@woosh/meep-engine 3.28.0 → 3.29.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/build/bundle-worker-terrain.js +1 -1
- package/package.json +1 -1
- package/src/core/binary/BitSet.d.ts +16 -0
- package/src/core/binary/BitSet.d.ts.map +1 -1
- package/src/core/binary/BitSet.js +159 -49
- package/src/core/binary/allocator/OffsetAllocator.d.ts +48 -0
- package/src/core/binary/allocator/OffsetAllocator.d.ts.map +1 -1
- package/src/core/binary/allocator/OffsetAllocator.js +208 -9
- package/src/core/binary/compression/compress_bytes.d.ts +20 -0
- package/src/core/binary/compression/compress_bytes.d.ts.map +1 -0
- package/src/core/binary/compression/compress_bytes.js +35 -0
- package/src/core/binary/compression/decompress_bytes_into.d.ts +30 -0
- package/src/core/binary/compression/decompress_bytes_into.d.ts.map +1 -0
- package/src/core/binary/compression/decompress_bytes_into.js +87 -0
- package/src/core/binary/compression/deflate_decompress_bound.d.ts +27 -0
- package/src/core/binary/compression/deflate_decompress_bound.d.ts.map +1 -0
- package/src/core/binary/compression/deflate_decompress_bound.js +32 -0
- package/src/core/geom/3d/quadric/quadric_attribute_add.d.ts +24 -0
- package/src/core/geom/3d/quadric/quadric_attribute_add.d.ts.map +1 -0
- package/src/core/geom/3d/quadric/quadric_attribute_add.js +31 -0
- package/src/core/geom/3d/quadric/quadric_attribute_reduce.d.ts +46 -0
- package/src/core/geom/3d/quadric/quadric_attribute_reduce.d.ts.map +1 -0
- package/src/core/geom/3d/quadric/quadric_attribute_reduce.js +104 -0
- package/src/core/geom/3d/quadric/quadric_attribute_set_from_triangle.d.ts +62 -0
- package/src/core/geom/3d/quadric/quadric_attribute_set_from_triangle.d.ts.map +1 -0
- package/src/core/geom/3d/quadric/quadric_attribute_set_from_triangle.js +158 -0
- package/src/core/geom/3d/quadric/quadric_attribute_size.d.ts +21 -0
- package/src/core/geom/3d/quadric/quadric_attribute_size.d.ts.map +1 -0
- package/src/core/geom/3d/quadric/quadric_attribute_size.js +24 -0
- package/src/core/geom/3d/quadric/quadric_attribute_solve.d.ts +34 -0
- package/src/core/geom/3d/quadric/quadric_attribute_solve.d.ts.map +1 -0
- package/src/core/geom/3d/quadric/quadric_attribute_solve.js +55 -0
- package/src/core/geom/3d/quadric/quadric_attribute_sub.d.ts +28 -0
- package/src/core/geom/3d/quadric/quadric_attribute_sub.d.ts.map +1 -0
- package/src/core/geom/3d/quadric/quadric_attribute_sub.js +35 -0
- package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.d.ts +15 -0
- package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.js +35 -0
- package/src/core/geom/3d/topology/struct/binary/BtWedgeSet.d.ts +93 -0
- package/src/core/geom/3d/topology/struct/binary/BtWedgeSet.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/BtWedgeSet.js +128 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_wedge_attribute_quadrics.d.ts +38 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_wedge_attribute_quadrics.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_wedge_attribute_quadrics.js +113 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.d.ts +47 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.js +677 -8
- package/src/core/geom/3d/topology/struct/binary/io/bt_wedges_live_count.d.ts +22 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_wedges_live_count.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_wedges_live_count.js +46 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_wedges_per_vertex.d.ts +19 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_wedges_per_vertex.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_wedges_per_vertex.js +49 -0
- package/src/core/graph/layout/layered/BoxLayoutOptions.d.ts +63 -0
- package/src/core/graph/layout/layered/BoxLayoutOptions.d.ts.map +1 -0
- package/src/core/graph/layout/layered/BoxLayoutOptions.js +80 -0
- package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/LayoutBoxGraph.d.ts +35 -0
- package/src/core/graph/layout/layered/LayoutBoxGraph.d.ts.map +1 -0
- package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/LayoutBoxGraph.js +53 -1
- package/src/core/graph/layout/layered/layout_assign_coordinates.d.ts.map +1 -0
- package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_assign_coordinates.js +72 -68
- package/src/core/graph/layout/layered/layout_assign_layers.d.ts.map +1 -0
- package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_assign_layers.js +4 -2
- package/src/core/graph/layout/layered/layout_break_cycles.d.ts.map +1 -0
- package/src/core/graph/layout/layered/layout_insert_lanes.d.ts.map +1 -0
- package/src/core/graph/layout/layered/layout_order_layers.d.ts.map +1 -0
- package/src/core/graph/layout/layered/layout_orient_links.d.ts.map +1 -0
- package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts +7 -51
- package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.js +8 -69
- package/src/core/model/node-graph/visual/layout/layout_build_problem.js +1 -1
- package/src/core/model/node-graph/visual/layout/layout_node_graph.js +6 -6
- package/src/core/model/node-graph/visual/layout/route_grid_build.js +1 -1
- package/src/engine/graphics3/DebugDrawSystem.d.ts +7 -5
- package/src/engine/graphics3/DebugDrawSystem.d.ts.map +1 -1
- package/src/engine/graphics3/DebugDrawSystem.js +206 -203
- package/src/engine/graphics3/DecalSystem.d.ts +4 -5
- package/src/engine/graphics3/DecalSystem.d.ts.map +1 -1
- package/src/engine/graphics3/DecalSystem.js +5 -5
- package/src/engine/graphics3/FogOfWarSystem.d.ts +7 -12
- package/src/engine/graphics3/FogOfWarSystem.d.ts.map +1 -1
- package/src/engine/graphics3/FogOfWarSystem.js +8 -12
- package/src/engine/graphics3/prefab/prefab_instantiate.js +230 -230
- package/src/shade/RENDERER_CONTRACT.md +12 -7
- package/src/shade/playground/caldera/README.md +529 -0
- package/src/shade/playground/caldera/caldera_format.d.ts +151 -0
- package/src/shade/playground/caldera/caldera_format.d.ts.map +1 -0
- package/src/shade/playground/caldera/caldera_format.js +241 -0
- package/src/shade/playground/caldera/index.html +126 -0
- package/src/shade/playground/caldera/main.d.ts.map +1 -0
- package/src/shade/playground/caldera/main.js +1565 -0
- package/src/shade/playground/mesh_row_ceiling/README.md +85 -0
- package/src/shade/playground/mesh_row_ceiling/index.html +31 -0
- package/src/shade/playground/mesh_row_ceiling/main.d.ts +2 -0
- package/src/shade/playground/mesh_row_ceiling/main.d.ts.map +1 -0
- package/src/shade/playground/mesh_row_ceiling/main.js +389 -0
- package/src/shade/playground/vgeo_runtime/README.md +5 -3
- package/src/shade/playground/vgeo_runtime/main.js +3 -2
- package/src/shade/playground/vgeo_runtime/sample_asset.d.ts +3 -3
- package/src/shade/playground/vgeo_runtime/sample_asset.d.ts.map +1 -1
- package/src/shade/playground/vgeo_runtime/sample_asset.js +3 -3
- package/src/shade/playground/vgeo_scene/README.md +103 -24
- package/src/shade/playground/vgeo_scene/main.js +525 -24
- package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
- package/src/shade/renderer/GraphicsContext.js +6 -0
- package/src/shade/renderer/Renderer.d.ts +2 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +23 -0
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +100 -8
- package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +69 -33
- package/src/shade/renderer/extension/RenderExtension.d.ts +15 -18
- package/src/shade/renderer/extension/RenderExtension.d.ts.map +1 -1
- package/src/shade/renderer/extension/RenderExtension.js +15 -19
- package/src/shade/renderer/extension/RenderExtensionRegistry.d.ts +5 -5
- package/src/shade/renderer/extension/RenderExtensionRegistry.d.ts.map +1 -1
- package/src/shade/renderer/extension/RenderExtensionRegistry.js +29 -166
- package/src/shade/renderer/geometry/GPUGeometryManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/GPUGeometryManager.js +73 -16
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +18 -3
- package/src/shade/renderer/geometry/meshlet/COMPACTION_PLAN_2026_09_16.md +663 -0
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts +100 -5
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +688 -81
- package/src/shade/renderer/geometry/virtual/ATTRIBUTE_PLAN_2026_09_18.md +540 -0
- package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +155 -64
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +30 -13
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +3 -3
- package/src/shade/renderer/geometry/virtual/WEDGE_PLAN_2026_09_18.md +358 -0
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +57 -7
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +63 -9
- package/src/shade/renderer/geometry/virtual/build/level/VGeoContribution.d.ts +40 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoContribution.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoContribution.js +24 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoFrontier.d.ts +91 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoFrontier.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoFrontier.js +91 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoGroupRepack.d.ts +24 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoGroupRepack.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoGroupRepack.js +25 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoGroupStep.d.ts +77 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoGroupStep.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoGroupStep.js +84 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelOptions.d.ts +19 -6
- package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelOptions.js +20 -7
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_cluster.d.ts +19 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_cluster.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_cluster.js +58 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_cluster_graph.d.ts +18 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_cluster_graph.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_cluster_graph.js +116 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.d.ts +18 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.js +545 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.d.ts +16 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.js +110 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_levels.d.ts +2 -27
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_levels.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_levels.js +120 -1564
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_compute_group_boundary.d.ts +26 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_compute_group_boundary.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_compute_group_boundary.js +123 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_error_bands.d.ts +26 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_error_bands.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_error_bands.js +78 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.d.ts +24 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.js +337 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.d.ts +29 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.js +147 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_stitch_frontier.d.ts +37 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_stitch_frontier.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_stitch_frontier.js +243 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.d.ts +29 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.js +117 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/VGEO_CREASE_ANGLE.d.ts +46 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/VGEO_CREASE_ANGLE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/VGEO_CREASE_ANGLE.js +45 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/VGEO_DEFAULT_ATTRIBUTE_WEIGHT_RATIOS.d.ts +64 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/VGEO_DEFAULT_ATTRIBUTE_WEIGHT_RATIOS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/VGEO_DEFAULT_ATTRIBUTE_WEIGHT_RATIOS.js +68 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/VirtualGeometryMesh.d.ts +12 -7
- package/src/shade/renderer/geometry/virtual/build/mesh/VirtualGeometryMesh.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/mesh/VirtualGeometryMesh.js +33 -11
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_layout.d.ts +58 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_layout.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_layout.js +79 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_read.d.ts +39 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_read.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_read.js +68 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_write.d.ts +53 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_write.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_write.js +243 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_normals.d.ts +24 -8
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_normals.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_normals.js +250 -25
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_tangents.d.ts +12 -8
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_tangents.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_tangents.js +58 -50
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_normalize_source.d.ts +8 -1
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_normalize_source.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_normalize_source.js +18 -3
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_resolve_attribute_weights.d.ts +38 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_resolve_attribute_weights.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_resolve_attribute_weights.js +81 -0
- package/src/shade/renderer/geometry/virtual/build/partition/VGeoFaceGraph.d.ts +23 -5
- package/src/shade/renderer/geometry/virtual/build/partition/VGeoFaceGraph.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/partition/VGeoFaceGraph.js +28 -21
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set.js +1 -1
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.js +224 -60
- package/src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.d.ts +15 -0
- package/src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.js +17 -0
- package/src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.d.ts +17 -0
- package/src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.js +19 -0
- package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.d.ts +10 -1
- package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.js +103 -9
- package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.d.ts +14 -2
- package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.js +38 -14
- package/src/shade/renderer/geometry/virtual/build/vgeo_build.d.ts +6 -2
- package/src/shade/renderer/geometry/virtual/build/vgeo_build.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +28 -5
- package/src/shade/renderer/geometry/virtual/build/vgeo_subtree_bounds.d.ts +32 -0
- package/src/shade/renderer/geometry/virtual/build/vgeo_subtree_bounds.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/vgeo_subtree_bounds.js +93 -0
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +20 -6
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +22 -8
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_corner.d.ts +16 -0
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_corner.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/attribute/{vgeo_layers_copy_vertex.js → vgeo_layers_copy_corner.js} +8 -8
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.d.ts +18 -7
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.js +19 -8
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_like.d.ts +3 -3
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_like.js +3 -3
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_mesh_wedges.d.ts +27 -0
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_mesh_wedges.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_mesh_wedges.js +97 -0
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.d.ts +7 -3
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.js +21 -11
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET_V4.d.ts +21 -0
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET_V4.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET_V4.js +41 -0
- package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts +19 -1
- package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +20 -1
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_DEFLATE.d.ts +25 -0
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_DEFLATE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_DEFLATE.js +24 -0
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.d.ts +5 -0
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.js +5 -0
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_codec_name.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_codec_name.js +5 -0
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.d.ts +10 -3
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.js +37 -3
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.d.ts +21 -13
- 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 +37 -13
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.d.ts +8 -2
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.js +14 -2
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.d.ts +18 -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 +19 -1
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_OFFSET.js +6 -0
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAX_LEVEL_COUNT.d.ts +21 -0
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAX_LEVEL_COUNT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAX_LEVEL_COUNT.js +20 -0
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.js +10 -1
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.d.ts +1 -2
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +10 -3
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET_V5.d.ts +20 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET_V5.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET_V5.js +43 -0
- package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.d.ts +4 -2
- package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.js +8 -4
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.js +2 -2
- package/src/shade/renderer/geometry/virtual/format/read/VGeoDirectory.d.ts +6 -4
- package/src/shade/renderer/geometry/virtual/format/read/VGeoDirectory.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoDirectory.js +6 -4
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +13 -2
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +13 -2
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts +5 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.js +14 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.js +1 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_directory.d.ts +4 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_directory.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_directory.js +53 -11
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.js +7 -3
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts +12 -2
- 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 +111 -33
- package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts +6 -2
- 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 +112 -42
- package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts +2 -2
- 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 +51 -21
- package/src/shade/renderer/geometry/virtual/runtime/CULL_PLAN_2026_09_16.md +385 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.js +9 -0
- 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 +34 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.js +18 -0
- 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 +47 -19
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.js +22 -4
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts +7 -2
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.js +8 -3
- 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 +10 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts +13 -11
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.js +13 -11
- 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 +4 -0
- 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 +3 -4
- package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.d.ts +6 -2
- package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.js +90 -12
- package/src/shade/renderer/gpu_primitive/indirect/WEBGPU_GUARANTEED_MAX_COMPUTE_WORKGROUPS_PER_DIMENSION.d.ts +22 -0
- package/src/shade/renderer/gpu_primitive/indirect/WEBGPU_GUARANTEED_MAX_COMPUTE_WORKGROUPS_PER_DIMENSION.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/indirect/WEBGPU_GUARANTEED_MAX_COMPUTE_WORKGROUPS_PER_DIMENSION.js +21 -0
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +13 -8
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +3 -6
- 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 +4 -12
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts +0 -2
- 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 +4 -5
- 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 +5 -3
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way.js +11 -4
- 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 +4 -3
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.js +3 -0
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_count_by_rasterization_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_count_by_rasterization_bucket.js +94 -90
- 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 +13 -5
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_rasterization_bucket_sort.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_rasterization_bucket_sort.js +96 -89
- package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.js +3 -1
- package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_two_way.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_two_way.js +4 -1
- package/src/shade/renderer/rasterize/expand/mesh/shader_mesh_expand_to_meshlets_prefix.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/mesh/shader_mesh_expand_to_meshlets_prefix.js +100 -89
- package/src/shade/renderer/rasterize/expand/mesh/shader_prefix_sum_to_command.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/mesh/shader_prefix_sum_to_command.js +31 -7
- 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 +1 -7
- package/src/shade/renderer/rasterize/expand/pass1/filter_meshlets.2-way.compute.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/pass1/filter_meshlets.2-way.compute.js +161 -153
- 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 +2 -7
- 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 +4 -8
- 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 +5 -8
- package/src/shade/renderer/shadow/map/DEFAULT_SHADOWMAP_UPDATE_BUDGET.d.ts +25 -0
- package/src/shade/renderer/shadow/map/DEFAULT_SHADOWMAP_UPDATE_BUDGET.d.ts.map +1 -0
- package/src/shade/renderer/shadow/map/DEFAULT_SHADOWMAP_UPDATE_BUDGET.js +24 -0
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts +10 -0
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +30 -21
- package/src/core/model/node-graph/visual/layout/LayoutBoxGraph.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/layout_assign_layers.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/layout_break_cycles.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/layout_orient_links.d.ts.map +0 -1
- package/src/shade/playground/vgeo_viewer/cut_geometry.d.ts +0 -61
- package/src/shade/playground/vgeo_viewer/cut_geometry.d.ts.map +0 -1
- package/src/shade/playground/vgeo_viewer/main.d.ts.map +0 -1
- package/src/shade/playground/vgeo_viewer/sample_asset.d.ts +0 -18
- package/src/shade/playground/vgeo_viewer/sample_asset.d.ts.map +0 -1
- package/src/shade/playground/vgeo_viewer/select_cut.d.ts +0 -173
- package/src/shade/playground/vgeo_viewer/select_cut.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/VGeoFaceGraph.d.ts +0 -52
- package/src/shade/renderer/geometry/virtual/build/VGeoFaceGraph.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/VGeoGatheredFaces.d.ts +0 -24
- package/src/shade/renderer/geometry/virtual/build/VGeoGatheredFaces.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/VGeoLevel.d.ts +0 -32
- package/src/shade/renderer/geometry/virtual/build/VGeoLevel.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/VGeoLevelOptions.d.ts +0 -59
- package/src/shade/renderer/geometry/virtual/build/VGeoLevelOptions.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/VGeoLevelSummary.d.ts +0 -44
- package/src/shade/renderer/geometry/virtual/build/VGeoLevelSummary.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/VGeoSubmesh.d.ts +0 -20
- package/src/shade/renderer/geometry/virtual/build/VGeoSubmesh.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/VirtualGeometryMesh.d.ts +0 -73
- package/src/shade/renderer/geometry/virtual/build/VirtualGeometryMesh.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts +0 -13
- package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_bounding_sphere.d.ts +0 -12
- package/src/shade/renderer/geometry/virtual/build/vgeo_bounding_sphere.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_build_levels.d.ts +0 -36
- package/src/shade/renderer/geometry/virtual/build/vgeo_build_levels.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_build_page_nodes.d.ts +0 -13
- package/src/shade/renderer/geometry/virtual/build/vgeo_build_page_nodes.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_build_root_group.d.ts +0 -19
- package/src/shade/renderer/geometry/virtual/build/vgeo_build_root_group.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_normals.d.ts +0 -29
- package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_normals.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_tangents.d.ts +0 -31
- package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_tangents.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_containing_sphere.d.ts +0 -18
- package/src/shade/renderer/geometry/virtual/build/vgeo_containing_sphere.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_extract_submesh.d.ts +0 -14
- package/src/shade/renderer/geometry/virtual/build/vgeo_extract_submesh.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_gather_faces.d.ts +0 -12
- package/src/shade/renderer/geometry/virtual/build/vgeo_gather_faces.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_graph_components.d.ts +0 -14
- package/src/shade/renderer/geometry/virtual/build/vgeo_graph_components.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_narrow_indices.d.ts +0 -11
- package/src/shade/renderer/geometry/virtual/build/vgeo_narrow_indices.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_normalize_source.d.ts +0 -46
- package/src/shade/renderer/geometry/virtual/build/vgeo_normalize_source.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts +0 -22
- package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_partition_graph.d.ts +0 -29
- package/src/shade/renderer/geometry/virtual/build/vgeo_partition_graph.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_sphere_inflate_to_contain.d.ts +0 -9
- package/src/shade/renderer/geometry/virtual/build/vgeo_sphere_inflate_to_contain.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set.d.ts +0 -10
- package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set_packed.d.ts +0 -15
- package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set_packed.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_vertex.d.ts +0 -16
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_vertex.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/fix_up_material_sides.d.ts +0 -10
- package/src/shade/renderer/loader/gltf/fix_up_material_sides.d.ts.map +0 -1
- package/src/shade/renderer/rasterize/expand/graph_triangles_filter_by_material_side.d.ts +0 -17
- package/src/shade/renderer/rasterize/expand/graph_triangles_filter_by_material_side.d.ts.map +0 -1
- package/src/shade/renderer/rasterize/expand/shader_filter_triangle_by_material_side.d.ts +0 -3
- package/src/shade/renderer/rasterize/expand/shader_filter_triangle_by_material_side.d.ts.map +0 -1
- package/src/shade/renderer/rasterize/forward/chunk_material_side_should_draw.d.ts +0 -8
- package/src/shade/renderer/rasterize/forward/chunk_material_side_should_draw.d.ts.map +0 -1
- /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_assign_coordinates.d.ts +0 -0
- /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_assign_layers.d.ts +0 -0
- /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_break_cycles.d.ts +0 -0
- /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_break_cycles.js +0 -0
- /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_insert_lanes.d.ts +0 -0
- /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_insert_lanes.js +0 -0
- /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_order_layers.d.ts +0 -0
- /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_order_layers.js +0 -0
- /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_orient_links.d.ts +0 -0
- /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_orient_links.js +0 -0
- /package/src/shade/playground/{vgeo_viewer → caldera}/main.d.ts +0 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import {
|
|
2
|
+
sphere_compute_bounding_of_2_spheres
|
|
3
|
+
} from "../../../../../../core/geom/3d/sphere/sphere_compute_bounding_of_2_spheres.js";
|
|
4
|
+
|
|
5
|
+
const scratch_sphere = new Float32Array(4);
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* How much of the space two clusters would waste by being merged, as a factor in `(0, 1]`.
|
|
9
|
+
*
|
|
10
|
+
* The ratio of what they occupy separately to what the sphere containing both would occupy. Two
|
|
11
|
+
* clusters side by side score near one; two clusters at opposite ends of the model score near zero,
|
|
12
|
+
* because the sphere over both is mostly empty. Scale-free by construction — it compares a volume
|
|
13
|
+
* to a volume, so it needs no notion of how big the model is or how far apart "far" is, which is
|
|
14
|
+
* exactly what a distance threshold would have needed and could never have been given.
|
|
15
|
+
*
|
|
16
|
+
* The group's sphere is what the runtime projects to decide the whole group's fate, so a group
|
|
17
|
+
* spread across empty space is one that gets refined from much further away than its geometry
|
|
18
|
+
* warrants. Cutting edge weight by this steers the partitioner away from those merges without ever
|
|
19
|
+
* forbidding one — when nothing better is available, a poor merge is still better than none.
|
|
20
|
+
*
|
|
21
|
+
* @param {Float32Array} a bounding sphere, centre then radius
|
|
22
|
+
* @param {Float32Array} b
|
|
23
|
+
* @returns {number}
|
|
24
|
+
*/
|
|
25
|
+
function compactness(a, b) {
|
|
26
|
+
sphere_compute_bounding_of_2_spheres(scratch_sphere, a, b);
|
|
27
|
+
|
|
28
|
+
const merged = scratch_sphere[3];
|
|
29
|
+
|
|
30
|
+
if (merged <= 0) {
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Volumes, up to the common factor of 4/3 pi, which cancels.
|
|
35
|
+
const separate = a[3] * a[3] * a[3] + b[3] * b[3] * b[3];
|
|
36
|
+
|
|
37
|
+
return Math.min(1, separate / (merged * merged * merged));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The cluster adjacency graph of a frontier: clusters are the vertices, shared mesh edges are the
|
|
42
|
+
* edges, and an edge weighs as much boundary as the two clusters share, discounted by how much empty
|
|
43
|
+
* space merging them would enclose.
|
|
44
|
+
*
|
|
45
|
+
* @param {VGeoFrontier} frontier
|
|
46
|
+
* @param {VGeoFaceGraph} face_graph of `frontier.mesh`
|
|
47
|
+
* @returns {{edge_addresses: Uint32Array, adjacency: Uint32Array, edge_weights: Float32Array}}
|
|
48
|
+
*
|
|
49
|
+
* @author Alex Goldring
|
|
50
|
+
* @copyright Company Named Limited (c) 2026
|
|
51
|
+
*/
|
|
52
|
+
export function vgeo_build_cluster_graph(frontier, face_graph) {
|
|
53
|
+
const cluster_of_face = new Int32Array(frontier.mesh.topology.faces.size).fill(-1);
|
|
54
|
+
|
|
55
|
+
frontier.cluster_faces.forEach((face_ids, cluster) => {
|
|
56
|
+
for (const face of face_ids) {
|
|
57
|
+
cluster_of_face[face] = cluster;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const cluster_count = frontier.clusters.length;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* `cluster -> (neighbour cluster -> shared boundary)`.
|
|
65
|
+
* @type {Map<number, number>[]}
|
|
66
|
+
*/
|
|
67
|
+
const neighbours = [];
|
|
68
|
+
|
|
69
|
+
for (let i = 0; i < cluster_count; i++) {
|
|
70
|
+
neighbours.push(new Map());
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const graph = face_graph.graph;
|
|
74
|
+
|
|
75
|
+
for (let vertex = 0; vertex < graph.vertex_count; vertex++) {
|
|
76
|
+
const cluster = cluster_of_face[face_graph.vertex_face_ids[vertex]];
|
|
77
|
+
|
|
78
|
+
for (let i = graph.edge_addresses[vertex]; i < graph.edge_addresses[vertex + 1]; i++) {
|
|
79
|
+
const other_cluster = cluster_of_face[face_graph.vertex_face_ids[graph.adjacency[i]]];
|
|
80
|
+
|
|
81
|
+
if (other_cluster === cluster) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const bucket = neighbours[cluster];
|
|
86
|
+
|
|
87
|
+
bucket.set(other_cluster, (bucket.get(other_cluster) ?? 0) + graph.edge_weights[i]);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const edge_addresses = new Uint32Array(cluster_count + 1);
|
|
92
|
+
const adjacency = [];
|
|
93
|
+
const edge_weights = [];
|
|
94
|
+
|
|
95
|
+
for (let cluster = 0; cluster < cluster_count; cluster++) {
|
|
96
|
+
edge_addresses[cluster] = adjacency.length;
|
|
97
|
+
|
|
98
|
+
const entries = Array.from(neighbours[cluster].entries()).sort((a, b) => a[0] - b[0]);
|
|
99
|
+
|
|
100
|
+
for (const [other, weight] of entries) {
|
|
101
|
+
adjacency.push(other);
|
|
102
|
+
|
|
103
|
+
edge_weights.push(weight * compactness(
|
|
104
|
+
frontier.clusters[cluster].bounds_sphere, frontier.clusters[other].bounds_sphere
|
|
105
|
+
));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
edge_addresses[cluster_count] = adjacency.length;
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
edge_addresses,
|
|
113
|
+
adjacency: Uint32Array.from(adjacency),
|
|
114
|
+
edge_weights: Float32Array.from(edge_weights),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simplify one group and cut the result into the parent clusters of every cluster in it.
|
|
3
|
+
*
|
|
4
|
+
* @param {VGeoFrontier} frontier
|
|
5
|
+
* @param {number[]} group_clusters cluster indices
|
|
6
|
+
* @param {Int32Array} group_of_face one entry per face slot, holding the group each face belongs to
|
|
7
|
+
* @param {number} group_index
|
|
8
|
+
* @param {number} level of the parents this step produces
|
|
9
|
+
* @param {VGeoLevelOptions} options
|
|
10
|
+
* @returns {VGeoGroupStep|undefined} `undefined` when the group has no coarser form at all, and the
|
|
11
|
+
* round should leave its clusters alone
|
|
12
|
+
*
|
|
13
|
+
* @author Alex Goldring
|
|
14
|
+
* @copyright Company Named Limited (c) 2026
|
|
15
|
+
*/
|
|
16
|
+
export function vgeo_build_group_step(frontier: VGeoFrontier, group_clusters: number[], group_of_face: Int32Array, group_index: number, level: number, options: VGeoLevelOptions): VGeoGroupStep | undefined;
|
|
17
|
+
import { VGeoGroupStep } from "./VGeoGroupStep.js";
|
|
18
|
+
//# sourceMappingURL=vgeo_build_group_step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vgeo_build_group_step.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.js"],"names":[],"mappings":"AAsEA;;;;;;;;;;;;;;GAcG;AACH,8EAXW,MAAM,EAAE,iBACR,UAAU,eACV,MAAM,SACN,MAAM,8BAEJ,aAAa,GAAC,SAAS,CAidnC;8BArgB6B,oBAAoB"}
|
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
import { assert } from "../../../../../../core/assert.js";
|
|
2
|
+
import { NULL_POINTER } from "../../../../../../core/geom/3d/topology/struct/binary/BinaryTopology.js";
|
|
3
|
+
import {
|
|
4
|
+
bt_mesh_simplify_with_quadrics
|
|
5
|
+
} from "../../../../../../core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.js";
|
|
6
|
+
import {
|
|
7
|
+
bt_wedges_live_count
|
|
8
|
+
} from "../../../../../../core/geom/3d/topology/struct/binary/io/bt_wedges_live_count.js";
|
|
9
|
+
import { bt_edge_get } from "../../../../../../core/geom/3d/topology/struct/binary/query/bt_edge_get.js";
|
|
10
|
+
import { bt_mesh_validate } from "../../../../../../core/geom/3d/topology/struct/binary/query/bt_mesh_validate.js";
|
|
11
|
+
import {
|
|
12
|
+
quadric_attribute_size
|
|
13
|
+
} from "../../../../../../core/geom/3d/quadric/quadric_attribute_size.js";
|
|
14
|
+
import { bt_mesh_build_face_graph } from "../../../../../../core/graph/metis/bt_mesh_build_face_graph.js";
|
|
15
|
+
import { VGEO_ATTRIBUTE } from "../../format/attribute/VGEO_ATTRIBUTE.js";
|
|
16
|
+
import { VGEO_MAX_CLUSTER_TRIANGLE_COUNT } from "../../format/cluster/VGEO_MAX_CLUSTER_TRIANGLE_COUNT.js";
|
|
17
|
+
import { VGEO_MAX_CLUSTER_VERTEX_COUNT } from "../../format/cluster/VGEO_MAX_CLUSTER_VERTEX_COUNT.js";
|
|
18
|
+
import { vgeo_attribute_vector_layout } from "../mesh/vgeo_attribute_vector_layout.js";
|
|
19
|
+
import { vgeo_attribute_vector_read } from "../mesh/vgeo_attribute_vector_read.js";
|
|
20
|
+
import { vgeo_attribute_vector_write } from "../mesh/vgeo_attribute_vector_write.js";
|
|
21
|
+
import { vgeo_compute_vertex_tangents } from "../mesh/vgeo_compute_vertex_tangents.js";
|
|
22
|
+
import { VGeoFaceGraph } from "../partition/VGeoFaceGraph.js";
|
|
23
|
+
import { vgeo_split_face_set_packed } from "../partition/vgeo_split_face_set_packed.js";
|
|
24
|
+
import { vgeo_containing_sphere } from "../sphere/vgeo_containing_sphere.js";
|
|
25
|
+
import { vgeo_extract_submesh } from "../submesh/vgeo_extract_submesh.js";
|
|
26
|
+
import { vgeo_build_cluster } from "./vgeo_build_cluster.js";
|
|
27
|
+
import { vgeo_compute_group_boundary } from "./vgeo_compute_group_boundary.js";
|
|
28
|
+
import { VGeoGroupStep } from "./VGeoGroupStep.js";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The defects a simplified group carries, as one line, or `''` when it carries none.
|
|
32
|
+
*
|
|
33
|
+
* Reached only from inside an `assert`, and that is the whole point of it being a function.
|
|
34
|
+
* {@link bt_mesh_validate} is a full reference, disk-cycle, radial-cycle and finite-value sweep of
|
|
35
|
+
* the submesh, and {@link reduce_to} would run it on every attempt: measured at 4.3% of a build of
|
|
36
|
+
* a 200k-face primitive. What it guards is real — a defect here is a crack that would be paged and
|
|
37
|
+
* drawn — but it guards against this file and the collapse below it being wrong, not against
|
|
38
|
+
* anything a source mesh can do, so it belongs where the other asserts are: on in development, and
|
|
39
|
+
* gone where they go.
|
|
40
|
+
*
|
|
41
|
+
* @param {BinaryTopology} topology
|
|
42
|
+
* @returns {string} at most the first four, joined
|
|
43
|
+
*/
|
|
44
|
+
function describe_defects(topology) {
|
|
45
|
+
return bt_mesh_validate(topology).slice(0, 4).map((defect) => defect.detail).join('; ');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A tangent derived from a normal is a pure function of it, so a vertex whose normal was restored
|
|
50
|
+
* unchanged gets its tangent back unchanged too — there is nothing for a pin to protect.
|
|
51
|
+
* @type {Set<number>}
|
|
52
|
+
*/
|
|
53
|
+
const NOTHING_PINNED = new Set();
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Largest error any of a group's clusters carries -- the floor a step above them must respect.
|
|
57
|
+
*
|
|
58
|
+
* @param {VirtualGeometryCluster[]} clusters
|
|
59
|
+
* @returns {number}
|
|
60
|
+
*/
|
|
61
|
+
function max_child_error(clusters) {
|
|
62
|
+
let result = 0;
|
|
63
|
+
|
|
64
|
+
for (const cluster of clusters) {
|
|
65
|
+
result = Math.max(result, cluster.self_error);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Simplify one group and cut the result into the parent clusters of every cluster in it.
|
|
73
|
+
*
|
|
74
|
+
* @param {VGeoFrontier} frontier
|
|
75
|
+
* @param {number[]} group_clusters cluster indices
|
|
76
|
+
* @param {Int32Array} group_of_face one entry per face slot, holding the group each face belongs to
|
|
77
|
+
* @param {number} group_index
|
|
78
|
+
* @param {number} level of the parents this step produces
|
|
79
|
+
* @param {VGeoLevelOptions} options
|
|
80
|
+
* @returns {VGeoGroupStep|undefined} `undefined` when the group has no coarser form at all, and the
|
|
81
|
+
* round should leave its clusters alone
|
|
82
|
+
*
|
|
83
|
+
* @author Alex Goldring
|
|
84
|
+
* @copyright Company Named Limited (c) 2026
|
|
85
|
+
*/
|
|
86
|
+
export function vgeo_build_group_step(
|
|
87
|
+
frontier, group_clusters, group_of_face, group_index, level, options
|
|
88
|
+
) {
|
|
89
|
+
// A group of one has nothing to merge, and the ceiling below — one fewer cluster than the group
|
|
90
|
+
// holds — would be zero. The grouping never produces one: a cluster it cannot place beside at
|
|
91
|
+
// least one other is returned to the frontier instead.
|
|
92
|
+
assert.greaterThan(group_clusters.length, 1, 'group_clusters.length');
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
*
|
|
96
|
+
* @type {number[]}
|
|
97
|
+
*/
|
|
98
|
+
const face_ids = [];
|
|
99
|
+
|
|
100
|
+
for (const cluster of group_clusters) {
|
|
101
|
+
for (const face of frontier.cluster_faces[cluster]) {
|
|
102
|
+
face_ids.push(face);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
face_ids.sort((a, b) => a - b);
|
|
107
|
+
|
|
108
|
+
const child_clusters = group_clusters.map((cluster) => frontier.clusters[cluster]);
|
|
109
|
+
|
|
110
|
+
const boundary = vgeo_compute_group_boundary(
|
|
111
|
+
frontier.mesh.topology, face_ids, group_of_face, group_index
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const submesh = vgeo_extract_submesh(frontier.mesh, face_ids, frontier.wedges);
|
|
115
|
+
|
|
116
|
+
const topology = submesh.mesh.topology;
|
|
117
|
+
|
|
118
|
+
// Cloned, not borrowed: the simplifier mutates these, and this whole attempt may be thrown away
|
|
119
|
+
// — by the polyline check below, by the round rejecting it, or by a wider band being tried
|
|
120
|
+
// instead. The frontier's own quadrics must survive all of that untouched.
|
|
121
|
+
const submesh_source_vertex_ids = submesh.source_vertex_ids;
|
|
122
|
+
const source_vertex_id_count = submesh_source_vertex_ids.length;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
*
|
|
126
|
+
* @type {Quadric3[]}
|
|
127
|
+
*/
|
|
128
|
+
const quadrics = new Array(source_vertex_id_count);
|
|
129
|
+
|
|
130
|
+
for (let i = 0; i < source_vertex_id_count; i++) {
|
|
131
|
+
const source = submesh_source_vertex_ids[i];
|
|
132
|
+
quadrics[i] = frontier.quadrics[source].clone();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/*
|
|
136
|
+
The shading channels, lifted out of the layers so the simplifier can carry them through every
|
|
137
|
+
collapse, and the fields it fits them from — cloned from the frontier's for the same reason the
|
|
138
|
+
geometric quadrics are, since this whole attempt may be thrown away.
|
|
139
|
+
|
|
140
|
+
Read once and carried across all of `reduce_to`'s attempts: a second pass is a continuation of
|
|
141
|
+
the first, not a fresh start.
|
|
142
|
+
*/
|
|
143
|
+
const attribute_layout = frontier.attribute_layout;
|
|
144
|
+
const attribute_components = attribute_layout.components;
|
|
145
|
+
|
|
146
|
+
let attributes = null;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* What travels but is never fitted -- the tangent's handedness. Read once and handed straight
|
|
150
|
+
* back: the simplifier is not given it, so a survivor's entry is still a survivor's.
|
|
151
|
+
* @type {Float64Array|null}
|
|
152
|
+
*/
|
|
153
|
+
let verbatim = null;
|
|
154
|
+
|
|
155
|
+
if (attribute_components > 0) {
|
|
156
|
+
const stride = quadric_attribute_size(attribute_components);
|
|
157
|
+
|
|
158
|
+
const wedge_count = submesh.wedges.count;
|
|
159
|
+
|
|
160
|
+
const quadrics_of_local = new Float64Array(wedge_count * stride);
|
|
161
|
+
|
|
162
|
+
for (let local = 0; local < wedge_count; local++) {
|
|
163
|
+
const source = submesh.source_wedge_ids[local];
|
|
164
|
+
|
|
165
|
+
quadrics_of_local.set(
|
|
166
|
+
frontier.attribute_quadrics.subarray(source * stride, source * stride + stride),
|
|
167
|
+
local * stride
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Empty wherever the tangent is derived rather than carried, which is every mesh without a
|
|
172
|
+
// `UV0` -- there is no flag to keep when the whole frame is a function of the normal.
|
|
173
|
+
verbatim = attribute_layout.verbatim_components === 0
|
|
174
|
+
? null
|
|
175
|
+
: vgeo_attribute_vector_read(
|
|
176
|
+
submesh.mesh, attribute_layout.verbatim_components, attribute_layout.verbatim,
|
|
177
|
+
submesh.wedges
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
attributes = {
|
|
181
|
+
values: vgeo_attribute_vector_read(
|
|
182
|
+
submesh.mesh, attribute_components, attribute_layout.channels, submesh.wedges
|
|
183
|
+
),
|
|
184
|
+
components: attribute_components,
|
|
185
|
+
quadrics: quadrics_of_local,
|
|
186
|
+
weights: frontier.attribute_weights,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* `source vertex id -> submesh local id`, for translating the lock set and the polyline.
|
|
192
|
+
* @type {Map<number, number>}
|
|
193
|
+
*/
|
|
194
|
+
const local_of_source = new Map();
|
|
195
|
+
|
|
196
|
+
for (let local = 0; local < source_vertex_id_count; local++) {
|
|
197
|
+
const source = submesh_source_vertex_ids[local];
|
|
198
|
+
local_of_source.set(source, local);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
*
|
|
203
|
+
* @type {Set<number>}
|
|
204
|
+
*/
|
|
205
|
+
const locked = new Set();
|
|
206
|
+
|
|
207
|
+
for (const vertex of boundary.locked) {
|
|
208
|
+
const local = local_of_source.get(vertex);
|
|
209
|
+
|
|
210
|
+
if (local !== undefined) {
|
|
211
|
+
locked.add(local);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// The faces carrying the group's boundary edges. Locking the endpoints keeps them where they
|
|
216
|
+
// are; protecting these faces is what keeps an edge *between* two locked vertices from losing
|
|
217
|
+
// the only face that holds it — see the polyline check below, which is the same guarantee
|
|
218
|
+
// stated as an assertion.
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
*
|
|
222
|
+
* @type {Set<number>}
|
|
223
|
+
*/
|
|
224
|
+
const protected_faces = new Set();
|
|
225
|
+
|
|
226
|
+
for (const [v1, v2] of boundary.polyline) {
|
|
227
|
+
const edge = bt_edge_get(topology, local_of_source.get(v1), local_of_source.get(v2));
|
|
228
|
+
|
|
229
|
+
if (edge === NULL_POINTER) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const first_loop = topology.edge_read_loop(edge);
|
|
234
|
+
|
|
235
|
+
let loop = first_loop;
|
|
236
|
+
|
|
237
|
+
do {
|
|
238
|
+
const face = topology.loop_read_face(loop);
|
|
239
|
+
|
|
240
|
+
if (face !== NULL_POINTER) {
|
|
241
|
+
protected_faces.add(face);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
loop = topology.loop_read_radial_next(loop);
|
|
245
|
+
} while (loop !== first_loop && loop !== NULL_POINTER);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Largest deviation any attempt measured, rather than the last one's.
|
|
250
|
+
*
|
|
251
|
+
* A vertex left behind by a patch that was consumed whole is faceless, and the simplifier reads
|
|
252
|
+
* it before it sweeps it away precisely because it is the only thing still carrying the quadric
|
|
253
|
+
* of what used to be there. It is gone by the next attempt, so the next attempt cannot see what
|
|
254
|
+
* it cost. The surface only ever moves further from the source as this loop tightens, so the
|
|
255
|
+
* running maximum is what the step actually did.
|
|
256
|
+
* @type {number}
|
|
257
|
+
*/
|
|
258
|
+
let deviation = 0;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Simplify *further*, down to `target_face_count`, and cut what is left into clusters.
|
|
262
|
+
*
|
|
263
|
+
* Further, not afresh: the submesh and its quadrics are carried across calls, which is what
|
|
264
|
+
* `bt_mesh_simplify_with_quadrics` is for. A second pass over the same geometry therefore
|
|
265
|
+
* accumulates onto the same quadrics and measures the same deviation from the source that one
|
|
266
|
+
* pass straight to the lower target would have — re-extracting instead would restart the
|
|
267
|
+
* collapse from the frontier and throw away everything the first attempt learned.
|
|
268
|
+
*
|
|
269
|
+
* @param {number} target_face_count
|
|
270
|
+
* @returns {{face_graph: VGeoFaceGraph, parts: number[][]}}
|
|
271
|
+
*/
|
|
272
|
+
function reduce_to(target_face_count) {
|
|
273
|
+
deviation = Math.max(deviation, bt_mesh_simplify_with_quadrics(
|
|
274
|
+
topology, target_face_count, locked, protected_faces, quadrics, attributes,
|
|
275
|
+
submesh.wedges
|
|
276
|
+
));
|
|
277
|
+
|
|
278
|
+
assert.equal(
|
|
279
|
+
describe_defects(topology), '',
|
|
280
|
+
`simplifying a group of ${group_clusters.length} clusters left the mesh inconsistent`
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
// The design asks for this explicitly: pinning a vertex does not by itself protect the
|
|
284
|
+
// *edges* between pinned vertices, and a face-kill path can strip one. A missing boundary
|
|
285
|
+
// edge is a crack between two groups that will never close, so the build stops here rather
|
|
286
|
+
// than shipping it.
|
|
287
|
+
for (const [v1, v2] of boundary.polyline) {
|
|
288
|
+
const local_1 = local_of_source.get(v1);
|
|
289
|
+
const local_2 = local_of_source.get(v2);
|
|
290
|
+
|
|
291
|
+
if (
|
|
292
|
+
local_1 === undefined
|
|
293
|
+
|| local_2 === undefined
|
|
294
|
+
|| bt_edge_get(topology, local_1, local_2) === NULL_POINTER
|
|
295
|
+
) {
|
|
296
|
+
throw new Error(
|
|
297
|
+
`group boundary edge (${v1}, ${v2}) did not survive simplification of a group of `
|
|
298
|
+
+ `${group_clusters.length} clusters`
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const face_graph = new VGeoFaceGraph(
|
|
304
|
+
topology, bt_mesh_build_face_graph(topology), submesh.wedges
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
const all = [];
|
|
308
|
+
|
|
309
|
+
for (let vertex = 0; vertex < face_graph.graph.vertex_count; vertex++) {
|
|
310
|
+
all.push(vertex);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Packed: this is a group, so its extent is already the group's, and one cluster per
|
|
314
|
+
// surviving island would undo the merge the group exists to make.
|
|
315
|
+
const parts = vgeo_split_face_set_packed(
|
|
316
|
+
face_graph, all, VGEO_MAX_CLUSTER_TRIANGLE_COUNT, VGEO_MAX_CLUSTER_VERTEX_COUNT
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
return { face_graph, parts };
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Aim at a number of *clusters*, not a fraction of the triangles. Halving the triangle count is
|
|
323
|
+
// a means; halving the cluster count is the end, and asking for it directly is what keeps
|
|
324
|
+
// parents full. Where the children are already full the two coincide exactly. Where they are
|
|
325
|
+
// not, this simplifies less — because the reduction is coming from packing the geometry better
|
|
326
|
+
// rather than from destroying it, which is the outcome to prefer.
|
|
327
|
+
const parent_target = Math.max(
|
|
328
|
+
1, Math.ceil(group_clusters.length * options.simplification_ratio)
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
const target = Math.min(
|
|
332
|
+
parent_target * VGEO_MAX_CLUSTER_TRIANGLE_COUNT,
|
|
333
|
+
// A group of under-filled clusters can already be under the cluster-count target, in which
|
|
334
|
+
// case nothing would be simplified and the step would record no error — a step the cut rule
|
|
335
|
+
// cannot take. Falling back to the triangle ratio keeps it a real simplification.
|
|
336
|
+
Math.max(2, Math.round(face_ids.length * options.simplification_ratio))
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
let outcome = reduce_to(target);
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Most clusters this step may come back with and still be worth taking.
|
|
343
|
+
*
|
|
344
|
+
* `parent_target` is what it aims at; this is what it has to clear. A step that hands the round
|
|
345
|
+
* as many clusters as the group gave it has merged nothing, and the round drops it — so the loop
|
|
346
|
+
* below chases the requirement rather than the aim, and a step that overshot the aim but cleared
|
|
347
|
+
* the requirement is left exactly as it is.
|
|
348
|
+
* @type {number}
|
|
349
|
+
*/
|
|
350
|
+
const ceiling = group_clusters.length - 1;
|
|
351
|
+
|
|
352
|
+
// A triangle target is a guess at a cluster count, and it is a guess that only accounts for one
|
|
353
|
+
// of the two numbers a cluster is bounded by. On geometry that has come apart — seams, small
|
|
354
|
+
// separate parts, patches the collapse has eaten the connective tissue out of — there are two or
|
|
355
|
+
// three vertices per triangle rather than a half, so the vertex ceiling is what binds, and
|
|
356
|
+
// halving the triangles does not halve the vertices. The result then needs as many clusters as
|
|
357
|
+
// the group started with, and the guess had no way of knowing.
|
|
358
|
+
//
|
|
359
|
+
// So the cluster count is measured and the target tightened until it holds. That is the same
|
|
360
|
+
// thing the guess was for, done where the answer is actually available: `parts` is the re-cut,
|
|
361
|
+
// and its length is the number this step exists to bring down.
|
|
362
|
+
//
|
|
363
|
+
// It is a loop, but it is not a search: over 25 of the Zorah primitives that could not be built
|
|
364
|
+
// at all, 70,665 of 70,752 steps cleared on the first attempt, 87 needed a second, and none took
|
|
365
|
+
// more than three extra. The step is the overshoot rather than the cluster ratio precisely so
|
|
366
|
+
// that it lands near, and what it costs where it does not is a pass over a group of at most a
|
|
367
|
+
// few hundred faces.
|
|
368
|
+
for (; ;) {
|
|
369
|
+
if (outcome.parts.length <= ceiling || outcome.parts.length === 0) {
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const faces = topology.faces.count();
|
|
374
|
+
|
|
375
|
+
// Wedges, not `vertices.count()`. A meshlet's vertex limit counts what it *carries*, and a
|
|
376
|
+
// vertex whose corners shade two ways is two of them — so asking the pool reads low at every
|
|
377
|
+
// crease and every chart boundary, and the step then aims at a target it has already missed.
|
|
378
|
+
const vertices = bt_wedges_live_count(topology, submesh.wedges);
|
|
379
|
+
|
|
380
|
+
// How far over the step is, on whichever of the two ceilings it actually broke.
|
|
381
|
+
const overshoot = Math.max(
|
|
382
|
+
faces / (ceiling * VGEO_MAX_CLUSTER_TRIANGLE_COUNT),
|
|
383
|
+
vertices / (ceiling * VGEO_MAX_CLUSTER_VERTEX_COUNT)
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
// Under both ceilings and still too many clusters: the geometry would fit, the packing did
|
|
387
|
+
// not. Nothing local says by how much, so aim at the share of it that would have.
|
|
388
|
+
const next = overshoot > 1
|
|
389
|
+
? Math.floor(faces / overshoot)
|
|
390
|
+
: Math.floor((faces * ceiling) / outcome.parts.length);
|
|
391
|
+
|
|
392
|
+
if (next >= faces) {
|
|
393
|
+
break;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
outcome = reduce_to(Math.max(1, next));
|
|
397
|
+
|
|
398
|
+
if (topology.faces.count() >= faces) {
|
|
399
|
+
// The simplifier has nothing left it is willing to collapse — every remaining edge is
|
|
400
|
+
// pinned, would fold, or has already been tried. Asking for less will not change that,
|
|
401
|
+
// and the round is the one that decides what to do with a group that cannot move.
|
|
402
|
+
break;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (outcome.parts.length === 0) {
|
|
407
|
+
// Some small closed shells have no coarser form under edge collapse at all — a tetrahedron
|
|
408
|
+
// loses two faces to the collapse and its other two to the fuse that follows, leaving
|
|
409
|
+
// nothing. Nothing to build a parent from, so the group is refused and its clusters go back
|
|
410
|
+
// to the frontier to be grouped differently.
|
|
411
|
+
return undefined;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/*
|
|
415
|
+
The frame the step's vertices carry, back into the layers the cluster encoder reads.
|
|
416
|
+
|
|
417
|
+
It was decided at the collapses, not here. Deriving it here — the area-weighted normal of the
|
|
418
|
+
mesh the simplifier just left — describes *that* mesh, which is a different surface from the one
|
|
419
|
+
the asset was authored as, and the difference is what a LOD transition pops by. Worse, it could
|
|
420
|
+
only ever be derived for the vertices the step was free to move: the group's perimeter is shared
|
|
421
|
+
with every neighbouring group and has to carry byte-identical values in all of them, so it would
|
|
422
|
+
have kept the frame it inherited while its own neighbours got a fresh one. Two rules over one
|
|
423
|
+
mesh, meeting along every triangle that straddles the perimeter — a third of the vertices at the
|
|
424
|
+
first level and half of them by the seventh, disagreeing by up to 175 degrees.
|
|
425
|
+
`ATTRIBUTE_PLAN_2026_09_18.md` §1.1 has the measurement.
|
|
426
|
+
|
|
427
|
+
Carried instead, both follow one rule, and the pin is back to meaning only what it is for.
|
|
428
|
+
*/
|
|
429
|
+
if (attributes !== null) {
|
|
430
|
+
vgeo_attribute_vector_write(
|
|
431
|
+
submesh.mesh, attribute_layout, attributes.values, verbatim, locked, submesh.wedges
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/*
|
|
436
|
+
With no `UV0` there is no parameterization for a tangent to be tangent to, and the frame is an
|
|
437
|
+
arbitrary well-conditioned basis around the normal — a *pure function* of it. So it is derived
|
|
438
|
+
rather than carried, which is both cheaper and safer: Frisvad's basis turns discontinuously with
|
|
439
|
+
the normal, and two neighbours' tangents can be nearly opposite and blend to nothing. A pure
|
|
440
|
+
function of a byte-identical normal is byte-identical, so the perimeter needs no exception
|
|
441
|
+
beyond the one `vgeo_compute_vertex_tangents` already makes. Where the mesh does carry `UV0`,
|
|
442
|
+
the tangent came through the vector above with the rest of the frame.
|
|
443
|
+
*/
|
|
444
|
+
if (submesh.mesh.layers[VGEO_ATTRIBUTE.UV0] === null) {
|
|
445
|
+
/*
|
|
446
|
+
Nothing pinned, and that is not a hole in the pin. Without a parameterization the frame is
|
|
447
|
+
`build_tangent_from_normal` of the normal and nothing else, the write above has just restored
|
|
448
|
+
every pinned vertex's normal to what it had, and a pure function of an unchanged input is an
|
|
449
|
+
unchanged output — bit for bit, which the byte-identity gate in `WEDGE_PLAN_2026_09_18.md`
|
|
450
|
+
§6.1 is what proves.
|
|
451
|
+
|
|
452
|
+
Passing `locked` instead would leave a pinned vertex's *donated* corners — the ones a
|
|
453
|
+
collapse re-pointed onto it — carrying the tangent they arrived with, which is the one thing
|
|
454
|
+
corner storage changed about what pinning has to cover.
|
|
455
|
+
*/
|
|
456
|
+
vgeo_compute_vertex_tangents(submesh.mesh, NOTHING_PINNED, submesh.wedges);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const submesh_face_graph = outcome.face_graph;
|
|
460
|
+
const parts = outcome.parts;
|
|
461
|
+
|
|
462
|
+
const step = new VGeoGroupStep();
|
|
463
|
+
|
|
464
|
+
step.child_clusters = child_clusters;
|
|
465
|
+
|
|
466
|
+
// Floored by what the children already carried. The accumulated quadric is a deviation from the
|
|
467
|
+
// source and nothing forces it to rise when the vertex carrying the previous maximum is the one
|
|
468
|
+
// collapsed away — but a parent that claimed to be closer to the source than its own child would
|
|
469
|
+
// make the cut oscillate, so monotonicity is imposed here rather than hoped for.
|
|
470
|
+
step.error = Math.max(deviation, max_child_error(child_clusters));
|
|
471
|
+
|
|
472
|
+
submesh.source_vertex_ids.forEach((source, local) => {
|
|
473
|
+
if (quadrics[local] !== null) {
|
|
474
|
+
step.quadrics.set(source, quadrics[local]);
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
if (attributes !== null) {
|
|
479
|
+
// Handed over whole, with the roots named separately. Liveness is no longer a question about
|
|
480
|
+
// the *vertex*: a collapse can leave a victim's wedge standing, adopted by the survivor and
|
|
481
|
+
// carrying corners of its own, so the vertex map would call a live wedge dead.
|
|
482
|
+
step.attribute_quadrics = attributes.quadrics;
|
|
483
|
+
step.attribute_source_wedge_ids = submesh.source_wedge_ids;
|
|
484
|
+
|
|
485
|
+
for (let wedge = 0; wedge < submesh.wedges.count; wedge++) {
|
|
486
|
+
if (submesh.wedges.find(wedge) === wedge) {
|
|
487
|
+
step.live_wedges.add(wedge);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
const parent_points = [];
|
|
493
|
+
|
|
494
|
+
for (const part of parts) {
|
|
495
|
+
const part_face_ids = part.map((dense) => submesh_face_graph.vertex_face_ids[dense]);
|
|
496
|
+
|
|
497
|
+
part_face_ids.sort((a, b) => a - b);
|
|
498
|
+
|
|
499
|
+
const built = vgeo_build_cluster(submesh.mesh, part_face_ids, level, submesh.wedges);
|
|
500
|
+
|
|
501
|
+
step.parent_clusters.push(built.cluster);
|
|
502
|
+
|
|
503
|
+
step.parent_geometry.push({
|
|
504
|
+
positions: built.gathered.positions,
|
|
505
|
+
indices: built.gathered.indices,
|
|
506
|
+
local_vertex_ids: built.gathered.vertex_ids,
|
|
507
|
+
source_vertex_ids: Uint32Array.from(
|
|
508
|
+
built.gathered.vertex_ids, (local) => submesh.source_vertex_ids[local]
|
|
509
|
+
),
|
|
510
|
+
attribute_ids: built.gathered.attribute_ids,
|
|
511
|
+
source_wedge_ids: Uint32Array.from(
|
|
512
|
+
built.gathered.wedge_ids, (wedge) => submesh.source_wedge_ids[wedge]
|
|
513
|
+
),
|
|
514
|
+
topology: submesh.mesh.topology,
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
parent_points.push(built.gathered.positions);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
let point_count = 0;
|
|
521
|
+
|
|
522
|
+
for (const points of parent_points) {
|
|
523
|
+
point_count += points.length;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const points = new Float32Array(point_count);
|
|
527
|
+
|
|
528
|
+
let cursor = 0;
|
|
529
|
+
|
|
530
|
+
for (const part of parent_points) {
|
|
531
|
+
points.set(part, cursor);
|
|
532
|
+
|
|
533
|
+
cursor += part.length;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// One sphere for the whole step, containing both what it consumed and what it produced. Sharing
|
|
537
|
+
// it is what makes every sibling project the same value, and containing the children is what
|
|
538
|
+
// makes the pair monotonic.
|
|
539
|
+
step.sphere = vgeo_containing_sphere(
|
|
540
|
+
step.child_clusters.map((cluster) => cluster.self_sphere),
|
|
541
|
+
points
|
|
542
|
+
);
|
|
543
|
+
|
|
544
|
+
return step;
|
|
545
|
+
}
|