@woosh/meep-engine 3.25.0 → 3.27.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/package.json +1 -1
- package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +542 -0
- package/src/core/binary/lz4/LZ4_LEVEL.d.ts +33 -0
- package/src/core/binary/lz4/LZ4_LEVEL.d.ts.map +1 -0
- package/src/core/binary/lz4/LZ4_LEVEL.js +32 -0
- package/src/core/binary/lz4/lz4_compress_block_at_level.d.ts +33 -0
- package/src/core/binary/lz4/lz4_compress_block_at_level.d.ts.map +1 -0
- package/src/core/binary/lz4/lz4_compress_block_at_level.js +47 -0
- package/src/core/binary/lz4/lz4_compress_block_hc.d.ts +40 -0
- package/src/core/binary/lz4/lz4_compress_block_hc.d.ts.map +1 -0
- package/src/core/binary/lz4/lz4_compress_block_hc.js +1382 -0
- package/src/core/binary/lz4/lz4_decompress_block.d.ts +2 -1
- package/src/core/binary/lz4/lz4_decompress_block.d.ts.map +1 -1
- package/src/core/binary/lz4/lz4_decompress_block.js +31 -6
- package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +66 -0
- package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/HeightMapShape3D.js +314 -20
- package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/PosedShape3D.js +57 -0
- package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/TransformedShape3D.js +102 -0
- package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/UnionShape3D.js +64 -0
- package/src/engine/physics/cloth/MEASUREMENTS.md +582 -0
- package/src/engine/physics/cloth/PLAN.md +330 -49
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +84 -17
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -1
- package/src/engine/physics/cloth/collider/ClothColliderIndex.js +451 -42
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +65 -7
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +72 -8
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +25 -4
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.js +75 -8
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +41 -4
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothWorld.js +207 -63
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +10 -0
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +17 -1
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +27 -3
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +28 -3
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +75 -10
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +131 -12
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +19 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +249 -201
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +62 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back.js +18 -10
- package/src/engine/physics/cloth/playground/collide_main.js +1 -1
- package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +29 -8
- package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_contact_find.js +37 -9
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +12 -2
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_solver_constants.js +12 -2
- package/src/engine/physics/cloth/solver/cloth_step_instance.js +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts +9 -2
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js +9 -2
- package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts +23 -9
- package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts.map +1 -1
- package/src/engine/physics/cloth/wind/AbstractClothWind.js +23 -9
- package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts +7 -5
- package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts.map +1 -1
- package/src/engine/physics/cloth/wind/ClothAmbientWind.js +12 -9
- package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -1
- package/src/engine/physics/cloth/wind/ClothFluidWind.js +5 -2
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +7 -2
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -1
- package/src/engine/physics/cloth/wind/cloth_sample_air.js +12 -5
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/playground/vgeo_runtime/README.md +167 -22
- package/src/shade/playground/vgeo_runtime/index.html +112 -62
- package/src/shade/playground/vgeo_runtime/main.js +660 -83
- package/src/shade/playground/vgeo_viewer/sample_asset.d.ts.map +1 -1
- package/src/shade/playground/vgeo_viewer/sample_asset.js +19 -2
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts +11 -0
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +16 -8
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +16 -11
- package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +73 -5
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +26 -15
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +5 -3
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +18 -0
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +20 -0
- package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +56 -9
- package/src/shade/renderer/geometry/virtual/build/vgeo_build.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +1 -0
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +22 -0
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +24 -0
- package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts +12 -0
- package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +13 -0
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.d.ts +8 -1
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +11 -3
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +10 -1
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.d.ts +18 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.js +17 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.d.ts +8 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.js +7 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +16 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.d.ts +14 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.js +13 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.d.ts +11 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.js +10 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts +20 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.js +20 -2
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts +4 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.js +4 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts +29 -3
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.js +81 -122
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +40 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +44 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts +69 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.js +236 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts +14 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.js +15 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.d.ts +31 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.js +32 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts +10 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.js +21 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.d.ts +15 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.js +84 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.d.ts +22 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.js +96 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +55 -0
- package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +202 -13
- package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +147 -10
- package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +637 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts +33 -36
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js +109 -193
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +58 -28
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +77 -105
- package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +37 -0
- package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +105 -22
- package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +548 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts +29 -50
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +47 -489
- package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts +84 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.js +393 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts +234 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.js +1363 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.d.ts +81 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.js +89 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts +53 -34
- package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +407 -124
- package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.d.ts +100 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.js +219 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.d.ts +17 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.js +47 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.d.ts +20 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.js +19 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.js +30 -12
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +15 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +18 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.js +5 -15
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.js +77 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.js +186 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js +20 -8
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +580 -188
- package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts +15 -18
- package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.js +19 -28
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +45 -25
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js +11 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts +0 -1
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.js +12 -10
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts +7 -2
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.js +8 -3
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts +2 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.js +19 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.js +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.d.ts +5 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.js +22 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.d.ts +14 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.js +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.d.ts +17 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.js +16 -0
- package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.d.ts +15 -0
- package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.js +16 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.d.ts +23 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.js +28 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.d.ts +2 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.js +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts +10 -5
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.js +15 -6
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts +6 -1
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.js +38 -1
- package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.js +4 -3
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +6 -3
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +6 -3
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +12 -4
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts +2 -0
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.js +58 -57
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.js +3 -5
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.js +3 -4
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.js +3 -4
- package/src/shade/renderer/rasterize/expand/pass0/pass_mesh_cull.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/pass0/pass_mesh_cull.js +7 -7
- package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.js +83 -78
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +7 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +7 -1
- package/src/shade/renderer/scene/GPUSceneContext.d.ts +22 -2
- package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUSceneContext.js +59 -4
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +92 -16
- package/src/shade/renderer/view/GPUViewContext.d.ts +5 -0
- package/src/shade/renderer/view/GPUViewContext.d.ts.map +1 -1
- package/src/shade/renderer/view/GPUViewContext.js +21 -0
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +74 -3
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.js +0 -723
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.js +0 -50
- package/src/shade/renderer/shader/chunk/jobs/NOTES.md +0 -47
- package/src/shade/renderer/shader/chunk/jobs/chunk_job_system.js +0 -102
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* its low nibble the match length less four; either saturates at fifteen and continues in whole
|
|
7
7
|
* bytes, a 255 meaning "and more". The match's distance is a 16-bit little-endian offset back from
|
|
8
8
|
* the write head, and it is allowed to reach into bytes this same sequence is producing — that
|
|
9
|
-
* overlap is how the format codes runs, so
|
|
9
|
+
* overlap is how the format codes runs, so a match that reaches back less far than it is long is
|
|
10
|
+
* copied a byte at a time.
|
|
10
11
|
*
|
|
11
12
|
* Blocks here are independent: a match reaches back no further than `destination_offset`, never
|
|
12
13
|
* into whatever a previous block left in the buffer. That is what `LZ4_compress_default` produces
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lz4_decompress_block.d.ts","sourceRoot":"","sources":["../../../../../src/core/binary/lz4/lz4_decompress_block.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lz4_decompress_block.d.ts","sourceRoot":"","sources":["../../../../../src/core/binary/lz4/lz4_decompress_block.js"],"names":[],"mappings":"AAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,kDATW,UAAU,sBACV,MAAM,mBACN,MAAM,UACN,UAAU,iBACV,MAAM,cACN,MAAM,GACJ,MAAM,CAyHlB"}
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { assert } from "../../assert.js";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Runs shorter than this are cheaper to copy a byte at a time than to hand to `set` or
|
|
5
|
+
* `copyWithin`, whose call overhead dominates until there is a memmove's worth of work behind it.
|
|
6
|
+
* Both halves earn their keep, and on real geometry it is the literals that carry the win: four
|
|
7
|
+
* fifths of a decoded `.vgeo` page arrives as literal runs of about thirty-five bytes, while its
|
|
8
|
+
* matches average nine and stay in the loop whatever this is set to.
|
|
9
|
+
*
|
|
10
|
+
* Swept on 2,267 real pages at both block shapes. The top of the curve is broad — anything from
|
|
11
|
+
* sixteen up is most of the win — and this is where it sits, which is also where
|
|
12
|
+
* {@link lz4_compress_block} put its own, arrived at separately and on literals alone.
|
|
13
|
+
*/
|
|
14
|
+
const BULK_COPY_LENGTH = 32;
|
|
15
|
+
|
|
3
16
|
/**
|
|
4
17
|
* Decode one LZ4 block.
|
|
5
18
|
*
|
|
@@ -8,7 +21,8 @@ import { assert } from "../../assert.js";
|
|
|
8
21
|
* its low nibble the match length less four; either saturates at fifteen and continues in whole
|
|
9
22
|
* bytes, a 255 meaning "and more". The match's distance is a 16-bit little-endian offset back from
|
|
10
23
|
* the write head, and it is allowed to reach into bytes this same sequence is producing — that
|
|
11
|
-
* overlap is how the format codes runs, so
|
|
24
|
+
* overlap is how the format codes runs, so a match that reaches back less far than it is long is
|
|
25
|
+
* copied a byte at a time.
|
|
12
26
|
*
|
|
13
27
|
* Blocks here are independent: a match reaches back no further than `destination_offset`, never
|
|
14
28
|
* into whatever a previous block left in the buffer. That is what `LZ4_compress_default` produces
|
|
@@ -72,8 +86,12 @@ export function lz4_decompress_block(destination, destination_offset, destinatio
|
|
|
72
86
|
);
|
|
73
87
|
}
|
|
74
88
|
|
|
75
|
-
|
|
76
|
-
destination
|
|
89
|
+
if (literal_length >= BULK_COPY_LENGTH) {
|
|
90
|
+
destination.set(source.subarray(s, s + literal_length), d);
|
|
91
|
+
} else {
|
|
92
|
+
for (let i = 0; i < literal_length; i++) {
|
|
93
|
+
destination[d + i] = source[s + i];
|
|
94
|
+
}
|
|
77
95
|
}
|
|
78
96
|
|
|
79
97
|
d += literal_length;
|
|
@@ -127,9 +145,16 @@ export function lz4_decompress_block(destination, destination_offset, destinatio
|
|
|
127
145
|
);
|
|
128
146
|
}
|
|
129
147
|
|
|
130
|
-
//
|
|
131
|
-
|
|
132
|
-
|
|
148
|
+
// A match that does not reach back as far as it is long overlaps the bytes it is writing, and
|
|
149
|
+
// that is how the format codes runs: `copyWithin` moves as if through a temporary, so it
|
|
150
|
+
// would lay down one copy of the pattern where the format means it to repeat. Only a match
|
|
151
|
+
// clear of its own output can take it, and the byte loop below is the run.
|
|
152
|
+
if (match_length >= BULK_COPY_LENGTH && match_offset >= match_length) {
|
|
153
|
+
destination.copyWithin(d, match_position, match_position + match_length);
|
|
154
|
+
} else {
|
|
155
|
+
for (let i = 0; i < match_length; i++) {
|
|
156
|
+
destination[d + i] = destination[match_position + i];
|
|
157
|
+
}
|
|
133
158
|
}
|
|
134
159
|
|
|
135
160
|
d += match_length;
|
|
@@ -158,6 +158,72 @@ export class HeightMapShape3D extends AbstractShape3D {
|
|
|
158
158
|
* site is forced to handle heightmaps explicitly.
|
|
159
159
|
*/
|
|
160
160
|
support(result: any, result_offset: any, direction_x: any, direction_y: any, direction_z: any): void;
|
|
161
|
+
/**
|
|
162
|
+
* Nearest ray hit against the height-field SURFACE, in the shape's body-local
|
|
163
|
+
* frame. Writes `[px, py, pz, nx, ny, nz]` into `hit` and returns true; a miss
|
|
164
|
+
* returns false and leaves `hit` untouched.
|
|
165
|
+
*
|
|
166
|
+
* ## What is hit
|
|
167
|
+
*
|
|
168
|
+
* The surface, not the solid. The class models a closed volume (floor at h=0,
|
|
169
|
+
* height field above), but a ray meets only the height field — there is no
|
|
170
|
+
* floor quad and no side skirt, so a ray that passes under the terrain or
|
|
171
|
+
* enters through the footprint edge below the surface reports a miss. That is
|
|
172
|
+
* the same body {@link heightmap_enumerate_triangles} hands the contact
|
|
173
|
+
* narrowphase, and the same body the terrain renderer draws; a raycast that
|
|
174
|
+
* answered for the skirt would disagree with both. Mirrors
|
|
175
|
+
* {@link MeshShape3D#raycast}, which is likewise surface-only.
|
|
176
|
+
*
|
|
177
|
+
* Precisely the same triangles, too: the traversal reads its corner heights at
|
|
178
|
+
* the identical `i / seg_u` / `j / seg_v` UVs through the identical Catmull-Rom
|
|
179
|
+
* filter, and splits each sub-cell on the same lower-left diagonal
|
|
180
|
+
* (`(A,D,B)`, `(D,C,B)`), so a cast and a contact resolve against a surface
|
|
181
|
+
* that agrees bit for bit — {@link tessellation} included.
|
|
182
|
+
*
|
|
183
|
+
* NORMAL: the triangle's geometric normal, flipped to face the incoming ray
|
|
184
|
+
* (the shared {@link tri3_raycast} convention). A cast from below the terrain
|
|
185
|
+
* therefore reports a downward normal, not the surface's true upward one.
|
|
186
|
+
*
|
|
187
|
+
* A hit landing exactly ON a seam between facets gets the normal of one of the
|
|
188
|
+
* facets meeting there. INSIDE a sub-cell the two paths agree — they split on
|
|
189
|
+
* the same D–B diagonal and break the resulting tie in favour of the same
|
|
190
|
+
* facet — which matters because that diagonal runs through the sub-cell's
|
|
191
|
+
* centre, so a cast down the middle of a cell lands on it routinely rather
|
|
192
|
+
* than exceptionally.
|
|
193
|
+
*
|
|
194
|
+
* BETWEEN sub-cells they can differ, and which facet each names follows from
|
|
195
|
+
* traversal order: this walks the grid along the ray, the narrowphase
|
|
196
|
+
* enumerates it row-major, so on a grid line — and especially a grid corner,
|
|
197
|
+
* where four facets meet — the two can name different facets. The hit POINT
|
|
198
|
+
* still agrees; a faceted surface simply has no single normal at a seam.
|
|
199
|
+
* Measure-zero, and called out because it is the only place the two answers
|
|
200
|
+
* part company.
|
|
201
|
+
*
|
|
202
|
+
* `size.y` does NOT bound the query. Sampler values are not clamped to it (see
|
|
203
|
+
* the class docstring), so clipping the ray to the height range that
|
|
204
|
+
* {@link compute_bounding_box} reports could reject real surface standing above
|
|
205
|
+
* it; only the footprint is clipped against.
|
|
206
|
+
*
|
|
207
|
+
* ## Cost
|
|
208
|
+
*
|
|
209
|
+
* A 2-D DDA over the `(W−1)·N × (H−1)·N` sub-cell grid, two triangles per cell,
|
|
210
|
+
* stopping at the first cell that hits — cells are visited in increasing ray
|
|
211
|
+
* order and a sub-cell's triangles project exactly onto its own footprint
|
|
212
|
+
* rectangle, so nothing behind can be nearer. O(cells the ray crosses), not
|
|
213
|
+
* O(cells in the ray's bounding box): a long diagonal cast costs the grid's
|
|
214
|
+
* diagonal rather than its area.
|
|
215
|
+
*
|
|
216
|
+
* Four Catmull-Rom evaluations per cell, uncached — deliberately unlike
|
|
217
|
+
* {@link heightmap_enumerate_triangles}, whose corner-row cache exists because
|
|
218
|
+
* the contact narrowphase re-samples the same rect every substep. A ray walks
|
|
219
|
+
* a diagonal, visits each cell once, and stops early; there is nothing to
|
|
220
|
+
* amortise against.
|
|
221
|
+
*
|
|
222
|
+
* @param {Float32Array|number[]} hit out: [px, py, pz, nx, ny, nz]
|
|
223
|
+
* @param {Ray3} ray body-local ray (unit direction; `ray[6]` = tMax)
|
|
224
|
+
* @returns {boolean} whether anything was hit
|
|
225
|
+
*/
|
|
226
|
+
raycast(hit: Float32Array | number[], ray: Ray3): boolean;
|
|
161
227
|
sample_random_point_in_volume(result: any, result_offset: any, random: any): void;
|
|
162
228
|
/**
|
|
163
229
|
* @param {HeightMapShape3D} other
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeightMapShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/HeightMapShape3D.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"HeightMapShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/HeightMapShape3D.js"],"names":[],"mappings":"AAuBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH;IA4DI;;;;;;;;;;;OAWG;IACH,wCATW,MAAM,UACN,MAAM,UACN,MAAM,gBACN,OAAO,iBACP,MAAM,GAGJ,gBAAgB,CAqB5B;IA1FD;;;;;OAKG;IACH,sBAFU,OAAO,CAEkB;IAEnC;;;;;;;OAOG;IACH,eAFU,OAAO,CAEW;IAE5B;;;;;OAKG;IACH,SAFU,YAAY,IAAI,CAEX;IAEf;;;;;;;;;;;;;;;;OAgBG;IACH,cAFU,MAAM,CAEC;IAEjB;;;;;OAKG;IACH,eAA6B;IAG7B,6BAA2B;IAE3B,6BAA2B;IAC3B,6BAA2B;IAmC3B;;;;;;;;;OASG;IACH,sBA8CC;IAED;;;;;;OAMG;IACH,yBAJW,MAAM,OACN,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;;;OAQG;IACH,8BALW,MAAM,MACN,MAAM,MACN,MAAM,GACJ,MAAM,CAelB;IAED,wCA6BC;IAED,oCA2BC;IAED;;;;;;;;OAQG;IACH,6CAmBC;IAED;;;;OAIG;IACH,4DA2BC;IAED;;;;;;;;;OASG;IACH,qGAEC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgEG;IACH,aAJW,YAAY,GAAC,MAAM,EAAE,cAEnB,OAAO,CA0NnB;IAED,kFAiBC;IA6CD;;;OAGG;IACH,cAHW,gBAAgB,GACd,OAAO,CAUnB;IAWL;;;;;;OAMG;IACH,6BAFU,OAAO,CAE4B;CAT5C;gCAluB+B,sBAAsB;wBAD9B,kBAAkB"}
|
|
@@ -2,12 +2,25 @@ import { hash_mix3 } from "../../../math/hash/hash_mix3.js";
|
|
|
2
2
|
import { hash_mix2 } from "../../../math/hash/hash_mix2.js";
|
|
3
3
|
import { assert } from "../../../assert.js";
|
|
4
4
|
import { clamp } from "../../../math/clamp.js";
|
|
5
|
+
import { clamp_index } from "../../../math/clamp_index.js";
|
|
5
6
|
import { optional_equality } from "../../../model/object/optional_equality.js";
|
|
6
7
|
import { optional_hash } from "../../../model/object/optional_hash.js";
|
|
8
|
+
import { tri3_raycast } from "../triangle/tri3_raycast.js";
|
|
9
|
+
import { v3_cross } from "../../vec3/v3_cross.js";
|
|
10
|
+
import { v3_dot } from "../../vec3/v3_dot.js";
|
|
7
11
|
import { v3_length } from "../../vec3/v3_length.js";
|
|
8
12
|
import { Vector3 } from "../../Vector3.js";
|
|
9
13
|
import { AbstractShape3D } from "./AbstractShape3D.js";
|
|
10
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Below this, a ray's footprint-plane velocity component counts as zero in
|
|
17
|
+
* {@link HeightMapShape3D#raycast}'s slab clip — the reciprocal a smaller value
|
|
18
|
+
* would produce is not a usable slab distance. Matches the concave narrowphase's
|
|
19
|
+
* `refine_ray_concave`, so the two agree on rays that graze the footprint edge.
|
|
20
|
+
* @type {number}
|
|
21
|
+
*/
|
|
22
|
+
const RAY_SLAB_EPSILON = 1e-12;
|
|
23
|
+
|
|
11
24
|
/**
|
|
12
25
|
* Heightmap shape, intended primarily for terrain.
|
|
13
26
|
*
|
|
@@ -182,14 +195,13 @@ export class HeightMapShape3D extends AbstractShape3D {
|
|
|
182
195
|
u_y *= u_inv;
|
|
183
196
|
u_z *= u_inv;
|
|
184
197
|
|
|
185
|
-
// v = u × n (for n=+Y, u=+X this gives v=+Z, the intuitive choice)
|
|
186
|
-
const v_x = u_y * nz - u_z * ny;
|
|
187
|
-
const v_y = u_z * nx - u_x * nz;
|
|
188
|
-
const v_z = u_x * ny - u_y * nx;
|
|
189
|
-
|
|
190
198
|
const b = this._basis;
|
|
199
|
+
|
|
191
200
|
b[0] = u_x; b[1] = u_y; b[2] = u_z;
|
|
192
|
-
|
|
201
|
+
|
|
202
|
+
// v = u × n (for n=+Y, u=+X this gives v=+Z, the intuitive choice)
|
|
203
|
+
v3_cross(b, 3, u_x, u_y, u_z, nx, ny, nz);
|
|
204
|
+
|
|
193
205
|
b[6] = nx; b[7] = ny; b[8] = nz;
|
|
194
206
|
|
|
195
207
|
this._basis_orientation_x = nx;
|
|
@@ -223,8 +235,8 @@ export class HeightMapShape3D extends AbstractShape3D {
|
|
|
223
235
|
const b = this._basis;
|
|
224
236
|
|
|
225
237
|
// project onto basis u and basis v
|
|
226
|
-
const u_coord = b[0]
|
|
227
|
-
const v_coord = b[3]
|
|
238
|
+
const u_coord = v3_dot(b[0], b[1], b[2], px, py, pz);
|
|
239
|
+
const v_coord = v3_dot(b[3], b[4], b[5], px, py, pz);
|
|
228
240
|
|
|
229
241
|
const u01 = u_coord / this.size[0] + 0.5;
|
|
230
242
|
const v01 = v_coord / this.size[2] + 0.5;
|
|
@@ -256,11 +268,10 @@ export class HeightMapShape3D extends AbstractShape3D {
|
|
|
256
268
|
|
|
257
269
|
const uv_extent = Math.abs(cu) * half_u + Math.abs(cv) * half_v;
|
|
258
270
|
|
|
259
|
-
const
|
|
260
|
-
const h_hi = ch > 0 ? ch * sy : 0;
|
|
271
|
+
const h_extent = ch * sy;
|
|
261
272
|
|
|
262
|
-
result[k] = -uv_extent +
|
|
263
|
-
result[k + 3] = uv_extent +
|
|
273
|
+
result[k] = -uv_extent + Math.min(h_extent, 0);
|
|
274
|
+
result[k + 3] = uv_extent + Math.max(h_extent, 0);
|
|
264
275
|
}
|
|
265
276
|
}
|
|
266
277
|
|
|
@@ -274,9 +285,9 @@ export class HeightMapShape3D extends AbstractShape3D {
|
|
|
274
285
|
const b = this._basis;
|
|
275
286
|
|
|
276
287
|
// project into heightmap-local frame (u, v, h)
|
|
277
|
-
const u_coord = b[0]
|
|
278
|
-
const v_coord = b[3]
|
|
279
|
-
const h_coord = b[6]
|
|
288
|
+
const u_coord = v3_dot(b[0], b[1], b[2], px, py, pz);
|
|
289
|
+
const v_coord = v3_dot(b[3], b[4], b[5], px, py, pz);
|
|
290
|
+
const h_coord = v3_dot(b[6], b[7], b[8], px, py, pz);
|
|
280
291
|
|
|
281
292
|
const half_u = this.size[0] * 0.5;
|
|
282
293
|
const half_v = this.size[2] * 0.5;
|
|
@@ -311,9 +322,9 @@ export class HeightMapShape3D extends AbstractShape3D {
|
|
|
311
322
|
|
|
312
323
|
const b = this._basis;
|
|
313
324
|
|
|
314
|
-
const u_coord = b[0]
|
|
315
|
-
const v_coord = b[3]
|
|
316
|
-
const h_coord = b[6]
|
|
325
|
+
const u_coord = v3_dot(b[0], b[1], b[2], px, py, pz);
|
|
326
|
+
const v_coord = v3_dot(b[3], b[4], b[5], px, py, pz);
|
|
327
|
+
const h_coord = v3_dot(b[6], b[7], b[8], px, py, pz);
|
|
317
328
|
|
|
318
329
|
const u01 = u_coord / this.size[0] + 0.5;
|
|
319
330
|
const v01 = v_coord / this.size[2] + 0.5;
|
|
@@ -337,8 +348,8 @@ export class HeightMapShape3D extends AbstractShape3D {
|
|
|
337
348
|
|
|
338
349
|
const b = this._basis;
|
|
339
350
|
|
|
340
|
-
const u_coord = b[0]
|
|
341
|
-
const v_coord = b[3]
|
|
351
|
+
const u_coord = v3_dot(b[0], b[1], b[2], rx, ry, rz);
|
|
352
|
+
const v_coord = v3_dot(b[3], b[4], b[5], rx, ry, rz);
|
|
342
353
|
|
|
343
354
|
const half_u = this.size[0] * 0.5;
|
|
344
355
|
const half_v = this.size[2] * 0.5;
|
|
@@ -371,6 +382,289 @@ export class HeightMapShape3D extends AbstractShape3D {
|
|
|
371
382
|
throw new Error("HeightMapShape3D.support: heightmaps are non-convex; the narrowphase must dispatch grid-traversal instead.");
|
|
372
383
|
}
|
|
373
384
|
|
|
385
|
+
/**
|
|
386
|
+
* Nearest ray hit against the height-field SURFACE, in the shape's body-local
|
|
387
|
+
* frame. Writes `[px, py, pz, nx, ny, nz]` into `hit` and returns true; a miss
|
|
388
|
+
* returns false and leaves `hit` untouched.
|
|
389
|
+
*
|
|
390
|
+
* ## What is hit
|
|
391
|
+
*
|
|
392
|
+
* The surface, not the solid. The class models a closed volume (floor at h=0,
|
|
393
|
+
* height field above), but a ray meets only the height field — there is no
|
|
394
|
+
* floor quad and no side skirt, so a ray that passes under the terrain or
|
|
395
|
+
* enters through the footprint edge below the surface reports a miss. That is
|
|
396
|
+
* the same body {@link heightmap_enumerate_triangles} hands the contact
|
|
397
|
+
* narrowphase, and the same body the terrain renderer draws; a raycast that
|
|
398
|
+
* answered for the skirt would disagree with both. Mirrors
|
|
399
|
+
* {@link MeshShape3D#raycast}, which is likewise surface-only.
|
|
400
|
+
*
|
|
401
|
+
* Precisely the same triangles, too: the traversal reads its corner heights at
|
|
402
|
+
* the identical `i / seg_u` / `j / seg_v` UVs through the identical Catmull-Rom
|
|
403
|
+
* filter, and splits each sub-cell on the same lower-left diagonal
|
|
404
|
+
* (`(A,D,B)`, `(D,C,B)`), so a cast and a contact resolve against a surface
|
|
405
|
+
* that agrees bit for bit — {@link tessellation} included.
|
|
406
|
+
*
|
|
407
|
+
* NORMAL: the triangle's geometric normal, flipped to face the incoming ray
|
|
408
|
+
* (the shared {@link tri3_raycast} convention). A cast from below the terrain
|
|
409
|
+
* therefore reports a downward normal, not the surface's true upward one.
|
|
410
|
+
*
|
|
411
|
+
* A hit landing exactly ON a seam between facets gets the normal of one of the
|
|
412
|
+
* facets meeting there. INSIDE a sub-cell the two paths agree — they split on
|
|
413
|
+
* the same D–B diagonal and break the resulting tie in favour of the same
|
|
414
|
+
* facet — which matters because that diagonal runs through the sub-cell's
|
|
415
|
+
* centre, so a cast down the middle of a cell lands on it routinely rather
|
|
416
|
+
* than exceptionally.
|
|
417
|
+
*
|
|
418
|
+
* BETWEEN sub-cells they can differ, and which facet each names follows from
|
|
419
|
+
* traversal order: this walks the grid along the ray, the narrowphase
|
|
420
|
+
* enumerates it row-major, so on a grid line — and especially a grid corner,
|
|
421
|
+
* where four facets meet — the two can name different facets. The hit POINT
|
|
422
|
+
* still agrees; a faceted surface simply has no single normal at a seam.
|
|
423
|
+
* Measure-zero, and called out because it is the only place the two answers
|
|
424
|
+
* part company.
|
|
425
|
+
*
|
|
426
|
+
* `size.y` does NOT bound the query. Sampler values are not clamped to it (see
|
|
427
|
+
* the class docstring), so clipping the ray to the height range that
|
|
428
|
+
* {@link compute_bounding_box} reports could reject real surface standing above
|
|
429
|
+
* it; only the footprint is clipped against.
|
|
430
|
+
*
|
|
431
|
+
* ## Cost
|
|
432
|
+
*
|
|
433
|
+
* A 2-D DDA over the `(W−1)·N × (H−1)·N` sub-cell grid, two triangles per cell,
|
|
434
|
+
* stopping at the first cell that hits — cells are visited in increasing ray
|
|
435
|
+
* order and a sub-cell's triangles project exactly onto its own footprint
|
|
436
|
+
* rectangle, so nothing behind can be nearer. O(cells the ray crosses), not
|
|
437
|
+
* O(cells in the ray's bounding box): a long diagonal cast costs the grid's
|
|
438
|
+
* diagonal rather than its area.
|
|
439
|
+
*
|
|
440
|
+
* Four Catmull-Rom evaluations per cell, uncached — deliberately unlike
|
|
441
|
+
* {@link heightmap_enumerate_triangles}, whose corner-row cache exists because
|
|
442
|
+
* the contact narrowphase re-samples the same rect every substep. A ray walks
|
|
443
|
+
* a diagonal, visits each cell once, and stops early; there is nothing to
|
|
444
|
+
* amortise against.
|
|
445
|
+
*
|
|
446
|
+
* @param {Float32Array|number[]} hit out: [px, py, pz, nx, ny, nz]
|
|
447
|
+
* @param {Ray3} ray body-local ray (unit direction; `ray[6]` = tMax)
|
|
448
|
+
* @returns {boolean} whether anything was hit
|
|
449
|
+
*/
|
|
450
|
+
raycast(hit, ray) {
|
|
451
|
+
const sampler = this.sampler;
|
|
452
|
+
|
|
453
|
+
if (sampler === null) {
|
|
454
|
+
return false;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const size_x = this.size[0];
|
|
458
|
+
const size_z = this.size[2];
|
|
459
|
+
|
|
460
|
+
if (size_x <= 0 || size_z <= 0) {
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// The collision grid heightmap_enumerate_triangles builds. A sampler too
|
|
465
|
+
// thin to hold one cell on an axis (width or height < 2), or tessellation
|
|
466
|
+
// 0, collapses it — no triangles exist, so nothing can be hit.
|
|
467
|
+
const seg_u = (sampler.width - 1) * this.tessellation;
|
|
468
|
+
const seg_v = (sampler.height - 1) * this.tessellation;
|
|
469
|
+
|
|
470
|
+
if (seg_u < 1 || seg_v < 1) {
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
this._ensure_basis();
|
|
475
|
+
|
|
476
|
+
const b = this._basis;
|
|
477
|
+
|
|
478
|
+
const o_x = ray[0], o_y = ray[1], o_z = ray[2];
|
|
479
|
+
const d_x = ray[3], d_y = ray[4], d_z = ray[5];
|
|
480
|
+
|
|
481
|
+
// Body → heightmap-local footprint coordinates. The basis is orthonormal,
|
|
482
|
+
// so the direction stays unit and `t` is the same distance in both frames;
|
|
483
|
+
// the height component is never needed, the triangles carry it.
|
|
484
|
+
const o_u = v3_dot(b[0], b[1], b[2], o_x, o_y, o_z);
|
|
485
|
+
const o_v = v3_dot(b[3], b[4], b[5], o_x, o_y, o_z);
|
|
486
|
+
const d_u = v3_dot(b[0], b[1], b[2], d_x, d_y, d_z);
|
|
487
|
+
const d_v = v3_dot(b[3], b[4], b[5], d_x, d_y, d_z);
|
|
488
|
+
|
|
489
|
+
const half_u = size_x * 0.5;
|
|
490
|
+
const half_v = size_z * 0.5;
|
|
491
|
+
|
|
492
|
+
const t_max = ray[6];
|
|
493
|
+
|
|
494
|
+
// ── Clip to the footprint slabs → the segment the DDA walks ──────────
|
|
495
|
+
let t_enter = 0;
|
|
496
|
+
let t_exit = t_max;
|
|
497
|
+
|
|
498
|
+
if (d_u > RAY_SLAB_EPSILON || d_u < -RAY_SLAB_EPSILON) {
|
|
499
|
+
const inv = 1 / d_u;
|
|
500
|
+
const t0 = (-half_u - o_u) * inv;
|
|
501
|
+
const t1 = (half_u - o_u) * inv;
|
|
502
|
+
|
|
503
|
+
t_enter = Math.max(t_enter, Math.min(t0, t1));
|
|
504
|
+
t_exit = Math.min(t_exit, Math.max(t0, t1));
|
|
505
|
+
} else if (o_u < -half_u || o_u > half_u) {
|
|
506
|
+
return false;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if (d_v > RAY_SLAB_EPSILON || d_v < -RAY_SLAB_EPSILON) {
|
|
510
|
+
const inv = 1 / d_v;
|
|
511
|
+
const t0 = (-half_v - o_v) * inv;
|
|
512
|
+
const t1 = (half_v - o_v) * inv;
|
|
513
|
+
|
|
514
|
+
t_enter = Math.max(t_enter, Math.min(t0, t1));
|
|
515
|
+
t_exit = Math.min(t_exit, Math.max(t0, t1));
|
|
516
|
+
} else if (o_v < -half_v || o_v > half_v) {
|
|
517
|
+
return false;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
if (t_exit < t_enter) {
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// ── Amanatides–Woo setup on the sub-cell grid ────────────────────────
|
|
525
|
+
//
|
|
526
|
+
// Grid coordinates run [0, seg_u] × [0, seg_v] across the footprint. A
|
|
527
|
+
// ray with no footprint-plane velocity (cast straight down the
|
|
528
|
+
// orientation axis) keeps both rates at 0, both t_next at Infinity, and
|
|
529
|
+
// the loop tests its single cell and stops.
|
|
530
|
+
const per_cell_u = seg_u / size_x;
|
|
531
|
+
const per_cell_v = seg_v / size_z;
|
|
532
|
+
|
|
533
|
+
const rate_u = d_u * per_cell_u;
|
|
534
|
+
const rate_v = d_v * per_cell_v;
|
|
535
|
+
|
|
536
|
+
const g_u = (o_u + d_u * t_enter + half_u) * per_cell_u;
|
|
537
|
+
const g_v = (o_v + d_v * t_enter + half_v) * per_cell_v;
|
|
538
|
+
|
|
539
|
+
// Clamped to the grid because the slab clip lands the entry point ON the
|
|
540
|
+
// boundary, where rounding can put it a ULP outside.
|
|
541
|
+
let i = clamp_index(Math.floor(g_u), seg_u);
|
|
542
|
+
let j = clamp_index(Math.floor(g_v), seg_v);
|
|
543
|
+
|
|
544
|
+
// `t_next` is the distance at which the ray leaves the starting cell
|
|
545
|
+
// through that axis' far grid line, `t_delta` the distance a whole cell
|
|
546
|
+
// costs thereafter. A zero rate leaves both at Infinity: that axis is
|
|
547
|
+
// never the one the walk steps along.
|
|
548
|
+
let step_i = 0, t_delta_u = Infinity, t_next_u = Infinity;
|
|
549
|
+
if (rate_u !== 0) {
|
|
550
|
+
// the grid line the starting cell is left through: its far side
|
|
551
|
+
// in the direction of travel
|
|
552
|
+
const exit_line = rate_u > 0 ? i + 1 : i;
|
|
553
|
+
|
|
554
|
+
step_i = rate_u > 0 ? 1 : -1;
|
|
555
|
+
t_delta_u = Math.abs(1 / rate_u);
|
|
556
|
+
t_next_u = t_enter + (exit_line - g_u) / rate_u;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
let step_j = 0, t_delta_v = Infinity, t_next_v = Infinity;
|
|
560
|
+
if (rate_v !== 0) {
|
|
561
|
+
const exit_line = rate_v > 0 ? j + 1 : j;
|
|
562
|
+
|
|
563
|
+
step_j = rate_v > 0 ? 1 : -1;
|
|
564
|
+
t_delta_v = Math.abs(1 / rate_v);
|
|
565
|
+
t_next_v = t_enter + (exit_line - g_v) / rate_v;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
const inv_seg_u = 1 / seg_u;
|
|
569
|
+
const inv_seg_v = 1 / seg_v;
|
|
570
|
+
|
|
571
|
+
const ux = b[0], uy = b[1], uz = b[2];
|
|
572
|
+
const vx = b[3], vy = b[4], vz = b[5];
|
|
573
|
+
const nx = b[6], ny = b[7], nz = b[8];
|
|
574
|
+
|
|
575
|
+
// Every iteration but the last ends by crossing one grid line, and a
|
|
576
|
+
// straight line crosses fewer than seg_u + seg_v of them (a corner costs
|
|
577
|
+
// two iterations to move diagonally — one per axis — but no extra lines).
|
|
578
|
+
// The walk normally ends on t_exit; this is the bound that holds when a
|
|
579
|
+
// near-denormal rate makes t_exit unreachable.
|
|
580
|
+
const max_steps = seg_u + seg_v + 2;
|
|
581
|
+
|
|
582
|
+
for (let step = 0; step < max_steps; step++) {
|
|
583
|
+
// ── The sub-cell's two triangles, built exactly as the enumerator
|
|
584
|
+
// builds them: corners (A,B,C,D) = (i,j), (i+1,j), (i+1,j+1),
|
|
585
|
+
// (i,j+1), split (A,D,B) and (D,C,B).
|
|
586
|
+
const u01_lo = i * inv_seg_u;
|
|
587
|
+
const u01_hi = (i + 1) * inv_seg_u;
|
|
588
|
+
const v01_lo = j * inv_seg_v;
|
|
589
|
+
const v01_hi = (j + 1) * inv_seg_v;
|
|
590
|
+
|
|
591
|
+
const u_lo = -half_u + size_x * u01_lo;
|
|
592
|
+
const u_hi = -half_u + size_x * u01_hi;
|
|
593
|
+
const v_lo = -half_v + size_z * v01_lo;
|
|
594
|
+
const v_hi = -half_v + size_z * v01_hi;
|
|
595
|
+
|
|
596
|
+
const hA = sampler.sampleChannelCatmullRomUV(u01_lo, v01_lo, 0);
|
|
597
|
+
const hB = sampler.sampleChannelCatmullRomUV(u01_hi, v01_lo, 0);
|
|
598
|
+
const hC = sampler.sampleChannelCatmullRomUV(u01_hi, v01_hi, 0);
|
|
599
|
+
const hD = sampler.sampleChannelCatmullRomUV(u01_lo, v01_hi, 0);
|
|
600
|
+
|
|
601
|
+
const Ax = ux * u_lo + vx * v_lo + nx * hA;
|
|
602
|
+
const Ay = uy * u_lo + vy * v_lo + ny * hA;
|
|
603
|
+
const Az = uz * u_lo + vz * v_lo + nz * hA;
|
|
604
|
+
|
|
605
|
+
const Bx = ux * u_hi + vx * v_lo + nx * hB;
|
|
606
|
+
const By = uy * u_hi + vy * v_lo + ny * hB;
|
|
607
|
+
const Bz = uz * u_hi + vz * v_lo + nz * hB;
|
|
608
|
+
|
|
609
|
+
const Cx = ux * u_hi + vx * v_hi + nx * hC;
|
|
610
|
+
const Cy = uy * u_hi + vy * v_hi + ny * hC;
|
|
611
|
+
const Cz = uz * u_hi + vz * v_hi + nz * hC;
|
|
612
|
+
|
|
613
|
+
const Dx = ux * u_lo + vx * v_hi + nx * hD;
|
|
614
|
+
const Dy = uy * u_lo + vy * v_hi + ny * hD;
|
|
615
|
+
const Dz = uz * u_lo + vz * v_hi + nz * hD;
|
|
616
|
+
|
|
617
|
+
// Tested in reverse enumeration order, and that is what decides the
|
|
618
|
+
// tie. The two facets share the D–B diagonal — which runs through the
|
|
619
|
+
// sub-cell's centre, so a ray landing on it is the ordinary case, not a
|
|
620
|
+
// corner one — and a ray that lands on it hits both at one distance.
|
|
621
|
+
// `refine_ray_concave` enumerates (A,D,B) first and lets a later
|
|
622
|
+
// triangle win only by a strictly smaller distance, so the facet it
|
|
623
|
+
// names is (A,D,B). tri3_raycast admits `t <= tMax` and writes hit[3..5]
|
|
624
|
+
// only on a hit, so testing (D,C,B) first and handing (A,D,B) its
|
|
625
|
+
// distance as the budget lets the equal hit overwrite the normal — and
|
|
626
|
+
// the two paths name the same facet.
|
|
627
|
+
const t_dcb = tri3_raycast(
|
|
628
|
+
hit, 3, o_x, o_y, o_z, d_x, d_y, d_z, t_max,
|
|
629
|
+
Dx, Dy, Dz, Cx, Cy, Cz, Bx, By, Bz
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
const t_adb = tri3_raycast(
|
|
633
|
+
hit, 3, o_x, o_y, o_z, d_x, d_y, d_z, Math.min(t_dcb, t_max),
|
|
634
|
+
Ax, Ay, Az, Dx, Dy, Dz, Bx, By, Bz
|
|
635
|
+
);
|
|
636
|
+
|
|
637
|
+
const best = Math.min(t_adb, t_dcb);
|
|
638
|
+
|
|
639
|
+
if (best !== Infinity) {
|
|
640
|
+
hit[0] = o_x + d_x * best;
|
|
641
|
+
hit[1] = o_y + d_y * best;
|
|
642
|
+
hit[2] = o_z + d_z * best;
|
|
643
|
+
|
|
644
|
+
return true;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// ── Advance to the next cell along the ray ───────────────────────
|
|
648
|
+
if (t_next_u < t_next_v) {
|
|
649
|
+
if (t_next_u > t_exit) break;
|
|
650
|
+
i += step_i;
|
|
651
|
+
if (i < 0 || i >= seg_u) break;
|
|
652
|
+
t_next_u += t_delta_u;
|
|
653
|
+
} else if (t_next_v !== Infinity) {
|
|
654
|
+
if (t_next_v > t_exit) break;
|
|
655
|
+
j += step_j;
|
|
656
|
+
if (j < 0 || j >= seg_v) break;
|
|
657
|
+
t_next_v += t_delta_v;
|
|
658
|
+
} else {
|
|
659
|
+
// Both rates are zero: the ray runs along the orientation axis and
|
|
660
|
+
// never leaves the cell it started in.
|
|
661
|
+
break;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
return false;
|
|
666
|
+
}
|
|
667
|
+
|
|
374
668
|
sample_random_point_in_volume(result, result_offset, random) {
|
|
375
669
|
const u01 = random();
|
|
376
670
|
const v01 = random();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PosedShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/PosedShape3D.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PosedShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/PosedShape3D.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;GAmBG;AACH;IAEI,mCAAmC;IACnC,OADW,eAAe,GAAC,IAAI,CAClB;IAEb,WAAO;IACP,WAAO;IACP,WAAO;IACP,WAAO;IACP,WAAO;IACP,WAAO;IACP,WAAO;IAEP;;;;;;;OAOG;IACH,aAJW,eAAe,YACf,UAAQ;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,YACpC,aAAW;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,QAe1D;IAED;;;;;;;;;;;;;;;OAeG;IACH,wBATW,eAAe,MACf,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QAMhB;IA+HD,wCASC;IA4BD;;;;;;;OAOG;IACH,gCAHW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,GAChC,MAAM,CAKlB;IAED;;;;;OAKG;IACH,sBAHW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,GAChC,OAAO,CAKnB;IAGL;;;;OAIG;IACH,yBAFU,OAAO,CAEoB;;CAPpC;gCA5Q+B,sBAAsB"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { assert } from "../../../assert.js";
|
|
2
|
+
import { v3_quaternion_apply } from "../../vec3/v3_quaternion_apply.js";
|
|
3
|
+
import { v3_quaternion_apply_inverse } from "../../vec3/v3_quaternion_apply_inverse.js";
|
|
2
4
|
import { aabb3_transform_oriented } from "../aabb/aabb3_transform_oriented.js";
|
|
5
|
+
import { Ray3 } from "../ray/Ray3.js";
|
|
3
6
|
import { AbstractShape3D } from "./AbstractShape3D.js";
|
|
4
7
|
|
|
5
8
|
const scratch_local = new Float64Array(3);
|
|
@@ -154,6 +157,60 @@ export class PosedShape3D extends AbstractShape3D {
|
|
|
154
157
|
result[result_offset + 2] = tsz * qw - tsw * qz - tsx * qy + tsy * qx + this.pz;
|
|
155
158
|
}
|
|
156
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Ray ↔ posed shape, with the ray given in the WRAPPER's frame. The inverse pose carries it into
|
|
162
|
+
* the subject's frame (translate by −position, rotate by the conjugate quaternion), the subject
|
|
163
|
+
* answers there, and the answer is rotated back — the point re-translated, the normal not.
|
|
164
|
+
*
|
|
165
|
+
* A rigid pose is an isometry, so the crossing changes nothing about the ray's parametrisation:
|
|
166
|
+
* the rotated direction is still unit, `tMax` goes through untouched, and the distance the subject
|
|
167
|
+
* measures IS the distance here. The normal's ORIENTATION survives for the same reason — a rotation
|
|
168
|
+
* preserves the angle between normal and direction, so a subject that turned its normal to meet the
|
|
169
|
+
* ray has turned this one to meet it too, and there is nothing to re-check.
|
|
170
|
+
*
|
|
171
|
+
* `hit` is handed straight to the subject rather than buffered and copied back: on a hit its
|
|
172
|
+
* contents are mapped in place, and on a miss the subject leaves it untouched — which is the
|
|
173
|
+
* convention this class owes its own caller, so it is passed on intact.
|
|
174
|
+
*
|
|
175
|
+
* The physics ray query does not come through here; it uses `refine_ray_posed`, which performs the
|
|
176
|
+
* same mapping on loose scalars. That path reports a distance rather than a point, so it never
|
|
177
|
+
* rotates anything but the normal.
|
|
178
|
+
*
|
|
179
|
+
* @param {Float32Array|number[]} hit out: [px, py, pz, nx, ny, nz]
|
|
180
|
+
* @param {Ray3} ray wrapper-frame ray (origin in [0..2], unit direction in [3..5], tMax in [6])
|
|
181
|
+
* @returns {boolean} whether anything was hit
|
|
182
|
+
*/
|
|
183
|
+
raycast(hit, ray) {
|
|
184
|
+
const shape = this.shape;
|
|
185
|
+
|
|
186
|
+
if (shape === null) {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const qx = this.qx, qy = this.qy, qz = this.qz, qw = this.qw;
|
|
191
|
+
|
|
192
|
+
// Allocated per call rather than kept as a module scratch: a posed shape may wrap another
|
|
193
|
+
// wrapper, and every level of that recursion needs its own sub-ray alive across the call below.
|
|
194
|
+
const local_ray = new Ray3();
|
|
195
|
+
|
|
196
|
+
v3_quaternion_apply_inverse(local_ray, 0, ray[0] - this.px, ray[1] - this.py, ray[2] - this.pz, qx, qy, qz, qw);
|
|
197
|
+
v3_quaternion_apply_inverse(local_ray, 3, ray[3], ray[4], ray[5], qx, qy, qz, qw);
|
|
198
|
+
local_ray[6] = ray[6];
|
|
199
|
+
|
|
200
|
+
if (!shape.raycast(hit, local_ray)) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
v3_quaternion_apply(hit, 0, hit[0], hit[1], hit[2], qx, qy, qz, qw);
|
|
205
|
+
v3_quaternion_apply(hit, 3, hit[3], hit[4], hit[5], qx, qy, qz, qw);
|
|
206
|
+
|
|
207
|
+
hit[0] += this.px;
|
|
208
|
+
hit[1] += this.py;
|
|
209
|
+
hit[2] += this.pz;
|
|
210
|
+
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
|
|
157
214
|
compute_bounding_box(result) {
|
|
158
215
|
this.shape.compute_bounding_box(scratch_local_aabb);
|
|
159
216
|
aabb3_transform_oriented(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransformedShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/TransformedShape3D.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TransformedShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/TransformedShape3D.js"],"names":[],"mappings":"AAyBA;IAwCI;;;;;OAKG;IACH,wBAHW,eAAe,MADf,MAAM,EAAE,GAAC,YAAY,OAAK,GAExB,kBAAkB,CAS9B;IAED;;;;;OAKG;IACH,uCAJW,eAAe,eACf,MAAM,EAAE,SACR,MAAM,EAAE,sBAiBlB;IAED;;;;OAIG;IACH,iCAHW,eAAe,eACf,MAAM,EAAE,sBAIlB;IAED;;;;;OAKG;IACH,2BAHW,eAAe,SACf,MAAM,EAAE,GAAC,YAAY,OAAK,GAFxB,kBAAkB,CAM9B;IA9FD;;;;OAIG;IACH,iBAAgC;IAEhC;;;;OAIG;IACH,yBAAwC;IAExC;;;;OAIG;IACH,kBAAiB;IAEjB;;;OAGG;IACH,+BAEC;IAqED;;;OAGG;IACH,0CAIC;IAED,yCAEC;IAED;;;;;;;OAOG;IACH,6BAEC;IAUD,wCAKC;IAED,mEAyDC;IAED,6CAEC;IAED,oCAKC;IAED,kFAIC;IAED,qGAwCC;IAuGD;;;;OAIG;IACH,cAHW,kBAAkB,GAChB,OAAO,CAOnB;IAQL;;;;;OAKG;IACH,+BAFU,OAAO,CAEgC;CARhD;gCAnY+B,sBAAsB"}
|