@woosh/meep-engine 3.28.0 → 3.30.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.
Files changed (685) hide show
  1. package/build/bundle-worker-image-decoder.js +1 -1
  2. package/build/bundle-worker-terrain.js +1 -1
  3. package/package.json +1 -1
  4. package/src/core/binary/BinaryBuffer.d.ts.map +1 -1
  5. package/src/core/binary/BinaryBuffer.js +14 -2
  6. package/src/core/binary/BitSet.d.ts +16 -0
  7. package/src/core/binary/BitSet.d.ts.map +1 -1
  8. package/src/core/binary/BitSet.js +159 -49
  9. package/src/core/binary/allocator/OffsetAllocator.d.ts +48 -0
  10. package/src/core/binary/allocator/OffsetAllocator.d.ts.map +1 -1
  11. package/src/core/binary/allocator/OffsetAllocator.js +208 -9
  12. package/src/core/binary/compression/compress_bytes.d.ts +20 -0
  13. package/src/core/binary/compression/compress_bytes.d.ts.map +1 -0
  14. package/src/core/binary/compression/compress_bytes.js +35 -0
  15. package/src/core/binary/compression/decompress_bytes_into.d.ts +30 -0
  16. package/src/core/binary/compression/decompress_bytes_into.d.ts.map +1 -0
  17. package/src/core/binary/compression/decompress_bytes_into.js +87 -0
  18. package/src/core/binary/compression/deflate_decompress_bound.d.ts +27 -0
  19. package/src/core/binary/compression/deflate_decompress_bound.d.ts.map +1 -0
  20. package/src/core/binary/compression/deflate_decompress_bound.js +32 -0
  21. package/src/core/bvh2/bvh3/BVH.d.ts.map +1 -1
  22. package/src/core/bvh2/bvh3/BVH.js +14 -1
  23. package/src/core/cache/FrequencySketch.d.ts +3 -1
  24. package/src/core/cache/FrequencySketch.d.ts.map +1 -1
  25. package/src/core/cache/FrequencySketch.js +10 -4
  26. package/src/core/cache/wtinylfu/CacheWTinylfu.d.ts.map +1 -1
  27. package/src/core/cache/wtinylfu/CacheWTinylfu.js +24 -2
  28. package/src/core/geom/3d/quadric/quadric_attribute_add.d.ts +24 -0
  29. package/src/core/geom/3d/quadric/quadric_attribute_add.d.ts.map +1 -0
  30. package/src/core/geom/3d/quadric/quadric_attribute_add.js +31 -0
  31. package/src/core/geom/3d/quadric/quadric_attribute_reduce.d.ts +46 -0
  32. package/src/core/geom/3d/quadric/quadric_attribute_reduce.d.ts.map +1 -0
  33. package/src/core/geom/3d/quadric/quadric_attribute_reduce.js +104 -0
  34. package/src/core/geom/3d/quadric/quadric_attribute_set_from_triangle.d.ts +62 -0
  35. package/src/core/geom/3d/quadric/quadric_attribute_set_from_triangle.d.ts.map +1 -0
  36. package/src/core/geom/3d/quadric/quadric_attribute_set_from_triangle.js +158 -0
  37. package/src/core/geom/3d/quadric/quadric_attribute_size.d.ts +21 -0
  38. package/src/core/geom/3d/quadric/quadric_attribute_size.d.ts.map +1 -0
  39. package/src/core/geom/3d/quadric/quadric_attribute_size.js +24 -0
  40. package/src/core/geom/3d/quadric/quadric_attribute_solve.d.ts +34 -0
  41. package/src/core/geom/3d/quadric/quadric_attribute_solve.d.ts.map +1 -0
  42. package/src/core/geom/3d/quadric/quadric_attribute_solve.js +55 -0
  43. package/src/core/geom/3d/quadric/quadric_attribute_sub.d.ts +28 -0
  44. package/src/core/geom/3d/quadric/quadric_attribute_sub.d.ts.map +1 -0
  45. package/src/core/geom/3d/quadric/quadric_attribute_sub.js +35 -0
  46. package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.d.ts +15 -0
  47. package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.d.ts.map +1 -1
  48. package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.js +35 -0
  49. package/src/core/geom/3d/topology/struct/binary/BtWedgeSet.d.ts +93 -0
  50. package/src/core/geom/3d/topology/struct/binary/BtWedgeSet.d.ts.map +1 -0
  51. package/src/core/geom/3d/topology/struct/binary/BtWedgeSet.js +128 -0
  52. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.d.ts +20 -0
  53. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.d.ts.map +1 -1
  54. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.js +69 -4
  55. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_wedge_attribute_quadrics.d.ts +38 -0
  56. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_wedge_attribute_quadrics.d.ts.map +1 -0
  57. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_wedge_attribute_quadrics.js +113 -0
  58. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.d.ts +93 -17
  59. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.d.ts.map +1 -1
  60. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.js +930 -69
  61. package/src/core/geom/3d/topology/struct/binary/io/bt_wedges_live_count.d.ts +22 -0
  62. package/src/core/geom/3d/topology/struct/binary/io/bt_wedges_live_count.d.ts.map +1 -0
  63. package/src/core/geom/3d/topology/struct/binary/io/bt_wedges_live_count.js +46 -0
  64. package/src/core/geom/3d/topology/struct/binary/io/bt_wedges_per_vertex.d.ts +19 -0
  65. package/src/core/geom/3d/topology/struct/binary/io/bt_wedges_per_vertex.d.ts.map +1 -0
  66. package/src/core/geom/3d/topology/struct/binary/io/bt_wedges_per_vertex.js +49 -0
  67. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_collapse_fold_limit.d.ts +25 -0
  68. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_collapse_fold_limit.d.ts.map +1 -0
  69. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_collapse_fold_limit.js +228 -0
  70. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_collapse_would_fold.d.ts +13 -0
  71. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_collapse_would_fold.d.ts.map +1 -1
  72. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_collapse_would_fold.js +10 -128
  73. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_build_face_bvh.d.ts.map +1 -1
  74. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_build_face_bvh.js +11 -1
  75. package/src/core/graph/layout/layered/BoxLayoutOptions.d.ts +63 -0
  76. package/src/core/graph/layout/layered/BoxLayoutOptions.d.ts.map +1 -0
  77. package/src/core/graph/layout/layered/BoxLayoutOptions.js +80 -0
  78. package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/LayoutBoxGraph.d.ts +35 -0
  79. package/src/core/graph/layout/layered/LayoutBoxGraph.d.ts.map +1 -0
  80. package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/LayoutBoxGraph.js +53 -1
  81. package/src/core/graph/layout/layered/layout_assign_coordinates.d.ts.map +1 -0
  82. package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_assign_coordinates.js +72 -68
  83. package/src/core/graph/layout/layered/layout_assign_layers.d.ts.map +1 -0
  84. package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_assign_layers.js +4 -2
  85. package/src/core/graph/layout/layered/layout_break_cycles.d.ts.map +1 -0
  86. package/src/core/graph/layout/layered/layout_insert_lanes.d.ts.map +1 -0
  87. package/src/core/graph/layout/layered/layout_order_layers.d.ts.map +1 -0
  88. package/src/core/graph/layout/layered/layout_orient_links.d.ts.map +1 -0
  89. package/src/core/graph/mn_graph_collapse_weighted_edge.js +6 -6
  90. package/src/core/math/lookup/ParameterLookupTable.d.ts.map +1 -1
  91. package/src/core/math/lookup/ParameterLookupTable.js +10 -5
  92. package/src/core/math/noise/sdnoise.d.ts.map +1 -1
  93. package/src/core/math/noise/sdnoise.js +16 -10
  94. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts +7 -51
  95. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts.map +1 -1
  96. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.js +8 -69
  97. package/src/core/model/node-graph/visual/layout/layout_build_problem.js +1 -1
  98. package/src/core/model/node-graph/visual/layout/layout_node_graph.js +6 -6
  99. package/src/core/model/node-graph/visual/layout/route_grid_build.js +1 -1
  100. package/src/core/model/object/ImmutableObjectPool.d.ts.map +1 -1
  101. package/src/core/model/object/ImmutableObjectPool.js +17 -7
  102. package/src/core/process/executor/ConcurrentExecutor.d.ts +1 -5
  103. package/src/core/process/executor/ConcurrentExecutor.d.ts.map +1 -1
  104. package/src/core/process/executor/ConcurrentExecutor.js +95 -1
  105. package/src/core/process/task/task_find_dependency_cycle.d.ts +17 -0
  106. package/src/core/process/task/task_find_dependency_cycle.d.ts.map +1 -0
  107. package/src/core/process/task/task_find_dependency_cycle.js +81 -0
  108. package/src/core/wfc/WFCCellChoice.d.ts +17 -0
  109. package/src/core/wfc/WFCCellChoice.d.ts.map +1 -0
  110. package/src/core/wfc/WFCCellChoice.js +36 -0
  111. package/src/core/wfc/WFCLattice.d.ts +105 -0
  112. package/src/core/wfc/WFCLattice.d.ts.map +1 -0
  113. package/src/core/wfc/WFCLattice.js +235 -0
  114. package/src/core/wfc/WFCRuleTable.d.ts +172 -0
  115. package/src/core/wfc/WFCRuleTable.d.ts.map +1 -0
  116. package/src/core/wfc/WFCRuleTable.js +334 -0
  117. package/src/core/wfc/WFCState.d.ts +273 -0
  118. package/src/core/wfc/WFCState.d.ts.map +1 -0
  119. package/src/core/wfc/WFCState.js +552 -0
  120. package/src/core/wfc/WFCStatus.d.ts +11 -0
  121. package/src/core/wfc/WFCStatus.d.ts.map +1 -0
  122. package/src/core/wfc/WFCStatus.js +28 -0
  123. package/src/core/wfc/WFCTileWeights.d.ts +48 -0
  124. package/src/core/wfc/WFCTileWeights.d.ts.map +1 -0
  125. package/src/core/wfc/WFCTileWeights.js +86 -0
  126. package/src/core/wfc/WFC_UNRESOLVED.d.ts +12 -0
  127. package/src/core/wfc/WFC_UNRESOLVED.d.ts.map +1 -0
  128. package/src/core/wfc/WFC_UNRESOLVED.js +11 -0
  129. package/src/core/wfc/wfc_estimate_bytes.d.ts +24 -0
  130. package/src/core/wfc/wfc_estimate_bytes.d.ts.map +1 -0
  131. package/src/core/wfc/wfc_estimate_bytes.js +47 -0
  132. package/src/core/wfc/wfc_rule_table_tile_components.d.ts +27 -0
  133. package/src/core/wfc/wfc_rule_table_tile_components.d.ts.map +1 -0
  134. package/src/core/wfc/wfc_rule_table_tile_components.js +80 -0
  135. package/src/core/wfc/wfc_solve.d.ts +21 -0
  136. package/src/core/wfc/wfc_solve.d.ts.map +1 -0
  137. package/src/core/wfc/wfc_solve.js +154 -0
  138. package/src/core/wfc/wfc_state_apply_boundary.d.ts +18 -0
  139. package/src/core/wfc/wfc_state_apply_boundary.d.ts.map +1 -0
  140. package/src/core/wfc/wfc_state_apply_boundary.js +61 -0
  141. package/src/core/wfc/wfc_state_assign.d.ts +11 -0
  142. package/src/core/wfc/wfc_state_assign.d.ts.map +1 -0
  143. package/src/core/wfc/wfc_state_assign.js +36 -0
  144. package/src/core/wfc/wfc_state_ban_bits.d.ts +17 -0
  145. package/src/core/wfc/wfc_state_ban_bits.d.ts.map +1 -0
  146. package/src/core/wfc/wfc_state_ban_bits.js +81 -0
  147. package/src/core/wfc/wfc_state_collapse.d.ts +12 -0
  148. package/src/core/wfc/wfc_state_collapse.d.ts.map +1 -0
  149. package/src/core/wfc/wfc_state_collapse.js +73 -0
  150. package/src/core/wfc/wfc_state_flush_dirty.d.ts +12 -0
  151. package/src/core/wfc/wfc_state_flush_dirty.d.ts.map +1 -0
  152. package/src/core/wfc/wfc_state_flush_dirty.js +39 -0
  153. package/src/core/wfc/wfc_state_propagate.d.ts +14 -0
  154. package/src/core/wfc/wfc_state_propagate.d.ts.map +1 -0
  155. package/src/core/wfc/wfc_state_propagate.js +155 -0
  156. package/src/core/wfc/wfc_state_read.d.ts +11 -0
  157. package/src/core/wfc/wfc_state_read.d.ts.map +1 -0
  158. package/src/core/wfc/wfc_state_read.js +38 -0
  159. package/src/core/wfc/wfc_state_restrict.d.ts +18 -0
  160. package/src/core/wfc/wfc_state_restrict.d.ts.map +1 -0
  161. package/src/core/wfc/wfc_state_restrict.js +39 -0
  162. package/src/core/wfc/wfc_state_set_eligible.d.ts +24 -0
  163. package/src/core/wfc/wfc_state_set_eligible.d.ts.map +1 -0
  164. package/src/core/wfc/wfc_state_set_eligible.js +49 -0
  165. package/src/core/wfc/wfc_state_undo_to.d.ts +13 -0
  166. package/src/core/wfc/wfc_state_undo_to.d.ts.map +1 -0
  167. package/src/core/wfc/wfc_state_undo_to.js +84 -0
  168. package/src/core/wfc/wfc_words_per_cell.d.ts +11 -0
  169. package/src/core/wfc/wfc_words_per_cell.d.ts.map +1 -0
  170. package/src/core/wfc/wfc_words_per_cell.js +16 -0
  171. package/src/engine/ecs/EntityComponentDataset.d.ts +8 -0
  172. package/src/engine/ecs/EntityComponentDataset.d.ts.map +1 -1
  173. package/src/engine/ecs/EntityComponentDataset.js +37 -14
  174. package/src/engine/ecs/fow/FogOfWarRevealerSystem.d.ts +8 -1
  175. package/src/engine/ecs/fow/FogOfWarRevealerSystem.d.ts.map +1 -1
  176. package/src/engine/ecs/fow/FogOfWarRevealerSystem.js +37 -2
  177. package/src/engine/ecs/guid/UUID.d.ts.map +1 -1
  178. package/src/engine/ecs/guid/UUID.js +45 -17
  179. package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.d.ts.map +1 -1
  180. package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +3 -1
  181. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.d.ts.map +1 -1
  182. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +366 -360
  183. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_linear.d.ts.map +1 -1
  184. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_linear.js +24 -10
  185. package/src/engine/graphics3/DebugDrawSystem.d.ts +7 -5
  186. package/src/engine/graphics3/DebugDrawSystem.d.ts.map +1 -1
  187. package/src/engine/graphics3/DebugDrawSystem.js +206 -203
  188. package/src/engine/graphics3/DecalSystem.d.ts +4 -5
  189. package/src/engine/graphics3/DecalSystem.d.ts.map +1 -1
  190. package/src/engine/graphics3/DecalSystem.js +5 -5
  191. package/src/engine/graphics3/FogOfWarSystem.d.ts +7 -12
  192. package/src/engine/graphics3/FogOfWarSystem.d.ts.map +1 -1
  193. package/src/engine/graphics3/FogOfWarSystem.js +8 -12
  194. package/src/engine/graphics3/prefab/prefab_instantiate.js +230 -230
  195. package/src/engine/grid/grid2transform/GridPosition2TransformSystem.d.ts.map +1 -1
  196. package/src/engine/grid/grid2transform/GridPosition2TransformSystem.js +24 -5
  197. package/src/engine/interpolation/Interpoland.d.ts +7 -1
  198. package/src/engine/interpolation/Interpoland.d.ts.map +1 -1
  199. package/src/engine/interpolation/Interpoland.js +8 -1
  200. package/src/engine/interpolation/InterpolationSystem.d.ts.map +1 -1
  201. package/src/engine/interpolation/InterpolationSystem.js +3 -0
  202. package/src/engine/interpolation/TransformPoseSerializationAdapter.d.ts +5 -3
  203. package/src/engine/interpolation/TransformPoseSerializationAdapter.d.ts.map +1 -1
  204. package/src/engine/interpolation/TransformPoseSerializationAdapter.js +14 -3
  205. package/src/engine/interpolation/pose_interpoland.d.ts.map +1 -1
  206. package/src/engine/interpolation/pose_interpoland.js +2 -0
  207. package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
  208. package/src/engine/network/orchestrator/NetworkPeer.js +15 -10
  209. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
  210. package/src/engine/physics/cloth/ecs/ClothWorld.js +17 -0
  211. package/src/engine/physics/mls-mpm/MLS_MPM.d.ts.map +1 -1
  212. package/src/engine/physics/mls-mpm/MLS_MPM.js +14 -0
  213. package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.d.ts +2 -1
  214. package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.d.ts.map +1 -1
  215. package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.js +1 -1
  216. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.d.ts +1 -0
  217. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.d.ts.map +1 -1
  218. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.d.ts +1 -0
  219. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.d.ts.map +1 -1
  220. package/src/engine/sound/sopra/definition/clip/SampleAudioClip.d.ts +2 -1
  221. package/src/engine/sound/sopra/definition/clip/SampleAudioClip.d.ts.map +1 -1
  222. package/src/engine/sound/sopra/definition/clip/SampleAudioClip.js +12 -3
  223. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.d.ts +1 -0
  224. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.d.ts.map +1 -1
  225. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts +1 -0
  226. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts.map +1 -1
  227. package/src/engine/sound/sopra/runtime/EventInstance.d.ts.map +1 -1
  228. package/src/engine/sound/sopra/runtime/EventInstance.js +4 -1
  229. package/src/format/image/avif/av1/decode/decode_coefficients.d.ts.map +1 -1
  230. package/src/format/image/avif/av1/decode/decode_coefficients.js +248 -259
  231. package/src/format/image/avif/av1/decode/read_golomb.d.ts +21 -0
  232. package/src/format/image/avif/av1/decode/read_golomb.d.ts.map +1 -0
  233. package/src/format/image/avif/av1/decode/read_golomb.js +49 -0
  234. package/src/format/image/avif/av1/filter/loop_restoration.js +461 -451
  235. package/src/format/image/avif/av1/util/round2.d.ts +19 -2
  236. package/src/format/image/avif/av1/util/round2.d.ts.map +1 -1
  237. package/src/format/image/avif/av1/util/round2.js +51 -27
  238. package/src/format/image/avif/heif/parse_avif_file.js +24 -0
  239. package/src/shade/RENDERER_CONTRACT.md +12 -7
  240. package/src/shade/playground/caldera/README.md +529 -0
  241. package/src/shade/playground/caldera/caldera_format.d.ts +151 -0
  242. package/src/shade/playground/caldera/caldera_format.d.ts.map +1 -0
  243. package/src/shade/playground/caldera/caldera_format.js +241 -0
  244. package/src/shade/playground/caldera/index.html +126 -0
  245. package/src/shade/playground/caldera/main.d.ts.map +1 -0
  246. package/src/shade/playground/caldera/main.js +1565 -0
  247. package/src/shade/playground/mesh_row_ceiling/README.md +85 -0
  248. package/src/shade/playground/mesh_row_ceiling/index.html +31 -0
  249. package/src/shade/playground/mesh_row_ceiling/main.d.ts +2 -0
  250. package/src/shade/playground/mesh_row_ceiling/main.d.ts.map +1 -0
  251. package/src/shade/playground/mesh_row_ceiling/main.js +389 -0
  252. package/src/shade/playground/vgeo_runtime/README.md +5 -3
  253. package/src/shade/playground/vgeo_runtime/main.js +3 -2
  254. package/src/shade/playground/vgeo_runtime/sample_asset.d.ts +3 -3
  255. package/src/shade/playground/vgeo_runtime/sample_asset.d.ts.map +1 -1
  256. package/src/shade/playground/vgeo_runtime/sample_asset.js +3 -3
  257. package/src/shade/playground/vgeo_scene/README.md +103 -24
  258. package/src/shade/playground/vgeo_scene/main.js +525 -24
  259. package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
  260. package/src/shade/renderer/GraphicsContext.js +6 -0
  261. package/src/shade/renderer/Renderer.d.ts +2 -0
  262. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  263. package/src/shade/renderer/Renderer.js +23 -0
  264. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  265. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +100 -8
  266. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts.map +1 -1
  267. package/src/shade/renderer/buffer/table/GPUTypedTable.js +14 -0
  268. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +69 -33
  269. package/src/shade/renderer/extension/RenderExtension.d.ts +15 -18
  270. package/src/shade/renderer/extension/RenderExtension.d.ts.map +1 -1
  271. package/src/shade/renderer/extension/RenderExtension.js +15 -19
  272. package/src/shade/renderer/extension/RenderExtensionRegistry.d.ts +5 -5
  273. package/src/shade/renderer/extension/RenderExtensionRegistry.d.ts.map +1 -1
  274. package/src/shade/renderer/extension/RenderExtensionRegistry.js +29 -166
  275. package/src/shade/renderer/geometry/GPUGeometryManager.d.ts.map +1 -1
  276. package/src/shade/renderer/geometry/GPUGeometryManager.js +73 -16
  277. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
  278. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +18 -3
  279. package/src/shade/renderer/geometry/meshlet/COMPACTION_PLAN_2026_09_16.md +663 -0
  280. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts +100 -5
  281. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  282. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +688 -81
  283. package/src/shade/renderer/geometry/virtual/ATTRIBUTE_PLAN_2026_09_18.md +540 -0
  284. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +155 -64
  285. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +76 -16
  286. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +3 -3
  287. package/src/shade/renderer/geometry/virtual/WEDGE_PLAN_2026_09_18.md +448 -0
  288. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +44 -7
  289. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
  290. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +48 -9
  291. package/src/shade/renderer/geometry/virtual/build/level/VGeoContribution.d.ts +40 -0
  292. package/src/shade/renderer/geometry/virtual/build/level/VGeoContribution.d.ts.map +1 -0
  293. package/src/shade/renderer/geometry/virtual/build/level/VGeoContribution.js +24 -0
  294. package/src/shade/renderer/geometry/virtual/build/level/VGeoFrontier.d.ts +91 -0
  295. package/src/shade/renderer/geometry/virtual/build/level/VGeoFrontier.d.ts.map +1 -0
  296. package/src/shade/renderer/geometry/virtual/build/level/VGeoFrontier.js +91 -0
  297. package/src/shade/renderer/geometry/virtual/build/level/VGeoGroupRepack.d.ts +24 -0
  298. package/src/shade/renderer/geometry/virtual/build/level/VGeoGroupRepack.d.ts.map +1 -0
  299. package/src/shade/renderer/geometry/virtual/build/level/VGeoGroupRepack.js +25 -0
  300. package/src/shade/renderer/geometry/virtual/build/level/VGeoGroupStep.d.ts +77 -0
  301. package/src/shade/renderer/geometry/virtual/build/level/VGeoGroupStep.d.ts.map +1 -0
  302. package/src/shade/renderer/geometry/virtual/build/level/VGeoGroupStep.js +84 -0
  303. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelOptions.d.ts +19 -6
  304. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelOptions.d.ts.map +1 -1
  305. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelOptions.js +20 -7
  306. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_cluster.d.ts +19 -0
  307. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_cluster.d.ts.map +1 -0
  308. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_cluster.js +58 -0
  309. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_cluster_graph.d.ts +18 -0
  310. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_cluster_graph.d.ts.map +1 -0
  311. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_cluster_graph.js +116 -0
  312. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.d.ts +18 -0
  313. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.d.ts.map +1 -0
  314. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.js +545 -0
  315. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.d.ts +16 -0
  316. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.d.ts.map +1 -0
  317. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.js +110 -0
  318. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_levels.d.ts +2 -27
  319. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_levels.d.ts.map +1 -1
  320. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_levels.js +120 -1564
  321. package/src/shade/renderer/geometry/virtual/build/level/vgeo_compute_group_boundary.d.ts +26 -0
  322. package/src/shade/renderer/geometry/virtual/build/level/vgeo_compute_group_boundary.d.ts.map +1 -0
  323. package/src/shade/renderer/geometry/virtual/build/level/vgeo_compute_group_boundary.js +123 -0
  324. package/src/shade/renderer/geometry/virtual/build/level/vgeo_error_bands.d.ts +26 -0
  325. package/src/shade/renderer/geometry/virtual/build/level/vgeo_error_bands.d.ts.map +1 -0
  326. package/src/shade/renderer/geometry/virtual/build/level/vgeo_error_bands.js +78 -0
  327. package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.d.ts +24 -0
  328. package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.d.ts.map +1 -0
  329. package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.js +337 -0
  330. package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.d.ts +29 -0
  331. package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.d.ts.map +1 -0
  332. package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.js +147 -0
  333. package/src/shade/renderer/geometry/virtual/build/level/vgeo_stitch_frontier.d.ts +37 -0
  334. package/src/shade/renderer/geometry/virtual/build/level/vgeo_stitch_frontier.d.ts.map +1 -0
  335. package/src/shade/renderer/geometry/virtual/build/level/vgeo_stitch_frontier.js +243 -0
  336. package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.d.ts +29 -0
  337. package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.d.ts.map +1 -0
  338. package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.js +117 -0
  339. package/src/shade/renderer/geometry/virtual/build/mesh/VGEO_CREASE_ANGLE.d.ts +46 -0
  340. package/src/shade/renderer/geometry/virtual/build/mesh/VGEO_CREASE_ANGLE.d.ts.map +1 -0
  341. package/src/shade/renderer/geometry/virtual/build/mesh/VGEO_DEFAULT_ATTRIBUTE_WEIGHT_RATIOS.d.ts +74 -0
  342. package/src/shade/renderer/geometry/virtual/build/mesh/VGEO_DEFAULT_ATTRIBUTE_WEIGHT_RATIOS.d.ts.map +1 -0
  343. package/src/shade/renderer/geometry/virtual/build/mesh/VGEO_DEFAULT_ATTRIBUTE_WEIGHT_RATIOS.js +78 -0
  344. package/src/shade/renderer/geometry/virtual/build/mesh/VirtualGeometryMesh.d.ts +12 -7
  345. package/src/shade/renderer/geometry/virtual/build/mesh/VirtualGeometryMesh.d.ts.map +1 -1
  346. package/src/shade/renderer/geometry/virtual/build/mesh/VirtualGeometryMesh.js +33 -11
  347. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_layout.d.ts +58 -0
  348. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_layout.d.ts.map +1 -0
  349. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_layout.js +79 -0
  350. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_read.d.ts +39 -0
  351. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_read.d.ts.map +1 -0
  352. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_read.js +68 -0
  353. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_write.d.ts +53 -0
  354. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_write.d.ts.map +1 -0
  355. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_attribute_vector_write.js +243 -0
  356. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_normals.d.ts +32 -7
  357. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_normals.d.ts.map +1 -1
  358. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_normals.js +243 -24
  359. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_tangents.d.ts +12 -8
  360. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_tangents.d.ts.map +1 -1
  361. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_tangents.js +58 -50
  362. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_normalize_source.d.ts +5 -0
  363. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_normalize_source.d.ts.map +1 -1
  364. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_normalize_source.js +13 -1
  365. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_resolve_attribute_weights.d.ts +38 -0
  366. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_resolve_attribute_weights.d.ts.map +1 -0
  367. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_resolve_attribute_weights.js +81 -0
  368. package/src/shade/renderer/geometry/virtual/build/partition/VGeoFaceGraph.d.ts +23 -5
  369. package/src/shade/renderer/geometry/virtual/build/partition/VGeoFaceGraph.d.ts.map +1 -1
  370. package/src/shade/renderer/geometry/virtual/build/partition/VGeoFaceGraph.js +28 -21
  371. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set.js +1 -1
  372. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.d.ts.map +1 -1
  373. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.js +224 -60
  374. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.d.ts +15 -0
  375. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.d.ts.map +1 -1
  376. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.js +17 -0
  377. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.d.ts +17 -0
  378. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.d.ts.map +1 -1
  379. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.js +19 -0
  380. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.d.ts +10 -1
  381. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.d.ts.map +1 -1
  382. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.js +103 -9
  383. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.d.ts +14 -2
  384. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.d.ts.map +1 -1
  385. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.js +38 -14
  386. package/src/shade/renderer/geometry/virtual/build/vgeo_build.d.ts +6 -2
  387. package/src/shade/renderer/geometry/virtual/build/vgeo_build.d.ts.map +1 -1
  388. package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +27 -4
  389. package/src/shade/renderer/geometry/virtual/build/vgeo_subtree_bounds.d.ts +32 -0
  390. package/src/shade/renderer/geometry/virtual/build/vgeo_subtree_bounds.d.ts.map +1 -0
  391. package/src/shade/renderer/geometry/virtual/build/vgeo_subtree_bounds.js +93 -0
  392. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +20 -6
  393. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
  394. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +22 -8
  395. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_corner.d.ts +16 -0
  396. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_corner.d.ts.map +1 -0
  397. package/src/shade/renderer/geometry/virtual/format/attribute/{vgeo_layers_copy_vertex.js → vgeo_layers_copy_corner.js} +8 -8
  398. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.d.ts +18 -7
  399. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.d.ts.map +1 -1
  400. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.js +19 -8
  401. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_like.d.ts +3 -3
  402. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_like.js +3 -3
  403. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_mesh_wedges.d.ts +27 -0
  404. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_mesh_wedges.d.ts.map +1 -0
  405. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_mesh_wedges.js +97 -0
  406. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.d.ts +7 -3
  407. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.d.ts.map +1 -1
  408. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.js +21 -11
  409. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET_V4.d.ts +21 -0
  410. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET_V4.d.ts.map +1 -0
  411. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET_V4.js +41 -0
  412. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts +19 -1
  413. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts.map +1 -1
  414. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +20 -1
  415. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_DEFLATE.d.ts +25 -0
  416. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_DEFLATE.d.ts.map +1 -0
  417. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_DEFLATE.js +24 -0
  418. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.d.ts +5 -0
  419. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.d.ts.map +1 -1
  420. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.js +5 -0
  421. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_codec_name.d.ts.map +1 -1
  422. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_codec_name.js +5 -0
  423. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.d.ts +10 -3
  424. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.d.ts.map +1 -1
  425. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.js +37 -3
  426. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.d.ts +21 -13
  427. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.d.ts.map +1 -1
  428. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +37 -13
  429. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.d.ts +8 -2
  430. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.d.ts.map +1 -1
  431. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.js +14 -2
  432. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.d.ts +18 -0
  433. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.d.ts.map +1 -1
  434. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +19 -1
  435. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_OFFSET.js +6 -0
  436. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAX_LEVEL_COUNT.d.ts +21 -0
  437. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAX_LEVEL_COUNT.d.ts.map +1 -0
  438. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAX_LEVEL_COUNT.js +20 -0
  439. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.d.ts +9 -0
  440. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.d.ts.map +1 -1
  441. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.js +10 -1
  442. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.d.ts +1 -2
  443. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +10 -3
  444. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET_V5.d.ts +20 -0
  445. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET_V5.d.ts.map +1 -0
  446. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET_V5.js +43 -0
  447. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.d.ts +4 -2
  448. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.d.ts.map +1 -1
  449. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.js +8 -4
  450. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts.map +1 -1
  451. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.js +2 -2
  452. package/src/shade/renderer/geometry/virtual/format/read/VGeoDirectory.d.ts +6 -4
  453. package/src/shade/renderer/geometry/virtual/format/read/VGeoDirectory.d.ts.map +1 -1
  454. package/src/shade/renderer/geometry/virtual/format/read/VGeoDirectory.js +6 -4
  455. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +13 -2
  456. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
  457. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +13 -2
  458. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts +5 -1
  459. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts.map +1 -1
  460. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.js +14 -1
  461. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.d.ts.map +1 -1
  462. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.js +1 -0
  463. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_directory.d.ts +4 -1
  464. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_directory.d.ts.map +1 -1
  465. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_directory.js +53 -11
  466. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.d.ts.map +1 -1
  467. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.js +7 -3
  468. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts +12 -2
  469. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
  470. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +111 -33
  471. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts +6 -2
  472. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
  473. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +112 -42
  474. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts +2 -2
  475. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
  476. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +51 -21
  477. package/src/shade/renderer/geometry/virtual/runtime/CULL_PLAN_2026_09_16.md +385 -0
  478. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts.map +1 -1
  479. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.js +9 -0
  480. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts.map +1 -1
  481. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.js +14 -1
  482. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -1
  483. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +34 -0
  484. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.d.ts.map +1 -1
  485. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.js +18 -0
  486. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -1
  487. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +47 -19
  488. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts +1 -0
  489. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.js +22 -4
  490. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts +7 -2
  491. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts.map +1 -1
  492. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.js +8 -3
  493. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts +1 -0
  494. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js +10 -0
  495. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +1 -1
  496. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts +13 -11
  497. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts.map +1 -1
  498. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.js +13 -11
  499. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts.map +1 -1
  500. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.js +4 -0
  501. package/src/shade/renderer/global_illumination/probe/octahedral/GPUProbeAtlas.d.ts.map +1 -1
  502. package/src/shade/renderer/global_illumination/probe/octahedral/GPUProbeAtlas.js +12 -3
  503. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.d.ts.map +1 -1
  504. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.js +3 -4
  505. package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.d.ts +6 -2
  506. package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.d.ts.map +1 -1
  507. package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.js +90 -12
  508. package/src/shade/renderer/gpu_primitive/indirect/WEBGPU_GUARANTEED_MAX_COMPUTE_WORKGROUPS_PER_DIMENSION.d.ts +22 -0
  509. package/src/shade/renderer/gpu_primitive/indirect/WEBGPU_GUARANTEED_MAX_COMPUTE_WORKGROUPS_PER_DIMENSION.d.ts.map +1 -0
  510. package/src/shade/renderer/gpu_primitive/indirect/WEBGPU_GUARANTEED_MAX_COMPUTE_WORKGROUPS_PER_DIMENSION.js +21 -0
  511. package/src/shade/renderer/light/environment/rgbe/RGBE_ReadPixels_RLE.d.ts.map +1 -1
  512. package/src/shade/renderer/light/environment/rgbe/RGBE_ReadPixels_RLE.js +7 -1
  513. package/src/shade/renderer/lightmap/GPULightMap.d.ts.map +1 -1
  514. package/src/shade/renderer/lightmap/GPULightMap.js +349 -336
  515. package/src/shade/renderer/loader/gltf/load_gltf.d.ts.map +1 -1
  516. package/src/shade/renderer/loader/gltf/load_gltf.js +1137 -1128
  517. package/src/shade/renderer/particles/DESIGN.md +14 -5
  518. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +25 -10
  519. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  520. package/src/shade/renderer/particles/GPUParticleSystem.js +182 -38
  521. package/src/shade/renderer/particles/graph/groups/simplex_reference.d.ts.map +1 -1
  522. package/src/shade/renderer/particles/graph/groups/simplex_reference.js +16 -10
  523. package/src/shade/renderer/particles/graph_particles.d.ts +4 -2
  524. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  525. package/src/shade/renderer/particles/graph_particles.js +8 -2
  526. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts.map +1 -1
  527. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.js +8 -2
  528. package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts.map +1 -1
  529. package/src/shade/renderer/particles/optimizer/pass_fold_constants.js +10 -4
  530. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  531. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +13 -8
  532. package/src/shade/renderer/particles/shaders/shader_particle_init_free_list.d.ts +31 -0
  533. package/src/shade/renderer/particles/shaders/shader_particle_init_free_list.d.ts.map +1 -0
  534. package/src/shade/renderer/particles/shaders/shader_particle_init_free_list.js +62 -0
  535. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  536. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +3 -6
  537. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts +13 -0
  538. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
  539. package/src/shade/renderer/particles/vm/ParticleVMReference.js +95 -17
  540. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  541. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +4 -12
  542. package/src/shade/renderer/rasterize/bucket/rasterization_has_opaque_bucket.d.ts +21 -0
  543. package/src/shade/renderer/rasterize/bucket/rasterization_has_opaque_bucket.d.ts.map +1 -0
  544. package/src/shade/renderer/rasterize/bucket/rasterization_has_opaque_bucket.js +28 -0
  545. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts +0 -2
  546. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts.map +1 -1
  547. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.js +4 -5
  548. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.d.ts.map +1 -1
  549. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.js +5 -3
  550. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way.d.ts.map +1 -1
  551. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way.js +11 -4
  552. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.d.ts.map +1 -1
  553. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.js +4 -3
  554. package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.d.ts.map +1 -1
  555. package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.js +3 -0
  556. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_count_by_rasterization_bucket.d.ts.map +1 -1
  557. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_count_by_rasterization_bucket.js +94 -90
  558. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.d.ts.map +1 -1
  559. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.js +13 -5
  560. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_rasterization_bucket_sort.d.ts.map +1 -1
  561. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_rasterization_bucket_sort.js +96 -89
  562. package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.d.ts.map +1 -1
  563. package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.js +3 -1
  564. package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_two_way.d.ts.map +1 -1
  565. package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_two_way.js +4 -1
  566. package/src/shade/renderer/rasterize/expand/mesh/shader_mesh_expand_to_meshlets_prefix.d.ts.map +1 -1
  567. package/src/shade/renderer/rasterize/expand/mesh/shader_mesh_expand_to_meshlets_prefix.js +100 -89
  568. package/src/shade/renderer/rasterize/expand/mesh/shader_prefix_sum_to_command.d.ts.map +1 -1
  569. package/src/shade/renderer/rasterize/expand/mesh/shader_prefix_sum_to_command.js +31 -7
  570. package/src/shade/renderer/rasterize/expand/pass0/pass_mesh_cull.d.ts.map +1 -1
  571. package/src/shade/renderer/rasterize/expand/pass0/pass_mesh_cull.js +1 -7
  572. package/src/shade/renderer/rasterize/expand/pass1/filter_meshlets.2-way.compute.d.ts.map +1 -1
  573. package/src/shade/renderer/rasterize/expand/pass1/filter_meshlets.2-way.compute.js +161 -153
  574. package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.d.ts.map +1 -1
  575. package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.js +2 -7
  576. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts.map +1 -1
  577. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +19 -2
  578. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  579. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +4 -8
  580. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  581. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +5 -8
  582. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts.map +1 -1
  583. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +19 -2
  584. package/src/shade/renderer/shader/type/WebGPUStruct.d.ts.map +1 -1
  585. package/src/shade/renderer/shader/type/WebGPUStruct.js +12 -0
  586. package/src/shade/renderer/shadow/map/DEFAULT_SHADOWMAP_UPDATE_BUDGET.d.ts +25 -0
  587. package/src/shade/renderer/shadow/map/DEFAULT_SHADOWMAP_UPDATE_BUDGET.d.ts.map +1 -0
  588. package/src/shade/renderer/shadow/map/DEFAULT_SHADOWMAP_UPDATE_BUDGET.js +24 -0
  589. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts +10 -0
  590. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  591. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +30 -21
  592. package/src/shade/renderer/texture/mipmaps/WebGPUMipmapGenerator.d.ts +8 -2
  593. package/src/shade/renderer/texture/mipmaps/WebGPUMipmapGenerator.d.ts.map +1 -1
  594. package/src/shade/renderer/texture/mipmaps/WebGPUMipmapGenerator.js +41 -6
  595. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +2383 -2356
  596. package/src/view/tooltip/DomTooltipManager.d.ts +7 -0
  597. package/src/view/tooltip/DomTooltipManager.d.ts.map +1 -1
  598. package/src/view/tooltip/DomTooltipManager.js +22 -0
  599. package/src/view/tooltip/DomTooltipObserver.d.ts.map +1 -1
  600. package/src/view/tooltip/DomTooltipObserver.js +13 -3
  601. package/src/core/model/node-graph/visual/layout/LayoutBoxGraph.d.ts.map +0 -1
  602. package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.d.ts.map +0 -1
  603. package/src/core/model/node-graph/visual/layout/layout_assign_layers.d.ts.map +0 -1
  604. package/src/core/model/node-graph/visual/layout/layout_break_cycles.d.ts.map +0 -1
  605. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts.map +0 -1
  606. package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts.map +0 -1
  607. package/src/core/model/node-graph/visual/layout/layout_orient_links.d.ts.map +0 -1
  608. package/src/shade/playground/vgeo_viewer/cut_geometry.d.ts +0 -61
  609. package/src/shade/playground/vgeo_viewer/cut_geometry.d.ts.map +0 -1
  610. package/src/shade/playground/vgeo_viewer/main.d.ts.map +0 -1
  611. package/src/shade/playground/vgeo_viewer/sample_asset.d.ts +0 -18
  612. package/src/shade/playground/vgeo_viewer/sample_asset.d.ts.map +0 -1
  613. package/src/shade/playground/vgeo_viewer/select_cut.d.ts +0 -173
  614. package/src/shade/playground/vgeo_viewer/select_cut.d.ts.map +0 -1
  615. package/src/shade/renderer/geometry/virtual/build/VGeoFaceGraph.d.ts +0 -52
  616. package/src/shade/renderer/geometry/virtual/build/VGeoFaceGraph.d.ts.map +0 -1
  617. package/src/shade/renderer/geometry/virtual/build/VGeoGatheredFaces.d.ts +0 -24
  618. package/src/shade/renderer/geometry/virtual/build/VGeoGatheredFaces.d.ts.map +0 -1
  619. package/src/shade/renderer/geometry/virtual/build/VGeoLevel.d.ts +0 -32
  620. package/src/shade/renderer/geometry/virtual/build/VGeoLevel.d.ts.map +0 -1
  621. package/src/shade/renderer/geometry/virtual/build/VGeoLevelOptions.d.ts +0 -59
  622. package/src/shade/renderer/geometry/virtual/build/VGeoLevelOptions.d.ts.map +0 -1
  623. package/src/shade/renderer/geometry/virtual/build/VGeoLevelSummary.d.ts +0 -44
  624. package/src/shade/renderer/geometry/virtual/build/VGeoLevelSummary.d.ts.map +0 -1
  625. package/src/shade/renderer/geometry/virtual/build/VGeoSubmesh.d.ts +0 -20
  626. package/src/shade/renderer/geometry/virtual/build/VGeoSubmesh.d.ts.map +0 -1
  627. package/src/shade/renderer/geometry/virtual/build/VirtualGeometryMesh.d.ts +0 -73
  628. package/src/shade/renderer/geometry/virtual/build/VirtualGeometryMesh.d.ts.map +0 -1
  629. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts +0 -13
  630. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +0 -1
  631. package/src/shade/renderer/geometry/virtual/build/vgeo_bounding_sphere.d.ts +0 -12
  632. package/src/shade/renderer/geometry/virtual/build/vgeo_bounding_sphere.d.ts.map +0 -1
  633. package/src/shade/renderer/geometry/virtual/build/vgeo_build_levels.d.ts +0 -36
  634. package/src/shade/renderer/geometry/virtual/build/vgeo_build_levels.d.ts.map +0 -1
  635. package/src/shade/renderer/geometry/virtual/build/vgeo_build_page_nodes.d.ts +0 -13
  636. package/src/shade/renderer/geometry/virtual/build/vgeo_build_page_nodes.d.ts.map +0 -1
  637. package/src/shade/renderer/geometry/virtual/build/vgeo_build_root_group.d.ts +0 -19
  638. package/src/shade/renderer/geometry/virtual/build/vgeo_build_root_group.d.ts.map +0 -1
  639. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_normals.d.ts +0 -29
  640. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_normals.d.ts.map +0 -1
  641. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_tangents.d.ts +0 -31
  642. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_tangents.d.ts.map +0 -1
  643. package/src/shade/renderer/geometry/virtual/build/vgeo_containing_sphere.d.ts +0 -18
  644. package/src/shade/renderer/geometry/virtual/build/vgeo_containing_sphere.d.ts.map +0 -1
  645. package/src/shade/renderer/geometry/virtual/build/vgeo_extract_submesh.d.ts +0 -14
  646. package/src/shade/renderer/geometry/virtual/build/vgeo_extract_submesh.d.ts.map +0 -1
  647. package/src/shade/renderer/geometry/virtual/build/vgeo_gather_faces.d.ts +0 -12
  648. package/src/shade/renderer/geometry/virtual/build/vgeo_gather_faces.d.ts.map +0 -1
  649. package/src/shade/renderer/geometry/virtual/build/vgeo_graph_components.d.ts +0 -14
  650. package/src/shade/renderer/geometry/virtual/build/vgeo_graph_components.d.ts.map +0 -1
  651. package/src/shade/renderer/geometry/virtual/build/vgeo_narrow_indices.d.ts +0 -11
  652. package/src/shade/renderer/geometry/virtual/build/vgeo_narrow_indices.d.ts.map +0 -1
  653. package/src/shade/renderer/geometry/virtual/build/vgeo_normalize_source.d.ts +0 -46
  654. package/src/shade/renderer/geometry/virtual/build/vgeo_normalize_source.d.ts.map +0 -1
  655. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts +0 -22
  656. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts.map +0 -1
  657. package/src/shade/renderer/geometry/virtual/build/vgeo_partition_graph.d.ts +0 -29
  658. package/src/shade/renderer/geometry/virtual/build/vgeo_partition_graph.d.ts.map +0 -1
  659. package/src/shade/renderer/geometry/virtual/build/vgeo_sphere_inflate_to_contain.d.ts +0 -9
  660. package/src/shade/renderer/geometry/virtual/build/vgeo_sphere_inflate_to_contain.d.ts.map +0 -1
  661. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set.d.ts +0 -10
  662. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set.d.ts.map +0 -1
  663. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set_packed.d.ts +0 -15
  664. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set_packed.d.ts.map +0 -1
  665. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_vertex.d.ts +0 -16
  666. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_vertex.d.ts.map +0 -1
  667. package/src/shade/renderer/loader/gltf/fix_up_material_sides.d.ts +0 -10
  668. package/src/shade/renderer/loader/gltf/fix_up_material_sides.d.ts.map +0 -1
  669. package/src/shade/renderer/rasterize/expand/graph_triangles_filter_by_material_side.d.ts +0 -17
  670. package/src/shade/renderer/rasterize/expand/graph_triangles_filter_by_material_side.d.ts.map +0 -1
  671. package/src/shade/renderer/rasterize/expand/shader_filter_triangle_by_material_side.d.ts +0 -3
  672. package/src/shade/renderer/rasterize/expand/shader_filter_triangle_by_material_side.d.ts.map +0 -1
  673. package/src/shade/renderer/rasterize/forward/chunk_material_side_should_draw.d.ts +0 -8
  674. package/src/shade/renderer/rasterize/forward/chunk_material_side_should_draw.d.ts.map +0 -1
  675. /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_assign_coordinates.d.ts +0 -0
  676. /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_assign_layers.d.ts +0 -0
  677. /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_break_cycles.d.ts +0 -0
  678. /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_break_cycles.js +0 -0
  679. /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_insert_lanes.d.ts +0 -0
  680. /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_insert_lanes.js +0 -0
  681. /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_order_layers.d.ts +0 -0
  682. /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_order_layers.js +0 -0
  683. /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_orient_links.d.ts +0 -0
  684. /package/src/core/{model/node-graph/visual/layout → graph/layout/layered}/layout_orient_links.js +0 -0
  685. /package/src/shade/playground/{vgeo_viewer → caldera}/main.d.ts +0 -0
@@ -0,0 +1,385 @@
1
+ # Virtual Geometry cut — the per-cluster frustum test, measured and tightened
2
+
3
+ **2026-09-16.** Follows `RUNTIME_PLAN_2026_09_14.md` §2.1 and §7, which left `pages visited` at half
4
+ to three quarters of the resident tier when zoomed in and named the LOD sphere's looseness as the
5
+ cause. This document measures that claim before acting on it, and the measurement changes what is
6
+ worth building. Everything measured here was measured on the real asset in node
7
+ (`measure_spheres*.mjs`, `measure3_breakdown.mjs`, `measure4_extents.mjs`, `measure5_reach.mjs`,
8
+ `measure6_error_bound.mjs`, `measure7_containment.mjs`, `measure8_lod_vertices.mjs` of the
9
+ building session).
10
+
11
+ ## 0. What the symptom is made of
12
+
13
+ The container is the Zorah rosette panel, mesh 2023 primitive 0, as rebuilt on 2026-09-14
14
+ (`5d4baf9e9ab4a0ea2bb6b3bcf48829f2.vgeo`, `format_version` 4, 942 MB): 17,213 pages, 590,858
15
+ clusters, 160,441 groups, 34.3 clusters a page. Its DAG is 42 levels deep counted as the longest
16
+ chain from a cluster down to a leaf, with 277,659 leaves. The tour of §7 saw, zoomed in at rest,
17
+ 3,220 pages visited of 4,096 resident against 4,060 clusters drawn.
18
+
19
+ A CPU cut over the whole container — every page resident, camera on the panel's normal at the
20
+ tour's poses, 50° fov, 1258×646, τ = 1 — reproduces that: 3,091 pages visited at rest with the
21
+ cluster test on the LOD sphere, 4,537 with no frustum test at all. Where those pages are is the
22
+ finding. At rest, of the 3,091:
23
+
24
+ | | pages | of which drew a cluster | transit only |
25
+ |---|---:|---:|---:|
26
+ | levels 0–3 (the surface on screen and one step above) | 1,326 | 661 | 665 |
27
+ | levels 4–19 | 1,665 | 7 | 1,658 |
28
+ | levels 20–41 | 100 | 0 | 100 |
29
+
30
+ A page is placed at the lowest level of any cluster it holds; 8,166 pages hold more than one level.
31
+ Levels 4 and up hold 1,836 pages of the file. **1,765 of them are entered at rest with the LOD
32
+ sphere and 1,650 with the exact subtree box** (levels 4–9: 415/466, 319/333, 247/251, 165/167,
33
+ 121/121, 80/80 visited with the sphere; 353, 293, 229, 160, 120, 78 with the box). Seven of them draw
34
+ anything. They are the way down.
35
+
36
+ ## 1. Why the coarse pages cannot be culled, by any bound
37
+
38
+ The cluster test decides whether a cluster refines into its child group. Culling it has to be
39
+ conservative for **everything reachable below it**, because the child group is reached through it
40
+ and a parent culled with an on-screen descendant is a hole. What is reachable below a cluster is
41
+ not "the geometry this cluster approximates". Every simplification step consumes one group and
42
+ produces two or more parents; every parent's `child_group` is the **whole** consumed group, so a
43
+ parent's subtree carries its sibling's half of the surface too, and each child's subtree carries
44
+ *its* sibling's, and so on down. The region below a cluster doubles per level. Measured, as the
45
+ median diagonal of the exact subtree AABB against the object's diagonal, with the cluster's own AABB
46
+ beside it:
47
+
48
+ | level | clusters | own AABB diagonal | subtree AABB diagonal |
49
+ |---:|---:|---:|---:|
50
+ | 0 | 277,659 | 0.3% | 0.3% |
51
+ | 4 | 18,783 | 0.7% | 1.1% |
52
+ | 7 | 5,405 | 1.1% | 9.2% |
53
+ | 10 | 2,919 | 1.2% | 23% |
54
+ | 14 | 1,531 | 1.6% | 43% |
55
+ | 20 | 948 | 1.9% | 64% |
56
+ | 28 | 574 | 3.5% | 97% |
57
+
58
+ A zoomed view covers one to two percent of the panel. From level 7 up the median cluster's subtree
59
+ is bigger than the view, and from level 12 up it is a third of the object. No sphere and no box
60
+ around that region is outside any zoomed frustum, and the coarse pages get visited because they
61
+ hold clusters like that. The LOD sphere's looseness is real — below — but it is not what fills the
62
+ tier.
63
+
64
+ **The DAG's shape makes it worse than it need be.** Below level 4 each level halves the cluster
65
+ count; above it the ratio decays to 0.6, 0.8 and by level 10 about 0.9 a level, so 58,000 clusters
66
+ and 1,800 pages sit in a long thin tail above the surface anyone draws. That tail is the transit set.
67
+ Pages also mix levels — 8,166 of 17,213 span more than one — so a coarse page's groups are
68
+ spatially wherever the assembler found room.
69
+
70
+ ## 2. What was measured, against the four questions asked
71
+
72
+ ### 2.1 Where a subtree sphere could come from, and how tight it gets
73
+
74
+ Install-derived is out by construction, not by measurement: `self_sphere` **is** a subtree bound.
75
+ The builder's step sphere contains the consumed clusters' own step spheres and the produced
76
+ clusters' vertices, so by induction it contains every vertex under it; a sample of 1,160 clusters
77
+ across levels 0–28 found no subtree vertex outside its `self_sphere` (worst excess −3·10⁻⁹ of the
78
+ radius, a leaf touching its own miniball). Nothing else a page carries is tighter for the subtree:
79
+ node spheres and child-table metrics are unions of these same spheres.
80
+
81
+ So the question is how much tighter a builder-computed bound is. Volume of the candidate over the
82
+ volume of the LOD sphere, medians per level:
83
+
84
+ | level | exact subtree AABB, as a box | its circumsphere | miniball over children's subtree boxes | miniball over every subtree AABB corner | miniball over every subtree vertex |
85
+ |---:|---:|---:|---:|---:|---:|
86
+ | 0 | — | 1.39 | 1.39 | 1.47 | 1.00 |
87
+ | 2 | — | 0.82 | 0.79 | 0.70 | 0.49 |
88
+ | 4 | — | 0.51 | 0.49 | 0.52 | 0.30 |
89
+ | 8 | — | 0.31 | 0.30 | 0.28 | 0.22 |
90
+ | 12 | — | 0.22 | 0.22 | 0.15 | 0.17 |
91
+ | 16 | — | 0.18 | 0.18 | 0.15 | 0.14 |
92
+ | 20 | — | 0.12 | 0.12 | 0.10 | — |
93
+
94
+ The last two columns are medians over samples of 300 and 40 clusters a level drawn with different
95
+ seeds, which is why the vertex miniball can read larger than the corner miniball at one level; the
96
+ first three are exhaustive. The LOD sphere compounds: 1.5× the exact volume at level 1, 3–5× from
97
+ level 4, 7× at level 20. A tight sphere is 0.55–0.6 of its radius at the levels that matter. The composable
98
+ children's-boxes miniball is within 5–15% of the exhaustive reference at every level and is O(N)
99
+ to build; the exact vertex miniball is the tightest and costs O(N·depth) points through a miniball,
100
+ which on this container is ten billion points.
101
+
102
+ ### 2.2 What the tighter bound buys the cut
103
+
104
+ Pages visited by the CPU cut, full residency, the tour's poses. `none` has the frustum test off
105
+ entirely; `lod` is today's kernel; the exact AABB is tested as a box (p-vertex against each plane):
106
+
107
+ | pose | none | LOD sphere | subtree-box circumsphere | children's-boxes miniball | exact subtree AABB |
108
+ |---|---:|---:|---:|---:|---:|
109
+ | rest (0.12 r) | 4,537 | 3,091 | 2,924 | 2,916 | **2,521** |
110
+ | stop 0 | 4,583 | 3,051 | 2,856 | 2,847 | 2,478 |
111
+ | stop 3 | 4,204 | 2,495 | 2,185 | 2,179 | **1,639** |
112
+ | stop 4 | 4,261 | 2,599 | 2,190 | 2,183 | **1,649** |
113
+ | stop 5 | 3,609 | 1,748 | 1,312 | 1,306 | **1,052** |
114
+ | stop 7 | 4,000 | 2,245 | 1,890 | 1,887 | 1,452 |
115
+ | framing (2.8 r) | 1,441 | 1,441 | 1,441 | 1,441 | 1,441 |
116
+
117
+ A tight **sphere** takes 5–6% off at rest and up to 25% at a stop. The exact **box** takes 18% off at
118
+ rest and 35–40% at stops 3, 4 and 5, and draws fewer clusters too (2,115 against 2,734 at rest: those
119
+ were on-screen by the sphere and off-screen in fact). The CPU cut's camera is not the tour's — its
120
+ orientation is the panel's normal and the tour's is the orbit controller's, and it drew 2,734 where the
121
+ tour drew 4,060 — so the tables compare candidates against each other, and §5's tour is what compares
122
+ before with after. The box wins because a subtree here is a flat
123
+ patch of a flat panel — its AABB is thin along the normal and its circumsphere is not.
124
+
125
+ ### 2.3 The one test that would have hit the target, and why it is not sound
126
+
127
+ A cluster's **own** bounds inflated by the error accumulated down its chain — `reach(P) =
128
+ P.self_error + max over the child group of reach(c)`, leaves 0 — is the Nanite-shaped argument: an
129
+ on-screen point of the fine surface is within the step's error of some parent's surface, so some
130
+ chain of parents each passing that test exists. It visits 1,444 pages at rest and 358–1,300 at the
131
+ stops, the two-to-fourfold cut the task hoped for. And it leaves **14 to 37 in-frustum clusters of
132
+ the open cut undrawn at every pose**, some with their box six diagonals inside the frustum — holes
133
+ in the middle of the screen, not slivers at its edge. Scaling the reach by 6 still leaves 10–20.
134
+
135
+ The reason is measurable and is a finding on its own: **the stored error is not a distance bound.**
136
+ Per step, the farthest any consumed vertex lies from the produced parents' triangles, over the step's
137
+ `self_error`:
138
+
139
+ | group level | steps sampled | ratio median | p90 | max | steps over 1 |
140
+ |---:|---:|---:|---:|---:|---:|
141
+ | 0 | 60 | 1.30 | 2.50 | 4.9 | 97% |
142
+ | 3 | 60 | 1.29 | 2.07 | 5.6 | 75% |
143
+ | 5 | 60 | 1.08 | 2.79 | 1,696 | 55% |
144
+ | 10 | 60 | 0.77 | 2.39 | 10.5 | 33% |
145
+ | 20 | 60 | 0.51 | 4.20 | 35.0 | 27% |
146
+ | 32 | 46 | 5.60 | 16.8 | 33.0 | 85% |
147
+
148
+ `self_error` is the quadric's conformance to the source, normalised by its weight (`vgeo_build_levels`
149
+ §"Error is conformance to the source") — a plane-distance statistic, which is the right thing for a
150
+ screen-space LOD threshold and the wrong thing to build a cull on. A cull that is right for most
151
+ steps is a hole for the rest. Rejected; the number is recorded so nobody measures it again.
152
+
153
+ ### 2.4 Row cost and slot fit
154
+
155
+ The exact subtree AABB is six words a cluster row: 13 → 19. `SELF_SPHERE` stays — the projection
156
+ reads it — and the existing sphere test stays in front of the box test (§3.4). On this container the
157
+ widest page is 52 clusters, 5 nodes, 15 groups, 25 parent entries: 851 words today, 1,163 at 19 words,
158
+ 56.8% of the 2,048-word slot a 64 KB page gets. `slot_words_for` and the install refusal are
159
+ unchanged in form. At the million resident clusters design §4 targets the arena is 76 MB rather than
160
+ 52.
161
+
162
+ ## 3. What is built
163
+
164
+ ### 3.1 Format — `subtree_aabb` in the cluster record, as `format_version` 5
165
+
166
+ The record stays 112 bytes. `bounds_sphere` goes: nothing at runtime read it (the row's doc said
167
+ so), the AABB already serves the meshlet metadata and every downstream cull, and its 16 bytes plus
168
+ `cone_reserved`'s 4 and the 6 that shift down make room for a 24-byte box in one place. Everything
169
+ from offset 40 moves, so `min_reader_version` moves to 5 with it — a version-4 reader would read a
170
+ version-5 record's `child_ref` out of its box.
171
+
172
+ | offset | type | field | |
173
+ |---:|---|---|---|
174
+ | 0 | [f32; 4] | self_sphere | unchanged |
175
+ | 16 | f32 | self_error | unchanged |
176
+ | 20 | f32 | parent_error | unchanged |
177
+ | 24 | [f32; 4] | parent_sphere | unchanged |
178
+ | 40 | [f32; 6] | **subtree_aabb** | object-space AABB of this cluster's vertices and of every cluster reachable below it through child groups; leaves: equals `aabb` |
179
+ | 64 | [f32; 6] | aabb | was 56 |
180
+ | 88 | u16 | child_ref | was 80 |
181
+ | 90 | u16 | child_group | was 82 |
182
+ | 92 | u32 | encoding_flags | was 88; `cone_reserved` (was 84) is gone |
183
+ | 96 | u32 | payload_offset | was 92 |
184
+ | 100 | u32 | payload_size | was 96 |
185
+ | 104 | u8 | vertex_count | was 100 |
186
+ | 105 | u8 | triangle_count | was 101 |
187
+ | 106 | [u8; 6] | reserved | was ten bytes at 102; the validator's zero check follows |
188
+
189
+ The writer and the validator read and write the record **positionally** (`vgeo_write_container` after
190
+ `SELF_SPHERE`, `read_clusters` in the validator), so both are re-sequenced, not just the offset table.
191
+ `VirtualGeometryCluster.bounds_sphere` stays as a **builder-only** field — the object sphere, the
192
+ group centroids and the leaf `self_sphere` are built from it — and its doc says it is no longer
193
+ written. `VIRTUAL_GEOMETRY_DESIGN.md` and `VIRTUAL_GEOMETRY_PLAN.md` mention `cone_reserved` as a
194
+ zeroed column and are corrected.
195
+
196
+ **Build invariant §11.17.** `subtree_aabb` contains the cluster's `aabb` and, for every cluster of its
197
+ child group, that cluster's `subtree_aabb`. Exact on stored values, no tolerance: the builder computes
198
+ the union of float32 extremes, which is exactly representable. By induction it contains every vertex
199
+ below the cluster, which is the whole of what the cull needs, and it needs no sphere nesting — the
200
+ containment that made §7's LOD pair compound is not asked of it.
201
+
202
+ **§11.7 gains what dropping `bounds_sphere` would have lost.** The validator checked
203
+ `bounds_sphere ∋ vertices` and never `self_sphere ∋ vertices`; the latter is what the sphere test and
204
+ the version-4 cube in §3.4 rest on, and it was only ever true by construction (`vgeo_build_levels`
205
+ sets a leaf's `self_sphere` to its miniball and inflates every step sphere to contain the produced
206
+ vertices). It is now stated in §11.7 and checked per cluster against the payload.
207
+
208
+ **Builder.** A memoised walk over `child_group` after `vgeo_build_levels`: a leaf's box is its `aabb`;
209
+ a parent's is its `aabb` unioned with each child-group member's `subtree_aabb`. Not a pass by level:
210
+ a round leaves unmerged clusters in the frontier, so a group formed at round L holds members created
211
+ at any lower level, and `group.level` says where the group was formed, not where its members were.
212
+ The walk is O(N) either way.
213
+
214
+ **Reader.** `VGeoPage.subtree_aabb` (`6 · cluster_count`) replaces `bounds_sphere`. The page decoder
215
+ is handed the container's `format_version` — through `VGeoPageFetcherCore`, whose three construction
216
+ sites (reader, in-process fetcher, worker) all have the header — and reads a version-4 record by the
217
+ old offsets, synthesising `subtree_aabb` as the cube around `self_sphere`: a conservative subtree
218
+ bound, so a container nobody has rebuilt still culls correctly. §3.4 says why it also culls no worse.
219
+ The validator accepts only the current version, as it always has.
220
+
221
+ ### 3.2 Runtime — `CULL_BOX` in the row, tested after the sphere and after the election
222
+
223
+ `VGEO_CLUSTER_ROW_OFFSET.CULL_BOX = 13`, six words, `VGEO_CLUSTER_ROW_WORDS = 19`;
224
+ `vgeo_runtime_write_page_block` copies `page.subtree_aabb`. `vg_visit_cluster` keeps its
225
+ `SELF_SPHERE` test and adds `vg_box_outside_frustum` on the row's box: a p-vertex per plane, five
226
+ planes, the same `VGEO_CUT_FLAG_CULL` bit. Clusters the sphere rejects count in `CULLED_CLUSTER` as
227
+ before; clusters the sphere passed and the box rejected count in a new `CULLED_CLUSTER_BOX`, so a
228
+ version-4 container reading zero there is §3.4's promise made visible. Two conservative bounds on the
229
+ same subtree; a cluster outside either is outside.
230
+
231
+ **The frustum tests move below the walk-up election.** Today the cull runs before the
232
+ `parent_projected <= tau` branch, so with the coarsen flag on a frontier cluster the frustum rejects
233
+ never elects the walk to its parents — and the parent's own `aabb` can protrude on screen beyond the
234
+ children's union, which is exactly why §3.1 adds it. A tighter bound fires that more often. A cluster
235
+ below the cut refines into nothing and claims nothing, so culling it buys residency nothing; the
236
+ election is evaluated first, unconditionally, and the frustum tests gate only what follows: drawing,
237
+ clamping and refining. The production caller never sets coarsen today; the spec does.
238
+
239
+ ### 3.3 The CPU reference cut
240
+
241
+ `vgeo_select_cut` culls on `page.subtree_aabb` with the same box test, so the fixture and the kernel
242
+ answer the same question, and its spec's claims ("never a hole while a page is missing", "a fully
243
+ resident cut is a whole-file reader's cut") run against the new bound.
244
+
245
+ ### 3.4 Why the sphere test stays
246
+
247
+ For a version-5 page the box is inside the sphere's cube and usually inside the sphere; the sphere
248
+ test culls almost nothing the box would not. For a version-4 page the synthesised box **is** the
249
+ sphere's cube, and a cube culls less than its inscribed sphere: the CPU cut visits 6–10% more pages
250
+ on the cube alone (3,292 against 3,091 at rest). With both tests a version-4 container culls exactly
251
+ what it culls today and a version-5 container culls what the box allows. No version reaches the
252
+ kernel.
253
+
254
+ ## 4. The proof, and where it lives
255
+
256
+ **Claim.** With culling on, the cut draws every cluster the open cut draws that has a vertex inside
257
+ the frustum, and no cluster the open cut does not draw — descending from the root, and walking up
258
+ from a kept frontier with the coarsen flag on. Parents of one group may decide differently —
259
+ a group is claimed and drawn once by whichever parent reaches it first — so no group-uniformity is
260
+ needed and none is argued; §2.1 of the 2026-09-14 plan leaned on it and did not need to.
261
+
262
+ **Argument.** A culled cluster's `CULL_BOX` (or `SELF_SPHERE`) is outside a frustum plane. Both
263
+ contain every vertex of every cluster reachable below it (§3.1's invariant for the box; §7's
264
+ construction for the sphere), so every such cluster is outside the same plane, and so is every
265
+ triangle they carry. Nothing on screen was under it. The LOD half of the rule is untouched, so
266
+ RUNTIME_PLAN §4.4's second proof — every cluster the flat rule draws is reached — holds for every
267
+ on-screen cluster: each ancestor along its chain contains it and so passes both tests.
268
+
269
+ **Where it is checked.** `vgeo_cut_agreement.spec.js`, `frustum culling removes only what is outside
270
+ the frustum`, rewritten to hold the kernel against the **reader's pages** and not against any bound
271
+ the row carries. For each cluster the open cut drew and the culled cut did not, it walks the child
272
+ groups through the reader and asserts every **vertex** of every cluster it reaches — decoded from the
273
+ payload, the same witness `vgeo_read_page.spec` uses for the `aabb` — is outside the frustum. Not the
274
+ descendants' boxes: a sphere that contains every vertex need not contain a box corner, so a
275
+ sphere-culled cluster with a straddling box would fail a box oracle on a correct kernel. For every
276
+ touched page but the root it asserts some cluster refining into it passes the kernel's own predicate
277
+ on bounds the spec computes itself — `self_sphere` not rejected and the union box of its subtree
278
+ not rejected — because a union box the frustum cuts through the gap between two members passes the
279
+ kernel's test with no member inside, and a p-vertex test admits a box just past an edge, so no
280
+ assertion about member boxes is implied by the design. The same test runs with the coarsen flag on
281
+ over a frontier seeded below the cut, against the open coarsen cut. That the **stored**
282
+ `subtree_aabb` equals the union the spec computes is `vgeo_read_page.spec.js`'s to check, and it does,
283
+ exactly. A child group whose page the reader does not hold is a leaf to the walk: nothing below a
284
+ missing page can be drawn, and the parent's own vertices are already in the check.
285
+
286
+ ## 5. What it reads after — measured 2026-09-16
287
+
288
+ The rosette panel rebuilt at version 5 (`5a01cc81…`, 17,213 pages, 590,858 clusters and 160,441
289
+ groups — identical to the version-4 build, and 940,215,784 bytes against 941,905,000), validated
290
+ clean including §11.17 and the new §11.7 check. The tour of RUNTIME_PLAN §7, same driver, same eight
291
+ stops twice round, 4,096 slots, 1258×646, then the rosette at rest. Both containers were driven
292
+ through **this** runtime, so the version-4 column is the §3.4 promise rather than an old reading.
293
+
294
+ | | version 4 (cube from the LOD sphere) | version 5 (subtree box) |
295
+ |---|---:|---:|
296
+ | pages visited, rosette at rest | 3,231 | **2,854** |
297
+ | pages visited, stops 3, 4, 5, 7 | 2,908 / 2,502 / 2,005 / 2,322 | **2,169 / 1,763 / 1,341 / 1,633** |
298
+ | pages visited, framing distance | 1,445 | 1,445 |
299
+ | pages visited, summed over the tour | 48,563 | **39,075** |
300
+ | clusters drawn at rest | 4,055 | 3,471 |
301
+ | clusters the box culled and the sphere did not, at rest | 0 | 5,520 |
302
+ | `clamped`, every stop | 0 | 0 |
303
+ | pages evicted over the run | 3,040 | **1,908** |
304
+ | installs refused over the run | 1,640 | **483** |
305
+ | pages fetched | 4,895 | 4,653 |
306
+
307
+ Against the same stop the box takes 12% off at rest, 14–18% at the three stops facing the panel
308
+ squarely, and 25–33% at the four oblique ones — where §2.2's node measurement said 35–40%, and the
309
+ difference is the sphere test still running in front of it. At the framing distance, where nothing
310
+ is off screen, it costs and saves nothing and the box culls zero. `culled (box)` is zero at every
311
+ stop of the version-4 run, which is §3.4 measured rather than argued.
312
+
313
+ **Drawn falls with visited**, 4,055 to 3,471 at rest, and that is the other half of the same fact:
314
+ those clusters passed a sphere that reaches well outside the geometry it stands for, and they were
315
+ off screen. The rest-pose screenshot is the same picture — same ornament, same shading, same depth
316
+ of detail; only the panel's own counters differ.
317
+
318
+ **What it is worth is residency, not the cut's own cost.** Evictions over the run fall by 37% and
319
+ refused installs by 71%, which is the LRU being handed a working set closer to what the view needs.
320
+ `clamped` stays zero throughout, so nothing is drawn coarse to pay for it.
321
+
322
+ ## 6. What this does not do, and what would
323
+
324
+ - **It does not get visited pages to a few hundred, and nothing conservative on a DAG edge can.** §1
325
+ is the floor: ~1,550 transit pages at every zoomed pose. That floor is the traversal's, not the
326
+ bound's. A descent that reaches groups through a **spatial** hierarchy — a BVH whose leaves are
327
+ groups at every level placed by their own bounds, the LOD range of what is beneath a node deciding
328
+ whether to enter it, the flat rule of §4.4 evaluated at each group reached — needs no subtree
329
+ bound at all, because nothing is reached *through* a coarse cluster; and it enumerates each group
330
+ once, which retires the claim. That is Nanite's shape and a different document: it replaces the
331
+ child-table descent, the claim, the frontier and the coarsen path of CUT_PLAN_2026_09_14.
332
+ - **It does not fix the builder's tail.** Convergence decaying from 0.5 to 0.9 a level above level
333
+ 4 is where the 1,700 transit pages come from, and the assembler mixing levels in a page is why a
334
+ zoomed view touches most of them. Both are the builder's, measured here and left open.
335
+ - **It does not make the error a bound.** §2.3's table is a property of the LOD metric, not of this
336
+ cull; whether the LOD switch should carry a geometric bound beside the quadric is its own question.
337
+ - **It does not touch the node test**, which culls inside an already-claimed page and does not move
338
+ residency.
339
+
340
+ ## 7. Order, and what each step leaves green
341
+
342
+ Each change carries a spec that fails before it and passes after; no spies, no mocks.
343
+
344
+ 1. **Format.** `VGEO_CLUSTER_OFFSET` v5 layout and a v4 table kept for the reader;
345
+ `VGEO_FORMAT_VERSION`/`VGEO_MIN_READER_VERSION` 5; writer re-sequenced and writing `subtree_aabb`;
346
+ builder computes it; reader reads it through `format_version` handed to `VGeoPageFetcherCore` at
347
+ its four construction sites (and synthesises the cube for v4); validator re-sequenced, checks §11.17
348
+ and `self_sphere ∋ vertices`, stops after a version defect. Pins: `vgeo_read_page.spec` — every
349
+ cluster's `subtree_aabb` is exactly the union of its `aabb` and its child group's boxes, and a
350
+ leaf's equals its `aabb`; `vgeo_validate_container.spec` — a shrunk `subtree_aabb` is caught, and so
351
+ is a `self_sphere` that leaves a vertex out; `VGeoContainerReader.spec` — a version-4 record layout
352
+ reads through the legacy offsets with the cube synthesised. `VGEO_FORMAT.md` §4, §7, §11 follow.
353
+ 2. **Rebuild the container** with the new builder, in the background, while the runtime lands.
354
+ 3. **Runtime.** Row layout, page block, kernel (box test, the new counter, the election ahead of the
355
+ culls), fixture cut. Pins: `VGeoRuntimeTables.spec` — the row carries the page's box;
356
+ `vgeo_cut_agreement.spec` — §4's rewritten test, descending and coarsening; the compile spec stays
357
+ at ten storage buffers.
358
+ 4. **Tour** on the rebuilt container and on its version-4 form; §5's table filled in; screenshot
359
+ compared. Done 2026-09-16.
360
+
361
+ ## 8. Review — folded in
362
+
363
+ One adversarial pass over the draft against the code, fifteen findings, the ones that changed the
364
+ document:
365
+
366
+ - **The spec's oracle was wrong for the sphere test (finding 1)** and its claim assertion was not
367
+ implied by the design (2). §4 now tests vertices and the kernel's own predicate on spec-computed
368
+ bounds.
369
+ - **"One level below" is false (3):** unmerged clusters ride the frontier upward. §3.1 memoises.
370
+ - **The coarsen path was unproven and the tighter bound widens its hole (4).** §3.2 moves the
371
+ frustum tests below the election and §4's claim now covers walking up.
372
+ - **`self_sphere ∋ vertices` was never a stated invariant (5)** and dropping `bounds_sphere` deleted
373
+ the only vertex-in-sphere check. §3.1 adds it to §11.7 and the validator.
374
+ - **`payload_offset`/`payload_size` move (6)** and both the writer and the validator are positional.
375
+ §3.1's table and step 1 say so.
376
+ - **Two tables disagreed (7):** §0's per-level split and §1's totals now use one classification, the
377
+ §2.1 caption names its samples, and §5 no longer transfers a CPU delta onto the GPU's count.
378
+ - **Four construction sites, not three (8)**, and the version rides the worker's first request with
379
+ the descriptor. The validator stops after a version defect (10) rather than misreading v4 records
380
+ positionally. `bounds_sphere` is scoped to the record (11). The slot-words doc is rewritten for 76
381
+ bytes a cluster (12). A separate counter tells box culls from sphere culls (15).
382
+
383
+ Confirmed by the pass and left as written: the object-space frustum makes the p-vertex test and the
384
+ version-4 cube conservative under instance scale (14); §2.4's arithmetic (12); `vgeo_read_header`'s
385
+ check admits both versions (9).
@@ -1 +1 @@
1
- {"version":3,"file":"VGeoPageFetcher.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.js"],"names":[],"mappings":"AAIA;;;GAGG;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH;IA0EI;;;;;;OAMG;IACH;QAL4B,YAAY,GAA7B,MAAM;QACuB,WAAW,SAA5B,MAAM;OAS5B;IAED;;OAEG;IACH,2BAEC;IAED;;;OAGG;IACH,iCAEC;IAED;;;OAGG;IACH,qCAEC;IAED;;OAEG;IACH,4BAEC;IAED;;;OAGG;IACH,gCAEC;IAED;;;;;;;OAOG;IACH,cAPW,mBAAmB,cACnB,MAAM,gBACN,MAAM,cACN,MAAM,WACN,WAAW,GACT,QAAQ,QAAQ,CAAC,CAc7B;IAED;;;;;;OAMG;IACH,eAHW,mBAAmB,GACjB,MAAM,CAuBlB;IAED;;;;OAIG;IACH,WAFa,IAAI,CAiBhB;;CAwKJ;kCAnYY,OAAO,uCAAuC,EAAE,mBAAmB;uBACnE,OAAO,4BAA4B,EAAE,QAAQ"}
1
+ {"version":3,"file":"VGeoPageFetcher.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.js"],"names":[],"mappings":"AAIA;;;GAGG;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH;IA0EI;;;;;;OAMG;IACH;QAL4B,YAAY,GAA7B,MAAM;QACuB,WAAW,SAA5B,MAAM;OAS5B;IAED;;OAEG;IACH,2BAEC;IAED;;;OAGG;IACH,iCAEC;IAED;;;OAGG;IACH,qCAEC;IAED;;OAEG;IACH,4BAEC;IAED;;;OAGG;IACH,gCAEC;IAED;;;;;;;OAOG;IACH,cAPW,mBAAmB,cACnB,MAAM,gBACN,MAAM,cACN,MAAM,WACN,WAAW,GACT,QAAQ,QAAQ,CAAC,CAc7B;IAED;;;;;;OAMG;IACH,eAHW,mBAAmB,GACjB,MAAM,CAuBlB;IAED;;;;OAIG;IACH,WAFa,IAAI,CAiBhB;;CAiLJ;kCA5YY,OAAO,uCAAuC,EAAE,mBAAmB;uBACnE,OAAO,4BAA4B,EAAE,QAAQ"}
@@ -301,6 +301,14 @@ export class VGeoPageFetcher {
301
301
  id,
302
302
  source_id,
303
303
  asset_id_low64: reader.header.asset_id_low64,
304
+ /*
305
+ The worker decodes cluster records and their layout is the container's (§7), so the
306
+ version travels with the identity. It rides every request rather than only the one
307
+ carrying the descriptor: the worker builds its core from whichever request arrives
308
+ first for a source, and a field that is only sometimes there is a field that is
309
+ sometimes undefined.
310
+ */
311
+ format_version: reader.header.format_version,
304
312
  verify_frames: options.verify_frames,
305
313
  fetch_retries: options.fetch_retries,
306
314
  fetch_retry_backoff_ms: options.fetch_retry_backoff_ms,
@@ -378,6 +386,7 @@ export class VGeoPageFetcher {
378
386
  core = new VGeoPageFetcherCore({
379
387
  read: (offset, length, abort) => source.read(offset, length, abort),
380
388
  asset_id_low64: () => reader.header.asset_id_low64,
389
+ format_version: () => reader.header.format_version,
381
390
  verify_frames: options.verify_frames,
382
391
  fetch_retries: options.fetch_retries,
383
392
  fetch_retry_backoff_ms: options.fetch_retry_backoff_ms,
@@ -1 +1 @@
1
- {"version":3,"file":"VGeoResidency.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/runtime/VGeoResidency.js"],"names":[],"mappings":"AA2GA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH;IAiKI;;;;;;;OAOG;IACH;QAN2C,IAAI,EAApC,sBAAsB;QACS,OAAO,GAAtC,oBAAoB;QACM,IAAI,GAA9B,eAAe;QACW,OAAO,GAAjC,eAAe;OA8BzB;IAID;;OAEG;IACH,oCAEC;IAED;;OAEG;IACH,4BAEC;IAED;;OAEG;IACH,+BAEC;IAED;;OAEG;IACH,yEAEC;IAED;;;;OAIG;IACH,oBAEC;IAED;;;;OAIG;IACH,gCAGC;IAED,+BAEC;IAED,iCAEC;IAED,6BAEC;IAED,2BAEC;IAED,iCAEC;IAED,gCAEC;IAED;;;;OAIG;IACH,oCAEC;IAED;;;OAGG;IACH,kCAEC;IAED;;;OAGG;IACH,kCAEC;IAED;;;OAGG;IACH,iCAEC;IAED;;;OAGG;IACH,iCAEC;IAED;;;OAGG;IACH,gCAEC;IAED;;;;;OAKG;IACH,gCAEC;IAED;;;OAGG;IACH,iCAEC;IAED,gCAEC;IAED,+BAEC;IAED,8BAEC;IAED;;OAEG;IACH,qCAQC;IAID;;;;;;;;;;OAUG;IACH,iBAHW,mBAAmB,GACjB,MAAM,CA8ClB;IAED;;;;;;OAMG;IACH,mBAHW,mBAAmB,GACjB,OAAO,CAgBnB;IAED;;;OAGG;IACH,sBAHW,mBAAmB,GACjB,OAAO,CAInB;IAED;;;;;;OAMG;IACH,cAJW,mBAAmB,cACnB,MAAM,GACJ,QAAQ,GAAC,UAAU,GAAC,aAAa,GAAC,KAAK,GAAC,MAAM,GAAC,cAAc,CAqBzE;IAgCD;;;;OAIG;IACH,SAFa,IAAI,CAOhB;IAED;;;;OAIG;IACH,WAFa,IAAI,CAUhB;IAED;;;;OAIG;IACH,qBAFa,MAAM,CAkBlB;IAID;;;;;;;;;OASG;IACH,aANW,WAAW,UACX;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAChF,UAAgB,EAAE,MAAM,CAAA;KAAC,iBACf,MAAM,GACJ,IAAI,CA6HhB;IA2FD;;;;;;OAMG;IACH,yBAHW,MAAM,GACJ,OAAO,CAgBnB;IAED;;;;;;OAMG;IACH,oBAHW,MAAM,GACJ,OAAO,CAoCnB;;CAqXJ;kCAr1CY,OAAO,uCAAuC,EAAE,mBAAmB;uBACnE,OAAO,4BAA4B,EAAE,QAAQ;qCAC7C,OAAO,6BAA6B,EAAE,sBAAsB;qCALpC,2BAA2B;gCALhC,gDAAgD;gCAIhD,sBAAsB"}
1
+ {"version":3,"file":"VGeoResidency.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/runtime/VGeoResidency.js"],"names":[],"mappings":"AA2GA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH;IAiKI;;;;;;;OAOG;IACH;QAN2C,IAAI,EAApC,sBAAsB;QACS,OAAO,GAAtC,oBAAoB;QACM,IAAI,GAA9B,eAAe;QACW,OAAO,GAAjC,eAAe;OA8BzB;IAID;;OAEG;IACH,oCAEC;IAED;;OAEG;IACH,4BAEC;IAED;;OAEG;IACH,+BAEC;IAED;;OAEG;IACH,yEAEC;IAED;;;;OAIG;IACH,oBAEC;IAED;;;;OAIG;IACH,gCAGC;IAED,+BAEC;IAED,iCAEC;IAED,6BAEC;IAED,2BAEC;IAED,iCAEC;IAED,gCAEC;IAED;;;;OAIG;IACH,oCAEC;IAED;;;OAGG;IACH,kCAEC;IAED;;;OAGG;IACH,kCAEC;IAED;;;OAGG;IACH,iCAEC;IAED;;;OAGG;IACH,iCAEC;IAED;;;OAGG;IACH,gCAEC;IAED;;;;;OAKG;IACH,gCAEC;IAED;;;OAGG;IACH,iCAEC;IAED,gCAEC;IAED,+BAEC;IAED,8BAEC;IAED;;OAEG;IACH,qCAQC;IAID;;;;;;;;;;OAUG;IACH,iBAHW,mBAAmB,GACjB,MAAM,CA8ClB;IAED;;;;;;OAMG;IACH,mBAHW,mBAAmB,GACjB,OAAO,CAgBnB;IAED;;;OAGG;IACH,sBAHW,mBAAmB,GACjB,OAAO,CAInB;IAED;;;;;;OAMG;IACH,cAJW,mBAAmB,cACnB,MAAM,GACJ,QAAQ,GAAC,UAAU,GAAC,aAAa,GAAC,KAAK,GAAC,MAAM,GAAC,cAAc,CAqBzE;IA6CD;;;;OAIG;IACH,SAFa,IAAI,CAOhB;IAED;;;;OAIG;IACH,WAFa,IAAI,CAUhB;IAED;;;;OAIG;IACH,qBAFa,MAAM,CAkBlB;IAID;;;;;;;;;OASG;IACH,aANW,WAAW,UACX;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAChF,UAAgB,EAAE,MAAM,CAAA;KAAC,iBACf,MAAM,GACJ,IAAI,CA6HhB;IA2FD;;;;;;OAMG;IACH,yBAHW,MAAM,GACJ,OAAO,CAgBnB;IAED;;;;;;OAMG;IACH,oBAHW,MAAM,GACJ,OAAO,CAoCnB;;CAqXJ;kCAl2CY,OAAO,uCAAuC,EAAE,mBAAmB;uBACnE,OAAO,4BAA4B,EAAE,QAAQ;qCAC7C,OAAO,6BAA6B,EAAE,sBAAsB;qCALpC,2BAA2B;gCALhC,gDAAgD;gCAIhD,sBAAsB"}
@@ -645,7 +645,20 @@ export class VGeoResidency {
645
645
  this.#vram_last_used[row] = 0;
646
646
  }
647
647
 
648
- if (tag === TAG_VRAM || tag === TAG_RAM) {
648
+ /**
649
+ * TAG_PENDING too. `#fetch` reserves the slot and charges its bytes before the read goes
650
+ * out, and a fetching page is TAG_PENDING — so leaving it out here meant the slot and
651
+ * its reserved bytes were never given back: both settle handlers return on
652
+ * `#geometries.get(reader) !== geometry` before they would free it, and `unregister`
653
+ * drops the geometry synchronously right after cancelling, so that is the branch that
654
+ * always runs. A scene that swaps assets leaked a slot per fetch on the wire until
655
+ * `#make_ram_room` refused everything, while `ram_resident_bytes` and `ram_page_count`
656
+ * both went on reporting the tier as empty.
657
+ *
658
+ * `#free_ram_slot` is a no-op for NO_SLOT and for a slot already given back, so the
659
+ * quarantined half of TAG_PENDING costs nothing here.
660
+ */
661
+ if (tag === TAG_VRAM || tag === TAG_RAM || tag === TAG_PENDING) {
649
662
  this.#free_ram_slot(geometry.slot[page_index]);
650
663
  }
651
664
 
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_vgeo_cut_access.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AACH,oCAFU,SAAS,CA+EQ;0BAjGD,0CAA0C"}
1
+ {"version":3,"file":"chunk_vgeo_cut_access.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AACH,oCAFU,SAAS,CAiHQ;0BAnID,0CAA0C"}
@@ -95,4 +95,38 @@ fn vg_sphere_outside_frustum(instance_base: u32, sphere: vec4<f32>) -> bool {
95
95
 
96
96
  return false;
97
97
  }
98
+
99
+ /**
100
+ * Whether a box is entirely outside the instance's object-space frustum.
101
+ *
102
+ * The same five planes, and one corner per plane rather than eight: the corner furthest along the
103
+ * plane's normal is the last of the box to leave the half-space, so if *it* is behind the plane the
104
+ * whole box is. Picking it per axis by the normal's sign is three selects and no branch.
105
+ *
106
+ * Unlike the sphere test this one does not care whether the planes are normalized — it compares a
107
+ * signed distance against zero rather than against a radius — which matters because the planes are
108
+ * the instance's own, pulled into object space through a transform that may not be a rotation.
109
+ *
110
+ * It is conservative in the direction that costs a visit rather than a hole: a box that lies past a
111
+ * frustum edge without crossing any single plane's half-space passes, and is descended into.
112
+ */
113
+ fn vg_box_outside_frustum(instance_base: u32, lower: vec3<f32>, upper: vec3<f32>) -> bool {
114
+ for (var plane = 0u; plane < 5u; plane = plane + 1u) {
115
+ let word = instance_base + ${VGEO_INSTANCE_OFFSET.FRUSTUM}u + plane * 4u;
116
+
117
+ let normal = vec3<f32>(
118
+ bitcast<f32>(instances[word]),
119
+ bitcast<f32>(instances[word + 1u]),
120
+ bitcast<f32>(instances[word + 2u])
121
+ );
122
+
123
+ let far_corner = select(lower, upper, normal >= vec3<f32>(0.0));
124
+
125
+ if (dot(normal, far_corner) + bitcast<f32>(instances[word + 3u]) < 0.0) {
126
+ return true;
127
+ }
128
+ }
129
+
130
+ return false;
131
+ }
98
132
  `, [chunk_vgeo_cut_arena]);
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_vgeo_cut_arena.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;GAeG;AACH,mCAFU,SAAS,CAwEZ;0BAjGmB,0CAA0C"}
1
+ {"version":3,"file":"chunk_vgeo_cut_arena.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;GAeG;AACH,mCAFU,SAAS,CA0FZ;0BAnHmB,0CAA0C"}
@@ -95,4 +95,22 @@ fn vg_sphere_at(word: u32) -> vec4<f32> {
95
95
  bitcast<f32>(vg_arena[word + 3u])
96
96
  );
97
97
  }
98
+
99
+ /**
100
+ * Six consecutive words as an axis-aligned box: the lower corner, then the upper.
101
+ */
102
+ fn vg_box_at(word: u32) -> array<vec3<f32>, 2> {
103
+ return array<vec3<f32>, 2>(
104
+ vec3<f32>(
105
+ bitcast<f32>(vg_arena[word]),
106
+ bitcast<f32>(vg_arena[word + 1u]),
107
+ bitcast<f32>(vg_arena[word + 2u])
108
+ ),
109
+ vec3<f32>(
110
+ bitcast<f32>(vg_arena[word + 3u]),
111
+ bitcast<f32>(vg_arena[word + 4u]),
112
+ bitcast<f32>(vg_arena[word + 5u])
113
+ )
114
+ );
115
+ }
98
116
  `, []);
@@ -1 +1 @@
1
- {"version":3,"file":"shader_vgeo_cut_traverse.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js"],"names":[],"mappings":"AAu2BA,qDAIG;8BAx2B2B,qCAAqC"}
1
+ {"version":3,"file":"shader_vgeo_cut_traverse.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js"],"names":[],"mappings":"AAm4BA,qDAIG;8BAp4B2B,qCAAqC"}
@@ -123,8 +123,14 @@ import { VGEO_CUT_WORKGROUP_SIZE } from "./VGEO_CUT_WORKGROUP_SIZE.js";
123
123
  * induction its page is visited. `P` fails `project(self) <= tau`, so it either enqueues `C`'s
124
124
  * page or clamps, and it clamps only when `C`'s group is not selectable, in which case `C` must
125
125
  * not be drawn. Neither cull intervenes: a node's sphere contains `P.parent_sphere` and its
126
- * `max_parent_error` is at least `P.parent_error`, so the LOD cull cannot fire, and the frustum
127
- * cull fires only where `C` is off-screen anyway.
126
+ * `max_parent_error` is at least `P.parent_error`, so the LOD cull cannot fire, and both frustum
127
+ * culls are on bounds of `P`'s whole subtree, which contains `C` — so they fire only where `C`
128
+ * is off-screen anyway.
129
+ *
130
+ * Note that the per-cluster frustum tests do **not** have to agree across a group's several
131
+ * parents, and nothing here asks them to. A group is claimed and descended once, by whichever
132
+ * parent reaches it first; a parent that culls itself out simply is not that one. What each test
133
+ * promises is about its own subtree and nothing else.
128
134
  *
129
135
  * Descent crosses a page boundary by producing the child page's **node 0**: uniform items, one
130
136
  * kernel, no special case for "entering a page". `SAME_PAGE` needs no special case either, because
@@ -472,23 +478,6 @@ fn vg_visit_cluster(
472
478
 
473
479
  vg_stat(${VGEO_CUT_STAT.CLUSTERS_TESTED}u, 1u);
474
480
 
475
- /*
476
- Before the cluster can refine, and the reason is residency rather than the draw: refining
477
- claims the child page, and a claim is a touch — the LRU's whole input — so an off-screen
478
- cluster that refined anyway would keep pages nobody can see hot and the tier full of them.
479
- self_sphere contains the cluster's own vertices (FORMAT §7), so this rejects nothing on
480
- screen; and every parent of a group shares one self_sphere, so a group's parents decide this
481
- uniformly and the cut's proofs stand (RUNTIME_PLAN §4.4).
482
- */
483
- if ((params.flags & ${VGEO_CUT_FLAG_CULL}u) != 0u
484
- && vg_sphere_outside_frustum(
485
- instance_base, vg_sphere_at(row + ${VGEO_CLUSTER_ROW_OFFSET.SELF_SPHERE}u)
486
- )) {
487
- vg_stat(${VGEO_CUT_STAT.CULLED_CLUSTER}u, 1u);
488
-
489
- return vg_expand_none();
490
- }
491
-
492
481
  let parent_projected = vg_project(
493
482
  vg_arena_f32(row + ${VGEO_CLUSTER_ROW_OFFSET.PARENT_ERROR}u),
494
483
  vg_sphere_at(row + ${VGEO_CLUSTER_ROW_OFFSET.PARENT_SPHERE}u),
@@ -525,6 +514,45 @@ fn vg_visit_cluster(
525
514
  );
526
515
  }
527
516
 
517
+ /*
518
+ The frustum, on two bounds of this cluster's whole subtree, and **below the election above**.
519
+
520
+ Why here and not at the top of the function. The reason to cull is residency rather than the
521
+ draw: refining claims the child page, and a claim is a touch — the LRU's whole input — so an
522
+ off-screen cluster that refined anyway would keep pages nobody can see hot and the tier full of
523
+ them. A cluster that took the branch above is below the cut: it refines into nothing, claims
524
+ nothing and draws nothing, so culling it buys residency exactly nothing, while skipping its
525
+ election costs a coarsen its walk up. The parent that election reaches can protrude on screen
526
+ past everything under it — that is what a coarser surface covering the same region looks like —
527
+ and with the test above the election it was never reached, so it was neither drawn nor stood in
528
+ for. A hole, and the tighter the bound the more often.
529
+
530
+ Why two bounds. Both contain every vertex reachable below this cluster, which is what makes
531
+ either safe to cull a subtree on: self_sphere by the builder's construction and FORMAT §11.7,
532
+ CULL_BOX by §11.17. The box is much the tighter of the two on real geometry — a subtree is a
533
+ patch of surface and its box is thin where a sphere is round — and the sphere stays because a
534
+ container written before the box existed has its cube there instead, and a cube culls less than
535
+ the sphere inside it.
536
+ */
537
+ if ((params.flags & ${VGEO_CUT_FLAG_CULL}u) != 0u) {
538
+ if (vg_sphere_outside_frustum(
539
+ instance_base, vg_sphere_at(row + ${VGEO_CLUSTER_ROW_OFFSET.SELF_SPHERE}u)
540
+ )) {
541
+ vg_stat(${VGEO_CUT_STAT.CULLED_CLUSTER}u, 1u);
542
+
543
+ return vg_expand_none();
544
+ }
545
+
546
+ let cull_box = vg_box_at(row + ${VGEO_CLUSTER_ROW_OFFSET.CULL_BOX}u);
547
+
548
+ if (vg_box_outside_frustum(instance_base, cull_box[0], cull_box[1])) {
549
+ vg_stat(${VGEO_CUT_STAT.CULLED_CLUSTER}u, 1u);
550
+ vg_stat(${VGEO_CUT_STAT.CULLED_CLUSTER_BOX}u, 1u);
551
+
552
+ return vg_expand_none();
553
+ }
554
+ }
555
+
528
556
  let self_projected = vg_project(
529
557
  vg_arena_f32(row + ${VGEO_CLUSTER_ROW_OFFSET.SELF_ERROR}u),
530
558
  vg_sphere_at(row + ${VGEO_CLUSTER_ROW_OFFSET.SELF_SPHERE}u),
@@ -6,5 +6,6 @@ export namespace VGEO_CLUSTER_ROW_OFFSET {
6
6
  let CHILD_PAGE_INDEX: number;
7
7
  let CHILD_GROUP: number;
8
8
  let CHILD_REF: number;
9
+ let CULL_BOX: number;
9
10
  }
10
11
  //# sourceMappingURL=VGEO_CLUSTER_ROW_OFFSET.d.ts.map