@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
@@ -17,6 +17,14 @@ import { vgeo_split_face_set } from "./vgeo_split_face_set.js";
17
17
  * has already been chosen for proximity, so packing inside one cannot reach further than the group
18
18
  * does.
19
19
  *
20
+ * The merge is two passes, and the caps decide which one is used rather than taste. The first walks
21
+ * the curve, so every cluster it makes is a run of it holding pieces that were beside each other —
22
+ * and over a real asset that is almost always all it takes: across a build of the Zorah sample it
23
+ * lands on the fewest clusters both caps allow in 97.6% of the re-cuts. The second pass is for the
24
+ * rest. Where the curve costs a whole extra cluster, the pieces are offered again largest first,
25
+ * into whichever cluster still has room. Reaching past a neighbour widens what a cluster carries, so
26
+ * it has to buy something; one cluster fewer is the price at which it does.
27
+ *
20
28
  * @author Alex Goldring
21
29
  * @copyright Company Named Limited (c) 2026
22
30
  */
@@ -25,22 +33,30 @@ const scratch_triangle = new Uint32Array(3);
25
33
  const scratch_coordinate = new Float32Array(3);
26
34
 
27
35
  /**
28
- * The mesh vertices a set of dense face-graph vertices touches, deduplicated.
36
+ * The **wedges** a set of dense face-graph vertices touches, deduplicated.
37
+ *
38
+ * Wedges and not mesh vertices, because a bin is a meshlet and a meshlet carries one record per
39
+ * wedge — see {@link VGeoFaceGraph#count_unique_wedges}, which is the same question asked of a
40
+ * whole part rather than of a piece being packed into one. The set is kept rather than counted here
41
+ * because the packer needs to know how much two pieces *overlap*, not only how big each is.
29
42
  *
30
43
  * @param {VGeoFaceGraph} face_graph
31
44
  * @param {number[]} members
32
45
  * @returns {Set<number>}
33
46
  */
34
- function unique_vertices(face_graph, members) {
47
+ function unique_wedges(face_graph, members) {
35
48
  const result = new Set();
36
49
 
50
+ const mesh = face_graph.mesh;
51
+ const wedges = face_graph.wedges;
52
+
37
53
  for (const member of members) {
38
- bt_face_read_triangle_vertices(
39
- scratch_triangle, face_graph.mesh, face_graph.vertex_face_ids[member]
40
- );
54
+ let loop = mesh.face_read_loop(face_graph.vertex_face_ids[member]);
41
55
 
42
- for (let i = 0; i < 3; i++) {
43
- result.add(scratch_triangle[i]);
56
+ for (let corner = 0; corner < 3; corner++) {
57
+ result.add(wedges.find(wedges.of_loop[loop]));
58
+
59
+ loop = mesh.loop_read_next(loop);
44
60
  }
45
61
  }
46
62
 
@@ -84,26 +100,13 @@ function piece_centroid(result, result_offset, face_graph, members) {
84
100
  }
85
101
 
86
102
  /**
87
- * Merge under-filled pieces into shared clusters, walking them in Morton order so that whatever ends
88
- * up together was near each other to begin with.
89
- *
90
- * Next-fit rather than best-fit: the curve already put spatial neighbours side by side, and letting a
91
- * piece jump backwards to top up an earlier bin would pull distant geometry into it for the sake of
92
- * a few triangles of fill.
103
+ * The pieces in Morton order of their centroids, so that neighbours in it were neighbours in space.
93
104
  *
94
105
  * @param {VGeoFaceGraph} face_graph
95
- * @param {number[][]} pieces each already within both caps
96
- * @param {number} max_faces
97
- * @param {number} max_vertices
98
- * @returns {number[][]}
106
+ * @param {number[][]} pieces
107
+ * @returns {number[]} indices into `pieces`
99
108
  */
100
- function pack_pieces(face_graph, pieces, max_faces, max_vertices) {
101
-
102
- if (pieces.length < 2) {
103
- // nothing to merge, pass through
104
- return pieces;
105
- }
106
-
109
+ function curve_order(face_graph, pieces) {
107
110
  const centroids = new Float32Array(pieces.length * 3);
108
111
 
109
112
  pieces.forEach((piece, index) => piece_centroid(centroids, index * 3, face_graph, piece));
@@ -125,61 +128,213 @@ function pack_pieces(face_graph, pieces, max_faces, max_vertices) {
125
128
 
126
129
  order.sort((a, b) => (codes[a] - codes[b]) || (pieces[a][0] - pieces[b][0]));
127
130
 
128
- /**
129
- *
130
- * @type {number[][]}
131
- */
131
+ return order;
132
+ }
133
+
134
+ /**
135
+ * A cluster under construction: which pieces are in it, and both of the numbers it is capped on.
136
+ *
137
+ * @param {number} index of the piece it starts from
138
+ * @param {number[]} piece
139
+ * @param {Set<number>} vertices the piece touches
140
+ * @returns {{pieces: number[], faces: number, vertices: Set<number>}}
141
+ */
142
+ function open_bin(index, piece, vertices) {
143
+ return { pieces: [index], faces: piece.length, vertices: new Set(vertices) };
144
+ }
145
+
146
+ /**
147
+ * Whether a piece can go into a bin without breaking either cap.
148
+ *
149
+ * The vertex side is a union rather than a sum: two pieces cut out of the same component share the
150
+ * vertices along the cut, and charging for those twice would refuse a merge that fits.
151
+ *
152
+ * @param {{faces: number, vertices: Set<number>}} bin
153
+ * @param {number[]} piece
154
+ * @param {Set<number>} vertices the piece touches
155
+ * @param {number} max_faces
156
+ * @param {number} max_vertices
157
+ * @returns {boolean}
158
+ */
159
+ function bin_accepts(bin, piece, vertices, max_faces, max_vertices) {
160
+ if (bin.faces + piece.length > max_faces) {
161
+ return false;
162
+ }
163
+
164
+ let added = 0;
165
+
166
+ for (const vertex of vertices) {
167
+ if (!bin.vertices.has(vertex)) {
168
+ added++;
169
+ }
170
+ }
171
+
172
+ return bin.vertices.size + added <= max_vertices;
173
+ }
174
+
175
+ /**
176
+ * @param {{pieces: number[], faces: number, vertices: Set<number>}} bin
177
+ * @param {number} index of the piece
178
+ * @param {number[]} piece
179
+ * @param {Set<number>} vertices the piece touches
180
+ */
181
+ function bin_add(bin, index, piece, vertices) {
182
+ bin.pieces.push(index);
183
+ bin.faces += piece.length;
184
+
185
+ for (const vertex of vertices) {
186
+ bin.vertices.add(vertex);
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Walk the curve, opening a new cluster whenever the next piece does not fit in the one already
192
+ * open.
193
+ *
194
+ * Next-fit rather than best-fit: the curve already put spatial neighbours side by side, and letting a
195
+ * piece jump backwards to top up an earlier bin would pull distant geometry into it for the sake of
196
+ * a few triangles of fill. Every cluster this produces is a contiguous run of the curve.
197
+ *
198
+ * @param {number[][]} pieces
199
+ * @param {Set<number>[]} piece_vertices one entry per piece
200
+ * @param {number[]} order indices into `pieces`, along the curve
201
+ * @param {number} max_faces
202
+ * @param {number} max_vertices
203
+ * @returns {{pieces: number[], faces: number, vertices: Set<number>}[]}
204
+ */
205
+ function fill_along_curve(pieces, piece_vertices, order, max_faces, max_vertices) {
132
206
  const result = [];
133
207
 
208
+ for (const index of order) {
209
+ const bin = result[result.length - 1];
210
+
211
+ if (
212
+ bin !== undefined
213
+ && bin_accepts(bin, pieces[index], piece_vertices[index], max_faces, max_vertices)
214
+ ) {
215
+ bin_add(bin, index, pieces[index], piece_vertices[index]);
216
+
217
+ continue;
218
+ }
219
+
220
+ result.push(open_bin(index, pieces[index], piece_vertices[index]));
221
+ }
222
+
223
+ return result;
224
+ }
225
+
226
+ /**
227
+ * Offer the pieces largest first, each into the first cluster that will take it.
228
+ *
229
+ * Largest first is the whole of the difference, and for the usual reason: a cluster already topped up
230
+ * with small pieces has no room left for a big one, so the big ones have to choose first. Two 66s and
231
+ * a 40 and a 34 are two clusters when the 66s choose first and three when they do not, and no walk of
232
+ * the curve finds the pairing because the pieces that belong together are not neighbours on it.
233
+ *
234
+ * The clusters are still tried in the curve's order, so a piece lands in the earliest — nearest —
235
+ * one that can hold it.
236
+ *
237
+ * @param {number[][]} pieces
238
+ * @param {Set<number>[]} piece_vertices one entry per piece
239
+ * @param {number[]} order indices into `pieces`, along the curve
240
+ * @param {number} max_faces
241
+ * @param {number} max_vertices
242
+ * @returns {{pieces: number[], faces: number, vertices: Set<number>}[]}
243
+ */
244
+ function fill_largest_first(pieces, piece_vertices, order, max_faces, max_vertices) {
134
245
  /**
135
- *
136
- * @type {number[]|undefined}
137
- */
138
- let bin = undefined;
139
- /**
140
- *
141
- * @type {Set<number>|undefined}
246
+ * `piece -> its place on the curve`, so that pieces of the same size keep the curve's order and
247
+ * the pack stays a function of the geometry rather than of the sort's own tie-breaking.
248
+ * @type {Int32Array}
142
249
  */
143
- let bin_vertices = undefined;
250
+ const place = new Int32Array(pieces.length);
144
251
 
145
- for (const index of order) {
146
- const piece = pieces[index];
252
+ order.forEach((index, position) => {
253
+ place[index] = position;
254
+ });
147
255
 
148
- if (bin !== undefined && (bin.length + piece.length) <= max_faces) {
149
- const piece_vertices = unique_vertices(face_graph, piece);
256
+ // How much of a cluster a piece costs, on whichever of the two caps it loads most.
257
+ const load = (index) => Math.max(
258
+ pieces[index].length / max_faces, piece_vertices[index].size / max_vertices
259
+ );
150
260
 
151
- let added = 0;
261
+ const by_size = order.slice();
152
262
 
153
- for (const vertex of piece_vertices) {
154
- if (!bin_vertices.has(vertex)) {
155
- added++;
156
- }
157
- }
263
+ by_size.sort((a, b) => (load(b) - load(a)) || (place[a] - place[b]));
158
264
 
159
- if (bin_vertices.size + added <= max_vertices) {
160
- for (const member of piece) {
161
- bin.push(member);
162
- }
265
+ const result = [];
163
266
 
164
- for (const vertex of piece_vertices) {
165
- bin_vertices.add(vertex);
166
- }
267
+ for (const index of by_size) {
268
+ let placed = false;
167
269
 
270
+ for (const bin of result) {
271
+ if (!bin_accepts(bin, pieces[index], piece_vertices[index], max_faces, max_vertices)) {
168
272
  continue;
169
273
  }
274
+
275
+ bin_add(bin, index, pieces[index], piece_vertices[index]);
276
+
277
+ placed = true;
278
+
279
+ break;
170
280
  }
171
281
 
172
- bin = piece.slice();
173
- bin_vertices = unique_vertices(face_graph, piece);
282
+ if (!placed) {
283
+ result.push(open_bin(index, pieces[index], piece_vertices[index]));
284
+ }
285
+ }
174
286
 
175
- result.push(bin);
287
+ return result;
288
+ }
289
+
290
+ /**
291
+ * Merge under-filled pieces into shared clusters.
292
+ *
293
+ * @param {VGeoFaceGraph} face_graph
294
+ * @param {number[][]} pieces each already within both caps
295
+ * @param {number} max_faces
296
+ * @param {number} max_vertices
297
+ * @param {number} floor fewest clusters both caps allow for the set as a whole
298
+ * @returns {number[][]}
299
+ */
300
+ function pack_pieces(face_graph, pieces, max_faces, max_vertices, floor) {
301
+
302
+ if (pieces.length < 2) {
303
+ // nothing to merge, pass through
304
+ return pieces;
176
305
  }
177
306
 
178
- for (const packed of result) {
179
- packed.sort((a, b) => a - b);
307
+ const piece_vertices = pieces.map((piece) => unique_wedges(face_graph, piece));
308
+
309
+ const order = curve_order(face_graph, pieces);
310
+
311
+ let bins = fill_along_curve(pieces, piece_vertices, order, max_faces, max_vertices);
312
+
313
+ if (bins.length > floor) {
314
+ // The caps would have held this in fewer clusters and walking the curve did not find how.
315
+ // Nothing local says which pieces belong together, so the only way to learn whether the
316
+ // extra cluster was necessary is to pack again with size deciding instead of position, and
317
+ // to keep that only if it turns out it was not.
318
+ const by_size = fill_largest_first(pieces, piece_vertices, order, max_faces, max_vertices);
319
+
320
+ if (by_size.length < bins.length) {
321
+ bins = by_size;
322
+ }
180
323
  }
181
324
 
182
- return result;
325
+ return bins.map((bin) => {
326
+ const packed = [];
327
+
328
+ for (const index of bin.pieces) {
329
+ for (const member of pieces[index]) {
330
+ packed.push(member);
331
+ }
332
+ }
333
+
334
+ packed.sort((a, b) => a - b);
335
+
336
+ return packed;
337
+ });
183
338
  }
184
339
 
185
340
  /**
@@ -196,9 +351,18 @@ function pack_pieces(face_graph, pieces, max_faces, max_vertices) {
196
351
  * @returns {number[][]} clusters within both caps, ordered by their lowest member
197
352
  */
198
353
  export function vgeo_split_face_set_packed(face_graph, members, max_faces, max_vertices) {
354
+ // What a perfect packing of this set would come back with. It is a bound and not always a
355
+ // reachable one — indivisible pieces need not add up to it — but it is the only thing that says
356
+ // whether the merge left a cluster on the table, and so the only thing that can decide whether
357
+ // the merge is worth attempting a second way.
358
+ const floor = Math.max(
359
+ Math.ceil(members.length / max_faces),
360
+ Math.ceil(face_graph.count_unique_wedges(members) / max_vertices)
361
+ );
362
+
199
363
  const packed = pack_pieces(
200
364
  face_graph, vgeo_split_face_set(face_graph, members, max_faces, max_vertices),
201
- max_faces, max_vertices
365
+ max_faces, max_vertices, floor
202
366
  );
203
367
 
204
368
  packed.sort((a, b) => a[0] - b[0]);
@@ -17,8 +17,23 @@ export class VGeoGatheredFaces {
17
17
  indices: Uint32Array;
18
18
  /**
19
19
  * Vertex ids in the mesh this was pulled out of, one per local vertex, in first-use order.
20
+ *
21
+ * **Not unique.** One entry per *wedge*, so a vertex whose corners shade two ways appears twice
22
+ * — which is what a seam has always cost, in any renderer, and is where it is paid.
20
23
  * @type {Uint32Array}
21
24
  */
22
25
  vertex_ids: Uint32Array;
26
+ /**
27
+ * The wedge each local vertex is, named in the mesh this was pulled out of. Parallel to
28
+ * {@link vertex_ids}, and unique where that is not.
29
+ * @type {Uint32Array}
30
+ */
31
+ wedge_ids: Uint32Array;
32
+ /**
33
+ * One corner per output vertex — the loop it was first seen at — for the appearance channels to
34
+ * be read through. They live on corners, so a vertex alone does not address them.
35
+ * @type {Uint32Array}
36
+ */
37
+ attribute_ids: Uint32Array;
23
38
  }
24
39
  //# sourceMappingURL=VGeoGatheredFaces.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"VGeoGatheredFaces.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH;IACI;;;OAGG;IACH,WAFU,YAAY,CAEU;IAEhC;;;OAGG;IACH,SAFU,WAAW,CAEQ;IAE7B;;;OAGG;IACH,YAFU,WAAW,CAEW;CACnC"}
1
+ {"version":3,"file":"VGeoGatheredFaces.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH;IACI;;;OAGG;IACH,WAFU,YAAY,CAEU;IAEhC;;;OAGG;IACH,SAFU,WAAW,CAEQ;IAE7B;;;;;;OAMG;IACH,YAFU,WAAW,CAEW;IAEhC;;;;OAIG;IACH,WAFU,WAAW,CAEU;IAE/B;;;;OAIG;IACH,eAFU,WAAW,CAEc;CACtC"}
@@ -19,7 +19,24 @@ export class VGeoGatheredFaces {
19
19
 
20
20
  /**
21
21
  * Vertex ids in the mesh this was pulled out of, one per local vertex, in first-use order.
22
+ *
23
+ * **Not unique.** One entry per *wedge*, so a vertex whose corners shade two ways appears twice
24
+ * — which is what a seam has always cost, in any renderer, and is where it is paid.
22
25
  * @type {Uint32Array}
23
26
  */
24
27
  vertex_ids = new Uint32Array(0);
28
+
29
+ /**
30
+ * The wedge each local vertex is, named in the mesh this was pulled out of. Parallel to
31
+ * {@link vertex_ids}, and unique where that is not.
32
+ * @type {Uint32Array}
33
+ */
34
+ wedge_ids = new Uint32Array(0);
35
+
36
+ /**
37
+ * One corner per output vertex — the loop it was first seen at — for the appearance channels to
38
+ * be read through. They live on corners, so a vertex alone does not address them.
39
+ * @type {Uint32Array}
40
+ */
41
+ attribute_ids = new Uint32Array(0);
25
42
  }
@@ -16,5 +16,22 @@ export class VGeoSubmesh {
16
16
  * @type {Uint32Array}
17
17
  */
18
18
  source_vertex_ids: Uint32Array;
19
+ /**
20
+ * Which corners of {@link mesh} shade as one, in ids local to it. Mutated by the simplifier as
21
+ * they merge, which is why a local id is what the carried values and quadrics are indexed by.
22
+ * @type {BtWedgeSet}
23
+ */
24
+ wedges: BtWedgeSet;
25
+ /**
26
+ * `source_wedge_ids[local wedge] = wedge id in the mesh this was extracted from`, the companion
27
+ * of {@link source_vertex_ids} and what carries an accumulated attribute quadric across the
28
+ * seam.
29
+ *
30
+ * Survives simplification the way the vertex map does, and for a sharper reason: **a collapse
31
+ * only ever merges wedges, never splits one**, so a local id that is still its own root after a
32
+ * step names exactly the source wedge it always did.
33
+ * @type {Uint32Array}
34
+ */
35
+ source_wedge_ids: Uint32Array;
19
36
  }
20
37
  //# sourceMappingURL=VGeoSubmesh.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"VGeoSubmesh.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH;IACI;;OAEG;IACH,0BAAY;IAEZ;;;;;OAKG;IACH,mBAFU,WAAW,CAEkB;CAC1C"}
1
+ {"version":3,"file":"VGeoSubmesh.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH;IACI;;OAEG;IACH,0BAAY;IAEZ;;;;;OAKG;IACH,mBAFU,WAAW,CAEkB;IAEvC;;;;OAIG;IACH,mBAAc;IAEd;;;;;;;;;OASG;IACH,kBAFU,WAAW,CAEiB;CACzC"}
@@ -17,4 +17,23 @@ export class VGeoSubmesh {
17
17
  * @type {Uint32Array}
18
18
  */
19
19
  source_vertex_ids = new Uint32Array(0);
20
+
21
+ /**
22
+ * Which corners of {@link mesh} shade as one, in ids local to it. Mutated by the simplifier as
23
+ * they merge, which is why a local id is what the carried values and quadrics are indexed by.
24
+ * @type {BtWedgeSet}
25
+ */
26
+ wedges = null;
27
+
28
+ /**
29
+ * `source_wedge_ids[local wedge] = wedge id in the mesh this was extracted from`, the companion
30
+ * of {@link source_vertex_ids} and what carries an accumulated attribute quadric across the
31
+ * seam.
32
+ *
33
+ * Survives simplification the way the vertex map does, and for a sharper reason: **a collapse
34
+ * only ever merges wedges, never splits one**, so a local id that is still its own root after a
35
+ * step names exactly the source wedge it always did.
36
+ * @type {Uint32Array}
37
+ */
38
+ source_wedge_ids = new Uint32Array(0);
20
39
  }
@@ -1,14 +1,23 @@
1
1
  /**
2
2
  * Extract a face set into a standalone mesh, attributes and all.
3
3
  *
4
+ * **Wedges are not vertices here.** The gather deduped on the wedge, because that is what a cluster
5
+ * payload's vertices are; a mesh's are not. Two wedges of one vertex are one point and one piece of
6
+ * connectivity, and giving them a vertex each would shred face adjacency along every seam — which
7
+ * is the move `WEDGE_PLAN_2026_09_18.md` §8 rejects and the reason the weld exists at all. So the
8
+ * gather's output is folded back onto one vertex per position and the wedges travel on the corners,
9
+ * where they belong.
10
+ *
4
11
  * @param {VirtualGeometryMesh} source
5
12
  * @param {number[]} face_ids
13
+ * @param {BtWedgeSet} source_wedges which corners of `source` shade as one
6
14
  * @returns {VGeoSubmesh}
7
15
  *
8
16
  * @author Alex Goldring
9
17
  * @copyright Company Named Limited (c) 2026
10
18
  */
11
- export function vgeo_extract_submesh(source: VirtualGeometryMesh, face_ids: number[]): VGeoSubmesh;
19
+ export function vgeo_extract_submesh(source: VirtualGeometryMesh, face_ids: number[], source_wedges: BtWedgeSet): VGeoSubmesh;
12
20
  import { VirtualGeometryMesh } from "../mesh/VirtualGeometryMesh.js";
21
+ import { BtWedgeSet } from "../../../../../../core/geom/3d/topology/struct/binary/BtWedgeSet.js";
13
22
  import { VGeoSubmesh } from "./VGeoSubmesh.js";
14
23
  //# sourceMappingURL=vgeo_extract_submesh.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vgeo_extract_submesh.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.js"],"names":[],"mappings":"AAUA;;;;;;;;;GASG;AACH,6CAPW,mBAAmB,YACnB,MAAM,EAAE,GACN,WAAW,CAyBvB;oCAhCmC,gCAAgC;4BADxC,kBAAkB"}
1
+ {"version":3,"file":"vgeo_extract_submesh.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.js"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;;GAiBG;AACH,6CARW,mBAAmB,YACnB,MAAM,EAAE,iBACR,UAAU,GACR,WAAW,CA4GvB;oCA3HmC,gCAAgC;2BARzC,qEAAqE;4BAOpE,kBAAkB"}
@@ -1,8 +1,11 @@
1
- import { BinaryTopology } from "../../../../../../core/geom/3d/topology/struct/binary/BinaryTopology.js";
1
+ import {
2
+ BinaryTopology, NULL_POINTER
3
+ } from "../../../../../../core/geom/3d/topology/struct/binary/BinaryTopology.js";
4
+ import { BtWedgeSet } from "../../../../../../core/geom/3d/topology/struct/binary/BtWedgeSet.js";
2
5
  import {
3
6
  bt_mesh_from_indexed_geometry
4
7
  } from "../../../../../../core/geom/3d/topology/struct/binary/io/bt_mesh_from_indexed_geometry.js";
5
- import { vgeo_layers_copy_vertex } from "../../format/attribute/vgeo_layers_copy_vertex.js";
8
+ import { vgeo_layers_copy_corner } from "../../format/attribute/vgeo_layers_copy_corner.js";
6
9
  import { vgeo_layers_like } from "../../format/attribute/vgeo_layers_like.js";
7
10
  import { vgeo_gather_faces } from "./vgeo_gather_faces.js";
8
11
  import { VGeoSubmesh } from "./VGeoSubmesh.js";
@@ -11,31 +14,122 @@ import { VirtualGeometryMesh } from "../mesh/VirtualGeometryMesh.js";
11
14
  /**
12
15
  * Extract a face set into a standalone mesh, attributes and all.
13
16
  *
17
+ * **Wedges are not vertices here.** The gather deduped on the wedge, because that is what a cluster
18
+ * payload's vertices are; a mesh's are not. Two wedges of one vertex are one point and one piece of
19
+ * connectivity, and giving them a vertex each would shred face adjacency along every seam — which
20
+ * is the move `WEDGE_PLAN_2026_09_18.md` §8 rejects and the reason the weld exists at all. So the
21
+ * gather's output is folded back onto one vertex per position and the wedges travel on the corners,
22
+ * where they belong.
23
+ *
14
24
  * @param {VirtualGeometryMesh} source
15
25
  * @param {number[]} face_ids
26
+ * @param {BtWedgeSet} source_wedges which corners of `source` shade as one
16
27
  * @returns {VGeoSubmesh}
17
28
  *
18
29
  * @author Alex Goldring
19
30
  * @copyright Company Named Limited (c) 2026
20
31
  */
21
- export function vgeo_extract_submesh(source, face_ids) {
22
- const gathered = vgeo_gather_faces(source, face_ids);
32
+ export function vgeo_extract_submesh(source, face_ids, source_wedges) {
33
+ const gathered = vgeo_gather_faces(source, face_ids, source_wedges);
34
+
35
+ const wedge_count = gathered.wedge_ids.length;
36
+
37
+ /**
38
+ * `source vertex id -> local vertex id`.
39
+ * @type {Map<number, number>}
40
+ */
41
+ const local_of_vertex = new Map();
42
+
43
+ /**
44
+ * The local vertex each gathered wedge sits at.
45
+ * @type {Uint32Array}
46
+ */
47
+ const vertex_of_wedge = new Uint32Array(wedge_count);
48
+
49
+ const source_vertex_ids = [];
50
+ const positions = [];
51
+
52
+ gathered.vertex_ids.forEach((vertex, wedge) => {
53
+ let local = local_of_vertex.get(vertex);
54
+
55
+ if (local === undefined) {
56
+ local = source_vertex_ids.length;
57
+
58
+ local_of_vertex.set(vertex, local);
59
+ source_vertex_ids.push(vertex);
60
+
61
+ positions.push(
62
+ gathered.positions[wedge * 3],
63
+ gathered.positions[wedge * 3 + 1],
64
+ gathered.positions[wedge * 3 + 2]
65
+ );
66
+ }
67
+
68
+ vertex_of_wedge[wedge] = local;
69
+ });
23
70
 
24
71
  const topology = new BinaryTopology();
25
72
 
26
73
  // Before the vertices, so no record has to be widened. See {@link VirtualGeometryMesh.from_geometry}.
27
74
  const layers = vgeo_layers_like(topology, source.layers);
28
75
 
29
- bt_mesh_from_indexed_geometry(topology, gathered.indices, gathered.positions);
76
+ bt_mesh_from_indexed_geometry(
77
+ topology,
78
+ Uint32Array.from(gathered.indices, (wedge) => vertex_of_wedge[wedge]),
79
+ Float32Array.from(positions)
80
+ );
30
81
 
31
- gathered.vertex_ids.forEach((source_vertex, local) => {
32
- vgeo_layers_copy_vertex(topology, source.topology, source_vertex, local);
33
- });
82
+ if (topology.faces.count() !== face_ids.length) {
83
+ // The corner walk below reads face `t` as the `t`th triangle of the index list, so a builder
84
+ // that dropped or reordered one would silently hand every corner the wrong appearance. A
85
+ // thrown build beats a wrong asset, and this cannot be an `assert` for exactly that reason:
86
+ // asserts are stripped from what ships.
87
+ throw new Error(
88
+ `extracting ${face_ids.length} faces produced ${topology.faces.count()}, so the corners `
89
+ + `of the result cannot be matched to the corners they came from`
90
+ );
91
+ }
92
+
93
+ const wedges = new BtWedgeSet();
94
+
95
+ wedges.count = wedge_count;
96
+ wedges.parent = Uint32Array.from({ length: wedge_count }, (_, wedge) => wedge);
97
+ wedges.next_of_wedge = new Uint32Array(wedge_count).fill(NULL_POINTER);
98
+ wedges.first_of_vertex = new Uint32Array(topology.vertices.size).fill(NULL_POINTER);
99
+ wedges.of_loop = new Uint32Array(topology.loops.size).fill(NULL_POINTER);
100
+
101
+ for (let wedge = 0; wedge < wedge_count; wedge++) {
102
+ wedges.attach(wedge, vertex_of_wedge[wedge]);
103
+ }
104
+
105
+ /*
106
+ Corner by corner, through the wedge each one names — which is the copy §6.1 could not make.
107
+ Going through the *vertex* was exact only while every corner of a vertex agreed; it does not
108
+ agree any more, and that is the point. The two meshes' loops are matched up here because the
109
+ faces were built from this very index list, in this order.
110
+ */
111
+ for (let face = 0; face < face_ids.length; face++) {
112
+ let loop = topology.face_read_loop(face);
113
+
114
+ for (let corner = 0; corner < 3; corner++) {
115
+ const wedge = gathered.indices[face * 3 + corner];
116
+
117
+ wedges.of_loop[loop] = wedge;
118
+
119
+ vgeo_layers_copy_corner(
120
+ topology, source.topology, gathered.attribute_ids[wedge], loop
121
+ );
122
+
123
+ loop = topology.loop_read_next(loop);
124
+ }
125
+ }
34
126
 
35
127
  const result = new VGeoSubmesh();
36
128
 
37
129
  result.mesh = new VirtualGeometryMesh(topology, layers);
38
- result.source_vertex_ids = gathered.vertex_ids;
130
+ result.source_vertex_ids = Uint32Array.from(source_vertex_ids);
131
+ result.wedges = wedges;
132
+ result.source_wedge_ids = gathered.wedge_ids;
39
133
 
40
134
  return result;
41
135
  }
@@ -1,12 +1,24 @@
1
1
  /**
2
- * Gather a face set: unique vertices in first-use order, local indices, coordinates copied out.
2
+ * Gather a face set: unique **wedges** in first-use order, local indices, coordinates copied out,
3
+ * and one corner per output vertex for the appearance to be read through.
4
+ *
5
+ * A wedge, not a vertex, and that is the whole of what a seam costs. Two corners of one vertex that
6
+ * shade differently cannot share an output vertex: the payload carries one value per vertex, so a
7
+ * hard edge or a texture chart boundary has to be two of them. It costs exactly what it has always
8
+ * cost anywhere else — a seam is an extra vertex in every renderer ever written — and it costs it
9
+ * *here*, at the gather, rather than in the topology, where splitting would shred face adjacency
10
+ * (`WEDGE_PLAN_2026_09_18.md` §8).
11
+ *
12
+ * A mesh with no seams has one wedge per vertex, every corner of a vertex resolves to it, and this
13
+ * dedupes on the vertex exactly as it always did.
3
14
  *
4
15
  * First-use order is what makes the result depend only on the face list, not on the pool's history.
5
16
  *
6
17
  * @param {VirtualGeometryMesh} mesh
7
18
  * @param {number[]} face_ids allocated triangular faces
19
+ * @param {BtWedgeSet} wedges which corners of each vertex shade as one
8
20
  * @returns {VGeoGatheredFaces}
9
21
  */
10
- export function vgeo_gather_faces(mesh: VirtualGeometryMesh, face_ids: number[]): VGeoGatheredFaces;
22
+ export function vgeo_gather_faces(mesh: VirtualGeometryMesh, face_ids: number[], wedges: BtWedgeSet): VGeoGatheredFaces;
11
23
  import { VGeoGatheredFaces } from "./VGeoGatheredFaces.js";
12
24
  //# sourceMappingURL=vgeo_gather_faces.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vgeo_gather_faces.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.js"],"names":[],"mappings":"AAcA;;;;;;;;GAQG;AACH,uEAHW,MAAM,EAAE,GACN,iBAAiB,CAiD7B;kCAlEiC,wBAAwB"}
1
+ {"version":3,"file":"vgeo_gather_faces.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,uEAJW,MAAM,EAAE,uBAEN,iBAAiB,CAgE7B;kCA5FiC,wBAAwB"}