@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
@@ -118,8 +118,8 @@ All u64/u128 fields are naturally 8-byte aligned.
118
118
  | offset | type | field | notes |
119
119
  |-------:|-----------|--------------------------|-------|
120
120
  | 0 | u32 | magic | `'VGEO'` = 0x4F454756 |
121
- | 4 | u16 | format_version | 4 today; breaking layout changes only |
122
- | 6 | u16 | min_reader_version | 3 today; reader MUST reject if its version is lower |
121
+ | 4 | u16 | format_version | 6 today; breaking layout changes only |
122
+ | 6 | u16 | min_reader_version | 6 today; reader MUST reject if its version is lower |
123
123
  | 8 | u16 | header_size | = 256 |
124
124
  | 10 | u8 | hash_algo | 0 = xxHash3; readers MUST reject unknown values |
125
125
  | 11 | u8 | reserved | |
@@ -138,8 +138,7 @@ All u64/u128 fields are naturally 8-byte aligned.
138
138
  | 88 | u64 | dir_block_checksums_offset | `ceil(total_pages / 128)` × u64 |
139
139
  | 96 | u32 | nominal_page_size | bytes a decoded page may come to; a **hard bound** when bit 0 of `feature_flags_ignorable` is set (§11.14), advisory otherwise |
140
140
  | 100 | u16 | reserved | |
141
- | 102 | u8 | level_count | levels `0..level_count-1` |
142
- | 103 | u8 | reserved | |
141
+ | 102 | u16 | level_count | levels `0..level_count-1`; ≤ 65,535. A `u8` through version 5, and the byte above it was reserved and written as zero — so little-endian makes this field read identically through either width for any container of 255 levels or fewer |
143
142
  | 104 | u64 | source_vertex_count | vertices of the normalized source mesh (post-weld) the leaves represent |
144
143
  | 112 | u64 | source_face_count | triangles of the normalized source mesh |
145
144
  | 120 | [f32; 4] | object_sphere | object-space minimal bounding sphere (center xyz, radius) of the whole geometry |
@@ -156,12 +155,35 @@ version-4 file correctly by ignoring them. In the other direction a version-4 re
156
155
  which is true — so neither direction needs a version test, and nothing has to be rebuilt to stay
157
156
  readable.
158
157
 
158
+ **5 moved both**, which is the pair working the other way. It put `subtree_aabb` in the cluster
159
+ record (§7) over the bytes `bounds_sphere` and `cone_reserved` held, so every field from offset 40
160
+ on shifted: a version-4 reader would take a version-5 `child_ref` out of the middle of a bounding
161
+ box and descend into whatever group that named. There is no ignoring it and no partial reading of
162
+ it, so `min_reader_version` moved with the version, which is what that field is for. A version-5
163
+ reader still reads version-4 records — it branches on the version it is holding — so nothing has to
164
+ be rebuilt to stay readable, only to be culled tightly.
165
+
166
+ **6 widened the level ordinal to `u16`** in all three places it is written down: `level_count`
167
+ here, the page band in the page header (§6.1), and the page band in the directory record (§9). 255
168
+ was a ceiling a real asset reached — the 2026-09-14 Zorah conversion refused a three-million-triangle
169
+ bush at exactly 255 levels with 39 clusters still unmerged, while the other 2,974 geometries of that
170
+ scene, one of them 27 million triangles, converged by 149 — and a ceiling an asset can touch is a
171
+ ceiling in the wrong place. Two of the three cost nothing: this header and the directory record both
172
+ had reserved bytes lying beside the field. The page header had none, and rather than grow the page
173
+ this spends `node_table_offset`, which only ever restated `56 + 8·group_count`. So **a page header
174
+ is still 56 bytes and every other field of every page ever written is still at its old offset** —
175
+ but bytes 4..8 and 20..24 of it now mean different things, and there is no partial reading of that,
176
+ so `min_reader_version` moved. A version-6 reader keeps the older page layout as it keeps the older
177
+ cluster layout, so again nothing has to be rebuilt to stay readable.
178
+
159
179
  ### 4.1 Level table (`level_count` × 32 B, immediately after the header)
160
180
 
161
181
  Statistics per level, at `256 + 32·i`, ending where the root page frame begins. Small —
162
- a hundred levels is 3.2 KB — so a single fetch of the file's head brings the header, the
163
- whole table, and the always-resident root page together, and the table is available before
164
- any page has been decoded.
182
+ a hundred levels is 3.2 KB, and the deepest container yet converted is 149 — so a single
183
+ fetch of the file's head brings the header, the whole table, and the always-resident root
184
+ page together, and the table is available before any page has been decoded. That is a
185
+ statement about what builds produce and not a bound: `level_count` is a `u16`, and a
186
+ reader sizing a head fetch must take the number it finds rather than assume this one.
165
187
 
166
188
  | offset | type | field | notes |
167
189
  |-------:|------|-------------------|-------|
@@ -219,7 +241,7 @@ Every page — root included — is stored as a self-delimiting frame:
219
241
  | offset | type | field | notes |
220
242
  |-------:|------|------------------|-------|
221
243
  | 0 | u32 | magic | `'VGPG'` = 0x47504756 |
222
- | 4 | u8 | codec | 0 = raw, 1 = one LZ4 block; applies to the blob only; readers MUST reject unknown values |
244
+ | 4 | u8 | codec | 0 = raw, 1 = one LZ4 block, 2 = one raw DEFLATE stream; applies to the blob only; readers MUST reject unknown values |
223
245
  | 5 | u8 | flags | 0 |
224
246
  | 6 | u16 | child_page_count | entries in the child table; 0 for all-leaf pages |
225
247
  | 8 | u32 | stored_size | bytes of blob (after the child table) |
@@ -258,26 +280,64 @@ terminator.
258
280
  and an asset may carry a mixture, so a reader that handles the defined codecs handles
259
281
  any file without asking what it was written with. That is what makes "compress unless it
260
282
  would not shrink" expressible — the LZ4 worst case is about one byte in 255 plus a
261
- token, and paying it to store bytes verbatim is a straight loss, so a page that does not
262
- compress is written raw and says so.
283
+ token, deflate's is a stored block that is never smaller than its input, and paying
284
+ either to store bytes verbatim is a straight loss, so a page that does not compress is
285
+ written raw and says so.
263
286
 
264
287
  A new codec id is a **per-asset capability gate, not a format break**, exactly as a new
265
288
  `payload_encoding` is: an older reader meets a codec it has no decoder for and refuses
266
289
  the asset instead of misreading it. `format_version` moves only when the container
267
- layout itself changes, and adding a codec does not change it.
290
+ layout itself changes, and adding a codec does not change it — `2` went in without
291
+ touching `format_version` or `min_reader_version`.
268
292
 
269
- `1` is a **bare LZ4 block**, not an LZ4 frame: LZ4's own framing carries a magic, a
270
- checksum and a content size that this frame already carries better, and `decoded_size`
271
- is what the block is decoded against. Blocks are independent — no match reaches outside
272
- the page — so a page decodes from its own bytes with no other page involved, which is
273
- the same property residency already needs.
293
+ `1` is a **bare LZ4 block**, not an LZ4 frame, and `2` is a **bare DEFLATE stream**
294
+ (RFC 1951), not a zlib or gzip member. Both wrappers carry a magic, a checksum and a
295
+ content size that this frame already carries better, and `decoded_size` is what the blob
296
+ is decoded against. Both codecs are independent per blob — no match reaches outside the
297
+ page — so a page decodes from its own bytes with no other page involved, which is the
298
+ same property residency already needs.
274
299
 
275
300
  `decoded_size` is untrusted input, and readers allocate against it before anything can
276
301
  contradict it. It MUST therefore be checked against what `stored_size` bytes could
277
302
  physically produce under `codec` — exactly `stored_size` for raw, at most
278
- `255·stored_size + 19` for LZ4 — *before* the allocation. A block that then decodes to
279
- anything other than `decoded_size` MUST be rejected: a page truncated to a plausible
280
- prefix is the one corruption that reads as a valid page with geometry missing.
303
+ `255·stored_size + 19` for LZ4, at most `1032·stored_size` for deflate — *before* the
304
+ allocation. A blob that then decodes to anything other than `decoded_size` MUST be
305
+ rejected: a page truncated to a plausible prefix is the one corruption that reads as a
306
+ valid page with geometry missing.
307
+
308
+ Those ceilings are what the *format* permits, and neither compressing one is anything
309
+ like what a page looks like, so a length check alone is a weak guard — deflate's 1032:1 admits a 256 KB blob claiming 264
310
+ MB. A decoder MUST therefore bound its own output as it produces it rather than
311
+ comparing lengths once it is done: the LZ4 decoder is given the end of the page as its
312
+ write limit, and the deflate decoder stops at the first chunk that would pass it. A blob
313
+ that expands further than its header admits then costs one chunk rather than the whole
314
+ expansion.
315
+
316
+ **Which codec, and why deflate is the default.** Measured over the 44 pages of a
317
+ 240×120 torus: LZ4 stores them at **1.295x** and deflate at **1.369x**, and decoding
318
+ every page costs **3.8 ms** under LZ4 against **16.9 ms** under deflate — 562 MB/s of
319
+ decoded output against 126. Deflate buys about seven points of ratio for four and a half
320
+ times the decode.
321
+
322
+ **The builder and the converter write deflate**, because the two sides of that trade are
323
+ not paid the same number of times: an asset is built once and fetched forever, and the
324
+ bytes deflate saves are saved on every fetch of every page by every client. LZ4 is the
325
+ deliberate setting for a container whose pages arrive while someone is looking at it —
326
+ there the decode is a page's *arrival* cost on the residency path, and 126 MB/s is what
327
+ that costs. Neither is a property of the file format: `codec` is a frame field and a
328
+ reader that handles the defined codecs reads either without being told.
329
+
330
+ A *default* codec is a statement about readers rather than about bytes. Under the gate
331
+ above, a container written with deflate opens only in a reader that carries the deflate
332
+ decoder, so the default is what decides which builds of this engine can open a freshly
333
+ converted asset. `format_version` still does not move, and an older reader still refuses
334
+ rather than misreads.
335
+
336
+ Deflate is also the *hosted* codec: `CompressionStream`/`DecompressionStream` are the
337
+ platform's own zlib, so it costs no bytes of library — and the platform offers it only
338
+ as a stream, which is why everything in this reader from the blob decode upwards is
339
+ asynchronous. Nothing in the format requires that; a synchronous inflate would read the
340
+ same files.
281
341
 
282
342
  **What it is worth, measured.** LZ4 over the pages of the Stanford models comes to
283
343
  **1.12x on the bunny, 1.18x on the dragon and 1.14x on the 27M-triangle lucy** — pages
@@ -292,10 +352,11 @@ is worth writing down because it says where the next win is rather than here:
292
352
  The tables compress, and there are not enough of them to matter. The payload does not,
293
353
  because under `SHADE_MESHLET_V1` it is float32 positions and packed attribute words —
294
354
  high-entropy at the byte level, with no repetition for an LZ matcher to find. For
295
- reference, on the same bytes `gzip -9` reaches 1.22x and `xz -9` 1.63x, so this is the
296
- data resisting rather than the codec failing; an entropy coder buys a little more for a
297
- lot more time. **The lever is `payload_encoding`, not `codec`** — quantized positions
298
- (§12) shrink those bytes directly and leave the residue far more compressible.
355
+ reference, on the same bytes `gzip -9` reaches 1.22x — codec `2`'s algorithm, at a level
356
+ the platform API does not expose — and `xz -9` 1.63x, so this is the data resisting
357
+ rather than the codec failing; an entropy coder buys a little more for a lot more time. **The lever is `payload_encoding`, not
358
+ `codec`** — quantized positions (§12) shrink those bytes directly and leave the residue
359
+ far more compressible.
299
360
 
300
361
  What the reader pays is one block decode per page installed, into the buffer the page was
301
362
  going to be copied into anyway: ~350–500 MB/s of decoded output from the JS decoder, so
@@ -309,9 +370,9 @@ about 0.6 ms for a 256 KB page.
309
370
  ```
310
371
 
311
372
  The two parent tables sit between the cluster records and the payload, and that placement is the
312
- reason `min_reader_version` did not move (§4): `node_table_offset`'s `= 56 + 8·group_count` stays
313
- true, every earlier offset is where it was, and both tables hold 4-byte entries over sections that
314
- are already multiples of four, so §11.8's word-aligned payload survives.
373
+ reason `min_reader_version` did not move when version 4 added them (§4): the node table's `= 56 +
374
+ 8·group_count` stays true, every earlier offset is where it was, and both tables hold 4-byte entries
375
+ over sections that are already multiples of four, so §11.8's word-aligned payload survives.
315
376
 
316
377
  PageHeader:
317
378
 
@@ -319,13 +380,13 @@ PageHeader:
319
380
  |-------:|------|-----------------------|-------|
320
381
  | 0 | u16 | group_count | ≥ 1; group table immediately follows the header |
321
382
  | 2 | u16 | cluster_count | ≥ 1 |
322
- | 4 | u8 | min_level | page band; non-root pages span one contiguous band |
323
- | 5 | u8 | max_level | |
324
- | 6 | u16 | node_count | ≥ 1; ≤ 2·`group_count` (§6.1) |
383
+ | 4 | u16 | min_level | page band; non-root pages span one contiguous band. A `u8` at 4 and another at 5 through version 5 |
384
+ | 6 | u16 | max_level | |
325
385
  | 8 | u32 | cluster_table_offset | |
326
386
  | 12 | u32 | payload_offset | |
327
387
  | 16 | u32 | payload_size | |
328
- | 20 | u32 | node_table_offset | = `56 + 8·group_count`; the node table follows the group table |
388
+ | 20 | u16 | node_count | ≥ 1; ≤ 2·`group_count` (§6.1). At 6 through version 5 |
389
+ | 22 | u16 | reserved | what version 5 spent on `node_table_offset`, which said only `56 + 8·group_count` — the group table follows the header and the node table follows the group table, so a reader derives it. MUST be zero |
329
390
  | 24 | u32 | parent_table_offset | start of the parent section — the parent-page table, then the group-parent table. **0 means the page carries neither**, which is what every container written before `format_version` 4 says about itself |
330
391
  | 28 | u16 | parent_entry_count | entries in the group-parent table (§6.3) = Σ `parent_cluster_count` over this page's groups |
331
392
  | 30 | u16 | parent_page_count | entries in the parent-page table (§6.4) |
@@ -435,11 +496,13 @@ decode it. Being a copy, it can drift; §11.11 requires it to match the page's o
435
496
  ## 7. Cluster record (112 bytes)
436
497
 
437
498
  Everything the runtime cut rule, culling, wants, and upload need — denormalized per
438
- cluster so selection reads one record. Two kinds of spheres, deliberately distinct: the
499
+ cluster so selection reads one record. Three kinds of bounds, deliberately distinct: the
439
500
  **LOD-metric pair** (`self_sphere`/`parent_sphere` — shared per group step so all
440
- siblings project identical values, monotonically inflated, never a tight fit) and the
441
- **culling bounds** (`bounds_sphere`/`aabb` — this cluster's own tight fits, never used
442
- in the cut test):
501
+ siblings project identical values, monotonically inflated, never a tight fit), the
502
+ **cluster's own box** (`aabb` — its tight fit, the meshlet metadata's `bounds_box`, culled
503
+ downstream by the HZB), and the **subtree box** (`subtree_aabb` — this cluster's geometry and
504
+ everything reachable below it, and the only one of the three the cut's per-cluster frustum test
505
+ can use, because culling a cluster takes its whole child group out of the descent):
443
506
 
444
507
  | offset | type | field | notes |
445
508
  |-------:|----------|-----------------|-------|
@@ -447,18 +510,23 @@ in the cut test):
447
510
  | 16 | f32 | self_error | object-space `r_e`; leaves: 0 |
448
511
  | 20 | f32 | parent_error | error of the step that consumed it; roots: +∞ |
449
512
  | 24 | [f32; 4] | parent_sphere | LOD-metric sphere of the consuming step; roots: duplicate of self_sphere |
450
- | 40 | [f32; 4] | bounds_sphere | this cluster's own minimal bounding sphere (miniball), object-space — culling |
451
- | 56 | [f32; 6] | aabb | this cluster's object-space AABB — culling, GPU metadata `bounds_box`, and the (future) dequantization grid |
452
- | 80 | u16 | child_ref | index into this frame's child table; `SAME_PAGE` when the child group is in this page; `NO_CHILD` for leaves |
453
- | 82 | u16 | child_group | group index within the child page (or this page, for `SAME_PAGE`); `NO_GROUP` for leaves |
454
- | 84 | u32 | cone_reserved | reserved — **write 0**. Named for a backface-cone cull pass that is now **declined outright** (design §9, plan §5), so no sub-encoding will ever be pinned here. Kept rather than reclaimed: removing it moves `format_version`, a constant-zero column costs nothing after the page codec, and there are ten more reserved bytes beside it at 102 and 104 anyway. A candidate to rename and reuse the next time the version moves for some other reason |
455
- | 88 | u32 | encoding_flags | frozen bit table in §8 |
456
- | 92 | u32 | payload_offset | into this page's payload section; ≡ 0 (mod 4) |
457
- | 96 | u32 | payload_size | bytes; ≡ 0 (mod 4) |
458
- | 100 | u8 | vertex_count | 3 ≤ n ≤ 128 |
459
- | 101 | u8 | triangle_count | 1 ≤ n ≤ 128 |
460
- | 102 | u16 | reserved | |
461
- | 104 | u64 | reserved | |
513
+ | 40 | [f32; 6] | subtree_aabb | object-space AABB of this cluster's vertices **and of every cluster reachable below it** through child groups (§11.17); leaves: equals `aabb`. What the runtime's per-cluster frustum cull reads |
514
+ | 64 | [f32; 6] | aabb | this cluster's own object-space AABB — GPU metadata `bounds_box`, the downstream culls, and the (future) dequantization grid |
515
+ | 88 | u16 | child_ref | index into this frame's child table; `SAME_PAGE` when the child group is in this page; `NO_CHILD` for leaves |
516
+ | 90 | u16 | child_group | group index within the child page (or this page, for `SAME_PAGE`); `NO_GROUP` for leaves |
517
+ | 92 | u32 | encoding_flags | frozen bit table in §8 |
518
+ | 96 | u32 | payload_offset | into this page's payload section; ≡ 0 (mod 4) |
519
+ | 100 | u32 | payload_size | bytes; ≡ 0 (mod 4) |
520
+ | 104 | u8 | vertex_count | 3 ≤ n ≤ 128 |
521
+ | 105 | u8 | triangle_count | 1 ≤ n ≤ 128 |
522
+ | 106 | [u8; 6] | reserved | **write 0** |
523
+
524
+ **What version 5 spent to fit `subtree_aabb` in the same 112 bytes.** `bounds_sphere`, the cluster's
525
+ own miniball, which no runtime ever read — the cut tests the LOD sphere, the HZB and the small-primitive
526
+ cull test `bounds_box`, and the builder keeps its own copy of the sphere for the object bounds and the
527
+ group centroids. And `cone_reserved`, four bytes held for a backface-cone cull that is **declined
528
+ outright** (design §9, plan §5): the earlier note kept it because reclaiming four bytes was not worth
529
+ moving `format_version`, and moving it for twenty-four was.
462
530
 
463
531
  Monotonicity (`parent_error ≥ self_error`, `parent_sphere ⊇ self_sphere`) is a build
464
532
  invariant, not a reader concern. A single-cluster asset is valid: one root page, one
@@ -522,12 +590,12 @@ derivable from the frames (§3) — standard runtime traversal never reads it.
522
590
  | 0 | u64 | frame_offset | absolute; frame per §5 |
523
591
  | 8 | u32 | fetch_size | as in the child table: the exact byte range to fetch is `[frame_offset, frame_offset + fetch_size)` |
524
592
  | 12 | u32 | decoded_size | MUST equal the frame's |
525
- | 16 | u8 | min_level | |
526
- | 17 | u8 | max_level | |
527
- | 18 | u16 | flags | bit 0: root page |
528
- | 20 | u16 | group_count | |
529
- | 22 | u16 | cluster_count | |
530
- | 24 | u64 | reserved | |
593
+ | 16 | u16 | min_level | a `u8` here and another at 17 through version 5, which is what moved the three fields below by two — into bytes this record has always held in reserve |
594
+ | 18 | u16 | max_level | |
595
+ | 20 | u16 | flags | bit 0: root page |
596
+ | 22 | u16 | group_count | |
597
+ | 24 | u16 | cluster_count | |
598
+ | 26 | [u8; 6] | reserved | |
531
599
 
532
600
  **Directory integrity**: `dir_block_checksums` holds one xxh3-64 per 128 directory
533
601
  records (one 4 KB block), seed = `asset_id_high64 XOR block_index`. Readers that use
@@ -748,8 +816,10 @@ clustering and simplification dominate regardless.
748
816
  one, and it is in page 0. Several parentless clusters would be several entry points,
749
817
  and the cut only ever enters at one; it is also what an unconverged build leaves
750
818
  behind, which is the likelier cause. All floats NaN-free.
751
- `bounds_sphere` and `aabb` contain the cluster's decoded vertices; the header's
752
- `object_sphere` and `object_bounds` contain the normalized source mesh.
819
+ `self_sphere`, `aabb` and `subtree_aabb` contain the cluster's decoded vertices; the header's
820
+ `object_sphere` and `object_bounds` contain the normalized source mesh. The `self_sphere` half is
821
+ what makes the LOD sphere usable as a conservative bound at all — the runtime's first frustum test
822
+ is on it, and a reader meeting a pre-5 container stands its cube in for `subtree_aabb`.
753
823
  8. Payload offsets and sizes are 4-byte multiples; every payload decodes/uploads
754
824
  against `payload_encoding` with no external state beyond its own cluster record.
755
825
  A leaf's `self_error` of 0 is only as honest as the simplifier's metric — see design
@@ -764,18 +834,23 @@ clustering and simplification dominate regardless.
764
834
  and the leaves partition the group table — each group reached through exactly one leaf. Each
765
835
  node's metric bounds its whole subtree: its sphere contains every child's, its `min_self_error`
766
836
  is no greater than any child's, its `max_parent_error` no less. The page header's metric equals
767
- the root node's.
837
+ the root node's. The table begins at `56 + 8·group_count` — derived, because the page header
838
+ carries no offset for it since version 6 — and the `u16` at 22 that its offset used to occupy is
839
+ zero.
768
840
  11. Every child-table entry's metric equals the header metric of the page it names. It is a copy
769
841
  read before that page is fetched, so nothing else can catch it having drifted — and a traversal
770
842
  that trusts a stale one skips a page it needed and leaves a hole.
771
843
  12. Every frame names a defined `codec` (§5); a raw frame's `stored_size` equals its
772
844
  `decoded_size`; and no frame's `decoded_size` exceeds what its codec could produce from
773
- `stored_size` bytes. Every blob decodes to exactly `decoded_size` — a short decode is a
774
- truncated page, and a page truncated to a plausible prefix is the one corruption that reads
775
- as valid geometry with pieces missing.
845
+ `stored_size` bytes. Every blob decodes to exactly `decoded_size` — neither short nor long. A
846
+ short decode is a truncated page, and a page truncated to a plausible prefix is the one
847
+ corruption that reads as valid geometry with pieces missing; a long one is a blob that would
848
+ write past what the reader allocated from `decoded_size`, and is stopped while it is producing
849
+ rather than measured afterwards.
776
850
  13. `root_page_offset = align16(256 + 32 · level_count)`; the level table's `cluster_count` and
777
851
  `group_count` columns sum to `total_clusters` and `total_groups`; every level holds at least
778
- one cluster and one group; `min_error ≤ max_error`, both finite and ≥ 0.
852
+ one cluster and one group; `min_error ≤ max_error`, both finite and ≥ 0. `level_count ≥ 1`,
853
+ and no page's `max_level` reaches it.
779
854
  14. **Page size is a bound.** When bit 0 of `feature_flags_ignorable` is set, every page's
780
855
  `decoded_size` is ≤ `nominal_page_size`, and `nominal_page_size` is non-zero. The bit is what a
781
856
  reader checks; unset, `nominal_page_size` is the advisory build parameter it used to be and
@@ -804,13 +879,29 @@ clustering and simplification dominate regardless.
804
879
  the run, rather than carrying a dedup bitmask sized by instances × groups — so the order is
805
880
  load-bearing and not presentation.
806
881
 
882
+ 17. **`subtree_aabb` bounds the subtree.** It contains the cluster's own `aabb` and, for every
883
+ cluster of the group the cluster refines into, that cluster's `subtree_aabb` — so by induction
884
+ it contains every vertex anywhere below the cluster in the DAG. A leaf's equals its `aabb`.
885
+
886
+ **Exact, on the stored values, with no tolerance.** A union of float32 extremes is a float32
887
+ extreme, so unlike the spheres there is nothing here for rounding to eat and nothing to inflate
888
+ against it. That is half of why the runtime cull is a box: the other half is that a subtree of a
889
+ surface is a flat patch, and its AABB is a fraction of the volume of any sphere around it.
890
+
891
+ **Why the subtree and not the cluster.** The runtime's per-cluster frustum test decides whether
892
+ a cluster refines into its child group, so culling it removes that whole group — and everything
893
+ under it — from the cut. A step consumes one group and produces several parents, each naming the
894
+ *whole* consumed group, so what is reachable below a cluster carries its siblings' surface too
895
+ and grows with depth. A bound that covered only the cluster would cull a parent with on-screen
896
+ descendants, and a culled subtree leaves a hole with nothing standing in over it.
897
+
807
898
  ## 12. Open
808
899
 
809
- - Page codec ids beyond raw and LZ4 (§5). LZ4 is the default and is where the cheap
810
- ratio is; a slower, denser codec (meshopt-style over the payload, deflate-family over
811
- the tables) is a per-frame `codec` id away and costs no reader that already handles a
812
- mixture. The quantized-position `payload_encoding` is the other half of the same
813
- question, and would take most of what LZ4 currently finds.
900
+ - ~~Page codec ids beyond raw and LZ4~~ — `2` is raw DEFLATE through the platform's own zlib (§5)
901
+ and is what the builder writes by default: 1.369x against LZ4's 1.295x on the same pages, for four
902
+ and a half times the decode. Still open is a codec that knows what it is compressing —
903
+ meshopt-style over the payload rather than an LZ matcher over its bytes. The quantized-position `payload_encoding` is the other half of the same
904
+ question, and would take most of what either general-purpose codec currently finds.
814
905
  - ~~Default `nominal_page_size`~~ — 64 KiB, `VGEO_DEFAULT_PAGE_SIZE`: one page size rather than
815
906
  Nanite's two, set between hiding fetch latency and paying for it in response time and in VRAM per
816
907
  resident page on a low-end device, with a floor at the largest group a build produces. Provisional
@@ -85,7 +85,7 @@ hands-off principle argues for anyway.
85
85
  possible and matter (§3).
86
86
  - **Bounds**: `Miniball` (minimal bounding sphere, iteration-capped). That is the whole list —
87
87
  **normal cones are not part of this design**. Backface cone culling is declined outright (§9,
88
- plan §5), so `cone_reserved` stays zero, and
88
+ plan §5), so `cone_reserved` was reclaimed by `format_version` 5 (format §7), and
89
89
  `bt_face_cluster_compute_normal_bounding_cone` — the `BinaryTopology` port of the old
90
90
  `TopoMesh` cone builder — has no consumer and no prospect of one.
91
91
  - **Renderer formats (the real seam)**: meshlets capped at 128 triangles / 128 vertices
@@ -140,8 +140,9 @@ Pinned:
140
140
  spanning an order of magnitude of error when the cut it takes is a *threshold* on error.
141
141
  The minimum share is not optional: on error spread thinly and continuously — a UV
142
142
  sphere, poles against equator — an octave alone holds a handful of clusters, and the
143
- round count then scales with the cluster count rather than its logarithm, which a u8
144
- `level_count` cannot survive. Measured on a 98k-triangle sphere against a sweep: growth
143
+ round count then scales with the cluster count rather than its logarithm, which no
144
+ `level_count` can survive and which a build refuses outright past
145
+ `VGeoLevelOptions.max_levels`. Measured on a 98k-triangle sphere against a sweep: growth
145
146
  4 cuts clusters-dragged-up by 38% for one extra level; growth 2 cuts it 60% for seven.
146
147
  On geometry of uniform error the band is the whole frontier and this *is* the sweep.
147
148
  - **A level is an ordinal, not a generation.** A group's band ordinal is what orders pages;
@@ -164,6 +165,19 @@ Pinned:
164
165
  group. A build that cannot reach one root **throws** — the runtime starts its cut at the
165
166
  root, and several parentless clusters is not a shape it can start from. The validator
166
167
  enforces it from the bytes: exactly one cluster with `parent_error = +∞`, in page 0.
168
+ - **A step aims at a cluster count, and a cluster is bounded by two numbers.** What the
169
+ simplifier is handed is a triangle target, but a cluster is capped at 128 triangles *and*
170
+ 128 vertices, and on geometry that has come apart — seams, small separate parts, the
171
+ patches a collapse leaves behind once it has eaten the connective tissue — there are two
172
+ or three vertices per triangle rather than a half. Halving the triangles then does not
173
+ halve the vertices, the re-cut needs as many clusters as the group consumed, and the step
174
+ is worth nothing to the round. So the re-cut is *measured* and the target tightened on
175
+ whichever of the two ceilings the attempt broke, until the step strictly shrinks its
176
+ group — tightened by the overshoot rather than by the cluster ratio, because what it
177
+ costs is fidelity and the overshoot is the least it can pay. Measured on the Zorah
178
+ sample: 187 of its 3,163 primitives reached a frontier no grouping could shrink, every
179
+ one of them this, and a 188th ran out of `VGeoLevelOptions.max_levels` inching forward a
180
+ merge a round — the same refusal to merge, spent on depth rather than on a stall.
167
181
  - **Islands merge by proximity, once adjacency has nothing left to offer.** A cluster alone
168
182
  in its connected component can never be coarsened — halving its triangles leaves one
169
183
  cluster where there was one — so a mesh of separate shells has no root at all under
@@ -209,9 +223,7 @@ Distilled from the pixel-error musings
209
223
  Pinned:
210
224
 
211
225
  - **Error is an object-space distance from the *source* surface**, not a density heuristic
212
- and not a sum of per-step deviations. It is measured before faceless vertices are cleaned
213
- away, so that a patch consumed whole — which leaves nothing behind to be measured — still
214
- costs what it cost. Vertex quadrics are built once from the source
226
+ and not a sum of per-step deviations. Vertex quadrics are built once from the source
215
227
  triangles and carried through the entire build: a survivor absorbs its victim's quadric at
216
228
  every collapse, at every round, so a vertex many rounds up still holds the planes of every
217
229
  source triangle folded into it, and evaluating that quadric at its current position
@@ -220,6 +232,51 @@ Pinned:
220
232
  `evaluate` is a sum of squared distances whose scale grows with the number of planes in the
221
233
  quadric, and its root is not a length. It remains a calibrated measure rather than a proven
222
234
  Hausdorff bound (blind to tangential drift), hence the sampled-Hausdorff gate in §3.
235
+ - **It is read at the collapses, per endpoint, and kept as a running maximum** — not as one
236
+ sweep of the surviving vertices at the end of a pass. The weight that makes the number a
237
+ length is also a divisor that grows every time a vertex absorbs another, so a vertex that
238
+ destroyed a feature and then spent the rest of the pass swallowing surface it sits exactly
239
+ on has that feature divided by all of it. The dilution therefore deepens with the DAG, and
240
+ understates most at the coarse levels where the cut spends its budget: measured on a unit
241
+ spike at the centre of a pinned grid, the same spike came back at `0.64` on a 7-vertex grid
242
+ and at `0.040` on a 33-vertex one. Read at each collapse the same spike reads `0.65`–`0.71`
243
+ at every size. Reading the two endpoints apart rather than summed is the same argument one
244
+ collapse at a time — the sum's reading is the weighted mean of the two, which averages a
245
+ small victim's residual into a large survivor's untouched history.
246
+
247
+ Nothing is given up by no longer sweeping the survivors, and it is a domination rather than
248
+ a coincidence. What the sweep reads off a survivor is its *merged* quadric at the placement
249
+ its last collapse chose, and a merged quadric's reading is the weight-weighted mean of its two
250
+ parts' readings at the same point — so it can never exceed the larger of the two already taken
251
+ there. Every value the sweep could report is one this maximum has seen or beaten, and the
252
+ maximum holds the earlier and sharper readings besides. A patch consumed whole, which leaves
253
+ behind a faceless vertex the cleanup then sweeps away, is likewise read at the collapse that
254
+ consumed it.
255
+
256
+ Each pass therefore reports what *its own* collapses cost, and a caller carrying quadrics
257
+ across passes carries the maximum across them too (`vgeo_build_group_step` across its
258
+ attempts, and the child floor below across levels). A vertex that arrives already deviating
259
+ needs no re-reading: that reading is what the pass which placed it there already returned.
260
+
261
+ Superseded: measuring after the pass, "before faceless vertices are cleaned away, so that a
262
+ patch consumed whole still costs what it cost". The measurement point was right about the
263
+ faceless vertex and wrong about everything the sweep threw away to get there.
264
+ - **A plane weighs the surface behind it, as a multiple of the mesh's mean triangle.** The
265
+ mean the error is read as has to be an average over the *surface*; over a plane count it is
266
+ an average over how the surface was cut, and a finely tessellated patch outvotes a coarse
267
+ one many times its size. Cutting one face in two along its own plane is the clean statement
268
+ of the defect — it adds no surface, and the metric heard the same plane twice. Weights are
269
+ ratios rather than areas because everything they are stated against is a ratio (the boundary
270
+ constraint is three *faces*; the attribute quadric summed with these weighs one per
271
+ triangle), and a slot holding square metres would make all of it depend on whether the asset
272
+ was authored in millimetres or kilometres. The reported error is a mean, which divides the
273
+ weights out again, so normalizing costs nothing there; it buys back every calibration.
274
+
275
+ This changes the quadric **matrix**, so it changes the placement solve and not only the
276
+ number — a behavioural change to simplification, landed on its own so it can be attributed.
277
+ `VGEO_DEFAULT_ATTRIBUTE_WEIGHT_RATIOS` was calibrated against the diluted reading and is
278
+ **not** re-tuned here; it needs re-tuning against this one, separately.
279
+
223
280
  - **Composition across levels does not happen**, and that is the point of carrying quadrics.
224
281
  The measured value is already deviation from the source; a step takes `max(measured, max(e
225
282
  of child groups))`, where the floor exists only to impose monotonicity — the accumulated
@@ -358,16 +415,19 @@ Pinned:
358
415
  in the file (coarse-first order is topological); non-root pages hold clusters of a
359
416
  single level band. Build-validated.
360
417
  - **Compression must not break random access.** Transparent HTTP compression does not
361
- compose with range requests, so compression is per-page *inside* the container. Two codecs
362
- are defined and both shipped — `raw` and a bare LZ4 block — chosen **per frame** rather than
363
- per file, so a page that would not shrink is stored verbatim and says so. Measured, LZ4 is
364
- worth 1.12x–1.18x on the Stanford models, and the reason it is not more is the reason to stop
365
- here: the payload is float32 positions and packed attribute words, and it does not compress.
366
- Quantization (§2) is the lever, not the codec.
418
+ compose with range requests, so compression is per-page *inside* the container. Three codecs
419
+ are defined and all three shipped — `raw`, a bare LZ4 block, and a bare DEFLATE stream through
420
+ the platform's own zlib — chosen **per frame** rather than per file, so a page that would not
421
+ shrink is stored verbatim and says so. Measured, LZ4 is worth 1.12x–1.18x on the Stanford
422
+ models and deflate about seven points more for four and a half times the decode; deflate is what
423
+ the builder writes, because a build happens once and a fetch happens forever. The reason neither
424
+ is worth more is the reason to stop here: the payload is float32 positions and packed attribute
425
+ words, and it does not compress. Quantization (§2) is the lever, not the codec.
367
426
  - **Coarse-first layout**: pages ordered so a plain prefix read of the file yields a
368
427
  complete coarse asset — progressive load without a feedback loop.
369
428
 
370
- Open: a denser page codec than LZ4, if quantization leaves one worth having;
429
+ Open: a page codec that knows what it is compressing — meshopt-style over the payload rather
430
+ than an LZ matcher over its bytes — if quantization leaves one worth having;
371
431
  per-attribute quantization widths (cluster-local grids); relationship to
372
432
  `MeshletGeometrySerializationAdapter` (extend vs parallel).
373
433
 
@@ -547,7 +607,7 @@ Pinned:
547
607
  `bt_mesh_validate` → level-0 clustering (+ CC split) → the §3 round loop → per-cluster
548
608
  encode → page assignment (level-banded, DAG + spatial locality, acyclicity check) →
549
609
  container emit. The encode is the miniball sphere, the AABB, and `SHADE_MESHLET_V1`
550
- attributes at their shipped widths (format §8): `cone_reserved` is zero because cone culling
610
+ attributes at their shipped widths (format §8): there is no cone field because cone culling
551
611
  is declined (§9), and positions are raw float32 because quantization is a `payload_encoding`
552
612
  that does not exist yet.
553
613
  - **The weld tolerance is scale-relative**, a fraction of each geometry's bounding-box
@@ -593,8 +653,8 @@ canonicalizing them is a preprocessor's job).
593
653
 
594
654
  - **Backface normal-cone culling — declined outright, not deferred.** The two-pass HZB already
595
655
  rejects what a cone would, on evidence rather than on a bound; see plan §5 for the mechanism
596
- and the reports behind it. `cone_reserved` stays a zeroed reserved field (format §7). This is
597
- the one entry here that is not a "v1" qualifier.
656
+ and the reports behind it. `cone_reserved` was a zeroed reserved field until `format_version` 5
657
+ spent it on `subtree_aabb` (format §7). This is the one entry here that is not a "v1" qualifier.
598
658
  - Skinned / morphing / WPO meshes through the VG path (static geometry only).
599
659
  - **Non-opaque VG instances.** The cut runs beside the mesh→meshlet expansion of the *opaque*
600
660
  rasterization paths, and the transparent and alpha-tested bucket path
@@ -452,9 +452,9 @@ attacked:
452
452
  library exposing cone data, and Remedy report the same for Northlight. Taken together with
453
453
  the mechanism above, there is nothing left to measure.
454
454
 
455
- Consequences, so that nobody re-derives them: `cone_reserved` stays a zeroed reserved u32
456
- (format §7) — reclaiming 4 bytes of 112 is not worth a `format_version` move, and the page
457
- codec compresses a constant-zero column away. `bt_face_cluster_compute_normal_bounding_cone`
455
+ Consequences, so that nobody re-derives them: `cone_reserved` was a zeroed reserved u32 until
456
+ `format_version` 5 (format §7) — reclaiming 4 bytes of 112 was never worth a version move on its
457
+ own, and it went when `subtree_aabb` needed 24 and the version moved anyway. `bt_face_cluster_compute_normal_bounding_cone`
458
458
  has no consumer and no prospect of one.
459
459
  - **Fixed-size residency slots** `[M §2.5]`. Micron gives every resident patch one slot of
460
460
  `MICRON_PATCH_SIZE_MAX × 3` vertices with occupancy in a BitSet: no allocator, no