@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
package/dist/shapes/shape.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shape.js","sources":["../../src/shapes/shape.ts"],"sourcesContent":["import type { Clonable, DeepRequireOptionals, Nullable } from '@zephyr3d/base';\r\nimport { Vector3, type Matrix4x4 } from '@zephyr3d/base';\r\nimport { Primitive } from '../render/primitive';\r\nimport { BoundingBox } from '../utility/bounding_volume';\r\n\r\n/**\r\n * Base class for creation options of any kind of shapes\r\n * @public\r\n */\r\nexport interface ShapeCreationOptions {\r\n /** true if we need to calculate normals for the shape */\r\n needNormal?: boolean;\r\n /** true if we need to calculate tangents for the shape */\r\n needTangent?: boolean;\r\n /** true if we need to calculate texture coordinates for the shape */\r\n needUV?: boolean;\r\n /** Transform matrix for the shape */\r\n transform?: Nullable<Matrix4x4>;\r\n}\r\n\r\n/**\r\n * Abstract base class for any kind of shapes\r\n * @public\r\n */\r\nexport abstract class Shape<T extends ShapeCreationOptions = ShapeCreationOptions>\r\n extends Primitive\r\n implements Clonable<Shape<T>>\r\n{\r\n static _defaultOptions = {\r\n needNormal: true,\r\n needTangent: true,\r\n needUV: true,\r\n transform: null\r\n };\r\n protected _options!: DeepRequireOptionals<T>;\r\n /**\r\n * Creates an instance of shape\r\n * @param options - The creation options\r\n */\r\n constructor(options?: T) {\r\n super();\r\n this._create(options);\r\n }\r\n protected static computeTangent(\r\n v0: number[],\r\n v1: number[],\r\n v2: number[],\r\n uv0: number[],\r\n uv1: number[],\r\n uv2: number[],\r\n normal: number[]\r\n ) {\r\n const dp1 = new Vector3(v1[0] - v0[0], v1[1] - v0[1], v1[2] - v0[2]);\r\n const dp2 = new Vector3(v2[0] - v0[0], v2[1] - v0[1], v2[2] - v0[2]);\r\n\r\n const du1 = uv1[0] - uv0[0],\r\n dv1 = uv1[1] - uv0[1];\r\n const du2 = uv2[0] - uv0[0],\r\n dv2 = uv2[1] - uv0[1];\r\n\r\n const denom = du1 * dv2 - dv1 * du2;\r\n\r\n if (Math.abs(denom) <= 1e-8) {\r\n return [1, 0, 0, 1];\r\n }\r\n\r\n const r = 1.0 / denom;\r\n let t0 = (dp1.x * dv2 - dp2.x * dv1) * r;\r\n let t1 = (dp1.y * dv2 - dp2.y * dv1) * r;\r\n let t2 = (dp1.z * dv2 - dp2.z * dv1) * r;\r\n const b0 = (dp2.x * du1 - dp1.x * du2) * r;\r\n const b1 = (dp2.y * du1 - dp1.y * du2) * r;\r\n const b2 = (dp2.z * du1 - dp1.z * du2) * r;\r\n\r\n // Gram-Schmidt\r\n const dotNT = normal[0] * t0 + normal[1] * t1 + normal[2] * t2;\r\n t0 -= normal[0] * dotNT;\r\n t1 -= normal[1] * dotNT;\r\n t2 -= normal[2] * dotNT;\r\n const lenT = Math.hypot(t0, t1, t2);\r\n if (lenT > 1e-8) {\r\n t0 /= lenT;\r\n t1 /= lenT;\r\n t2 /= lenT;\r\n } else {\r\n t0 = 1;\r\n t1 = 0;\r\n t2 = 0;\r\n }\r\n\r\n // w\r\n const c0 = normal[1] * t2 - normal[2] * t1;\r\n const c1 = normal[2] * t0 - normal[0] * t2;\r\n const c2 = normal[0] * t1 - normal[1] * t0;\r\n const w = c0 * b0 + c1 * b1 + c2 * b2 < 0 ? -1 : 1;\r\n\r\n return [t0, t1, t2, w];\r\n }\r\n\r\n abstract clone(): this;\r\n /** Get shape creation options */\r\n get options(): DeepRequireOptionals<T> {\r\n return this._options;\r\n }\r\n set options(options: T) {\r\n this._create(options);\r\n }\r\n /** Get shape type */\r\n abstract get type(): string;\r\n /**\r\n * Normalize options\r\n * @param options - creation options\r\n * @returns Normalized creation options\r\n */\r\n normalizeOptions(options?: T): DeepRequireOptionals<T> {\r\n const defaultOptions = (this.constructor as any)._defaultOptions as DeepRequireOptionals<T>;\r\n return Object.assign({}, defaultOptions, options ?? {});\r\n }\r\n /** @internal */\r\n protected _create(options?: T): boolean {\r\n this._options = this.normalizeOptions(options);\r\n const vertices: number[] = [];\r\n const indices: number[] = [];\r\n const normals: Nullable<number[]> = this._options.needNormal ? [] : null;\r\n const tangents: Nullable<number[]> = this._options.needTangent ? [] : null;\r\n const uvs: Nullable<number[]> = this._options.needUV ? [] : null;\r\n const bbox = new BoundingBox();\r\n bbox.beginExtend();\r\n this.primitiveType = (this.constructor as any).generateData(\r\n this._options,\r\n vertices,\r\n normals,\r\n tangents,\r\n uvs,\r\n indices,\r\n bbox,\r\n null,\r\n null\r\n );\r\n for (const s of ['position', 'normal', 'tangent', 'texCoord0'] as const) {\r\n this.removeVertexBuffer(s);\r\n }\r\n this.setIndexBuffer(null);\r\n this.createAndSetVertexBuffer('position_f32x3', new Float32Array(vertices));\r\n if (normals) {\r\n this.createAndSetVertexBuffer('normal_f32x3', new Float32Array(normals));\r\n }\r\n if (tangents) {\r\n this.createAndSetVertexBuffer('tangent_f32x4', new Float32Array(tangents));\r\n }\r\n if (uvs) {\r\n this.createAndSetVertexBuffer('tex0_f32x2', new Float32Array(uvs));\r\n }\r\n this.createAndSetIndexBuffer(new Uint16Array(indices));\r\n this.setBoundingVolume(bbox);\r\n this.indexCount = indices.length;\r\n return true;\r\n }\r\n /** @internal */\r\n protected static _transform(\r\n matrix: Nullable<Matrix4x4> | undefined,\r\n vertices: number[],\r\n normals: Nullable<number[]>,\r\n offset: number,\r\n tangents?: Nullable<number[]>\r\n ) {\r\n if (matrix) {\r\n const tmpVec = new Vector3();\r\n const tangentOffset = (offset / 3) * 4;\r\n for (let i = offset, tangentIndex = tangentOffset; i < vertices.length - 2; i += 3, tangentIndex += 4) {\r\n tmpVec.setXYZ(vertices[i], vertices[i + 1], vertices[i + 2]);\r\n matrix.transformPointAffine(tmpVec, tmpVec);\r\n vertices[i] = tmpVec.x;\r\n vertices[i + 1] = tmpVec.y;\r\n vertices[i + 2] = tmpVec.z;\r\n if (normals) {\r\n tmpVec.setXYZ(normals[i], normals[i + 1], normals[i + 2]);\r\n matrix.transformVectorAffine(tmpVec, tmpVec);\r\n tmpVec.inplaceNormalize();\r\n normals[i] = tmpVec.x;\r\n normals[i + 1] = tmpVec.y;\r\n normals[i + 2] = tmpVec.z;\r\n }\r\n if (tangents) {\r\n tmpVec.setXYZ(tangents[tangentIndex], tangents[tangentIndex + 1], tangents[tangentIndex + 2]);\r\n matrix.transformVectorAffine(tmpVec, tmpVec);\r\n tmpVec.inplaceNormalize();\r\n tangents[tangentIndex] = tmpVec.x;\r\n tangents[tangentIndex + 1] = tmpVec.y;\r\n tangents[tangentIndex + 2] = tmpVec.z;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n"],"names":["Shape","Primitive","_defaultOptions","needNormal","needTangent","needUV","transform","_options","options","_create","computeTangent","v0","v1","v2","uv0","uv1","uv2","normal","dp1","Vector3","dp2","du1","dv1","du2","dv2","denom","Math","abs","r","t0","x","t1","y","t2","z","b0","b1","b2","dotNT","lenT","hypot","c0","c1","c2","w","normalizeOptions","defaultOptions","Object","assign","vertices","indices","normals","tangents","uvs","bbox","BoundingBox","beginExtend","primitiveType","generateData","s","removeVertexBuffer","setIndexBuffer","createAndSetVertexBuffer","Float32Array","createAndSetIndexBuffer","Uint16Array","setBoundingVolume","indexCount","length","_transform","matrix","offset","tmpVec","tangentOffset","i","tangentIndex","setXYZ","transformPointAffine","transformVectorAffine","inplaceNormalize"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shape.js","sources":["../../src/shapes/shape.ts"],"sourcesContent":["import type { Clonable, DeepRequireOptionals, Nullable } from '@zephyr3d/base';\r\nimport { Vector3, type Matrix4x4 } from '@zephyr3d/base';\r\nimport { Primitive } from '../render/primitive';\r\nimport { BoundingBox } from '../utility/bounding_volume';\r\nimport { buildLodChain } from '../asset/mesh_lod_builder';\r\nimport type { MeshLodSettings, MeshSimplifier } from '../asset/mesh_lod_builder';\r\nimport { getMeshoptSimplifier, getMeshoptSimplifierIfReady } from '../asset/meshopt_simplifier';\r\n\r\n/**\r\n * Base class for creation options of any kind of shapes\r\n * @public\r\n */\r\nexport interface ShapeCreationOptions {\r\n /** true if we need to calculate normals for the shape */\r\n needNormal?: boolean;\r\n /** true if we need to calculate tangents for the shape */\r\n needTangent?: boolean;\r\n /** true if we need to calculate texture coordinates for the shape */\r\n needUV?: boolean;\r\n /** Transform matrix for the shape */\r\n transform?: Nullable<Matrix4x4>;\r\n /**\r\n * Levels of detail generated from the shape, as {@link SharedModel.generateLods} does for\r\n * imported meshes, or null for none. Regenerated whenever the shape is, so they always match\r\n * its options; only the settings are saved with it.\r\n */\r\n lod?: Nullable<MeshLodSettings>;\r\n}\r\n\r\n/**\r\n * Abstract base class for any kind of shapes\r\n * @public\r\n */\r\nexport abstract class Shape<T extends ShapeCreationOptions = ShapeCreationOptions>\r\n extends Primitive\r\n implements Clonable<Shape<T>>\r\n{\r\n static _defaultOptions = {\r\n needNormal: true,\r\n needTangent: true,\r\n needUV: true,\r\n transform: null,\r\n lod: null\r\n };\r\n protected _options!: DeepRequireOptionals<T>;\r\n /** @internal Counts creations, so levels of detail generated late only apply to the current one */\r\n private _createCount = 0;\r\n /**\r\n * Creates an instance of shape\r\n * @param options - The creation options\r\n */\r\n constructor(options?: T) {\r\n super();\r\n this._create(options);\r\n }\r\n protected static computeTangent(\r\n v0: number[],\r\n v1: number[],\r\n v2: number[],\r\n uv0: number[],\r\n uv1: number[],\r\n uv2: number[],\r\n normal: number[]\r\n ) {\r\n const dp1 = new Vector3(v1[0] - v0[0], v1[1] - v0[1], v1[2] - v0[2]);\r\n const dp2 = new Vector3(v2[0] - v0[0], v2[1] - v0[1], v2[2] - v0[2]);\r\n\r\n const du1 = uv1[0] - uv0[0],\r\n dv1 = uv1[1] - uv0[1];\r\n const du2 = uv2[0] - uv0[0],\r\n dv2 = uv2[1] - uv0[1];\r\n\r\n const denom = du1 * dv2 - dv1 * du2;\r\n\r\n if (Math.abs(denom) <= 1e-8) {\r\n return [1, 0, 0, 1];\r\n }\r\n\r\n const r = 1.0 / denom;\r\n let t0 = (dp1.x * dv2 - dp2.x * dv1) * r;\r\n let t1 = (dp1.y * dv2 - dp2.y * dv1) * r;\r\n let t2 = (dp1.z * dv2 - dp2.z * dv1) * r;\r\n const b0 = (dp2.x * du1 - dp1.x * du2) * r;\r\n const b1 = (dp2.y * du1 - dp1.y * du2) * r;\r\n const b2 = (dp2.z * du1 - dp1.z * du2) * r;\r\n\r\n // Gram-Schmidt\r\n const dotNT = normal[0] * t0 + normal[1] * t1 + normal[2] * t2;\r\n t0 -= normal[0] * dotNT;\r\n t1 -= normal[1] * dotNT;\r\n t2 -= normal[2] * dotNT;\r\n const lenT = Math.hypot(t0, t1, t2);\r\n if (lenT > 1e-8) {\r\n t0 /= lenT;\r\n t1 /= lenT;\r\n t2 /= lenT;\r\n } else {\r\n t0 = 1;\r\n t1 = 0;\r\n t2 = 0;\r\n }\r\n\r\n // w\r\n const c0 = normal[1] * t2 - normal[2] * t1;\r\n const c1 = normal[2] * t0 - normal[0] * t2;\r\n const c2 = normal[0] * t1 - normal[1] * t0;\r\n const w = c0 * b0 + c1 * b1 + c2 * b2 < 0 ? -1 : 1;\r\n\r\n return [t0, t1, t2, w];\r\n }\r\n\r\n abstract clone(): this;\r\n /** Get shape creation options */\r\n get options(): DeepRequireOptionals<T> {\r\n return this._options;\r\n }\r\n set options(options: T) {\r\n this._create(options);\r\n }\r\n /** Get shape type */\r\n abstract get type(): string;\r\n /**\r\n * Normalize options\r\n * @param options - creation options\r\n * @returns Normalized creation options\r\n */\r\n normalizeOptions(options?: T): DeepRequireOptionals<T> {\r\n const defaultOptions = (this.constructor as any)._defaultOptions as DeepRequireOptionals<T>;\r\n return Object.assign({}, defaultOptions, options ?? {});\r\n }\r\n /** @internal */\r\n protected _create(options?: T): boolean {\r\n this._options = this.normalizeOptions(options);\r\n const vertices: number[] = [];\r\n const indices: number[] = [];\r\n const normals: Nullable<number[]> = this._options.needNormal ? [] : null;\r\n const tangents: Nullable<number[]> = this._options.needTangent ? [] : null;\r\n const uvs: Nullable<number[]> = this._options.needUV ? [] : null;\r\n const bbox = new BoundingBox();\r\n bbox.beginExtend();\r\n this.primitiveType = (this.constructor as any).generateData(\r\n this._options,\r\n vertices,\r\n normals,\r\n tangents,\r\n uvs,\r\n indices,\r\n bbox,\r\n null,\r\n null\r\n );\r\n for (const s of ['position', 'normal', 'tangent', 'texCoord0'] as const) {\r\n this.removeVertexBuffer(s);\r\n }\r\n this.setIndexBuffer(null);\r\n this.createAndSetVertexBuffer('position_f32x3', new Float32Array(vertices));\r\n if (normals) {\r\n this.createAndSetVertexBuffer('normal_f32x3', new Float32Array(normals));\r\n }\r\n if (tangents) {\r\n this.createAndSetVertexBuffer('tangent_f32x4', new Float32Array(tangents));\r\n }\r\n if (uvs) {\r\n this.createAndSetVertexBuffer('tex0_f32x2', new Float32Array(uvs));\r\n }\r\n this.createAndSetIndexBuffer(new Uint16Array(indices));\r\n this.setBoundingVolume(bbox);\r\n this.indexCount = indices.length;\r\n // Levels of the previous creation do not match these indices, nor do levels still being made\r\n this.lods = [];\r\n this._createCount++;\r\n const lod = this._options.lod;\r\n if (lod && this.primitiveType === 'triangle-list' && indices.length >= 3) {\r\n this.generateLods(lod, vertices, normals, indices, bbox);\r\n }\r\n return true;\r\n }\r\n /** @internal Simplify the created shape into levels of detail, once the simplifier is ready */\r\n private generateLods(\r\n settings: MeshLodSettings,\r\n vertices: number[],\r\n normals: Nullable<number[]>,\r\n indices: number[],\r\n bbox: BoundingBox\r\n ) {\r\n const count = this._createCount;\r\n const positionData = new Float32Array(vertices);\r\n const normalData = normals ? new Float32Array(normals) : null;\r\n const indexData = new Uint32Array(indices);\r\n const extents = bbox.extents;\r\n const radius = Math.hypot(extents.x, extents.y, extents.z);\r\n const apply = (simplifier: MeshSimplifier) => {\r\n // Superseded by another creation, or released, while the simplifier loaded\r\n if (this.disposed || count !== this._createCount) {\r\n return;\r\n }\r\n const chain = buildLodChain(simplifier, indexData, positionData, normalData, radius, settings);\r\n if (chain.levels.length <= 1) {\r\n return;\r\n }\r\n this.createAndSetIndexBuffer(\r\n positionData.length / 3 <= 0x10000 ? Uint16Array.from(chain.indices) : chain.indices\r\n );\r\n this.indexCount = chain.levels[0].indexCount;\r\n this.lods = chain.levels.slice(1).map(({ indexStart, indexCount, screenSize, hysteresis }) => ({\r\n indexStart,\r\n indexCount,\r\n screenSize,\r\n hysteresis\r\n }));\r\n };\r\n const simplifier = getMeshoptSimplifierIfReady();\r\n if (simplifier) {\r\n apply(simplifier);\r\n } else {\r\n getMeshoptSimplifier().then(apply, (err) => console.error(`Shape levels of detail failed: ${err}`));\r\n }\r\n }\r\n /** @internal */\r\n protected static _transform(\r\n matrix: Nullable<Matrix4x4> | undefined,\r\n vertices: number[],\r\n normals: Nullable<number[]>,\r\n offset: number,\r\n tangents?: Nullable<number[]>\r\n ) {\r\n if (matrix) {\r\n const tmpVec = new Vector3();\r\n const tangentOffset = (offset / 3) * 4;\r\n for (let i = offset, tangentIndex = tangentOffset; i < vertices.length - 2; i += 3, tangentIndex += 4) {\r\n tmpVec.setXYZ(vertices[i], vertices[i + 1], vertices[i + 2]);\r\n matrix.transformPointAffine(tmpVec, tmpVec);\r\n vertices[i] = tmpVec.x;\r\n vertices[i + 1] = tmpVec.y;\r\n vertices[i + 2] = tmpVec.z;\r\n if (normals) {\r\n tmpVec.setXYZ(normals[i], normals[i + 1], normals[i + 2]);\r\n matrix.transformVectorAffine(tmpVec, tmpVec);\r\n tmpVec.inplaceNormalize();\r\n normals[i] = tmpVec.x;\r\n normals[i + 1] = tmpVec.y;\r\n normals[i + 2] = tmpVec.z;\r\n }\r\n if (tangents) {\r\n tmpVec.setXYZ(tangents[tangentIndex], tangents[tangentIndex + 1], tangents[tangentIndex + 2]);\r\n matrix.transformVectorAffine(tmpVec, tmpVec);\r\n tmpVec.inplaceNormalize();\r\n tangents[tangentIndex] = tmpVec.x;\r\n tangents[tangentIndex + 1] = tmpVec.y;\r\n tangents[tangentIndex + 2] = tmpVec.z;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n"],"names":["Shape","Primitive","_defaultOptions","needNormal","needTangent","needUV","transform","lod","_options","_createCount","options","_create","computeTangent","v0","v1","v2","uv0","uv1","uv2","normal","dp1","Vector3","dp2","du1","dv1","du2","dv2","denom","Math","abs","r","t0","x","t1","y","t2","z","b0","b1","b2","dotNT","lenT","hypot","c0","c1","c2","w","normalizeOptions","defaultOptions","Object","assign","vertices","indices","normals","tangents","uvs","bbox","BoundingBox","beginExtend","primitiveType","generateData","s","removeVertexBuffer","setIndexBuffer","createAndSetVertexBuffer","Float32Array","createAndSetIndexBuffer","Uint16Array","setBoundingVolume","indexCount","length","lods","generateLods","settings","count","positionData","normalData","indexData","Uint32Array","extents","radius","apply","simplifier","disposed","chain","buildLodChain","levels","from","slice","map","indexStart","screenSize","hysteresis","getMeshoptSimplifierIfReady","getMeshoptSimplifier","then","err","console","error","_transform","matrix","offset","tmpVec","tangentOffset","i","tangentIndex","setXYZ","transformPointAffine","transformVectorAffine","inplaceNormalize"],"mappings":"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"}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { Vector3, Quaternion } from '@zephyr3d/base';
|
|
2
|
+
|
|
3
|
+
/** Standard gravity, in metres per second squared. @public */ const STANDARD_GRAVITY = 9.81;
|
|
4
|
+
/**
|
|
5
|
+
* Largest step of {@link FloatingBody}, in seconds.
|
|
6
|
+
*
|
|
7
|
+
* Buoyancy is a stiff spring, so a long step overshoots and diverges; longer
|
|
8
|
+
* frames are split into steps of at most this. @internal
|
|
9
|
+
*/ const MAX_STEP = 1 / 120;
|
|
10
|
+
/** Ceiling on steps per frame, so a very late frame cannot stall the loop. @internal */ const MAX_STEPS_PER_FRAME = 8;
|
|
11
|
+
/**
|
|
12
|
+
* The buoyancy a box-shaped hull gets from a water surface, as a force and a
|
|
13
|
+
* torque, independent of what integrates them.
|
|
14
|
+
*
|
|
15
|
+
* Pair it with {@link FloatingBody} for a self-contained float, or feed the
|
|
16
|
+
* force and torque to a rigid body in whatever physics library the
|
|
17
|
+
* application uses.
|
|
18
|
+
*
|
|
19
|
+
* ## The model
|
|
20
|
+
*
|
|
21
|
+
* The hull is filled with a lattice of probes, each a block of hull carrying an
|
|
22
|
+
* equal share of the lift the whole hull can produce, scaled by how much of the
|
|
23
|
+
* block is under water. Summed, that is the buoyancy of whatever part of the
|
|
24
|
+
* hull is submerged, acting at that part's centroid - which is the centre of
|
|
25
|
+
* buoyancy, and the thing a righting moment is made of: the water pushes up
|
|
26
|
+
* hardest on whichever side has more of its blocks under, which rolls a boat
|
|
27
|
+
* back upright. There is no separate upright target.
|
|
28
|
+
*
|
|
29
|
+
* The lattice fills the box rather than sitting on the bottom face: probes on
|
|
30
|
+
* the bottom alone give a moment that pushes a rolled hull further over.
|
|
31
|
+
*
|
|
32
|
+
* The lift a fully submerged hull produces is `mass * g / submergedFraction`:
|
|
33
|
+
* the force that, once the configured share of the probes is under, balances
|
|
34
|
+
* the weight. `submergedFraction` is then the density ratio and alone sets the
|
|
35
|
+
* float height; the mass drops out of the buoyant motion, and a heavy body
|
|
36
|
+
* cannot sink past its deck.
|
|
37
|
+
*
|
|
38
|
+
* ## What is not modelled
|
|
39
|
+
*
|
|
40
|
+
* No hull-volume integral, no added mass, no drag. A probe's contribution grows
|
|
41
|
+
* linearly with depth up to its own height, which is accurate while a vessel
|
|
42
|
+
* rides on its waterline and approximate for a fully submerged one.
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/ class BuoyancyVolume {
|
|
46
|
+
/** Full extents in metres, in local axes. */ size;
|
|
47
|
+
/** Mass in kilograms. */ mass;
|
|
48
|
+
/** Share of the height under water at rest. */ submergedFraction;
|
|
49
|
+
/** Gravity in metres per second squared. */ gravity;
|
|
50
|
+
/** Lift of the fully submerged hull, in newtons. */ maxBuoyancy;
|
|
51
|
+
/** Height of the waterline above the bottom face at rest, in metres. */ draft;
|
|
52
|
+
/** Height of the hull's centre above the still-water level at rest, in metres. */ restHeight;
|
|
53
|
+
/** Probe centres in local space. */ probes;
|
|
54
|
+
/** Height of one probe's block, in metres. */ probeHeight;
|
|
55
|
+
/** Share of the total lift each probe carries when fully under. */ _probeShare;
|
|
56
|
+
_probeWorld;
|
|
57
|
+
/**
|
|
58
|
+
* Creates a buoyancy volume.
|
|
59
|
+
*/ constructor(options){
|
|
60
|
+
this.size = options.size.clone();
|
|
61
|
+
this.mass = Math.max(1e-3, options.mass ?? 1000);
|
|
62
|
+
this.submergedFraction = Math.min(0.95, Math.max(0.05, options.submergedFraction ?? 0.5));
|
|
63
|
+
this.gravity = options.gravity ?? STANDARD_GRAVITY;
|
|
64
|
+
this.maxBuoyancy = this.mass * this.gravity / this.submergedFraction;
|
|
65
|
+
this.draft = this.size.y * this.submergedFraction;
|
|
66
|
+
this.restHeight = this.size.y / 2 - this.draft;
|
|
67
|
+
const cols = Math.max(1, Math.floor(options.probeColumns ?? 3));
|
|
68
|
+
const rows = Math.max(1, Math.floor(options.probeRows ?? 3));
|
|
69
|
+
const layers = Math.max(1, Math.floor(options.probeLayers ?? 3));
|
|
70
|
+
const sx = this.size.x;
|
|
71
|
+
const sy = this.size.y;
|
|
72
|
+
const sz = this.size.z;
|
|
73
|
+
this.probeHeight = sy / layers;
|
|
74
|
+
this.probes = [];
|
|
75
|
+
const dx = sx / cols;
|
|
76
|
+
const dy = sy / layers;
|
|
77
|
+
const dz = sz / rows;
|
|
78
|
+
for(let l = 0; l < layers; l++){
|
|
79
|
+
const y = -sy / 2 + (l + 0.5) * dy;
|
|
80
|
+
for(let j = 0; j < rows; j++){
|
|
81
|
+
const z = -sz / 2 + (j + 0.5) * dz;
|
|
82
|
+
for(let i = 0; i < cols; i++){
|
|
83
|
+
const x = -sx / 2 + (i + 0.5) * dx;
|
|
84
|
+
this.probes.push(new Vector3(x, y, z));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
this._probeShare = 1 / this.probes.length;
|
|
89
|
+
this._probeWorld = new Vector3();
|
|
90
|
+
}
|
|
91
|
+
/** World Y the hull's centre rests at on a still surface at `waterLevel`. */ restY(waterLevel) {
|
|
92
|
+
return waterLevel + this.restHeight;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Buoyant force and torque on the hull at a pose, in world space, about the
|
|
96
|
+
* hull's centre. Gravity is not included.
|
|
97
|
+
*
|
|
98
|
+
* @param position - World position of the hull's centre.
|
|
99
|
+
* @param rotation - World orientation of the hull.
|
|
100
|
+
* @param waveHeight - Surface height above `waterLevel` at a world XZ.
|
|
101
|
+
* @param waterLevel - World Y of the still-water level.
|
|
102
|
+
* @param outForce - Receives the force in newtons.
|
|
103
|
+
* @param outTorque - Receives the torque in newton-metres.
|
|
104
|
+
* @returns How much of the hull is under water, 0 to 1. Useful for blending
|
|
105
|
+
* drag between air and water.
|
|
106
|
+
*/ computeForces(position, rotation, waveHeight, waterLevel, outForce, outTorque) {
|
|
107
|
+
outForce.setXYZ(0, 0, 0);
|
|
108
|
+
outTorque.setXYZ(0, 0, 0);
|
|
109
|
+
let submerged = 0;
|
|
110
|
+
const pw = this._probeWorld;
|
|
111
|
+
for(let i = 0; i < this.probes.length; i++){
|
|
112
|
+
rotation.transform(this.probes[i], pw);
|
|
113
|
+
const worldX = position.x + pw.x;
|
|
114
|
+
const worldY = position.y + pw.y;
|
|
115
|
+
const worldZ = position.z + pw.z;
|
|
116
|
+
// How much of this block is under: its centre's depth, offset by half
|
|
117
|
+
// its height and clamped, so a block straddling the surface counts the
|
|
118
|
+
// part below and a block wholly under counts all of itself and no more.
|
|
119
|
+
const depth = waterLevel + waveHeight(worldX, worldZ) - worldY;
|
|
120
|
+
const fraction = Math.min(1, Math.max(0, depth / this.probeHeight + 0.5));
|
|
121
|
+
if (fraction <= 0) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
submerged += this._probeShare * fraction;
|
|
125
|
+
const magnitude = this.maxBuoyancy * this._probeShare * fraction;
|
|
126
|
+
outForce.y += magnitude;
|
|
127
|
+
// r x F for a straight-up force at lever arm r from the centre.
|
|
128
|
+
outTorque.x -= pw.z * magnitude;
|
|
129
|
+
outTorque.z += pw.x * magnitude;
|
|
130
|
+
}
|
|
131
|
+
return submerged;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* A rigid body that floats on a water surface, with its own integrator.
|
|
136
|
+
*
|
|
137
|
+
* For applications without a physics library. The motion is force driven: the
|
|
138
|
+
* body owns a position, an orientation and their velocities, and the water
|
|
139
|
+
* only ever applies the force and torque a {@link BuoyancyVolume} computes, so
|
|
140
|
+
* the hull lags the surface, overshoots and rolls back.
|
|
141
|
+
*
|
|
142
|
+
* Semi-implicit Euler at a fixed step, box inertia kept as a diagonal in body
|
|
143
|
+
* axes, quaternion orientation renormalised every step. Water resistance is a
|
|
144
|
+
* per-second fraction of velocity, blended between the air and water values by
|
|
145
|
+
* how much of the body is under, so a body launched clear of the water keeps
|
|
146
|
+
* its speed until it lands. No collision.
|
|
147
|
+
*
|
|
148
|
+
* @public
|
|
149
|
+
*/ class FloatingBody {
|
|
150
|
+
/** The hull's buoyancy. */ volume;
|
|
151
|
+
/** Node driven by the body, if any. */ node;
|
|
152
|
+
/** Fraction of linear velocity shed per second in water. */ linearDamping;
|
|
153
|
+
/** Fraction of angular velocity shed per second in water. */ angularDamping;
|
|
154
|
+
/** Fraction of linear velocity shed per second in air. */ airLinearDamping;
|
|
155
|
+
/** Fraction of angular velocity shed per second in air. */ airAngularDamping;
|
|
156
|
+
/** World position of the hull's centre. */ position;
|
|
157
|
+
/** World orientation. */ rotation;
|
|
158
|
+
/** Linear velocity in metres per second. */ velocity;
|
|
159
|
+
/** Angular velocity in radians per second, world axes. */ angularVelocity;
|
|
160
|
+
/** Extra force applied at the centre of mass on the next step, in newtons. Cleared after each frame. */ externalForce;
|
|
161
|
+
/** Extra torque applied on the next step, in newton-metres. Cleared after each frame. */ externalTorque;
|
|
162
|
+
_invInertiaBody;
|
|
163
|
+
_force;
|
|
164
|
+
_torque;
|
|
165
|
+
_tmp;
|
|
166
|
+
_torqueBody;
|
|
167
|
+
_conj;
|
|
168
|
+
_wq;
|
|
169
|
+
_accumulator;
|
|
170
|
+
/**
|
|
171
|
+
* Creates a floating body.
|
|
172
|
+
*/ constructor(options){
|
|
173
|
+
this.volume = new BuoyancyVolume(options);
|
|
174
|
+
this.node = options.node ?? null;
|
|
175
|
+
// Defaults sit well under critical damping (about twice the heave frequency
|
|
176
|
+
// sqrt(rho g A / m)), so a dropped body bounces a couple of times and settles.
|
|
177
|
+
this.linearDamping = Math.max(0, options.linearDamping ?? 2.5);
|
|
178
|
+
this.angularDamping = Math.max(0, options.angularDamping ?? 3);
|
|
179
|
+
this.airLinearDamping = Math.max(0, options.airLinearDamping ?? 0.05);
|
|
180
|
+
this.airAngularDamping = Math.max(0, options.airAngularDamping ?? 0.1);
|
|
181
|
+
this.position = new Vector3();
|
|
182
|
+
this.rotation = new Quaternion();
|
|
183
|
+
this.velocity = new Vector3();
|
|
184
|
+
this.angularVelocity = new Vector3();
|
|
185
|
+
this.externalForce = new Vector3();
|
|
186
|
+
this.externalTorque = new Vector3();
|
|
187
|
+
// Inertia of a solid box about its centre. A box has no products of
|
|
188
|
+
// inertia, so the world tensor is never formed: torques are rotated into
|
|
189
|
+
// the body frame, divided there, and rotated back.
|
|
190
|
+
const m = this.volume.mass;
|
|
191
|
+
const { x: sx, y: sy, z: sz } = this.volume.size;
|
|
192
|
+
this._invInertiaBody = new Vector3(12 / (m * (sy * sy + sz * sz)), 12 / (m * (sx * sx + sz * sz)), 12 / (m * (sx * sx + sy * sy)));
|
|
193
|
+
this._force = new Vector3();
|
|
194
|
+
this._torque = new Vector3();
|
|
195
|
+
this._tmp = new Vector3();
|
|
196
|
+
this._torqueBody = new Vector3();
|
|
197
|
+
this._conj = new Quaternion();
|
|
198
|
+
this._wq = new Quaternion();
|
|
199
|
+
this._accumulator = 0;
|
|
200
|
+
}
|
|
201
|
+
/** Mass in kilograms. */ get mass() {
|
|
202
|
+
return this.volume.mass;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Place the body at rest on a still surface and clear its velocities.
|
|
206
|
+
* @param x - World X.
|
|
207
|
+
* @param z - World Z.
|
|
208
|
+
* @param waterLevel - Still-water level the body should float on.
|
|
209
|
+
* @param yaw - Heading in radians about world Y.
|
|
210
|
+
*/ reset(x, z, waterLevel = 0, yaw = 0) {
|
|
211
|
+
this.position.setXYZ(x, this.volume.restY(waterLevel), z);
|
|
212
|
+
Quaternion.fromEulerAngle(0, yaw, 0, 'ZYX', this.rotation);
|
|
213
|
+
this.velocity.setXYZ(0, 0, 0);
|
|
214
|
+
this.angularVelocity.setXYZ(0, 0, 0);
|
|
215
|
+
this._accumulator = 0;
|
|
216
|
+
this.applyToNode();
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Integrate one frame.
|
|
220
|
+
* @param deltaSeconds - Frame delta in seconds.
|
|
221
|
+
* @param waveHeight - Surface height above the still-water level at a world XZ.
|
|
222
|
+
* @param waterLevel - World Y of the still-water level.
|
|
223
|
+
*/ update(deltaSeconds, waveHeight, waterLevel) {
|
|
224
|
+
this._accumulator += Math.min(0.25, deltaSeconds);
|
|
225
|
+
let steps = 0;
|
|
226
|
+
while(this._accumulator >= MAX_STEP && steps < MAX_STEPS_PER_FRAME){
|
|
227
|
+
this.step(MAX_STEP, waveHeight, waterLevel);
|
|
228
|
+
this._accumulator -= MAX_STEP;
|
|
229
|
+
steps++;
|
|
230
|
+
}
|
|
231
|
+
// A frame so late that the backlog cannot be worked off drops it: carrying
|
|
232
|
+
// it would make the next frame worse.
|
|
233
|
+
if (this._accumulator > MAX_STEP) {
|
|
234
|
+
this._accumulator = 0;
|
|
235
|
+
}
|
|
236
|
+
this.externalForce.setXYZ(0, 0, 0);
|
|
237
|
+
this.externalTorque.setXYZ(0, 0, 0);
|
|
238
|
+
this.applyToNode();
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Advance the body by one fixed step.
|
|
242
|
+
* @param dt - Step in seconds.
|
|
243
|
+
* @param waveHeight - Surface height above the still-water level at a world XZ.
|
|
244
|
+
* @param waterLevel - World Y of the still-water level.
|
|
245
|
+
*/ step(dt, waveHeight, waterLevel) {
|
|
246
|
+
const force = this._force;
|
|
247
|
+
const torque = this._torque;
|
|
248
|
+
const submerged = this.volume.computeForces(this.position, this.rotation, waveHeight, waterLevel, force, torque);
|
|
249
|
+
// Gravity at the centre of mass, so it contributes no torque.
|
|
250
|
+
force.y -= this.volume.mass * this.volume.gravity;
|
|
251
|
+
force.addBy(this.externalForce);
|
|
252
|
+
torque.addBy(this.externalTorque);
|
|
253
|
+
// Resistance, blended between air and water by how much is under.
|
|
254
|
+
const linear = this.airLinearDamping + (this.linearDamping - this.airLinearDamping) * submerged;
|
|
255
|
+
const angular = this.airAngularDamping + (this.angularDamping - this.airAngularDamping) * submerged;
|
|
256
|
+
this.velocity.scaleBy(Math.exp(-linear * dt));
|
|
257
|
+
this.angularVelocity.scaleBy(Math.exp(-angular * dt));
|
|
258
|
+
// Semi-implicit Euler: velocity first, then position. The ordering is what
|
|
259
|
+
// keeps a stiff spring stable at this step size.
|
|
260
|
+
Vector3.scale(force, dt / this.volume.mass, this._tmp);
|
|
261
|
+
this.velocity.addBy(this._tmp);
|
|
262
|
+
Vector3.scale(this.velocity, dt, this._tmp);
|
|
263
|
+
this.position.addBy(this._tmp);
|
|
264
|
+
// Angular motion in the body frame, where the inertia tensor is diagonal.
|
|
265
|
+
this._conj.setXYZW(-this.rotation.x, -this.rotation.y, -this.rotation.z, this.rotation.w);
|
|
266
|
+
this._conj.transform(torque, this._torqueBody);
|
|
267
|
+
this._torqueBody.setXYZ(this._torqueBody.x * this._invInertiaBody.x, this._torqueBody.y * this._invInertiaBody.y, this._torqueBody.z * this._invInertiaBody.z);
|
|
268
|
+
this.rotation.transform(this._torqueBody, this._tmp);
|
|
269
|
+
this._tmp.scaleBy(dt);
|
|
270
|
+
this.angularVelocity.addBy(this._tmp);
|
|
271
|
+
// q += 0.5 * (omega as a pure quaternion) * q, then renormalise.
|
|
272
|
+
const av = this.angularVelocity;
|
|
273
|
+
this._wq.setXYZW(av.x * dt * 0.5, av.y * dt * 0.5, av.z * dt * 0.5, 0);
|
|
274
|
+
Quaternion.multiply(this._wq, this.rotation, this._wq);
|
|
275
|
+
this.rotation.setXYZW(this.rotation.x + this._wq.x, this.rotation.y + this._wq.y, this.rotation.z + this._wq.z, this.rotation.w + this._wq.w);
|
|
276
|
+
Quaternion.normalize(this.rotation, this.rotation);
|
|
277
|
+
}
|
|
278
|
+
/** Write the pose to the node, if there is one. */ applyToNode() {
|
|
279
|
+
if (this.node) {
|
|
280
|
+
this.node.position.setXYZ(this.position.x, this.position.y, this.position.z);
|
|
281
|
+
this.node.rotation = this.rotation;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export { BuoyancyVolume, FloatingBody, STANDARD_GRAVITY };
|
|
287
|
+
//# sourceMappingURL=buoyancy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buoyancy.js","sources":["../../src/utility/buoyancy.ts"],"sourcesContent":["import { Quaternion, Vector3 } from '@zephyr3d/base';\r\nimport type { SceneNode } from '../scene/scene_node';\r\n\r\n/** Standard gravity, in metres per second squared. @public */\r\nexport const STANDARD_GRAVITY = 9.81;\r\n/**\r\n * Largest step of {@link FloatingBody}, in seconds.\r\n *\r\n * Buoyancy is a stiff spring, so a long step overshoots and diverges; longer\r\n * frames are split into steps of at most this. @internal\r\n */\r\nconst MAX_STEP = 1 / 120;\r\n/** Ceiling on steps per frame, so a very late frame cannot stall the loop. @internal */\r\nconst MAX_STEPS_PER_FRAME = 8;\r\n\r\n/**\r\n * Surface height above the still-water level at a world XZ, in metres.\r\n * @public\r\n */\r\nexport type WaveHeightFn = (x: number, z: number) => number;\r\n\r\n/**\r\n * Options for {@link BuoyancyVolume}.\r\n * @public\r\n */\r\nexport interface BuoyancyVolumeOptions {\r\n /** Full extents of the hull in metres, in its local axes. */\r\n size: Vector3;\r\n /**\r\n * Mass in kilograms. Sets the lift the fully submerged hull produces; the\r\n * float height does not depend on it. Defaults to 1000.\r\n */\r\n mass?: number;\r\n /**\r\n * Share of the hull's height below the waterline at rest, which is its\r\n * density relative to water. Lower floats higher. Defaults to 0.5.\r\n */\r\n submergedFraction?: number;\r\n /** Probes across the local X axis. Defaults to 3. */\r\n probeColumns?: number;\r\n /** Probes across the local Z axis. Defaults to 3. */\r\n probeRows?: number;\r\n /** Probes up the local Y axis. Defaults to 3. */\r\n probeLayers?: number;\r\n /** Gravity in metres per second squared. Defaults to {@link STANDARD_GRAVITY}. */\r\n gravity?: number;\r\n}\r\n\r\n/**\r\n * The buoyancy a box-shaped hull gets from a water surface, as a force and a\r\n * torque, independent of what integrates them.\r\n *\r\n * Pair it with {@link FloatingBody} for a self-contained float, or feed the\r\n * force and torque to a rigid body in whatever physics library the\r\n * application uses.\r\n *\r\n * ## The model\r\n *\r\n * The hull is filled with a lattice of probes, each a block of hull carrying an\r\n * equal share of the lift the whole hull can produce, scaled by how much of the\r\n * block is under water. Summed, that is the buoyancy of whatever part of the\r\n * hull is submerged, acting at that part's centroid - which is the centre of\r\n * buoyancy, and the thing a righting moment is made of: the water pushes up\r\n * hardest on whichever side has more of its blocks under, which rolls a boat\r\n * back upright. There is no separate upright target.\r\n *\r\n * The lattice fills the box rather than sitting on the bottom face: probes on\r\n * the bottom alone give a moment that pushes a rolled hull further over.\r\n *\r\n * The lift a fully submerged hull produces is `mass * g / submergedFraction`:\r\n * the force that, once the configured share of the probes is under, balances\r\n * the weight. `submergedFraction` is then the density ratio and alone sets the\r\n * float height; the mass drops out of the buoyant motion, and a heavy body\r\n * cannot sink past its deck.\r\n *\r\n * ## What is not modelled\r\n *\r\n * No hull-volume integral, no added mass, no drag. A probe's contribution grows\r\n * linearly with depth up to its own height, which is accurate while a vessel\r\n * rides on its waterline and approximate for a fully submerged one.\r\n *\r\n * @public\r\n */\r\nexport class BuoyancyVolume {\r\n /** Full extents in metres, in local axes. */\r\n readonly size: Vector3;\r\n /** Mass in kilograms. */\r\n readonly mass: number;\r\n /** Share of the height under water at rest. */\r\n readonly submergedFraction: number;\r\n /** Gravity in metres per second squared. */\r\n readonly gravity: number;\r\n /** Lift of the fully submerged hull, in newtons. */\r\n readonly maxBuoyancy: number;\r\n /** Height of the waterline above the bottom face at rest, in metres. */\r\n readonly draft: number;\r\n /** Height of the hull's centre above the still-water level at rest, in metres. */\r\n readonly restHeight: number;\r\n /** Probe centres in local space. */\r\n readonly probes: Vector3[];\r\n /** Height of one probe's block, in metres. */\r\n readonly probeHeight: number;\r\n /** Share of the total lift each probe carries when fully under. */\r\n private readonly _probeShare: number;\r\n private readonly _probeWorld: Vector3;\r\n /**\r\n * Creates a buoyancy volume.\r\n */\r\n constructor(options: BuoyancyVolumeOptions) {\r\n this.size = options.size.clone();\r\n this.mass = Math.max(1e-3, options.mass ?? 1000);\r\n this.submergedFraction = Math.min(0.95, Math.max(0.05, options.submergedFraction ?? 0.5));\r\n this.gravity = options.gravity ?? STANDARD_GRAVITY;\r\n this.maxBuoyancy = (this.mass * this.gravity) / this.submergedFraction;\r\n this.draft = this.size.y * this.submergedFraction;\r\n this.restHeight = this.size.y / 2 - this.draft;\r\n const cols = Math.max(1, Math.floor(options.probeColumns ?? 3));\r\n const rows = Math.max(1, Math.floor(options.probeRows ?? 3));\r\n const layers = Math.max(1, Math.floor(options.probeLayers ?? 3));\r\n const sx = this.size.x;\r\n const sy = this.size.y;\r\n const sz = this.size.z;\r\n this.probeHeight = sy / layers;\r\n this.probes = [];\r\n const dx = sx / cols;\r\n const dy = sy / layers;\r\n const dz = sz / rows;\r\n for (let l = 0; l < layers; l++) {\r\n const y = -sy / 2 + (l + 0.5) * dy;\r\n for (let j = 0; j < rows; j++) {\r\n const z = -sz / 2 + (j + 0.5) * dz;\r\n for (let i = 0; i < cols; i++) {\r\n const x = -sx / 2 + (i + 0.5) * dx;\r\n this.probes.push(new Vector3(x, y, z));\r\n }\r\n }\r\n }\r\n this._probeShare = 1 / this.probes.length;\r\n this._probeWorld = new Vector3();\r\n }\r\n /** World Y the hull's centre rests at on a still surface at `waterLevel`. */\r\n restY(waterLevel: number) {\r\n return waterLevel + this.restHeight;\r\n }\r\n /**\r\n * Buoyant force and torque on the hull at a pose, in world space, about the\r\n * hull's centre. Gravity is not included.\r\n *\r\n * @param position - World position of the hull's centre.\r\n * @param rotation - World orientation of the hull.\r\n * @param waveHeight - Surface height above `waterLevel` at a world XZ.\r\n * @param waterLevel - World Y of the still-water level.\r\n * @param outForce - Receives the force in newtons.\r\n * @param outTorque - Receives the torque in newton-metres.\r\n * @returns How much of the hull is under water, 0 to 1. Useful for blending\r\n * drag between air and water.\r\n */\r\n computeForces(\r\n position: Vector3,\r\n rotation: Quaternion,\r\n waveHeight: WaveHeightFn,\r\n waterLevel: number,\r\n outForce: Vector3,\r\n outTorque: Vector3\r\n ) {\r\n outForce.setXYZ(0, 0, 0);\r\n outTorque.setXYZ(0, 0, 0);\r\n let submerged = 0;\r\n const pw = this._probeWorld;\r\n for (let i = 0; i < this.probes.length; i++) {\r\n rotation.transform(this.probes[i], pw);\r\n const worldX = position.x + pw.x;\r\n const worldY = position.y + pw.y;\r\n const worldZ = position.z + pw.z;\r\n // How much of this block is under: its centre's depth, offset by half\r\n // its height and clamped, so a block straddling the surface counts the\r\n // part below and a block wholly under counts all of itself and no more.\r\n const depth = waterLevel + waveHeight(worldX, worldZ) - worldY;\r\n const fraction = Math.min(1, Math.max(0, depth / this.probeHeight + 0.5));\r\n if (fraction <= 0) {\r\n continue;\r\n }\r\n submerged += this._probeShare * fraction;\r\n const magnitude = this.maxBuoyancy * this._probeShare * fraction;\r\n outForce.y += magnitude;\r\n // r x F for a straight-up force at lever arm r from the centre.\r\n outTorque.x -= pw.z * magnitude;\r\n outTorque.z += pw.x * magnitude;\r\n }\r\n return submerged;\r\n }\r\n}\r\n\r\n/**\r\n * Options for {@link FloatingBody}, on top of those of {@link BuoyancyVolume}.\r\n * @public\r\n */\r\nexport interface FloatingBodyOptions extends BuoyancyVolumeOptions {\r\n /** Node to drive, or null to read {@link FloatingBody.position} and {@link FloatingBody.rotation} directly. */\r\n node?: SceneNode | null;\r\n /** Fraction of linear velocity shed per second in water. Defaults to 2.5. */\r\n linearDamping?: number;\r\n /** Fraction of angular velocity shed per second in water. Defaults to 3. */\r\n angularDamping?: number;\r\n /** The same, clear of the water. Defaults to 0.05. */\r\n airLinearDamping?: number;\r\n /** The same, clear of the water. Defaults to 0.1. */\r\n airAngularDamping?: number;\r\n}\r\n\r\n/**\r\n * A rigid body that floats on a water surface, with its own integrator.\r\n *\r\n * For applications without a physics library. The motion is force driven: the\r\n * body owns a position, an orientation and their velocities, and the water\r\n * only ever applies the force and torque a {@link BuoyancyVolume} computes, so\r\n * the hull lags the surface, overshoots and rolls back.\r\n *\r\n * Semi-implicit Euler at a fixed step, box inertia kept as a diagonal in body\r\n * axes, quaternion orientation renormalised every step. Water resistance is a\r\n * per-second fraction of velocity, blended between the air and water values by\r\n * how much of the body is under, so a body launched clear of the water keeps\r\n * its speed until it lands. No collision.\r\n *\r\n * @public\r\n */\r\nexport class FloatingBody {\r\n /** The hull's buoyancy. */\r\n readonly volume: BuoyancyVolume;\r\n /** Node driven by the body, if any. */\r\n node: SceneNode | null;\r\n /** Fraction of linear velocity shed per second in water. */\r\n linearDamping: number;\r\n /** Fraction of angular velocity shed per second in water. */\r\n angularDamping: number;\r\n /** Fraction of linear velocity shed per second in air. */\r\n airLinearDamping: number;\r\n /** Fraction of angular velocity shed per second in air. */\r\n airAngularDamping: number;\r\n /** World position of the hull's centre. */\r\n readonly position: Vector3;\r\n /** World orientation. */\r\n readonly rotation: Quaternion;\r\n /** Linear velocity in metres per second. */\r\n readonly velocity: Vector3;\r\n /** Angular velocity in radians per second, world axes. */\r\n readonly angularVelocity: Vector3;\r\n /** Extra force applied at the centre of mass on the next step, in newtons. Cleared after each frame. */\r\n readonly externalForce: Vector3;\r\n /** Extra torque applied on the next step, in newton-metres. Cleared after each frame. */\r\n readonly externalTorque: Vector3;\r\n private readonly _invInertiaBody: Vector3;\r\n private readonly _force: Vector3;\r\n private readonly _torque: Vector3;\r\n private readonly _tmp: Vector3;\r\n private readonly _torqueBody: Vector3;\r\n private readonly _conj: Quaternion;\r\n private readonly _wq: Quaternion;\r\n private _accumulator: number;\r\n /**\r\n * Creates a floating body.\r\n */\r\n constructor(options: FloatingBodyOptions) {\r\n this.volume = new BuoyancyVolume(options);\r\n this.node = options.node ?? null;\r\n // Defaults sit well under critical damping (about twice the heave frequency\r\n // sqrt(rho g A / m)), so a dropped body bounces a couple of times and settles.\r\n this.linearDamping = Math.max(0, options.linearDamping ?? 2.5);\r\n this.angularDamping = Math.max(0, options.angularDamping ?? 3);\r\n this.airLinearDamping = Math.max(0, options.airLinearDamping ?? 0.05);\r\n this.airAngularDamping = Math.max(0, options.airAngularDamping ?? 0.1);\r\n this.position = new Vector3();\r\n this.rotation = new Quaternion();\r\n this.velocity = new Vector3();\r\n this.angularVelocity = new Vector3();\r\n this.externalForce = new Vector3();\r\n this.externalTorque = new Vector3();\r\n // Inertia of a solid box about its centre. A box has no products of\r\n // inertia, so the world tensor is never formed: torques are rotated into\r\n // the body frame, divided there, and rotated back.\r\n const m = this.volume.mass;\r\n const { x: sx, y: sy, z: sz } = this.volume.size;\r\n this._invInertiaBody = new Vector3(\r\n 12 / (m * (sy * sy + sz * sz)),\r\n 12 / (m * (sx * sx + sz * sz)),\r\n 12 / (m * (sx * sx + sy * sy))\r\n );\r\n this._force = new Vector3();\r\n this._torque = new Vector3();\r\n this._tmp = new Vector3();\r\n this._torqueBody = new Vector3();\r\n this._conj = new Quaternion();\r\n this._wq = new Quaternion();\r\n this._accumulator = 0;\r\n }\r\n /** Mass in kilograms. */\r\n get mass() {\r\n return this.volume.mass;\r\n }\r\n /**\r\n * Place the body at rest on a still surface and clear its velocities.\r\n * @param x - World X.\r\n * @param z - World Z.\r\n * @param waterLevel - Still-water level the body should float on.\r\n * @param yaw - Heading in radians about world Y.\r\n */\r\n reset(x: number, z: number, waterLevel = 0, yaw = 0) {\r\n this.position.setXYZ(x, this.volume.restY(waterLevel), z);\r\n Quaternion.fromEulerAngle(0, yaw, 0, 'ZYX', this.rotation);\r\n this.velocity.setXYZ(0, 0, 0);\r\n this.angularVelocity.setXYZ(0, 0, 0);\r\n this._accumulator = 0;\r\n this.applyToNode();\r\n }\r\n /**\r\n * Integrate one frame.\r\n * @param deltaSeconds - Frame delta in seconds.\r\n * @param waveHeight - Surface height above the still-water level at a world XZ.\r\n * @param waterLevel - World Y of the still-water level.\r\n */\r\n update(deltaSeconds: number, waveHeight: WaveHeightFn, waterLevel: number) {\r\n this._accumulator += Math.min(0.25, deltaSeconds);\r\n let steps = 0;\r\n while (this._accumulator >= MAX_STEP && steps < MAX_STEPS_PER_FRAME) {\r\n this.step(MAX_STEP, waveHeight, waterLevel);\r\n this._accumulator -= MAX_STEP;\r\n steps++;\r\n }\r\n // A frame so late that the backlog cannot be worked off drops it: carrying\r\n // it would make the next frame worse.\r\n if (this._accumulator > MAX_STEP) {\r\n this._accumulator = 0;\r\n }\r\n this.externalForce.setXYZ(0, 0, 0);\r\n this.externalTorque.setXYZ(0, 0, 0);\r\n this.applyToNode();\r\n }\r\n /**\r\n * Advance the body by one fixed step.\r\n * @param dt - Step in seconds.\r\n * @param waveHeight - Surface height above the still-water level at a world XZ.\r\n * @param waterLevel - World Y of the still-water level.\r\n */\r\n step(dt: number, waveHeight: WaveHeightFn, waterLevel: number) {\r\n const force = this._force;\r\n const torque = this._torque;\r\n const submerged = this.volume.computeForces(\r\n this.position,\r\n this.rotation,\r\n waveHeight,\r\n waterLevel,\r\n force,\r\n torque\r\n );\r\n // Gravity at the centre of mass, so it contributes no torque.\r\n force.y -= this.volume.mass * this.volume.gravity;\r\n force.addBy(this.externalForce);\r\n torque.addBy(this.externalTorque);\r\n // Resistance, blended between air and water by how much is under.\r\n const linear = this.airLinearDamping + (this.linearDamping - this.airLinearDamping) * submerged;\r\n const angular = this.airAngularDamping + (this.angularDamping - this.airAngularDamping) * submerged;\r\n this.velocity.scaleBy(Math.exp(-linear * dt));\r\n this.angularVelocity.scaleBy(Math.exp(-angular * dt));\r\n // Semi-implicit Euler: velocity first, then position. The ordering is what\r\n // keeps a stiff spring stable at this step size.\r\n Vector3.scale(force, dt / this.volume.mass, this._tmp);\r\n this.velocity.addBy(this._tmp);\r\n Vector3.scale(this.velocity, dt, this._tmp);\r\n this.position.addBy(this._tmp);\r\n // Angular motion in the body frame, where the inertia tensor is diagonal.\r\n this._conj.setXYZW(-this.rotation.x, -this.rotation.y, -this.rotation.z, this.rotation.w);\r\n this._conj.transform(torque, this._torqueBody);\r\n this._torqueBody.setXYZ(\r\n this._torqueBody.x * this._invInertiaBody.x,\r\n this._torqueBody.y * this._invInertiaBody.y,\r\n this._torqueBody.z * this._invInertiaBody.z\r\n );\r\n this.rotation.transform(this._torqueBody, this._tmp);\r\n this._tmp.scaleBy(dt);\r\n this.angularVelocity.addBy(this._tmp);\r\n // q += 0.5 * (omega as a pure quaternion) * q, then renormalise.\r\n const av = this.angularVelocity;\r\n this._wq.setXYZW(av.x * dt * 0.5, av.y * dt * 0.5, av.z * dt * 0.5, 0);\r\n Quaternion.multiply(this._wq, this.rotation, this._wq);\r\n this.rotation.setXYZW(\r\n this.rotation.x + this._wq.x,\r\n this.rotation.y + this._wq.y,\r\n this.rotation.z + this._wq.z,\r\n this.rotation.w + this._wq.w\r\n );\r\n Quaternion.normalize(this.rotation, this.rotation);\r\n }\r\n /** Write the pose to the node, if there is one. */\r\n applyToNode() {\r\n if (this.node) {\r\n this.node.position.setXYZ(this.position.x, this.position.y, this.position.z);\r\n this.node.rotation = this.rotation;\r\n }\r\n }\r\n}\r\n"],"names":["STANDARD_GRAVITY","MAX_STEP","MAX_STEPS_PER_FRAME","BuoyancyVolume","_probeWorld","options","size","clone","mass","Math","max","submergedFraction","min","gravity","maxBuoyancy","draft","y","restHeight","cols","floor","probeColumns","rows","probeRows","layers","probeLayers","sx","x","sy","sz","z","probeHeight","probes","dx","dy","dz","l","j","i","push","Vector3","_probeShare","length","restY","waterLevel","computeForces","position","rotation","waveHeight","outForce","outTorque","setXYZ","submerged","pw","transform","worldX","worldY","worldZ","depth","fraction","magnitude","FloatingBody","node","linearDamping","angularDamping","airLinearDamping","airAngularDamping","_invInertiaBody","_force","_torque","_tmp","_torqueBody","_conj","_wq","_accumulator","volume","Quaternion","velocity","angularVelocity","externalForce","externalTorque","m","reset","yaw","fromEulerAngle","applyToNode","update","deltaSeconds","steps","step","dt","force","torque","addBy","linear","angular","scaleBy","exp","scale","setXYZW","w","av","multiply","normalize"],"mappings":"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"}
|
package/dist/utility/physical.js
CHANGED
|
@@ -45,6 +45,15 @@
|
|
|
45
45
|
*
|
|
46
46
|
* @public
|
|
47
47
|
*/ const PHYSICAL_BAKE_EXPOSURE = 1 / 38400;
|
|
48
|
+
/**
|
|
49
|
+
* Fixed exposure GI caches (voxel radiance, probe irradiance) are stored at:
|
|
50
|
+
* {@link PHYSICAL_BAKE_EXPOSURE} in physical mode, 1 in legacy. Readers convert with
|
|
51
|
+
* `cameraExposure / getGICacheExposure(...)`.
|
|
52
|
+
*
|
|
53
|
+
* @internal
|
|
54
|
+
*/ function getGICacheExposure(lightingMode) {
|
|
55
|
+
return lightingMode === 'physical' ? PHYSICAL_BAKE_EXPOSURE : 1;
|
|
56
|
+
}
|
|
48
57
|
/** Calculate photographic EV100 from aperture, shutter time and ISO. */ function calculateEV100(aperture, shutterSeconds, iso) {
|
|
49
58
|
const safeAperture = Math.max(aperture, 0.0001);
|
|
50
59
|
const safeShutter = Math.max(shutterSeconds, 0.000001);
|
|
@@ -70,5 +79,5 @@
|
|
|
70
79
|
return 2 * Math.atan(Math.max(sensorHeightMm, 0.0001) / (2 * focalLength));
|
|
71
80
|
}
|
|
72
81
|
|
|
73
|
-
export { PHYSICAL_BAKE_EXPOSURE, calculateEV100, calculatePhysicalExposure, calculateVerticalFov };
|
|
82
|
+
export { PHYSICAL_BAKE_EXPOSURE, calculateEV100, calculatePhysicalExposure, calculateVerticalFov, getGICacheExposure };
|
|
74
83
|
//# sourceMappingURL=physical.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"physical.js","sources":["../../src/utility/physical.ts"],"sourcesContent":["/**\r\n * Scene lighting unit model.\r\n *\r\n * @remarks\r\n * `legacy` keeps the original unitless model: light `intensity` is an arbitrary multiplier and\r\n * tonemapping applies a plain `toneMapExposure`. It is a public, widely used API and its behaviour\r\n * is frozen.\r\n *\r\n * `physical` uses photometric units throughout, following Filament's conventions:\r\n *\r\n * | Quantity | Unit | Property |\r\n * | --- | --- | --- |\r\n * | Directional light | lux (lm/m²) | {@link DirectionalLight.illuminance} |\r\n * | Point light | lumen (authored) / candela (shaded) | `luminousPower` / `luminousIntensity` |\r\n * | Spot light | lumen (authored) / candela (shaded) | `luminousPower` / `luminousIntensity` |\r\n * | Rect light | cd/m² (nit) | {@link RectLight.luminance} |\r\n * | Environment / IBL | cd/m² (nit) | `EnvLightWrapper.intensity` |\r\n * | Emissive material | cd/m² (nit) at `emissiveExposureWeight` 1 | `emissiveLuminance` (legacy: `emissiveStrength`) |\r\n * | Camera exposure | unitless multiplier | {@link Camera.exposure} |\r\n *\r\n * Lighting is pre-exposed on the CPU: every light quantity is multiplied by the camera exposure\r\n * before upload, so the HDR render target stays near 1.0 and downstream passes (bloom, SSR, SSGI,\r\n * fog) need no unit awareness. Tonemapping therefore applies the ACES curve only.\r\n *\r\n * Emissive is the one exception, because it is authored on a material rather than a light. It is\r\n * exposed in the shader, and `emissiveExposureWeight` decides whether it is exposed at all: at 1 it\r\n * is a true cd/m² luminance, at 0 the exposure cancels out and `emissiveLuminance` degrades to a\r\n * display-referred multiplier. Imported glTF/FBX materials use 0 to preserve glTF's display-referred\r\n * emissive, so their `emissiveLuminance` does not read in nits.\r\n *\r\n * @public\r\n */\r\nexport type LightingMode = 'legacy' | 'physical';\r\n\r\n/**\r\n * Camera projection parameterization.\r\n *\r\n * @public\r\n */\r\nexport type CameraProjectionMode = 'fov' | 'physical';\r\n\r\n/**\r\n * Sensor dimension used to derive the perspective field of view.\r\n *\r\n * @public\r\n */\r\nexport type CameraSensorFit = 'horizontal' | 'vertical';\r\n\r\n/**\r\n * Fixed exposure the physical sky bake (IBL, distant-light LUT, baked skybox) is stored at, equal\r\n * to the Sunny-16 reference: `1 / 38400 === calculatePhysicalExposure(16, 1/125, 100)`.\r\n *\r\n * @remarks\r\n * The bake is cached and only invalidated when the sun changes, so it cannot carry the live camera\r\n * exposure. Nor can it hold raw photometric luminance: the environment cubemap is `rg11b10uf`\r\n * (max ~65,024) or `rgba16f` (max 65,504), while a 100,000 lux sun drives the atmosphere model to\r\n * ~384,000. That overflows to `Inf` in the sun's direction, and the GGX prefilter plus the SH\r\n * projection then spread the `Inf` across the entire IBL.\r\n *\r\n * Storing at this fixed reference keeps the bake exposure-independent *and* in range. Consumers\r\n * convert to the live exposure with `cameraExposure / PHYSICAL_BAKE_EXPOSURE`.\r\n *\r\n * @public\r\n */\r\nexport const PHYSICAL_BAKE_EXPOSURE = 1 / 38400;\r\n\r\n/** Calculate photographic EV100 from aperture, shutter time and ISO. */\r\nexport function calculateEV100(aperture: number, shutterSeconds: number, iso: number): number {\r\n const safeAperture = Math.max(aperture, 0.0001);\r\n const safeShutter = Math.max(shutterSeconds, 0.000001);\r\n const safeISO = Math.max(iso, 0.0001);\r\n return Math.log2(((safeAperture * safeAperture) / safeShutter) * (100 / safeISO));\r\n}\r\n\r\n/**\r\n * Calculate the scene-linear exposure multiplier for a photometrically calibrated camera.\r\n *\r\n * Uses the saturation-based calibration commonly used by real-time PBR renderers:\r\n * `1 / (1.2 * 2 ^ EV100)`.\r\n */\r\nexport function calculatePhysicalExposure(\r\n aperture: number,\r\n shutterSeconds: number,\r\n iso: number,\r\n compensationEV = 0\r\n): number {\r\n const ev100 = calculateEV100(aperture, shutterSeconds, iso) - compensationEV;\r\n return 1 / (1.2 * Math.pow(2, ev100));\r\n}\r\n\r\n/** Calculate vertical field of view from physical camera parameters. */\r\nexport function calculateVerticalFov(\r\n focalLengthMm: number,\r\n sensorWidthMm: number,\r\n sensorHeightMm: number,\r\n aspect: number,\r\n sensorFit: CameraSensorFit\r\n): number {\r\n const focalLength = Math.max(focalLengthMm, 0.0001);\r\n if (sensorFit === 'horizontal') {\r\n const safeAspect = Math.max(aspect, 0.0001);\r\n const fovX = 2 * Math.atan(Math.max(sensorWidthMm, 0.0001) / (2 * focalLength));\r\n return 2 * Math.atan(Math.tan(fovX * 0.5) / safeAspect);\r\n }\r\n return 2 * Math.atan(Math.max(sensorHeightMm, 0.0001) / (2 * focalLength));\r\n}\r\n"],"names":["PHYSICAL_BAKE_EXPOSURE","calculateEV100","aperture","shutterSeconds","iso","safeAperture","Math","max","safeShutter","safeISO","log2","calculatePhysicalExposure","compensationEV","ev100","pow","calculateVerticalFov","focalLengthMm","sensorWidthMm","sensorHeightMm","aspect","sensorFit","focalLength","safeAspect","fovX","atan","tan"],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DC,IACM,MAAMA,sBAAyB,GAAA,CAAA,GAAI;AAE1C,yEACO,
|
|
1
|
+
{"version":3,"file":"physical.js","sources":["../../src/utility/physical.ts"],"sourcesContent":["/**\r\n * Scene lighting unit model.\r\n *\r\n * @remarks\r\n * `legacy` keeps the original unitless model: light `intensity` is an arbitrary multiplier and\r\n * tonemapping applies a plain `toneMapExposure`. It is a public, widely used API and its behaviour\r\n * is frozen.\r\n *\r\n * `physical` uses photometric units throughout, following Filament's conventions:\r\n *\r\n * | Quantity | Unit | Property |\r\n * | --- | --- | --- |\r\n * | Directional light | lux (lm/m²) | {@link DirectionalLight.illuminance} |\r\n * | Point light | lumen (authored) / candela (shaded) | `luminousPower` / `luminousIntensity` |\r\n * | Spot light | lumen (authored) / candela (shaded) | `luminousPower` / `luminousIntensity` |\r\n * | Rect light | cd/m² (nit) | {@link RectLight.luminance} |\r\n * | Environment / IBL | cd/m² (nit) | `EnvLightWrapper.intensity` |\r\n * | Emissive material | cd/m² (nit) at `emissiveExposureWeight` 1 | `emissiveLuminance` (legacy: `emissiveStrength`) |\r\n * | Camera exposure | unitless multiplier | {@link Camera.exposure} |\r\n *\r\n * Lighting is pre-exposed on the CPU: every light quantity is multiplied by the camera exposure\r\n * before upload, so the HDR render target stays near 1.0 and downstream passes (bloom, SSR, SSGI,\r\n * fog) need no unit awareness. Tonemapping therefore applies the ACES curve only.\r\n *\r\n * Emissive is the one exception, because it is authored on a material rather than a light. It is\r\n * exposed in the shader, and `emissiveExposureWeight` decides whether it is exposed at all: at 1 it\r\n * is a true cd/m² luminance, at 0 the exposure cancels out and `emissiveLuminance` degrades to a\r\n * display-referred multiplier. Imported glTF/FBX materials use 0 to preserve glTF's display-referred\r\n * emissive, so their `emissiveLuminance` does not read in nits.\r\n *\r\n * @public\r\n */\r\nexport type LightingMode = 'legacy' | 'physical';\r\n\r\n/**\r\n * Camera projection parameterization.\r\n *\r\n * @public\r\n */\r\nexport type CameraProjectionMode = 'fov' | 'physical';\r\n\r\n/**\r\n * Sensor dimension used to derive the perspective field of view.\r\n *\r\n * @public\r\n */\r\nexport type CameraSensorFit = 'horizontal' | 'vertical';\r\n\r\n/**\r\n * Fixed exposure the physical sky bake (IBL, distant-light LUT, baked skybox) is stored at, equal\r\n * to the Sunny-16 reference: `1 / 38400 === calculatePhysicalExposure(16, 1/125, 100)`.\r\n *\r\n * @remarks\r\n * The bake is cached and only invalidated when the sun changes, so it cannot carry the live camera\r\n * exposure. Nor can it hold raw photometric luminance: the environment cubemap is `rg11b10uf`\r\n * (max ~65,024) or `rgba16f` (max 65,504), while a 100,000 lux sun drives the atmosphere model to\r\n * ~384,000. That overflows to `Inf` in the sun's direction, and the GGX prefilter plus the SH\r\n * projection then spread the `Inf` across the entire IBL.\r\n *\r\n * Storing at this fixed reference keeps the bake exposure-independent *and* in range. Consumers\r\n * convert to the live exposure with `cameraExposure / PHYSICAL_BAKE_EXPOSURE`.\r\n *\r\n * @public\r\n */\r\nexport const PHYSICAL_BAKE_EXPOSURE = 1 / 38400;\r\n\r\n/**\r\n * Fixed exposure GI caches (voxel radiance, probe irradiance) are stored at:\r\n * {@link PHYSICAL_BAKE_EXPOSURE} in physical mode, 1 in legacy. Readers convert with\r\n * `cameraExposure / getGICacheExposure(...)`.\r\n *\r\n * @internal\r\n */\r\nexport function getGICacheExposure(lightingMode: string) {\r\n return lightingMode === 'physical' ? PHYSICAL_BAKE_EXPOSURE : 1;\r\n}\r\n\r\n/** Calculate photographic EV100 from aperture, shutter time and ISO. */\r\nexport function calculateEV100(aperture: number, shutterSeconds: number, iso: number): number {\r\n const safeAperture = Math.max(aperture, 0.0001);\r\n const safeShutter = Math.max(shutterSeconds, 0.000001);\r\n const safeISO = Math.max(iso, 0.0001);\r\n return Math.log2(((safeAperture * safeAperture) / safeShutter) * (100 / safeISO));\r\n}\r\n\r\n/**\r\n * Calculate the scene-linear exposure multiplier for a photometrically calibrated camera.\r\n *\r\n * Uses the saturation-based calibration commonly used by real-time PBR renderers:\r\n * `1 / (1.2 * 2 ^ EV100)`.\r\n */\r\nexport function calculatePhysicalExposure(\r\n aperture: number,\r\n shutterSeconds: number,\r\n iso: number,\r\n compensationEV = 0\r\n): number {\r\n const ev100 = calculateEV100(aperture, shutterSeconds, iso) - compensationEV;\r\n return 1 / (1.2 * Math.pow(2, ev100));\r\n}\r\n\r\n/** Calculate vertical field of view from physical camera parameters. */\r\nexport function calculateVerticalFov(\r\n focalLengthMm: number,\r\n sensorWidthMm: number,\r\n sensorHeightMm: number,\r\n aspect: number,\r\n sensorFit: CameraSensorFit\r\n): number {\r\n const focalLength = Math.max(focalLengthMm, 0.0001);\r\n if (sensorFit === 'horizontal') {\r\n const safeAspect = Math.max(aspect, 0.0001);\r\n const fovX = 2 * Math.atan(Math.max(sensorWidthMm, 0.0001) / (2 * focalLength));\r\n return 2 * Math.atan(Math.tan(fovX * 0.5) / safeAspect);\r\n }\r\n return 2 * Math.atan(Math.max(sensorHeightMm, 0.0001) / (2 * focalLength));\r\n}\r\n"],"names":["PHYSICAL_BAKE_EXPOSURE","getGICacheExposure","lightingMode","calculateEV100","aperture","shutterSeconds","iso","safeAperture","Math","max","safeShutter","safeISO","log2","calculatePhysicalExposure","compensationEV","ev100","pow","calculateVerticalFov","focalLengthMm","sensorWidthMm","sensorHeightMm","aspect","sensorFit","focalLength","safeAspect","fovX","atan","tan"],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DC,IACM,MAAMA,sBAAyB,GAAA,CAAA,GAAI;AAE1C;;;;;;IAOO,SAASC,kBAAAA,CAAmBC,YAAoB,EAAA;IACrD,OAAOA,YAAAA,KAAiB,aAAaF,sBAAyB,GAAA,CAAA;AAChE;AAEA,yEACO,SAASG,cAAAA,CAAeC,QAAgB,EAAEC,cAAsB,EAAEC,GAAW,EAAA;AAClF,IAAA,MAAMC,YAAeC,GAAAA,IAAAA,CAAKC,GAAG,CAACL,QAAU,EAAA,MAAA,CAAA;AACxC,IAAA,MAAMM,WAAcF,GAAAA,IAAAA,CAAKC,GAAG,CAACJ,cAAgB,EAAA,QAAA,CAAA;AAC7C,IAAA,MAAMM,OAAUH,GAAAA,IAAAA,CAAKC,GAAG,CAACH,GAAK,EAAA,MAAA,CAAA;IAC9B,OAAOE,IAAAA,CAAKI,IAAI,CAAGL,eAAeA,YAAgBG,GAAAA,WAAAA,IAAgB,GAAA,GAAMC,OAAM,CAAA,CAAA;AAChF;AAEA;;;;;IAMO,SAASE,yBAAAA,CACdT,QAAgB,EAChBC,cAAsB,EACtBC,GAAW,EACXQ,cAAAA,GAAiB,CAAC,EAAA;AAElB,IAAA,MAAMC,KAAQZ,GAAAA,cAAAA,CAAeC,QAAUC,EAAAA,cAAAA,EAAgBC,GAAOQ,CAAAA,GAAAA,cAAAA;AAC9D,IAAA,OAAO,KAAK,GAAA,GAAMN,KAAKQ,GAAG,CAAC,GAAGD,KAAK,CAAA,CAAA;AACrC;AAEA,yEACO,SAASE,oBAAAA,CACdC,aAAqB,EACrBC,aAAqB,EACrBC,cAAsB,EACtBC,MAAc,EACdC,SAA0B,EAAA;AAE1B,IAAA,MAAMC,WAAcf,GAAAA,IAAAA,CAAKC,GAAG,CAACS,aAAe,EAAA,MAAA,CAAA;AAC5C,IAAA,IAAII,cAAc,YAAc,EAAA;AAC9B,QAAA,MAAME,UAAahB,GAAAA,IAAAA,CAAKC,GAAG,CAACY,MAAQ,EAAA,MAAA,CAAA;AACpC,QAAA,MAAMI,IAAO,GAAA,CAAA,GAAIjB,IAAKkB,CAAAA,IAAI,CAAClB,IAAAA,CAAKC,GAAG,CAACU,aAAe,EAAA,MAAA,CAAA,IAAW,CAAA,GAAII,WAAU,CAAA,CAAA;QAC5E,OAAO,CAAA,GAAIf,KAAKkB,IAAI,CAAClB,KAAKmB,GAAG,CAACF,OAAO,GAAOD,CAAAA,GAAAA,UAAAA,CAAAA;AAC9C;IACA,OAAO,CAAA,GAAIhB,IAAKkB,CAAAA,IAAI,CAAClB,IAAAA,CAAKC,GAAG,CAACW,cAAgB,EAAA,MAAA,CAAA,IAAW,CAAA,GAAIG,WAAU,CAAA,CAAA;AACzE;;;;"}
|
package/dist/utility/pmrem.js
CHANGED
|
@@ -111,49 +111,23 @@ function createPMREMProgram(type, numSamples) {
|
|
|
111
111
|
this.NUM_SAMPLES_FLOAT_INVERSED = pb.float(1 / numSamples);
|
|
112
112
|
this.K = pb.float(4);
|
|
113
113
|
this.$outputs.outcolor = pb.vec4();
|
|
114
|
-
|
|
115
|
-
pb.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
});
|
|
132
|
-
pb.func('hammersley2d', [
|
|
133
|
-
pb.int('i'),
|
|
134
|
-
pb.int('N')
|
|
135
|
-
], function() {
|
|
136
|
-
this.$return(pb.vec2(pb.div(pb.float(this.i), pb.float(this.N)), this.radicalInverse_VdC(this.i)));
|
|
137
|
-
});
|
|
138
|
-
} else {
|
|
139
|
-
pb.func('radicalInverse_VdC', [
|
|
140
|
-
pb.uint('bits')
|
|
141
|
-
], function() {
|
|
142
|
-
this.$l.n = this.bits;
|
|
143
|
-
this.n = pb.compOr(pb.sal(this.n, 16), pb.sar(this.n, 16));
|
|
144
|
-
this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x55555555), 1), pb.sar(pb.compAnd(this.n, 0xaaaaaaaa), 1));
|
|
145
|
-
this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x33333333), 2), pb.sar(pb.compAnd(this.n, 0xcccccccc), 2));
|
|
146
|
-
this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x0f0f0f0f), 4), pb.sar(pb.compAnd(this.n, 0xf0f0f0f0), 4));
|
|
147
|
-
this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x00ff00ff), 8), pb.sar(pb.compAnd(this.n, 0xff00ff00), 8));
|
|
148
|
-
this.$return(pb.mul(pb.float(this.n), 2.3283064365386963e-10));
|
|
149
|
-
});
|
|
150
|
-
pb.func('hammersley2d', [
|
|
151
|
-
pb.int('i'),
|
|
152
|
-
pb.int('N')
|
|
153
|
-
], function() {
|
|
154
|
-
this.$return(pb.vec2(pb.div(pb.float(this.i), pb.float(this.N)), this.radicalInverse_VdC(pb.uint(this.i))));
|
|
155
|
-
});
|
|
156
|
-
}
|
|
114
|
+
pb.func('radicalInverse_VdC', [
|
|
115
|
+
pb.uint('bits')
|
|
116
|
+
], function() {
|
|
117
|
+
this.$l.n = this.bits;
|
|
118
|
+
this.n = pb.compOr(pb.sal(this.n, 16), pb.sar(this.n, 16));
|
|
119
|
+
this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x55555555), 1), pb.sar(pb.compAnd(this.n, 0xaaaaaaaa), 1));
|
|
120
|
+
this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x33333333), 2), pb.sar(pb.compAnd(this.n, 0xcccccccc), 2));
|
|
121
|
+
this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x0f0f0f0f), 4), pb.sar(pb.compAnd(this.n, 0xf0f0f0f0), 4));
|
|
122
|
+
this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x00ff00ff), 8), pb.sar(pb.compAnd(this.n, 0xff00ff00), 8));
|
|
123
|
+
this.$return(pb.mul(pb.float(this.n), 2.3283064365386963e-10));
|
|
124
|
+
});
|
|
125
|
+
pb.func('hammersley2d', [
|
|
126
|
+
pb.int('i'),
|
|
127
|
+
pb.int('N')
|
|
128
|
+
], function() {
|
|
129
|
+
this.$return(pb.vec2(pb.div(pb.float(this.i), pb.float(this.N)), this.radicalInverse_VdC(pb.uint(this.i))));
|
|
130
|
+
});
|
|
157
131
|
pb.func('log4', [
|
|
158
132
|
pb.float('x')
|
|
159
133
|
], function() {
|