@woosh/meep-engine 3.0.2 → 3.2.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 (1823) hide show
  1. package/LICENSE +188 -188
  2. package/README.md +152 -145
  3. package/editor/Editor.js +598 -598
  4. package/editor/EditorCameraNavigation.js +205 -205
  5. package/editor/EditorKeyMap.js +182 -182
  6. package/editor/SelectionVisualizer.js +127 -127
  7. package/editor/actions/concrete/ActionInvalidateSampler.js +27 -27
  8. package/editor/actions/concrete/PatchTerrainHeightAction.js +85 -85
  9. package/editor/camera/camera_framing.js +104 -104
  10. package/editor/clipboard.js +184 -184
  11. package/editor/ecs/component/editors/ObservedIntegerEditor.js +22 -22
  12. package/editor/ecs/component/editors/ObservedStringEditor.js +34 -34
  13. package/editor/ecs/component/editors/common/two_way_sync.js +50 -50
  14. package/editor/ecs/component/editors/ecs/GridObstacleEditor.js +19 -19
  15. package/editor/ecs/component/editors/ecs/ParameterLookupTableEditor.js +35 -35
  16. package/editor/ecs/component/editors/ecs/ParameterTrackEditor.js +17 -17
  17. package/editor/ecs/component/editors/ecs/SGMeshEditor.js +24 -24
  18. package/editor/ecs/component/editors/ecs/ShadedGeometryEditor.js +33 -33
  19. package/editor/ecs/component/editors/ecs/Trail3DEditor.js +45 -45
  20. package/editor/ecs/component/editors/ecs/buildGridObstaclePreview.js +19 -19
  21. package/editor/ecs/component/editors/ecs/terrain/TerrainEditor.js +72 -72
  22. package/editor/ecs/component/editors/shade/MeshletGeometryEditor.js +30 -30
  23. package/editor/ecs/component/editors/shade/ShadeImageEditor.js +70 -70
  24. package/editor/ecs/component/editors/shade/ShadeMaterialEditor.js +34 -34
  25. package/editor/ecs/component/editors/shade/ShadeTextureEditor.js +46 -46
  26. package/editor/ecs/component/editors/shade/StandardShadeMaterialEditor.js +24 -24
  27. package/editor/ecs/component/prototypeObjectEditor.js +265 -265
  28. package/editor/ecs/component/registerBasicTypeEditors.js +100 -100
  29. package/editor/ecs/component/registerEngineComponentEditors.js +95 -95
  30. package/editor/entity_world_bounds.js +27 -27
  31. package/editor/particles/lut_ops.js +148 -148
  32. package/editor/particles/particleEditEvents.js +12 -12
  33. package/editor/particles/rebuildParticleEmitter.js +31 -31
  34. package/editor/persistence/EditorLayoutStore.js +71 -71
  35. package/editor/persistence/SceneMetadata.js +52 -52
  36. package/editor/persistence/SceneSlotManager.js +144 -144
  37. package/editor/persistence/buildNewSceneDataset.js +67 -67
  38. package/editor/persistence/files.js +68 -68
  39. package/editor/persistence/scene_import.js +143 -143
  40. package/editor/persistence/scene_serialization.js +79 -79
  41. package/editor/persistence/string_buffer_codec.js +41 -41
  42. package/editor/process/GridDisplayProcess.js +125 -125
  43. package/editor/process/SymbolicDisplayProcess.js +106 -108
  44. package/editor/process/symbolic/CameraSymbolicDisplay.js +146 -146
  45. package/editor/process/symbolic/LightSymbolicDisplay.js +172 -172
  46. package/editor/process/symbolic/PathSymbolicDisplay.js +118 -118
  47. package/editor/process/symbolic/PositionedMarkerSymbolicDisplay.js +79 -79
  48. package/editor/process/symbolic/SoundEmitterSymbolicDisplay.js +57 -57
  49. package/editor/process/symbolic/SymbolicDisplay.js +62 -62
  50. package/editor/process/symbolic/gizmo_draw_wire_box_oriented.js +85 -85
  51. package/editor/process/symbolic/gizmo_draw_wire_circle.js +53 -53
  52. package/editor/prototypeEditorShell.js +156 -156
  53. package/editor/selection/editor_pick.js +130 -130
  54. package/editor/selection/screen_rect_frustum.js +119 -119
  55. package/editor/style/controls.scss +168 -168
  56. package/editor/style/inspector.scss +223 -223
  57. package/editor/templates/entity_templates.js +167 -167
  58. package/editor/tools/GridPaintTool.js +273 -273
  59. package/editor/tools/SelectionTool.js +307 -307
  60. package/editor/tools/TransformToolV2.js +378 -378
  61. package/editor/tools/engine/ToolEngine.js +188 -188
  62. package/editor/tools/paint/TerrainTexturePaintTool.js +250 -250
  63. package/editor/tools/v2/BlenderCameraOrientationGizmo.js +501 -501
  64. package/editor/tools/v2/TransformControls.js +971 -971
  65. package/editor/tools/v2/handle/gizmo_drag_plane.js +141 -141
  66. package/editor/tools/v2/handle/gizmo_draw.js +399 -399
  67. package/editor/tools/v2/handle/gizmo_handles.js +364 -364
  68. package/editor/tools/v2/handle/gizmo_ray_shapes.js +239 -239
  69. package/editor/view/ecs/HierarchicalEntityListView.js +339 -339
  70. package/editor/view/ecs/components/DatGuiController.js +2 -2
  71. package/editor/view/ecs/components/common/AutoCanvasView.js +100 -100
  72. package/editor/view/ecs/components/common/TextController.js +59 -59
  73. package/editor/view/library/MeshLibraryView.js +175 -175
  74. package/editor/view/library/mesh_library_drag.js +63 -63
  75. package/editor/view/library/model_thumbnail_source.js +86 -86
  76. package/editor/view/makeEntityDecorators.js +125 -125
  77. package/editor/view/node-graph/NodeGraphSelection.js +89 -89
  78. package/editor/view/node-graph/NodeView.js +211 -211
  79. package/editor/view/node-graph/actions/ConnectionDeleteAction.js +36 -36
  80. package/editor/view/node-graph/actions/NodesMoveAction.js +41 -41
  81. package/editor/view/node-graph/connection_wire_geometry.js +107 -107
  82. package/editor/view/particles/ColorLutGradientView.js +291 -291
  83. package/editor/view/particles/ScalarLutCurveView.js +279 -279
  84. package/editor/view/prepareMeshLibrary.js +188 -188
  85. package/editor/view/shell/SceneTreePanelView.js +119 -119
  86. package/editor/view/v2/SplitView.js +2 -2
  87. package/package.json +94 -94
  88. package/samples/generation/generators/interactive/mir_generator_place_buff_objects.js +362 -362
  89. package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +738 -738
  90. package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +79 -79
  91. package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +93 -93
  92. package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +80 -80
  93. package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +164 -164
  94. package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +69 -69
  95. package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +102 -102
  96. package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +129 -129
  97. package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +72 -72
  98. package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +74 -74
  99. package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +169 -169
  100. package/src/DUPLICATION_AUDIT_2026_08_07.md +254 -254
  101. package/src/DUPLICATION_AUDIT_REMEDIATION.md +250 -250
  102. package/src/REVIEW_2026_08_06/adv-core.md +511 -511
  103. package/src/REVIEW_2026_08_06/adv-gfx.md +480 -480
  104. package/src/REVIEW_2026_08_06/adv-view.md +446 -446
  105. package/src/REVIEW_2026_08_06/api-core.md +296 -296
  106. package/src/REVIEW_2026_08_06/api-engine.md +195 -195
  107. package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +507 -507
  108. package/src/REVIEW_2026_08_06/core-binary.md +348 -348
  109. package/src/REVIEW_2026_08_06/core-collection.md +376 -376
  110. package/src/REVIEW_2026_08_06/core-math.md +221 -221
  111. package/src/REVIEW_2026_08_06/core-process.md +266 -266
  112. package/src/REVIEW_2026_08_06/core-science.md +223 -223
  113. package/src/REVIEW_2026_08_06/engine-ai-nav.md +279 -279
  114. package/src/REVIEW_2026_08_06/engine-animation.md +167 -167
  115. package/src/REVIEW_2026_08_06/engine-asset.md +166 -166
  116. package/src/REVIEW_2026_08_06/engine-ecs.md +920 -920
  117. package/src/REVIEW_2026_08_06/engine-input.md +197 -197
  118. package/src/REVIEW_2026_08_06/engine-misc.md +248 -248
  119. package/src/REVIEW_2026_08_06/engine-terrain.md +52 -52
  120. package/src/REVIEW_2026_08_06/generation.md +176 -176
  121. package/src/REVIEW_2026_08_06/geom-2d.md +434 -434
  122. package/src/REVIEW_2026_08_06/geom-3d.md +117 -117
  123. package/src/REVIEW_2026_08_06/gfx-gi.md +143 -143
  124. package/src/REVIEW_2026_08_06/gfx-render.md +740 -740
  125. package/src/REVIEW_2026_08_06/gfx-texture.md +690 -690
  126. package/src/REVIEW_2026_08_06/prior-criticals.md +49 -49
  127. package/src/REVIEW_2026_08_06/prior-highs.md +138 -138
  128. package/src/REVIEW_2026_08_06/test-gaps.md +364 -364
  129. package/src/REVIEW_2026_08_06/view.md +667 -667
  130. package/src/REVIEW_2026_08_06.md +610 -610
  131. package/src/avif/codec/dec/avif_dec.cpp +233 -233
  132. package/src/avif/codec/dec/avif_dec.js +16 -16
  133. package/src/core/binary/BitImage2.js +246 -246
  134. package/src/core/binary/align_32.js +21 -21
  135. package/src/core/binary/data_view/DataType2DataViewReaders.js +23 -23
  136. package/src/core/binary/data_view/DataType2DataViewWriters.js +25 -25
  137. package/src/core/binary/hash/XXH128Hash.js +55 -55
  138. package/src/core/binary/hash/XXH3_SECRET.js +25 -25
  139. package/src/core/binary/hash/xxh3_128.js +341 -341
  140. package/src/core/binary/hash/xxh3_64.js +241 -241
  141. package/src/core/binary/hash/xxh3_common.js +476 -476
  142. package/src/core/binary/lz4/LZ4_MAX_INPUT_SIZE.js +9 -9
  143. package/src/core/binary/lz4/lz4_compress_block.js +385 -385
  144. package/src/core/binary/lz4/lz4_compress_bound.js +25 -25
  145. package/src/core/binary/lz4/lz4_decompress_block.js +139 -139
  146. package/src/core/binary/lz4/lz4_decompress_bound.js +30 -30
  147. package/src/core/binary/meshopt/MESHOPT_GROUP_SIZE.js +18 -18
  148. package/src/core/binary/meshopt/MeshoptCompressionFilter.js +30 -30
  149. package/src/core/binary/meshopt/MeshoptCompressionMode.js +21 -21
  150. package/src/core/binary/meshopt/__meshopt_test_streams.js +237 -237
  151. package/src/core/binary/meshopt/meshopt_decode.js +73 -73
  152. package/src/core/binary/meshopt/meshopt_decode_byte_group.js +67 -67
  153. package/src/core/binary/meshopt/meshopt_decode_data_block.js +59 -59
  154. package/src/core/binary/meshopt/meshopt_decode_filter_color.js +69 -69
  155. package/src/core/binary/meshopt/meshopt_decode_filter_exponential.js +43 -43
  156. package/src/core/binary/meshopt/meshopt_decode_filter_octahedral.js +60 -60
  157. package/src/core/binary/meshopt/meshopt_decode_filter_quaternion.js +71 -71
  158. package/src/core/binary/meshopt/meshopt_decode_index_buffer.js +294 -294
  159. package/src/core/binary/meshopt/meshopt_decode_index_sequence.js +115 -115
  160. package/src/core/binary/meshopt/meshopt_decode_vertex_buffer.js +381 -381
  161. package/src/core/binary/meshopt/meshopt_read_uint_var.js +59 -59
  162. package/src/core/binary/reinterpret_float32_as_uint32.js +13 -13
  163. package/src/core/binary/reinterpret_uint32_as_float32.js +14 -14
  164. package/src/core/binary/type/DataType2TypedArrayConstructorMapping.js +35 -35
  165. package/src/core/bvh2/bvh3/ebvh_geometry_query_any_triangle_ray.js +149 -149
  166. package/src/core/bvh2/bvh3/ebvh_sort_for_traversal_depth_first.js +96 -96
  167. package/src/core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js +101 -101
  168. package/src/core/bvh2/bvh3/query/bvh_query_leaves_generic.js +77 -77
  169. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray.js +90 -90
  170. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray_segment.js +94 -94
  171. package/src/core/bvh2/bvh3/query/bvh_query_user_data_generic.js +86 -86
  172. package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_capsule.js +101 -101
  173. package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_sphere.js +92 -92
  174. package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray.js +96 -96
  175. package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray_segment.js +100 -100
  176. package/src/core/bvh2/visual/BVHGeometry.js +131 -131
  177. package/src/core/bvh8/BVH8.js +436 -436
  178. package/src/core/bvh8/aabb3_round_to_float32.js +22 -22
  179. package/src/core/bvh8/build/BVH8Converter.js +588 -588
  180. package/src/core/bvh8/build/TriangleCluster.js +122 -122
  181. package/src/core/bvh8/build/aabb3_compute_merge_cost.js +28 -28
  182. package/src/core/bvh8/build/aabb3_from_triangle_by_index.js +17 -17
  183. package/src/core/bvh8/build/bvh8_build_for_geometry.js +303 -303
  184. package/src/core/bvh8/build/bvh8_from_proxy.js +256 -256
  185. package/src/core/bvh8/build/byte.js +9 -9
  186. package/src/core/bvh8/build/encode_bounds_e.js +11 -11
  187. package/src/core/bvh8/bvh8_convert_to_dot.js +132 -132
  188. package/src/core/bvh8/bvh8_count_primitives.js +98 -98
  189. package/src/core/bvh8/bvh8_geometry_validate.js +138 -138
  190. package/src/core/bvh8/bvh8_geometry_validate_indirect.js +166 -166
  191. package/src/core/bvh8/bvh8_get_node_bounds.js +34 -34
  192. package/src/core/bvh8/bvh8_get_node_child_bounds.js +52 -52
  193. package/src/core/bvh8/bvh8_node_child_surface_area.js +18 -18
  194. package/src/core/bvh8/bvh8_node_count_triangles.js +27 -27
  195. package/src/core/bvh8/bvh8_quality.js +72 -72
  196. package/src/core/bvh8/bvh8_validate_structure.js +87 -87
  197. package/src/core/clipboard/obtainClipBoard.js +29 -29
  198. package/src/core/clipboard/safeClipboardReadText.js +55 -55
  199. package/src/core/clipboard/safeClipboardWriteText.js +23 -23
  200. package/src/core/collection/array/typed/typed_array_value_denormalize.js +52 -52
  201. package/src/core/collection/array/typed/typed_array_value_normalize.js +51 -51
  202. package/src/core/collection/union-find/union_find.js +79 -79
  203. package/src/core/color/YCoCg/rgb_to_ycocg.js +20 -20
  204. package/src/core/color/YCoCg/ycocg_to_rgb.js +17 -17
  205. package/src/core/color/colormap/MAGMA_LUT.js +26 -26
  206. package/src/core/color/illuminant/D65_TRISTIMULUS_XYZ.js +19 -19
  207. package/src/core/color/lab/lab_apply_hunt_adjustment.js +27 -27
  208. package/src/core/color/lab/lab_distance_hyab.js +23 -23
  209. package/src/core/color/lab/xyz_to_lab.js +62 -62
  210. package/src/core/color/operations/color_darken.js +24 -24
  211. package/src/core/color/operations/color_desaturate.js +24 -24
  212. package/src/core/color/operations/color_lighten.js +24 -24
  213. package/src/core/color/operations/color_saturate.js +24 -24
  214. package/src/core/color/operations/color_scale_okhsv_channel.js +45 -45
  215. package/src/core/color/tonemap/tonemap_aces.js +41 -41
  216. package/src/core/color/ycxcz/xyz_to_ycxcz.js +28 -28
  217. package/src/core/color/ycxcz/ycxcz_to_xyz.js +19 -19
  218. package/src/core/dom/isImageBitmap.js +12 -12
  219. package/src/core/function/frameThrottle.js +23 -23
  220. package/src/core/geom/2d/aabb/aabb2_array_combine.js +7 -7
  221. package/src/core/geom/2d/aabb/aabb2_compute_area.js +7 -7
  222. package/src/core/geom/2d/aabb/aabb2_compute_center_from_multiple.js +7 -7
  223. package/src/core/geom/2d/aabb/aabb2_compute_overlap.js +7 -7
  224. package/src/core/geom/2d/aabb/aabb2_from_v2_array.js +7 -7
  225. package/src/core/geom/2d/aabb/aabb2_intersects_point.js +7 -7
  226. package/src/core/geom/2d/aabb/aabb2_overlap_exists.js +7 -7
  227. package/src/core/geom/2d/circle/circle_compute_circle_intersection.js +7 -7
  228. package/src/core/geom/2d/circle/circle_compute_circle_penetration.js +7 -7
  229. package/src/core/geom/2d/circle/circle_intersects_point.js +7 -7
  230. package/src/core/geom/2d/compute_polygon_area_2d.js +7 -7
  231. package/src/core/geom/2d/convex-hull/fixed_convex_hull_humus.js +7 -7
  232. package/src/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +7 -7
  233. package/src/core/geom/2d/convex-hull/orientation3_array.js +7 -7
  234. package/src/core/geom/2d/intersect_ray_2d.js +7 -7
  235. package/src/core/geom/2d/line/line2_distance_to_point_sqr.js +7 -7
  236. package/src/core/geom/2d/line/line2_segment_intersection_fraction_2d.js +44 -44
  237. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_2d.js +7 -7
  238. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_array_2d.js +7 -7
  239. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_2d.js +7 -7
  240. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_array_2d.js +7 -7
  241. package/src/core/geom/2d/line/line_segment_intersection_fraction_2d.js +7 -7
  242. package/src/core/geom/2d/line/line_segment_line_segment_intersection_exists_2d.js +7 -7
  243. package/src/core/geom/2d/line/segment2_intersects_segment2_2d.js +25 -25
  244. package/src/core/geom/2d/line/segment2_segment_compute_intersection_array_2d.js +46 -46
  245. package/src/core/geom/2d/line/segment2_segment_intersection_fractions.js +52 -52
  246. package/src/core/geom/2d/oriented-box/min_area_rect_2d.js +69 -69
  247. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +433 -433
  248. package/src/core/geom/2d/polygon/polygon2_clip_axis_halfplane.js +51 -51
  249. package/src/core/geom/2d/polygon/polygon2_clip_halfplane.js +50 -50
  250. package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.js +84 -84
  251. package/src/core/geom/2d/polygon/polygon2_signed_area.js +52 -52
  252. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.js +86 -86
  253. package/src/core/geom/2d/polygon/polygon2_triangulate.js +1280 -1280
  254. package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.js +77 -77
  255. package/src/core/geom/2d/quad-tree/qt_collect_by_circle.js +39 -39
  256. package/src/core/geom/2d/quad-tree/qt_match_data_by_circle.js +101 -101
  257. package/src/core/geom/2d/quad-tree/qt_query_data_nearest_to_point.js +7 -7
  258. package/src/core/geom/2d/rectangle_to_aabb.js +7 -7
  259. package/src/core/geom/2d/spline_bezier2_2d.js +7 -7
  260. package/src/core/geom/2d/triangle/tri2_rasterize_conservative.js +99 -99
  261. package/src/core/geom/2d/triangle/tri2_signed_area.js +35 -35
  262. package/src/core/geom/2d/triangle2d_compute_area.js +7 -7
  263. package/src/core/geom/2d/triangle2d_contains_point.js +7 -7
  264. package/src/core/geom/2d/triangle2d_get_barycentric.js +7 -7
  265. package/src/core/geom/2d/v2_morton_encode.js +23 -23
  266. package/src/core/geom/3d/aabb/aabb3_array_intersects_frustum_degree.js +7 -7
  267. package/src/core/geom/3d/aabb/aabb3_box_surface_area_2.js +7 -7
  268. package/src/core/geom/3d/aabb/aabb3_build_frustum.js +5 -5
  269. package/src/core/geom/3d/aabb/aabb3_closest_point_on_surface.js +57 -57
  270. package/src/core/geom/3d/aabb/aabb3_combined_surface_area.js +7 -7
  271. package/src/core/geom/3d/aabb/aabb3_compute_half_surface_area.js +7 -7
  272. package/src/core/geom/3d/aabb/aabb3_compute_projected_area.js +7 -7
  273. package/src/core/geom/3d/aabb/aabb3_compute_surface_area.js +7 -7
  274. package/src/core/geom/3d/aabb/aabb3_detailed_volume_intersection.js +7 -7
  275. package/src/core/geom/3d/aabb/aabb3_estimate_projected_area2.js +7 -7
  276. package/src/core/geom/3d/aabb/aabb3_from_threejs_geometry.js +7 -7
  277. package/src/core/geom/3d/aabb/aabb3_from_triangle_group.js +46 -46
  278. package/src/core/geom/3d/aabb/aabb3_intersects_frustum_degree.js +7 -7
  279. package/src/core/geom/3d/aabb/aabb3_intersects_line_segment.js +7 -7
  280. package/src/core/geom/3d/aabb/aabb3_near_distance_to_intersection_ray_segment.js +7 -7
  281. package/src/core/geom/3d/aabb/aabb3_nearest_point_on_surface.js +7 -7
  282. package/src/core/geom/3d/aabb/aabb3_ray_segment_entry_distance.js +95 -95
  283. package/src/core/geom/3d/aabb/aabb3_raycast.js +7 -7
  284. package/src/core/geom/3d/aabb/aabb3_transform_oriented.js +93 -93
  285. package/src/core/geom/3d/aabb/aabb3_transform_oriented_inverse.js +82 -82
  286. package/src/core/geom/3d/aabb/compute_aabb_from_points.js +7 -7
  287. package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.js +7 -7
  288. package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +486 -486
  289. package/src/core/geom/3d/atlas/BFF_PLAN.md +174 -174
  290. package/src/core/geom/3d/atlas/Chart.js +77 -77
  291. package/src/core/geom/3d/atlas/REVIEW_02.md +392 -392
  292. package/src/core/geom/3d/atlas/atlas_bench_lib.js +315 -315
  293. package/src/core/geom/3d/atlas/atlas_chart_type.js +16 -16
  294. package/src/core/geom/3d/atlas/atlas_compute_charts.js +188 -188
  295. package/src/core/geom/3d/atlas/atlas_extract_chart.js +107 -107
  296. package/src/core/geom/3d/atlas/atlas_generate.js +50 -50
  297. package/src/core/geom/3d/atlas/atlas_test_fixtures.js +266 -266
  298. package/src/core/geom/3d/atlas/atlas_write_chart_uvs.js +36 -36
  299. package/src/core/geom/3d/atlas/data/atlas_build_edge_dihedrals.js +62 -62
  300. package/src/core/geom/3d/atlas/data/atlas_build_edge_lengths.js +33 -33
  301. package/src/core/geom/3d/atlas/data/atlas_build_face_areas.js +50 -50
  302. package/src/core/geom/3d/atlas/io/atlas_mesh_weld_colocals.js +39 -39
  303. package/src/core/geom/3d/atlas/io/bt_loop_uv.js +35 -35
  304. package/src/core/geom/3d/atlas/pack/ChartPlacement.js +46 -46
  305. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.js +269 -269
  306. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.js +209 -209
  307. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_ortho.js +38 -38
  308. package/src/core/geom/3d/atlas/param/atlas_chart_stretch_metric.js +86 -86
  309. package/src/core/geom/3d/atlas/param/atlas_piecewise_resegment.js +183 -183
  310. package/src/core/geom/3d/atlas/param/fit_plane_basis.js +66 -66
  311. package/src/core/geom/3d/atlas/segment/RegionGraph.js +40 -40
  312. package/src/core/geom/3d/atlas/segment/atlas_build_region_graph.js +136 -136
  313. package/src/core/geom/3d/atlas/segment/atlas_chart_roundness_delta.js +30 -30
  314. package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.js +77 -77
  315. package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +116 -116
  316. package/src/core/geom/3d/atlas/segment/atlas_segment_charts.js +271 -271
  317. package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.js +191 -191
  318. package/src/core/geom/3d/box/box3_projected_half_extent.js +35 -35
  319. package/src/core/geom/3d/capsule/capsule_intersects_aabb3_closed.js +67 -67
  320. package/src/core/geom/3d/capsule/capsule_intersects_aabb3_iterative.js +137 -137
  321. package/src/core/geom/3d/compute_circle_bounding_box.js +7 -7
  322. package/src/core/geom/3d/cone/computeConeBoundingBox.js +7 -7
  323. package/src/core/geom/3d/cone/computeConePlaneSide.js +7 -7
  324. package/src/core/geom/3d/cone/compute_bounding_cone_of_2_cones.js +7 -7
  325. package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts +38 -0
  326. package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts.map +1 -0
  327. package/src/core/geom/3d/cylinder/cylinder3_raycast.js +105 -0
  328. package/src/core/geom/3d/equirectangular/equirectangular_direction_to_uv.js +18 -18
  329. package/src/core/geom/3d/equirectangular/equirectangular_uv_to_direction.js +24 -24
  330. package/src/core/geom/3d/frustum/clipping_volume_matrix4_project.js +7 -7
  331. package/src/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +7 -7
  332. package/src/core/geom/3d/frustum/frustum3_compute_closest_point.js +117 -117
  333. package/src/core/geom/3d/frustum/frustum_matrix4_project.js +7 -7
  334. package/src/core/geom/3d/frustum/hexahedron_from_aabb.js +7 -7
  335. package/src/core/geom/3d/frustum/read_frustum_corner.js +17 -17
  336. package/src/core/geom/3d/frustum/read_three_planes_to_array.js +7 -7
  337. package/src/core/geom/3d/frustum/slice_frustum_linear_to_points.js +7 -7
  338. package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +146 -146
  339. package/src/core/geom/3d/gjk/gjk.js +430 -430
  340. package/src/core/geom/3d/gjk/gjk_epa_penetration.js +520 -520
  341. package/src/core/geom/3d/gjk/minkowski_support.js +71 -71
  342. package/src/core/geom/3d/gjk/mpr.js +368 -368
  343. package/src/core/geom/3d/line/line3_closest_points_segment_segment.js +7 -7
  344. package/src/core/geom/3d/line/line3_compute_nearest_point_to_point.js +7 -7
  345. package/src/core/geom/3d/line/line3_compute_point_segment_point_distance_unfolded.js +64 -64
  346. package/src/core/geom/3d/line/line3_compute_segment_closest_point_to_aabb3_t.js +153 -153
  347. package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_aabb3_t.js +7 -7
  348. package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_point_t.js +7 -7
  349. package/src/core/geom/3d/line/line3_compute_segment_segment_closest_points.js +88 -88
  350. package/src/core/geom/3d/line/line3_segment_segment_closest_point_pair.js +71 -71
  351. package/src/core/geom/3d/line/segment3_point_distance_to_segments.js +25 -25
  352. package/src/core/geom/3d/mat4/allocate_m4.js +7 -7
  353. package/src/core/geom/3d/mat4/apply_mat4_transform_to_direction_v3_array.js +7 -7
  354. package/src/core/geom/3d/mat4/apply_mat4_transform_to_v3_array.js +7 -7
  355. package/src/core/geom/3d/mat4/compose_matrix4_array.js +7 -7
  356. package/src/core/geom/3d/mat4/decompose_matrix_4_array.js +7 -7
  357. package/src/core/geom/3d/mat4/eulerAnglesFromMatrix.js +7 -7
  358. package/src/core/geom/3d/mat4/m4_compose.js +22 -22
  359. package/src/core/geom/3d/mat4/m4_compute_normal_matrix3.js +7 -7
  360. package/src/core/geom/3d/mat4/m4_decompose.js +64 -64
  361. package/src/core/geom/3d/mat4/m4_decompose_array.js +157 -157
  362. package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.js +32 -32
  363. package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale_scalar.js +67 -67
  364. package/src/core/geom/3d/mat4/m4_linear_matrix3.js +29 -29
  365. package/src/core/geom/3d/mat4/m4_look_at.js +96 -96
  366. package/src/core/geom/3d/mat4/m4_make_rotation_x.js +47 -47
  367. package/src/core/geom/3d/mat4/m4_make_rotation_y.js +47 -47
  368. package/src/core/geom/3d/mat4/m4_make_rotation_z.js +47 -47
  369. package/src/core/geom/3d/mat4/m4_normal_matrix3.js +39 -39
  370. package/src/core/geom/3d/mat4/m4_perspective.js +66 -66
  371. package/src/core/geom/3d/mat4/m4_transpose.js +48 -48
  372. package/src/core/geom/3d/morton/mortonEncode_LUT.js +7 -7
  373. package/src/core/geom/3d/morton/mortonEncode_magicbits.js +7 -7
  374. package/src/core/geom/3d/normal/hemioct/encode_unit3_hemioct.js +5 -5
  375. package/src/core/geom/3d/normal/hemioct/encode_unit_to_hemioct.js +28 -28
  376. package/src/core/geom/3d/normal/lambert_azimuth/decode_azimuth_to_unit.js +30 -30
  377. package/src/core/geom/3d/normal/lambert_azimuth/encode_unit_to_azimuth.js +19 -19
  378. package/src/core/geom/3d/normal/spherical/decode_spheremap_to_unit.js +38 -38
  379. package/src/core/geom/3d/normal/spherical/encode_unit_to_spheremap.js +30 -30
  380. package/src/core/geom/3d/plane/is_point_within_planes.js +7 -7
  381. package/src/core/geom/3d/plane/orient3d_fast_point.js +47 -47
  382. package/src/core/geom/3d/plane/plane3_compute_convex_3_plane_intersection.js +7 -7
  383. package/src/core/geom/3d/plane/plane3_compute_plane_intersection.js +7 -7
  384. package/src/core/geom/3d/plane/plane3_intersect_plane.js +7 -7
  385. package/src/core/geom/3d/plane/plane3_three_compute_convex_3_plane_intersection.js +7 -7
  386. package/src/core/geom/3d/point/point3_raycast.d.ts +33 -0
  387. package/src/core/geom/3d/point/point3_raycast.d.ts.map +1 -0
  388. package/src/core/geom/3d/point/point3_raycast.js +47 -0
  389. package/src/core/geom/3d/polygon/polygon3_compute_normal.js +60 -60
  390. package/src/core/geom/3d/polygon/polygon3_triangulate.js +94 -94
  391. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts +40 -0
  392. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts.map +1 -0
  393. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.js +94 -0
  394. package/src/core/geom/3d/quadric/QUADRIC3_SIZE.js +14 -14
  395. package/src/core/geom/3d/quadric/Quadric3.js +282 -282
  396. package/src/core/geom/3d/quadric/quadric3_add.js +33 -33
  397. package/src/core/geom/3d/quadric/quadric3_clear.js +25 -25
  398. package/src/core/geom/3d/quadric/quadric3_copy.js +27 -27
  399. package/src/core/geom/3d/quadric/quadric3_distance.js +36 -36
  400. package/src/core/geom/3d/quadric/quadric3_evaluate.js +25 -25
  401. package/src/core/geom/3d/quadric/quadric3_optimize.js +45 -45
  402. package/src/core/geom/3d/quadric/quadric3_scale.js +32 -32
  403. package/src/core/geom/3d/quadric/quadric3_set_from_plane_through_point.js +30 -30
  404. package/src/core/geom/3d/quadric/quadric3_set_from_vector4.js +35 -35
  405. package/src/core/geom/3d/quadric/quadric3_sub.js +36 -36
  406. package/src/core/geom/3d/quadric/quadric3_to_tensor_m3.js +28 -28
  407. package/src/core/geom/3d/quadric/quadric3_to_tensor_m3_inverse.js +56 -56
  408. package/src/core/geom/3d/quadric/quadric3_to_vector3.js +19 -19
  409. package/src/core/geom/3d/quaternion/quat3_createFromAxisAngle.js +7 -7
  410. package/src/core/geom/3d/quaternion/quat3_integrate.js +62 -62
  411. package/src/core/geom/3d/quaternion/quat3_multiply.js +31 -31
  412. package/src/core/geom/3d/quaternion/quat3_nlerp.js +72 -72
  413. package/src/core/geom/3d/quaternion/quat3_to_matrix3.js +69 -69
  414. package/src/core/geom/3d/quaternion/quat_decode_from_uint32.js +7 -7
  415. package/src/core/geom/3d/quaternion/quat_encode_to_uint32.js +7 -7
  416. package/src/core/geom/3d/ray/ray3_array_compose.js +7 -7
  417. package/src/core/geom/3d/ray/ray3_compute_nearest_point_to_point.js +7 -7
  418. package/src/core/geom/3d/ray/ray3_distance_to_point.js +7 -7
  419. package/src/core/geom/3d/ray/ray3_shift_origin_along_direction.js +7 -7
  420. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts +17 -0
  421. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
  422. package/src/core/geom/3d/shape/ConvexHullShape3D.js +43 -0
  423. package/src/core/geom/3d/shape/CylinderShape3D.d.ts +1 -0
  424. package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -1
  425. package/src/core/geom/3d/shape/CylinderShape3D.js +21 -0
  426. package/src/core/geom/3d/shape/PointShape3D.d.ts +7 -0
  427. package/src/core/geom/3d/shape/PointShape3D.d.ts.map +1 -1
  428. package/src/core/geom/3d/shape/PointShape3D.js +88 -63
  429. package/src/core/geom/3d/shape/PosedShape3D.d.ts +6 -0
  430. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
  431. package/src/core/geom/3d/shape/PosedShape3D.js +27 -0
  432. package/src/core/geom/3d/shape/TransformedShape3D.d.ts +10 -0
  433. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  434. package/src/core/geom/3d/shape/TransformedShape3D.js +13 -0
  435. package/src/core/geom/3d/shape/Triangle3D.d.ts +1 -0
  436. package/src/core/geom/3d/shape/Triangle3D.d.ts.map +1 -1
  437. package/src/core/geom/3d/shape/Triangle3D.js +26 -0
  438. package/src/core/geom/3d/shape/UnionShape3D.d.ts +6 -0
  439. package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
  440. package/src/core/geom/3d/shape/UnionShape3D.js +7 -0
  441. package/src/core/geom/3d/shape/UnitCubeShape3D.js +45 -45
  442. package/src/core/geom/3d/shape/UnitSphereShape3D.js +44 -44
  443. package/src/core/geom/3d/shape/shape3_mesh_from_geometry.js +64 -64
  444. package/src/core/geom/3d/shape/shape_mesh_from_geometry.js +7 -7
  445. package/src/core/geom/3d/shape/util/compute_signed_distance_gradient_by_sampling.js +51 -51
  446. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +7 -7
  447. package/src/core/geom/3d/sphere/compute_bounding_sphere_of_2_spheres.js +7 -7
  448. package/src/core/geom/3d/sphere/harmonics/sh3_convolve_with_zh.js +53 -53
  449. package/src/core/geom/3d/sphere/harmonics/sh3_ggx_zh.js +30 -30
  450. package/src/core/geom/3d/sphere/harmonics/sh3_rotate_bl.js +7 -7
  451. package/src/core/geom/3d/sphere/harmonics/sh_compute_K.js +7 -7
  452. package/src/core/geom/3d/sphere/sphere_array_intersects_point.js +7 -7
  453. package/src/core/geom/3d/sphere/sphere_array_intersects_ray.js +7 -7
  454. package/src/core/geom/3d/sphere/sphere_intersects_point.js +7 -7
  455. package/src/core/geom/3d/sphere/sphere_matrix4_transform.js +5 -5
  456. package/src/core/geom/3d/sphere/sphere_projected_sphere_radius_sqr.js +7 -7
  457. package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.js +7 -7
  458. package/src/core/geom/3d/sphere/spherical_from_cartesian.js +7 -7
  459. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.js +174 -174
  460. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.js +7 -7
  461. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_volume.js +7 -7
  462. package/src/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.js +7 -7
  463. package/src/core/geom/3d/tetrahedra/graphics/build_tetrahedral_mesh_geometry.js +39 -39
  464. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.js +48 -48
  465. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +173 -173
  466. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_compute_tet_quality.js +22 -22
  467. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.js +146 -146
  468. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.js +232 -232
  469. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.js +255 -255
  470. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +387 -387
  471. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +140 -140
  472. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_tet_get_neighbours.js +7 -7
  473. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +97 -97
  474. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.js +66 -66
  475. package/src/core/geom/3d/tetrahedra/triangle/triangle_decode_depth.js +59 -59
  476. package/src/core/geom/3d/tetrahedra/triangle/triangle_rasterized_depth_sample_index.js +54 -54
  477. package/src/core/geom/3d/tetrahedra/validate_neighbour.js +70 -70
  478. package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.js +314 -314
  479. package/src/core/geom/3d/topology/struct/binary/BinaryDataLayer.js +364 -364
  480. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +567 -567
  481. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +1085 -1085
  482. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +73 -73
  483. package/src/core/geom/3d/topology/struct/binary/io/bt_loop_kill.js +35 -35
  484. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_append.js +119 -119
  485. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +84 -84
  486. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.js +172 -172
  487. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_face_normals.js +56 -56
  488. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadratics.js +7 -7
  489. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.js +227 -227
  490. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.js +161 -161
  491. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_island_erode.js +490 -490
  492. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +120 -120
  493. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_from_indexed_geometry.js +120 -120
  494. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_collapse.js +52 -52
  495. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +115 -115
  496. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_flip.js +142 -142
  497. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.js +21 -21
  498. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.js +92 -92
  499. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_split.js +179 -179
  500. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_swap_vertex_slots.js +28 -28
  501. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_kill_only_edge.js +8 -8
  502. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_fuse_duplicate_edges.js +83 -83
  503. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.js +89 -89
  504. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_kill.js +25 -25
  505. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_poke.js +127 -127
  506. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.js +268 -268
  507. package/src/core/geom/3d/topology/struct/binary/io/face/bt_kill_only_face.js +8 -8
  508. package/src/core/geom/3d/topology/struct/binary/io/face/bt_mesh_kill_degenerate_faces.js +72 -72
  509. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_kill_only_vert.js +7 -7
  510. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_merge_verts_by_distance.js +7 -7
  511. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_relative_merge_distance.js +48 -48
  512. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_split_pinched_vertices.js +256 -256
  513. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_vertex_merge_distance.js +77 -77
  514. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_fuse_duplicate_edges.js +7 -7
  515. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_kill.js +7 -7
  516. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_fuse_duplicate_edges.js +148 -148
  517. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_kill_only.js +7 -7
  518. package/src/core/geom/3d/topology/struct/binary/query/bt_collect_boundary_segments.js +29 -29
  519. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_collapse_breaks_link_condition.js +107 -107
  520. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_is_legal.js +41 -41
  521. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_would_fold.js +120 -120
  522. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.js +42 -42
  523. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_is_boundary.js +20 -20
  524. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_read_diamond.js +96 -96
  525. package/src/core/geom/3d/topology/struct/binary/query/bt_face_compute_newell_normal.js +72 -72
  526. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_attached_faces.js +7 -7
  527. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces.js +39 -39
  528. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces_weighted.js +93 -93
  529. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_neighbour_faces.js +7 -7
  530. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_shared_loop.js +48 -48
  531. package/src/core/geom/3d/topology/struct/binary/query/bt_face_island_flood_fill.js +45 -45
  532. package/src/core/geom/3d/topology/struct/binary/query/bt_face_read_triangle.js +66 -66
  533. package/src/core/geom/3d/topology/struct/binary/query/bt_faces_shared_loop.js +7 -7
  534. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.js +44 -44
  535. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_build_boundary_euclidean_distance_field.js +32 -32
  536. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_compute_face_islands.js +53 -53
  537. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path.js +703 -703
  538. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +181 -181
  539. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_segment_penetrates_surface.js +133 -133
  540. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_surface_ray_parity.js +82 -82
  541. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.js +599 -599
  542. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.js +108 -108
  543. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.js +7 -7
  544. package/src/core/geom/3d/triangle/computeTriangleClosestPointToPointBarycentric.js +7 -7
  545. package/src/core/geom/3d/triangle/computeTriangleRayIntersection.js +7 -7
  546. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentric.js +7 -7
  547. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricEdge.js +7 -7
  548. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricGeometry.js +7 -7
  549. package/src/core/geom/3d/triangle/compute_triangle_area_3d.js +7 -7
  550. package/src/core/geom/3d/triangle/compute_triangle_normal.js +7 -7
  551. package/src/core/geom/3d/triangle/rayTriangleIntersection.js +7 -7
  552. package/src/core/geom/3d/triangle/tri3_closest_point.js +65 -65
  553. package/src/core/geom/3d/triangle/tri3_closest_point_barycentric.js +171 -171
  554. package/src/core/geom/3d/triangle/tri3_flatten_isometric.js +79 -79
  555. package/src/core/geom/3d/triangle/tri3_ray_intersection.js +160 -160
  556. package/src/core/geom/3d/triangle/tri3_ray_intersection_barycentric.js +96 -96
  557. package/src/core/geom/3d/triangle/tri3_raycast.d.ts +42 -0
  558. package/src/core/geom/3d/triangle/tri3_raycast.d.ts.map +1 -0
  559. package/src/core/geom/3d/triangle/tri3_raycast.js +94 -0
  560. package/src/core/geom/3d/triangle/triangle3_incenter.js +7 -7
  561. package/src/core/geom/3d/triangle/triangle_compute_plane_side.js +7 -7
  562. package/src/core/geom/3d/triangle/triangle_compute_signed_volume.js +7 -7
  563. package/src/core/geom/3d/triangle/triangle_intersects_clipping_volume.js +7 -7
  564. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.js +7 -7
  565. package/src/core/geom/3d/triangle/v3_compute_triangle_normal.js +7 -7
  566. package/src/core/geom/3d/util/make_justified_point_grid.js +7 -7
  567. package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +381 -381
  568. package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +684 -684
  569. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +554 -554
  570. package/src/core/geom/mat3/m3_cm_from_translation.js +7 -7
  571. package/src/core/geom/mat3/m3_cm_invert.js +7 -7
  572. package/src/core/geom/mat3/m3_make_rotation.js +5 -5
  573. package/src/core/geom/mat3/m3_make_rotation_TBN.js +31 -31
  574. package/src/core/geom/mat3/m3_multiply_vec3.js +7 -7
  575. package/src/core/geom/packing/computeBoundingSphereOfSpheres.js +7 -7
  576. package/src/core/geom/packing/max-rect/cost/costByBestShortSide.js +7 -7
  577. package/src/core/geom/packing/max-rect/cost/costByRemainingArea.js +7 -7
  578. package/src/core/geom/packing/max-rect/cutArea.js +7 -7
  579. package/src/core/geom/packing/max-rect/findBestContainer.js +7 -7
  580. package/src/core/geom/packing/max-rect/packMaxRectangles.js +7 -7
  581. package/src/core/geom/packing/max-rect/packOneBox.js +7 -7
  582. package/src/core/geom/packing/max-rect/removeRedundantBoxes.js +7 -7
  583. package/src/core/geom/packing/max-rect/removeRedundantBoxesArray.js +7 -7
  584. package/src/core/geom/random/randomPointInBox.js +7 -7
  585. package/src/core/geom/random/randomPointInCircle.js +7 -7
  586. package/src/core/geom/random/randomPointInPoint.js +7 -7
  587. package/src/core/geom/random/randomPointInSphere.js +7 -7
  588. package/src/core/geom/random/randomPointOnBox.js +7 -7
  589. package/src/core/geom/random/randomPointOnSphere.js +7 -7
  590. package/src/core/geom/random/random_orthonormal_basis.js +31 -31
  591. package/src/core/geom/vec/vector_axpy.js +15 -15
  592. package/src/core/geom/vec/vector_axpy_offset.js +20 -20
  593. package/src/core/geom/vec/vector_copy.js +7 -7
  594. package/src/core/geom/vec/vector_dot_offset.js +25 -25
  595. package/src/core/geom/vec/vector_scale_array.js +7 -7
  596. package/src/core/geom/vec2/v2_rotate.js +21 -21
  597. package/src/core/geom/vec2/v2_rotate_cos_sin.js +21 -21
  598. package/src/core/geom/vec3/v3_angle_atan2_between.js +7 -7
  599. package/src/core/geom/vec3/v3_angle_between.js +7 -7
  600. package/src/core/geom/vec3/v3_angle_cos_between.js +7 -7
  601. package/src/core/geom/vec3/v3_array_add_in_place.js +7 -7
  602. package/src/core/geom/vec3/v3_array_centroid.js +7 -7
  603. package/src/core/geom/vec3/v3_array_copy.js +7 -7
  604. package/src/core/geom/vec3/v3_array_displace_in_direction.js +7 -7
  605. package/src/core/geom/vec3/v3_array_equals.js +7 -7
  606. package/src/core/geom/vec3/v3_array_immediate_add.js +7 -7
  607. package/src/core/geom/vec3/v3_array_matrix4_rotate.js +7 -7
  608. package/src/core/geom/vec3/v3_array_normalize.js +7 -7
  609. package/src/core/geom/vec3/v3_array_scale.js +7 -7
  610. package/src/core/geom/vec3/v3_compute_interior_angle.js +7 -7
  611. package/src/core/geom/vec3/v3_cotangent.js +33 -33
  612. package/src/core/geom/vec3/v3_dot_array_array.js +7 -7
  613. package/src/core/geom/vec3/v3_matrix3_multiply.js +30 -30
  614. package/src/core/geom/vec3/v3_matrix3_rotate.js +49 -49
  615. package/src/core/geom/vec3/v3_matrix4_rotate.js +7 -7
  616. package/src/core/geom/vec3/v3_multiply.js +23 -23
  617. package/src/core/geom/vec3/v3_multiply_scalar.js +7 -7
  618. package/src/core/geom/vec3/v3_orthonormal_matrix_from_normal.js +49 -49
  619. package/src/core/geom/vec3/v3_quat3_apply.js +7 -7
  620. package/src/core/geom/vec3/v3_quat3_apply_inverse.js +7 -7
  621. package/src/core/geom/vec3/v3_quaternion_apply.js +39 -39
  622. package/src/core/geom/vec3/v3_quaternion_apply_inverse.js +41 -41
  623. package/src/core/geom/vec3/v3_reflect.js +24 -24
  624. package/src/core/geom/vec3/v3_scale_array.js +18 -18
  625. package/src/core/geom/vec3/v3_triple_cross.js +45 -45
  626. package/src/core/geom/vec3/v3_triple_cross_product.js +7 -7
  627. package/src/core/geom/vec3/v3_uniform_sample_cone.js +21 -21
  628. package/src/core/geom/vec4/v4_multiply_mat4.js +7 -7
  629. package/src/core/graph/csr/csr_graph_build_distance_field.js +112 -112
  630. package/src/core/graph/csr/csr_graph_find_edge.js +25 -25
  631. package/src/core/graph/csr/csr_graph_find_shortest_path.js +105 -105
  632. package/src/core/graph/csr/csr_graph_from_undirected_edge_list.js +94 -94
  633. package/src/core/graph/graph_k_means_cluster.js +250 -250
  634. package/src/core/graph/layout/CircleLayout.js +1 -1
  635. package/src/core/graph/layout/box/BoxLayouter.js +1 -1
  636. package/src/core/graph/layout/graph_peel_topological_layer.js +45 -45
  637. package/src/core/graph/metis/BinaryTopologyFaceGraph.js +49 -49
  638. package/src/core/graph/metis/bt_mesh_build_face_graph.js +111 -111
  639. package/src/core/graph/metis/cluster_mesh_metis.js +137 -137
  640. package/src/core/graph/metis/native/bisection/bisect_graph.js +100 -100
  641. package/src/core/graph/metis/native/bisection/compute_2way_params.js +86 -86
  642. package/src/core/graph/metis/native/bisection/fm_2way.js +297 -297
  643. package/src/core/graph/metis/native/bisection/grow_bisection.js +137 -137
  644. package/src/core/graph/metis/native/bisection/split_graph_two_way.js +119 -119
  645. package/src/core/graph/metis/native/coarsen/coarsen_graph.js +94 -94
  646. package/src/core/graph/metis/native/coarsen/create_coarse_graph.js +158 -158
  647. package/src/core/graph/metis/native/coarsen/match_shem.js +175 -175
  648. package/src/core/graph/metis/native/initial/initial_kway_bfs.js +122 -122
  649. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.js +170 -170
  650. package/src/core/graph/metis/native/metis_partition_kway.js +126 -126
  651. package/src/core/graph/metis/native/refine/RefinementScratch.js +53 -53
  652. package/src/core/graph/metis/native/refine/fm_kway.js +487 -487
  653. package/src/core/graph/metis/native/refine/project_kway.js +43 -43
  654. package/src/core/graph/metis/native/refine/refine_kway.js +43 -43
  655. package/src/core/lang/reactive/pegjs/parser.js +3458 -3458
  656. package/src/core/math/complex/complex_horner_eval.js +31 -31
  657. package/src/core/math/computeWholeDivisorLow.js +33 -33
  658. package/src/core/math/f32_next_down.js +24 -24
  659. package/src/core/math/f32_next_up.js +27 -27
  660. package/src/core/math/hash/hash_mix2.js +22 -22
  661. package/src/core/math/hash/hash_mix3.js +19 -19
  662. package/src/core/math/linalg/cg/cg_solve.js +106 -106
  663. package/src/core/math/linalg/cg/cg_solve_normal_equations.js +59 -59
  664. package/src/core/math/linalg/cubic_residual_times_derivative_accumulate.js +43 -43
  665. package/src/core/math/linalg/eigen/matrix_householder_in_place.js +122 -122
  666. package/src/core/math/linalg/eigen/matrix_qr_in_place.js +190 -190
  667. package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js +117 -117
  668. package/src/core/math/linalg/givens/givens_apply_rows.js +28 -28
  669. package/src/core/math/linalg/givens/givens_apply_rows_offset.js +30 -30
  670. package/src/core/math/linalg/givens/givens_rotation_coefficients.js +39 -39
  671. package/src/core/math/linalg/lu_factor_linear_system.js +108 -108
  672. package/src/core/math/linalg/lu_solve_linear_system.js +53 -53
  673. package/src/core/math/linalg/polynomial_add_into.js +29 -29
  674. package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.js +159 -159
  675. package/src/core/math/linalg/polynomial_cubic_derivative_eval.js +16 -16
  676. package/src/core/math/linalg/polynomial_cubic_horner_eval.js +19 -19
  677. package/src/core/math/linalg/polynomial_cubic_second_derivative_eval.js +14 -14
  678. package/src/core/math/linalg/polynomial_multiply.js +41 -41
  679. package/src/core/math/linalg/polynomial_real_roots_in_interval.js +211 -211
  680. package/src/core/math/linalg/polynomial_root_bound_cauchy.js +30 -30
  681. package/src/core/math/linalg/polynomial_scale_into.js +17 -17
  682. package/src/core/math/linalg/polynomial_sub_into.js +29 -29
  683. package/src/core/math/linalg/solve_linear_system_GEPP_2x2.js +96 -96
  684. package/src/core/math/linalg/sor_optimal_omega.js +42 -42
  685. package/src/core/math/linalg/sparse/SparseMatrixCSR.js +88 -88
  686. package/src/core/math/linalg/sparse/spm_matvec.js +22 -22
  687. package/src/core/math/linalg/sparse/spm_matvec_transpose.js +29 -29
  688. package/src/core/math/lookup/LUT_HEATMAP.js +30 -30
  689. package/src/core/math/lookup/ParameterLookupTable.js +495 -495
  690. package/src/core/math/lookup/ParameterLookupTableFlags.js +6 -6
  691. package/src/core/math/noise/curl_noise_3d.js +18 -18
  692. package/src/core/math/physics/brdf/cone_cosine_from_roughness.js +28 -28
  693. package/src/core/math/physics/brdf/reflection_sample_weight.js +48 -48
  694. package/src/core/math/physics/kinematics/computeInterceptPoint.js +79 -79
  695. package/src/core/math/random/randomSeed.js +16 -16
  696. package/src/core/math/random/random_pick_weighted_index.js +26 -26
  697. package/src/core/math/round_half_away_from_zero.js +13 -13
  698. package/src/core/math/spline/spline3_hermite_apply_transform.js +107 -107
  699. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.js +125 -125
  700. package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.js +50 -50
  701. package/src/core/math/spline/spline3_hermite_reverse.js +49 -49
  702. package/src/core/math/spline/spline3_hermite_to_monomial.js +37 -37
  703. package/src/core/math/statistics/hammersley_sequence.js +53 -53
  704. package/src/core/model/reactive/model/util/createRandomReactiveExpression.js +185 -185
  705. package/src/core/path/convertPathToURL.js +107 -107
  706. package/src/core/process/delay.js +16 -16
  707. package/src/core/science/units/MEASUREMENT_UNITS_SCIENTIFIC.js +87 -87
  708. package/src/core/science/units/MEASUREMENT_UNITS_SI.js +17 -17
  709. package/src/core/science/units/NamedUnit.js +48 -48
  710. package/src/core/science/units/UNIT_DIMENSION_MAPPING.js +29 -29
  711. package/src/core/science/units/UnitDimension.js +28 -28
  712. package/src/core/science/units/format_quantity.js +74 -74
  713. package/src/core/science/units/magnitude_prefix.js +127 -127
  714. package/src/core/science/units/si/AMPERE.js +13 -13
  715. package/src/core/science/units/si/CANDELA.js +13 -13
  716. package/src/core/science/units/si/DIMENSIONLESS.js +14 -14
  717. package/src/core/science/units/si/KELVIN.js +13 -13
  718. package/src/core/science/units/si/KILOGRAM.js +13 -13
  719. package/src/core/science/units/si/METER.js +13 -13
  720. package/src/core/science/units/si/MOLE.js +13 -13
  721. package/src/core/science/units/si/SECOND.js +13 -13
  722. package/src/core/science/units/si/derived/BECQUEREL.js +16 -16
  723. package/src/core/science/units/si/derived/COULOMB.js +13 -13
  724. package/src/core/science/units/si/derived/FARAD.js +13 -13
  725. package/src/core/science/units/si/derived/GRAY.js +16 -16
  726. package/src/core/science/units/si/derived/HENRY.js +13 -13
  727. package/src/core/science/units/si/derived/HERTZ.js +16 -16
  728. package/src/core/science/units/si/derived/JOULE.js +13 -13
  729. package/src/core/science/units/si/derived/KATAL.js +13 -13
  730. package/src/core/science/units/si/derived/LUMEN.js +14 -14
  731. package/src/core/science/units/si/derived/LUX.js +13 -13
  732. package/src/core/science/units/si/derived/NEWTON.js +13 -13
  733. package/src/core/science/units/si/derived/OHM.js +13 -13
  734. package/src/core/science/units/si/derived/PASCAL.js +13 -13
  735. package/src/core/science/units/si/derived/SIEMENS.js +13 -13
  736. package/src/core/science/units/si/derived/SIEVERT.js +16 -16
  737. package/src/core/science/units/si/derived/TESLA.js +13 -13
  738. package/src/core/science/units/si/derived/VOLT.js +13 -13
  739. package/src/core/science/units/si/derived/WATT.js +13 -13
  740. package/src/core/science/units/si/derived/WEBER.js +13 -13
  741. package/src/core/science/units/unit_matrix_to_string.js +403 -403
  742. package/src/engine/Engine.js +726 -726
  743. package/src/engine/EngineHarness.js +590 -590
  744. package/src/engine/REVIEW_2026_07_03.md +211 -211
  745. package/src/engine/animation/AnimatedActions.js +81 -81
  746. package/src/engine/animation/AnimationUtils.js +252 -252
  747. package/src/engine/animation/async/TimeSeries.js +300 -300
  748. package/src/engine/animation/curve/animation_curve_binary_codec.js +60 -60
  749. package/src/engine/animation/curve/draw/canvas_point_to_curve.js +22 -22
  750. package/src/engine/animation/curve/draw/curve_point_to_canvas.js +38 -38
  751. package/src/engine/animation/curve/draw/position_canvas_to_curve.js +22 -22
  752. package/src/engine/animation/curve/draw/position_curve_to_canvas.js +22 -22
  753. package/src/engine/asset/GameAssetType.d.ts +0 -1
  754. package/src/engine/asset/GameAssetType.js +0 -1
  755. package/src/engine/asset/load_model_scene_bundle.js +27 -27
  756. package/src/engine/asset/loaders/font/FontAsset.js +21 -21
  757. package/src/engine/asset/loaders/font/FontAssetLoader.js +20 -20
  758. package/src/engine/asset/loaders/gltf_test_fixtures.js +358 -358
  759. package/src/engine/asset/loaders/image/ImageBitmapAssetLoader.js +52 -52
  760. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +94 -94
  761. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterAverage.js +59 -59
  762. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterNone.js +55 -55
  763. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterPaeth.js +74 -74
  764. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterSub.js +34 -34
  765. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterUp.js +46 -46
  766. package/src/engine/control/first-person/DESIGN.md +640 -640
  767. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +563 -563
  768. package/src/engine/control/first-person/FirstPersonMotionPhase.js +134 -134
  769. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2045 -2045
  770. package/src/engine/control/first-person/mastery/DecisionPoint.js +30 -30
  771. package/src/engine/control/first-person/math/Spring.js +71 -71
  772. package/src/engine/control/first-person/math/computeJumpFromApex.js +23 -23
  773. package/src/engine/control/first-person/math/computeLRCBreathRate.js +41 -41
  774. package/src/engine/control/first-person/math/computeMassRatios.js +44 -44
  775. package/src/engine/control/first-person/math/criticallyDampedSpring.js +34 -34
  776. package/src/engine/control/first-person/math/dampedSpringStep.js +72 -72
  777. package/src/engine/control/first-person/math/jumpDynamics.js +108 -108
  778. package/src/engine/control/first-person/math/stepTowards.js +20 -20
  779. package/src/engine/control/first-person/pose/FirstPersonPose.js +137 -137
  780. package/src/engine/control/first-person/pose/FirstPersonPosture.js +27 -27
  781. package/src/engine/control/first-person/test/buildTestPlayer.js +36 -36
  782. package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +531 -531
  783. package/src/engine/ecs/EntityManager.d.ts +7 -3
  784. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  785. package/src/engine/ecs/EntityManager.js +10 -5
  786. package/src/engine/ecs/HIERARCHY_REVIEW.md +717 -717
  787. package/src/engine/ecs/async/SystemWorkerHost.js +329 -329
  788. package/src/engine/ecs/async/SystemWorkerLoopback.js +143 -143
  789. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +246 -246
  790. package/src/engine/ecs/async/WorkerSystem.js +702 -702
  791. package/src/engine/ecs/async/WorkerSystemProtocol.js +150 -150
  792. package/src/engine/ecs/fow/FogOfWar.js +707 -707
  793. package/src/engine/ecs/fow/FogOfWarEdgeMode.js +40 -40
  794. package/src/engine/ecs/fow/fog_of_war_mask_world_bounds.js +24 -24
  795. package/src/engine/ecs/fow/fog_of_war_uv_transform.js +30 -30
  796. package/src/engine/ecs/gui/hud/testHudEdgeStick.js +132 -134
  797. package/src/engine/ecs/hierarchy/EntityChildIndex.js +140 -140
  798. package/src/engine/ecs/ik/IKProblem.js +42 -42
  799. package/src/engine/ecs/ik/InverseKinematicsSystem.js +193 -193
  800. package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +134 -134
  801. package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +97 -97
  802. package/src/engine/ecs/ik/ik_bone_chain.js +85 -85
  803. package/src/engine/ecs/ik/ik_probe_terrain_contact.js +119 -119
  804. package/src/engine/ecs/parent/EntityNode.d.ts +1 -1
  805. package/src/engine/ecs/parent/EntityNode.js +2 -2
  806. package/src/engine/ecs/parent/ParentEntitySystem.js +255 -255
  807. package/src/engine/ecs/speaker/VoiceSystem.d.ts +2 -2
  808. package/src/engine/ecs/speaker/VoiceSystem.d.ts.map +1 -1
  809. package/src/engine/ecs/speaker/VoiceSystem.js +13 -7
  810. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +269 -269
  811. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectDeSerializer.js +315 -315
  812. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectSerializer.js +331 -331
  813. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +199 -199
  814. package/src/engine/ecs/storage/binary/object-v2/ObjectBinaryFormat.js +57 -57
  815. package/src/engine/ecs/storage/binary/object-v2/ObjectSerializationAdapter.js +56 -56
  816. package/src/engine/ecs/storage/binary/object-v2/README.md +110 -110
  817. package/src/engine/ecs/storage/binary/object-v2/objectStringCodec.js +48 -48
  818. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.js +44 -44
  819. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +265 -265
  820. package/src/engine/ecs/terrain/TerrainClouds.js +97 -97
  821. package/src/engine/ecs/terrain/ecs/StubTerrainBuildWorker.js +65 -65
  822. package/src/engine/ecs/terrain/ecs/Terrain.d.ts +4 -0
  823. package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
  824. package/src/engine/ecs/terrain/ecs/Terrain.js +790 -790
  825. package/src/engine/ecs/terrain/ecs/TerrainSystem.js +209 -209
  826. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +316 -316
  827. package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.js +416 -416
  828. package/src/engine/ecs/terrain/ecs/splat/SplatMapping.js +525 -525
  829. package/src/engine/ecs/terrain/overlay/TerrainOverlay.js +302 -302
  830. package/src/engine/ecs/terrain/tiles/TerrainTile.js +561 -561
  831. package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +896 -896
  832. package/src/engine/ecs/terrain/tiles/tile_geometry_to_meshlets.js +36 -36
  833. package/src/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +129 -129
  834. package/src/engine/ecs/transform/Transform64.js +814 -814
  835. package/src/engine/ecs/transform/t64_copy_from_transform.js +35 -35
  836. package/src/engine/ecs/transform/t64_equals_transform.js +55 -55
  837. package/src/engine/ecs/transform/t64_look_rotation.js +36 -36
  838. package/src/engine/ecs/transform/t64_transform_direction.js +25 -25
  839. package/src/engine/ecs/transform/transform_copy_from_t64.js +28 -28
  840. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +345 -345
  841. package/src/engine/ecs/transform-attachment/transform_attachment_find_descendant_by_name.js +65 -65
  842. package/src/engine/ecs/transform-attachment/transform_attachment_parent_of.js +24 -24
  843. package/src/engine/ecs/util/hideEntityGracefully.js +208 -208
  844. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +446 -446
  845. package/src/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js +14 -14
  846. package/src/engine/graphics/FrameThrottle.js +2 -2
  847. package/src/engine/graphics/ecs/animation/animator/graph/AnimationState.js +207 -207
  848. package/src/engine/graphics/ecs/animation/animator/graph/AnimationTransition.js +151 -151
  849. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.js +22 -22
  850. package/src/engine/graphics/ecs/camera/Camera.js +165 -165
  851. package/src/engine/graphics/ecs/camera/camera_active_frustum.js +25 -25
  852. package/src/engine/graphics/ecs/camera/camera_find_active.js +28 -28
  853. package/src/engine/graphics/ecs/camera/camera_traverse_active.js +18 -18
  854. package/src/engine/graphics/ecs/camera/pp/PerfectPanner.js +170 -170
  855. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.js +68 -68
  856. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +296 -296
  857. package/src/engine/graphics/ecs/decal/v2/Decal.js +220 -220
  858. package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.js +56 -56
  859. package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_0_1.js +38 -38
  860. package/src/engine/graphics/ecs/light/shadow/compute_view_frustum_aabb_in_space.js +62 -62
  861. package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.js +77 -77
  862. package/src/engine/graphics/ecs/make_bvh_depth_range_computer.js +33 -33
  863. package/src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.js +88 -88
  864. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +428 -428
  865. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +303 -303
  866. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.d.ts +1 -1
  867. package/src/engine/graphics/ecs/mesh-v2/aggregate/serialization/SGMeshSerializationAdapter.js +39 -39
  868. package/src/engine/graphics/ecs/mesh-v2/sg_hierarchy_compute_bounding_box_via_parent_entity.js +36 -36
  869. package/src/engine/graphics/ecs/path/tube/build/GeometryStream.js +94 -94
  870. package/src/engine/graphics/ecs/path/tube/build/build_stream_catmullrom.js +310 -310
  871. package/src/engine/graphics/ecs/path/tube/build/build_stream_linear.js +73 -73
  872. package/src/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +199 -199
  873. package/src/engine/graphics/ecs/path/tube/build/makeTubeStream.js +217 -217
  874. package/src/engine/graphics/ecs/path/tube/build/make_cap.js +340 -340
  875. package/src/engine/graphics/ecs/path/tube/build/make_ring_faces.js +40 -40
  876. package/src/engine/graphics/ecs/path/tube/build/make_ring_vertices.js +153 -153
  877. package/src/engine/graphics/ecs/render_layers_compute_depth_range.js +64 -64
  878. package/src/engine/graphics/ecs/trail3d/Trail3D.js +483 -483
  879. package/src/engine/graphics/ecs/trail3d/Trail3DFlags.js +26 -26
  880. package/src/engine/graphics/ecs/trail3d/advance_trail.js +42 -42
  881. package/src/engine/graphics/ecs/trail3d/make_gradient_stroke.js +58 -58
  882. package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.js +90 -90
  883. package/src/engine/graphics/ecs/trail3d/seed_trail_tube.js +75 -75
  884. package/src/engine/graphics/ecs/trail3d/trail_head_position.js +19 -19
  885. package/src/engine/graphics/ecs/water/Water.js +104 -104
  886. package/src/engine/graphics/geometry/AttributeData.js +84 -84
  887. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_indexed.js +49 -49
  888. package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +288 -288
  889. package/src/engine/graphics/geometry/buffered/query/nearest_point_on_triangle_record.js +87 -87
  890. package/src/engine/graphics/geometry/buffered/read_triangle_vertices.js +102 -102
  891. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_buffered_geometry.js +52 -52
  892. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_indexed_geometry.js +20 -20
  893. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_unindexed_geometry.js +19 -19
  894. package/src/engine/graphics/geometry/optimization/geometry_optimize_uv_tension.js +135 -135
  895. package/src/engine/graphics/impostors/voxel/README.md +149 -149
  896. package/src/engine/graphics/impostors/voxel/VoxelImpostorDescription.js +141 -141
  897. package/src/engine/graphics/particles/node-based/codegen/glsl/getTypeByteSize.js +20 -20
  898. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts +2 -0
  899. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts.map +1 -1
  900. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts +2 -0
  901. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts.map +1 -1
  902. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts +2 -0
  903. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts.map +1 -1
  904. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts +1 -2
  905. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts.map +1 -1
  906. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts +2 -0
  907. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts.map +1 -1
  908. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts +2 -0
  909. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts.map +1 -1
  910. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts +2 -0
  911. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts.map +1 -1
  912. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts +2 -0
  913. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts.map +1 -1
  914. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts +2 -0
  915. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts.map +1 -1
  916. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts +2 -0
  917. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts.map +1 -1
  918. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts +2 -0
  919. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts.map +1 -1
  920. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts +2 -0
  921. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts.map +1 -1
  922. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts +2 -0
  923. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts.map +1 -1
  924. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts +2 -0
  925. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts.map +1 -1
  926. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts +2 -0
  927. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts.map +1 -1
  928. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts +2 -0
  929. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts.map +1 -1
  930. package/src/engine/graphics/particles/node-based/nodes/particle_data_type_component_count.js +45 -45
  931. package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +229 -229
  932. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts +2 -10
  933. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts.map +1 -1
  934. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +1149 -1149
  935. package/src/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +472 -472
  936. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +2 -2
  937. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.js +2 -2
  938. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.d.ts.map +1 -1
  939. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.js +3 -5
  940. package/src/engine/graphics/particles/particular/engine/shader/ShaderManager.js +135 -135
  941. package/src/engine/graphics/particles/particular/engine/utils/distribute_points_on_indexed_triangles.js +168 -168
  942. package/src/engine/graphics/render/forward_plus/plugin/forwardPlusMaterialMarker.js +18 -18
  943. package/src/engine/graphics/render/forward_plus/read_frustum_corner.js +2 -2
  944. package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +219 -219
  945. package/src/engine/graphics/render/frame_graph/FrameGraph.js +900 -900
  946. package/src/engine/graphics/render/frame_graph/FrameGraphScope.js +72 -72
  947. package/src/engine/graphics/render/frame_graph/FrameGraphState.js +39 -39
  948. package/src/engine/graphics/render/frame_graph/ResourceEntry.js +96 -96
  949. package/src/engine/graphics/render/gizmo/GizmoShapeBuffer.js +105 -105
  950. package/src/engine/graphics/render/gizmo/GizmoShapeRenderingInterface.js +162 -162
  951. package/src/engine/graphics/render/layers/RenderLayer.js +95 -95
  952. package/src/engine/graphics/sh3/build_injected_shader.js +56 -56
  953. package/src/engine/graphics/sh3/grid_dilate_average.js +175 -175
  954. package/src/engine/graphics/sh3/path_tracer/BufferedGeometryBVH.js +506 -506
  955. package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.js +161 -161
  956. package/src/engine/graphics/sh3/path_tracer/PathTracedRenderer.js +205 -205
  957. package/src/engine/graphics/sh3/path_tracer/PathTracedScene.js +698 -698
  958. package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +490 -490
  959. package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.js +2 -2
  960. package/src/engine/graphics/sh3/path_tracer/make_sky_hosek.js +45 -45
  961. package/src/engine/graphics/sh3/path_tracer/populate_path_traced_scene_from_ecd.js +73 -73
  962. package/src/engine/graphics/sh3/path_tracer/ray_hit_apply_transform.js +32 -32
  963. package/src/engine/graphics/sh3/path_tracer/texture/apply_texture_clamping_to_coordinate.js +28 -28
  964. package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +142 -142
  965. package/src/engine/graphics/sh3/sky/hosek/render_hosek_sky_to_equirectangular.js +70 -70
  966. package/src/engine/graphics/sh3/sky/hosek/sky_hosek_compute_irradiance_by_direction.js +388 -388
  967. package/src/engine/graphics/shaders/chunks/glsl_octahedral_impostor.js +277 -277
  968. package/src/engine/graphics/shaders/chunks/glsl_voxel_impostor_splat.js +57 -57
  969. package/src/engine/graphics/shadows/vsm.glsl.js +43 -43
  970. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.js +81 -81
  971. package/src/engine/graphics/texture/EnvironmentTextureProjection.js +15 -15
  972. package/src/engine/graphics/texture/channel_count_to_format_prefix.js +26 -26
  973. package/src/engine/graphics/texture/isImageBitmap.js +2 -2
  974. package/src/engine/graphics/texture/reflection/convolve_equirectangular_reflection.js +189 -189
  975. package/src/engine/graphics/texture/reflection/equirectangular_reflection_roughness.js +51 -51
  976. package/src/engine/graphics/texture/sampler/HarmonicDiffusionGrid.js +145 -145
  977. package/src/engine/graphics/texture/sampler/Sampler2DArray.js +172 -172
  978. package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +466 -466
  979. package/src/engine/graphics/texture/sampler/compare/flip/FlipParameters.js +18 -18
  980. package/src/engine/graphics/texture/sampler/compare/flip/FlipPooling.js +33 -33
  981. package/src/engine/graphics/texture/sampler/compare/flip/flip_build_feature_kernel.js +147 -147
  982. package/src/engine/graphics/texture/sampler/compare/flip/flip_build_spatial_kernel.js +177 -177
  983. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_color_difference.js +104 -104
  984. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_feature_difference.js +76 -76
  985. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_pixels_per_degree.js +34 -34
  986. package/src/engine/graphics/texture/sampler/compare/flip/flip_constants.js +77 -77
  987. package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_feature.js +48 -48
  988. package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_spatial.js +86 -86
  989. package/src/engine/graphics/texture/sampler/compare/flip/flip_pool.js +71 -71
  990. package/src/engine/graphics/texture/sampler/compare/flip/flip_srgb_to_ycxcz.js +55 -55
  991. package/src/engine/graphics/texture/sampler/compare/flip/sampler2d_flip_ldr.js +80 -80
  992. package/src/engine/graphics/texture/sampler/filter/SeparableKernel.js +82 -82
  993. package/src/engine/graphics/texture/sampler/filter/sampler2d_convolve_separable.js +122 -122
  994. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.js +148 -148
  995. package/src/engine/graphics/texture/sampler/sampler2d_channel_apply_lut.js +82 -82
  996. package/src/engine/graphics/texture/sampler/sampler2d_combine.js +67 -67
  997. package/src/engine/graphics/texture/sampler/sampler2d_linear_f16_to_srgb_u8.js +54 -54
  998. package/src/engine/graphics/texture/sampler/sampler2d_sample_equirectangular_direction.js +63 -63
  999. package/src/engine/graphics/texture/sampler/sampler2d_srgb_to_linear.js +33 -33
  1000. package/src/engine/graphics/texture/sampler/sampler2d_srgb_u8_to_linear_f16.js +68 -68
  1001. package/src/engine/graphics/texture/shade_image_preview.js +103 -103
  1002. package/src/engine/graphics/trail/TrailSpawnMode.js +20 -20
  1003. package/src/engine/graphics/trail/tube/TubeX.js +573 -573
  1004. package/src/engine/graphics/trail/tube/TubeXMaterialSpec.js +58 -58
  1005. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.js +34 -34
  1006. package/src/engine/graphics/trail/tube/tube_attributes_spec.js +69 -69
  1007. package/src/engine/graphics/trail/tube/tube_frame.js +83 -83
  1008. package/src/engine/graphics3/AnimationGraphSystem3.js +329 -329
  1009. package/src/engine/graphics3/AnimationSystem3.js +352 -352
  1010. package/src/engine/graphics3/CameraSystem3.js +170 -170
  1011. package/src/engine/graphics3/DecalSystem3.js +441 -441
  1012. package/src/engine/graphics3/FogOfWarSystem3.js +265 -265
  1013. package/src/engine/graphics3/GraphicsEngine3.js +776 -776
  1014. package/src/engine/graphics3/HighlightSystem3.js +241 -241
  1015. package/src/engine/graphics3/LightSystem3.js +211 -211
  1016. package/src/engine/graphics3/MeshSystem3.js +646 -646
  1017. package/src/engine/graphics3/ParticleEmitterSystem3.js +289 -289
  1018. package/src/engine/graphics3/PathDisplaySystem3.js +309 -309
  1019. package/src/engine/graphics3/PickingQuery.js +48 -48
  1020. package/src/engine/graphics3/PickingResult.js +47 -47
  1021. package/src/engine/graphics3/PickingSystem3.js +273 -273
  1022. package/src/engine/graphics3/ShadeCameraAdapter.js +55 -55
  1023. package/src/engine/graphics3/ShadedGeometrySystem3.js +169 -169
  1024. package/src/engine/graphics3/TerrainSystem3.js +566 -566
  1025. package/src/engine/graphics3/TooltipComponentSystem3.js +328 -328
  1026. package/src/engine/graphics3/Trail3DSystem3.js +221 -221
  1027. package/src/engine/graphics3/WaterSystem3.js +293 -293
  1028. package/src/engine/graphics3/animation/ClipPlayback.js +84 -84
  1029. package/src/engine/graphics3/animation/wrap_clip_time.js +23 -23
  1030. package/src/engine/graphics3/animation/write_graph_playback.js +48 -48
  1031. package/src/engine/graphics3/camera_sync_from_transform.js +29 -29
  1032. package/src/engine/graphics3/debug/gizmo_view_from_camera.js +48 -48
  1033. package/src/engine/graphics3/decal/DECAL_CLUSTER.js +61 -61
  1034. package/src/engine/graphics3/decal/DECAL_GPU_RECORD.js +117 -117
  1035. package/src/engine/graphics3/decal/DecalAtlas.js +194 -194
  1036. package/src/engine/graphics3/decal/DecalAtlasFill.js +32 -32
  1037. package/src/engine/graphics3/decal/GPUDecalRenderer.js +360 -360
  1038. package/src/engine/graphics3/decal/chunk_decal_intersects_frustum.js +59 -59
  1039. package/src/engine/graphics3/decal/chunk_decal_sampling_info.js +57 -57
  1040. package/src/engine/graphics3/decal/chunk_decal_surface_frame.js +54 -54
  1041. package/src/engine/graphics3/decal/decal_atlas_border.js +69 -69
  1042. package/src/engine/graphics3/decal/decal_gpu_records.js +120 -120
  1043. package/src/engine/graphics3/decal/decal_material_samplers.js +109 -109
  1044. package/src/engine/graphics3/decal/graph_build_decal_clusters.js +212 -212
  1045. package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +207 -207
  1046. package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +108 -108
  1047. package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +151 -151
  1048. package/src/engine/graphics3/highlight/HIGHLIGHT_OUTLINE.js +23 -23
  1049. package/src/engine/graphics3/highlight/chunk_highlight_lookup.js +53 -53
  1050. package/src/engine/graphics3/highlight/pack_highlight_color.js +44 -44
  1051. package/src/engine/graphics3/highlight/pack_highlight_table.js +74 -74
  1052. package/src/engine/graphics3/highlight/shader_highlight_outline.js +150 -150
  1053. package/src/engine/graphics3/load_cube_environment.js +68 -68
  1054. package/src/engine/graphics3/make_default_environment.js +107 -107
  1055. package/src/engine/graphics3/particles/particle_gpu_records.js +221 -221
  1056. package/src/engine/graphics3/path/build_tube_path_streams.js +98 -98
  1057. package/src/engine/graphics3/path/tube_stream_write_geometry.js +90 -90
  1058. package/src/engine/graphics3/preview/ModelPreviewFraming.js +35 -35
  1059. package/src/engine/graphics3/preview/make_model_preview_scene.js +154 -154
  1060. package/src/engine/graphics3/preview/make_model_thumbnail.js +48 -48
  1061. package/src/engine/graphics3/preview/model_preview_framing.js +70 -70
  1062. package/src/engine/graphics3/shade_bundle_bounds.js +55 -55
  1063. package/src/engine/graphics3/shade_camera_projection_ray.js +77 -77
  1064. package/src/engine/graphics3/shade_node_to_entity_composition.js +84 -84
  1065. package/src/engine/graphics3/terrain/GPUTerrainSplatRenderer.js +481 -481
  1066. package/src/engine/graphics3/terrain/chunk_terrain_grid_overlay.js +61 -61
  1067. package/src/engine/graphics3/terrain/chunk_terrain_splat_mix.js +66 -66
  1068. package/src/engine/graphics3/terrain/pack_terrain_row_table.js +53 -53
  1069. package/src/engine/graphics3/terrain/shader_terrain_splat.js +215 -215
  1070. package/src/engine/graphics3/trail/trail_tube_write_geometry.js +158 -158
  1071. package/src/engine/grid/grid2transform/GridPosition2TransformSystem.d.ts +2 -2
  1072. package/src/engine/grid/grid2transform/GridPosition2TransformSystem.d.ts.map +1 -1
  1073. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +717 -717
  1074. package/src/engine/input/analog/apply_radial_dead_zone.js +38 -38
  1075. package/src/engine/input/devices/GamepadDevice.js +466 -466
  1076. package/src/engine/input/devices/ManualInputDevice.js +152 -152
  1077. package/src/engine/input/devices/PointerCoordinates.js +26 -26
  1078. package/src/engine/input/devices/events/GamepadEvents.js +10 -10
  1079. package/src/engine/input/devices/gamepad/GamepadAxes.js +19 -19
  1080. package/src/engine/input/devices/gamepad/GamepadButtons.js +29 -29
  1081. package/src/engine/input/devices/gamepad/GamepadCoordinates.js +17 -17
  1082. package/src/engine/input/devices/gamepad/GamepadDeviceLayout.js +323 -323
  1083. package/src/engine/input/devices/gamepad/GamepadHandle.js +286 -286
  1084. package/src/engine/input/devices/gamepad/GamepadLayout.js +160 -160
  1085. package/src/engine/input/devices/gamepad/GamepadStandardMapping.js +31 -31
  1086. package/src/engine/input/devices/gamepad/GamepadStick.js +169 -169
  1087. package/src/engine/input/devices/gamepad/GamepadStickCalibration.js +119 -119
  1088. package/src/engine/input/devices/gamepad/GamepadStickCalibrator.js +250 -250
  1089. package/src/engine/input/devices/gamepad/gamepad_layout_database.js +144 -144
  1090. package/src/engine/input/devices/gamepad/gamepad_read_hat_axis.js +61 -61
  1091. package/src/engine/input/devices/gamepad/gamepad_write_dpad_vector.js +30 -30
  1092. package/src/engine/input/devices/gamepad/prototypeGamepadTester.js +2124 -2124
  1093. package/src/engine/input/devices/mouse/MouseButtons.js +22 -22
  1094. package/src/engine/input/ecs/components/Input.js +118 -118
  1095. package/src/engine/input/ecs/components/InputController.js +78 -78
  1096. package/src/engine/input/ecs/ism/ISM_DESIGN.md +1523 -1523
  1097. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +627 -627
  1098. package/src/engine/input/ecs/ism/InputActionEvent.js +40 -40
  1099. package/src/engine/input/ecs/ism/InputBinding.js +71 -71
  1100. package/src/engine/input/ecs/ism/InputCoordinateKind.js +25 -25
  1101. package/src/engine/input/ecs/ism/InputCoordinateSource.js +86 -86
  1102. package/src/engine/input/ecs/ism/InputDirection.js +33 -33
  1103. package/src/engine/input/ecs/ism/InputMapProgram.js +236 -236
  1104. package/src/engine/input/ecs/ism/InputMapSystem.js +976 -976
  1105. package/src/engine/input/ecs/ism/InputOcclusion.js +31 -31
  1106. package/src/engine/input/ecs/ism/InputSource.js +67 -67
  1107. package/src/engine/input/ecs/ism/InputSourceTable.js +107 -107
  1108. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannel.js +93 -93
  1109. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannelType.js +11 -11
  1110. package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.js +153 -153
  1111. package/src/engine/input/ecs/ism/coordinate/InputCoordinateSwitches.js +160 -160
  1112. package/src/engine/input/ecs/ism/device/GAMEPAD_INPUT_DEVICE_ID.js +9 -9
  1113. package/src/engine/input/ecs/ism/device/GamepadInputDeviceAdapter.js +88 -88
  1114. package/src/engine/input/ecs/ism/device/InputDeviceAdapter.js +72 -72
  1115. package/src/engine/input/ecs/ism/device/KEYBOARD_INPUT_DEVICE_ID.js +9 -9
  1116. package/src/engine/input/ecs/ism/device/KeyboardInputDeviceAdapter.js +63 -63
  1117. package/src/engine/input/ecs/ism/device/ManualInputDeviceAdapter.js +55 -55
  1118. package/src/engine/input/ecs/ism/device/POINTER_INPUT_DEVICE_ID.js +9 -9
  1119. package/src/engine/input/ecs/ism/device/PointerInputDeviceAdapter.js +160 -160
  1120. package/src/engine/input/ecs/ism/map/InputBinding.js +88 -88
  1121. package/src/engine/input/ecs/ism/map/InputCoordinateBinding.js +102 -102
  1122. package/src/engine/input/ecs/ism/map/InputLayer.js +220 -220
  1123. package/src/engine/input/ecs/ism/map/InputMap.js +331 -331
  1124. package/src/engine/input/ecs/ism/prototypeInputMap.js +309 -309
  1125. package/src/engine/input/ecs/ism/trigger/InputTrigger.js +148 -148
  1126. package/src/engine/input/ecs/ism/trigger/InputTriggerChord.js +173 -173
  1127. package/src/engine/input/ecs/ism/trigger/InputTriggerGamepadButton.js +37 -37
  1128. package/src/engine/input/ecs/ism/trigger/InputTriggerHold.js +176 -176
  1129. package/src/engine/input/ecs/ism/trigger/InputTriggerKey.js +39 -39
  1130. package/src/engine/input/ecs/ism/trigger/InputTriggerMouseButton.js +38 -38
  1131. package/src/engine/input/ecs/ism/trigger/InputTriggerRelease.js +120 -120
  1132. package/src/engine/input/ecs/ism/trigger/InputTriggerSequence.js +315 -315
  1133. package/src/engine/input/ecs/ism/trigger/InputTriggerSwitch.js +105 -105
  1134. package/src/engine/input/ecs/ism/trigger/InputTriggerType.js +17 -17
  1135. package/src/engine/input/ecs/systems/InputControllerSystem.js +253 -253
  1136. package/src/engine/input/ecs/systems/InputSystem.js +162 -162
  1137. package/src/engine/intelligence/behavior/primitive/FailingBehaviorSerializationAdapter.js +25 -25
  1138. package/src/engine/intelligence/behavior/primitive/SucceedingBehaviorSerializationAdapter.js +26 -26
  1139. package/src/engine/intelligence/behavior/util/AsynchronousDelayAction.js +55 -55
  1140. package/src/engine/interpolation/BinaryInterpolationAdapter.js +56 -56
  1141. package/src/engine/interpolation/Interpoland.js +49 -49
  1142. package/src/engine/interpolation/Interpolated.js +149 -149
  1143. package/src/engine/interpolation/PoseInterpolationAdapter.js +61 -61
  1144. package/src/engine/interpolation/TransformPoseSerializationAdapter.js +57 -57
  1145. package/src/engine/interpolation/pose_interpoland.js +27 -27
  1146. package/src/engine/navigation/ecs/path_following/PathFollower.js +222 -222
  1147. package/src/engine/navigation/mesh/NavigationMesh.js +145 -145
  1148. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +661 -0
  1149. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +229 -229
  1150. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.d.ts.map +1 -1
  1151. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.js +628 -520
  1152. package/src/engine/network/CONGESTION_CONTROL.md +87 -87
  1153. package/src/engine/network/README.md +52 -52
  1154. package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +43 -43
  1155. package/src/engine/network/adapters/TransformInterpolationAdapter.js +84 -84
  1156. package/src/engine/network/adapters/TransformReplicationAdapter.js +87 -87
  1157. package/src/engine/network/adapters/Vector3InterpolationAdapter.js +46 -46
  1158. package/src/engine/network/convertPathToURL.js +2 -2
  1159. package/src/engine/network/core/MalformedPacketError.js +26 -26
  1160. package/src/engine/network/core/quantize/quantize_float.js +73 -73
  1161. package/src/engine/network/core/quantize/quantize_position.js +65 -65
  1162. package/src/engine/network/core/sequence/ack_bitfield.js +77 -77
  1163. package/src/engine/network/core/sequence/seq16.js +69 -69
  1164. package/src/engine/network/core/sequence/seq32.js +73 -73
  1165. package/src/engine/network/ecs/NetworkSystem.js +84 -84
  1166. package/src/engine/network/ecs/components/NetworkIdentity.js +73 -73
  1167. package/src/engine/network/ecs/owner_authorization.js +55 -55
  1168. package/src/engine/network/ecs/serialization/NetworkIdentitySerializationAdapter.js +64 -64
  1169. package/src/engine/network/replication/ScopeFilter.js +71 -71
  1170. package/src/engine/network/sim/ActionLog.js +152 -152
  1171. package/src/engine/network/sim/SimAction.js +273 -273
  1172. package/src/engine/network/sim/Snapshotter.js +222 -222
  1173. package/src/engine/network/state/FrameBufferRing.js +168 -168
  1174. package/src/engine/network/state/InputRing.js +134 -134
  1175. package/src/engine/network/state/PriorityAccumulator.js +180 -180
  1176. package/src/engine/network/time/TimeDilation.js +62 -62
  1177. package/src/engine/network/transport/Channel.js +336 -336
  1178. package/src/engine/network/transport/Transport.js +203 -203
  1179. package/src/engine/network/transport/adapters/NodeUDPTransport.js +186 -186
  1180. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +105 -105
  1181. package/src/engine/network/transport/fragments/fragment_send.js +147 -147
  1182. package/src/engine/network/transport/fragments/packet_size.js +101 -101
  1183. package/src/engine/network/xhr.js +23 -23
  1184. package/src/engine/physics/BULLET_REVIEW.md +945 -945
  1185. package/src/engine/physics/CANNON_REVIEW.md +1300 -1300
  1186. package/src/engine/physics/CONSTRAINT_SOLVER_BENCH_LOG.md +208 -208
  1187. package/src/engine/physics/CONSTRAINT_SOLVER_IMPROVEMENTS_PLAN.md +364 -364
  1188. package/src/engine/physics/INTEPOLATION_SYSTEM_PLAN.md +287 -287
  1189. package/src/engine/physics/JOLT_REVIEW.md +913 -913
  1190. package/src/engine/physics/PLAN.md +1120 -1094
  1191. package/src/engine/physics/RAPIER_REVIEW.md +934 -934
  1192. package/src/engine/physics/REVIEW_001_ACTION_PLAN.md +642 -642
  1193. package/src/engine/physics/REVIEW_002.md +151 -151
  1194. package/src/engine/physics/REVIEW_003.md +166 -166
  1195. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +97 -97
  1196. package/src/engine/physics/constraint/DofMode.js +35 -35
  1197. package/src/engine/physics/constraint/solve_constraints.js +1 -1
  1198. package/src/engine/physics/contact/combine_material.js +35 -35
  1199. package/src/engine/physics/ecs/BodyKind.js +29 -29
  1200. package/src/engine/physics/ecs/Collider.js +177 -177
  1201. package/src/engine/physics/ecs/ColliderFlags.js +15 -15
  1202. package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -37
  1203. package/src/engine/physics/ecs/Joint.js +475 -475
  1204. package/src/engine/physics/ecs/JointSerializationAdapter.js +72 -72
  1205. package/src/engine/physics/ecs/PhysicsSystem.d.ts +3 -0
  1206. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  1207. package/src/engine/physics/ecs/PhysicsSystem.js +7 -2
  1208. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.js +37 -37
  1209. package/src/engine/physics/ecs/SleepState.js +12 -12
  1210. package/src/engine/physics/ecs/find_non_finite_physics_state.js +76 -76
  1211. package/src/engine/physics/fluid/FluidField.js +867 -867
  1212. package/src/engine/physics/fluid/FluidSimulator.js +832 -832
  1213. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +243 -243
  1214. package/src/engine/physics/fluid/SliceVisualiser.js +190 -190
  1215. package/src/engine/physics/fluid/ecs/FluidComponent.js +239 -239
  1216. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -89
  1217. package/src/engine/physics/fluid/ecs/FluidObstacle.js +97 -97
  1218. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +348 -348
  1219. package/src/engine/physics/fluid/ecs/FluidSystem.js +142 -142
  1220. package/src/engine/physics/fluid/ecs/FluidWorkerCore.js +123 -123
  1221. package/src/engine/physics/fluid/ecs/WorkerFluidSystem.js +395 -395
  1222. package/src/engine/physics/fluid/ecs/fluid.worker.js +12 -12
  1223. package/src/engine/physics/fluid/ecs/fluid_build_world_to_grid.js +32 -32
  1224. package/src/engine/physics/fluid/ecs/fluid_gather_visible_effectors.js +47 -47
  1225. package/src/engine/physics/fluid/ecs/fluid_reanchor_field.js +85 -85
  1226. package/src/engine/physics/fluid/ecs/fluid_sync_effectors_from_transform.js +16 -16
  1227. package/src/engine/physics/fluid/ecs/fluid_worker_protocol.js +111 -111
  1228. package/src/engine/physics/fluid/ecs/makeFluidWorker.js +18 -18
  1229. package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -81
  1230. package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +202 -202
  1231. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +257 -257
  1232. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +405 -405
  1233. package/src/engine/physics/fluid/prototype.js +126 -126
  1234. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.js +143 -143
  1235. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.js +162 -162
  1236. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.js +107 -107
  1237. package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.js +131 -131
  1238. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +90 -90
  1239. package/src/engine/physics/fluid/solver/v3_grid_limit8_at_indices.js +38 -38
  1240. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.js +77 -77
  1241. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -113
  1242. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.js +92 -92
  1243. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -107
  1244. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +135 -135
  1245. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +511 -511
  1246. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +108 -108
  1247. package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.js +317 -317
  1248. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.js +236 -236
  1249. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.js +217 -217
  1250. package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.js +174 -174
  1251. package/src/engine/physics/fluid/solver/v3_mac_clip_trace.js +95 -95
  1252. package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.js +77 -77
  1253. package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.js +131 -131
  1254. package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.js +104 -104
  1255. package/src/engine/physics/inertia/world_inverse_inertia.js +160 -160
  1256. package/src/engine/physics/integration/integrate_position.js +97 -97
  1257. package/src/engine/physics/narrowphase/box_box_manifold.js +681 -681
  1258. package/src/engine/physics/narrowphase/box_triangle_contact.js +906 -906
  1259. package/src/engine/physics/narrowphase/capsule_triangle_contact.js +395 -395
  1260. package/src/engine/physics/narrowphase/compute_penetration.js +369 -369
  1261. package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.js +55 -55
  1262. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.js +37 -37
  1263. package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.js +117 -117
  1264. package/src/engine/physics/narrowphase/narrowphase_step.js +1738 -1738
  1265. package/src/engine/physics/narrowphase/reduce_manifold_contacts.js +74 -74
  1266. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +12 -11
  1267. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
  1268. package/src/engine/physics/narrowphase/refine_ray_hit.js +228 -36
  1269. package/src/engine/physics/narrowphase/sphere_sphere_contact.js +52 -52
  1270. package/src/engine/physics/narrowphase/sphere_triangle_contact.js +138 -138
  1271. package/src/engine/physics/persistence/solver_caches.js +309 -309
  1272. package/src/engine/physics/queries/overlap_shape.js +187 -187
  1273. package/src/engine/physics/queries/raycast.d.ts +7 -4
  1274. package/src/engine/physics/queries/raycast.d.ts.map +1 -1
  1275. package/src/engine/physics/queries/raycast.js +11 -5
  1276. package/src/engine/physics/queries/shape_cast.js +417 -417
  1277. package/src/engine/physics/solver/apply_impulse_to_body.js +86 -86
  1278. package/src/engine/physics/solver/friction_cone.js +37 -37
  1279. package/src/engine/physics/solver/solve_contacts.js +1 -1
  1280. package/src/engine/platform/WebEnginePlatform.d.ts.map +1 -1
  1281. package/src/engine/platform/WebEnginePlatform.js +1 -2
  1282. package/src/engine/scene/SerializedScene.d.ts +2 -2
  1283. package/src/engine/scene/SerializedScene.d.ts.map +1 -1
  1284. package/src/engine/scene/transitionToScene.js +121 -121
  1285. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  1286. package/src/engine/simulation/Ticker.js +33 -0
  1287. package/src/engine/sound/ecs/audio/LiveEmitterSet.js +345 -345
  1288. package/src/engine/sound/ecs/audio/SpatialAudioIndex.js +140 -140
  1289. package/src/engine/sound/simulation/AcousticSimulator.js +646 -646
  1290. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +432 -432
  1291. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +250 -250
  1292. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +322 -322
  1293. package/src/engine/sound/simulation/README.md +277 -277
  1294. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +261 -261
  1295. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +121 -121
  1296. package/src/engine/sound/simulation/configureAcousticSimulation.js +48 -48
  1297. package/src/engine/sound/simulation/core/AcousticMedium.js +113 -113
  1298. package/src/engine/sound/simulation/core/AcousticMediumSerializationAdapter.js +27 -27
  1299. package/src/engine/sound/simulation/core/AcousticOccluderIndex.js +312 -312
  1300. package/src/engine/sound/simulation/core/AcousticRegionIndex.js +159 -159
  1301. package/src/engine/sound/simulation/core/AcousticSolution.js +90 -90
  1302. package/src/engine/sound/simulation/core/AcousticSourceState.js +109 -109
  1303. package/src/engine/sound/simulation/core/AcousticVolumeRegion.js +73 -73
  1304. package/src/engine/sound/simulation/core/OcclusionSolver.js +112 -112
  1305. package/src/engine/sound/simulation/core/RayHit.js +50 -50
  1306. package/src/engine/sound/simulation/core/VolumeField.js +149 -149
  1307. package/src/engine/sound/simulation/definition/AcousticDirectivity.js +114 -114
  1308. package/src/engine/sound/simulation/definition/AcousticDirectivitySerializationAdapter.js +30 -30
  1309. package/src/engine/sound/simulation/definition/AcousticMaterial.js +122 -122
  1310. package/src/engine/sound/simulation/definition/AcousticMaterialSerializationAdapter.js +32 -32
  1311. package/src/engine/sound/simulation/ecs/AcousticBody.js +48 -48
  1312. package/src/engine/sound/simulation/ecs/AcousticBodySerializationAdapter.js +34 -34
  1313. package/src/engine/sound/simulation/ecs/AcousticProbeFieldSystem.js +64 -64
  1314. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +75 -75
  1315. package/src/engine/sound/simulation/ecs/AcousticVolume.js +74 -74
  1316. package/src/engine/sound/simulation/ecs/AcousticVolumeSerializationAdapter.js +37 -37
  1317. package/src/engine/sound/simulation/ecs/AcousticVolumeSystem.js +66 -66
  1318. package/src/engine/sound/simulation/probe/AcousticProbeField.js +578 -578
  1319. package/src/engine/sound/simulation/probe/AcousticProbeFieldSerializationAdapter.js +60 -60
  1320. package/src/engine/sound/simulation/probe/ProbeFieldPathingSolution.js +64 -64
  1321. package/src/engine/sound/simulation/probe/ProbeVisibilityRecheck.js +132 -132
  1322. package/src/engine/sound/simulation/probe/acoustic_probe_transfer.js +103 -103
  1323. package/src/engine/sound/simulation/probe/acoustic_trace_energy.js +136 -136
  1324. package/src/engine/sound/simulation/probe/bakeProbeField.js +169 -169
  1325. package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +110 -110
  1326. package/src/engine/sound/simulation/probe/bakeReverbBands.js +110 -110
  1327. package/src/engine/sound/simulation/probe/bakeVisibility.js +148 -148
  1328. package/src/engine/sound/simulation/probe/echogram_band_rt60.js +83 -83
  1329. package/src/engine/sound/simulation/probe/probe_delaunay_edges.js +215 -215
  1330. package/src/engine/sound/simulation/probe/probe_densify_portals.js +140 -140
  1331. package/src/engine/sound/simulation/probe/probe_detect_portals.js +196 -196
  1332. package/src/engine/sound/simulation/probe/probe_edge_key.js +38 -38
  1333. package/src/engine/sound/simulation/probe/probe_edge_visible.js +41 -41
  1334. package/src/engine/sound/simulation/probe/probe_place_sdf_cover.js +82 -82
  1335. package/src/engine/sound/simulation/probe/probe_refine_connectivity.js +181 -181
  1336. package/src/engine/sound/simulation/probe/probe_sdf_grid.js +171 -171
  1337. package/src/engine/sound/simulation/probe/probe_visibility_augment.js +146 -146
  1338. package/src/engine/sound/simulation/probe/probe_visibility_bridge_components.js +167 -167
  1339. package/src/engine/sound/simulation/render/FoaProbeReverbRenderer.js +354 -354
  1340. package/src/engine/sound/simulation/render/ProbeReverbRenderer.js +231 -231
  1341. package/src/engine/sound/simulation/render/foaReverbImpulseResponse.js +105 -105
  1342. package/src/engine/sound/simulation/render/reverbImpulseResponse.js +66 -66
  1343. package/src/engine/sound/simulation/render/reverb_band_tails.js +93 -93
  1344. package/src/engine/sound/simulation/serialization/populateAcousticSerializationRegistry.js +25 -25
  1345. package/src/engine/sound/sopra/README.md +643 -643
  1346. package/src/engine/sound/sopra/SopraEngine.js +432 -432
  1347. package/src/engine/sound/sopra/asset/AssetManagerBufferProvider.js +71 -71
  1348. package/src/engine/sound/sopra/asset/BufferProvider.js +29 -29
  1349. package/src/engine/sound/sopra/asset/StubBufferProvider.js +58 -58
  1350. package/src/engine/sound/sopra/definition/BusDefinition.js +142 -142
  1351. package/src/engine/sound/sopra/definition/BusDefinitionSerializationAdapter.js +54 -54
  1352. package/src/engine/sound/sopra/definition/DuckingRule.js +106 -106
  1353. package/src/engine/sound/sopra/definition/DuckingRuleSerializationAdapter.js +31 -31
  1354. package/src/engine/sound/sopra/definition/EventDescription.js +262 -262
  1355. package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +55 -55
  1356. package/src/engine/sound/sopra/definition/MixerSnapshot.js +83 -83
  1357. package/src/engine/sound/sopra/definition/MixerSnapshotSerializationAdapter.js +39 -39
  1358. package/src/engine/sound/sopra/definition/ParameterDefinition.js +117 -117
  1359. package/src/engine/sound/sopra/definition/ParameterDefinitionSerializationAdapter.js +31 -31
  1360. package/src/engine/sound/sopra/definition/VoiceStealMode.js +18 -18
  1361. package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.js +109 -109
  1362. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.js +185 -185
  1363. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.js +59 -59
  1364. package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.js +128 -128
  1365. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.js +226 -226
  1366. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClipSerializationAdapter.js +54 -54
  1367. package/src/engine/sound/sopra/definition/clip/SampleAudioClip.js +191 -191
  1368. package/src/engine/sound/sopra/definition/clip/SampleAudioClipSerializationAdapter.js +39 -39
  1369. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.js +79 -79
  1370. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClipSerializationAdapter.js +42 -42
  1371. package/src/engine/sound/sopra/definition/clip/SilenceAudioClip.js +77 -77
  1372. package/src/engine/sound/sopra/definition/clip/SilenceAudioClipSerializationAdapter.js +27 -27
  1373. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts +5 -0
  1374. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts.map +1 -1
  1375. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.js +125 -125
  1376. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClipSerializationAdapter.js +41 -41
  1377. package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +24 -24
  1378. package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +120 -120
  1379. package/src/engine/sound/sopra/definition/effect/CompressorEffectSerializationAdapter.js +31 -31
  1380. package/src/engine/sound/sopra/definition/effect/EqEffect.js +128 -128
  1381. package/src/engine/sound/sopra/definition/effect/EqEffectSerializationAdapter.js +29 -29
  1382. package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +113 -113
  1383. package/src/engine/sound/sopra/definition/effect/ReverbEffectSerializationAdapter.js +25 -25
  1384. package/src/engine/sound/sopra/runtime/BusGraph.js +231 -231
  1385. package/src/engine/sound/sopra/runtime/ParameterStore.js +98 -98
  1386. package/src/engine/sound/sopra/runtime/SopraPlaybackContext.js +68 -68
  1387. package/src/engine/sound/sopra/runtime/Voice.js +145 -145
  1388. package/src/engine/sound/sopra/runtime/VoiceManager.js +136 -136
  1389. package/src/engine/sound/sopra/runtime/VoicePool.js +17 -17
  1390. package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +42 -42
  1391. package/src/engine/sound/sopra/serialization/sopraJSON.js +99 -99
  1392. package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +49 -49
  1393. package/src/engine/sound/sopra/util/MockAudioContext.js +224 -224
  1394. package/src/engine/sound/sopra/util/fadeOutAndStop.js +60 -60
  1395. package/src/engine/ui/DraggableAspect.js +115 -115
  1396. package/src/engine/ui/apply_pointer_tilt_3d.js +50 -50
  1397. package/src/generation/COORDINATES.md +54 -54
  1398. package/src/generation/GridGenerationResource.js +24 -24
  1399. package/src/generation/GridTaskGroup.js +214 -214
  1400. package/src/generation/REVIEW_01_ACTION_PLAN.md +628 -628
  1401. package/src/generation/automata/CaveGeneratorCellularAutomata.js +79 -79
  1402. package/src/generation/automata/CellularAutomata.js +22 -22
  1403. package/src/generation/compute_writes_union.js +25 -25
  1404. package/src/generation/filtering/CellFilter.js +117 -117
  1405. package/src/generation/filtering/core/CellFilterBinaryOperation.js +37 -37
  1406. package/src/generation/filtering/core/CellFilterOperationTertiary.js +43 -43
  1407. package/src/generation/filtering/core/CellFilterUnaryOperation.js +29 -29
  1408. package/src/generation/filtering/numeric/process/computeCellFilterSobel.js +36 -36
  1409. package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.js +42 -42
  1410. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.js +18 -18
  1411. package/src/generation/filtering/numeric/util/write_cell_filter_to_sampler2d.js +47 -47
  1412. package/src/generation/filtering/util/cell_filter_weights_pick.js +54 -54
  1413. package/src/generation/grid/GridData.js +233 -233
  1414. package/src/generation/grid/coords/grid_to_texel.js +10 -10
  1415. package/src/generation/grid/coords/texel_to_grid.js +10 -10
  1416. package/src/generation/grid/generation/GridTaskApplyActionToCells.js +90 -90
  1417. package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +388 -388
  1418. package/src/generation/grid/generation/GridTaskExecuteRuleTimes.js +127 -127
  1419. package/src/generation/grid/generation/GridTaskSequence.js +58 -58
  1420. package/src/generation/grid/generation/NoopGridTaskGenerator.js +12 -12
  1421. package/src/generation/grid/generation/discrete/GridTaskActionRuleSet.js +48 -48
  1422. package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.js +146 -146
  1423. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +540 -540
  1424. package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +222 -222
  1425. package/src/generation/grid/generation/grid/GridTaskAddNodesFixed.js +44 -44
  1426. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +614 -614
  1427. package/src/generation/markers/GridCellActionPlaceMarker.js +244 -244
  1428. package/src/generation/markers/GridCellActionPlaceMarkerGroup.js +86 -86
  1429. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.js +266 -266
  1430. package/src/generation/markers/emitter/MarkerNodeEmitterGridCellAction.js +49 -49
  1431. package/src/generation/placement/GridCellActionTransformNearbyMarkers.js +120 -120
  1432. package/src/generation/placement/action/GridCellAction.js +45 -45
  1433. package/src/generation/placement/action/GridCellActionPlaceTags.js +140 -140
  1434. package/src/generation/placement/action/GridCellActionWriteFilterToLayer.js +89 -89
  1435. package/src/generation/placement/action/random/CellActionSelectRandom.js +69 -69
  1436. package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.js +91 -91
  1437. package/src/generation/placement/action/util/GridCellActionSequence.js +61 -61
  1438. package/src/generation/placement/action/util/GridCellDisplacedAction.js +61 -61
  1439. package/src/generation/rules/cell/CellMatcherRemovalPreservesConnectivity.js +183 -183
  1440. package/src/generation/theme/ThemeEngine.js +666 -666
  1441. package/src/shade/RENDERER_CONTRACT.md +568 -0
  1442. package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +267 -267
  1443. package/src/shade/device/ShadeDeviceFailure.js +104 -104
  1444. package/src/shade/device/ShadeDeviceFailureReason.js +41 -41
  1445. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +255 -255
  1446. package/src/shade/device/mock/REVIEW_2026_08_22.md +527 -527
  1447. package/src/shade/device/mock/SoftwareGPUBindGroup.js +23 -23
  1448. package/src/shade/device/mock/SoftwareGPUBindGroupLayout.js +22 -22
  1449. package/src/shade/device/mock/SoftwareGPUError.js +63 -63
  1450. package/src/shade/device/mock/SoftwareGPUPipeline.js +75 -75
  1451. package/src/shade/device/mock/SoftwareGPUQuerySet.js +113 -113
  1452. package/src/shade/device/mock/SoftwareGPUSampler.js +30 -30
  1453. package/src/shade/device/mock/SoftwareGPUShaderModule.js +32 -32
  1454. package/src/shade/device/mock/SoftwareGPUTextureView.js +22 -22
  1455. package/src/shade/device/mock/SoftwareGPUUncapturedErrorEvent.js +23 -23
  1456. package/src/shade/device/mock/normalize_dynamic_offsets.js +26 -26
  1457. package/src/shade/device/mock/texture_copy.js +287 -287
  1458. package/src/shade/device/timing/GPUTimer.js +285 -285
  1459. package/src/shade/device/timing/GPUTimerArray.js +205 -205
  1460. package/src/shade/playground/add_random_lights.js +49 -49
  1461. package/src/shade/playground/add_random_meshes.js +83 -83
  1462. package/src/shade/playground/animation_prototype.js +508 -508
  1463. package/src/shade/playground/animation_prototype_skinning.js +647 -647
  1464. package/src/shade/playground/animation_prototype_stress.js +765 -765
  1465. package/src/shade/playground/enable_picker.js +59 -59
  1466. package/src/shade/playground/gltf_skinned_prototype.js +560 -560
  1467. package/src/shade/playground/gltf_skinned_stress_prototype.js +387 -387
  1468. package/src/shade/playground/gltf_viewer.js +282 -282
  1469. package/src/shade/playground/load_default_environment.js +19 -19
  1470. package/src/shade/playground/main.js +2727 -2727
  1471. package/src/shade/playground/make_animated_instances.js +117 -117
  1472. package/src/shade/playground/prototype_virtual_texture.js +274 -274
  1473. package/src/shade/playground/prototype_volumetrics_01.js +206 -206
  1474. package/src/shade/playground/sample.js +234 -234
  1475. package/src/shade/playground/sample_load_gltf.js +102 -102
  1476. package/src/shade/playground/spread_node3d_grid.js +19 -19
  1477. package/src/shade/renderer/Renderer.js +2436 -2436
  1478. package/src/shade/renderer/ShadeIndirectLightingMode.js +14 -14
  1479. package/src/shade/renderer/animation/ShadeAnimationChannel.js +414 -414
  1480. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.js +531 -531
  1481. package/src/shade/renderer/animation/pose/PosePlayback.js +55 -55
  1482. package/src/shade/renderer/animation/pose/pose_evaluate_local.js +179 -179
  1483. package/src/shade/renderer/animation/pose/pose_evaluate_world.js +76 -76
  1484. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +1024 -1024
  1485. package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.js +79 -79
  1486. package/src/shade/renderer/animation/skinning/chunk_skin_blend_mesh_local.js +56 -56
  1487. package/src/shade/renderer/binding/BindGroupManager.js +282 -282
  1488. package/src/shade/renderer/binding/adapt_cache_capacity.js +25 -25
  1489. package/src/shade/renderer/buffer/GPUBufferAllocator.js +116 -116
  1490. package/src/shade/renderer/buffer/buffer_pool_ops.js +123 -123
  1491. package/src/shade/renderer/buffer/table/GPU_DATABASE_PAGE_SIZE.js +9 -9
  1492. package/src/shade/renderer/buffer/table/GPU_DATABASE_UPLOAD_BUFFER_LIMIT.js +8 -8
  1493. package/src/shade/renderer/buffer/table/PageBufferPool.js +71 -71
  1494. package/src/shade/renderer/buffer/table/PageSlotAllocator.js +95 -95
  1495. package/src/shade/renderer/camera/Camera.js +281 -281
  1496. package/src/shade/renderer/camera/GPUCameraContext.js +233 -233
  1497. package/src/shade/renderer/camera/orbital/README.md +84 -84
  1498. package/src/shade/renderer/deferred/shader_composite_volumetrics.js +75 -75
  1499. package/src/shade/renderer/dynamic/DYNAMIC_MESH_VERTEX.js +25 -25
  1500. package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.js +342 -342
  1501. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
  1502. package/src/shade/renderer/dynamic/shader_dynamic_mesh.js +170 -170
  1503. package/src/shade/renderer/extension/FrameContext.js +263 -263
  1504. package/src/shade/renderer/extension/FramePhase.js +104 -104
  1505. package/src/shade/renderer/extension/FrameRecord.js +126 -126
  1506. package/src/shade/renderer/extension/GBufferTextures.js +83 -83
  1507. package/src/shade/renderer/extension/PresentTarget.js +34 -34
  1508. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +918 -918
  1509. package/src/shade/renderer/extension/RenderExtension.js +69 -69
  1510. package/src/shade/renderer/extension/RenderExtensionRegistry.js +319 -319
  1511. package/src/shade/renderer/extension/SceneColor.js +40 -40
  1512. package/src/shade/renderer/extension/ViewTextures.js +78 -78
  1513. package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +182 -182
  1514. package/src/shade/renderer/geometry/Geometry.js +608 -608
  1515. package/src/shade/renderer/geometry/geometry_build_from_meshlet_geometry.js +342 -342
  1516. package/src/shade/renderer/geometry/meshlet_geometry_transfer.js +41 -41
  1517. package/src/shade/renderer/geometry/primitives/make_box_geometry.js +153 -153
  1518. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +240 -240
  1519. package/src/shade/renderer/geometry/primitives/make_plane_geometry.js +145 -145
  1520. package/src/shade/renderer/geometry/primitives/make_polyhedron_geometry.js +327 -327
  1521. package/src/shade/renderer/geometry/primitives/make_torus_geometry.js +107 -107
  1522. package/src/shade/renderer/geometry/primitives/make_torus_knot_geometry.js +165 -165
  1523. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +607 -607
  1524. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +66 -66
  1525. package/src/shade/renderer/geometry/virtual/build/VGeoBuildResult.js +32 -32
  1526. package/src/shade/renderer/geometry/virtual/build/VGeoFaceGraph.js +103 -103
  1527. package/src/shade/renderer/geometry/virtual/build/VGeoGatheredFaces.js +25 -25
  1528. package/src/shade/renderer/geometry/virtual/build/VGeoLevel.js +33 -33
  1529. package/src/shade/renderer/geometry/virtual/build/VGeoLevelOptions.js +62 -62
  1530. package/src/shade/renderer/geometry/virtual/build/VGeoLevelSummary.js +49 -49
  1531. package/src/shade/renderer/geometry/virtual/build/VGeoSubmesh.js +20 -20
  1532. package/src/shade/renderer/geometry/virtual/build/VirtualGeometryMesh.js +214 -214
  1533. package/src/shade/renderer/geometry/virtual/build/gltf/GltfByteSource.js +122 -122
  1534. package/src/shade/renderer/geometry/virtual/build/gltf/GltfCollectReport.js +29 -29
  1535. package/src/shade/renderer/geometry/virtual/build/gltf/GltfDocument.js +210 -210
  1536. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometry.js +48 -48
  1537. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometryInstance.js +25 -25
  1538. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometrySelection.js +28 -28
  1539. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_collect_geometries.js +296 -296
  1540. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.js +166 -166
  1541. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_read_geometry.js +199 -199
  1542. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +173 -173
  1543. package/src/shade/renderer/geometry/virtual/build/vgeo_bounding_sphere.js +28 -28
  1544. package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +200 -200
  1545. package/src/shade/renderer/geometry/virtual/build/vgeo_build_levels.js +1786 -1786
  1546. package/src/shade/renderer/geometry/virtual/build/vgeo_build_page_nodes.js +157 -157
  1547. package/src/shade/renderer/geometry/virtual/build/vgeo_build_root_group.js +26 -26
  1548. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_normals.js +75 -75
  1549. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_tangents.js +143 -143
  1550. package/src/shade/renderer/geometry/virtual/build/vgeo_containing_sphere.js +44 -44
  1551. package/src/shade/renderer/geometry/virtual/build/vgeo_extract_submesh.js +41 -41
  1552. package/src/shade/renderer/geometry/virtual/build/vgeo_gather_faces.js +71 -71
  1553. package/src/shade/renderer/geometry/virtual/build/vgeo_graph_components.js +123 -123
  1554. package/src/shade/renderer/geometry/virtual/build/vgeo_narrow_indices.js +26 -26
  1555. package/src/shade/renderer/geometry/virtual/build/vgeo_normalize_source.js +112 -112
  1556. package/src/shade/renderer/geometry/virtual/build/vgeo_partition_graph.js +56 -56
  1557. package/src/shade/renderer/geometry/virtual/build/vgeo_sphere_inflate_to_contain.js +70 -70
  1558. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set.js +187 -187
  1559. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set_packed.js +207 -207
  1560. package/src/shade/renderer/geometry/virtual/format/VGEO_DEFECT.js +18 -18
  1561. package/src/shade/renderer/geometry/virtual/format/VGeoDefect.js +38 -38
  1562. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +64 -64
  1563. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTE.js +13 -13
  1564. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTES.js +50 -50
  1565. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_allocate.js +28 -28
  1566. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_mask.js +23 -23
  1567. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.js +31 -31
  1568. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_vertex.js +32 -32
  1569. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.js +46 -46
  1570. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_like.js +19 -19
  1571. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.js +27 -27
  1572. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_asset_id_preimage.js +62 -62
  1573. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_asset_id.js +13 -13
  1574. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_directory_block_checksum.js +41 -41
  1575. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_frame_checksum.js +41 -41
  1576. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_header_checksum.js +25 -25
  1577. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.js +20 -20
  1578. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_RECORD_SIZE.js +5 -5
  1579. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CHILD_REF.js +5 -5
  1580. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_TRIANGLE_COUNT.js +5 -5
  1581. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_VERTEX_COUNT.js +5 -5
  1582. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_CHILD.js +5 -5
  1583. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_GROUP.js +5 -5
  1584. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_SAME_PAGE.js +6 -6
  1585. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +81 -81
  1586. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryGroup.js +37 -37
  1587. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryPageNode.js +55 -55
  1588. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_BLOCK_RECORDS.js +5 -5
  1589. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_FLAG_ROOT_PAGE.js +5 -5
  1590. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_RECORD_SIZE.js +5 -5
  1591. package/src/shade/renderer/geometry/virtual/format/directory/vgeo_directory_block_count.js +12 -12
  1592. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_OFFSET.js +11 -11
  1593. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_TABLE_ENTRY_SIZE.js +5 -5
  1594. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.js +11 -11
  1595. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_RAW.js +5 -5
  1596. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_ALIGNMENT.js +5 -5
  1597. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_HEADER_SIZE.js +5 -5
  1598. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_OFFSET.js +13 -13
  1599. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_PAGE_MAGIC.js +5 -5
  1600. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameBlob.js +21 -21
  1601. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameExtent.js +59 -59
  1602. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_codec_name.js +27 -27
  1603. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.js +84 -84
  1604. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +56 -56
  1605. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.js +35 -35
  1606. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_scan_frames.js +74 -74
  1607. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +6 -6
  1608. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HASH_ALGO_XXH3.js +5 -5
  1609. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_OFFSET.js +31 -31
  1610. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_SIZE.js +5 -5
  1611. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_OFFSET.js +20 -20
  1612. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_RECORD_SIZE.js +9 -9
  1613. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAGIC.js +5 -5
  1614. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.js +5 -5
  1615. package/src/shade/renderer/geometry/virtual/format/header/VGEO_PAYLOAD_ENCODING_SHADE_MESHLET_V1.js +5 -5
  1616. package/src/shade/renderer/geometry/virtual/format/header/VGeoLevelRecord.js +41 -41
  1617. package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_RECORD_SIZE.js +5 -5
  1618. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_GROUP_CLUSTER_COUNT.js +6 -6
  1619. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_OFFSET.js +21 -21
  1620. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_SIZE.js +5 -5
  1621. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FANOUT.js +9 -9
  1622. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FLAG_LEAF.js +5 -5
  1623. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_OFFSET.js +10 -10
  1624. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_RECORD_SIZE.js +5 -5
  1625. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_HEADER_SIZE.js +5 -5
  1626. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +16 -16
  1627. package/src/shade/renderer/geometry/virtual/format/payload/VGEO_ENCODING_FLAGS_MASK.js +6 -6
  1628. package/src/shade/renderer/geometry/virtual/format/payload/VGeoEncodedPayload.js +18 -18
  1629. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.js +200 -200
  1630. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_attribute_offset.js +39 -39
  1631. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_size.js +20 -20
  1632. package/src/shade/renderer/geometry/virtual/format/prototypeVGEOFormatViewer.js +2063 -2063
  1633. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +1622 -1622
  1634. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +485 -485
  1635. package/src/shade/renderer/gpu_primitive/sort/ffx/graph_radix_sort.js +115 -115
  1636. package/src/shade/renderer/gpu_primitive/sort/one_sweep/verify_radix_sort_one_sweep.js +110 -110
  1637. package/src/shade/renderer/light/environment/octahedral_resample_kernel.js +50 -50
  1638. package/src/shade/renderer/light/environment/octahedral_uv_to_direction.js +30 -30
  1639. package/src/shade/renderer/light/environment/resample_cube_to_octahedral.js +157 -157
  1640. package/src/shade/renderer/light/make_sunlight.js +35 -35
  1641. package/src/shade/renderer/light/model/io/light_record_point.js +39 -39
  1642. package/src/shade/renderer/loader/gltf/GLTF_PRIMITIVE_MODE.js +23 -23
  1643. package/src/shade/renderer/loader/gltf/MESHOPT_COMPRESSION_PLAN.md +793 -793
  1644. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtension.js +54 -54
  1645. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtensionSet.js +109 -109
  1646. package/src/shade/renderer/loader/gltf/ext/gltf_apply_buffer_view_extensions.js +69 -69
  1647. package/src/shade/renderer/loader/gltf/ext/gltf_buffer_view_extensions.js +22 -22
  1648. package/src/shade/renderer/loader/gltf/ext/gltf_geometry_extensions.js +39 -39
  1649. package/src/shade/renderer/loader/gltf/ext/meshopt/MeshoptBufferViewExtension.js +301 -301
  1650. package/src/shade/renderer/loader/gltf/gltf_component_type.js +223 -223
  1651. package/src/shade/renderer/loader/gltf/gltf_node_world_matrices.js +137 -137
  1652. package/src/shade/renderer/loader/gltf/gltf_parse_container.js +241 -241
  1653. package/src/shade/renderer/loader/gltf/gltf_read_accessor.js +294 -294
  1654. package/src/shade/renderer/loader/gltf/gltf_used_image_indices.js +49 -49
  1655. package/src/shade/renderer/loader/gltf/load_gltf.js +1253 -1253
  1656. package/src/shade/renderer/loader/gltf/tiny-gltf.js +646 -646
  1657. package/src/shade/renderer/loader/usd/UsdError.js +33 -33
  1658. package/src/shade/renderer/loader/usd/UsdExtensionRegistry.js +69 -69
  1659. package/src/shade/renderer/loader/usd/load_usd.js +226 -226
  1660. package/src/shade/renderer/loader/usd/parse_usda.js +931 -931
  1661. package/src/shade/renderer/loader/usd/unpack_usdz.js +106 -106
  1662. package/src/shade/renderer/loader/usd/usd_build_scene.js +658 -658
  1663. package/src/shade/renderer/loader/usd/usd_compose_transform.js +258 -258
  1664. package/src/shade/renderer/loader/usd/usd_decode_image.js +384 -384
  1665. package/src/shade/renderer/loader/usd/usd_lz4.js +182 -182
  1666. package/src/shade/renderer/loader/usd/usd_triangulate.js +159 -159
  1667. package/src/shade/renderer/material/ShadeMaterial.d.ts +2 -2
  1668. package/src/shade/renderer/material/ShadeMaterial.js +2 -2
  1669. package/src/shade/renderer/material/standard/fragment_gbuffer.js +334 -334
  1670. package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
  1671. package/src/shade/renderer/material/standard/material_gbuffer_vertex.js +45 -45
  1672. package/src/shade/renderer/material/standard_material_to_struct.js +23 -23
  1673. package/src/shade/renderer/particles/prototypeParticleSystem.js +450 -450
  1674. package/src/shade/renderer/particles/runtime/spawn_request_encoding.js +52 -52
  1675. package/src/shade/renderer/pool/TransientResourcePool.js +392 -392
  1676. package/src/shade/renderer/postprocess/bloom/bloom_chain_resolution.js +29 -29
  1677. package/src/shade/renderer/postprocess/bloom/graph_bloom_downsample.js +109 -109
  1678. package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.js +155 -155
  1679. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +114 -114
  1680. package/src/shade/renderer/postprocess/dof/DOF_AUTOFOCUS_PARAMS_STRUCT.js +25 -25
  1681. package/src/shade/renderer/postprocess/dof/DOF_FOCUS_STATE_STRUCT.js +23 -23
  1682. package/src/shade/renderer/postprocess/dof/DOF_PRESETS.js +27 -27
  1683. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_diameter.js +41 -41
  1684. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_radius.js +32 -32
  1685. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_coefficient.js +26 -26
  1686. package/src/shade/renderer/postprocess/dof/compute_dof_autofocus_params.js +64 -64
  1687. package/src/shade/renderer/postprocess/dof/compute_dof_uniform.js +54 -54
  1688. package/src/shade/renderer/postprocess/dof/gather/DOF2_CONFIG.js +91 -91
  1689. package/src/shade/renderer/postprocess/dof/gather/DOF2_PRESETS.js +9 -9
  1690. package/src/shade/renderer/postprocess/dof/gather/DOF2_SETTINGS_STRUCT.js +66 -66
  1691. package/src/shade/renderer/postprocess/dof/gather/DOF2_TEXTURE_FORMAT.js +22 -22
  1692. package/src/shade/renderer/postprocess/dof/gather/DepthOfFieldU.js +292 -292
  1693. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_coc_to_near_far.js +25 -25
  1694. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_gather_weight.js +30 -30
  1695. package/src/shade/renderer/postprocess/dof/gather/compute_dof2_uniform.js +54 -54
  1696. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +194 -194
  1697. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_fill.js +68 -68
  1698. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +140 -140
  1699. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +142 -142
  1700. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +99 -99
  1701. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +102 -102
  1702. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_dilate.js +75 -75
  1703. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_max.js +73 -73
  1704. package/src/shade/renderer/postprocess/dof/raymarch/DOF_SETTINGS_STRUCT.js +49 -49
  1705. package/src/shade/renderer/postprocess/dof/raymarch/DepthOfField.js +298 -298
  1706. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +244 -244
  1707. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +91 -91
  1708. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_firefly_cleanup.js +61 -61
  1709. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +90 -90
  1710. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +267 -267
  1711. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +271 -271
  1712. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_dilate.js +70 -70
  1713. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_max.js +72 -72
  1714. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +99 -99
  1715. package/src/shade/renderer/postprocess/gtao/generate_magic_square_noise.js +51 -51
  1716. package/src/shade/renderer/postprocess/motion_blur/MotionBlur.js +56 -56
  1717. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +78 -78
  1718. package/src/shade/renderer/postprocess/upscale-dither/UpscaleDither.js +95 -95
  1719. package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +204 -204
  1720. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +58 -58
  1721. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +230 -230
  1722. package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.js +278 -278
  1723. package/src/shade/renderer/rasterize/native/oit/chunk_material_side_should_draw.js +26 -26
  1724. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +178 -178
  1725. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +235 -235
  1726. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +208 -208
  1727. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +206 -206
  1728. package/src/shade/renderer/scene/DynamicMesh.js +70 -70
  1729. package/src/shade/renderer/scene/DynamicMeshBatch.js +90 -90
  1730. package/src/shade/renderer/scene/GPUSceneContext.js +901 -901
  1731. package/src/shade/renderer/scene/SceneNodeBinding.js +56 -56
  1732. package/src/shade/renderer/scene/SkinnedMesh.js +55 -55
  1733. package/src/shade/renderer/scene/TransformAuthority.js +33 -33
  1734. package/src/shade/renderer/scene/optimization/deduplicate_geometries.js +38 -38
  1735. package/src/shade/renderer/scene/optimization/deduplicate_images.js +93 -93
  1736. package/src/shade/renderer/scene/optimization/geometry/internal/match_refit_validate.js +127 -127
  1737. package/src/shade/renderer/scene/optimization/geometry/internal/match_solve_transform.js +492 -492
  1738. package/src/shade/renderer/scene/optimization/optimize_texture_set.js +81 -81
  1739. package/src/shade/renderer/scene/optimization/source_to_sampler2d.js +21 -21
  1740. package/src/shade/renderer/scene/serialization/STANDARD_MATERIAL_SERIALIZED_BYTE_SIZE.js +12 -12
  1741. package/src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_transform_point.js +26 -26
  1742. package/src/shade/renderer/shader/chunk/noise/chunk_interleaved_gradient_noise.js +20 -20
  1743. package/src/shade/renderer/shader/chunk/spherical_harmonics/dering/chunk_sh2_dering_optimize_positive.js +61 -61
  1744. package/src/shade/renderer/shader/chunk/texture/chunk_texture_filter_fxaa_lite.js +225 -225
  1745. package/src/shade/renderer/shader/chunk/texture/dither/chunk_dither_color_8bit_gradient_noise.js +25 -25
  1746. package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.js +384 -384
  1747. package/src/shade/renderer/shadow/map/PointLightShadowmap.js +105 -105
  1748. package/src/shade/renderer/shadow/map/SpotLightShadowmap.js +63 -63
  1749. package/src/shade/renderer/shadow/map/TetrahedronPointLightShadowmap.js +89 -89
  1750. package/src/shade/renderer/shadow/map/shadowmap_update_score.js +232 -232
  1751. package/src/shade/renderer/texture/GPUTextureAllocator.js +85 -85
  1752. package/src/shade/renderer/texture/texture_pool_ops.js +171 -171
  1753. package/src/shade/renderer/texture/virtual/PageTableQuadAllocator.js +253 -253
  1754. package/src/shade/renderer/texture/virtual/README.md +276 -276
  1755. package/src/shade/renderer/texture/virtual/VTPageTable.js +330 -330
  1756. package/src/shade/renderer/texture/virtual/VTPhysicalCache.js +349 -349
  1757. package/src/shade/renderer/texture/virtual/VT_CONSTANTS.js +154 -154
  1758. package/src/shade/renderer/texture/virtual/VT_STACK_INFO_STRUCT.js +20 -20
  1759. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +1276 -1276
  1760. package/src/shade/renderer/texture/virtual/VirtualTextureStack.js +106 -106
  1761. package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.js +150 -150
  1762. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +232 -232
  1763. package/src/shade/renderer/texture/virtual/chunk_vt_request_key.js +28 -28
  1764. package/src/shade/renderer/texture/virtual/source/VTSourceImage.js +207 -207
  1765. package/src/shade/renderer/texture/virtual/source/VTSourceProcedural.js +135 -135
  1766. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.js +132 -132
  1767. package/src/shade/renderer/water/GPUWaterRenderer.js +167 -167
  1768. package/src/shade/renderer/water/shader_water.js +246 -246
  1769. package/src/shade/renderer/water/water_height_texture_from_sampler.js +56 -56
  1770. package/src/shade/vitest.setup.mjs +89 -89
  1771. package/src/shade/wgsl/validate_wgsl_source.js +316 -316
  1772. package/src/view/controller/controls/NumericIntervalControl.js +90 -90
  1773. package/src/view/controller/controls/Vector2Control.js +83 -83
  1774. package/src/view/controller/controls/Vector3Control.js +90 -90
  1775. package/src/view/elements/Group.js +56 -56
  1776. package/src/view/elements/drawCheckers.js +33 -33
  1777. package/src/view/elements/windrose/WindRoseDiagram.js +369 -369
  1778. package/src/view/graphics/WebGLContextFailureView.js +76 -76
  1779. package/src/view/layout/DockPanel.js +51 -51
  1780. package/src/view/layout/SplitView.js +365 -365
  1781. package/src/view/layout/show_popup_menu.js +81 -81
  1782. package/src/view/minimap/MinimapCanvasView.js +411 -411
  1783. package/src/view/minimap/MinimapImageCache.js +88 -88
  1784. package/src/view/minimap/MinimapMarkerCollection.d.ts +0 -1
  1785. package/src/view/minimap/MinimapMarkerCollection.d.ts.map +1 -1
  1786. package/src/view/minimap/MinimapMarkerCollection.js +180 -180
  1787. package/src/view/minimap/dom/MinimapCameraView.js +206 -206
  1788. package/src/view/minimap/minimap_focus_area.js +97 -97
  1789. package/editor/process/symbolic/SocketsSymbolicDisplay.js +0 -192
  1790. package/src/core/geom/3d/topology/struct/binary/io/moved_tests.txt +0 -37
  1791. package/src/engine/ecs/attachment/Attachment.d.ts +0 -40
  1792. package/src/engine/ecs/attachment/Attachment.d.ts.map +0 -1
  1793. package/src/engine/ecs/attachment/Attachment.js +0 -57
  1794. package/src/engine/ecs/attachment/AttachmentBinding.d.ts +0 -28
  1795. package/src/engine/ecs/attachment/AttachmentBinding.d.ts.map +0 -1
  1796. package/src/engine/ecs/attachment/AttachmentBinding.js +0 -41
  1797. package/src/engine/ecs/attachment/AttachmentSystem.d.ts +0 -61
  1798. package/src/engine/ecs/attachment/AttachmentSystem.d.ts.map +0 -1
  1799. package/src/engine/ecs/attachment/AttachmentSystem.js +0 -307
  1800. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts +0 -27
  1801. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts.map +0 -1
  1802. package/src/engine/ecs/attachment/BoneAttachmentBinding.js +0 -69
  1803. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts +0 -4
  1804. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts.map +0 -1
  1805. package/src/engine/ecs/attachment/TransformAttachmentBinding.js +0 -51
  1806. package/src/engine/ecs/sockets/AttachmentSocket.d.ts +0 -32
  1807. package/src/engine/ecs/sockets/AttachmentSocket.d.ts.map +0 -1
  1808. package/src/engine/ecs/sockets/AttachmentSocket.js +0 -60
  1809. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts +0 -6
  1810. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts.map +0 -1
  1811. package/src/engine/ecs/sockets/AttachmentSocketType.js +0 -8
  1812. package/src/engine/ecs/sockets/AttachmentSockets.d.ts +0 -57
  1813. package/src/engine/ecs/sockets/AttachmentSockets.d.ts.map +0 -1
  1814. package/src/engine/ecs/sockets/AttachmentSockets.js +0 -130
  1815. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts +0 -29
  1816. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts.map +0 -1
  1817. package/src/engine/ecs/sockets/BoneAttachmentSocket.js +0 -56
  1818. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts +0 -6
  1819. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts.map +0 -1
  1820. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.js +0 -19
  1821. package/src/shade/renderer/animation/_dump_resolve.d.mts +0 -2
  1822. package/src/shade/renderer/animation/_dump_resolve.d.mts.map +0 -1
  1823. package/src/shade/renderer/animation/_dump_resolve.mjs +0 -5
@@ -1,793 +1,793 @@
1
- # `EXT_meshopt_compression` / `KHR_meshopt_compression` — implementation plan
2
-
3
- Status: plan. Written 2026-08-20.
4
-
5
- Scope: decode side of both extensions.
6
-
7
- - `EXT_meshopt_compression` — ratified, Vendor.
8
- <https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Vendor/EXT_meshopt_compression>
9
- - `KHR_meshopt_compression` — ratified, Khronos, merged 2026-01-23 (PR #2517).
10
- <https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_meshopt_compression>
11
-
12
- Reference encoder/decoder: <https://github.com/zeux/meshoptimizer>. Consulted for questions the
13
- specification text leaves ambiguous; **not vendored and not transcribed** — no new dependency, and
14
- the bitstream below is implemented from the two specifications.
15
-
16
- ## 1. What these extensions are, and why that shapes the split
17
-
18
- Neither is a geometry extension. Both are *bufferView* extensions: a bufferView declares that its
19
- bytes are produced by running a decoder over a byte range of some other buffer. Nothing about the
20
- decode depends on what the bufferView is later read as — vertex attributes, index data, morph
21
- deltas, animation keyframes and `EXT_mesh_gpu_instancing` transforms all go through the same three
22
- modes and (now) five filters.
23
-
24
- That is the seam. Everything except roughly two dozen lines is a **byte-array in, byte-array out**
25
- codec with no knowledge of glTF at all:
26
-
27
- ```
28
- src/core/binary/meshopt/ pure codec — bytes in, bytes out.
29
- ^ No glTF, no geometry, no engine.
30
- | called by
31
- src/.../gltf/ext/meshopt/ one bufferView's worth of meshopt: read the
32
- ^ extension object, check it, return the bytes.
33
- | called through GltfBufferViewExtension by
34
- src/.../gltf/ext/ the generic bufferView-extension layer — which
35
- ^ extension claims a view, and what becomes of what
36
- | it produced. Names no codec.
37
- | called by
38
- src/shade/renderer/loader/gltf/tiny-gltf.js one call, after buffers resolve. Names no
39
- extension at all.
40
- ```
41
-
42
- `core/binary` is the codec's right home: it is where meep already keeps byte-level codecs
43
- (`base64/`, `base58/`, `half_to_float_uint16`, `BinaryBuffer`'s LEB128 `readUintVar`). The codec
44
- imports nothing outside `core/`, so it is usable from a worker, a tool, or the USD loader without
45
- dragging Shade in.
46
-
47
- ### 1.1 KHR is EXT plus three things
48
-
49
- The two extensions share a JSON shape, a `bufferView`/`buffer` model, fallback buffers, and modes
50
- 1 and 2 byte for byte. KHR adds:
51
-
52
- 1. **Attribute codec version 1** (header `0xa1`). A genuinely different bitstream for mode 0: a
53
- per-block control header, four control modes, an extra 1-bit sentinel encoding, and three
54
- *channel* modes that widen the delta from 8-bit to 16-bit or to a rotated 32-bit XOR.
55
- Version 0 (`0xa0`) remains legal under KHR and is bit-identical to EXT.
56
- 2. **Filter 4, `COLOR`** — YCoCg, `byteStride` 4 or 8.
57
- 3. One extra validity rule (`ATTRIBUTES` requires `byteStride >= 4`) and the constraint that a
58
- bufferView must not carry both extensions.
59
-
60
- So there is one codec that decodes everything, and a glTF layer that enforces the per-name subset:
61
- a `0xa1` stream or a `COLOR` filter under the `EXT_` name is an invalid file and is rejected.
62
-
63
- ## 2. Modules
64
-
65
- ### 2.1 `src/core/binary/meshopt/` — the codec
66
-
67
- | File | Export |
68
- |:--|:--|
69
- | `MeshoptCompressionMode.js` | `@enum` — `Attributes: 0`, `Triangles: 1`, `Indices: 2` |
70
- | `MeshoptCompressionFilter.js` | `@enum` — `None: 0`, `Octahedral: 1`, `Quaternion: 2`, `Exponential: 3`, `Color: 4` |
71
- | `MESHOPT_GROUP_SIZE.js` | the group size, and the 24-byte bound a group read stays inside |
72
- | `meshopt_decode_byte_group.js` | one group of 16 byte-deltas at a given sentinel width |
73
- | `meshopt_decode_data_block.js` | one "data block": header bits + its groups, for one byte position |
74
- | `meshopt_decode_vertex_buffer.js` | mode 0, versions 0 and 1 |
75
- | `meshopt_decode_index_buffer.js` | mode 1 |
76
- | `meshopt_decode_index_sequence.js` | mode 2 |
77
- | `meshopt_decode_filter_octahedral.js` | filter 1, in place |
78
- | `meshopt_decode_filter_quaternion.js` | filter 2, in place |
79
- | `meshopt_decode_filter_exponential.js` | filter 3, in place |
80
- | `meshopt_decode_filter_color.js` | filter 4, in place |
81
- | `meshopt_decode.js` | dispatch: mode, then filter |
82
- | `meshopt_read_uint_var.js` | bounded LEB128 over a `Uint8Array` |
83
- | `__meshopt_test_streams.js` | test-only encoders, shared by the codec specs and the glTF fixtures |
84
-
85
- Signatures:
86
-
87
- ```js
88
- meshopt_decode_vertex_buffer(destination, count, byte_stride, source)
89
- meshopt_decode_index_buffer(destination, index_count, index_size, source)
90
- meshopt_decode_index_sequence(destination, index_count, index_size, source)
91
- meshopt_decode_filter_*(destination, count, byte_stride)
92
- meshopt_decode(destination, count, byte_stride, mode, filter, source)
93
- ```
94
-
95
- `destination` and `source` are `Uint8Array` throughout — the codec never assumes an aligned
96
- `ArrayBuffer` offset, because a compressed source range in a glTF is only byte-aligned. Index modes
97
- and filters build their typed views internally from `index_size` / `byte_stride`.
98
-
99
- Two additions outside the package, both genuinely generic and both matching meep's existing naming:
100
-
101
- - `src/core/math/round_half_away_from_zero.js` — `Math.round` breaks ties toward `+Infinity`
102
- (`Math.round(-2.5) === -2`). Four of the five filters specify `round()` on a signed symmetric
103
- quantity and round half away from zero. Sits beside the existing `round_up.js`.
104
- - nothing else: `msb_32` (`core/binary`) is already `findMSB` including its `-1` for zero, `exp2`
105
- and `copysign` (`core/math`) already exist, and `decode_octahedron_to_unit`
106
- (`core/geom/3d/normal/octahedron`) is reused by filter 1 — see §4.1.
107
-
108
- ### 2.2 `src/shade/renderer/loader/gltf/ext/` — bufferView extensions, generically
109
-
110
- A bufferView extension says "these bytes are not in the buffer I point at; run this to get them".
111
- Meshopt is two of them; a future codec would be a third. The parser should know that shape and
112
- nothing else, so the layer is split in two — see §9 for why this is not how it was first written.
113
-
114
- | File | What it is |
115
- |:--|:--|
116
- | `GltfBufferViewExtension.js` | the contract one extension implements: a `name`, `decode()`, and whether it declares placeholder buffers |
117
- | `GltfBufferViewExtensionSet.js` | which extensions a parser honours, and `claim(view)` — the *only* thing that decides whether anything happens |
118
- | `gltf_apply_buffer_view_extensions.js` | the walk: claim, delegate, append the buffer, replace the descriptor. Identical for every extension |
119
- | `gltf_buffer_view_extensions.js` | `GLTF_BUFFER_VIEW_EXTENSIONS`, the set the parser uses by default |
120
- | `meshopt/MeshoptBufferViewExtension.js` | one class, two instances: `EXT_MESHOPT_COMPRESSION`, `KHR_MESHOPT_COMPRESSION` |
121
-
122
- The walker:
123
-
124
- 1. returns a **new** `bufferViews` array — claimed entries are replaced by fresh descriptors,
125
- unclaimed entries pass through **by reference**,
126
- 2. **appends** each decoded buffer to `buffers`, pointing the new descriptor at it with
127
- `byteOffset: 0`,
128
- 3. keeps `byteStride`, `target` and everything else from the parent, so accessor reads are unchanged,
129
- 4. refuses a decoder that answered with the wrong number of bytes, whichever decoder it was.
130
-
131
- Returning a new array rather than mutating the old descriptors is load-bearing, not taste — §6.3.
132
-
133
- The difference between the two meshopt instances is two fields and no branches: which filter names
134
- the extension defines, and the newest codec version each *mode* may carry. Per mode because both
135
- index codecs' version 1 is legal under either extension; it is only the attribute codec that the
136
- vendor extension pins at 0.
137
-
138
- ### 2.3 `tiny-gltf.js` — the call site
139
-
140
- Three edits, all in `loadFromJson`:
141
-
142
- - **`~L422-448`, buffer resolution.** Today a buffer with no `uri` outside the GLB fast path is fed
143
- to `resolveUri(undefined, baseUrl)` and fetched as `<baseUrl>undefined`. That is exactly the shape
144
- of a meshopt *fallback* buffer (`{ "byteLength": N }`, no URI), so today a `gltfpack`-produced
145
- `.gltf` cannot load at all. A buffer that is marked `fallback` or has no `uri` resolves to a
146
- zero-length `ArrayBuffer` instead of a request (§6.8). Also: the GLB branch currently loads *only*
147
- the binary chunk and ignores `buffers[1..n]`, which is where both extensions put the placeholder —
148
- the branch becomes "buffer 0 is the chunk, the rest resolve normally".
149
- - **`~L524-534`, an image sourced from a bufferView.** Throw if that bufferView is compressed. The
150
- combination is legal in the abstract and pointless in practice (the payload is already a PNG or a
151
- JPEG); the alternative to throwing is handing `createImageBitmap` the fallback buffer's bytes,
152
- which is a silent wrong answer.
153
- - **`~L557`, after `await Promise.all(pendingBuffers)`.** One call to
154
- `gltf_apply_buffer_view_extensions` before `json.buffers` and `json.bufferViews` are published.
155
-
156
- The parser names no extension: it asks `this.bufferViewExtensions` — a public field, defaulted to the
157
- standard set and replaceable — and the set is the one place that knows what is implemented.
158
-
159
- **Nothing in `load_gltf.js` changes.** It reads `gltf.bufferViews` / `gltf.buffers` inside
160
- `process()`, which runs after `loadFromJson` has returned, so it sees decoded views and never learns
161
- either extension exists. That is the point of doing this at the bufferView layer.
162
-
163
- ## 3. The bitstream, as implemented
164
-
165
- Written from the two specifications' Appendix A/B. Notes marked ⚠ are places where a plausible
166
- reading is wrong.
167
-
168
- ### 3.1 Mode 0 — attributes
169
-
170
- ```
171
- header 1 byte: 0xa0 (version 0) or 0xa1 (version 1, KHR only)
172
- blocks one or more attribute blocks
173
- tail padding zero bytes
174
- tail block baseline element (byte_stride bytes)
175
- channel modes (byte_stride / 4 bytes, version 1 only)
176
- ```
177
-
178
- ⚠ **The padding comes BEFORE the tail block; the tail block is flush against the end of the
179
- stream.** So the baseline element starts at `byteLength - tail_size`, where
180
-
181
- ```
182
- tail_size = byte_stride + (version === 1 ? byte_stride / 4 : 0)
183
- tail_size_pad = max(tail_size, version === 1 ? 24 : 32)
184
- ```
185
-
186
- and the decoder must have consumed exactly `byteLength - tail_size_pad` bytes when the blocks are
187
- done. EXT's wording — "a baseline element stored verbatim, padded to 32 bytes" — reads equally well
188
- as element-then-padding, which for any stride below 32 puts the baseline in the wrong place and
189
- decodes garbage. KHR's rewording ("Tail padding, which pads the size of the *subsequent* tail
190
- block…") settles it, and the reference decoder agrees: it takes the baseline from
191
- `data_end - tail_size`, with `tail_size` **unpadded**, while validating the remainder against
192
- `tail_size_pad`. Two different quantities that coincide only when `byte_stride >= 32`.
193
-
194
- Block loop, identical in both versions:
195
-
196
- ```
197
- max_block_elements = min(floor(8192 / byte_stride) & ~15, 256)
198
- block_elements = min(remaining, max_block_elements)
199
- group_count = ceil(block_elements / 16)
200
- ```
201
-
202
- ⚠ `8192 / byte_stride` is integer division — `floor` before the mask. With `byte_stride <= 256` the
203
- result is never below 32, so the loop always advances.
204
-
205
- A block is, in order:
206
-
207
- - a **control header** of `byte_stride / 4` bytes — **version 1 only**,
208
- - `byte_stride` **data blocks**, one per byte position `k` of the element.
209
-
210
- The control header packs a 2-bit *control mode* per byte position, low bits first:
211
- `(c0 << 0) | (c1 << 2) | (c2 << 4) | (c3 << 6)`, one byte per aligned group of four byte positions.
212
- The control mode selects what the data block for that byte position looks like:
213
-
214
- | control mode | data block |
215
- |:--|:--|
216
- | 0 | header bits, group encodings `{zero, 1-bit, 2-bit, 4-bit}` |
217
- | 1 | header bits, group encodings `{1-bit, 2-bit, 4-bit, raw}` |
218
- | 2 | nothing at all — every delta byte is 0, no header bits, no bytes consumed |
219
- | 3 | literal: `group_count * 16` delta bytes, no header bits |
220
-
221
- Version 0 has no control header and behaves as a fixed table
222
- `{zero, 2-bit, 4-bit, raw}` for every byte position.
223
-
224
- Where header bits are present they are `ceil(group_count / 4)` bytes, 2 bits per group, packed
225
- **low bits first**: `(g0 << 0) | (g1 << 2) | (g2 << 4) | (g3 << 6)`. Group encodings:
226
-
227
- | encoding | packed bytes | sentinel | total |
228
- |:--|:--|:--|:--|
229
- | zero | 0 | — | 0 |
230
- | 1-bit | 2 | `1` | 2..18 |
231
- | 2-bit | 4 | `3` | 4..20 |
232
- | 4-bit | 8 | `15` | 8..24 |
233
- | raw | 16 | — | 16 |
234
-
235
- ⚠ Bit order inside a packed byte is **not uniform**. 2-bit and 4-bit run high bits first —
236
- `(d3 << 0) | (d2 << 2) | (d1 << 4) | (d0 << 6)` and `(d1 << 0) | (d0 << 4)` — while **1-bit runs low
237
- bits first**, `(d0 << 0) | (d1 << 1) | … | (d7 << 7)`. The spec says so explicitly (it is there to
238
- let SIMD implementations reuse a lookup table); it is not a transcription slip.
239
-
240
- A delta equal to the sentinel means the real value is outside the bit range and is taken as a whole
241
- byte from the run that follows the packed bytes, in order of appearance.
242
-
243
- The delta bytes so recovered are then turned into values by the **channel mode**. Channels are
244
- aligned groups of four byte positions; version 1 stores one mode byte per channel in the tail, and
245
- version 0 behaves as though every channel were mode 0.
246
-
247
- | channel mode | reconstruction |
248
- |:--|:--|
249
- | 0 | per byte: `v = (unzigzag8(d) + prev) & 0xff` |
250
- | 1 | per aligned 2 bytes, little-endian: `v = (unzigzag16(d) + prev) & 0xffff` |
251
- | 2 | per aligned 4 bytes, little-endian: `v = rotl32(d, r) ^ prev` |
252
-
253
- `r` is the **high** 4 bits of the channel mode byte and applies only to mode 2. ⚠ The decoder
254
- rotates **left by `r`** — the spec's `rotate(v, r) = (v << r) | (v >> ((32 - r) & 31))` is the
255
- decode direction, despite the surrounding sentence describing how the encoder produced the delta.
256
- A mode byte whose low nibble is 3 or above, or whose high nibble is non-zero for mode 0 or 1, makes
257
- the stream invalid.
258
-
259
- Groups always decode sixteen elements; anything past `block_elements` is discarded and does not
260
- advance the delta chain. Each block ends by taking its **last decoded element** as the next block's
261
- baseline.
262
-
263
- The specification's own worked example is the acceptance test for the group decoder (§5.1).
264
-
265
- ### 3.2 Mode 1 — triangles
266
-
267
- ```
268
- header 1 byte, (h & 0xf0) == 0xe0; version = h & 0x0f, 0 or 1 (both specs pin 0xe1)
269
- codes index_count / 3 bytes, one per triangle
270
- data variable, immediately after the codes
271
- codeaux the last 16 bytes
272
- ```
273
-
274
- State: `next` (high-watermark, 0), `last` (0), a 16-entry edge FIFO and a 16-entry vertex FIFO, both
275
- filled with `0xFFFFFFFF`. `data` must end exactly at the start of `codeaux` — that equality is the
276
- stream's own checksum.
277
-
278
- `fec_max` is 13 for version 1 and 15 for version 0; it is what makes codes `0xXd`/`0xXe` mean
279
- `last - 1` / `last + 1` rather than two more FIFO slots. Reading it from the header rather than
280
- hard-coding 13 is why both versions decode correctly.
281
-
282
- ⚠ The two branches index the vertex FIFO differently: the `code < 0xf0` path reads
283
- `(offset - 1 - fec) & 15`, the `0xf0..0xff` paths read `(offset - feb) & 15`. This follows from the
284
- spec's own wording ("index Y" versus "index Z-1") and is not a slip.
285
-
286
- ⚠ A conditional push writes the value at `offset` and then does not advance `offset`. Skipping the
287
- write as well is *not* equivalent: every later FIFO read at distance `d` would see what belongs at
288
- `d - 1`. Two tests reach back past a vertex that was not pushed, because until something does the
289
- difference is invisible.
290
-
291
- ⚠ The explicit indices in the `0xfe`/`0xff` branch are read in the order a, b, c, and `last` chains
292
- through them, so that order is load-bearing. Their position relative to the `next++` allocations is
293
- *not*: an index is either fresh or explicit, never both, so the two passes do not interfere. (The
294
- plan asserted otherwise; see §8.)
295
-
296
- ### 3.3 Mode 2 — indices
297
-
298
- ```
299
- header 1 byte, (h & 0xf0) == 0xd0 (both specs pin 0xd1)
300
- deltas one LEB128 varint per index
301
- tail 4 reserved bytes
302
- ```
303
-
304
- `v & 1` selects one of two running baselines; `v >> 1` is a zigzag delta applied to it. Two
305
- baselines rather than one is what lets an encoder splice two monotonic runs (strips, line lists)
306
- cheaply. Again `data` must land exactly on the 4-byte tail.
307
-
308
- ### 3.4 Filters
309
-
310
- All five are in place over the already-decoded bufferView, `count` elements of `byte_stride` bytes.
311
-
312
- - **Octahedral** — `byte_stride` 4 → `Int8Array`, 8 → `Int16Array`. Components 0 and 1 are the
313
- octahedral pair, component 2 encodes 1.0 at the element's own precision `K`, component 3 passes
314
- through untouched. Output scaled by `max` = 127 or 32767. Reuses meep's own
315
- `decode_octahedron_to_unit` — see §4.1.
316
- - **Quaternion** — `byte_stride` 8, `Int16Array`. `one = input[3] | 3`,
317
- `max_component = input[3] & 3`; outputs land at `(max_component + 1..3) & 3` for x/y/z and
318
- `(max_component + 0) & 3` for w.
319
- ⚠ `input[3]` is read for *both* purposes before any output is written — one of the four writes
320
- lands on it.
321
- ⚠ The radicand `1 - x² - y² - z²` is clamped at 0. meep already learned this in
322
- `quat3_decode_from_uint32`; a NaN quaternion out of a loader poisons every transform downstream.
323
- - **Exponential** — `byte_stride` divisible by 4. Each 32-bit word is `e = word >> 24` (signed),
324
- `m = (word << 8) >> 8` (signed); the result `2^e · m` is written back as a float32. `e` is
325
- spec-bounded to [-100, 100] and `|m| < 2^23`, so the product is exact in float32 and computing it
326
- in JS doubles and storing through a `Float32Array` is bit-identical to the reference's
327
- build-the-exponent-and-multiply.
328
- - **Color** (KHR only) — `byte_stride` 4 → `Uint8Array`, 8 → `Uint16Array`. YCoCg:
329
-
330
- ```
331
- as = (1 << (msb_32(input[3]) + 1)) - 1
332
- r = input[0] + int(input[1]) - int(input[2])
333
- g = input[0] + int(input[2])
334
- b = input[0] - int(input[1]) - int(input[2])
335
- a = input[3] & (as >> 1); a = (a << 1) | (a & 1)
336
- output = round(component * (UINTN_MAX / as))
337
- ```
338
-
339
- ⚠ Components 0 and 3 are **unsigned**, components 1 and 2 are **signed**, in the same element.
340
- `msb_32` already returns `-1` for zero, so a malformed `input[3] === 0` yields `as = 0`, an
341
- infinite scale, and finite garbage bytes once stored through a `Uint8Array` — defined, ugly, and
342
- not worth a guard (§6.9).
343
-
344
- ## 4. What is reused, and what deliberately is not
345
-
346
- ### 4.1 Reused
347
-
348
- - **`decode_octahedron_to_unit`** (`core/geom/3d/normal/octahedron`) implements filter 1's core.
349
- meep's fold is the same arithmetic as the spec's `copysign` form (`x + t·sign(x)` either way) and
350
- it renormalises, but it is written **Y-up**: meep's `(x, y, z)` is the spec's `(x, z, y)`. The
351
- swizzle is the whole of the adaptation, and a spec checks the composition against the
352
- specification's formula directly rather than against meep's.
353
- - **`msb_32`** (`core/binary`) is `findMSB` for filter 4, `-1`-on-zero included.
354
- - **`exp2`** and **`copysign`** (`core/math`).
355
- - **`gltf_test_fixtures.js`** (`engine/asset/loaders`) already builds a one-triangle glTF and GLB by
356
- hand; the end-to-end fixture extends it rather than introducing a second fixture vocabulary.
357
-
358
- ### 4.2 Deliberately not
359
-
360
- - **`BinaryBuffer.readUintVar`** is the same LEB128 scheme and reusing it would honour "use meep's
361
- existing code". It is still wrong here: it reads through a `DataView` bound to a whole
362
- `ArrayBuffer` where the compressed range is a slice, it is unbounded on malformed input where the
363
- reference stops at five bytes, and `value |= (b & 0x7f) << shift` turns negative once `shift`
364
- reaches 28 — which is inside the range mode 1 and mode 2 indices legitimately use. The deviation
365
- and its three reasons are documented where `meshopt_read_uint_var` is defined, so the next reader
366
- does not "fix" the duplication.
367
- - **`quat3_decode_from_uint32`** is a different packing — 10-bit, fixed range, dropped component
368
- inserted *at* index `max` — where filter 2 is 16-bit, variable precision and *cyclic*. Documented
369
- as deliberately not reused rather than left to look overlooked.
370
- - **`Vector3` / `Quaternion` / `vec3` helpers.** The filters run over hundreds of thousands of
371
- elements through typed-array views; routing each through an object allocation would be the one
372
- place in this feature where reuse costs more than it is worth. Scalars, module-static scratch.
373
-
374
- ## 5. Tests
375
-
376
- Every module gets a `.spec.js` beside it. House rules apply: black-box, no mocks, and no rejection
377
- tests against `assert.*` (stripped in production) — everything that must reject bad *file* input
378
- does so with a real `throw`, and those are tested.
379
-
380
- ### 5.1 The independent oracle
381
-
382
- The single most valuable test is free: **Appendix A of both specifications contains a worked
383
- example** of the 4-bit sentinel encoding —
384
-
385
- ```
386
- 0x17 0x5f 0xf0 0xbc 0x77 0xa9 0x21 0x00 0x34 0xb5
387
- -> -1 -4 -3 26 -91 0 -6 6 -4 -4 5 -5 1 -1 0 0
388
- ```
389
-
390
- — which pins the packed-nibble order, the sentinel value, the sentinel run's position and its
391
- ordering, and the zigzag, all at once, from a document that is not this implementation. It is the
392
- first test written, and the group decoder is developed against it. (Checked by hand while writing
393
- this plan: the nibbles are `1 7 5 S S 0 11 12 7 7 10 9 2 1 0 0`, the two sentinels take `0x34` and
394
- `0xb5`, and de-zigzagging reproduces the stated line exactly.)
395
-
396
- ### 5.2 Hand-derived vectors
397
-
398
- The remaining streams are small enough to author by hand from the spec, with the derivation in the
399
- test as a comment. Worked out in advance so this plan can be checked before any code exists:
400
-
401
- - **mode 0 v0, all-zero groups.** `byte_stride` 4, `count` 3 → one block, one group, four data
402
- blocks each a single `0x00` header byte: `[0xa0, 0x00, 0x00, 0x00, 0x00]` then 28 zero bytes then
403
- the 4 baseline bytes. All three elements equal the baseline. This is the test that fails if the
404
- tail is read from the wrong end (§3.1 ⚠) — under the element-then-padding reading the baseline
405
- comes out `0,0,0,0`.
406
- - **mode 0 v1, control modes.** The same shape with header `0xa1`, one control byte, and one tail
407
- channel-mode byte: control mode 2 (nothing stored) on every byte position; then control mode 3
408
- (literal) with hand-written delta bytes; then control mode 0 with a 1-bit sentinel group, which
409
- is the only place the low-bits-first packing is exercised.
410
- - **mode 0 v1, channel modes 1 and 2.** `byte_stride` 4, one channel: a 16-bit delta pair that
411
- wraps modulo 65536, and a rotated XOR whose `r` is non-zero — the two places where a
412
- left-versus-right rotation or a byte-order slip is invisible at `r = 0`.
413
- - **mode 1, one triangle.** `[0xe1, 0xf0]` + 16 `codeaux` bytes with `codeaux[0] = 0x00` →
414
- `feb = fec = 0` → `a, b, c = next++, next++, next++` → `[0, 1, 2]`. 18 bytes, `1 + 6/3 + 16`;
415
- `data` lands exactly on `codeaux`.
416
- - **mode 1, two triangles sharing an edge.** Append code `0x00`: after triangle one the edge FIFO
417
- holds `(1,0), (2,1), (0,2)` at offset 3, so `fe = 0` reads `(0, 2)` and `fec = 0` takes
418
- `c = next = 3` → `[0, 1, 2, 0, 2, 3]`. This is the test that fails if the edge-FIFO push order is
419
- wrong.
420
- - **mode 1, the `0xXf` and `0xfe`/`0xff` paths** — explicit indices through `decodeIndex`, and the
421
- `codeaux == 0` restart that resets `next`.
422
- - **mode 2.** `[0xd1, 0x14, 0x08, 0, 0, 0, 0]` → `0x14 = 20`: baseline 0, zigzag 10, delta +5 → `5`;
423
- `0x08 = 8`: baseline 0, zigzag 4, delta +2 → `7`. Output `[5, 7]`. Plus a vector that alternates
424
- the baseline bit, which is the whole reason mode 2 exists.
425
- - **filters.** Values computed from each spec's own pseudo-code in the test, not from the
426
- implementation: unit ±X/±Y/±Z normals through octahedral at both strides, identity and
427
- each-of-four-`max_component` quaternions, exponential words with negative exponents, negative
428
- mantissas and `m = 0`, and for colour a grey, a saturated primary and a partial alpha at both
429
- strides and at a `K` below the component width.
430
- - **rejection.** Truncated streams, wrong header bytes, a `0xa1` stream offered under the `EXT_`
431
- name, a `COLOR` filter under the `EXT_` name, an invalid channel mode byte, and a mode 1 stream
432
- whose `data` does not land on `codeaux`.
433
-
434
- ### 5.3 Round trip
435
-
436
- A **test-only** mode 0 encoder in the spec file (raw-byte groups only, the simplest legal encoding)
437
- gives a randomised round trip over strides 4/8/12/16/64 and counts that straddle the 16-element
438
- group and 256-element block boundaries. It is deliberately *secondary*: it shares the layout
439
- assumptions of the decoder, so a shared misreading passes. Its job is exercising the block and group
440
- loop bounds, not proving the format. §5.1 and §5.2 prove the format.
441
-
442
- ### 5.4 End to end
443
-
444
- `gltf_test_fixtures.js` gains `build_meshopt_triangle_gltf_json(extension_name, buffer_uri, options)`
445
- and a matching `_glb`: the one-triangle model with its four bufferViews compressed (positions, normals and
446
- uvs in mode 0, indices in mode 1) by the fixture's own minimal encoder, a `fallback: true`
447
- placeholder buffer with no URI, and `extensionsUsed` / `extensionsRequired` set. A spec then loads
448
- it through the real `AssetManager` and `GLTFSceneBundleAssetLoader` — as
449
- `GLTFSceneBundleAssetLoader.spec.js` already does — under **both** extension names, and asserts the
450
- resulting bundle's geometry equals the uncompressed fixture's. That covers the fallback-buffer path,
451
- the bufferView rewrite, and the fact that `load_gltf.js` needs no changes.
452
-
453
- That file, though, is one the *vendor* extension could have described just as well — the Khronos name
454
- on it and nothing else. `options` makes it a file only KHR defines: attribute streams at codec
455
- version 1 carrying a channel mode each (a rotated exclusive-or over the positions, byte deltas over
456
- the normals, 16-bit deltas over the texture coordinates), and a `COLOR`-filtered `COLOR_0` the mesh
457
- reader maps to `StandardAttributes.Color`. Each of the two is served on its own as well as together,
458
- so that a test watching the vendor extension refuse one is refusing *that* one — asserting against a
459
- file carrying both passes on either constraint, and then removing one of them from the vendor
460
- extension goes unnoticed.
461
-
462
- ### 5.5 What none of this covers
463
-
464
- No test here decodes a stream produced by `gltfpack`. Every byte under test was authored from a
465
- specification by me or by a fixture encoder I also wrote; a misreading shared between them survives.
466
- §5.1 is the only genuinely external oracle, and it covers one group encoding of one mode.
467
-
468
- **Recommendation to the sponsor: drop one `gltfpack -noq -cc` output (and one `-cc -vv` for codec
469
- version 1) into the repo, and add a golden test that decodes it and checks every `POSITION`
470
- accessor's values against that accessor's declared `min`/`max`, and every index against the vertex
471
- count.** Those bounds are written by the encoder, are not derivable from the compressed bytes, and
472
- would catch a systematic misreading immediately. Left out of this plan because it needs files only
473
- the sponsor can supply.
474
-
475
- ## 6. Adversarial review of this plan
476
-
477
- Each item is a way this plan is wrong or insufficient, and what it changes.
478
-
479
- ### 6.1 The tail was read from the wrong end
480
-
481
- The first draft of this plan had the baseline element at the **start** of a `max(stride, 32)`-byte
482
- tail, from EXT's "a baseline element stored verbatim, padded to 32 bytes", and cited a reading of
483
- the reference decoder that appeared to confirm it. Both were wrong, and for any `byteStride` below
484
- 32 — which is every attribute meshopt is actually used on — it decodes an entire model to garbage
485
- while every unit test written from the same misreading passes.
486
-
487
- What caught it was reading KHR, which reworded the same clause to "Tail padding, which pads the size
488
- of the *subsequent* tail block…" and added a second item to the tail block that forces the question.
489
- The corroborating detail is that the reference keeps two quantities, `tail_size` and
490
- `tail_size_pad`, uses the **unpadded** one to locate the baseline and the **padded** one to validate
491
- the remainder — a distinction that has no meaning at all under the wrong reading.
492
-
493
- **Changes:** §3.1 states both quantities and where each is used; §5.2's first vector is chosen
494
- specifically to discriminate them; and the general lesson is written into §6.11.
495
-
496
- ### 6.2 `Uint8Array` out-of-bounds reads return `undefined`, and `undefined & 0xff` is `0`
497
-
498
- The worst failure mode in the design. JavaScript does not fault on a typed-array read past the end —
499
- it yields `undefined`, and every bitwise operator coerces that to `0`. A truncated or malformed
500
- stream therefore decodes to *plausible-looking zeros* rather than an error, and the model loads
501
- wrong instead of failing. The reference is bounds-checked at every group and every index read for
502
- exactly this reason.
503
-
504
- **Change:** explicit bounds checks are not optional, and are not `assert` (stripped in production —
505
- this input is a file, not a caller). Real `throw` at the header, at each byte group against the
506
- 24-byte decode limit, at each literal and control-header read, at each index varint, and at the
507
- final data-lands-on-the-tail equality in all three modes. Reject-a-truncated-stream cases added to
508
- §5.2.
509
-
510
- ### 6.3 Mutating the bufferView descriptors races the image loader
511
-
512
- The first draft rewrote `json.bufferViews[i]` in place. `loadFromJson` builds the image promises
513
- *before* buffers resolve, and each one closes over its `bufferView` object and reads `.byteOffset` /
514
- `.byteLength` inside a `.then()` that runs *after* the rewrite. Mutating in place changes what an
515
- already-scheduled image read sees, from a different code path, with no visible link between the two.
516
-
517
- **Change:** §2.2 returns a new array of new descriptors and leaves the originals untouched. The
518
- image path keeps reading exactly what it reads today, whatever order the promises settle in. This is
519
- the reason for a design choice that otherwise looks like needless allocation, and it is recorded
520
- where the code lives.
521
-
522
- ### 6.4 `Math.round` is not the spec's `round`
523
-
524
- `Math.round(-2.5)` is `-2`. The filters round signed symmetric quantities and the reference rounds
525
- half away from zero. Half a quantisation step on normals is invisible in a screenshot and visible in
526
- a diff against any other decoder — exactly the kind of drift nobody attributes correctly six months
527
- later.
528
-
529
- **Change:** `round_half_away_from_zero` in `core/math`, used by every filter, with the asymmetry
530
- named in its JSDoc.
531
-
532
- ### 6.5 A green suite here does not mean a `gltfpack` file loads
533
-
534
- Two things sit between this feature and a real compressed asset, and neither is in scope:
535
-
536
- - **`KHR_mesh_quantization`.** `gltfpack`'s default output quantises as well as compresses, and meep
537
- does not implement that extension. Worse, quantised attributes are padded — a `VEC3`/`SHORT`
538
- position gets `byteStride` 8, not 6 — and `load_gltf.js` rejects any bufferView whose `byteStride`
539
- differs from `componentSize × componentCount` with `'Interleaved attributes are not supported'`.
540
- So a default `gltfpack` file will fail *after* decompressing correctly.
541
- - **Interleaved attributes**, same rejection, for the same reason.
542
-
543
- `gltfpack -noq -cc` produces meshopt-compressed, non-quantised, non-interleaved output, and that is
544
- the configuration this feature makes work. Stated here rather than discovered later; picking up
545
- `KHR_mesh_quantization` is separate work and is not silently folded into this one.
546
-
547
- ### 6.6 Pure JS is roughly an order of magnitude off the reference
548
-
549
- The reference reaches ~1 GB/s with WebAssembly SIMD. This will not, and the extension exists partly
550
- *because* decode is meant to be nearly free. Decompression is synchronous inside `loadFromJson`, so
551
- it lands on whichever thread is parsing — the main thread for a foreground load.
552
-
553
- Accepted, not designed around: the alternative is a WASM dependency, which the brief excludes.
554
- Mitigated by the shape the reference already uses — a module-static 8 KiB delta scratch (one
555
- attribute block's worth: `byte_stride × max_block_elements <= 8192` by construction) and a 256-byte
556
- group buffer, so the strided writes stay in cache and there is no per-block allocation. No
557
- performance claim is made without a measurement, and none has been taken.
558
-
559
- ### 6.7 The extension's `count` is not the accessor's `count`
560
-
561
- `count` is the number of *stride-sized elements in the bufferView*; for index modes that is the
562
- index count, not the triangle count. Reading it as either is a silent 3× error that only shows on
563
- non-triangle-aligned data.
564
-
565
- **Change:** each spec's own invariants become the validation list, checked before decode and thrown
566
- on. Parent `byteLength === byteStride × count`; parent `byteStride`, when present, equals the
567
- extension's; `ATTRIBUTES` → stride divisible by 4, `>= 4` (KHR) and `<= 256`; `TRIANGLES` → count
568
- divisible by 3; `TRIANGLES`/`INDICES` → stride 2 or 4 and filter absent or `NONE`; `OCTAHEDRAL` →
569
- stride 4 or 8; `QUATERNION` → stride 8; `EXPONENTIAL` → stride divisible by 4; `COLOR` → stride 4
570
- or 8 **and** the KHR name. Plus the source range lying inside the source buffer, which both specs
571
- leave implicit, and the KHR rule that a bufferView must not carry both extension names.
572
-
573
- ### 6.8 The fallback buffer is allocated at its declared `byteLength`
574
-
575
- Both specs require a placeholder large enough to hold every uncompressed view referencing it — a
576
- megabyte-scale allocation for a real model, of a buffer that by construction nothing reads once the
577
- views are rewritten.
578
-
579
- **Change:** it resolves to a **zero-length** buffer. A well-formed file never touches it; a
580
- malformed one — a view referencing the fallback without carrying the extension — fails loudly on an
581
- out-of-range typed-array construction, which is the correct outcome and is preferable to quietly
582
- handing out a megabyte of zeros that renders as a degenerate mesh.
583
-
584
- ### 6.9 Version and name policy has three different answers, and uniformity would be a bug
585
-
586
- The temptation is one rule for all three headers. They are not the same:
587
-
588
- - Mode 0 version 1 is a *different bitstream*, so decoding `0xa1` as `0xa0` is a silent wrong
589
- answer. It is supported, and it is rejected under the `EXT_` name, which does not define it.
590
- - Mode 1 and mode 2 versions 0 and 1 differ only in `fec_max`, which is read from the header, so
591
- both decode correctly and both are accepted under either name.
592
- - Filter `COLOR` is accepted only under the `KHR_` name.
593
-
594
- And two decode-time hazards are left alone on purpose, because the specs declare them unspecified
595
- and JavaScript's typed arrays already contain the damage: a colour element whose fourth component is
596
- zero (infinite scale, finite garbage bytes on store) and a quaternion whose retained components
597
- exceed unit length (already clamped at the radicand). Neither can produce a `NaN` that escapes into
598
- the scene, and neither gets a guard.
599
-
600
- ### 6.10 Nothing checks `extensionsRequired`
601
-
602
- The loader ignores `extensionsRequired` entirely, so a file requiring an extension meep does not
603
- implement loads and renders wrong. Pre-existing and out of scope — noted so it is not mistaken for
604
- something this change introduced or fixed.
605
-
606
- ### 6.11 The residual risk this plan cannot retire
607
-
608
- Three details are taken from questions put to the reference implementation rather than from
609
- specification text, and one is taken from an inference:
610
-
611
- - literal control mode 3 consumes the **group-aligned** element count per byte position, not the
612
- block's unaligned count (inferred: all four control modes must agree on the scratch stride);
613
- - channel mode 2 rotates **left** by `r` on decode;
614
- - the version 1 tail-padding minimum is 24 bytes, not 32.
615
-
616
- Each is a silent-garbage failure if wrong, and none is discriminated by any test in §5 — a fixture
617
- encoder written from the same understanding agrees with the decoder. They are the specific reason
618
- §5.5's ask matters: one real `gltfpack -cc -vv` file settles all three at once. Until there is one,
619
- **version 1 support is implemented and tested but not evidenced**, and this paragraph is the honest
620
- statement of that.
621
-
622
- ## 7. Commit sequence
623
-
624
- Each commit is independently green (`npm run test` from `H:/git/moh`).
625
-
626
- 1. `feat(math): rounding that breaks its ties away from zero`
627
- 2. `feat(binary): meshopt's attribute codec, against the bytes the spec itself decodes`
628
- — mode 0 version 0, the group and channel decoders, the varint, the two enums, specs.
629
- 3. `feat(binary): the attribute codec's second version, and the channels it decodes through`
630
- — mode 0 version 1: control header, control modes, 1-bit groups, channel modes, specs.
631
- 4. `feat(binary): meshopt's two index codecs, and the tail that checks them`
632
- — modes 1 and 2, specs.
633
- 5. `feat(binary): four meshopt filters, one of them meep's own octahedron`
634
- — filters 1/2/3/4, specs.
635
- 6. `feat(binary): one entry point per compressed buffer view`
636
- — `meshopt_decode` dispatch, spec.
637
- 7. `feat(gltf): a compressed buffer view becomes an ordinary one`
638
- — the binding module and its validation, under both extension names, spec.
639
- 8. `fix(gltf): a buffer with no URI is a placeholder, not a request`
640
- — the tiny-gltf buffer loop, GLB buffers past the chunk.
641
- 9. `feat(gltf): the loader decodes compressed views before an accessor reads one`
642
- — the `loadFromJson` call, the compressed-image-view throw, the end-to-end fixture and spec.
643
-
644
- ## 8. What execution changed
645
-
646
- Written after the work landed. The plan above is corrected in place where it was factually wrong
647
- about the format; everything else is recorded here rather than edited away, because a plan that
648
- quietly matches its outcome is not evidence of anything.
649
-
650
- ### 8.1 The plan was wrong about the `0xfe`/`0xff` ordering
651
-
652
- §3.2 claimed that computing and explicitly reading each of the three indices in turn "diverges on
653
- the first triangle that mixes them". It does not. An index in that branch is either fresh — and
654
- takes a turn at `next` — or explicit, and takes a varint; never both. The two passes are disjoint
655
- per index, so interleaving them is equivalent.
656
-
657
- Found by mutation: rewriting the branch to interleave them left all fifty-four tests green, and the
658
- question "which test should have caught this?" has the answer "none, because there is nothing to
659
- catch". What *is* order-dependent is the sequence of the explicit reads, because `last` chains
660
- through them; a test with a codeaux of `0xff`, where all three indices are explicit, now pins it.
661
-
662
- §3.2 also conflated two things about the conditional FIFO push. The *write* at a non-advancing
663
- offset is unobservable (no well-formed stream reads distance 16). The *non-advance* is very much
664
- observable, at any distance a later code reaches. Two tests now do.
665
-
666
- ### 8.2 A specification erratum, in both documents
667
-
668
- Of the three worked examples both extensions print for the varint encoding,
669
-
670
- ```
671
- 0x7f => 0x7f
672
- 0x81 0x04 => 0x201
673
- 0xff 0xa0 0x05 => 0x1fd005
674
- ```
675
-
676
- the third is wrong. Those bytes are the LEB128 encoding of `0x1fd005` written back to front; read as
677
- LEB128 they are `0x1507f`, and `0x1fd005` encodes as `0x85 0xa0 0x7f`. The example only works if the
678
- groups are read most significant first, which contradicts the example above it, the encoding the
679
- document names, and the reference implementation.
680
-
681
- `meshopt_read_uint_var.spec.js` pins both readings of both byte strings so that nobody later "fixes"
682
- the reader to match the printed line.
683
-
684
- ### 8.3 Two things the plan claimed mattered, which cannot be observed
685
-
686
- Both were found by mutating the implementation and watching the suite stay green, and both are now
687
- written down where they live rather than left to look like tested behaviour.
688
-
689
- - **§6.4, the rounding mode.** `round_half_away_from_zero` cannot be told from `Math.round` through
690
- any of the four filters. A renormalised octahedral component is a ratio with an irrational
691
- denominator and never lands halfway between two integers — checked exhaustively over the whole
692
- 8-bit input space, 8388477 component values, no ties — and the quaternion filter's scale is
693
- irrational for the same reason. The colour filter's scale is rational, but its inputs are
694
- non-negative for any valid element, and a positive tie rounds the same way either way. The helper
695
- is kept because it is what the specifications say; the claim that a test proves it is withdrawn,
696
- and a standing sweep now asserts the no-ties property that makes it moot.
697
- - **§3.4, the quaternion radicand's clamp.** The output goes through an `Int16Array`, and storing a
698
- `NaN` there yields the same zero the clamp produces. Kept so the function is total on its own
699
- rather than by a coincidence thirty lines downstream — which is exactly the kind of thing a
700
- refactor removes — but nothing tests it, and the spec now says so.
701
-
702
- ### 8.4 Structure
703
-
704
- - Planned commits 2 and 3 (attribute codec versions 0 and 1) landed as one. The block loop, the
705
- group decoder and the channel reconstruction are shared; splitting them would have meant writing
706
- the module twice.
707
- - The test-only encoder §5.3 put inline in a spec file became `__meshopt_test_streams.js`, because
708
- the end-to-end glTF fixtures need the same streams. `**/__**.js` is already how meep's coverage
709
- configuration spells "scaffolding".
710
- - Three test vectors in the first draft were wrong and the implementation was right: a quaternion
711
- component stored at full scale is `1/sqrt(2)` and not 1; a quaternion whose four components are
712
- equal has its dropped component absorb all three of the others' rounding, so it is up to three and
713
- a half quantisation steps out rather than half a step; and a colour alpha of `0x80` is the marker
714
- bit over an empty field, which is zero and not one. The bounds are now derived in the test from
715
- the quantisation step rather than picked.
716
-
717
- ### 8.5 The record
718
-
719
- Thirty-two mutations were applied to the finished implementation to check the suite says so. Thirty
720
- failed at least one test. The two that did not are §8.3, and are documented rather than papered over.
721
-
722
- `npm run test` from `H:/git/moh` covers all of it; the meshopt package and its glTF binding are 96
723
- tests across 12 files, plus 7 end-to-end through the real asset framework.
724
-
725
- ### 8.6 What is still owed
726
-
727
- §5.5 and §6.11 stand unchanged, and are the honest limit of this work:
728
-
729
- **No test here decodes a stream `gltfpack` produced.** Every byte under test was authored from a
730
- specification by me, or by a fixture encoder I also wrote. Three details — literal control mode 3's
731
- element count, channel mode 2's rotation direction, and version 1's 24-byte tail minimum — come from
732
- questions put to the reference rather than from specification text, and no test discriminates any of
733
- them.
734
-
735
- One `gltfpack -noq -cc` output and one `-cc -vv` output, checked in with a golden test that
736
- validates every `POSITION` accessor against its own declared `min`/`max` and every index against the
737
- vertex count, would settle all three at once. Those bounds are written by the encoder and are not
738
- derivable from the compressed bytes.
739
-
740
- Until then: version 0 is corroborated by the specification's own worked example, and **version 1 is
741
- implemented and tested but not evidenced.**
742
-
743
- ## 9. The seam this was first built on the wrong side of
744
-
745
- The first version put the whole glTF half in one module, `gltf_meshopt_compression.js`, exporting
746
- `gltf_meshopt_decode_buffer_views(buffer_views, buffers)`. The parser imported that by name and
747
- called it on every model it loaded.
748
-
749
- It worked, and every test above passed against it. It was still the wrong shape, for reasons worth
750
- writing down because none of them is a bug:
751
-
752
- - **The name described the caller's hope, not the function.** A thing called
753
- `gltf_meshopt_decode_buffer_views` does not decode bufferViews. It walks all of them, works out
754
- which are anybody's, decodes those, and rewrites the array. Three jobs under one codec's name.
755
- - **Detection was welded to decoding.** The parser assumed meshopt by importing it, and the check
756
- that it was meshopt happened *inside*, four frames down. Reading the call site told you nothing
757
- about whether a plain glTF paid anything — which is exactly the question it should answer.
758
- - **The second extension proved the point and the third would have made it.** `KHR_` was bolted on
759
- as `if (name === MESHOPT_COMPRESSION_EXT && ...)` inside the decoder. A Draco or a future codec
760
- would have been another module the parser imported by name, and another branch.
761
-
762
- What replaced it is in §2.2. The parser asks a set what claims a view; the set answers with an
763
- extension or with nothing; the walk is identical for all of them. `tiny-gltf.js` no longer contains
764
- the string "meshopt" anywhere, comments included.
765
-
766
- Two smaller things went the same way:
767
-
768
- - `meshopt_decode`'s mode and filter dispatch were a seven-branch `if / else if` chain. The three
769
- modes already share a signature and the filters already share theirs, so both are now arrays
770
- indexed by the enum, and "none" is a function that does nothing rather than a branch that asks
771
- whether to.
772
- - The extension validator was fourteen `if (...) throw` in a row, several of them comparing mode and
773
- filter names. The specifications state those constraints as a table, so it is a table: what each
774
- mode and each filter admits of a stride and a count, with the rule's own wording carried alongside
775
- for the message. Eight guards, none of them naming a mode.
776
-
777
- Eight mutations were applied to the new seams to check the suite says so — the walker decoding
778
- unclaimed views, the walker dropping its length backstop, the set taking the first claimant, the set
779
- forgetting placeholder buffers, meshopt admitting any filter it can name, one version ceiling for
780
- every mode, and each dispatch table shuffled. All eight fail at least one test.
781
-
782
- ## Addendum, 2026-08-20: a document's resolved buffers are `Uint8Array`
783
-
784
- Written into the plan as `ArrayBuffer`, and changed when the virtual-geometry builder started
785
- reading containers through the same layer. A buffer is a *range* of bytes: a `.glb`'s binary chunk
786
- is a range of the file it arrived in, and a buffer read off a filesystem starts wherever the runtime
787
- put it. Carrying the offset with the bytes is what lets the chunk be handed on without copying a
788
- model-sized allocation, and `Uint8Array.subarray` is what a decoder's source range wants anyway —
789
- `MeshoptBufferViewExtension` reads one with `subarray` rather than a three-argument constructor that
790
- can only be laid over an aligned offset.
791
-
792
- `decode()` answers with a `Uint8Array` for the same reason, and the length check over it is
793
- unchanged.
1
+ # `EXT_meshopt_compression` / `KHR_meshopt_compression` — implementation plan
2
+
3
+ Status: plan. Written 2026-08-20.
4
+
5
+ Scope: decode side of both extensions.
6
+
7
+ - `EXT_meshopt_compression` — ratified, Vendor.
8
+ <https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Vendor/EXT_meshopt_compression>
9
+ - `KHR_meshopt_compression` — ratified, Khronos, merged 2026-01-23 (PR #2517).
10
+ <https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_meshopt_compression>
11
+
12
+ Reference encoder/decoder: <https://github.com/zeux/meshoptimizer>. Consulted for questions the
13
+ specification text leaves ambiguous; **not vendored and not transcribed** — no new dependency, and
14
+ the bitstream below is implemented from the two specifications.
15
+
16
+ ## 1. What these extensions are, and why that shapes the split
17
+
18
+ Neither is a geometry extension. Both are *bufferView* extensions: a bufferView declares that its
19
+ bytes are produced by running a decoder over a byte range of some other buffer. Nothing about the
20
+ decode depends on what the bufferView is later read as — vertex attributes, index data, morph
21
+ deltas, animation keyframes and `EXT_mesh_gpu_instancing` transforms all go through the same three
22
+ modes and (now) five filters.
23
+
24
+ That is the seam. Everything except roughly two dozen lines is a **byte-array in, byte-array out**
25
+ codec with no knowledge of glTF at all:
26
+
27
+ ```
28
+ src/core/binary/meshopt/ pure codec — bytes in, bytes out.
29
+ ^ No glTF, no geometry, no engine.
30
+ | called by
31
+ src/.../gltf/ext/meshopt/ one bufferView's worth of meshopt: read the
32
+ ^ extension object, check it, return the bytes.
33
+ | called through GltfBufferViewExtension by
34
+ src/.../gltf/ext/ the generic bufferView-extension layer — which
35
+ ^ extension claims a view, and what becomes of what
36
+ | it produced. Names no codec.
37
+ | called by
38
+ src/shade/renderer/loader/gltf/tiny-gltf.js one call, after buffers resolve. Names no
39
+ extension at all.
40
+ ```
41
+
42
+ `core/binary` is the codec's right home: it is where meep already keeps byte-level codecs
43
+ (`base64/`, `base58/`, `half_to_float_uint16`, `BinaryBuffer`'s LEB128 `readUintVar`). The codec
44
+ imports nothing outside `core/`, so it is usable from a worker, a tool, or the USD loader without
45
+ dragging Shade in.
46
+
47
+ ### 1.1 KHR is EXT plus three things
48
+
49
+ The two extensions share a JSON shape, a `bufferView`/`buffer` model, fallback buffers, and modes
50
+ 1 and 2 byte for byte. KHR adds:
51
+
52
+ 1. **Attribute codec version 1** (header `0xa1`). A genuinely different bitstream for mode 0: a
53
+ per-block control header, four control modes, an extra 1-bit sentinel encoding, and three
54
+ *channel* modes that widen the delta from 8-bit to 16-bit or to a rotated 32-bit XOR.
55
+ Version 0 (`0xa0`) remains legal under KHR and is bit-identical to EXT.
56
+ 2. **Filter 4, `COLOR`** — YCoCg, `byteStride` 4 or 8.
57
+ 3. One extra validity rule (`ATTRIBUTES` requires `byteStride >= 4`) and the constraint that a
58
+ bufferView must not carry both extensions.
59
+
60
+ So there is one codec that decodes everything, and a glTF layer that enforces the per-name subset:
61
+ a `0xa1` stream or a `COLOR` filter under the `EXT_` name is an invalid file and is rejected.
62
+
63
+ ## 2. Modules
64
+
65
+ ### 2.1 `src/core/binary/meshopt/` — the codec
66
+
67
+ | File | Export |
68
+ |:--|:--|
69
+ | `MeshoptCompressionMode.js` | `@enum` — `Attributes: 0`, `Triangles: 1`, `Indices: 2` |
70
+ | `MeshoptCompressionFilter.js` | `@enum` — `None: 0`, `Octahedral: 1`, `Quaternion: 2`, `Exponential: 3`, `Color: 4` |
71
+ | `MESHOPT_GROUP_SIZE.js` | the group size, and the 24-byte bound a group read stays inside |
72
+ | `meshopt_decode_byte_group.js` | one group of 16 byte-deltas at a given sentinel width |
73
+ | `meshopt_decode_data_block.js` | one "data block": header bits + its groups, for one byte position |
74
+ | `meshopt_decode_vertex_buffer.js` | mode 0, versions 0 and 1 |
75
+ | `meshopt_decode_index_buffer.js` | mode 1 |
76
+ | `meshopt_decode_index_sequence.js` | mode 2 |
77
+ | `meshopt_decode_filter_octahedral.js` | filter 1, in place |
78
+ | `meshopt_decode_filter_quaternion.js` | filter 2, in place |
79
+ | `meshopt_decode_filter_exponential.js` | filter 3, in place |
80
+ | `meshopt_decode_filter_color.js` | filter 4, in place |
81
+ | `meshopt_decode.js` | dispatch: mode, then filter |
82
+ | `meshopt_read_uint_var.js` | bounded LEB128 over a `Uint8Array` |
83
+ | `__meshopt_test_streams.js` | test-only encoders, shared by the codec specs and the glTF fixtures |
84
+
85
+ Signatures:
86
+
87
+ ```js
88
+ meshopt_decode_vertex_buffer(destination, count, byte_stride, source)
89
+ meshopt_decode_index_buffer(destination, index_count, index_size, source)
90
+ meshopt_decode_index_sequence(destination, index_count, index_size, source)
91
+ meshopt_decode_filter_*(destination, count, byte_stride)
92
+ meshopt_decode(destination, count, byte_stride, mode, filter, source)
93
+ ```
94
+
95
+ `destination` and `source` are `Uint8Array` throughout — the codec never assumes an aligned
96
+ `ArrayBuffer` offset, because a compressed source range in a glTF is only byte-aligned. Index modes
97
+ and filters build their typed views internally from `index_size` / `byte_stride`.
98
+
99
+ Two additions outside the package, both genuinely generic and both matching meep's existing naming:
100
+
101
+ - `src/core/math/round_half_away_from_zero.js` — `Math.round` breaks ties toward `+Infinity`
102
+ (`Math.round(-2.5) === -2`). Four of the five filters specify `round()` on a signed symmetric
103
+ quantity and round half away from zero. Sits beside the existing `round_up.js`.
104
+ - nothing else: `msb_32` (`core/binary`) is already `findMSB` including its `-1` for zero, `exp2`
105
+ and `copysign` (`core/math`) already exist, and `decode_octahedron_to_unit`
106
+ (`core/geom/3d/normal/octahedron`) is reused by filter 1 — see §4.1.
107
+
108
+ ### 2.2 `src/shade/renderer/loader/gltf/ext/` — bufferView extensions, generically
109
+
110
+ A bufferView extension says "these bytes are not in the buffer I point at; run this to get them".
111
+ Meshopt is two of them; a future codec would be a third. The parser should know that shape and
112
+ nothing else, so the layer is split in two — see §9 for why this is not how it was first written.
113
+
114
+ | File | What it is |
115
+ |:--|:--|
116
+ | `GltfBufferViewExtension.js` | the contract one extension implements: a `name`, `decode()`, and whether it declares placeholder buffers |
117
+ | `GltfBufferViewExtensionSet.js` | which extensions a parser honours, and `claim(view)` — the *only* thing that decides whether anything happens |
118
+ | `gltf_apply_buffer_view_extensions.js` | the walk: claim, delegate, append the buffer, replace the descriptor. Identical for every extension |
119
+ | `gltf_buffer_view_extensions.js` | `GLTF_BUFFER_VIEW_EXTENSIONS`, the set the parser uses by default |
120
+ | `meshopt/MeshoptBufferViewExtension.js` | one class, two instances: `EXT_MESHOPT_COMPRESSION`, `KHR_MESHOPT_COMPRESSION` |
121
+
122
+ The walker:
123
+
124
+ 1. returns a **new** `bufferViews` array — claimed entries are replaced by fresh descriptors,
125
+ unclaimed entries pass through **by reference**,
126
+ 2. **appends** each decoded buffer to `buffers`, pointing the new descriptor at it with
127
+ `byteOffset: 0`,
128
+ 3. keeps `byteStride`, `target` and everything else from the parent, so accessor reads are unchanged,
129
+ 4. refuses a decoder that answered with the wrong number of bytes, whichever decoder it was.
130
+
131
+ Returning a new array rather than mutating the old descriptors is load-bearing, not taste — §6.3.
132
+
133
+ The difference between the two meshopt instances is two fields and no branches: which filter names
134
+ the extension defines, and the newest codec version each *mode* may carry. Per mode because both
135
+ index codecs' version 1 is legal under either extension; it is only the attribute codec that the
136
+ vendor extension pins at 0.
137
+
138
+ ### 2.3 `tiny-gltf.js` — the call site
139
+
140
+ Three edits, all in `loadFromJson`:
141
+
142
+ - **`~L422-448`, buffer resolution.** Today a buffer with no `uri` outside the GLB fast path is fed
143
+ to `resolveUri(undefined, baseUrl)` and fetched as `<baseUrl>undefined`. That is exactly the shape
144
+ of a meshopt *fallback* buffer (`{ "byteLength": N }`, no URI), so today a `gltfpack`-produced
145
+ `.gltf` cannot load at all. A buffer that is marked `fallback` or has no `uri` resolves to a
146
+ zero-length `ArrayBuffer` instead of a request (§6.8). Also: the GLB branch currently loads *only*
147
+ the binary chunk and ignores `buffers[1..n]`, which is where both extensions put the placeholder —
148
+ the branch becomes "buffer 0 is the chunk, the rest resolve normally".
149
+ - **`~L524-534`, an image sourced from a bufferView.** Throw if that bufferView is compressed. The
150
+ combination is legal in the abstract and pointless in practice (the payload is already a PNG or a
151
+ JPEG); the alternative to throwing is handing `createImageBitmap` the fallback buffer's bytes,
152
+ which is a silent wrong answer.
153
+ - **`~L557`, after `await Promise.all(pendingBuffers)`.** One call to
154
+ `gltf_apply_buffer_view_extensions` before `json.buffers` and `json.bufferViews` are published.
155
+
156
+ The parser names no extension: it asks `this.bufferViewExtensions` — a public field, defaulted to the
157
+ standard set and replaceable — and the set is the one place that knows what is implemented.
158
+
159
+ **Nothing in `load_gltf.js` changes.** It reads `gltf.bufferViews` / `gltf.buffers` inside
160
+ `process()`, which runs after `loadFromJson` has returned, so it sees decoded views and never learns
161
+ either extension exists. That is the point of doing this at the bufferView layer.
162
+
163
+ ## 3. The bitstream, as implemented
164
+
165
+ Written from the two specifications' Appendix A/B. Notes marked ⚠ are places where a plausible
166
+ reading is wrong.
167
+
168
+ ### 3.1 Mode 0 — attributes
169
+
170
+ ```
171
+ header 1 byte: 0xa0 (version 0) or 0xa1 (version 1, KHR only)
172
+ blocks one or more attribute blocks
173
+ tail padding zero bytes
174
+ tail block baseline element (byte_stride bytes)
175
+ channel modes (byte_stride / 4 bytes, version 1 only)
176
+ ```
177
+
178
+ ⚠ **The padding comes BEFORE the tail block; the tail block is flush against the end of the
179
+ stream.** So the baseline element starts at `byteLength - tail_size`, where
180
+
181
+ ```
182
+ tail_size = byte_stride + (version === 1 ? byte_stride / 4 : 0)
183
+ tail_size_pad = max(tail_size, version === 1 ? 24 : 32)
184
+ ```
185
+
186
+ and the decoder must have consumed exactly `byteLength - tail_size_pad` bytes when the blocks are
187
+ done. EXT's wording — "a baseline element stored verbatim, padded to 32 bytes" — reads equally well
188
+ as element-then-padding, which for any stride below 32 puts the baseline in the wrong place and
189
+ decodes garbage. KHR's rewording ("Tail padding, which pads the size of the *subsequent* tail
190
+ block…") settles it, and the reference decoder agrees: it takes the baseline from
191
+ `data_end - tail_size`, with `tail_size` **unpadded**, while validating the remainder against
192
+ `tail_size_pad`. Two different quantities that coincide only when `byte_stride >= 32`.
193
+
194
+ Block loop, identical in both versions:
195
+
196
+ ```
197
+ max_block_elements = min(floor(8192 / byte_stride) & ~15, 256)
198
+ block_elements = min(remaining, max_block_elements)
199
+ group_count = ceil(block_elements / 16)
200
+ ```
201
+
202
+ ⚠ `8192 / byte_stride` is integer division — `floor` before the mask. With `byte_stride <= 256` the
203
+ result is never below 32, so the loop always advances.
204
+
205
+ A block is, in order:
206
+
207
+ - a **control header** of `byte_stride / 4` bytes — **version 1 only**,
208
+ - `byte_stride` **data blocks**, one per byte position `k` of the element.
209
+
210
+ The control header packs a 2-bit *control mode* per byte position, low bits first:
211
+ `(c0 << 0) | (c1 << 2) | (c2 << 4) | (c3 << 6)`, one byte per aligned group of four byte positions.
212
+ The control mode selects what the data block for that byte position looks like:
213
+
214
+ | control mode | data block |
215
+ |:--|:--|
216
+ | 0 | header bits, group encodings `{zero, 1-bit, 2-bit, 4-bit}` |
217
+ | 1 | header bits, group encodings `{1-bit, 2-bit, 4-bit, raw}` |
218
+ | 2 | nothing at all — every delta byte is 0, no header bits, no bytes consumed |
219
+ | 3 | literal: `group_count * 16` delta bytes, no header bits |
220
+
221
+ Version 0 has no control header and behaves as a fixed table
222
+ `{zero, 2-bit, 4-bit, raw}` for every byte position.
223
+
224
+ Where header bits are present they are `ceil(group_count / 4)` bytes, 2 bits per group, packed
225
+ **low bits first**: `(g0 << 0) | (g1 << 2) | (g2 << 4) | (g3 << 6)`. Group encodings:
226
+
227
+ | encoding | packed bytes | sentinel | total |
228
+ |:--|:--|:--|:--|
229
+ | zero | 0 | — | 0 |
230
+ | 1-bit | 2 | `1` | 2..18 |
231
+ | 2-bit | 4 | `3` | 4..20 |
232
+ | 4-bit | 8 | `15` | 8..24 |
233
+ | raw | 16 | — | 16 |
234
+
235
+ ⚠ Bit order inside a packed byte is **not uniform**. 2-bit and 4-bit run high bits first —
236
+ `(d3 << 0) | (d2 << 2) | (d1 << 4) | (d0 << 6)` and `(d1 << 0) | (d0 << 4)` — while **1-bit runs low
237
+ bits first**, `(d0 << 0) | (d1 << 1) | … | (d7 << 7)`. The spec says so explicitly (it is there to
238
+ let SIMD implementations reuse a lookup table); it is not a transcription slip.
239
+
240
+ A delta equal to the sentinel means the real value is outside the bit range and is taken as a whole
241
+ byte from the run that follows the packed bytes, in order of appearance.
242
+
243
+ The delta bytes so recovered are then turned into values by the **channel mode**. Channels are
244
+ aligned groups of four byte positions; version 1 stores one mode byte per channel in the tail, and
245
+ version 0 behaves as though every channel were mode 0.
246
+
247
+ | channel mode | reconstruction |
248
+ |:--|:--|
249
+ | 0 | per byte: `v = (unzigzag8(d) + prev) & 0xff` |
250
+ | 1 | per aligned 2 bytes, little-endian: `v = (unzigzag16(d) + prev) & 0xffff` |
251
+ | 2 | per aligned 4 bytes, little-endian: `v = rotl32(d, r) ^ prev` |
252
+
253
+ `r` is the **high** 4 bits of the channel mode byte and applies only to mode 2. ⚠ The decoder
254
+ rotates **left by `r`** — the spec's `rotate(v, r) = (v << r) | (v >> ((32 - r) & 31))` is the
255
+ decode direction, despite the surrounding sentence describing how the encoder produced the delta.
256
+ A mode byte whose low nibble is 3 or above, or whose high nibble is non-zero for mode 0 or 1, makes
257
+ the stream invalid.
258
+
259
+ Groups always decode sixteen elements; anything past `block_elements` is discarded and does not
260
+ advance the delta chain. Each block ends by taking its **last decoded element** as the next block's
261
+ baseline.
262
+
263
+ The specification's own worked example is the acceptance test for the group decoder (§5.1).
264
+
265
+ ### 3.2 Mode 1 — triangles
266
+
267
+ ```
268
+ header 1 byte, (h & 0xf0) == 0xe0; version = h & 0x0f, 0 or 1 (both specs pin 0xe1)
269
+ codes index_count / 3 bytes, one per triangle
270
+ data variable, immediately after the codes
271
+ codeaux the last 16 bytes
272
+ ```
273
+
274
+ State: `next` (high-watermark, 0), `last` (0), a 16-entry edge FIFO and a 16-entry vertex FIFO, both
275
+ filled with `0xFFFFFFFF`. `data` must end exactly at the start of `codeaux` — that equality is the
276
+ stream's own checksum.
277
+
278
+ `fec_max` is 13 for version 1 and 15 for version 0; it is what makes codes `0xXd`/`0xXe` mean
279
+ `last - 1` / `last + 1` rather than two more FIFO slots. Reading it from the header rather than
280
+ hard-coding 13 is why both versions decode correctly.
281
+
282
+ ⚠ The two branches index the vertex FIFO differently: the `code < 0xf0` path reads
283
+ `(offset - 1 - fec) & 15`, the `0xf0..0xff` paths read `(offset - feb) & 15`. This follows from the
284
+ spec's own wording ("index Y" versus "index Z-1") and is not a slip.
285
+
286
+ ⚠ A conditional push writes the value at `offset` and then does not advance `offset`. Skipping the
287
+ write as well is *not* equivalent: every later FIFO read at distance `d` would see what belongs at
288
+ `d - 1`. Two tests reach back past a vertex that was not pushed, because until something does the
289
+ difference is invisible.
290
+
291
+ ⚠ The explicit indices in the `0xfe`/`0xff` branch are read in the order a, b, c, and `last` chains
292
+ through them, so that order is load-bearing. Their position relative to the `next++` allocations is
293
+ *not*: an index is either fresh or explicit, never both, so the two passes do not interfere. (The
294
+ plan asserted otherwise; see §8.)
295
+
296
+ ### 3.3 Mode 2 — indices
297
+
298
+ ```
299
+ header 1 byte, (h & 0xf0) == 0xd0 (both specs pin 0xd1)
300
+ deltas one LEB128 varint per index
301
+ tail 4 reserved bytes
302
+ ```
303
+
304
+ `v & 1` selects one of two running baselines; `v >> 1` is a zigzag delta applied to it. Two
305
+ baselines rather than one is what lets an encoder splice two monotonic runs (strips, line lists)
306
+ cheaply. Again `data` must land exactly on the 4-byte tail.
307
+
308
+ ### 3.4 Filters
309
+
310
+ All five are in place over the already-decoded bufferView, `count` elements of `byte_stride` bytes.
311
+
312
+ - **Octahedral** — `byte_stride` 4 → `Int8Array`, 8 → `Int16Array`. Components 0 and 1 are the
313
+ octahedral pair, component 2 encodes 1.0 at the element's own precision `K`, component 3 passes
314
+ through untouched. Output scaled by `max` = 127 or 32767. Reuses meep's own
315
+ `decode_octahedron_to_unit` — see §4.1.
316
+ - **Quaternion** — `byte_stride` 8, `Int16Array`. `one = input[3] | 3`,
317
+ `max_component = input[3] & 3`; outputs land at `(max_component + 1..3) & 3` for x/y/z and
318
+ `(max_component + 0) & 3` for w.
319
+ ⚠ `input[3]` is read for *both* purposes before any output is written — one of the four writes
320
+ lands on it.
321
+ ⚠ The radicand `1 - x² - y² - z²` is clamped at 0. meep already learned this in
322
+ `quat3_decode_from_uint32`; a NaN quaternion out of a loader poisons every transform downstream.
323
+ - **Exponential** — `byte_stride` divisible by 4. Each 32-bit word is `e = word >> 24` (signed),
324
+ `m = (word << 8) >> 8` (signed); the result `2^e · m` is written back as a float32. `e` is
325
+ spec-bounded to [-100, 100] and `|m| < 2^23`, so the product is exact in float32 and computing it
326
+ in JS doubles and storing through a `Float32Array` is bit-identical to the reference's
327
+ build-the-exponent-and-multiply.
328
+ - **Color** (KHR only) — `byte_stride` 4 → `Uint8Array`, 8 → `Uint16Array`. YCoCg:
329
+
330
+ ```
331
+ as = (1 << (msb_32(input[3]) + 1)) - 1
332
+ r = input[0] + int(input[1]) - int(input[2])
333
+ g = input[0] + int(input[2])
334
+ b = input[0] - int(input[1]) - int(input[2])
335
+ a = input[3] & (as >> 1); a = (a << 1) | (a & 1)
336
+ output = round(component * (UINTN_MAX / as))
337
+ ```
338
+
339
+ ⚠ Components 0 and 3 are **unsigned**, components 1 and 2 are **signed**, in the same element.
340
+ `msb_32` already returns `-1` for zero, so a malformed `input[3] === 0` yields `as = 0`, an
341
+ infinite scale, and finite garbage bytes once stored through a `Uint8Array` — defined, ugly, and
342
+ not worth a guard (§6.9).
343
+
344
+ ## 4. What is reused, and what deliberately is not
345
+
346
+ ### 4.1 Reused
347
+
348
+ - **`decode_octahedron_to_unit`** (`core/geom/3d/normal/octahedron`) implements filter 1's core.
349
+ meep's fold is the same arithmetic as the spec's `copysign` form (`x + t·sign(x)` either way) and
350
+ it renormalises, but it is written **Y-up**: meep's `(x, y, z)` is the spec's `(x, z, y)`. The
351
+ swizzle is the whole of the adaptation, and a spec checks the composition against the
352
+ specification's formula directly rather than against meep's.
353
+ - **`msb_32`** (`core/binary`) is `findMSB` for filter 4, `-1`-on-zero included.
354
+ - **`exp2`** and **`copysign`** (`core/math`).
355
+ - **`gltf_test_fixtures.js`** (`engine/asset/loaders`) already builds a one-triangle glTF and GLB by
356
+ hand; the end-to-end fixture extends it rather than introducing a second fixture vocabulary.
357
+
358
+ ### 4.2 Deliberately not
359
+
360
+ - **`BinaryBuffer.readUintVar`** is the same LEB128 scheme and reusing it would honour "use meep's
361
+ existing code". It is still wrong here: it reads through a `DataView` bound to a whole
362
+ `ArrayBuffer` where the compressed range is a slice, it is unbounded on malformed input where the
363
+ reference stops at five bytes, and `value |= (b & 0x7f) << shift` turns negative once `shift`
364
+ reaches 28 — which is inside the range mode 1 and mode 2 indices legitimately use. The deviation
365
+ and its three reasons are documented where `meshopt_read_uint_var` is defined, so the next reader
366
+ does not "fix" the duplication.
367
+ - **`quat3_decode_from_uint32`** is a different packing — 10-bit, fixed range, dropped component
368
+ inserted *at* index `max` — where filter 2 is 16-bit, variable precision and *cyclic*. Documented
369
+ as deliberately not reused rather than left to look overlooked.
370
+ - **`Vector3` / `Quaternion` / `vec3` helpers.** The filters run over hundreds of thousands of
371
+ elements through typed-array views; routing each through an object allocation would be the one
372
+ place in this feature where reuse costs more than it is worth. Scalars, module-static scratch.
373
+
374
+ ## 5. Tests
375
+
376
+ Every module gets a `.spec.js` beside it. House rules apply: black-box, no mocks, and no rejection
377
+ tests against `assert.*` (stripped in production) — everything that must reject bad *file* input
378
+ does so with a real `throw`, and those are tested.
379
+
380
+ ### 5.1 The independent oracle
381
+
382
+ The single most valuable test is free: **Appendix A of both specifications contains a worked
383
+ example** of the 4-bit sentinel encoding —
384
+
385
+ ```
386
+ 0x17 0x5f 0xf0 0xbc 0x77 0xa9 0x21 0x00 0x34 0xb5
387
+ -> -1 -4 -3 26 -91 0 -6 6 -4 -4 5 -5 1 -1 0 0
388
+ ```
389
+
390
+ — which pins the packed-nibble order, the sentinel value, the sentinel run's position and its
391
+ ordering, and the zigzag, all at once, from a document that is not this implementation. It is the
392
+ first test written, and the group decoder is developed against it. (Checked by hand while writing
393
+ this plan: the nibbles are `1 7 5 S S 0 11 12 7 7 10 9 2 1 0 0`, the two sentinels take `0x34` and
394
+ `0xb5`, and de-zigzagging reproduces the stated line exactly.)
395
+
396
+ ### 5.2 Hand-derived vectors
397
+
398
+ The remaining streams are small enough to author by hand from the spec, with the derivation in the
399
+ test as a comment. Worked out in advance so this plan can be checked before any code exists:
400
+
401
+ - **mode 0 v0, all-zero groups.** `byte_stride` 4, `count` 3 → one block, one group, four data
402
+ blocks each a single `0x00` header byte: `[0xa0, 0x00, 0x00, 0x00, 0x00]` then 28 zero bytes then
403
+ the 4 baseline bytes. All three elements equal the baseline. This is the test that fails if the
404
+ tail is read from the wrong end (§3.1 ⚠) — under the element-then-padding reading the baseline
405
+ comes out `0,0,0,0`.
406
+ - **mode 0 v1, control modes.** The same shape with header `0xa1`, one control byte, and one tail
407
+ channel-mode byte: control mode 2 (nothing stored) on every byte position; then control mode 3
408
+ (literal) with hand-written delta bytes; then control mode 0 with a 1-bit sentinel group, which
409
+ is the only place the low-bits-first packing is exercised.
410
+ - **mode 0 v1, channel modes 1 and 2.** `byte_stride` 4, one channel: a 16-bit delta pair that
411
+ wraps modulo 65536, and a rotated XOR whose `r` is non-zero — the two places where a
412
+ left-versus-right rotation or a byte-order slip is invisible at `r = 0`.
413
+ - **mode 1, one triangle.** `[0xe1, 0xf0]` + 16 `codeaux` bytes with `codeaux[0] = 0x00` →
414
+ `feb = fec = 0` → `a, b, c = next++, next++, next++` → `[0, 1, 2]`. 18 bytes, `1 + 6/3 + 16`;
415
+ `data` lands exactly on `codeaux`.
416
+ - **mode 1, two triangles sharing an edge.** Append code `0x00`: after triangle one the edge FIFO
417
+ holds `(1,0), (2,1), (0,2)` at offset 3, so `fe = 0` reads `(0, 2)` and `fec = 0` takes
418
+ `c = next = 3` → `[0, 1, 2, 0, 2, 3]`. This is the test that fails if the edge-FIFO push order is
419
+ wrong.
420
+ - **mode 1, the `0xXf` and `0xfe`/`0xff` paths** — explicit indices through `decodeIndex`, and the
421
+ `codeaux == 0` restart that resets `next`.
422
+ - **mode 2.** `[0xd1, 0x14, 0x08, 0, 0, 0, 0]` → `0x14 = 20`: baseline 0, zigzag 10, delta +5 → `5`;
423
+ `0x08 = 8`: baseline 0, zigzag 4, delta +2 → `7`. Output `[5, 7]`. Plus a vector that alternates
424
+ the baseline bit, which is the whole reason mode 2 exists.
425
+ - **filters.** Values computed from each spec's own pseudo-code in the test, not from the
426
+ implementation: unit ±X/±Y/±Z normals through octahedral at both strides, identity and
427
+ each-of-four-`max_component` quaternions, exponential words with negative exponents, negative
428
+ mantissas and `m = 0`, and for colour a grey, a saturated primary and a partial alpha at both
429
+ strides and at a `K` below the component width.
430
+ - **rejection.** Truncated streams, wrong header bytes, a `0xa1` stream offered under the `EXT_`
431
+ name, a `COLOR` filter under the `EXT_` name, an invalid channel mode byte, and a mode 1 stream
432
+ whose `data` does not land on `codeaux`.
433
+
434
+ ### 5.3 Round trip
435
+
436
+ A **test-only** mode 0 encoder in the spec file (raw-byte groups only, the simplest legal encoding)
437
+ gives a randomised round trip over strides 4/8/12/16/64 and counts that straddle the 16-element
438
+ group and 256-element block boundaries. It is deliberately *secondary*: it shares the layout
439
+ assumptions of the decoder, so a shared misreading passes. Its job is exercising the block and group
440
+ loop bounds, not proving the format. §5.1 and §5.2 prove the format.
441
+
442
+ ### 5.4 End to end
443
+
444
+ `gltf_test_fixtures.js` gains `build_meshopt_triangle_gltf_json(extension_name, buffer_uri, options)`
445
+ and a matching `_glb`: the one-triangle model with its four bufferViews compressed (positions, normals and
446
+ uvs in mode 0, indices in mode 1) by the fixture's own minimal encoder, a `fallback: true`
447
+ placeholder buffer with no URI, and `extensionsUsed` / `extensionsRequired` set. A spec then loads
448
+ it through the real `AssetManager` and `GLTFSceneBundleAssetLoader` — as
449
+ `GLTFSceneBundleAssetLoader.spec.js` already does — under **both** extension names, and asserts the
450
+ resulting bundle's geometry equals the uncompressed fixture's. That covers the fallback-buffer path,
451
+ the bufferView rewrite, and the fact that `load_gltf.js` needs no changes.
452
+
453
+ That file, though, is one the *vendor* extension could have described just as well — the Khronos name
454
+ on it and nothing else. `options` makes it a file only KHR defines: attribute streams at codec
455
+ version 1 carrying a channel mode each (a rotated exclusive-or over the positions, byte deltas over
456
+ the normals, 16-bit deltas over the texture coordinates), and a `COLOR`-filtered `COLOR_0` the mesh
457
+ reader maps to `StandardAttributes.Color`. Each of the two is served on its own as well as together,
458
+ so that a test watching the vendor extension refuse one is refusing *that* one — asserting against a
459
+ file carrying both passes on either constraint, and then removing one of them from the vendor
460
+ extension goes unnoticed.
461
+
462
+ ### 5.5 What none of this covers
463
+
464
+ No test here decodes a stream produced by `gltfpack`. Every byte under test was authored from a
465
+ specification by me or by a fixture encoder I also wrote; a misreading shared between them survives.
466
+ §5.1 is the only genuinely external oracle, and it covers one group encoding of one mode.
467
+
468
+ **Recommendation to the sponsor: drop one `gltfpack -noq -cc` output (and one `-cc -vv` for codec
469
+ version 1) into the repo, and add a golden test that decodes it and checks every `POSITION`
470
+ accessor's values against that accessor's declared `min`/`max`, and every index against the vertex
471
+ count.** Those bounds are written by the encoder, are not derivable from the compressed bytes, and
472
+ would catch a systematic misreading immediately. Left out of this plan because it needs files only
473
+ the sponsor can supply.
474
+
475
+ ## 6. Adversarial review of this plan
476
+
477
+ Each item is a way this plan is wrong or insufficient, and what it changes.
478
+
479
+ ### 6.1 The tail was read from the wrong end
480
+
481
+ The first draft of this plan had the baseline element at the **start** of a `max(stride, 32)`-byte
482
+ tail, from EXT's "a baseline element stored verbatim, padded to 32 bytes", and cited a reading of
483
+ the reference decoder that appeared to confirm it. Both were wrong, and for any `byteStride` below
484
+ 32 — which is every attribute meshopt is actually used on — it decodes an entire model to garbage
485
+ while every unit test written from the same misreading passes.
486
+
487
+ What caught it was reading KHR, which reworded the same clause to "Tail padding, which pads the size
488
+ of the *subsequent* tail block…" and added a second item to the tail block that forces the question.
489
+ The corroborating detail is that the reference keeps two quantities, `tail_size` and
490
+ `tail_size_pad`, uses the **unpadded** one to locate the baseline and the **padded** one to validate
491
+ the remainder — a distinction that has no meaning at all under the wrong reading.
492
+
493
+ **Changes:** §3.1 states both quantities and where each is used; §5.2's first vector is chosen
494
+ specifically to discriminate them; and the general lesson is written into §6.11.
495
+
496
+ ### 6.2 `Uint8Array` out-of-bounds reads return `undefined`, and `undefined & 0xff` is `0`
497
+
498
+ The worst failure mode in the design. JavaScript does not fault on a typed-array read past the end —
499
+ it yields `undefined`, and every bitwise operator coerces that to `0`. A truncated or malformed
500
+ stream therefore decodes to *plausible-looking zeros* rather than an error, and the model loads
501
+ wrong instead of failing. The reference is bounds-checked at every group and every index read for
502
+ exactly this reason.
503
+
504
+ **Change:** explicit bounds checks are not optional, and are not `assert` (stripped in production —
505
+ this input is a file, not a caller). Real `throw` at the header, at each byte group against the
506
+ 24-byte decode limit, at each literal and control-header read, at each index varint, and at the
507
+ final data-lands-on-the-tail equality in all three modes. Reject-a-truncated-stream cases added to
508
+ §5.2.
509
+
510
+ ### 6.3 Mutating the bufferView descriptors races the image loader
511
+
512
+ The first draft rewrote `json.bufferViews[i]` in place. `loadFromJson` builds the image promises
513
+ *before* buffers resolve, and each one closes over its `bufferView` object and reads `.byteOffset` /
514
+ `.byteLength` inside a `.then()` that runs *after* the rewrite. Mutating in place changes what an
515
+ already-scheduled image read sees, from a different code path, with no visible link between the two.
516
+
517
+ **Change:** §2.2 returns a new array of new descriptors and leaves the originals untouched. The
518
+ image path keeps reading exactly what it reads today, whatever order the promises settle in. This is
519
+ the reason for a design choice that otherwise looks like needless allocation, and it is recorded
520
+ where the code lives.
521
+
522
+ ### 6.4 `Math.round` is not the spec's `round`
523
+
524
+ `Math.round(-2.5)` is `-2`. The filters round signed symmetric quantities and the reference rounds
525
+ half away from zero. Half a quantisation step on normals is invisible in a screenshot and visible in
526
+ a diff against any other decoder — exactly the kind of drift nobody attributes correctly six months
527
+ later.
528
+
529
+ **Change:** `round_half_away_from_zero` in `core/math`, used by every filter, with the asymmetry
530
+ named in its JSDoc.
531
+
532
+ ### 6.5 A green suite here does not mean a `gltfpack` file loads
533
+
534
+ Two things sit between this feature and a real compressed asset, and neither is in scope:
535
+
536
+ - **`KHR_mesh_quantization`.** `gltfpack`'s default output quantises as well as compresses, and meep
537
+ does not implement that extension. Worse, quantised attributes are padded — a `VEC3`/`SHORT`
538
+ position gets `byteStride` 8, not 6 — and `load_gltf.js` rejects any bufferView whose `byteStride`
539
+ differs from `componentSize × componentCount` with `'Interleaved attributes are not supported'`.
540
+ So a default `gltfpack` file will fail *after* decompressing correctly.
541
+ - **Interleaved attributes**, same rejection, for the same reason.
542
+
543
+ `gltfpack -noq -cc` produces meshopt-compressed, non-quantised, non-interleaved output, and that is
544
+ the configuration this feature makes work. Stated here rather than discovered later; picking up
545
+ `KHR_mesh_quantization` is separate work and is not silently folded into this one.
546
+
547
+ ### 6.6 Pure JS is roughly an order of magnitude off the reference
548
+
549
+ The reference reaches ~1 GB/s with WebAssembly SIMD. This will not, and the extension exists partly
550
+ *because* decode is meant to be nearly free. Decompression is synchronous inside `loadFromJson`, so
551
+ it lands on whichever thread is parsing — the main thread for a foreground load.
552
+
553
+ Accepted, not designed around: the alternative is a WASM dependency, which the brief excludes.
554
+ Mitigated by the shape the reference already uses — a module-static 8 KiB delta scratch (one
555
+ attribute block's worth: `byte_stride × max_block_elements <= 8192` by construction) and a 256-byte
556
+ group buffer, so the strided writes stay in cache and there is no per-block allocation. No
557
+ performance claim is made without a measurement, and none has been taken.
558
+
559
+ ### 6.7 The extension's `count` is not the accessor's `count`
560
+
561
+ `count` is the number of *stride-sized elements in the bufferView*; for index modes that is the
562
+ index count, not the triangle count. Reading it as either is a silent 3× error that only shows on
563
+ non-triangle-aligned data.
564
+
565
+ **Change:** each spec's own invariants become the validation list, checked before decode and thrown
566
+ on. Parent `byteLength === byteStride × count`; parent `byteStride`, when present, equals the
567
+ extension's; `ATTRIBUTES` → stride divisible by 4, `>= 4` (KHR) and `<= 256`; `TRIANGLES` → count
568
+ divisible by 3; `TRIANGLES`/`INDICES` → stride 2 or 4 and filter absent or `NONE`; `OCTAHEDRAL` →
569
+ stride 4 or 8; `QUATERNION` → stride 8; `EXPONENTIAL` → stride divisible by 4; `COLOR` → stride 4
570
+ or 8 **and** the KHR name. Plus the source range lying inside the source buffer, which both specs
571
+ leave implicit, and the KHR rule that a bufferView must not carry both extension names.
572
+
573
+ ### 6.8 The fallback buffer is allocated at its declared `byteLength`
574
+
575
+ Both specs require a placeholder large enough to hold every uncompressed view referencing it — a
576
+ megabyte-scale allocation for a real model, of a buffer that by construction nothing reads once the
577
+ views are rewritten.
578
+
579
+ **Change:** it resolves to a **zero-length** buffer. A well-formed file never touches it; a
580
+ malformed one — a view referencing the fallback without carrying the extension — fails loudly on an
581
+ out-of-range typed-array construction, which is the correct outcome and is preferable to quietly
582
+ handing out a megabyte of zeros that renders as a degenerate mesh.
583
+
584
+ ### 6.9 Version and name policy has three different answers, and uniformity would be a bug
585
+
586
+ The temptation is one rule for all three headers. They are not the same:
587
+
588
+ - Mode 0 version 1 is a *different bitstream*, so decoding `0xa1` as `0xa0` is a silent wrong
589
+ answer. It is supported, and it is rejected under the `EXT_` name, which does not define it.
590
+ - Mode 1 and mode 2 versions 0 and 1 differ only in `fec_max`, which is read from the header, so
591
+ both decode correctly and both are accepted under either name.
592
+ - Filter `COLOR` is accepted only under the `KHR_` name.
593
+
594
+ And two decode-time hazards are left alone on purpose, because the specs declare them unspecified
595
+ and JavaScript's typed arrays already contain the damage: a colour element whose fourth component is
596
+ zero (infinite scale, finite garbage bytes on store) and a quaternion whose retained components
597
+ exceed unit length (already clamped at the radicand). Neither can produce a `NaN` that escapes into
598
+ the scene, and neither gets a guard.
599
+
600
+ ### 6.10 Nothing checks `extensionsRequired`
601
+
602
+ The loader ignores `extensionsRequired` entirely, so a file requiring an extension meep does not
603
+ implement loads and renders wrong. Pre-existing and out of scope — noted so it is not mistaken for
604
+ something this change introduced or fixed.
605
+
606
+ ### 6.11 The residual risk this plan cannot retire
607
+
608
+ Three details are taken from questions put to the reference implementation rather than from
609
+ specification text, and one is taken from an inference:
610
+
611
+ - literal control mode 3 consumes the **group-aligned** element count per byte position, not the
612
+ block's unaligned count (inferred: all four control modes must agree on the scratch stride);
613
+ - channel mode 2 rotates **left** by `r` on decode;
614
+ - the version 1 tail-padding minimum is 24 bytes, not 32.
615
+
616
+ Each is a silent-garbage failure if wrong, and none is discriminated by any test in §5 — a fixture
617
+ encoder written from the same understanding agrees with the decoder. They are the specific reason
618
+ §5.5's ask matters: one real `gltfpack -cc -vv` file settles all three at once. Until there is one,
619
+ **version 1 support is implemented and tested but not evidenced**, and this paragraph is the honest
620
+ statement of that.
621
+
622
+ ## 7. Commit sequence
623
+
624
+ Each commit is independently green (`npm run test` from `H:/git/moh`).
625
+
626
+ 1. `feat(math): rounding that breaks its ties away from zero`
627
+ 2. `feat(binary): meshopt's attribute codec, against the bytes the spec itself decodes`
628
+ — mode 0 version 0, the group and channel decoders, the varint, the two enums, specs.
629
+ 3. `feat(binary): the attribute codec's second version, and the channels it decodes through`
630
+ — mode 0 version 1: control header, control modes, 1-bit groups, channel modes, specs.
631
+ 4. `feat(binary): meshopt's two index codecs, and the tail that checks them`
632
+ — modes 1 and 2, specs.
633
+ 5. `feat(binary): four meshopt filters, one of them meep's own octahedron`
634
+ — filters 1/2/3/4, specs.
635
+ 6. `feat(binary): one entry point per compressed buffer view`
636
+ — `meshopt_decode` dispatch, spec.
637
+ 7. `feat(gltf): a compressed buffer view becomes an ordinary one`
638
+ — the binding module and its validation, under both extension names, spec.
639
+ 8. `fix(gltf): a buffer with no URI is a placeholder, not a request`
640
+ — the tiny-gltf buffer loop, GLB buffers past the chunk.
641
+ 9. `feat(gltf): the loader decodes compressed views before an accessor reads one`
642
+ — the `loadFromJson` call, the compressed-image-view throw, the end-to-end fixture and spec.
643
+
644
+ ## 8. What execution changed
645
+
646
+ Written after the work landed. The plan above is corrected in place where it was factually wrong
647
+ about the format; everything else is recorded here rather than edited away, because a plan that
648
+ quietly matches its outcome is not evidence of anything.
649
+
650
+ ### 8.1 The plan was wrong about the `0xfe`/`0xff` ordering
651
+
652
+ §3.2 claimed that computing and explicitly reading each of the three indices in turn "diverges on
653
+ the first triangle that mixes them". It does not. An index in that branch is either fresh — and
654
+ takes a turn at `next` — or explicit, and takes a varint; never both. The two passes are disjoint
655
+ per index, so interleaving them is equivalent.
656
+
657
+ Found by mutation: rewriting the branch to interleave them left all fifty-four tests green, and the
658
+ question "which test should have caught this?" has the answer "none, because there is nothing to
659
+ catch". What *is* order-dependent is the sequence of the explicit reads, because `last` chains
660
+ through them; a test with a codeaux of `0xff`, where all three indices are explicit, now pins it.
661
+
662
+ §3.2 also conflated two things about the conditional FIFO push. The *write* at a non-advancing
663
+ offset is unobservable (no well-formed stream reads distance 16). The *non-advance* is very much
664
+ observable, at any distance a later code reaches. Two tests now do.
665
+
666
+ ### 8.2 A specification erratum, in both documents
667
+
668
+ Of the three worked examples both extensions print for the varint encoding,
669
+
670
+ ```
671
+ 0x7f => 0x7f
672
+ 0x81 0x04 => 0x201
673
+ 0xff 0xa0 0x05 => 0x1fd005
674
+ ```
675
+
676
+ the third is wrong. Those bytes are the LEB128 encoding of `0x1fd005` written back to front; read as
677
+ LEB128 they are `0x1507f`, and `0x1fd005` encodes as `0x85 0xa0 0x7f`. The example only works if the
678
+ groups are read most significant first, which contradicts the example above it, the encoding the
679
+ document names, and the reference implementation.
680
+
681
+ `meshopt_read_uint_var.spec.js` pins both readings of both byte strings so that nobody later "fixes"
682
+ the reader to match the printed line.
683
+
684
+ ### 8.3 Two things the plan claimed mattered, which cannot be observed
685
+
686
+ Both were found by mutating the implementation and watching the suite stay green, and both are now
687
+ written down where they live rather than left to look like tested behaviour.
688
+
689
+ - **§6.4, the rounding mode.** `round_half_away_from_zero` cannot be told from `Math.round` through
690
+ any of the four filters. A renormalised octahedral component is a ratio with an irrational
691
+ denominator and never lands halfway between two integers — checked exhaustively over the whole
692
+ 8-bit input space, 8388477 component values, no ties — and the quaternion filter's scale is
693
+ irrational for the same reason. The colour filter's scale is rational, but its inputs are
694
+ non-negative for any valid element, and a positive tie rounds the same way either way. The helper
695
+ is kept because it is what the specifications say; the claim that a test proves it is withdrawn,
696
+ and a standing sweep now asserts the no-ties property that makes it moot.
697
+ - **§3.4, the quaternion radicand's clamp.** The output goes through an `Int16Array`, and storing a
698
+ `NaN` there yields the same zero the clamp produces. Kept so the function is total on its own
699
+ rather than by a coincidence thirty lines downstream — which is exactly the kind of thing a
700
+ refactor removes — but nothing tests it, and the spec now says so.
701
+
702
+ ### 8.4 Structure
703
+
704
+ - Planned commits 2 and 3 (attribute codec versions 0 and 1) landed as one. The block loop, the
705
+ group decoder and the channel reconstruction are shared; splitting them would have meant writing
706
+ the module twice.
707
+ - The test-only encoder §5.3 put inline in a spec file became `__meshopt_test_streams.js`, because
708
+ the end-to-end glTF fixtures need the same streams. `**/__**.js` is already how meep's coverage
709
+ configuration spells "scaffolding".
710
+ - Three test vectors in the first draft were wrong and the implementation was right: a quaternion
711
+ component stored at full scale is `1/sqrt(2)` and not 1; a quaternion whose four components are
712
+ equal has its dropped component absorb all three of the others' rounding, so it is up to three and
713
+ a half quantisation steps out rather than half a step; and a colour alpha of `0x80` is the marker
714
+ bit over an empty field, which is zero and not one. The bounds are now derived in the test from
715
+ the quantisation step rather than picked.
716
+
717
+ ### 8.5 The record
718
+
719
+ Thirty-two mutations were applied to the finished implementation to check the suite says so. Thirty
720
+ failed at least one test. The two that did not are §8.3, and are documented rather than papered over.
721
+
722
+ `npm run test` from `H:/git/moh` covers all of it; the meshopt package and its glTF binding are 96
723
+ tests across 12 files, plus 7 end-to-end through the real asset framework.
724
+
725
+ ### 8.6 What is still owed
726
+
727
+ §5.5 and §6.11 stand unchanged, and are the honest limit of this work:
728
+
729
+ **No test here decodes a stream `gltfpack` produced.** Every byte under test was authored from a
730
+ specification by me, or by a fixture encoder I also wrote. Three details — literal control mode 3's
731
+ element count, channel mode 2's rotation direction, and version 1's 24-byte tail minimum — come from
732
+ questions put to the reference rather than from specification text, and no test discriminates any of
733
+ them.
734
+
735
+ One `gltfpack -noq -cc` output and one `-cc -vv` output, checked in with a golden test that
736
+ validates every `POSITION` accessor against its own declared `min`/`max` and every index against the
737
+ vertex count, would settle all three at once. Those bounds are written by the encoder and are not
738
+ derivable from the compressed bytes.
739
+
740
+ Until then: version 0 is corroborated by the specification's own worked example, and **version 1 is
741
+ implemented and tested but not evidenced.**
742
+
743
+ ## 9. The seam this was first built on the wrong side of
744
+
745
+ The first version put the whole glTF half in one module, `gltf_meshopt_compression.js`, exporting
746
+ `gltf_meshopt_decode_buffer_views(buffer_views, buffers)`. The parser imported that by name and
747
+ called it on every model it loaded.
748
+
749
+ It worked, and every test above passed against it. It was still the wrong shape, for reasons worth
750
+ writing down because none of them is a bug:
751
+
752
+ - **The name described the caller's hope, not the function.** A thing called
753
+ `gltf_meshopt_decode_buffer_views` does not decode bufferViews. It walks all of them, works out
754
+ which are anybody's, decodes those, and rewrites the array. Three jobs under one codec's name.
755
+ - **Detection was welded to decoding.** The parser assumed meshopt by importing it, and the check
756
+ that it was meshopt happened *inside*, four frames down. Reading the call site told you nothing
757
+ about whether a plain glTF paid anything — which is exactly the question it should answer.
758
+ - **The second extension proved the point and the third would have made it.** `KHR_` was bolted on
759
+ as `if (name === MESHOPT_COMPRESSION_EXT && ...)` inside the decoder. A Draco or a future codec
760
+ would have been another module the parser imported by name, and another branch.
761
+
762
+ What replaced it is in §2.2. The parser asks a set what claims a view; the set answers with an
763
+ extension or with nothing; the walk is identical for all of them. `tiny-gltf.js` no longer contains
764
+ the string "meshopt" anywhere, comments included.
765
+
766
+ Two smaller things went the same way:
767
+
768
+ - `meshopt_decode`'s mode and filter dispatch were a seven-branch `if / else if` chain. The three
769
+ modes already share a signature and the filters already share theirs, so both are now arrays
770
+ indexed by the enum, and "none" is a function that does nothing rather than a branch that asks
771
+ whether to.
772
+ - The extension validator was fourteen `if (...) throw` in a row, several of them comparing mode and
773
+ filter names. The specifications state those constraints as a table, so it is a table: what each
774
+ mode and each filter admits of a stride and a count, with the rule's own wording carried alongside
775
+ for the message. Eight guards, none of them naming a mode.
776
+
777
+ Eight mutations were applied to the new seams to check the suite says so — the walker decoding
778
+ unclaimed views, the walker dropping its length backstop, the set taking the first claimant, the set
779
+ forgetting placeholder buffers, meshopt admitting any filter it can name, one version ceiling for
780
+ every mode, and each dispatch table shuffled. All eight fail at least one test.
781
+
782
+ ## Addendum, 2026-08-20: a document's resolved buffers are `Uint8Array`
783
+
784
+ Written into the plan as `ArrayBuffer`, and changed when the virtual-geometry builder started
785
+ reading containers through the same layer. A buffer is a *range* of bytes: a `.glb`'s binary chunk
786
+ is a range of the file it arrived in, and a buffer read off a filesystem starts wherever the runtime
787
+ put it. Carrying the offset with the bytes is what lets the chunk be handed on without copying a
788
+ model-sized allocation, and `Uint8Array.subarray` is what a decoder's source range wants anyway —
789
+ `MeshoptBufferViewExtension` reads one with `subarray` rather than a three-argument constructor that
790
+ can only be laid over an aligned offset.
791
+
792
+ `decode()` answers with a `Uint8Array` for the same reason, and the length check over it is
793
+ unchanged.