@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.
- package/LICENSE +188 -188
- package/README.md +152 -145
- package/editor/Editor.js +598 -598
- package/editor/EditorCameraNavigation.js +205 -205
- package/editor/EditorKeyMap.js +182 -182
- package/editor/SelectionVisualizer.js +127 -127
- package/editor/actions/concrete/ActionInvalidateSampler.js +27 -27
- package/editor/actions/concrete/PatchTerrainHeightAction.js +85 -85
- package/editor/camera/camera_framing.js +104 -104
- package/editor/clipboard.js +184 -184
- package/editor/ecs/component/editors/ObservedIntegerEditor.js +22 -22
- package/editor/ecs/component/editors/ObservedStringEditor.js +34 -34
- package/editor/ecs/component/editors/common/two_way_sync.js +50 -50
- package/editor/ecs/component/editors/ecs/GridObstacleEditor.js +19 -19
- package/editor/ecs/component/editors/ecs/ParameterLookupTableEditor.js +35 -35
- package/editor/ecs/component/editors/ecs/ParameterTrackEditor.js +17 -17
- package/editor/ecs/component/editors/ecs/SGMeshEditor.js +24 -24
- package/editor/ecs/component/editors/ecs/ShadedGeometryEditor.js +33 -33
- package/editor/ecs/component/editors/ecs/Trail3DEditor.js +45 -45
- package/editor/ecs/component/editors/ecs/buildGridObstaclePreview.js +19 -19
- package/editor/ecs/component/editors/ecs/terrain/TerrainEditor.js +72 -72
- package/editor/ecs/component/editors/shade/MeshletGeometryEditor.js +30 -30
- package/editor/ecs/component/editors/shade/ShadeImageEditor.js +70 -70
- package/editor/ecs/component/editors/shade/ShadeMaterialEditor.js +34 -34
- package/editor/ecs/component/editors/shade/ShadeTextureEditor.js +46 -46
- package/editor/ecs/component/editors/shade/StandardShadeMaterialEditor.js +24 -24
- package/editor/ecs/component/prototypeObjectEditor.js +265 -265
- package/editor/ecs/component/registerBasicTypeEditors.js +100 -100
- package/editor/ecs/component/registerEngineComponentEditors.js +95 -95
- package/editor/entity_world_bounds.js +27 -27
- package/editor/particles/lut_ops.js +148 -148
- package/editor/particles/particleEditEvents.js +12 -12
- package/editor/particles/rebuildParticleEmitter.js +31 -31
- package/editor/persistence/EditorLayoutStore.js +71 -71
- package/editor/persistence/SceneMetadata.js +52 -52
- package/editor/persistence/SceneSlotManager.js +144 -144
- package/editor/persistence/buildNewSceneDataset.js +67 -67
- package/editor/persistence/files.js +68 -68
- package/editor/persistence/scene_import.js +143 -143
- package/editor/persistence/scene_serialization.js +79 -79
- package/editor/persistence/string_buffer_codec.js +41 -41
- package/editor/process/GridDisplayProcess.js +125 -125
- package/editor/process/SymbolicDisplayProcess.js +106 -108
- package/editor/process/symbolic/CameraSymbolicDisplay.js +146 -146
- package/editor/process/symbolic/LightSymbolicDisplay.js +172 -172
- package/editor/process/symbolic/PathSymbolicDisplay.js +118 -118
- package/editor/process/symbolic/PositionedMarkerSymbolicDisplay.js +79 -79
- package/editor/process/symbolic/SoundEmitterSymbolicDisplay.js +57 -57
- package/editor/process/symbolic/SymbolicDisplay.js +62 -62
- package/editor/process/symbolic/gizmo_draw_wire_box_oriented.js +85 -85
- package/editor/process/symbolic/gizmo_draw_wire_circle.js +53 -53
- package/editor/prototypeEditorShell.js +156 -156
- package/editor/selection/editor_pick.js +130 -130
- package/editor/selection/screen_rect_frustum.js +119 -119
- package/editor/style/controls.scss +168 -168
- package/editor/style/inspector.scss +223 -223
- package/editor/templates/entity_templates.js +167 -167
- package/editor/tools/GridPaintTool.js +273 -273
- package/editor/tools/SelectionTool.js +307 -307
- package/editor/tools/TransformToolV2.js +378 -378
- package/editor/tools/engine/ToolEngine.js +188 -188
- package/editor/tools/paint/TerrainTexturePaintTool.js +250 -250
- package/editor/tools/v2/BlenderCameraOrientationGizmo.js +501 -501
- package/editor/tools/v2/TransformControls.js +971 -971
- package/editor/tools/v2/handle/gizmo_drag_plane.js +141 -141
- package/editor/tools/v2/handle/gizmo_draw.js +399 -399
- package/editor/tools/v2/handle/gizmo_handles.js +364 -364
- package/editor/tools/v2/handle/gizmo_ray_shapes.js +239 -239
- package/editor/view/ecs/HierarchicalEntityListView.js +339 -339
- package/editor/view/ecs/components/DatGuiController.js +2 -2
- package/editor/view/ecs/components/common/AutoCanvasView.js +100 -100
- package/editor/view/ecs/components/common/TextController.js +59 -59
- package/editor/view/library/MeshLibraryView.js +175 -175
- package/editor/view/library/mesh_library_drag.js +63 -63
- package/editor/view/library/model_thumbnail_source.js +86 -86
- package/editor/view/makeEntityDecorators.js +125 -125
- package/editor/view/node-graph/NodeGraphSelection.js +89 -89
- package/editor/view/node-graph/NodeView.js +211 -211
- package/editor/view/node-graph/actions/ConnectionDeleteAction.js +36 -36
- package/editor/view/node-graph/actions/NodesMoveAction.js +41 -41
- package/editor/view/node-graph/connection_wire_geometry.js +107 -107
- package/editor/view/particles/ColorLutGradientView.js +291 -291
- package/editor/view/particles/ScalarLutCurveView.js +279 -279
- package/editor/view/prepareMeshLibrary.js +188 -188
- package/editor/view/shell/SceneTreePanelView.js +119 -119
- package/editor/view/v2/SplitView.js +2 -2
- package/package.json +94 -94
- package/samples/generation/generators/interactive/mir_generator_place_buff_objects.js +362 -362
- package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +738 -738
- package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +79 -79
- package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +93 -93
- package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +80 -80
- package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +164 -164
- package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +69 -69
- package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +102 -102
- package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +129 -129
- package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +72 -72
- package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +74 -74
- package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +169 -169
- package/src/DUPLICATION_AUDIT_2026_08_07.md +254 -254
- package/src/DUPLICATION_AUDIT_REMEDIATION.md +250 -250
- package/src/REVIEW_2026_08_06/adv-core.md +511 -511
- package/src/REVIEW_2026_08_06/adv-gfx.md +480 -480
- package/src/REVIEW_2026_08_06/adv-view.md +446 -446
- package/src/REVIEW_2026_08_06/api-core.md +296 -296
- package/src/REVIEW_2026_08_06/api-engine.md +195 -195
- package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +507 -507
- package/src/REVIEW_2026_08_06/core-binary.md +348 -348
- package/src/REVIEW_2026_08_06/core-collection.md +376 -376
- package/src/REVIEW_2026_08_06/core-math.md +221 -221
- package/src/REVIEW_2026_08_06/core-process.md +266 -266
- package/src/REVIEW_2026_08_06/core-science.md +223 -223
- package/src/REVIEW_2026_08_06/engine-ai-nav.md +279 -279
- package/src/REVIEW_2026_08_06/engine-animation.md +167 -167
- package/src/REVIEW_2026_08_06/engine-asset.md +166 -166
- package/src/REVIEW_2026_08_06/engine-ecs.md +920 -920
- package/src/REVIEW_2026_08_06/engine-input.md +197 -197
- package/src/REVIEW_2026_08_06/engine-misc.md +248 -248
- package/src/REVIEW_2026_08_06/engine-terrain.md +52 -52
- package/src/REVIEW_2026_08_06/generation.md +176 -176
- package/src/REVIEW_2026_08_06/geom-2d.md +434 -434
- package/src/REVIEW_2026_08_06/geom-3d.md +117 -117
- package/src/REVIEW_2026_08_06/gfx-gi.md +143 -143
- package/src/REVIEW_2026_08_06/gfx-render.md +740 -740
- package/src/REVIEW_2026_08_06/gfx-texture.md +690 -690
- package/src/REVIEW_2026_08_06/prior-criticals.md +49 -49
- package/src/REVIEW_2026_08_06/prior-highs.md +138 -138
- package/src/REVIEW_2026_08_06/test-gaps.md +364 -364
- package/src/REVIEW_2026_08_06/view.md +667 -667
- package/src/REVIEW_2026_08_06.md +610 -610
- package/src/avif/codec/dec/avif_dec.cpp +233 -233
- package/src/avif/codec/dec/avif_dec.js +16 -16
- package/src/core/binary/BitImage2.js +246 -246
- package/src/core/binary/align_32.js +21 -21
- package/src/core/binary/data_view/DataType2DataViewReaders.js +23 -23
- package/src/core/binary/data_view/DataType2DataViewWriters.js +25 -25
- package/src/core/binary/hash/XXH128Hash.js +55 -55
- package/src/core/binary/hash/XXH3_SECRET.js +25 -25
- package/src/core/binary/hash/xxh3_128.js +341 -341
- package/src/core/binary/hash/xxh3_64.js +241 -241
- package/src/core/binary/hash/xxh3_common.js +476 -476
- package/src/core/binary/lz4/LZ4_MAX_INPUT_SIZE.js +9 -9
- package/src/core/binary/lz4/lz4_compress_block.js +385 -385
- package/src/core/binary/lz4/lz4_compress_bound.js +25 -25
- package/src/core/binary/lz4/lz4_decompress_block.js +139 -139
- package/src/core/binary/lz4/lz4_decompress_bound.js +30 -30
- package/src/core/binary/meshopt/MESHOPT_GROUP_SIZE.js +18 -18
- package/src/core/binary/meshopt/MeshoptCompressionFilter.js +30 -30
- package/src/core/binary/meshopt/MeshoptCompressionMode.js +21 -21
- package/src/core/binary/meshopt/__meshopt_test_streams.js +237 -237
- package/src/core/binary/meshopt/meshopt_decode.js +73 -73
- package/src/core/binary/meshopt/meshopt_decode_byte_group.js +67 -67
- package/src/core/binary/meshopt/meshopt_decode_data_block.js +59 -59
- package/src/core/binary/meshopt/meshopt_decode_filter_color.js +69 -69
- package/src/core/binary/meshopt/meshopt_decode_filter_exponential.js +43 -43
- package/src/core/binary/meshopt/meshopt_decode_filter_octahedral.js +60 -60
- package/src/core/binary/meshopt/meshopt_decode_filter_quaternion.js +71 -71
- package/src/core/binary/meshopt/meshopt_decode_index_buffer.js +294 -294
- package/src/core/binary/meshopt/meshopt_decode_index_sequence.js +115 -115
- package/src/core/binary/meshopt/meshopt_decode_vertex_buffer.js +381 -381
- package/src/core/binary/meshopt/meshopt_read_uint_var.js +59 -59
- package/src/core/binary/reinterpret_float32_as_uint32.js +13 -13
- package/src/core/binary/reinterpret_uint32_as_float32.js +14 -14
- package/src/core/binary/type/DataType2TypedArrayConstructorMapping.js +35 -35
- package/src/core/bvh2/bvh3/ebvh_geometry_query_any_triangle_ray.js +149 -149
- package/src/core/bvh2/bvh3/ebvh_sort_for_traversal_depth_first.js +96 -96
- package/src/core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js +101 -101
- package/src/core/bvh2/bvh3/query/bvh_query_leaves_generic.js +77 -77
- package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray.js +90 -90
- package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray_segment.js +94 -94
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_generic.js +86 -86
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_capsule.js +101 -101
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_sphere.js +92 -92
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray.js +96 -96
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray_segment.js +100 -100
- package/src/core/bvh2/visual/BVHGeometry.js +131 -131
- package/src/core/bvh8/BVH8.js +436 -436
- package/src/core/bvh8/aabb3_round_to_float32.js +22 -22
- package/src/core/bvh8/build/BVH8Converter.js +588 -588
- package/src/core/bvh8/build/TriangleCluster.js +122 -122
- package/src/core/bvh8/build/aabb3_compute_merge_cost.js +28 -28
- package/src/core/bvh8/build/aabb3_from_triangle_by_index.js +17 -17
- package/src/core/bvh8/build/bvh8_build_for_geometry.js +303 -303
- package/src/core/bvh8/build/bvh8_from_proxy.js +256 -256
- package/src/core/bvh8/build/byte.js +9 -9
- package/src/core/bvh8/build/encode_bounds_e.js +11 -11
- package/src/core/bvh8/bvh8_convert_to_dot.js +132 -132
- package/src/core/bvh8/bvh8_count_primitives.js +98 -98
- package/src/core/bvh8/bvh8_geometry_validate.js +138 -138
- package/src/core/bvh8/bvh8_geometry_validate_indirect.js +166 -166
- package/src/core/bvh8/bvh8_get_node_bounds.js +34 -34
- package/src/core/bvh8/bvh8_get_node_child_bounds.js +52 -52
- package/src/core/bvh8/bvh8_node_child_surface_area.js +18 -18
- package/src/core/bvh8/bvh8_node_count_triangles.js +27 -27
- package/src/core/bvh8/bvh8_quality.js +72 -72
- package/src/core/bvh8/bvh8_validate_structure.js +87 -87
- package/src/core/clipboard/obtainClipBoard.js +29 -29
- package/src/core/clipboard/safeClipboardReadText.js +55 -55
- package/src/core/clipboard/safeClipboardWriteText.js +23 -23
- package/src/core/collection/array/typed/typed_array_value_denormalize.js +52 -52
- package/src/core/collection/array/typed/typed_array_value_normalize.js +51 -51
- package/src/core/collection/union-find/union_find.js +79 -79
- package/src/core/color/YCoCg/rgb_to_ycocg.js +20 -20
- package/src/core/color/YCoCg/ycocg_to_rgb.js +17 -17
- package/src/core/color/colormap/MAGMA_LUT.js +26 -26
- package/src/core/color/illuminant/D65_TRISTIMULUS_XYZ.js +19 -19
- package/src/core/color/lab/lab_apply_hunt_adjustment.js +27 -27
- package/src/core/color/lab/lab_distance_hyab.js +23 -23
- package/src/core/color/lab/xyz_to_lab.js +62 -62
- package/src/core/color/operations/color_darken.js +24 -24
- package/src/core/color/operations/color_desaturate.js +24 -24
- package/src/core/color/operations/color_lighten.js +24 -24
- package/src/core/color/operations/color_saturate.js +24 -24
- package/src/core/color/operations/color_scale_okhsv_channel.js +45 -45
- package/src/core/color/tonemap/tonemap_aces.js +41 -41
- package/src/core/color/ycxcz/xyz_to_ycxcz.js +28 -28
- package/src/core/color/ycxcz/ycxcz_to_xyz.js +19 -19
- package/src/core/dom/isImageBitmap.js +12 -12
- package/src/core/function/frameThrottle.js +23 -23
- package/src/core/geom/2d/aabb/aabb2_array_combine.js +7 -7
- package/src/core/geom/2d/aabb/aabb2_compute_area.js +7 -7
- package/src/core/geom/2d/aabb/aabb2_compute_center_from_multiple.js +7 -7
- package/src/core/geom/2d/aabb/aabb2_compute_overlap.js +7 -7
- package/src/core/geom/2d/aabb/aabb2_from_v2_array.js +7 -7
- package/src/core/geom/2d/aabb/aabb2_intersects_point.js +7 -7
- package/src/core/geom/2d/aabb/aabb2_overlap_exists.js +7 -7
- package/src/core/geom/2d/circle/circle_compute_circle_intersection.js +7 -7
- package/src/core/geom/2d/circle/circle_compute_circle_penetration.js +7 -7
- package/src/core/geom/2d/circle/circle_intersects_point.js +7 -7
- package/src/core/geom/2d/compute_polygon_area_2d.js +7 -7
- package/src/core/geom/2d/convex-hull/fixed_convex_hull_humus.js +7 -7
- package/src/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +7 -7
- package/src/core/geom/2d/convex-hull/orientation3_array.js +7 -7
- package/src/core/geom/2d/intersect_ray_2d.js +7 -7
- package/src/core/geom/2d/line/line2_distance_to_point_sqr.js +7 -7
- package/src/core/geom/2d/line/line2_segment_intersection_fraction_2d.js +44 -44
- package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_2d.js +7 -7
- package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_array_2d.js +7 -7
- package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_2d.js +7 -7
- package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_array_2d.js +7 -7
- package/src/core/geom/2d/line/line_segment_intersection_fraction_2d.js +7 -7
- package/src/core/geom/2d/line/line_segment_line_segment_intersection_exists_2d.js +7 -7
- package/src/core/geom/2d/line/segment2_intersects_segment2_2d.js +25 -25
- package/src/core/geom/2d/line/segment2_segment_compute_intersection_array_2d.js +46 -46
- package/src/core/geom/2d/line/segment2_segment_intersection_fractions.js +52 -52
- package/src/core/geom/2d/oriented-box/min_area_rect_2d.js +69 -69
- package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +433 -433
- package/src/core/geom/2d/polygon/polygon2_clip_axis_halfplane.js +51 -51
- package/src/core/geom/2d/polygon/polygon2_clip_halfplane.js +50 -50
- package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.js +84 -84
- package/src/core/geom/2d/polygon/polygon2_signed_area.js +52 -52
- package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.js +86 -86
- package/src/core/geom/2d/polygon/polygon2_triangulate.js +1280 -1280
- package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.js +77 -77
- package/src/core/geom/2d/quad-tree/qt_collect_by_circle.js +39 -39
- package/src/core/geom/2d/quad-tree/qt_match_data_by_circle.js +101 -101
- package/src/core/geom/2d/quad-tree/qt_query_data_nearest_to_point.js +7 -7
- package/src/core/geom/2d/rectangle_to_aabb.js +7 -7
- package/src/core/geom/2d/spline_bezier2_2d.js +7 -7
- package/src/core/geom/2d/triangle/tri2_rasterize_conservative.js +99 -99
- package/src/core/geom/2d/triangle/tri2_signed_area.js +35 -35
- package/src/core/geom/2d/triangle2d_compute_area.js +7 -7
- package/src/core/geom/2d/triangle2d_contains_point.js +7 -7
- package/src/core/geom/2d/triangle2d_get_barycentric.js +7 -7
- package/src/core/geom/2d/v2_morton_encode.js +23 -23
- package/src/core/geom/3d/aabb/aabb3_array_intersects_frustum_degree.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_box_surface_area_2.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_build_frustum.js +5 -5
- package/src/core/geom/3d/aabb/aabb3_closest_point_on_surface.js +57 -57
- package/src/core/geom/3d/aabb/aabb3_combined_surface_area.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_compute_half_surface_area.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_compute_projected_area.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_compute_surface_area.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_detailed_volume_intersection.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_estimate_projected_area2.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_from_threejs_geometry.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_from_triangle_group.js +46 -46
- package/src/core/geom/3d/aabb/aabb3_intersects_frustum_degree.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_intersects_line_segment.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_near_distance_to_intersection_ray_segment.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_nearest_point_on_surface.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_ray_segment_entry_distance.js +95 -95
- package/src/core/geom/3d/aabb/aabb3_raycast.js +7 -7
- package/src/core/geom/3d/aabb/aabb3_transform_oriented.js +93 -93
- package/src/core/geom/3d/aabb/aabb3_transform_oriented_inverse.js +82 -82
- package/src/core/geom/3d/aabb/compute_aabb_from_points.js +7 -7
- package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.js +7 -7
- package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +486 -486
- package/src/core/geom/3d/atlas/BFF_PLAN.md +174 -174
- package/src/core/geom/3d/atlas/Chart.js +77 -77
- package/src/core/geom/3d/atlas/REVIEW_02.md +392 -392
- package/src/core/geom/3d/atlas/atlas_bench_lib.js +315 -315
- package/src/core/geom/3d/atlas/atlas_chart_type.js +16 -16
- package/src/core/geom/3d/atlas/atlas_compute_charts.js +188 -188
- package/src/core/geom/3d/atlas/atlas_extract_chart.js +107 -107
- package/src/core/geom/3d/atlas/atlas_generate.js +50 -50
- package/src/core/geom/3d/atlas/atlas_test_fixtures.js +266 -266
- package/src/core/geom/3d/atlas/atlas_write_chart_uvs.js +36 -36
- package/src/core/geom/3d/atlas/data/atlas_build_edge_dihedrals.js +62 -62
- package/src/core/geom/3d/atlas/data/atlas_build_edge_lengths.js +33 -33
- package/src/core/geom/3d/atlas/data/atlas_build_face_areas.js +50 -50
- package/src/core/geom/3d/atlas/io/atlas_mesh_weld_colocals.js +39 -39
- package/src/core/geom/3d/atlas/io/bt_loop_uv.js +35 -35
- package/src/core/geom/3d/atlas/pack/ChartPlacement.js +46 -46
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.js +269 -269
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.js +209 -209
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_ortho.js +38 -38
- package/src/core/geom/3d/atlas/param/atlas_chart_stretch_metric.js +86 -86
- package/src/core/geom/3d/atlas/param/atlas_piecewise_resegment.js +183 -183
- package/src/core/geom/3d/atlas/param/fit_plane_basis.js +66 -66
- package/src/core/geom/3d/atlas/segment/RegionGraph.js +40 -40
- package/src/core/geom/3d/atlas/segment/atlas_build_region_graph.js +136 -136
- package/src/core/geom/3d/atlas/segment/atlas_chart_roundness_delta.js +30 -30
- package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.js +77 -77
- package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +116 -116
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts.js +271 -271
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.js +191 -191
- package/src/core/geom/3d/box/box3_projected_half_extent.js +35 -35
- package/src/core/geom/3d/capsule/capsule_intersects_aabb3_closed.js +67 -67
- package/src/core/geom/3d/capsule/capsule_intersects_aabb3_iterative.js +137 -137
- package/src/core/geom/3d/compute_circle_bounding_box.js +7 -7
- package/src/core/geom/3d/cone/computeConeBoundingBox.js +7 -7
- package/src/core/geom/3d/cone/computeConePlaneSide.js +7 -7
- package/src/core/geom/3d/cone/compute_bounding_cone_of_2_cones.js +7 -7
- package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts +38 -0
- package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts.map +1 -0
- package/src/core/geom/3d/cylinder/cylinder3_raycast.js +105 -0
- package/src/core/geom/3d/equirectangular/equirectangular_direction_to_uv.js +18 -18
- package/src/core/geom/3d/equirectangular/equirectangular_uv_to_direction.js +24 -24
- package/src/core/geom/3d/frustum/clipping_volume_matrix4_project.js +7 -7
- package/src/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +7 -7
- package/src/core/geom/3d/frustum/frustum3_compute_closest_point.js +117 -117
- package/src/core/geom/3d/frustum/frustum_matrix4_project.js +7 -7
- package/src/core/geom/3d/frustum/hexahedron_from_aabb.js +7 -7
- package/src/core/geom/3d/frustum/read_frustum_corner.js +17 -17
- package/src/core/geom/3d/frustum/read_three_planes_to_array.js +7 -7
- package/src/core/geom/3d/frustum/slice_frustum_linear_to_points.js +7 -7
- package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +146 -146
- package/src/core/geom/3d/gjk/gjk.js +430 -430
- package/src/core/geom/3d/gjk/gjk_epa_penetration.js +520 -520
- package/src/core/geom/3d/gjk/minkowski_support.js +71 -71
- package/src/core/geom/3d/gjk/mpr.js +368 -368
- package/src/core/geom/3d/line/line3_closest_points_segment_segment.js +7 -7
- package/src/core/geom/3d/line/line3_compute_nearest_point_to_point.js +7 -7
- package/src/core/geom/3d/line/line3_compute_point_segment_point_distance_unfolded.js +64 -64
- package/src/core/geom/3d/line/line3_compute_segment_closest_point_to_aabb3_t.js +153 -153
- package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_aabb3_t.js +7 -7
- package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_point_t.js +7 -7
- package/src/core/geom/3d/line/line3_compute_segment_segment_closest_points.js +88 -88
- package/src/core/geom/3d/line/line3_segment_segment_closest_point_pair.js +71 -71
- package/src/core/geom/3d/line/segment3_point_distance_to_segments.js +25 -25
- package/src/core/geom/3d/mat4/allocate_m4.js +7 -7
- package/src/core/geom/3d/mat4/apply_mat4_transform_to_direction_v3_array.js +7 -7
- package/src/core/geom/3d/mat4/apply_mat4_transform_to_v3_array.js +7 -7
- package/src/core/geom/3d/mat4/compose_matrix4_array.js +7 -7
- package/src/core/geom/3d/mat4/decompose_matrix_4_array.js +7 -7
- package/src/core/geom/3d/mat4/eulerAnglesFromMatrix.js +7 -7
- package/src/core/geom/3d/mat4/m4_compose.js +22 -22
- package/src/core/geom/3d/mat4/m4_compute_normal_matrix3.js +7 -7
- package/src/core/geom/3d/mat4/m4_decompose.js +64 -64
- package/src/core/geom/3d/mat4/m4_decompose_array.js +157 -157
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.js +32 -32
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale_scalar.js +67 -67
- package/src/core/geom/3d/mat4/m4_linear_matrix3.js +29 -29
- package/src/core/geom/3d/mat4/m4_look_at.js +96 -96
- package/src/core/geom/3d/mat4/m4_make_rotation_x.js +47 -47
- package/src/core/geom/3d/mat4/m4_make_rotation_y.js +47 -47
- package/src/core/geom/3d/mat4/m4_make_rotation_z.js +47 -47
- package/src/core/geom/3d/mat4/m4_normal_matrix3.js +39 -39
- package/src/core/geom/3d/mat4/m4_perspective.js +66 -66
- package/src/core/geom/3d/mat4/m4_transpose.js +48 -48
- package/src/core/geom/3d/morton/mortonEncode_LUT.js +7 -7
- package/src/core/geom/3d/morton/mortonEncode_magicbits.js +7 -7
- package/src/core/geom/3d/normal/hemioct/encode_unit3_hemioct.js +5 -5
- package/src/core/geom/3d/normal/hemioct/encode_unit_to_hemioct.js +28 -28
- package/src/core/geom/3d/normal/lambert_azimuth/decode_azimuth_to_unit.js +30 -30
- package/src/core/geom/3d/normal/lambert_azimuth/encode_unit_to_azimuth.js +19 -19
- package/src/core/geom/3d/normal/spherical/decode_spheremap_to_unit.js +38 -38
- package/src/core/geom/3d/normal/spherical/encode_unit_to_spheremap.js +30 -30
- package/src/core/geom/3d/plane/is_point_within_planes.js +7 -7
- package/src/core/geom/3d/plane/orient3d_fast_point.js +47 -47
- package/src/core/geom/3d/plane/plane3_compute_convex_3_plane_intersection.js +7 -7
- package/src/core/geom/3d/plane/plane3_compute_plane_intersection.js +7 -7
- package/src/core/geom/3d/plane/plane3_intersect_plane.js +7 -7
- package/src/core/geom/3d/plane/plane3_three_compute_convex_3_plane_intersection.js +7 -7
- package/src/core/geom/3d/point/point3_raycast.d.ts +33 -0
- package/src/core/geom/3d/point/point3_raycast.d.ts.map +1 -0
- package/src/core/geom/3d/point/point3_raycast.js +47 -0
- package/src/core/geom/3d/polygon/polygon3_compute_normal.js +60 -60
- package/src/core/geom/3d/polygon/polygon3_triangulate.js +94 -94
- package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts +40 -0
- package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts.map +1 -0
- package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.js +94 -0
- package/src/core/geom/3d/quadric/QUADRIC3_SIZE.js +14 -14
- package/src/core/geom/3d/quadric/Quadric3.js +282 -282
- package/src/core/geom/3d/quadric/quadric3_add.js +33 -33
- package/src/core/geom/3d/quadric/quadric3_clear.js +25 -25
- package/src/core/geom/3d/quadric/quadric3_copy.js +27 -27
- package/src/core/geom/3d/quadric/quadric3_distance.js +36 -36
- package/src/core/geom/3d/quadric/quadric3_evaluate.js +25 -25
- package/src/core/geom/3d/quadric/quadric3_optimize.js +45 -45
- package/src/core/geom/3d/quadric/quadric3_scale.js +32 -32
- package/src/core/geom/3d/quadric/quadric3_set_from_plane_through_point.js +30 -30
- package/src/core/geom/3d/quadric/quadric3_set_from_vector4.js +35 -35
- package/src/core/geom/3d/quadric/quadric3_sub.js +36 -36
- package/src/core/geom/3d/quadric/quadric3_to_tensor_m3.js +28 -28
- package/src/core/geom/3d/quadric/quadric3_to_tensor_m3_inverse.js +56 -56
- package/src/core/geom/3d/quadric/quadric3_to_vector3.js +19 -19
- package/src/core/geom/3d/quaternion/quat3_createFromAxisAngle.js +7 -7
- package/src/core/geom/3d/quaternion/quat3_integrate.js +62 -62
- package/src/core/geom/3d/quaternion/quat3_multiply.js +31 -31
- package/src/core/geom/3d/quaternion/quat3_nlerp.js +72 -72
- package/src/core/geom/3d/quaternion/quat3_to_matrix3.js +69 -69
- package/src/core/geom/3d/quaternion/quat_decode_from_uint32.js +7 -7
- package/src/core/geom/3d/quaternion/quat_encode_to_uint32.js +7 -7
- package/src/core/geom/3d/ray/ray3_array_compose.js +7 -7
- package/src/core/geom/3d/ray/ray3_compute_nearest_point_to_point.js +7 -7
- package/src/core/geom/3d/ray/ray3_distance_to_point.js +7 -7
- package/src/core/geom/3d/ray/ray3_shift_origin_along_direction.js +7 -7
- package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts +17 -0
- package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/ConvexHullShape3D.js +43 -0
- package/src/core/geom/3d/shape/CylinderShape3D.d.ts +1 -0
- package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/CylinderShape3D.js +21 -0
- package/src/core/geom/3d/shape/PointShape3D.d.ts +7 -0
- package/src/core/geom/3d/shape/PointShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/PointShape3D.js +88 -63
- package/src/core/geom/3d/shape/PosedShape3D.d.ts +6 -0
- package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/PosedShape3D.js +27 -0
- package/src/core/geom/3d/shape/TransformedShape3D.d.ts +10 -0
- package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/TransformedShape3D.js +13 -0
- package/src/core/geom/3d/shape/Triangle3D.d.ts +1 -0
- package/src/core/geom/3d/shape/Triangle3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/Triangle3D.js +26 -0
- package/src/core/geom/3d/shape/UnionShape3D.d.ts +6 -0
- package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/UnionShape3D.js +7 -0
- package/src/core/geom/3d/shape/UnitCubeShape3D.js +45 -45
- package/src/core/geom/3d/shape/UnitSphereShape3D.js +44 -44
- package/src/core/geom/3d/shape/shape3_mesh_from_geometry.js +64 -64
- package/src/core/geom/3d/shape/shape_mesh_from_geometry.js +7 -7
- package/src/core/geom/3d/shape/util/compute_signed_distance_gradient_by_sampling.js +51 -51
- package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +7 -7
- package/src/core/geom/3d/sphere/compute_bounding_sphere_of_2_spheres.js +7 -7
- package/src/core/geom/3d/sphere/harmonics/sh3_convolve_with_zh.js +53 -53
- package/src/core/geom/3d/sphere/harmonics/sh3_ggx_zh.js +30 -30
- package/src/core/geom/3d/sphere/harmonics/sh3_rotate_bl.js +7 -7
- package/src/core/geom/3d/sphere/harmonics/sh_compute_K.js +7 -7
- package/src/core/geom/3d/sphere/sphere_array_intersects_point.js +7 -7
- package/src/core/geom/3d/sphere/sphere_array_intersects_ray.js +7 -7
- package/src/core/geom/3d/sphere/sphere_intersects_point.js +7 -7
- package/src/core/geom/3d/sphere/sphere_matrix4_transform.js +5 -5
- package/src/core/geom/3d/sphere/sphere_projected_sphere_radius_sqr.js +7 -7
- package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.js +7 -7
- package/src/core/geom/3d/sphere/spherical_from_cartesian.js +7 -7
- package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.js +174 -174
- package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.js +7 -7
- package/src/core/geom/3d/tetrahedra/compute_tetrahedron_volume.js +7 -7
- package/src/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.js +7 -7
- package/src/core/geom/3d/tetrahedra/graphics/build_tetrahedral_mesh_geometry.js +39 -39
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.js +48 -48
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +173 -173
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_compute_tet_quality.js +22 -22
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.js +146 -146
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.js +232 -232
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.js +255 -255
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +387 -387
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +140 -140
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_tet_get_neighbours.js +7 -7
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +97 -97
- package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.js +66 -66
- package/src/core/geom/3d/tetrahedra/triangle/triangle_decode_depth.js +59 -59
- package/src/core/geom/3d/tetrahedra/triangle/triangle_rasterized_depth_sample_index.js +54 -54
- package/src/core/geom/3d/tetrahedra/validate_neighbour.js +70 -70
- package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.js +314 -314
- package/src/core/geom/3d/topology/struct/binary/BinaryDataLayer.js +364 -364
- package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +567 -567
- package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +1085 -1085
- package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +73 -73
- package/src/core/geom/3d/topology/struct/binary/io/bt_loop_kill.js +35 -35
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_append.js +119 -119
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +84 -84
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.js +172 -172
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_face_normals.js +56 -56
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadratics.js +7 -7
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.js +227 -227
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.js +161 -161
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_island_erode.js +490 -490
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +120 -120
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_from_indexed_geometry.js +120 -120
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_collapse.js +52 -52
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +115 -115
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_flip.js +142 -142
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.js +21 -21
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.js +92 -92
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_split.js +179 -179
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_swap_vertex_slots.js +28 -28
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_kill_only_edge.js +8 -8
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_fuse_duplicate_edges.js +83 -83
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.js +89 -89
- package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_kill.js +25 -25
- package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_poke.js +127 -127
- package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.js +268 -268
- package/src/core/geom/3d/topology/struct/binary/io/face/bt_kill_only_face.js +8 -8
- package/src/core/geom/3d/topology/struct/binary/io/face/bt_mesh_kill_degenerate_faces.js +72 -72
- package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_kill_only_vert.js +7 -7
- package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_merge_verts_by_distance.js +7 -7
- package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_relative_merge_distance.js +48 -48
- package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_split_pinched_vertices.js +256 -256
- package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_vertex_merge_distance.js +77 -77
- package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_fuse_duplicate_edges.js +7 -7
- package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_kill.js +7 -7
- package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_fuse_duplicate_edges.js +148 -148
- package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_kill_only.js +7 -7
- package/src/core/geom/3d/topology/struct/binary/query/bt_collect_boundary_segments.js +29 -29
- package/src/core/geom/3d/topology/struct/binary/query/bt_edge_collapse_breaks_link_condition.js +107 -107
- package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_is_legal.js +41 -41
- package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_would_fold.js +120 -120
- package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.js +42 -42
- package/src/core/geom/3d/topology/struct/binary/query/bt_edge_is_boundary.js +20 -20
- package/src/core/geom/3d/topology/struct/binary/query/bt_edge_read_diamond.js +96 -96
- package/src/core/geom/3d/topology/struct/binary/query/bt_face_compute_newell_normal.js +72 -72
- package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_attached_faces.js +7 -7
- package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces.js +39 -39
- package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces_weighted.js +93 -93
- package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_neighbour_faces.js +7 -7
- package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_shared_loop.js +48 -48
- package/src/core/geom/3d/topology/struct/binary/query/bt_face_island_flood_fill.js +45 -45
- package/src/core/geom/3d/topology/struct/binary/query/bt_face_read_triangle.js +66 -66
- package/src/core/geom/3d/topology/struct/binary/query/bt_faces_shared_loop.js +7 -7
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.js +44 -44
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_build_boundary_euclidean_distance_field.js +32 -32
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_compute_face_islands.js +53 -53
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path.js +703 -703
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +181 -181
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_segment_penetrates_surface.js +133 -133
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_surface_ray_parity.js +82 -82
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.js +599 -599
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.js +108 -108
- package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.js +7 -7
- package/src/core/geom/3d/triangle/computeTriangleClosestPointToPointBarycentric.js +7 -7
- package/src/core/geom/3d/triangle/computeTriangleRayIntersection.js +7 -7
- package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentric.js +7 -7
- package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricEdge.js +7 -7
- package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricGeometry.js +7 -7
- package/src/core/geom/3d/triangle/compute_triangle_area_3d.js +7 -7
- package/src/core/geom/3d/triangle/compute_triangle_normal.js +7 -7
- package/src/core/geom/3d/triangle/rayTriangleIntersection.js +7 -7
- package/src/core/geom/3d/triangle/tri3_closest_point.js +65 -65
- package/src/core/geom/3d/triangle/tri3_closest_point_barycentric.js +171 -171
- package/src/core/geom/3d/triangle/tri3_flatten_isometric.js +79 -79
- package/src/core/geom/3d/triangle/tri3_ray_intersection.js +160 -160
- package/src/core/geom/3d/triangle/tri3_ray_intersection_barycentric.js +96 -96
- package/src/core/geom/3d/triangle/tri3_raycast.d.ts +42 -0
- package/src/core/geom/3d/triangle/tri3_raycast.d.ts.map +1 -0
- package/src/core/geom/3d/triangle/tri3_raycast.js +94 -0
- package/src/core/geom/3d/triangle/triangle3_incenter.js +7 -7
- package/src/core/geom/3d/triangle/triangle_compute_plane_side.js +7 -7
- package/src/core/geom/3d/triangle/triangle_compute_signed_volume.js +7 -7
- package/src/core/geom/3d/triangle/triangle_intersects_clipping_volume.js +7 -7
- package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.js +7 -7
- package/src/core/geom/3d/triangle/v3_compute_triangle_normal.js +7 -7
- package/src/core/geom/3d/util/make_justified_point_grid.js +7 -7
- package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +381 -381
- package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +684 -684
- package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +554 -554
- package/src/core/geom/mat3/m3_cm_from_translation.js +7 -7
- package/src/core/geom/mat3/m3_cm_invert.js +7 -7
- package/src/core/geom/mat3/m3_make_rotation.js +5 -5
- package/src/core/geom/mat3/m3_make_rotation_TBN.js +31 -31
- package/src/core/geom/mat3/m3_multiply_vec3.js +7 -7
- package/src/core/geom/packing/computeBoundingSphereOfSpheres.js +7 -7
- package/src/core/geom/packing/max-rect/cost/costByBestShortSide.js +7 -7
- package/src/core/geom/packing/max-rect/cost/costByRemainingArea.js +7 -7
- package/src/core/geom/packing/max-rect/cutArea.js +7 -7
- package/src/core/geom/packing/max-rect/findBestContainer.js +7 -7
- package/src/core/geom/packing/max-rect/packMaxRectangles.js +7 -7
- package/src/core/geom/packing/max-rect/packOneBox.js +7 -7
- package/src/core/geom/packing/max-rect/removeRedundantBoxes.js +7 -7
- package/src/core/geom/packing/max-rect/removeRedundantBoxesArray.js +7 -7
- package/src/core/geom/random/randomPointInBox.js +7 -7
- package/src/core/geom/random/randomPointInCircle.js +7 -7
- package/src/core/geom/random/randomPointInPoint.js +7 -7
- package/src/core/geom/random/randomPointInSphere.js +7 -7
- package/src/core/geom/random/randomPointOnBox.js +7 -7
- package/src/core/geom/random/randomPointOnSphere.js +7 -7
- package/src/core/geom/random/random_orthonormal_basis.js +31 -31
- package/src/core/geom/vec/vector_axpy.js +15 -15
- package/src/core/geom/vec/vector_axpy_offset.js +20 -20
- package/src/core/geom/vec/vector_copy.js +7 -7
- package/src/core/geom/vec/vector_dot_offset.js +25 -25
- package/src/core/geom/vec/vector_scale_array.js +7 -7
- package/src/core/geom/vec2/v2_rotate.js +21 -21
- package/src/core/geom/vec2/v2_rotate_cos_sin.js +21 -21
- package/src/core/geom/vec3/v3_angle_atan2_between.js +7 -7
- package/src/core/geom/vec3/v3_angle_between.js +7 -7
- package/src/core/geom/vec3/v3_angle_cos_between.js +7 -7
- package/src/core/geom/vec3/v3_array_add_in_place.js +7 -7
- package/src/core/geom/vec3/v3_array_centroid.js +7 -7
- package/src/core/geom/vec3/v3_array_copy.js +7 -7
- package/src/core/geom/vec3/v3_array_displace_in_direction.js +7 -7
- package/src/core/geom/vec3/v3_array_equals.js +7 -7
- package/src/core/geom/vec3/v3_array_immediate_add.js +7 -7
- package/src/core/geom/vec3/v3_array_matrix4_rotate.js +7 -7
- package/src/core/geom/vec3/v3_array_normalize.js +7 -7
- package/src/core/geom/vec3/v3_array_scale.js +7 -7
- package/src/core/geom/vec3/v3_compute_interior_angle.js +7 -7
- package/src/core/geom/vec3/v3_cotangent.js +33 -33
- package/src/core/geom/vec3/v3_dot_array_array.js +7 -7
- package/src/core/geom/vec3/v3_matrix3_multiply.js +30 -30
- package/src/core/geom/vec3/v3_matrix3_rotate.js +49 -49
- package/src/core/geom/vec3/v3_matrix4_rotate.js +7 -7
- package/src/core/geom/vec3/v3_multiply.js +23 -23
- package/src/core/geom/vec3/v3_multiply_scalar.js +7 -7
- package/src/core/geom/vec3/v3_orthonormal_matrix_from_normal.js +49 -49
- package/src/core/geom/vec3/v3_quat3_apply.js +7 -7
- package/src/core/geom/vec3/v3_quat3_apply_inverse.js +7 -7
- package/src/core/geom/vec3/v3_quaternion_apply.js +39 -39
- package/src/core/geom/vec3/v3_quaternion_apply_inverse.js +41 -41
- package/src/core/geom/vec3/v3_reflect.js +24 -24
- package/src/core/geom/vec3/v3_scale_array.js +18 -18
- package/src/core/geom/vec3/v3_triple_cross.js +45 -45
- package/src/core/geom/vec3/v3_triple_cross_product.js +7 -7
- package/src/core/geom/vec3/v3_uniform_sample_cone.js +21 -21
- package/src/core/geom/vec4/v4_multiply_mat4.js +7 -7
- package/src/core/graph/csr/csr_graph_build_distance_field.js +112 -112
- package/src/core/graph/csr/csr_graph_find_edge.js +25 -25
- package/src/core/graph/csr/csr_graph_find_shortest_path.js +105 -105
- package/src/core/graph/csr/csr_graph_from_undirected_edge_list.js +94 -94
- package/src/core/graph/graph_k_means_cluster.js +250 -250
- package/src/core/graph/layout/CircleLayout.js +1 -1
- package/src/core/graph/layout/box/BoxLayouter.js +1 -1
- package/src/core/graph/layout/graph_peel_topological_layer.js +45 -45
- package/src/core/graph/metis/BinaryTopologyFaceGraph.js +49 -49
- package/src/core/graph/metis/bt_mesh_build_face_graph.js +111 -111
- package/src/core/graph/metis/cluster_mesh_metis.js +137 -137
- package/src/core/graph/metis/native/bisection/bisect_graph.js +100 -100
- package/src/core/graph/metis/native/bisection/compute_2way_params.js +86 -86
- package/src/core/graph/metis/native/bisection/fm_2way.js +297 -297
- package/src/core/graph/metis/native/bisection/grow_bisection.js +137 -137
- package/src/core/graph/metis/native/bisection/split_graph_two_way.js +119 -119
- package/src/core/graph/metis/native/coarsen/coarsen_graph.js +94 -94
- package/src/core/graph/metis/native/coarsen/create_coarse_graph.js +158 -158
- package/src/core/graph/metis/native/coarsen/match_shem.js +175 -175
- package/src/core/graph/metis/native/initial/initial_kway_bfs.js +122 -122
- package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.js +170 -170
- package/src/core/graph/metis/native/metis_partition_kway.js +126 -126
- package/src/core/graph/metis/native/refine/RefinementScratch.js +53 -53
- package/src/core/graph/metis/native/refine/fm_kway.js +487 -487
- package/src/core/graph/metis/native/refine/project_kway.js +43 -43
- package/src/core/graph/metis/native/refine/refine_kway.js +43 -43
- package/src/core/lang/reactive/pegjs/parser.js +3458 -3458
- package/src/core/math/complex/complex_horner_eval.js +31 -31
- package/src/core/math/computeWholeDivisorLow.js +33 -33
- package/src/core/math/f32_next_down.js +24 -24
- package/src/core/math/f32_next_up.js +27 -27
- package/src/core/math/hash/hash_mix2.js +22 -22
- package/src/core/math/hash/hash_mix3.js +19 -19
- package/src/core/math/linalg/cg/cg_solve.js +106 -106
- package/src/core/math/linalg/cg/cg_solve_normal_equations.js +59 -59
- package/src/core/math/linalg/cubic_residual_times_derivative_accumulate.js +43 -43
- package/src/core/math/linalg/eigen/matrix_householder_in_place.js +122 -122
- package/src/core/math/linalg/eigen/matrix_qr_in_place.js +190 -190
- package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js +117 -117
- package/src/core/math/linalg/givens/givens_apply_rows.js +28 -28
- package/src/core/math/linalg/givens/givens_apply_rows_offset.js +30 -30
- package/src/core/math/linalg/givens/givens_rotation_coefficients.js +39 -39
- package/src/core/math/linalg/lu_factor_linear_system.js +108 -108
- package/src/core/math/linalg/lu_solve_linear_system.js +53 -53
- package/src/core/math/linalg/polynomial_add_into.js +29 -29
- package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.js +159 -159
- package/src/core/math/linalg/polynomial_cubic_derivative_eval.js +16 -16
- package/src/core/math/linalg/polynomial_cubic_horner_eval.js +19 -19
- package/src/core/math/linalg/polynomial_cubic_second_derivative_eval.js +14 -14
- package/src/core/math/linalg/polynomial_multiply.js +41 -41
- package/src/core/math/linalg/polynomial_real_roots_in_interval.js +211 -211
- package/src/core/math/linalg/polynomial_root_bound_cauchy.js +30 -30
- package/src/core/math/linalg/polynomial_scale_into.js +17 -17
- package/src/core/math/linalg/polynomial_sub_into.js +29 -29
- package/src/core/math/linalg/solve_linear_system_GEPP_2x2.js +96 -96
- package/src/core/math/linalg/sor_optimal_omega.js +42 -42
- package/src/core/math/linalg/sparse/SparseMatrixCSR.js +88 -88
- package/src/core/math/linalg/sparse/spm_matvec.js +22 -22
- package/src/core/math/linalg/sparse/spm_matvec_transpose.js +29 -29
- package/src/core/math/lookup/LUT_HEATMAP.js +30 -30
- package/src/core/math/lookup/ParameterLookupTable.js +495 -495
- package/src/core/math/lookup/ParameterLookupTableFlags.js +6 -6
- package/src/core/math/noise/curl_noise_3d.js +18 -18
- package/src/core/math/physics/brdf/cone_cosine_from_roughness.js +28 -28
- package/src/core/math/physics/brdf/reflection_sample_weight.js +48 -48
- package/src/core/math/physics/kinematics/computeInterceptPoint.js +79 -79
- package/src/core/math/random/randomSeed.js +16 -16
- package/src/core/math/random/random_pick_weighted_index.js +26 -26
- package/src/core/math/round_half_away_from_zero.js +13 -13
- package/src/core/math/spline/spline3_hermite_apply_transform.js +107 -107
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.js +125 -125
- package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.js +50 -50
- package/src/core/math/spline/spline3_hermite_reverse.js +49 -49
- package/src/core/math/spline/spline3_hermite_to_monomial.js +37 -37
- package/src/core/math/statistics/hammersley_sequence.js +53 -53
- package/src/core/model/reactive/model/util/createRandomReactiveExpression.js +185 -185
- package/src/core/path/convertPathToURL.js +107 -107
- package/src/core/process/delay.js +16 -16
- package/src/core/science/units/MEASUREMENT_UNITS_SCIENTIFIC.js +87 -87
- package/src/core/science/units/MEASUREMENT_UNITS_SI.js +17 -17
- package/src/core/science/units/NamedUnit.js +48 -48
- package/src/core/science/units/UNIT_DIMENSION_MAPPING.js +29 -29
- package/src/core/science/units/UnitDimension.js +28 -28
- package/src/core/science/units/format_quantity.js +74 -74
- package/src/core/science/units/magnitude_prefix.js +127 -127
- package/src/core/science/units/si/AMPERE.js +13 -13
- package/src/core/science/units/si/CANDELA.js +13 -13
- package/src/core/science/units/si/DIMENSIONLESS.js +14 -14
- package/src/core/science/units/si/KELVIN.js +13 -13
- package/src/core/science/units/si/KILOGRAM.js +13 -13
- package/src/core/science/units/si/METER.js +13 -13
- package/src/core/science/units/si/MOLE.js +13 -13
- package/src/core/science/units/si/SECOND.js +13 -13
- package/src/core/science/units/si/derived/BECQUEREL.js +16 -16
- package/src/core/science/units/si/derived/COULOMB.js +13 -13
- package/src/core/science/units/si/derived/FARAD.js +13 -13
- package/src/core/science/units/si/derived/GRAY.js +16 -16
- package/src/core/science/units/si/derived/HENRY.js +13 -13
- package/src/core/science/units/si/derived/HERTZ.js +16 -16
- package/src/core/science/units/si/derived/JOULE.js +13 -13
- package/src/core/science/units/si/derived/KATAL.js +13 -13
- package/src/core/science/units/si/derived/LUMEN.js +14 -14
- package/src/core/science/units/si/derived/LUX.js +13 -13
- package/src/core/science/units/si/derived/NEWTON.js +13 -13
- package/src/core/science/units/si/derived/OHM.js +13 -13
- package/src/core/science/units/si/derived/PASCAL.js +13 -13
- package/src/core/science/units/si/derived/SIEMENS.js +13 -13
- package/src/core/science/units/si/derived/SIEVERT.js +16 -16
- package/src/core/science/units/si/derived/TESLA.js +13 -13
- package/src/core/science/units/si/derived/VOLT.js +13 -13
- package/src/core/science/units/si/derived/WATT.js +13 -13
- package/src/core/science/units/si/derived/WEBER.js +13 -13
- package/src/core/science/units/unit_matrix_to_string.js +403 -403
- package/src/engine/Engine.js +726 -726
- package/src/engine/EngineHarness.js +590 -590
- package/src/engine/REVIEW_2026_07_03.md +211 -211
- package/src/engine/animation/AnimatedActions.js +81 -81
- package/src/engine/animation/AnimationUtils.js +252 -252
- package/src/engine/animation/async/TimeSeries.js +300 -300
- package/src/engine/animation/curve/animation_curve_binary_codec.js +60 -60
- package/src/engine/animation/curve/draw/canvas_point_to_curve.js +22 -22
- package/src/engine/animation/curve/draw/curve_point_to_canvas.js +38 -38
- package/src/engine/animation/curve/draw/position_canvas_to_curve.js +22 -22
- package/src/engine/animation/curve/draw/position_curve_to_canvas.js +22 -22
- package/src/engine/asset/GameAssetType.d.ts +0 -1
- package/src/engine/asset/GameAssetType.js +0 -1
- package/src/engine/asset/load_model_scene_bundle.js +27 -27
- package/src/engine/asset/loaders/font/FontAsset.js +21 -21
- package/src/engine/asset/loaders/font/FontAssetLoader.js +20 -20
- package/src/engine/asset/loaders/gltf_test_fixtures.js +358 -358
- package/src/engine/asset/loaders/image/ImageBitmapAssetLoader.js +52 -52
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +94 -94
- package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterAverage.js +59 -59
- package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterNone.js +55 -55
- package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterPaeth.js +74 -74
- package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterSub.js +34 -34
- package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterUp.js +46 -46
- package/src/engine/control/first-person/DESIGN.md +640 -640
- package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +563 -563
- package/src/engine/control/first-person/FirstPersonMotionPhase.js +134 -134
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2045 -2045
- package/src/engine/control/first-person/mastery/DecisionPoint.js +30 -30
- package/src/engine/control/first-person/math/Spring.js +71 -71
- package/src/engine/control/first-person/math/computeJumpFromApex.js +23 -23
- package/src/engine/control/first-person/math/computeLRCBreathRate.js +41 -41
- package/src/engine/control/first-person/math/computeMassRatios.js +44 -44
- package/src/engine/control/first-person/math/criticallyDampedSpring.js +34 -34
- package/src/engine/control/first-person/math/dampedSpringStep.js +72 -72
- package/src/engine/control/first-person/math/jumpDynamics.js +108 -108
- package/src/engine/control/first-person/math/stepTowards.js +20 -20
- package/src/engine/control/first-person/pose/FirstPersonPose.js +137 -137
- package/src/engine/control/first-person/pose/FirstPersonPosture.js +27 -27
- package/src/engine/control/first-person/test/buildTestPlayer.js +36 -36
- package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +531 -531
- package/src/engine/ecs/EntityManager.d.ts +7 -3
- package/src/engine/ecs/EntityManager.d.ts.map +1 -1
- package/src/engine/ecs/EntityManager.js +10 -5
- package/src/engine/ecs/HIERARCHY_REVIEW.md +717 -717
- package/src/engine/ecs/async/SystemWorkerHost.js +329 -329
- package/src/engine/ecs/async/SystemWorkerLoopback.js +143 -143
- package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +246 -246
- package/src/engine/ecs/async/WorkerSystem.js +702 -702
- package/src/engine/ecs/async/WorkerSystemProtocol.js +150 -150
- package/src/engine/ecs/fow/FogOfWar.js +707 -707
- package/src/engine/ecs/fow/FogOfWarEdgeMode.js +40 -40
- package/src/engine/ecs/fow/fog_of_war_mask_world_bounds.js +24 -24
- package/src/engine/ecs/fow/fog_of_war_uv_transform.js +30 -30
- package/src/engine/ecs/gui/hud/testHudEdgeStick.js +132 -134
- package/src/engine/ecs/hierarchy/EntityChildIndex.js +140 -140
- package/src/engine/ecs/ik/IKProblem.js +42 -42
- package/src/engine/ecs/ik/InverseKinematicsSystem.js +193 -193
- package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +134 -134
- package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +97 -97
- package/src/engine/ecs/ik/ik_bone_chain.js +85 -85
- package/src/engine/ecs/ik/ik_probe_terrain_contact.js +119 -119
- package/src/engine/ecs/parent/EntityNode.d.ts +1 -1
- package/src/engine/ecs/parent/EntityNode.js +2 -2
- package/src/engine/ecs/parent/ParentEntitySystem.js +255 -255
- package/src/engine/ecs/speaker/VoiceSystem.d.ts +2 -2
- package/src/engine/ecs/speaker/VoiceSystem.d.ts.map +1 -1
- package/src/engine/ecs/speaker/VoiceSystem.js +13 -7
- package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +269 -269
- package/src/engine/ecs/storage/binary/object-v2/BinaryObjectDeSerializer.js +315 -315
- package/src/engine/ecs/storage/binary/object-v2/BinaryObjectSerializer.js +331 -331
- package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +199 -199
- package/src/engine/ecs/storage/binary/object-v2/ObjectBinaryFormat.js +57 -57
- package/src/engine/ecs/storage/binary/object-v2/ObjectSerializationAdapter.js +56 -56
- package/src/engine/ecs/storage/binary/object-v2/README.md +110 -110
- package/src/engine/ecs/storage/binary/object-v2/objectStringCodec.js +48 -48
- package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.js +44 -44
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +265 -265
- package/src/engine/ecs/terrain/TerrainClouds.js +97 -97
- package/src/engine/ecs/terrain/ecs/StubTerrainBuildWorker.js +65 -65
- package/src/engine/ecs/terrain/ecs/Terrain.d.ts +4 -0
- package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
- package/src/engine/ecs/terrain/ecs/Terrain.js +790 -790
- package/src/engine/ecs/terrain/ecs/TerrainSystem.js +209 -209
- package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +316 -316
- package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.js +416 -416
- package/src/engine/ecs/terrain/ecs/splat/SplatMapping.js +525 -525
- package/src/engine/ecs/terrain/overlay/TerrainOverlay.js +302 -302
- package/src/engine/ecs/terrain/tiles/TerrainTile.js +561 -561
- package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +896 -896
- package/src/engine/ecs/terrain/tiles/tile_geometry_to_meshlets.js +36 -36
- package/src/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +129 -129
- package/src/engine/ecs/transform/Transform64.js +814 -814
- package/src/engine/ecs/transform/t64_copy_from_transform.js +35 -35
- package/src/engine/ecs/transform/t64_equals_transform.js +55 -55
- package/src/engine/ecs/transform/t64_look_rotation.js +36 -36
- package/src/engine/ecs/transform/t64_transform_direction.js +25 -25
- package/src/engine/ecs/transform/transform_copy_from_t64.js +28 -28
- package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +345 -345
- package/src/engine/ecs/transform-attachment/transform_attachment_find_descendant_by_name.js +65 -65
- package/src/engine/ecs/transform-attachment/transform_attachment_parent_of.js +24 -24
- package/src/engine/ecs/util/hideEntityGracefully.js +208 -208
- package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +446 -446
- package/src/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js +14 -14
- package/src/engine/graphics/FrameThrottle.js +2 -2
- package/src/engine/graphics/ecs/animation/animator/graph/AnimationState.js +207 -207
- package/src/engine/graphics/ecs/animation/animator/graph/AnimationTransition.js +151 -151
- package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.js +22 -22
- package/src/engine/graphics/ecs/camera/Camera.js +165 -165
- package/src/engine/graphics/ecs/camera/camera_active_frustum.js +25 -25
- package/src/engine/graphics/ecs/camera/camera_find_active.js +28 -28
- package/src/engine/graphics/ecs/camera/camera_traverse_active.js +18 -18
- package/src/engine/graphics/ecs/camera/pp/PerfectPanner.js +170 -170
- package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.js +68 -68
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +296 -296
- package/src/engine/graphics/ecs/decal/v2/Decal.js +220 -220
- package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.js +56 -56
- package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_0_1.js +38 -38
- package/src/engine/graphics/ecs/light/shadow/compute_view_frustum_aabb_in_space.js +62 -62
- package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.js +77 -77
- package/src/engine/graphics/ecs/make_bvh_depth_range_computer.js +33 -33
- package/src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.js +88 -88
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +428 -428
- package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +303 -303
- package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.d.ts +1 -1
- package/src/engine/graphics/ecs/mesh-v2/aggregate/serialization/SGMeshSerializationAdapter.js +39 -39
- package/src/engine/graphics/ecs/mesh-v2/sg_hierarchy_compute_bounding_box_via_parent_entity.js +36 -36
- package/src/engine/graphics/ecs/path/tube/build/GeometryStream.js +94 -94
- package/src/engine/graphics/ecs/path/tube/build/build_stream_catmullrom.js +310 -310
- package/src/engine/graphics/ecs/path/tube/build/build_stream_linear.js +73 -73
- package/src/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +199 -199
- package/src/engine/graphics/ecs/path/tube/build/makeTubeStream.js +217 -217
- package/src/engine/graphics/ecs/path/tube/build/make_cap.js +340 -340
- package/src/engine/graphics/ecs/path/tube/build/make_ring_faces.js +40 -40
- package/src/engine/graphics/ecs/path/tube/build/make_ring_vertices.js +153 -153
- package/src/engine/graphics/ecs/render_layers_compute_depth_range.js +64 -64
- package/src/engine/graphics/ecs/trail3d/Trail3D.js +483 -483
- package/src/engine/graphics/ecs/trail3d/Trail3DFlags.js +26 -26
- package/src/engine/graphics/ecs/trail3d/advance_trail.js +42 -42
- package/src/engine/graphics/ecs/trail3d/make_gradient_stroke.js +58 -58
- package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.js +90 -90
- package/src/engine/graphics/ecs/trail3d/seed_trail_tube.js +75 -75
- package/src/engine/graphics/ecs/trail3d/trail_head_position.js +19 -19
- package/src/engine/graphics/ecs/water/Water.js +104 -104
- package/src/engine/graphics/geometry/AttributeData.js +84 -84
- package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_indexed.js +49 -49
- package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +288 -288
- package/src/engine/graphics/geometry/buffered/query/nearest_point_on_triangle_record.js +87 -87
- package/src/engine/graphics/geometry/buffered/read_triangle_vertices.js +102 -102
- package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_buffered_geometry.js +52 -52
- package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_indexed_geometry.js +20 -20
- package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_unindexed_geometry.js +19 -19
- package/src/engine/graphics/geometry/optimization/geometry_optimize_uv_tension.js +135 -135
- package/src/engine/graphics/impostors/voxel/README.md +149 -149
- package/src/engine/graphics/impostors/voxel/VoxelImpostorDescription.js +141 -141
- package/src/engine/graphics/particles/node-based/codegen/glsl/getTypeByteSize.js +20 -20
- package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts +1 -2
- package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts +2 -0
- package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/nodes/particle_data_type_component_count.js +45 -45
- package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +229 -229
- package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts +2 -10
- package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts.map +1 -1
- package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +1149 -1149
- package/src/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +472 -472
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +2 -2
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.js +2 -2
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.d.ts.map +1 -1
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.js +3 -5
- package/src/engine/graphics/particles/particular/engine/shader/ShaderManager.js +135 -135
- package/src/engine/graphics/particles/particular/engine/utils/distribute_points_on_indexed_triangles.js +168 -168
- package/src/engine/graphics/render/forward_plus/plugin/forwardPlusMaterialMarker.js +18 -18
- package/src/engine/graphics/render/forward_plus/read_frustum_corner.js +2 -2
- package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +219 -219
- package/src/engine/graphics/render/frame_graph/FrameGraph.js +900 -900
- package/src/engine/graphics/render/frame_graph/FrameGraphScope.js +72 -72
- package/src/engine/graphics/render/frame_graph/FrameGraphState.js +39 -39
- package/src/engine/graphics/render/frame_graph/ResourceEntry.js +96 -96
- package/src/engine/graphics/render/gizmo/GizmoShapeBuffer.js +105 -105
- package/src/engine/graphics/render/gizmo/GizmoShapeRenderingInterface.js +162 -162
- package/src/engine/graphics/render/layers/RenderLayer.js +95 -95
- package/src/engine/graphics/sh3/build_injected_shader.js +56 -56
- package/src/engine/graphics/sh3/grid_dilate_average.js +175 -175
- package/src/engine/graphics/sh3/path_tracer/BufferedGeometryBVH.js +506 -506
- package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.js +161 -161
- package/src/engine/graphics/sh3/path_tracer/PathTracedRenderer.js +205 -205
- package/src/engine/graphics/sh3/path_tracer/PathTracedScene.js +698 -698
- package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +490 -490
- package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.js +2 -2
- package/src/engine/graphics/sh3/path_tracer/make_sky_hosek.js +45 -45
- package/src/engine/graphics/sh3/path_tracer/populate_path_traced_scene_from_ecd.js +73 -73
- package/src/engine/graphics/sh3/path_tracer/ray_hit_apply_transform.js +32 -32
- package/src/engine/graphics/sh3/path_tracer/texture/apply_texture_clamping_to_coordinate.js +28 -28
- package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +142 -142
- package/src/engine/graphics/sh3/sky/hosek/render_hosek_sky_to_equirectangular.js +70 -70
- package/src/engine/graphics/sh3/sky/hosek/sky_hosek_compute_irradiance_by_direction.js +388 -388
- package/src/engine/graphics/shaders/chunks/glsl_octahedral_impostor.js +277 -277
- package/src/engine/graphics/shaders/chunks/glsl_voxel_impostor_splat.js +57 -57
- package/src/engine/graphics/shadows/vsm.glsl.js +43 -43
- package/src/engine/graphics/texture/3d/scs3d_sample_linear3.js +81 -81
- package/src/engine/graphics/texture/EnvironmentTextureProjection.js +15 -15
- package/src/engine/graphics/texture/channel_count_to_format_prefix.js +26 -26
- package/src/engine/graphics/texture/isImageBitmap.js +2 -2
- package/src/engine/graphics/texture/reflection/convolve_equirectangular_reflection.js +189 -189
- package/src/engine/graphics/texture/reflection/equirectangular_reflection_roughness.js +51 -51
- package/src/engine/graphics/texture/sampler/HarmonicDiffusionGrid.js +145 -145
- package/src/engine/graphics/texture/sampler/Sampler2DArray.js +172 -172
- package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +466 -466
- package/src/engine/graphics/texture/sampler/compare/flip/FlipParameters.js +18 -18
- package/src/engine/graphics/texture/sampler/compare/flip/FlipPooling.js +33 -33
- package/src/engine/graphics/texture/sampler/compare/flip/flip_build_feature_kernel.js +147 -147
- package/src/engine/graphics/texture/sampler/compare/flip/flip_build_spatial_kernel.js +177 -177
- package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_color_difference.js +104 -104
- package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_feature_difference.js +76 -76
- package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_pixels_per_degree.js +34 -34
- package/src/engine/graphics/texture/sampler/compare/flip/flip_constants.js +77 -77
- package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_feature.js +48 -48
- package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_spatial.js +86 -86
- package/src/engine/graphics/texture/sampler/compare/flip/flip_pool.js +71 -71
- package/src/engine/graphics/texture/sampler/compare/flip/flip_srgb_to_ycxcz.js +55 -55
- package/src/engine/graphics/texture/sampler/compare/flip/sampler2d_flip_ldr.js +80 -80
- package/src/engine/graphics/texture/sampler/filter/SeparableKernel.js +82 -82
- package/src/engine/graphics/texture/sampler/filter/sampler2d_convolve_separable.js +122 -122
- package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.js +148 -148
- package/src/engine/graphics/texture/sampler/sampler2d_channel_apply_lut.js +82 -82
- package/src/engine/graphics/texture/sampler/sampler2d_combine.js +67 -67
- package/src/engine/graphics/texture/sampler/sampler2d_linear_f16_to_srgb_u8.js +54 -54
- package/src/engine/graphics/texture/sampler/sampler2d_sample_equirectangular_direction.js +63 -63
- package/src/engine/graphics/texture/sampler/sampler2d_srgb_to_linear.js +33 -33
- package/src/engine/graphics/texture/sampler/sampler2d_srgb_u8_to_linear_f16.js +68 -68
- package/src/engine/graphics/texture/shade_image_preview.js +103 -103
- package/src/engine/graphics/trail/TrailSpawnMode.js +20 -20
- package/src/engine/graphics/trail/tube/TubeX.js +573 -573
- package/src/engine/graphics/trail/tube/TubeXMaterialSpec.js +58 -58
- package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.js +34 -34
- package/src/engine/graphics/trail/tube/tube_attributes_spec.js +69 -69
- package/src/engine/graphics/trail/tube/tube_frame.js +83 -83
- package/src/engine/graphics3/AnimationGraphSystem3.js +329 -329
- package/src/engine/graphics3/AnimationSystem3.js +352 -352
- package/src/engine/graphics3/CameraSystem3.js +170 -170
- package/src/engine/graphics3/DecalSystem3.js +441 -441
- package/src/engine/graphics3/FogOfWarSystem3.js +265 -265
- package/src/engine/graphics3/GraphicsEngine3.js +776 -776
- package/src/engine/graphics3/HighlightSystem3.js +241 -241
- package/src/engine/graphics3/LightSystem3.js +211 -211
- package/src/engine/graphics3/MeshSystem3.js +646 -646
- package/src/engine/graphics3/ParticleEmitterSystem3.js +289 -289
- package/src/engine/graphics3/PathDisplaySystem3.js +309 -309
- package/src/engine/graphics3/PickingQuery.js +48 -48
- package/src/engine/graphics3/PickingResult.js +47 -47
- package/src/engine/graphics3/PickingSystem3.js +273 -273
- package/src/engine/graphics3/ShadeCameraAdapter.js +55 -55
- package/src/engine/graphics3/ShadedGeometrySystem3.js +169 -169
- package/src/engine/graphics3/TerrainSystem3.js +566 -566
- package/src/engine/graphics3/TooltipComponentSystem3.js +328 -328
- package/src/engine/graphics3/Trail3DSystem3.js +221 -221
- package/src/engine/graphics3/WaterSystem3.js +293 -293
- package/src/engine/graphics3/animation/ClipPlayback.js +84 -84
- package/src/engine/graphics3/animation/wrap_clip_time.js +23 -23
- package/src/engine/graphics3/animation/write_graph_playback.js +48 -48
- package/src/engine/graphics3/camera_sync_from_transform.js +29 -29
- package/src/engine/graphics3/debug/gizmo_view_from_camera.js +48 -48
- package/src/engine/graphics3/decal/DECAL_CLUSTER.js +61 -61
- package/src/engine/graphics3/decal/DECAL_GPU_RECORD.js +117 -117
- package/src/engine/graphics3/decal/DecalAtlas.js +194 -194
- package/src/engine/graphics3/decal/DecalAtlasFill.js +32 -32
- package/src/engine/graphics3/decal/GPUDecalRenderer.js +360 -360
- package/src/engine/graphics3/decal/chunk_decal_intersects_frustum.js +59 -59
- package/src/engine/graphics3/decal/chunk_decal_sampling_info.js +57 -57
- package/src/engine/graphics3/decal/chunk_decal_surface_frame.js +54 -54
- package/src/engine/graphics3/decal/decal_atlas_border.js +69 -69
- package/src/engine/graphics3/decal/decal_gpu_records.js +120 -120
- package/src/engine/graphics3/decal/decal_material_samplers.js +109 -109
- package/src/engine/graphics3/decal/graph_build_decal_clusters.js +212 -212
- package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +207 -207
- package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +108 -108
- package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +151 -151
- package/src/engine/graphics3/highlight/HIGHLIGHT_OUTLINE.js +23 -23
- package/src/engine/graphics3/highlight/chunk_highlight_lookup.js +53 -53
- package/src/engine/graphics3/highlight/pack_highlight_color.js +44 -44
- package/src/engine/graphics3/highlight/pack_highlight_table.js +74 -74
- package/src/engine/graphics3/highlight/shader_highlight_outline.js +150 -150
- package/src/engine/graphics3/load_cube_environment.js +68 -68
- package/src/engine/graphics3/make_default_environment.js +107 -107
- package/src/engine/graphics3/particles/particle_gpu_records.js +221 -221
- package/src/engine/graphics3/path/build_tube_path_streams.js +98 -98
- package/src/engine/graphics3/path/tube_stream_write_geometry.js +90 -90
- package/src/engine/graphics3/preview/ModelPreviewFraming.js +35 -35
- package/src/engine/graphics3/preview/make_model_preview_scene.js +154 -154
- package/src/engine/graphics3/preview/make_model_thumbnail.js +48 -48
- package/src/engine/graphics3/preview/model_preview_framing.js +70 -70
- package/src/engine/graphics3/shade_bundle_bounds.js +55 -55
- package/src/engine/graphics3/shade_camera_projection_ray.js +77 -77
- package/src/engine/graphics3/shade_node_to_entity_composition.js +84 -84
- package/src/engine/graphics3/terrain/GPUTerrainSplatRenderer.js +481 -481
- package/src/engine/graphics3/terrain/chunk_terrain_grid_overlay.js +61 -61
- package/src/engine/graphics3/terrain/chunk_terrain_splat_mix.js +66 -66
- package/src/engine/graphics3/terrain/pack_terrain_row_table.js +53 -53
- package/src/engine/graphics3/terrain/shader_terrain_splat.js +215 -215
- package/src/engine/graphics3/trail/trail_tube_write_geometry.js +158 -158
- package/src/engine/grid/grid2transform/GridPosition2TransformSystem.d.ts +2 -2
- package/src/engine/grid/grid2transform/GridPosition2TransformSystem.d.ts.map +1 -1
- package/src/engine/input/GAMEPAD_API_PROPOSAL.md +717 -717
- package/src/engine/input/analog/apply_radial_dead_zone.js +38 -38
- package/src/engine/input/devices/GamepadDevice.js +466 -466
- package/src/engine/input/devices/ManualInputDevice.js +152 -152
- package/src/engine/input/devices/PointerCoordinates.js +26 -26
- package/src/engine/input/devices/events/GamepadEvents.js +10 -10
- package/src/engine/input/devices/gamepad/GamepadAxes.js +19 -19
- package/src/engine/input/devices/gamepad/GamepadButtons.js +29 -29
- package/src/engine/input/devices/gamepad/GamepadCoordinates.js +17 -17
- package/src/engine/input/devices/gamepad/GamepadDeviceLayout.js +323 -323
- package/src/engine/input/devices/gamepad/GamepadHandle.js +286 -286
- package/src/engine/input/devices/gamepad/GamepadLayout.js +160 -160
- package/src/engine/input/devices/gamepad/GamepadStandardMapping.js +31 -31
- package/src/engine/input/devices/gamepad/GamepadStick.js +169 -169
- package/src/engine/input/devices/gamepad/GamepadStickCalibration.js +119 -119
- package/src/engine/input/devices/gamepad/GamepadStickCalibrator.js +250 -250
- package/src/engine/input/devices/gamepad/gamepad_layout_database.js +144 -144
- package/src/engine/input/devices/gamepad/gamepad_read_hat_axis.js +61 -61
- package/src/engine/input/devices/gamepad/gamepad_write_dpad_vector.js +30 -30
- package/src/engine/input/devices/gamepad/prototypeGamepadTester.js +2124 -2124
- package/src/engine/input/devices/mouse/MouseButtons.js +22 -22
- package/src/engine/input/ecs/components/Input.js +118 -118
- package/src/engine/input/ecs/components/InputController.js +78 -78
- package/src/engine/input/ecs/ism/ISM_DESIGN.md +1523 -1523
- package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +627 -627
- package/src/engine/input/ecs/ism/InputActionEvent.js +40 -40
- package/src/engine/input/ecs/ism/InputBinding.js +71 -71
- package/src/engine/input/ecs/ism/InputCoordinateKind.js +25 -25
- package/src/engine/input/ecs/ism/InputCoordinateSource.js +86 -86
- package/src/engine/input/ecs/ism/InputDirection.js +33 -33
- package/src/engine/input/ecs/ism/InputMapProgram.js +236 -236
- package/src/engine/input/ecs/ism/InputMapSystem.js +976 -976
- package/src/engine/input/ecs/ism/InputOcclusion.js +31 -31
- package/src/engine/input/ecs/ism/InputSource.js +67 -67
- package/src/engine/input/ecs/ism/InputSourceTable.js +107 -107
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannel.js +93 -93
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannelType.js +11 -11
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.js +153 -153
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateSwitches.js +160 -160
- package/src/engine/input/ecs/ism/device/GAMEPAD_INPUT_DEVICE_ID.js +9 -9
- package/src/engine/input/ecs/ism/device/GamepadInputDeviceAdapter.js +88 -88
- package/src/engine/input/ecs/ism/device/InputDeviceAdapter.js +72 -72
- package/src/engine/input/ecs/ism/device/KEYBOARD_INPUT_DEVICE_ID.js +9 -9
- package/src/engine/input/ecs/ism/device/KeyboardInputDeviceAdapter.js +63 -63
- package/src/engine/input/ecs/ism/device/ManualInputDeviceAdapter.js +55 -55
- package/src/engine/input/ecs/ism/device/POINTER_INPUT_DEVICE_ID.js +9 -9
- package/src/engine/input/ecs/ism/device/PointerInputDeviceAdapter.js +160 -160
- package/src/engine/input/ecs/ism/map/InputBinding.js +88 -88
- package/src/engine/input/ecs/ism/map/InputCoordinateBinding.js +102 -102
- package/src/engine/input/ecs/ism/map/InputLayer.js +220 -220
- package/src/engine/input/ecs/ism/map/InputMap.js +331 -331
- package/src/engine/input/ecs/ism/prototypeInputMap.js +309 -309
- package/src/engine/input/ecs/ism/trigger/InputTrigger.js +148 -148
- package/src/engine/input/ecs/ism/trigger/InputTriggerChord.js +173 -173
- package/src/engine/input/ecs/ism/trigger/InputTriggerGamepadButton.js +37 -37
- package/src/engine/input/ecs/ism/trigger/InputTriggerHold.js +176 -176
- package/src/engine/input/ecs/ism/trigger/InputTriggerKey.js +39 -39
- package/src/engine/input/ecs/ism/trigger/InputTriggerMouseButton.js +38 -38
- package/src/engine/input/ecs/ism/trigger/InputTriggerRelease.js +120 -120
- package/src/engine/input/ecs/ism/trigger/InputTriggerSequence.js +315 -315
- package/src/engine/input/ecs/ism/trigger/InputTriggerSwitch.js +105 -105
- package/src/engine/input/ecs/ism/trigger/InputTriggerType.js +17 -17
- package/src/engine/input/ecs/systems/InputControllerSystem.js +253 -253
- package/src/engine/input/ecs/systems/InputSystem.js +162 -162
- package/src/engine/intelligence/behavior/primitive/FailingBehaviorSerializationAdapter.js +25 -25
- package/src/engine/intelligence/behavior/primitive/SucceedingBehaviorSerializationAdapter.js +26 -26
- package/src/engine/intelligence/behavior/util/AsynchronousDelayAction.js +55 -55
- package/src/engine/interpolation/BinaryInterpolationAdapter.js +56 -56
- package/src/engine/interpolation/Interpoland.js +49 -49
- package/src/engine/interpolation/Interpolated.js +149 -149
- package/src/engine/interpolation/PoseInterpolationAdapter.js +61 -61
- package/src/engine/interpolation/TransformPoseSerializationAdapter.js +57 -57
- package/src/engine/interpolation/pose_interpoland.js +27 -27
- package/src/engine/navigation/ecs/path_following/PathFollower.js +222 -222
- package/src/engine/navigation/mesh/NavigationMesh.js +145 -145
- package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +661 -0
- package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +229 -229
- package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.d.ts.map +1 -1
- package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.js +628 -520
- package/src/engine/network/CONGESTION_CONTROL.md +87 -87
- package/src/engine/network/README.md +52 -52
- package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +43 -43
- package/src/engine/network/adapters/TransformInterpolationAdapter.js +84 -84
- package/src/engine/network/adapters/TransformReplicationAdapter.js +87 -87
- package/src/engine/network/adapters/Vector3InterpolationAdapter.js +46 -46
- package/src/engine/network/convertPathToURL.js +2 -2
- package/src/engine/network/core/MalformedPacketError.js +26 -26
- package/src/engine/network/core/quantize/quantize_float.js +73 -73
- package/src/engine/network/core/quantize/quantize_position.js +65 -65
- package/src/engine/network/core/sequence/ack_bitfield.js +77 -77
- package/src/engine/network/core/sequence/seq16.js +69 -69
- package/src/engine/network/core/sequence/seq32.js +73 -73
- package/src/engine/network/ecs/NetworkSystem.js +84 -84
- package/src/engine/network/ecs/components/NetworkIdentity.js +73 -73
- package/src/engine/network/ecs/owner_authorization.js +55 -55
- package/src/engine/network/ecs/serialization/NetworkIdentitySerializationAdapter.js +64 -64
- package/src/engine/network/replication/ScopeFilter.js +71 -71
- package/src/engine/network/sim/ActionLog.js +152 -152
- package/src/engine/network/sim/SimAction.js +273 -273
- package/src/engine/network/sim/Snapshotter.js +222 -222
- package/src/engine/network/state/FrameBufferRing.js +168 -168
- package/src/engine/network/state/InputRing.js +134 -134
- package/src/engine/network/state/PriorityAccumulator.js +180 -180
- package/src/engine/network/time/TimeDilation.js +62 -62
- package/src/engine/network/transport/Channel.js +336 -336
- package/src/engine/network/transport/Transport.js +203 -203
- package/src/engine/network/transport/adapters/NodeUDPTransport.js +186 -186
- package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +105 -105
- package/src/engine/network/transport/fragments/fragment_send.js +147 -147
- package/src/engine/network/transport/fragments/packet_size.js +101 -101
- package/src/engine/network/xhr.js +23 -23
- package/src/engine/physics/BULLET_REVIEW.md +945 -945
- package/src/engine/physics/CANNON_REVIEW.md +1300 -1300
- package/src/engine/physics/CONSTRAINT_SOLVER_BENCH_LOG.md +208 -208
- package/src/engine/physics/CONSTRAINT_SOLVER_IMPROVEMENTS_PLAN.md +364 -364
- package/src/engine/physics/INTEPOLATION_SYSTEM_PLAN.md +287 -287
- package/src/engine/physics/JOLT_REVIEW.md +913 -913
- package/src/engine/physics/PLAN.md +1120 -1094
- package/src/engine/physics/RAPIER_REVIEW.md +934 -934
- package/src/engine/physics/REVIEW_001_ACTION_PLAN.md +642 -642
- package/src/engine/physics/REVIEW_002.md +151 -151
- package/src/engine/physics/REVIEW_003.md +166 -166
- package/src/engine/physics/broadphase/compute_fat_world_aabb.js +97 -97
- package/src/engine/physics/constraint/DofMode.js +35 -35
- package/src/engine/physics/constraint/solve_constraints.js +1 -1
- package/src/engine/physics/contact/combine_material.js +35 -35
- package/src/engine/physics/ecs/BodyKind.js +29 -29
- package/src/engine/physics/ecs/Collider.js +177 -177
- package/src/engine/physics/ecs/ColliderFlags.js +15 -15
- package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -37
- package/src/engine/physics/ecs/Joint.js +475 -475
- package/src/engine/physics/ecs/JointSerializationAdapter.js +72 -72
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +3 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +7 -2
- package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.js +37 -37
- package/src/engine/physics/ecs/SleepState.js +12 -12
- package/src/engine/physics/ecs/find_non_finite_physics_state.js +76 -76
- package/src/engine/physics/fluid/FluidField.js +867 -867
- package/src/engine/physics/fluid/FluidSimulator.js +832 -832
- package/src/engine/physics/fluid/REVIEW_02_PLAN.md +243 -243
- package/src/engine/physics/fluid/SliceVisualiser.js +190 -190
- package/src/engine/physics/fluid/ecs/FluidComponent.js +239 -239
- package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -89
- package/src/engine/physics/fluid/ecs/FluidObstacle.js +97 -97
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +348 -348
- package/src/engine/physics/fluid/ecs/FluidSystem.js +142 -142
- package/src/engine/physics/fluid/ecs/FluidWorkerCore.js +123 -123
- package/src/engine/physics/fluid/ecs/WorkerFluidSystem.js +395 -395
- package/src/engine/physics/fluid/ecs/fluid.worker.js +12 -12
- package/src/engine/physics/fluid/ecs/fluid_build_world_to_grid.js +32 -32
- package/src/engine/physics/fluid/ecs/fluid_gather_visible_effectors.js +47 -47
- package/src/engine/physics/fluid/ecs/fluid_reanchor_field.js +85 -85
- package/src/engine/physics/fluid/ecs/fluid_sync_effectors_from_transform.js +16 -16
- package/src/engine/physics/fluid/ecs/fluid_worker_protocol.js +111 -111
- package/src/engine/physics/fluid/ecs/makeFluidWorker.js +18 -18
- package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -81
- package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +202 -202
- package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +257 -257
- package/src/engine/physics/fluid/effector/WakeFluidEffector.js +405 -405
- package/src/engine/physics/fluid/prototype.js +126 -126
- package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.js +143 -143
- package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.js +162 -162
- package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.js +107 -107
- package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.js +131 -131
- package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +90 -90
- package/src/engine/physics/fluid/solver/v3_grid_limit8_at_indices.js +38 -38
- package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.js +77 -77
- package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -113
- package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.js +92 -92
- package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -107
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +135 -135
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +511 -511
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +108 -108
- package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.js +317 -317
- package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.js +236 -236
- package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.js +217 -217
- package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.js +174 -174
- package/src/engine/physics/fluid/solver/v3_mac_clip_trace.js +95 -95
- package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.js +77 -77
- package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.js +131 -131
- package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.js +104 -104
- package/src/engine/physics/inertia/world_inverse_inertia.js +160 -160
- package/src/engine/physics/integration/integrate_position.js +97 -97
- package/src/engine/physics/narrowphase/box_box_manifold.js +681 -681
- package/src/engine/physics/narrowphase/box_triangle_contact.js +906 -906
- package/src/engine/physics/narrowphase/capsule_triangle_contact.js +395 -395
- package/src/engine/physics/narrowphase/compute_penetration.js +369 -369
- package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.js +55 -55
- package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.js +37 -37
- package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.js +117 -117
- package/src/engine/physics/narrowphase/narrowphase_step.js +1738 -1738
- package/src/engine/physics/narrowphase/reduce_manifold_contacts.js +74 -74
- package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +12 -11
- package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/refine_ray_hit.js +228 -36
- package/src/engine/physics/narrowphase/sphere_sphere_contact.js +52 -52
- package/src/engine/physics/narrowphase/sphere_triangle_contact.js +138 -138
- package/src/engine/physics/persistence/solver_caches.js +309 -309
- package/src/engine/physics/queries/overlap_shape.js +187 -187
- package/src/engine/physics/queries/raycast.d.ts +7 -4
- package/src/engine/physics/queries/raycast.d.ts.map +1 -1
- package/src/engine/physics/queries/raycast.js +11 -5
- package/src/engine/physics/queries/shape_cast.js +417 -417
- package/src/engine/physics/solver/apply_impulse_to_body.js +86 -86
- package/src/engine/physics/solver/friction_cone.js +37 -37
- package/src/engine/physics/solver/solve_contacts.js +1 -1
- package/src/engine/platform/WebEnginePlatform.d.ts.map +1 -1
- package/src/engine/platform/WebEnginePlatform.js +1 -2
- package/src/engine/scene/SerializedScene.d.ts +2 -2
- package/src/engine/scene/SerializedScene.d.ts.map +1 -1
- package/src/engine/scene/transitionToScene.js +121 -121
- package/src/engine/simulation/Ticker.d.ts.map +1 -1
- package/src/engine/simulation/Ticker.js +33 -0
- package/src/engine/sound/ecs/audio/LiveEmitterSet.js +345 -345
- package/src/engine/sound/ecs/audio/SpatialAudioIndex.js +140 -140
- package/src/engine/sound/simulation/AcousticSimulator.js +646 -646
- package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +432 -432
- package/src/engine/sound/simulation/PROBE_PLACEMENT.md +250 -250
- package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +322 -322
- package/src/engine/sound/simulation/README.md +277 -277
- package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +261 -261
- package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +121 -121
- package/src/engine/sound/simulation/configureAcousticSimulation.js +48 -48
- package/src/engine/sound/simulation/core/AcousticMedium.js +113 -113
- package/src/engine/sound/simulation/core/AcousticMediumSerializationAdapter.js +27 -27
- package/src/engine/sound/simulation/core/AcousticOccluderIndex.js +312 -312
- package/src/engine/sound/simulation/core/AcousticRegionIndex.js +159 -159
- package/src/engine/sound/simulation/core/AcousticSolution.js +90 -90
- package/src/engine/sound/simulation/core/AcousticSourceState.js +109 -109
- package/src/engine/sound/simulation/core/AcousticVolumeRegion.js +73 -73
- package/src/engine/sound/simulation/core/OcclusionSolver.js +112 -112
- package/src/engine/sound/simulation/core/RayHit.js +50 -50
- package/src/engine/sound/simulation/core/VolumeField.js +149 -149
- package/src/engine/sound/simulation/definition/AcousticDirectivity.js +114 -114
- package/src/engine/sound/simulation/definition/AcousticDirectivitySerializationAdapter.js +30 -30
- package/src/engine/sound/simulation/definition/AcousticMaterial.js +122 -122
- package/src/engine/sound/simulation/definition/AcousticMaterialSerializationAdapter.js +32 -32
- package/src/engine/sound/simulation/ecs/AcousticBody.js +48 -48
- package/src/engine/sound/simulation/ecs/AcousticBodySerializationAdapter.js +34 -34
- package/src/engine/sound/simulation/ecs/AcousticProbeFieldSystem.js +64 -64
- package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +75 -75
- package/src/engine/sound/simulation/ecs/AcousticVolume.js +74 -74
- package/src/engine/sound/simulation/ecs/AcousticVolumeSerializationAdapter.js +37 -37
- package/src/engine/sound/simulation/ecs/AcousticVolumeSystem.js +66 -66
- package/src/engine/sound/simulation/probe/AcousticProbeField.js +578 -578
- package/src/engine/sound/simulation/probe/AcousticProbeFieldSerializationAdapter.js +60 -60
- package/src/engine/sound/simulation/probe/ProbeFieldPathingSolution.js +64 -64
- package/src/engine/sound/simulation/probe/ProbeVisibilityRecheck.js +132 -132
- package/src/engine/sound/simulation/probe/acoustic_probe_transfer.js +103 -103
- package/src/engine/sound/simulation/probe/acoustic_trace_energy.js +136 -136
- package/src/engine/sound/simulation/probe/bakeProbeField.js +169 -169
- package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +110 -110
- package/src/engine/sound/simulation/probe/bakeReverbBands.js +110 -110
- package/src/engine/sound/simulation/probe/bakeVisibility.js +148 -148
- package/src/engine/sound/simulation/probe/echogram_band_rt60.js +83 -83
- package/src/engine/sound/simulation/probe/probe_delaunay_edges.js +215 -215
- package/src/engine/sound/simulation/probe/probe_densify_portals.js +140 -140
- package/src/engine/sound/simulation/probe/probe_detect_portals.js +196 -196
- package/src/engine/sound/simulation/probe/probe_edge_key.js +38 -38
- package/src/engine/sound/simulation/probe/probe_edge_visible.js +41 -41
- package/src/engine/sound/simulation/probe/probe_place_sdf_cover.js +82 -82
- package/src/engine/sound/simulation/probe/probe_refine_connectivity.js +181 -181
- package/src/engine/sound/simulation/probe/probe_sdf_grid.js +171 -171
- package/src/engine/sound/simulation/probe/probe_visibility_augment.js +146 -146
- package/src/engine/sound/simulation/probe/probe_visibility_bridge_components.js +167 -167
- package/src/engine/sound/simulation/render/FoaProbeReverbRenderer.js +354 -354
- package/src/engine/sound/simulation/render/ProbeReverbRenderer.js +231 -231
- package/src/engine/sound/simulation/render/foaReverbImpulseResponse.js +105 -105
- package/src/engine/sound/simulation/render/reverbImpulseResponse.js +66 -66
- package/src/engine/sound/simulation/render/reverb_band_tails.js +93 -93
- package/src/engine/sound/simulation/serialization/populateAcousticSerializationRegistry.js +25 -25
- package/src/engine/sound/sopra/README.md +643 -643
- package/src/engine/sound/sopra/SopraEngine.js +432 -432
- package/src/engine/sound/sopra/asset/AssetManagerBufferProvider.js +71 -71
- package/src/engine/sound/sopra/asset/BufferProvider.js +29 -29
- package/src/engine/sound/sopra/asset/StubBufferProvider.js +58 -58
- package/src/engine/sound/sopra/definition/BusDefinition.js +142 -142
- package/src/engine/sound/sopra/definition/BusDefinitionSerializationAdapter.js +54 -54
- package/src/engine/sound/sopra/definition/DuckingRule.js +106 -106
- package/src/engine/sound/sopra/definition/DuckingRuleSerializationAdapter.js +31 -31
- package/src/engine/sound/sopra/definition/EventDescription.js +262 -262
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +55 -55
- package/src/engine/sound/sopra/definition/MixerSnapshot.js +83 -83
- package/src/engine/sound/sopra/definition/MixerSnapshotSerializationAdapter.js +39 -39
- package/src/engine/sound/sopra/definition/ParameterDefinition.js +117 -117
- package/src/engine/sound/sopra/definition/ParameterDefinitionSerializationAdapter.js +31 -31
- package/src/engine/sound/sopra/definition/VoiceStealMode.js +18 -18
- package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.js +109 -109
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.js +185 -185
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.js +59 -59
- package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.js +128 -128
- package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.js +226 -226
- package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClipSerializationAdapter.js +54 -54
- package/src/engine/sound/sopra/definition/clip/SampleAudioClip.js +191 -191
- package/src/engine/sound/sopra/definition/clip/SampleAudioClipSerializationAdapter.js +39 -39
- package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.js +79 -79
- package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClipSerializationAdapter.js +42 -42
- package/src/engine/sound/sopra/definition/clip/SilenceAudioClip.js +77 -77
- package/src/engine/sound/sopra/definition/clip/SilenceAudioClipSerializationAdapter.js +27 -27
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts +5 -0
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.js +125 -125
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClipSerializationAdapter.js +41 -41
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +24 -24
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +120 -120
- package/src/engine/sound/sopra/definition/effect/CompressorEffectSerializationAdapter.js +31 -31
- package/src/engine/sound/sopra/definition/effect/EqEffect.js +128 -128
- package/src/engine/sound/sopra/definition/effect/EqEffectSerializationAdapter.js +29 -29
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +113 -113
- package/src/engine/sound/sopra/definition/effect/ReverbEffectSerializationAdapter.js +25 -25
- package/src/engine/sound/sopra/runtime/BusGraph.js +231 -231
- package/src/engine/sound/sopra/runtime/ParameterStore.js +98 -98
- package/src/engine/sound/sopra/runtime/SopraPlaybackContext.js +68 -68
- package/src/engine/sound/sopra/runtime/Voice.js +145 -145
- package/src/engine/sound/sopra/runtime/VoiceManager.js +136 -136
- package/src/engine/sound/sopra/runtime/VoicePool.js +17 -17
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +42 -42
- package/src/engine/sound/sopra/serialization/sopraJSON.js +99 -99
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +49 -49
- package/src/engine/sound/sopra/util/MockAudioContext.js +224 -224
- package/src/engine/sound/sopra/util/fadeOutAndStop.js +60 -60
- package/src/engine/ui/DraggableAspect.js +115 -115
- package/src/engine/ui/apply_pointer_tilt_3d.js +50 -50
- package/src/generation/COORDINATES.md +54 -54
- package/src/generation/GridGenerationResource.js +24 -24
- package/src/generation/GridTaskGroup.js +214 -214
- package/src/generation/REVIEW_01_ACTION_PLAN.md +628 -628
- package/src/generation/automata/CaveGeneratorCellularAutomata.js +79 -79
- package/src/generation/automata/CellularAutomata.js +22 -22
- package/src/generation/compute_writes_union.js +25 -25
- package/src/generation/filtering/CellFilter.js +117 -117
- package/src/generation/filtering/core/CellFilterBinaryOperation.js +37 -37
- package/src/generation/filtering/core/CellFilterOperationTertiary.js +43 -43
- package/src/generation/filtering/core/CellFilterUnaryOperation.js +29 -29
- package/src/generation/filtering/numeric/process/computeCellFilterSobel.js +36 -36
- package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.js +42 -42
- package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.js +18 -18
- package/src/generation/filtering/numeric/util/write_cell_filter_to_sampler2d.js +47 -47
- package/src/generation/filtering/util/cell_filter_weights_pick.js +54 -54
- package/src/generation/grid/GridData.js +233 -233
- package/src/generation/grid/coords/grid_to_texel.js +10 -10
- package/src/generation/grid/coords/texel_to_grid.js +10 -10
- package/src/generation/grid/generation/GridTaskApplyActionToCells.js +90 -90
- package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +388 -388
- package/src/generation/grid/generation/GridTaskExecuteRuleTimes.js +127 -127
- package/src/generation/grid/generation/GridTaskSequence.js +58 -58
- package/src/generation/grid/generation/NoopGridTaskGenerator.js +12 -12
- package/src/generation/grid/generation/discrete/GridTaskActionRuleSet.js +48 -48
- package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.js +146 -146
- package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +540 -540
- package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +222 -222
- package/src/generation/grid/generation/grid/GridTaskAddNodesFixed.js +44 -44
- package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +614 -614
- package/src/generation/markers/GridCellActionPlaceMarker.js +244 -244
- package/src/generation/markers/GridCellActionPlaceMarkerGroup.js +86 -86
- package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.js +266 -266
- package/src/generation/markers/emitter/MarkerNodeEmitterGridCellAction.js +49 -49
- package/src/generation/placement/GridCellActionTransformNearbyMarkers.js +120 -120
- package/src/generation/placement/action/GridCellAction.js +45 -45
- package/src/generation/placement/action/GridCellActionPlaceTags.js +140 -140
- package/src/generation/placement/action/GridCellActionWriteFilterToLayer.js +89 -89
- package/src/generation/placement/action/random/CellActionSelectRandom.js +69 -69
- package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.js +91 -91
- package/src/generation/placement/action/util/GridCellActionSequence.js +61 -61
- package/src/generation/placement/action/util/GridCellDisplacedAction.js +61 -61
- package/src/generation/rules/cell/CellMatcherRemovalPreservesConnectivity.js +183 -183
- package/src/generation/theme/ThemeEngine.js +666 -666
- package/src/shade/RENDERER_CONTRACT.md +568 -0
- package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +267 -267
- package/src/shade/device/ShadeDeviceFailure.js +104 -104
- package/src/shade/device/ShadeDeviceFailureReason.js +41 -41
- package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +255 -255
- package/src/shade/device/mock/REVIEW_2026_08_22.md +527 -527
- package/src/shade/device/mock/SoftwareGPUBindGroup.js +23 -23
- package/src/shade/device/mock/SoftwareGPUBindGroupLayout.js +22 -22
- package/src/shade/device/mock/SoftwareGPUError.js +63 -63
- package/src/shade/device/mock/SoftwareGPUPipeline.js +75 -75
- package/src/shade/device/mock/SoftwareGPUQuerySet.js +113 -113
- package/src/shade/device/mock/SoftwareGPUSampler.js +30 -30
- package/src/shade/device/mock/SoftwareGPUShaderModule.js +32 -32
- package/src/shade/device/mock/SoftwareGPUTextureView.js +22 -22
- package/src/shade/device/mock/SoftwareGPUUncapturedErrorEvent.js +23 -23
- package/src/shade/device/mock/normalize_dynamic_offsets.js +26 -26
- package/src/shade/device/mock/texture_copy.js +287 -287
- package/src/shade/device/timing/GPUTimer.js +285 -285
- package/src/shade/device/timing/GPUTimerArray.js +205 -205
- package/src/shade/playground/add_random_lights.js +49 -49
- package/src/shade/playground/add_random_meshes.js +83 -83
- package/src/shade/playground/animation_prototype.js +508 -508
- package/src/shade/playground/animation_prototype_skinning.js +647 -647
- package/src/shade/playground/animation_prototype_stress.js +765 -765
- package/src/shade/playground/enable_picker.js +59 -59
- package/src/shade/playground/gltf_skinned_prototype.js +560 -560
- package/src/shade/playground/gltf_skinned_stress_prototype.js +387 -387
- package/src/shade/playground/gltf_viewer.js +282 -282
- package/src/shade/playground/load_default_environment.js +19 -19
- package/src/shade/playground/main.js +2727 -2727
- package/src/shade/playground/make_animated_instances.js +117 -117
- package/src/shade/playground/prototype_virtual_texture.js +274 -274
- package/src/shade/playground/prototype_volumetrics_01.js +206 -206
- package/src/shade/playground/sample.js +234 -234
- package/src/shade/playground/sample_load_gltf.js +102 -102
- package/src/shade/playground/spread_node3d_grid.js +19 -19
- package/src/shade/renderer/Renderer.js +2436 -2436
- package/src/shade/renderer/ShadeIndirectLightingMode.js +14 -14
- package/src/shade/renderer/animation/ShadeAnimationChannel.js +414 -414
- package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.js +531 -531
- package/src/shade/renderer/animation/pose/PosePlayback.js +55 -55
- package/src/shade/renderer/animation/pose/pose_evaluate_local.js +179 -179
- package/src/shade/renderer/animation/pose/pose_evaluate_world.js +76 -76
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +1024 -1024
- package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.js +79 -79
- package/src/shade/renderer/animation/skinning/chunk_skin_blend_mesh_local.js +56 -56
- package/src/shade/renderer/binding/BindGroupManager.js +282 -282
- package/src/shade/renderer/binding/adapt_cache_capacity.js +25 -25
- package/src/shade/renderer/buffer/GPUBufferAllocator.js +116 -116
- package/src/shade/renderer/buffer/buffer_pool_ops.js +123 -123
- package/src/shade/renderer/buffer/table/GPU_DATABASE_PAGE_SIZE.js +9 -9
- package/src/shade/renderer/buffer/table/GPU_DATABASE_UPLOAD_BUFFER_LIMIT.js +8 -8
- package/src/shade/renderer/buffer/table/PageBufferPool.js +71 -71
- package/src/shade/renderer/buffer/table/PageSlotAllocator.js +95 -95
- package/src/shade/renderer/camera/Camera.js +281 -281
- package/src/shade/renderer/camera/GPUCameraContext.js +233 -233
- package/src/shade/renderer/camera/orbital/README.md +84 -84
- package/src/shade/renderer/deferred/shader_composite_volumetrics.js +75 -75
- package/src/shade/renderer/dynamic/DYNAMIC_MESH_VERTEX.js +25 -25
- package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.js +342 -342
- package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
- package/src/shade/renderer/dynamic/shader_dynamic_mesh.js +170 -170
- package/src/shade/renderer/extension/FrameContext.js +263 -263
- package/src/shade/renderer/extension/FramePhase.js +104 -104
- package/src/shade/renderer/extension/FrameRecord.js +126 -126
- package/src/shade/renderer/extension/GBufferTextures.js +83 -83
- package/src/shade/renderer/extension/PresentTarget.js +34 -34
- package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +918 -918
- package/src/shade/renderer/extension/RenderExtension.js +69 -69
- package/src/shade/renderer/extension/RenderExtensionRegistry.js +319 -319
- package/src/shade/renderer/extension/SceneColor.js +40 -40
- package/src/shade/renderer/extension/ViewTextures.js +78 -78
- package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +182 -182
- package/src/shade/renderer/geometry/Geometry.js +608 -608
- package/src/shade/renderer/geometry/geometry_build_from_meshlet_geometry.js +342 -342
- package/src/shade/renderer/geometry/meshlet_geometry_transfer.js +41 -41
- package/src/shade/renderer/geometry/primitives/make_box_geometry.js +153 -153
- package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +240 -240
- package/src/shade/renderer/geometry/primitives/make_plane_geometry.js +145 -145
- package/src/shade/renderer/geometry/primitives/make_polyhedron_geometry.js +327 -327
- package/src/shade/renderer/geometry/primitives/make_torus_geometry.js +107 -107
- package/src/shade/renderer/geometry/primitives/make_torus_knot_geometry.js +165 -165
- package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +607 -607
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +66 -66
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildResult.js +32 -32
- package/src/shade/renderer/geometry/virtual/build/VGeoFaceGraph.js +103 -103
- package/src/shade/renderer/geometry/virtual/build/VGeoGatheredFaces.js +25 -25
- package/src/shade/renderer/geometry/virtual/build/VGeoLevel.js +33 -33
- package/src/shade/renderer/geometry/virtual/build/VGeoLevelOptions.js +62 -62
- package/src/shade/renderer/geometry/virtual/build/VGeoLevelSummary.js +49 -49
- package/src/shade/renderer/geometry/virtual/build/VGeoSubmesh.js +20 -20
- package/src/shade/renderer/geometry/virtual/build/VirtualGeometryMesh.js +214 -214
- package/src/shade/renderer/geometry/virtual/build/gltf/GltfByteSource.js +122 -122
- package/src/shade/renderer/geometry/virtual/build/gltf/GltfCollectReport.js +29 -29
- package/src/shade/renderer/geometry/virtual/build/gltf/GltfDocument.js +210 -210
- package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometry.js +48 -48
- package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometryInstance.js +25 -25
- package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometrySelection.js +28 -28
- package/src/shade/renderer/geometry/virtual/build/gltf/gltf_collect_geometries.js +296 -296
- package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.js +166 -166
- package/src/shade/renderer/geometry/virtual/build/gltf/gltf_read_geometry.js +199 -199
- package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +173 -173
- package/src/shade/renderer/geometry/virtual/build/vgeo_bounding_sphere.js +28 -28
- package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +200 -200
- package/src/shade/renderer/geometry/virtual/build/vgeo_build_levels.js +1786 -1786
- package/src/shade/renderer/geometry/virtual/build/vgeo_build_page_nodes.js +157 -157
- package/src/shade/renderer/geometry/virtual/build/vgeo_build_root_group.js +26 -26
- package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_normals.js +75 -75
- package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_tangents.js +143 -143
- package/src/shade/renderer/geometry/virtual/build/vgeo_containing_sphere.js +44 -44
- package/src/shade/renderer/geometry/virtual/build/vgeo_extract_submesh.js +41 -41
- package/src/shade/renderer/geometry/virtual/build/vgeo_gather_faces.js +71 -71
- package/src/shade/renderer/geometry/virtual/build/vgeo_graph_components.js +123 -123
- package/src/shade/renderer/geometry/virtual/build/vgeo_narrow_indices.js +26 -26
- package/src/shade/renderer/geometry/virtual/build/vgeo_normalize_source.js +112 -112
- package/src/shade/renderer/geometry/virtual/build/vgeo_partition_graph.js +56 -56
- package/src/shade/renderer/geometry/virtual/build/vgeo_sphere_inflate_to_contain.js +70 -70
- package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set.js +187 -187
- package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set_packed.js +207 -207
- package/src/shade/renderer/geometry/virtual/format/VGEO_DEFECT.js +18 -18
- package/src/shade/renderer/geometry/virtual/format/VGeoDefect.js +38 -38
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +64 -64
- package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTE.js +13 -13
- package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTES.js +50 -50
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_allocate.js +28 -28
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_mask.js +23 -23
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.js +31 -31
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_vertex.js +32 -32
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.js +46 -46
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_like.js +19 -19
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.js +27 -27
- package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_asset_id_preimage.js +62 -62
- package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_asset_id.js +13 -13
- package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_directory_block_checksum.js +41 -41
- package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_frame_checksum.js +41 -41
- package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_header_checksum.js +25 -25
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.js +20 -20
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_RECORD_SIZE.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CHILD_REF.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_TRIANGLE_COUNT.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_VERTEX_COUNT.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_CHILD.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_GROUP.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_SAME_PAGE.js +6 -6
- package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +81 -81
- package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryGroup.js +37 -37
- package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryPageNode.js +55 -55
- package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_BLOCK_RECORDS.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_FLAG_ROOT_PAGE.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_RECORD_SIZE.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/directory/vgeo_directory_block_count.js +12 -12
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_OFFSET.js +11 -11
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_TABLE_ENTRY_SIZE.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.js +11 -11
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_RAW.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_ALIGNMENT.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_HEADER_SIZE.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_OFFSET.js +13 -13
- package/src/shade/renderer/geometry/virtual/format/frame/VGEO_PAGE_MAGIC.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameBlob.js +21 -21
- package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameExtent.js +59 -59
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_codec_name.js +27 -27
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.js +84 -84
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +56 -56
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.js +35 -35
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_scan_frames.js +74 -74
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +6 -6
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_HASH_ALGO_XXH3.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_OFFSET.js +31 -31
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_SIZE.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_OFFSET.js +20 -20
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_RECORD_SIZE.js +9 -9
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAGIC.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_PAYLOAD_ENCODING_SHADE_MESHLET_V1.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/header/VGeoLevelRecord.js +41 -41
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_RECORD_SIZE.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_GROUP_CLUSTER_COUNT.js +6 -6
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_OFFSET.js +21 -21
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_SIZE.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FANOUT.js +9 -9
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FLAG_LEAF.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_OFFSET.js +10 -10
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_RECORD_SIZE.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_HEADER_SIZE.js +5 -5
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +16 -16
- package/src/shade/renderer/geometry/virtual/format/payload/VGEO_ENCODING_FLAGS_MASK.js +6 -6
- package/src/shade/renderer/geometry/virtual/format/payload/VGeoEncodedPayload.js +18 -18
- package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.js +200 -200
- package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_attribute_offset.js +39 -39
- package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_size.js +20 -20
- package/src/shade/renderer/geometry/virtual/format/prototypeVGEOFormatViewer.js +2063 -2063
- package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +1622 -1622
- package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +485 -485
- package/src/shade/renderer/gpu_primitive/sort/ffx/graph_radix_sort.js +115 -115
- package/src/shade/renderer/gpu_primitive/sort/one_sweep/verify_radix_sort_one_sweep.js +110 -110
- package/src/shade/renderer/light/environment/octahedral_resample_kernel.js +50 -50
- package/src/shade/renderer/light/environment/octahedral_uv_to_direction.js +30 -30
- package/src/shade/renderer/light/environment/resample_cube_to_octahedral.js +157 -157
- package/src/shade/renderer/light/make_sunlight.js +35 -35
- package/src/shade/renderer/light/model/io/light_record_point.js +39 -39
- package/src/shade/renderer/loader/gltf/GLTF_PRIMITIVE_MODE.js +23 -23
- package/src/shade/renderer/loader/gltf/MESHOPT_COMPRESSION_PLAN.md +793 -793
- package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtension.js +54 -54
- package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtensionSet.js +109 -109
- package/src/shade/renderer/loader/gltf/ext/gltf_apply_buffer_view_extensions.js +69 -69
- package/src/shade/renderer/loader/gltf/ext/gltf_buffer_view_extensions.js +22 -22
- package/src/shade/renderer/loader/gltf/ext/gltf_geometry_extensions.js +39 -39
- package/src/shade/renderer/loader/gltf/ext/meshopt/MeshoptBufferViewExtension.js +301 -301
- package/src/shade/renderer/loader/gltf/gltf_component_type.js +223 -223
- package/src/shade/renderer/loader/gltf/gltf_node_world_matrices.js +137 -137
- package/src/shade/renderer/loader/gltf/gltf_parse_container.js +241 -241
- package/src/shade/renderer/loader/gltf/gltf_read_accessor.js +294 -294
- package/src/shade/renderer/loader/gltf/gltf_used_image_indices.js +49 -49
- package/src/shade/renderer/loader/gltf/load_gltf.js +1253 -1253
- package/src/shade/renderer/loader/gltf/tiny-gltf.js +646 -646
- package/src/shade/renderer/loader/usd/UsdError.js +33 -33
- package/src/shade/renderer/loader/usd/UsdExtensionRegistry.js +69 -69
- package/src/shade/renderer/loader/usd/load_usd.js +226 -226
- package/src/shade/renderer/loader/usd/parse_usda.js +931 -931
- package/src/shade/renderer/loader/usd/unpack_usdz.js +106 -106
- package/src/shade/renderer/loader/usd/usd_build_scene.js +658 -658
- package/src/shade/renderer/loader/usd/usd_compose_transform.js +258 -258
- package/src/shade/renderer/loader/usd/usd_decode_image.js +384 -384
- package/src/shade/renderer/loader/usd/usd_lz4.js +182 -182
- package/src/shade/renderer/loader/usd/usd_triangulate.js +159 -159
- package/src/shade/renderer/material/ShadeMaterial.d.ts +2 -2
- package/src/shade/renderer/material/ShadeMaterial.js +2 -2
- package/src/shade/renderer/material/standard/fragment_gbuffer.js +334 -334
- package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
- package/src/shade/renderer/material/standard/material_gbuffer_vertex.js +45 -45
- package/src/shade/renderer/material/standard_material_to_struct.js +23 -23
- package/src/shade/renderer/particles/prototypeParticleSystem.js +450 -450
- package/src/shade/renderer/particles/runtime/spawn_request_encoding.js +52 -52
- package/src/shade/renderer/pool/TransientResourcePool.js +392 -392
- package/src/shade/renderer/postprocess/bloom/bloom_chain_resolution.js +29 -29
- package/src/shade/renderer/postprocess/bloom/graph_bloom_downsample.js +109 -109
- package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.js +155 -155
- package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +114 -114
- package/src/shade/renderer/postprocess/dof/DOF_AUTOFOCUS_PARAMS_STRUCT.js +25 -25
- package/src/shade/renderer/postprocess/dof/DOF_FOCUS_STATE_STRUCT.js +23 -23
- package/src/shade/renderer/postprocess/dof/DOF_PRESETS.js +27 -27
- package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_diameter.js +41 -41
- package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_radius.js +32 -32
- package/src/shade/renderer/postprocess/dof/chunk_dof_coc_coefficient.js +26 -26
- package/src/shade/renderer/postprocess/dof/compute_dof_autofocus_params.js +64 -64
- package/src/shade/renderer/postprocess/dof/compute_dof_uniform.js +54 -54
- package/src/shade/renderer/postprocess/dof/gather/DOF2_CONFIG.js +91 -91
- package/src/shade/renderer/postprocess/dof/gather/DOF2_PRESETS.js +9 -9
- package/src/shade/renderer/postprocess/dof/gather/DOF2_SETTINGS_STRUCT.js +66 -66
- package/src/shade/renderer/postprocess/dof/gather/DOF2_TEXTURE_FORMAT.js +22 -22
- package/src/shade/renderer/postprocess/dof/gather/DepthOfFieldU.js +292 -292
- package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_coc_to_near_far.js +25 -25
- package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_gather_weight.js +30 -30
- package/src/shade/renderer/postprocess/dof/gather/compute_dof2_uniform.js +54 -54
- package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +194 -194
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_fill.js +68 -68
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +140 -140
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +142 -142
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +99 -99
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +102 -102
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_dilate.js +75 -75
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_max.js +73 -73
- package/src/shade/renderer/postprocess/dof/raymarch/DOF_SETTINGS_STRUCT.js +49 -49
- package/src/shade/renderer/postprocess/dof/raymarch/DepthOfField.js +298 -298
- package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +244 -244
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +91 -91
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_firefly_cleanup.js +61 -61
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +90 -90
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +267 -267
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +271 -271
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_dilate.js +70 -70
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_max.js +72 -72
- package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +99 -99
- package/src/shade/renderer/postprocess/gtao/generate_magic_square_noise.js +51 -51
- package/src/shade/renderer/postprocess/motion_blur/MotionBlur.js +56 -56
- package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +78 -78
- package/src/shade/renderer/postprocess/upscale-dither/UpscaleDither.js +95 -95
- package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +204 -204
- package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +58 -58
- package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +230 -230
- package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.js +278 -278
- package/src/shade/renderer/rasterize/native/oit/chunk_material_side_should_draw.js +26 -26
- package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +178 -178
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +235 -235
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +208 -208
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +206 -206
- package/src/shade/renderer/scene/DynamicMesh.js +70 -70
- package/src/shade/renderer/scene/DynamicMeshBatch.js +90 -90
- package/src/shade/renderer/scene/GPUSceneContext.js +901 -901
- package/src/shade/renderer/scene/SceneNodeBinding.js +56 -56
- package/src/shade/renderer/scene/SkinnedMesh.js +55 -55
- package/src/shade/renderer/scene/TransformAuthority.js +33 -33
- package/src/shade/renderer/scene/optimization/deduplicate_geometries.js +38 -38
- package/src/shade/renderer/scene/optimization/deduplicate_images.js +93 -93
- package/src/shade/renderer/scene/optimization/geometry/internal/match_refit_validate.js +127 -127
- package/src/shade/renderer/scene/optimization/geometry/internal/match_solve_transform.js +492 -492
- package/src/shade/renderer/scene/optimization/optimize_texture_set.js +81 -81
- package/src/shade/renderer/scene/optimization/source_to_sampler2d.js +21 -21
- package/src/shade/renderer/scene/serialization/STANDARD_MATERIAL_SERIALIZED_BYTE_SIZE.js +12 -12
- package/src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_transform_point.js +26 -26
- package/src/shade/renderer/shader/chunk/noise/chunk_interleaved_gradient_noise.js +20 -20
- package/src/shade/renderer/shader/chunk/spherical_harmonics/dering/chunk_sh2_dering_optimize_positive.js +61 -61
- package/src/shade/renderer/shader/chunk/texture/chunk_texture_filter_fxaa_lite.js +225 -225
- package/src/shade/renderer/shader/chunk/texture/dither/chunk_dither_color_8bit_gradient_noise.js +25 -25
- package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.js +384 -384
- package/src/shade/renderer/shadow/map/PointLightShadowmap.js +105 -105
- package/src/shade/renderer/shadow/map/SpotLightShadowmap.js +63 -63
- package/src/shade/renderer/shadow/map/TetrahedronPointLightShadowmap.js +89 -89
- package/src/shade/renderer/shadow/map/shadowmap_update_score.js +232 -232
- package/src/shade/renderer/texture/GPUTextureAllocator.js +85 -85
- package/src/shade/renderer/texture/texture_pool_ops.js +171 -171
- package/src/shade/renderer/texture/virtual/PageTableQuadAllocator.js +253 -253
- package/src/shade/renderer/texture/virtual/README.md +276 -276
- package/src/shade/renderer/texture/virtual/VTPageTable.js +330 -330
- package/src/shade/renderer/texture/virtual/VTPhysicalCache.js +349 -349
- package/src/shade/renderer/texture/virtual/VT_CONSTANTS.js +154 -154
- package/src/shade/renderer/texture/virtual/VT_STACK_INFO_STRUCT.js +20 -20
- package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +1276 -1276
- package/src/shade/renderer/texture/virtual/VirtualTextureStack.js +106 -106
- package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.js +150 -150
- package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +232 -232
- package/src/shade/renderer/texture/virtual/chunk_vt_request_key.js +28 -28
- package/src/shade/renderer/texture/virtual/source/VTSourceImage.js +207 -207
- package/src/shade/renderer/texture/virtual/source/VTSourceProcedural.js +135 -135
- package/src/shade/renderer/texture/virtual/source/VTSourceTiled.js +132 -132
- package/src/shade/renderer/water/GPUWaterRenderer.js +167 -167
- package/src/shade/renderer/water/shader_water.js +246 -246
- package/src/shade/renderer/water/water_height_texture_from_sampler.js +56 -56
- package/src/shade/vitest.setup.mjs +89 -89
- package/src/shade/wgsl/validate_wgsl_source.js +316 -316
- package/src/view/controller/controls/NumericIntervalControl.js +90 -90
- package/src/view/controller/controls/Vector2Control.js +83 -83
- package/src/view/controller/controls/Vector3Control.js +90 -90
- package/src/view/elements/Group.js +56 -56
- package/src/view/elements/drawCheckers.js +33 -33
- package/src/view/elements/windrose/WindRoseDiagram.js +369 -369
- package/src/view/graphics/WebGLContextFailureView.js +76 -76
- package/src/view/layout/DockPanel.js +51 -51
- package/src/view/layout/SplitView.js +365 -365
- package/src/view/layout/show_popup_menu.js +81 -81
- package/src/view/minimap/MinimapCanvasView.js +411 -411
- package/src/view/minimap/MinimapImageCache.js +88 -88
- package/src/view/minimap/MinimapMarkerCollection.d.ts +0 -1
- package/src/view/minimap/MinimapMarkerCollection.d.ts.map +1 -1
- package/src/view/minimap/MinimapMarkerCollection.js +180 -180
- package/src/view/minimap/dom/MinimapCameraView.js +206 -206
- package/src/view/minimap/minimap_focus_area.js +97 -97
- package/editor/process/symbolic/SocketsSymbolicDisplay.js +0 -192
- package/src/core/geom/3d/topology/struct/binary/io/moved_tests.txt +0 -37
- package/src/engine/ecs/attachment/Attachment.d.ts +0 -40
- package/src/engine/ecs/attachment/Attachment.d.ts.map +0 -1
- package/src/engine/ecs/attachment/Attachment.js +0 -57
- package/src/engine/ecs/attachment/AttachmentBinding.d.ts +0 -28
- package/src/engine/ecs/attachment/AttachmentBinding.d.ts.map +0 -1
- package/src/engine/ecs/attachment/AttachmentBinding.js +0 -41
- package/src/engine/ecs/attachment/AttachmentSystem.d.ts +0 -61
- package/src/engine/ecs/attachment/AttachmentSystem.d.ts.map +0 -1
- package/src/engine/ecs/attachment/AttachmentSystem.js +0 -307
- package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts +0 -27
- package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts.map +0 -1
- package/src/engine/ecs/attachment/BoneAttachmentBinding.js +0 -69
- package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts +0 -4
- package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts.map +0 -1
- package/src/engine/ecs/attachment/TransformAttachmentBinding.js +0 -51
- package/src/engine/ecs/sockets/AttachmentSocket.d.ts +0 -32
- package/src/engine/ecs/sockets/AttachmentSocket.d.ts.map +0 -1
- package/src/engine/ecs/sockets/AttachmentSocket.js +0 -60
- package/src/engine/ecs/sockets/AttachmentSocketType.d.ts +0 -6
- package/src/engine/ecs/sockets/AttachmentSocketType.d.ts.map +0 -1
- package/src/engine/ecs/sockets/AttachmentSocketType.js +0 -8
- package/src/engine/ecs/sockets/AttachmentSockets.d.ts +0 -57
- package/src/engine/ecs/sockets/AttachmentSockets.d.ts.map +0 -1
- package/src/engine/ecs/sockets/AttachmentSockets.js +0 -130
- package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts +0 -29
- package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts.map +0 -1
- package/src/engine/ecs/sockets/BoneAttachmentSocket.js +0 -56
- package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts +0 -6
- package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts.map +0 -1
- package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.js +0 -19
- package/src/shade/renderer/animation/_dump_resolve.d.mts +0 -2
- package/src/shade/renderer/animation/_dump_resolve.d.mts.map +0 -1
- package/src/shade/renderer/animation/_dump_resolve.mjs +0 -5
|
@@ -1,607 +1,607 @@
|
|
|
1
|
-
# `.vgeo` — Virtual Geometry Container Format
|
|
2
|
-
|
|
3
|
-
Status: **writer and validator implemented; no reader yet.** Companion to
|
|
4
|
-
[VIRTUAL_GEOMETRY_DESIGN.md](./VIRTUAL_GEOMETRY_DESIGN.md); every requirement pinned in
|
|
5
|
-
its §5/§6 is realized here as a concrete field or invariant. Pinned structure below;
|
|
6
|
-
open details are listed at the end. One `.vgeo` file = one unique geometry's complete
|
|
7
|
-
cluster DAG; instances share the file.
|
|
8
|
-
|
|
9
|
-
The implementation lives beside this document: `format/` is the container — what a file is,
|
|
10
|
-
how one is written, and `vgeo_validate_container.js`, which audits every §11 invariant in
|
|
11
|
-
one — and `build/` is the pipeline that produces it from a `Geometry`, glTF front end
|
|
12
|
-
included. The node command line over both is at `tools/geometry/virtual/`. One glTF yields **one file per
|
|
13
|
-
primitive**, in object space, with the scene's placements written to a sidecar manifest
|
|
14
|
-
rather than baked in. The runtime side (pager, residency, cut pass) is still design only.
|
|
15
|
-
|
|
16
|
-
## 1. Design constraints (inherited, binding)
|
|
17
|
-
|
|
18
|
-
- **Geometry only.** `.vgeo` carries geometry and its vertex attributes — nothing else.
|
|
19
|
-
Materials are orthogonal, engine-side concerns; a multi-material source splits into
|
|
20
|
-
one geometry per material before it reaches the DAG builder — for glTF that split is
|
|
21
|
-
free, since a primitive already carries exactly one material, and the converter's
|
|
22
|
-
front-end emits one file per primitive. The format has no material fields.
|
|
23
|
-
- Billions of source triangles per asset: 64-bit file offsets, 32-bit page indices.
|
|
24
|
-
- Immutable, content-addressed; perfect HTTP/CDN caching; fetched by single-range
|
|
25
|
-
requests.
|
|
26
|
-
- Fetch unit = size-bounded **page**, independently decodable; a group never spans pages.
|
|
27
|
-
- No separate global hierarchy: cluster metadata travels **in** pages, so the hierarchy
|
|
28
|
-
streams with the geometry it describes.
|
|
29
|
-
- **Traversal-first**: a page carries everything needed to fetch the pages it refines
|
|
30
|
-
into. Standard runtime operation is header → root page → page-to-page traversal; the
|
|
31
|
-
directory is auxiliary (tooling, validation, arbitrary-page access), never a hot-path
|
|
32
|
-
dependency.
|
|
33
|
-
- Time-to-first-pixel = header + root page, O(1) in asset size.
|
|
34
|
-
- Prefix-readable: a plain byte-prefix of the file is a complete coarse asset.
|
|
35
|
-
- Per-page compression inside the container only; transparent HTTP compression is
|
|
36
|
-
assumed absent (it does not compose with range requests).
|
|
37
|
-
- The page DAG is acyclic by construction: child references point strictly forward in
|
|
38
|
-
the file.
|
|
39
|
-
|
|
40
|
-
## 2. Conventions
|
|
41
|
-
|
|
42
|
-
- Little-endian throughout. Types: `u8 u16 u32 u64 f32`; `[T; N]` = N-element array.
|
|
43
|
-
- All file offsets are absolute byte offsets from file start. All in-page offsets are
|
|
44
|
-
byte offsets from the start of the **decoded** page.
|
|
45
|
-
- **Frames** (stored pages) start at 16-byte-aligned file offsets; `directory_offset`
|
|
46
|
-
is 16-aligned; alignment padding is real bytes in the file. Inside a decoded page,
|
|
47
|
-
all tables and payload sections are 4-byte aligned (Shade's pools are u32-word
|
|
48
|
-
addressed).
|
|
49
|
-
- Levels are numbered `0 = leaves`, increasing toward the root. "Coarser" = higher
|
|
50
|
-
level. A page's **band** is a contiguous level range `min_level..max_level`.
|
|
51
|
-
A level is a **group** ordinal, not a per-cluster depth: it says which band a group
|
|
52
|
-
sits in, and a group's clusters may sit at several different depths in the DAG,
|
|
53
|
-
because a cluster the builder had no use for is carried forward untouched rather than
|
|
54
|
-
coarsened for the sake of symmetry. Cluster records carry no level, and nothing needs
|
|
55
|
-
one. What the ordinal guarantees is the property file order depends on: **every group
|
|
56
|
-
is in a strictly lower band than the group holding its parents**, so pages laid out by
|
|
57
|
-
descending band make every child reference point forward.
|
|
58
|
-
- Sentinels for cluster `child_ref`: `NO_CHILD = 0xFFFF` (leaves),
|
|
59
|
-
`SAME_PAGE = 0xFFFE` (child group lives in this page — legal only in multi-level
|
|
60
|
-
pages, the root page included); valid child-table indices are `≤ 0xFFFD`. Cluster
|
|
61
|
-
`child_group`: `NO_GROUP = 0xFFFF`, exactly for leaves. All `f32` fields are NaN-free.
|
|
62
|
-
Error values are finite `≥ 0`, except the root's parent error which is `+∞` (f32
|
|
63
|
-
infinity).
|
|
64
|
-
- Reserved fields: writers MUST write 0; readers MUST ignore their contents.
|
|
65
|
-
- Hashing is xxHash3; a `hash_algo` id is reserved for future change. **Integrity
|
|
66
|
-
model**: identity-seeded per-frame checksums are the *operative client-side*
|
|
67
|
-
mechanism — and because all DAG edges (child tables, cluster records) live inside
|
|
68
|
-
frames, the traversal path is covered by them end to end; the header and the
|
|
69
|
-
directory carry their own checksums; `asset_id` is whole-file and
|
|
70
|
-
*publisher/pipeline/cache-side* — a range-fetching client never reads the whole file
|
|
71
|
-
and can never verify it. None of these are a security boundary — they defend against
|
|
72
|
-
truncation, corruption, version skew, and cache mixups, not attackers.
|
|
73
|
-
|
|
74
|
-
## 3. Top-level layout
|
|
75
|
-
|
|
76
|
-
```
|
|
77
|
-
[ Header (256 B) ]
|
|
78
|
-
[ Level table ] ← level_count × 32 B, §4.1
|
|
79
|
-
[ Root page frame ] ← always-resident set = header + table + this
|
|
80
|
-
[ Page frames, coarse-first band order ] ← prefix of the file = coarse asset
|
|
81
|
-
[ Page directory ] ← flat 32 B records, range-fetchable
|
|
82
|
-
[ Directory block checksums ] ← u64 per 128 records (4 KB block)
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
The frame region is **exactly** `[root_page_offset, directory_offset)` — that is the
|
|
86
|
-
normative end-of-frames rule (see §5). Its start is a header field rather than a constant
|
|
87
|
-
because the level table (§4.1) precedes it and its size depends on the build. The directory is **derived data**: every field in it is
|
|
88
|
-
reconstructible by scanning frames and decoding page headers. It exists for special
|
|
89
|
-
tasks — tooling, validation, RAM budgeting before fetch, resuming from a disk cache,
|
|
90
|
-
jumping to an arbitrary page without walking the DAG — and standard runtime traversal
|
|
91
|
-
never touches it. Random-access readers fetch directory slices on demand: record `i`
|
|
92
|
-
lives at exactly `directory_offset + 32·i`.
|
|
93
|
-
|
|
94
|
-
## 4. Header (256 bytes, fixed)
|
|
95
|
-
|
|
96
|
-
All u64/u128 fields are naturally 8-byte aligned.
|
|
97
|
-
|
|
98
|
-
| offset | type | field | notes |
|
|
99
|
-
|-------:|-----------|--------------------------|-------|
|
|
100
|
-
| 0 | u32 | magic | `'VGEO'` = 0x4F454756 |
|
|
101
|
-
| 4 | u16 | format_version | breaking layout changes only |
|
|
102
|
-
| 6 | u16 | min_reader_version | reader MUST reject if its version is lower |
|
|
103
|
-
| 8 | u16 | header_size | = 256 |
|
|
104
|
-
| 10 | u8 | hash_algo | 0 = xxHash3; readers MUST reject unknown values |
|
|
105
|
-
| 11 | u8 | reserved | |
|
|
106
|
-
| 12 | u32 | feature_flags_required | readers MUST reject any unknown set bit |
|
|
107
|
-
| 16 | u32 | feature_flags_ignorable | readers MUST ignore unknown set bits |
|
|
108
|
-
| 20 | u32 | payload_encoding | 1 = `SHADE_MESHLET_V1` (§8); readers MUST reject unknown values |
|
|
109
|
-
| 24 | [u8; 16] | asset_id | xxh3-128 of the whole file with every **derived checksum field** zeroed (see below); stored low64 LE at bytes 0–7, high64 LE at bytes 8–15 |
|
|
110
|
-
| 40 | u32 | vertex_attribute_mask | advisory attribute presence (§8 bit table) |
|
|
111
|
-
| 44 | u32 | total_pages | = directory record count |
|
|
112
|
-
| 48 | u64 | total_clusters | ≥ 1 |
|
|
113
|
-
| 56 | u64 | total_groups | ≥ 1 |
|
|
114
|
-
| 64 | u64 | root_page_offset | = `align16(256 + 32 · level_count)` — the level table (§4.1) sits between |
|
|
115
|
-
| 72 | u32 | root_page_fetch_size | same definition as child-table/directory `fetch_size`, for page 0 |
|
|
116
|
-
| 76 | u32 | root_page_decoded_size | RAM admission for the always-resident set, known from the header alone |
|
|
117
|
-
| 80 | u64 | directory_offset | also the exact end of the frame region |
|
|
118
|
-
| 88 | u64 | dir_block_checksums_offset | `ceil(total_pages / 128)` × u64 |
|
|
119
|
-
| 96 | u32 | nominal_page_size | build parameter, bytes; informational — readers MUST NOT assume (§11.5 exception) |
|
|
120
|
-
| 100 | u16 | reserved | |
|
|
121
|
-
| 102 | u8 | level_count | levels `0..level_count-1` |
|
|
122
|
-
| 103 | u8 | reserved | |
|
|
123
|
-
| 104 | u64 | source_vertex_count | vertices of the normalized source mesh (post-weld) the leaves represent |
|
|
124
|
-
| 112 | u64 | source_face_count | triangles of the normalized source mesh |
|
|
125
|
-
| 120 | [f32; 4] | object_sphere | object-space minimal bounding sphere (center xyz, radius) of the whole geometry |
|
|
126
|
-
| 136 | [f32; 6] | object_bounds | object-space AABB (min xyz, max xyz); instances transform at runtime |
|
|
127
|
-
| 160 | [u8; 88] | reserved | |
|
|
128
|
-
| 248 | u64 | header_checksum | xxh3-64 of bytes 0–255 with this field zeroed (`asset_id` already final) |
|
|
129
|
-
|
|
130
|
-
### 4.1 Level table (`level_count` × 32 B, immediately after the header)
|
|
131
|
-
|
|
132
|
-
Statistics per level, at `256 + 32·i`, ending where the root page frame begins. Small —
|
|
133
|
-
a hundred levels is 3.2 KB — so a single fetch of the file's head brings the header, the
|
|
134
|
-
whole table, and the always-resident root page together, and the table is available before
|
|
135
|
-
any page has been decoded.
|
|
136
|
-
|
|
137
|
-
| offset | type | field | notes |
|
|
138
|
-
|-------:|------|-------------------|-------|
|
|
139
|
-
| 0 | f32 | min_error | smallest object-space `r_e` any cluster of this level carries |
|
|
140
|
-
| 4 | f32 | max_error | largest |
|
|
141
|
-
| 8 | f32 | max_sphere_radius | largest LOD-metric sphere radius at this level |
|
|
142
|
-
| 12 | u32 | cluster_count | ≥ 1 |
|
|
143
|
-
| 16 | u32 | group_count | groups sitting in this band; ≥ 1 |
|
|
144
|
-
| 20 | u32 | triangle_count | |
|
|
145
|
-
| 24 | u64 | reserved | |
|
|
146
|
-
|
|
147
|
-
What it is for: an instance's level range can be **bracketed** from the errors and radii
|
|
148
|
-
alone — the coarsest level that still passes the threshold at the instance's near point,
|
|
149
|
-
the finest that could be wanted at its far one — without reading a cluster record or
|
|
150
|
-
fetching a page. That is what lets a scene of ten thousand identical parts resolve to a
|
|
151
|
-
handful of distinct cuts instead of ten thousand of them, and what lets a prefetch name
|
|
152
|
-
exactly the bands a bracket spans.
|
|
153
|
-
|
|
154
|
-
These are facts about the build, not a policy. In particular **`max_error` is not monotonic
|
|
155
|
-
in the level**: a round merges an error band, and a later round can produce a cluster finer
|
|
156
|
-
than an earlier one did, by finally reaching geometry that had been waiting for a partner.
|
|
157
|
-
A reader that wants a monotonic bound takes a running maximum from the coarsest end; that
|
|
158
|
-
is the reader's choice and not the file's.
|
|
159
|
-
|
|
160
|
-
`cluster_count` and `group_count` sum to the header's `total_clusters` and `total_groups`,
|
|
161
|
-
which is the cross-check that keeps the table from drifting from the pages.
|
|
162
|
-
|
|
163
|
-
**What `asset_id` covers.** The whole file, with these fields treated as zero: `asset_id` itself,
|
|
164
|
-
`header_checksum`, every frame's `checksum` (§5), and the entire `dir_block_checksums` region (§9).
|
|
165
|
-
Excluding the last two is what breaks the circle — the frame checksums are seeded from
|
|
166
|
-
`asset_id_low64` and the directory block checksums from `asset_id_high64`, so covering them would
|
|
167
|
-
make the identity a function of itself. Nothing is lost by the exclusion: every one of those fields
|
|
168
|
-
is a function of content the hash still covers, so any change to the asset still moves `asset_id`.
|
|
169
|
-
|
|
170
|
-
Build order, and the order a verifier repeats: zero those fields → hash → write `asset_id` →
|
|
171
|
-
compute and write the frame and directory-block checksums it seeds → compute and write
|
|
172
|
-
`header_checksum` over bytes 0–255 with only that field zeroed.
|
|
173
|
-
|
|
174
|
-
The asset filename MUST be derived from `asset_id` in streamed deployments (content
|
|
175
|
-
addressing is what makes same-URL version skew impossible; every client-side integrity
|
|
176
|
-
property leans on it). The field is authoritative, the name is the enforcement.
|
|
177
|
-
|
|
178
|
-
A new `payload_encoding` (e.g. quantized positions) is a **per-asset capability gate,
|
|
179
|
-
not a format break**: old readers cleanly reject the asset instead of misreading it;
|
|
180
|
-
`format_version` moves only when the container layout itself changes.
|
|
181
|
-
|
|
182
|
-
## 5. Page frame (stored page)
|
|
183
|
-
|
|
184
|
-
Every page — root included — is stored as a self-delimiting frame:
|
|
185
|
-
|
|
186
|
-
```
|
|
187
|
-
[ FrameHeader (24 B) ] [ Child table (plaintext) ] [ blob (codec-encoded) ]
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
| offset | type | field | notes |
|
|
191
|
-
|-------:|------|------------------|-------|
|
|
192
|
-
| 0 | u32 | magic | `'VGPG'` = 0x47504756 |
|
|
193
|
-
| 4 | u8 | codec | 0 = raw, 1 = one LZ4 block; applies to the blob only; readers MUST reject unknown values |
|
|
194
|
-
| 5 | u8 | flags | 0 |
|
|
195
|
-
| 6 | u16 | child_page_count | entries in the child table; 0 for all-leaf pages |
|
|
196
|
-
| 8 | u32 | stored_size | bytes of blob (after the child table) |
|
|
197
|
-
| 12 | u32 | decoded_size | decoded-page bytes (== stored_size when raw); MUST equal the referencing child-table entry's (and the directory record's), else reject |
|
|
198
|
-
| 16 | u64 | checksum | xxh3-64, **seed = asset_id_low64 XOR page_index**, over frame bytes `[0, 16)` followed by `[24, 24 + 48·child_page_count + stored_size)` — everything but this field |
|
|
199
|
-
|
|
200
|
-
**Child table** — `child_page_count` × 48 B, plaintext (never compressed), deduplicated:
|
|
201
|
-
one entry per distinct child page this page's clusters refine into. This is what makes
|
|
202
|
-
traversal self-sufficient — an installed page needs nothing but itself to fetch every
|
|
203
|
-
page one level down — and it is plaintext for two load-bearing reasons: fetch ranges
|
|
204
|
-
are readable before (or without) blob decode, and stored sizes stay independent of
|
|
205
|
-
offset values, which keeps the build's layout computation non-circular (§10).
|
|
206
|
-
|
|
207
|
-
| offset | type | field | notes |
|
|
208
|
-
|-------:|------|---------------|-------|
|
|
209
|
-
| 0 | u64 | frame_offset | absolute; strictly greater than this page's own frame offset (§11.3) |
|
|
210
|
-
| 8 | u32 | page_index | the child page's global index (frame ordinal) — checksum seed, want dedup |
|
|
211
|
-
| 12 | u32 | fetch_size | `24 + 48·child.child_page_count + child.stored_size`, rounded up to 16 — the exact range to fetch |
|
|
212
|
-
| 16 | u32 | decoded_size | RAM budgeting before fetch; MUST equal the child frame's |
|
|
213
|
-
| 20 | u32 | reserved | |
|
|
214
|
-
| 24 | metric | metric | the child page's own metric (§6.2), copied — this is what makes a page testable *before* it is fetched; MUST equal that page's header metric (§11.11) |
|
|
215
|
-
|
|
216
|
-
The identity-seeded checksum binds the frame to *this page of this asset* and covers
|
|
217
|
-
the frame header fields, the child table, and the blob — a well-formed frame of the
|
|
218
|
-
wrong page, wrong asset, or wrong version fails verification instead of installing
|
|
219
|
-
silently. It also guards the traversal path itself: a corrupt child-table entry fetches
|
|
220
|
-
a range whose frame cannot checksum as the expected page index.
|
|
221
|
-
|
|
222
|
-
The next frame starts at `round_up(frame_offset + 24 + 48·child_page_count +
|
|
223
|
-
stored_size, 16)`. **Prefix scanning**: page indices are frame ordinals (file order ==
|
|
224
|
-
index order); scan sequentially and stop when the next aligned offset + 24 exceeds
|
|
225
|
-
`min(bytes_available, directory_offset)` — never rely on magic mismatch as a
|
|
226
|
-
terminator.
|
|
227
|
-
|
|
228
|
-
**Codecs.** `codec` is a property of one frame, not of the file: a writer picks per page
|
|
229
|
-
and an asset may carry a mixture, so a reader that handles the defined codecs handles
|
|
230
|
-
any file without asking what it was written with. That is what makes "compress unless it
|
|
231
|
-
would not shrink" expressible — the LZ4 worst case is about one byte in 255 plus a
|
|
232
|
-
token, and paying it to store bytes verbatim is a straight loss, so a page that does not
|
|
233
|
-
compress is written raw and says so.
|
|
234
|
-
|
|
235
|
-
A new codec id is a **per-asset capability gate, not a format break**, exactly as a new
|
|
236
|
-
`payload_encoding` is: an older reader meets a codec it has no decoder for and refuses
|
|
237
|
-
the asset instead of misreading it. `format_version` moves only when the container
|
|
238
|
-
layout itself changes, and adding a codec does not change it.
|
|
239
|
-
|
|
240
|
-
`1` is a **bare LZ4 block**, not an LZ4 frame: LZ4's own framing carries a magic, a
|
|
241
|
-
checksum and a content size that this frame already carries better, and `decoded_size`
|
|
242
|
-
is what the block is decoded against. Blocks are independent — no match reaches outside
|
|
243
|
-
the page — so a page decodes from its own bytes with no other page involved, which is
|
|
244
|
-
the same property residency already needs.
|
|
245
|
-
|
|
246
|
-
`decoded_size` is untrusted input, and readers allocate against it before anything can
|
|
247
|
-
contradict it. It MUST therefore be checked against what `stored_size` bytes could
|
|
248
|
-
physically produce under `codec` — exactly `stored_size` for raw, at most
|
|
249
|
-
`255·stored_size + 19` for LZ4 — *before* the allocation. A block that then decodes to
|
|
250
|
-
anything other than `decoded_size` MUST be rejected: a page truncated to a plausible
|
|
251
|
-
prefix is the one corruption that reads as a valid page with geometry missing.
|
|
252
|
-
|
|
253
|
-
**What it is worth, measured.** LZ4 over the pages of the Stanford models comes to
|
|
254
|
-
**1.12x on the bunny, 1.18x on the dragon and 1.14x on the 27M-triangle lucy** — pages
|
|
255
|
-
are >99% of a file, so that is very nearly the file ratio. That is modest, and the reason
|
|
256
|
-
is worth writing down because it says where the next win is rather than here:
|
|
257
|
-
|
|
258
|
-
| section | share of page bytes | lz4 |
|
|
259
|
-
|---|---:|---:|
|
|
260
|
-
| page header, group, node and cluster tables | 7% | 1.6x |
|
|
261
|
-
| payload | 93% | 1.09–1.15x |
|
|
262
|
-
|
|
263
|
-
The tables compress, and there are not enough of them to matter. The payload does not,
|
|
264
|
-
because under `SHADE_MESHLET_V1` it is float32 positions and packed attribute words —
|
|
265
|
-
high-entropy at the byte level, with no repetition for an LZ matcher to find. For
|
|
266
|
-
reference, on the same bytes `gzip -9` reaches 1.22x and `xz -9` 1.63x, so this is the
|
|
267
|
-
data resisting rather than the codec failing; an entropy coder buys a little more for a
|
|
268
|
-
lot more time. **The lever is `payload_encoding`, not `codec`** — quantized positions
|
|
269
|
-
(§12) shrink those bytes directly and leave the residue far more compressible.
|
|
270
|
-
|
|
271
|
-
What the reader pays is one block decode per page installed, into the buffer the page was
|
|
272
|
-
going to be copied into anyway: ~350–500 MB/s of decoded output from the JS decoder, so
|
|
273
|
-
about 0.6 ms for a 256 KB page.
|
|
274
|
-
|
|
275
|
-
## 6. Decoded page
|
|
276
|
-
|
|
277
|
-
```
|
|
278
|
-
[ PageHeader (56 B) ] [ Group table ] [ Node table ] [ Cluster records ] [ Payload ]
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
PageHeader:
|
|
282
|
-
|
|
283
|
-
| offset | type | field | notes |
|
|
284
|
-
|-------:|------|-----------------------|-------|
|
|
285
|
-
| 0 | u16 | group_count | ≥ 1; group table immediately follows the header |
|
|
286
|
-
| 2 | u16 | cluster_count | ≥ 1 |
|
|
287
|
-
| 4 | u8 | min_level | page band; non-root pages span one contiguous band |
|
|
288
|
-
| 5 | u8 | max_level | |
|
|
289
|
-
| 6 | u16 | node_count | ≥ 1; ≤ 2·`group_count` (§6.1) |
|
|
290
|
-
| 8 | u32 | cluster_table_offset | |
|
|
291
|
-
| 12 | u32 | payload_offset | |
|
|
292
|
-
| 16 | u32 | payload_size | |
|
|
293
|
-
| 20 | u32 | node_table_offset | = `56 + 8·group_count`; the node table follows the group table |
|
|
294
|
-
| 24 | [u8; 8] | reserved | |
|
|
295
|
-
| 32 | metric | metric | this page's own traversal metric (§6.2) — the root node's, repeated here so an installed page can be tested from itself |
|
|
296
|
-
|
|
297
|
-
Group table — `group_count` × 8 B. Groups are the atomic LOD/residency unit; because a
|
|
298
|
-
group never spans pages, installing/evicting a page carries whole groups by
|
|
299
|
-
construction — no global group index exists or is needed:
|
|
300
|
-
|
|
301
|
-
| offset | type | field | notes |
|
|
302
|
-
|-------:|------|----------------------|-------|
|
|
303
|
-
| 0 | u16 | cluster_first | index into this page's cluster records |
|
|
304
|
-
| 2 | u16 | cluster_count | ≥ 1; ≤ 4096 (format cap, §11.5) |
|
|
305
|
-
| 4 | u16 | parent_cluster_count | number of parent clusters referencing this group, `SAME_PAGE` references included; 0 exactly for the root page's topmost-level groups — drives activation (§10) |
|
|
306
|
-
| 6 | u16 | reserved | |
|
|
307
|
-
|
|
308
|
-
### 6.1 Node table (`node_count` × 32 B)
|
|
309
|
-
|
|
310
|
-
A tree over **this page's groups**, and nothing else. It is the part of the hierarchy below page
|
|
311
|
-
granularity, and it has no paging question of its own: it arrives with the page it describes,
|
|
312
|
-
leaves with it, and can never name anything that is not there.
|
|
313
|
-
|
|
314
|
-
| offset | type | field | notes |
|
|
315
|
-
|-------:|--------|-------------|-------|
|
|
316
|
-
| 0 | metric | metric | bounds everything under this node (§6.2) |
|
|
317
|
-
| 24 | u16 | child_first | first child — a node index when interior, a group index when a leaf |
|
|
318
|
-
| 26 | u16 | child_count | 1..4 |
|
|
319
|
-
| 28 | u16 | flags | bit 0: leaf (children are groups) |
|
|
320
|
-
| 30 | u16 | reserved | |
|
|
321
|
-
|
|
322
|
-
Node 0 is the root, always. Children occupy a **contiguous run**, and the tree is laid out
|
|
323
|
-
breadth-first, so an interior node's `child_first` is strictly greater than its own index — which
|
|
324
|
-
bounds any walk without a reader having to track one. Leaves **partition** the group table: every
|
|
325
|
-
group is reached through exactly one leaf, no group twice and none not at all. A page with a single
|
|
326
|
-
group still has a tree: one leaf node covering it, so a reader always starts at node 0 and never
|
|
327
|
-
special-cases.
|
|
328
|
-
|
|
329
|
-
Cost, measured across sphere assets from 3k to 98k triangles at page sizes from 8 KB to 256 KB: the
|
|
330
|
-
node table plus every metric copy runs **0.3%–1.6% of asset size**, and trees come out one to three
|
|
331
|
-
deep.
|
|
332
|
-
|
|
333
|
-
### 6.2 Traversal metric (24 B)
|
|
334
|
-
|
|
335
|
-
The same three fields wherever they appear — a child-table entry (§5), a page header (§6), a node
|
|
336
|
-
(§6.1):
|
|
337
|
-
|
|
338
|
-
| offset | type | field | notes |
|
|
339
|
-
|-------:|----------|------------------|-------|
|
|
340
|
-
| 0 | [f32; 4] | sphere | contains every bound anything covered carries |
|
|
341
|
-
| 16 | f32 | min_self_error | finest error covered |
|
|
342
|
-
| 20 | f32 | max_parent_error | coarsest parent error covered; `+∞` where the root is covered |
|
|
343
|
-
|
|
344
|
-
One sphere serves both the spatial test and the projection. It is the union of the covered clusters'
|
|
345
|
-
`parent_sphere`s, and monotonicity does the rest: `parent_sphere` contains `self_sphere`, which
|
|
346
|
-
contains the cluster's own vertices, so nothing under the node escapes it.
|
|
347
|
-
|
|
348
|
-
`max_parent_error` is the load-bearing number. A cluster is drawn only while `project(parent) > τ`,
|
|
349
|
-
so if the *largest* parent error under a node still projects to no more than τ, nothing under it can
|
|
350
|
-
be drawn and the entire subtree is skippable. `min_self_error` answers the other question — whether
|
|
351
|
-
anything here is drawable at all, or whether this is only a waypoint on the way to something finer —
|
|
352
|
-
which is what a prefetch ranks its wants by.
|
|
353
|
-
|
|
354
|
-
A group is the natural unit for all of this and needs no new geometry: every cluster of a group is
|
|
355
|
-
consumed by one step and therefore shares that step's `parent_sphere` and `parent_error`, which is
|
|
356
|
-
the same fact that makes the group the atomic LOD decision.
|
|
357
|
-
|
|
358
|
-
**The copy in a child-table entry is the point of the whole thing.** It is what a traversal reads
|
|
359
|
-
*before* fetching a page, and without it the only way to learn a page was not wanted is to fetch and
|
|
360
|
-
decode it. Being a copy, it can drift; §11.11 requires it to match the page's own.
|
|
361
|
-
|
|
362
|
-
## 7. Cluster record (112 bytes)
|
|
363
|
-
|
|
364
|
-
Everything the runtime cut rule, culling, wants, and upload need — denormalized per
|
|
365
|
-
cluster so selection reads one record. Two kinds of spheres, deliberately distinct: the
|
|
366
|
-
**LOD-metric pair** (`self_sphere`/`parent_sphere` — shared per group step so all
|
|
367
|
-
siblings project identical values, monotonically inflated, never a tight fit) and the
|
|
368
|
-
**culling bounds** (`bounds_sphere`/`aabb` — this cluster's own tight fits, never used
|
|
369
|
-
in the cut test):
|
|
370
|
-
|
|
371
|
-
| offset | type | field | notes |
|
|
372
|
-
|-------:|----------|-----------------|-------|
|
|
373
|
-
| 0 | [f32; 4] | self_sphere | LOD-metric sphere (center xyz + radius) of the group step that created this cluster; leaves: equals `bounds_sphere` |
|
|
374
|
-
| 16 | f32 | self_error | object-space `r_e`; leaves: 0 |
|
|
375
|
-
| 20 | f32 | parent_error | error of the step that consumed it; roots: +∞ |
|
|
376
|
-
| 24 | [f32; 4] | parent_sphere | LOD-metric sphere of the consuming step; roots: duplicate of self_sphere |
|
|
377
|
-
| 40 | [f32; 4] | bounds_sphere | this cluster's own minimal bounding sphere (miniball), object-space — culling |
|
|
378
|
-
| 56 | [f32; 6] | aabb | this cluster's object-space AABB — culling, GPU metadata `bounds_box`, and the (future) dequantization grid |
|
|
379
|
-
| 80 | u16 | child_ref | index into this frame's child table; `SAME_PAGE` when the child group is in this page; `NO_CHILD` for leaves |
|
|
380
|
-
| 82 | u16 | child_group | group index within the child page (or this page, for `SAME_PAGE`); `NO_GROUP` for leaves |
|
|
381
|
-
| 84 | u32 | cone_reserved | reserved for backface-cone culling — **write 0**. No cull pass consumes a cone today and the producer needs a `BinaryTopology` port; the sub-encoding is pinned together with that pass, not before |
|
|
382
|
-
| 88 | u32 | encoding_flags | frozen bit table in §8 |
|
|
383
|
-
| 92 | u32 | payload_offset | into this page's payload section; ≡ 0 (mod 4) |
|
|
384
|
-
| 96 | u32 | payload_size | bytes; ≡ 0 (mod 4) |
|
|
385
|
-
| 100 | u8 | vertex_count | 3 ≤ n ≤ 128 |
|
|
386
|
-
| 101 | u8 | triangle_count | 1 ≤ n ≤ 128 |
|
|
387
|
-
| 102 | u16 | reserved | |
|
|
388
|
-
| 104 | u64 | reserved | |
|
|
389
|
-
|
|
390
|
-
Monotonicity (`parent_error ≥ self_error`, `parent_sphere ⊇ self_sphere`) is a build
|
|
391
|
-
invariant, not a reader concern. A single-cluster asset is valid: one root page, one
|
|
392
|
-
group with `parent_cluster_count = 0`, one cluster with `parent_error = +∞`,
|
|
393
|
-
`child_ref = NO_CHILD`, `child_page_count = 0`.
|
|
394
|
-
|
|
395
|
-
## 8. Payload encoding
|
|
396
|
-
|
|
397
|
-
`payload_encoding = 1` (`SHADE_MESHLET_V1`). **Byte-compat scope**: the payload block is
|
|
398
|
-
byte-compatible with `GPUMeshletManager`'s **data pool** — uploading it is a copy. The
|
|
399
|
-
40-byte GPU metadata rows (`MESHLET_METADATA_STRUCT`: bounds_box, address,
|
|
400
|
-
primitive_count, vertex_count, flags) are **synthesized at install** from the cluster
|
|
401
|
-
record (aabb → bounds_box, counts widened to u32, `address = slot_base_word +
|
|
402
|
-
payload_offset/4`, flags = encoding_flags) — a small pack step that is part of the
|
|
403
|
-
design's "VRAM paging mechanism is new work", not an existing patch path.
|
|
404
|
-
|
|
405
|
-
Payload block layout:
|
|
406
|
-
|
|
407
|
-
1. Index section: `triangle_count × 3` local u8 indices, zero-padded to a 4-byte word
|
|
408
|
-
boundary.
|
|
409
|
-
2. Attribute sections, in the frozen order below, each `words × vertex_count` u32
|
|
410
|
-
words — unless its `encoding_flags` bit marks it constant-compressed, in which case
|
|
411
|
-
exactly `words` u32s are stored once.
|
|
412
|
-
|
|
413
|
-
Frozen tables (byte-identical to Shade's `ENCODED_ORDERED_ATTRIBUTES`,
|
|
414
|
-
`ENCODED_ATTRIBUTE_SIZES`, `MESHLET_METADATA_FLAGS` as of this writing — the spec, not
|
|
415
|
-
the source, is now the authority for `.vgeo` files):
|
|
416
|
-
|
|
417
|
-
| # | attribute | words/vertex | encoding | flags bit (constant-compressed) | mask bit |
|
|
418
|
-
|---|-----------|-------------:|----------------------------|-------------------------------:|---------:|
|
|
419
|
-
| 0 | position | 3 | raw f32×3 | — (never compressed) | 0 |
|
|
420
|
-
| 1 | normal | 1 | octahedral u32 | 1 (0x01) | 1 |
|
|
421
|
-
| 2 | tangent | 1 | packed u32 | 2 (0x02) | 2 |
|
|
422
|
-
| 3 | color | 1 | RGBA8 u32 | 4 (0x04) | 3 |
|
|
423
|
-
| 4 | uv0 | 2 | raw f32×2 | 8 (0x08) | 4 |
|
|
424
|
-
| 5 | uv1 | 1 | 2×unorm16 u32 | 16 (0x10) | 5 |
|
|
425
|
-
|
|
426
|
-
- `encoding_flags` bits 5 (0x20, skinning joints) and 6 (0x40, skinning weights) MUST
|
|
427
|
-
be clear, and **no skinning sections are stored** — `SHADE_MESHLET_V1` payloads end
|
|
428
|
-
at uv1. (Load-bearing note: skinning attributes are last in Shade's attribute order
|
|
429
|
-
and the static decode path never addresses them, which is exactly what makes their
|
|
430
|
-
omission safe. VG is static-only, design §9.)
|
|
431
|
-
- All other `encoding_flags` bits are reserved, MUST be 0.
|
|
432
|
-
- An attribute the source lacks still ships its section, constant-compressed to the
|
|
433
|
-
engine default — **sections are never omitted**; `vertex_attribute_mask` is advisory
|
|
434
|
-
(which attributes carry real data). True section omission would shift every following
|
|
435
|
-
offset and is only expressible as a new `payload_encoding` id.
|
|
436
|
-
|
|
437
|
-
Quantized positions land as a **new `payload_encoding` id** (plus a page codec if
|
|
438
|
-
entropy coding pays). The cluster record already carries the dequantization grid
|
|
439
|
-
(`aabb`).
|
|
440
|
-
|
|
441
|
-
## 9. Page directory (auxiliary)
|
|
442
|
-
|
|
443
|
-
Flat array of `total_pages` 32 B records at `directory_offset`; record `i` describes
|
|
444
|
-
page index `i` (page index order == file order == coarse-first). Auxiliary and fully
|
|
445
|
-
derivable from the frames (§3) — standard runtime traversal never reads it.
|
|
446
|
-
|
|
447
|
-
| offset | type | field | notes |
|
|
448
|
-
|-------:|------|----------------|-------|
|
|
449
|
-
| 0 | u64 | frame_offset | absolute; frame per §5 |
|
|
450
|
-
| 8 | u32 | fetch_size | as in the child table: the exact byte range to fetch is `[frame_offset, frame_offset + fetch_size)` |
|
|
451
|
-
| 12 | u32 | decoded_size | MUST equal the frame's |
|
|
452
|
-
| 16 | u8 | min_level | |
|
|
453
|
-
| 17 | u8 | max_level | |
|
|
454
|
-
| 18 | u16 | flags | bit 0: root page |
|
|
455
|
-
| 20 | u16 | group_count | |
|
|
456
|
-
| 22 | u16 | cluster_count | |
|
|
457
|
-
| 24 | u64 | reserved | |
|
|
458
|
-
|
|
459
|
-
**Directory integrity**: `dir_block_checksums` holds one xxh3-64 per 128 directory
|
|
460
|
-
records (one 4 KB block), seed = `asset_id_high64 XOR block_index`. Readers that use
|
|
461
|
-
the directory fetch it at block granularity and MUST verify.
|
|
462
|
-
|
|
463
|
-
## 10. Reader requirements
|
|
464
|
-
|
|
465
|
-
Standard runtime operation is **pure traversal** — the directory is not involved:
|
|
466
|
-
|
|
467
|
-
- Cold start: fetch `[0, 256)`, verify `header_checksum`, magic, versions (§4 reject
|
|
468
|
-
rules), then fetch `[root_page_offset, root_page_offset + root_page_fetch_size)` — the
|
|
469
|
-
level table (§4.1) sits between the two, so a head prefix covering both brings the whole
|
|
470
|
-
always-resident set in one request. The root frame's `decoded_size` MUST equal
|
|
471
|
-
`root_page_decoded_size` and its frame extent MUST match `root_page_fetch_size`, else
|
|
472
|
-
reject. Or speculatively fetch one larger head prefix — coarse-first layout makes every
|
|
473
|
-
prefix byte useful.
|
|
474
|
-
- **Refinement**: a want is a `child_ref` in an installed page; its child-table entry
|
|
475
|
-
carries the exact byte range — one round-trip per cold page, no metadata fetch ever.
|
|
476
|
-
Wants dedup on `page_index` across clusters, groups, and instances. A want whose
|
|
477
|
-
target page is **already installed** resolves as an activation recheck of the
|
|
478
|
-
referenced group (below), never a fetch.
|
|
479
|
-
- **Activation (closure without dependency lists)** — the selectable invariant:
|
|
480
|
-
|
|
481
|
-
*A group `g` is selectable iff every one of its `parent_cluster_count` references is
|
|
482
|
-
live — the referencing cluster's page is installed and that cluster's own group is
|
|
483
|
-
selectable. Groups with `parent_cluster_count = 0` (exactly the root page's topmost
|
|
484
|
-
level) are selectable at install.*
|
|
485
|
-
|
|
486
|
-
By induction, a selectable cluster's entire ancestor cone is installed and
|
|
487
|
-
selectable — the closure the cut rule needs, restored by a per-group counter instead
|
|
488
|
-
of dependency lists. Runtime bookkeeping: each resident group keeps a live-reference
|
|
489
|
-
counter; when a group becomes selectable, its clusters' references (child-table and
|
|
490
|
-
`SAME_PAGE` alike) increment the referenced groups' counters — cascading
|
|
491
|
-
transitively; installing a page counts the existing live references into it (the
|
|
492
|
-
runtime maintains a reverse-reference index for pending pages — the same structure
|
|
493
|
-
that carries wants). Counters only grow while the pages involved stay resident (the
|
|
494
|
-
eviction rule below guarantees referencing parents outlive children). Activation
|
|
495
|
-
flips whole groups; the cut rule's clamp reads *selectable*, not merely resident
|
|
496
|
-
(design §4/§6): resident-but-inactive groups draw nothing, their coarser selectable
|
|
497
|
-
ancestors keep covering that surface — **no holes and no double-draw, in any arrival
|
|
498
|
-
order**, because a group never draws before all pages holding its parents are
|
|
499
|
-
installed and selectable.
|
|
500
|
-
- **In-flight protection**: a fetch discovered through parent page P pins P until the
|
|
501
|
-
child installs — known at queue time, purely local. Arrivals verify the
|
|
502
|
-
identity-seeded frame checksum; activation makes any arrival order safe beyond that.
|
|
503
|
-
- **Eviction**: within each residency tier, a page is evictable only while it has no
|
|
504
|
-
resident child pages in that tier — checked against its own child table (`SAME_PAGE`
|
|
505
|
-
references never pin). Leaves-first order emerges from the rule; the root page is
|
|
506
|
-
pinned.
|
|
507
|
-
- Verify every ranged response is `206` with the requested `Content-Range`; a `200`
|
|
508
|
-
means the server ignored the range — abort the transfer immediately (design §6).
|
|
509
|
-
- Verify frame checksums (identity-seeded, §5) before decode, and `decoded_size`
|
|
510
|
-
against the child-table entry used to fetch and against the codec's decode bound
|
|
511
|
-
(§5) before allocating for it. On mismatch: bounded retries with
|
|
512
|
-
backoff, then **quarantine** the page — the clamped cut keeps a coarse stand-in
|
|
513
|
-
correct indefinitely — and surface telemetry. Never retry-loop: corruption at a
|
|
514
|
-
content-addressed URL is deterministic.
|
|
515
|
-
- After install, stamp each cluster's selection row with its own page index and its
|
|
516
|
-
child page index/group (touch and want emission, design §6/§7).
|
|
517
|
-
- Fetch batching: coalesce adjacent wanted pages into contiguous single ranges; ranges
|
|
518
|
-
never cross a band boundary by construction (coarse-first ordering), so coalescing
|
|
519
|
-
lives within bands — the within-band spatial curve (§12) is what carries fetch
|
|
520
|
-
locality and must be chosen with that as a criterion. Fetching through small unwanted
|
|
521
|
-
gaps is permitted under an implementation waste threshold.
|
|
522
|
-
- Never assume `nominal_page_size`; per-page sizes come from child tables (traversal),
|
|
523
|
-
frames (prefix scan), or the directory (special tasks).
|
|
524
|
-
|
|
525
|
-
Build consequence (accepted): child tables hold downstream offsets — the format is
|
|
526
|
-
optimized for reading, and the builder pays for it. Preferred strategy: emit frames
|
|
527
|
-
with placeholder child tables, then **backpatch** them once all offsets are known, and
|
|
528
|
-
finalize frame checksums last (the checksum covers the child table). Computing the full
|
|
529
|
-
layout up front (compress all blobs → prefix-sum offsets → one forward emit) is equally
|
|
530
|
-
valid. Both are cheap and non-circular **because child tables are plaintext in the
|
|
531
|
-
frame**: a frame's extent (`24 + 48·children + stored_size`, with `stored_size` the
|
|
532
|
-
blob's compressed size) never depends on the offset values, and patching plaintext
|
|
533
|
-
bytes needs no re-compression. Build times are non-interactive by expectation —
|
|
534
|
-
clustering and simplification dominate regardless.
|
|
535
|
-
|
|
536
|
-
## 11. Build invariants (validated at build, assumed by readers)
|
|
537
|
-
|
|
538
|
-
1. A group's clusters are contiguous in one page (`cluster_first/cluster_count`); a
|
|
539
|
-
group never spans pages. Non-root pages span a single contiguous level band.
|
|
540
|
-
2. Child tables are exact: deduplicated, one entry per distinct **other** page
|
|
541
|
-
referenced by this page's clusters (`SAME_PAGE` references appear in no child
|
|
542
|
-
table); every `child_ref`/`child_group` resolves to a valid entry and group;
|
|
543
|
-
`frame_offset`/`fetch_size`/`decoded_size` agree with the referenced frame and the
|
|
544
|
-
directory (all referencing pages agree by construction).
|
|
545
|
-
3. Acyclicity and reachability: every child-table `frame_offset` is strictly greater
|
|
546
|
-
than the owning page's frame offset (file order is topological), and every page is
|
|
547
|
-
reachable from the root page through child tables.
|
|
548
|
-
4. File order (== page index order) is coarse-first: the root page first, bands by
|
|
549
|
-
descending level, spatial locality within a band. The root page contains the
|
|
550
|
-
complete topmost level(s) — at minimum a complete drawable cut of the DAG. A
|
|
551
|
-
cluster's child group is always in a page whose band tops out strictly below its own
|
|
552
|
-
page's, unless the reference is `SAME_PAGE`.
|
|
553
|
-
5. Group size: `1 ≤ cluster_count ≤ 4096` (format cap; builders target far less —
|
|
554
|
-
design §3 grouping is adaptive from ~4). `parent_cluster_count` equals the exact
|
|
555
|
-
number of clusters (across all pages, `SAME_PAGE` included) whose
|
|
556
|
-
`child_ref/child_group` name this group; it is 0 exactly for the root page's
|
|
557
|
-
topmost-level groups. A page holding one indivisible oversized group MAY exceed
|
|
558
|
-
`nominal_page_size`; the hard bound is the frame's u32 `stored_size`.
|
|
559
|
-
6. `1 ≤ triangle_count ≤ 128`, `3 ≤ vertex_count ≤ 128` (Shade meshlet limits);
|
|
560
|
-
`total_clusters ≥ 1`; `source_vertex_count ≥ 3`, `source_face_count ≥ 1`.
|
|
561
|
-
7. Error/sphere monotonicity per design §4; `self_error = 0` and `child_ref = NO_CHILD`
|
|
562
|
-
exactly for leaves; `parent_error = +∞` exactly for **the** root — there is exactly
|
|
563
|
-
one, and it is in page 0. Several parentless clusters would be several entry points,
|
|
564
|
-
and the cut only ever enters at one; it is also what an unconverged build leaves
|
|
565
|
-
behind, which is the likelier cause. All floats NaN-free.
|
|
566
|
-
`bounds_sphere` and `aabb` contain the cluster's decoded vertices; the header's
|
|
567
|
-
`object_sphere` and `object_bounds` contain the normalized source mesh.
|
|
568
|
-
8. Payload offsets and sizes are 4-byte multiples; every payload decodes/uploads
|
|
569
|
-
against `payload_encoding` with no external state beyond its own cluster record.
|
|
570
|
-
A leaf's `self_error` of 0 is only as honest as the simplifier's metric — see design
|
|
571
|
-
§2, boundary constraint quadrics — and no reader-side check can distinguish an
|
|
572
|
-
exact coarse cluster from one whose error went unrecorded.
|
|
573
|
-
9. `asset_id` and `header_checksum` verify per §4 — including its zeroing rule, which excludes
|
|
574
|
-
every derived checksum field; every frame verifies per §5; the directory verifies per §9 and
|
|
575
|
-
byte-for-byte matches what a frame scan reconstructs. `header_checksum` covers bytes 0–255
|
|
576
|
-
only, so the level table's integrity rests on `asset_id`, which covers the whole file.
|
|
577
|
-
10. Every page's node table is a tree over exactly that page's groups: node 0 is the root, an
|
|
578
|
-
interior node's children are a contiguous run at a strictly greater index, `1 ≤ child_count ≤ 4`,
|
|
579
|
-
and the leaves partition the group table — each group reached through exactly one leaf. Each
|
|
580
|
-
node's metric bounds its whole subtree: its sphere contains every child's, its `min_self_error`
|
|
581
|
-
is no greater than any child's, its `max_parent_error` no less. The page header's metric equals
|
|
582
|
-
the root node's.
|
|
583
|
-
11. Every child-table entry's metric equals the header metric of the page it names. It is a copy
|
|
584
|
-
read before that page is fetched, so nothing else can catch it having drifted — and a traversal
|
|
585
|
-
that trusts a stale one skips a page it needed and leaves a hole.
|
|
586
|
-
12. Every frame names a defined `codec` (§5); a raw frame's `stored_size` equals its
|
|
587
|
-
`decoded_size`; and no frame's `decoded_size` exceeds what its codec could produce from
|
|
588
|
-
`stored_size` bytes. Every blob decodes to exactly `decoded_size` — a short decode is a
|
|
589
|
-
truncated page, and a page truncated to a plausible prefix is the one corruption that reads
|
|
590
|
-
as valid geometry with pieces missing.
|
|
591
|
-
13. `root_page_offset = align16(256 + 32 · level_count)`; the level table's `cluster_count` and
|
|
592
|
-
`group_count` columns sum to `total_clusters` and `total_groups`; every level holds at least
|
|
593
|
-
one cluster and one group; `min_error ≤ max_error`, both finite and ≥ 0.
|
|
594
|
-
|
|
595
|
-
## 12. Open
|
|
596
|
-
|
|
597
|
-
- Page codec ids beyond raw and LZ4 (§5). LZ4 is the default and is where the cheap
|
|
598
|
-
ratio is; a slower, denser codec (meshopt-style over the payload, deflate-family over
|
|
599
|
-
the tables) is a per-frame `codec` id away and costs no reader that already handles a
|
|
600
|
-
mixture. The quantized-position `payload_encoding` is the other half of the same
|
|
601
|
-
question, and would take most of what LZ4 currently finds.
|
|
602
|
-
- Default `nominal_page_size` (design §5: order hundreds of KB, measured).
|
|
603
|
-
- Spatial ordering curve within a level band (Morton over group centroids is the
|
|
604
|
-
default candidate; chosen with fetch-coalescing locality as an explicit criterion,
|
|
605
|
-
§10).
|
|
606
|
-
- Backface-cone cull pass and, with it, the `cone_reserved` sub-encoding.
|
|
607
|
-
- Multi-geometry containers (v1: one geometry per file; scenes reference many files).
|
|
1
|
+
# `.vgeo` — Virtual Geometry Container Format
|
|
2
|
+
|
|
3
|
+
Status: **writer and validator implemented; no reader yet.** Companion to
|
|
4
|
+
[VIRTUAL_GEOMETRY_DESIGN.md](./VIRTUAL_GEOMETRY_DESIGN.md); every requirement pinned in
|
|
5
|
+
its §5/§6 is realized here as a concrete field or invariant. Pinned structure below;
|
|
6
|
+
open details are listed at the end. One `.vgeo` file = one unique geometry's complete
|
|
7
|
+
cluster DAG; instances share the file.
|
|
8
|
+
|
|
9
|
+
The implementation lives beside this document: `format/` is the container — what a file is,
|
|
10
|
+
how one is written, and `vgeo_validate_container.js`, which audits every §11 invariant in
|
|
11
|
+
one — and `build/` is the pipeline that produces it from a `Geometry`, glTF front end
|
|
12
|
+
included. The node command line over both is at `tools/geometry/virtual/`. One glTF yields **one file per
|
|
13
|
+
primitive**, in object space, with the scene's placements written to a sidecar manifest
|
|
14
|
+
rather than baked in. The runtime side (pager, residency, cut pass) is still design only.
|
|
15
|
+
|
|
16
|
+
## 1. Design constraints (inherited, binding)
|
|
17
|
+
|
|
18
|
+
- **Geometry only.** `.vgeo` carries geometry and its vertex attributes — nothing else.
|
|
19
|
+
Materials are orthogonal, engine-side concerns; a multi-material source splits into
|
|
20
|
+
one geometry per material before it reaches the DAG builder — for glTF that split is
|
|
21
|
+
free, since a primitive already carries exactly one material, and the converter's
|
|
22
|
+
front-end emits one file per primitive. The format has no material fields.
|
|
23
|
+
- Billions of source triangles per asset: 64-bit file offsets, 32-bit page indices.
|
|
24
|
+
- Immutable, content-addressed; perfect HTTP/CDN caching; fetched by single-range
|
|
25
|
+
requests.
|
|
26
|
+
- Fetch unit = size-bounded **page**, independently decodable; a group never spans pages.
|
|
27
|
+
- No separate global hierarchy: cluster metadata travels **in** pages, so the hierarchy
|
|
28
|
+
streams with the geometry it describes.
|
|
29
|
+
- **Traversal-first**: a page carries everything needed to fetch the pages it refines
|
|
30
|
+
into. Standard runtime operation is header → root page → page-to-page traversal; the
|
|
31
|
+
directory is auxiliary (tooling, validation, arbitrary-page access), never a hot-path
|
|
32
|
+
dependency.
|
|
33
|
+
- Time-to-first-pixel = header + root page, O(1) in asset size.
|
|
34
|
+
- Prefix-readable: a plain byte-prefix of the file is a complete coarse asset.
|
|
35
|
+
- Per-page compression inside the container only; transparent HTTP compression is
|
|
36
|
+
assumed absent (it does not compose with range requests).
|
|
37
|
+
- The page DAG is acyclic by construction: child references point strictly forward in
|
|
38
|
+
the file.
|
|
39
|
+
|
|
40
|
+
## 2. Conventions
|
|
41
|
+
|
|
42
|
+
- Little-endian throughout. Types: `u8 u16 u32 u64 f32`; `[T; N]` = N-element array.
|
|
43
|
+
- All file offsets are absolute byte offsets from file start. All in-page offsets are
|
|
44
|
+
byte offsets from the start of the **decoded** page.
|
|
45
|
+
- **Frames** (stored pages) start at 16-byte-aligned file offsets; `directory_offset`
|
|
46
|
+
is 16-aligned; alignment padding is real bytes in the file. Inside a decoded page,
|
|
47
|
+
all tables and payload sections are 4-byte aligned (Shade's pools are u32-word
|
|
48
|
+
addressed).
|
|
49
|
+
- Levels are numbered `0 = leaves`, increasing toward the root. "Coarser" = higher
|
|
50
|
+
level. A page's **band** is a contiguous level range `min_level..max_level`.
|
|
51
|
+
A level is a **group** ordinal, not a per-cluster depth: it says which band a group
|
|
52
|
+
sits in, and a group's clusters may sit at several different depths in the DAG,
|
|
53
|
+
because a cluster the builder had no use for is carried forward untouched rather than
|
|
54
|
+
coarsened for the sake of symmetry. Cluster records carry no level, and nothing needs
|
|
55
|
+
one. What the ordinal guarantees is the property file order depends on: **every group
|
|
56
|
+
is in a strictly lower band than the group holding its parents**, so pages laid out by
|
|
57
|
+
descending band make every child reference point forward.
|
|
58
|
+
- Sentinels for cluster `child_ref`: `NO_CHILD = 0xFFFF` (leaves),
|
|
59
|
+
`SAME_PAGE = 0xFFFE` (child group lives in this page — legal only in multi-level
|
|
60
|
+
pages, the root page included); valid child-table indices are `≤ 0xFFFD`. Cluster
|
|
61
|
+
`child_group`: `NO_GROUP = 0xFFFF`, exactly for leaves. All `f32` fields are NaN-free.
|
|
62
|
+
Error values are finite `≥ 0`, except the root's parent error which is `+∞` (f32
|
|
63
|
+
infinity).
|
|
64
|
+
- Reserved fields: writers MUST write 0; readers MUST ignore their contents.
|
|
65
|
+
- Hashing is xxHash3; a `hash_algo` id is reserved for future change. **Integrity
|
|
66
|
+
model**: identity-seeded per-frame checksums are the *operative client-side*
|
|
67
|
+
mechanism — and because all DAG edges (child tables, cluster records) live inside
|
|
68
|
+
frames, the traversal path is covered by them end to end; the header and the
|
|
69
|
+
directory carry their own checksums; `asset_id` is whole-file and
|
|
70
|
+
*publisher/pipeline/cache-side* — a range-fetching client never reads the whole file
|
|
71
|
+
and can never verify it. None of these are a security boundary — they defend against
|
|
72
|
+
truncation, corruption, version skew, and cache mixups, not attackers.
|
|
73
|
+
|
|
74
|
+
## 3. Top-level layout
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
[ Header (256 B) ]
|
|
78
|
+
[ Level table ] ← level_count × 32 B, §4.1
|
|
79
|
+
[ Root page frame ] ← always-resident set = header + table + this
|
|
80
|
+
[ Page frames, coarse-first band order ] ← prefix of the file = coarse asset
|
|
81
|
+
[ Page directory ] ← flat 32 B records, range-fetchable
|
|
82
|
+
[ Directory block checksums ] ← u64 per 128 records (4 KB block)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The frame region is **exactly** `[root_page_offset, directory_offset)` — that is the
|
|
86
|
+
normative end-of-frames rule (see §5). Its start is a header field rather than a constant
|
|
87
|
+
because the level table (§4.1) precedes it and its size depends on the build. The directory is **derived data**: every field in it is
|
|
88
|
+
reconstructible by scanning frames and decoding page headers. It exists for special
|
|
89
|
+
tasks — tooling, validation, RAM budgeting before fetch, resuming from a disk cache,
|
|
90
|
+
jumping to an arbitrary page without walking the DAG — and standard runtime traversal
|
|
91
|
+
never touches it. Random-access readers fetch directory slices on demand: record `i`
|
|
92
|
+
lives at exactly `directory_offset + 32·i`.
|
|
93
|
+
|
|
94
|
+
## 4. Header (256 bytes, fixed)
|
|
95
|
+
|
|
96
|
+
All u64/u128 fields are naturally 8-byte aligned.
|
|
97
|
+
|
|
98
|
+
| offset | type | field | notes |
|
|
99
|
+
|-------:|-----------|--------------------------|-------|
|
|
100
|
+
| 0 | u32 | magic | `'VGEO'` = 0x4F454756 |
|
|
101
|
+
| 4 | u16 | format_version | breaking layout changes only |
|
|
102
|
+
| 6 | u16 | min_reader_version | reader MUST reject if its version is lower |
|
|
103
|
+
| 8 | u16 | header_size | = 256 |
|
|
104
|
+
| 10 | u8 | hash_algo | 0 = xxHash3; readers MUST reject unknown values |
|
|
105
|
+
| 11 | u8 | reserved | |
|
|
106
|
+
| 12 | u32 | feature_flags_required | readers MUST reject any unknown set bit |
|
|
107
|
+
| 16 | u32 | feature_flags_ignorable | readers MUST ignore unknown set bits |
|
|
108
|
+
| 20 | u32 | payload_encoding | 1 = `SHADE_MESHLET_V1` (§8); readers MUST reject unknown values |
|
|
109
|
+
| 24 | [u8; 16] | asset_id | xxh3-128 of the whole file with every **derived checksum field** zeroed (see below); stored low64 LE at bytes 0–7, high64 LE at bytes 8–15 |
|
|
110
|
+
| 40 | u32 | vertex_attribute_mask | advisory attribute presence (§8 bit table) |
|
|
111
|
+
| 44 | u32 | total_pages | = directory record count |
|
|
112
|
+
| 48 | u64 | total_clusters | ≥ 1 |
|
|
113
|
+
| 56 | u64 | total_groups | ≥ 1 |
|
|
114
|
+
| 64 | u64 | root_page_offset | = `align16(256 + 32 · level_count)` — the level table (§4.1) sits between |
|
|
115
|
+
| 72 | u32 | root_page_fetch_size | same definition as child-table/directory `fetch_size`, for page 0 |
|
|
116
|
+
| 76 | u32 | root_page_decoded_size | RAM admission for the always-resident set, known from the header alone |
|
|
117
|
+
| 80 | u64 | directory_offset | also the exact end of the frame region |
|
|
118
|
+
| 88 | u64 | dir_block_checksums_offset | `ceil(total_pages / 128)` × u64 |
|
|
119
|
+
| 96 | u32 | nominal_page_size | build parameter, bytes; informational — readers MUST NOT assume (§11.5 exception) |
|
|
120
|
+
| 100 | u16 | reserved | |
|
|
121
|
+
| 102 | u8 | level_count | levels `0..level_count-1` |
|
|
122
|
+
| 103 | u8 | reserved | |
|
|
123
|
+
| 104 | u64 | source_vertex_count | vertices of the normalized source mesh (post-weld) the leaves represent |
|
|
124
|
+
| 112 | u64 | source_face_count | triangles of the normalized source mesh |
|
|
125
|
+
| 120 | [f32; 4] | object_sphere | object-space minimal bounding sphere (center xyz, radius) of the whole geometry |
|
|
126
|
+
| 136 | [f32; 6] | object_bounds | object-space AABB (min xyz, max xyz); instances transform at runtime |
|
|
127
|
+
| 160 | [u8; 88] | reserved | |
|
|
128
|
+
| 248 | u64 | header_checksum | xxh3-64 of bytes 0–255 with this field zeroed (`asset_id` already final) |
|
|
129
|
+
|
|
130
|
+
### 4.1 Level table (`level_count` × 32 B, immediately after the header)
|
|
131
|
+
|
|
132
|
+
Statistics per level, at `256 + 32·i`, ending where the root page frame begins. Small —
|
|
133
|
+
a hundred levels is 3.2 KB — so a single fetch of the file's head brings the header, the
|
|
134
|
+
whole table, and the always-resident root page together, and the table is available before
|
|
135
|
+
any page has been decoded.
|
|
136
|
+
|
|
137
|
+
| offset | type | field | notes |
|
|
138
|
+
|-------:|------|-------------------|-------|
|
|
139
|
+
| 0 | f32 | min_error | smallest object-space `r_e` any cluster of this level carries |
|
|
140
|
+
| 4 | f32 | max_error | largest |
|
|
141
|
+
| 8 | f32 | max_sphere_radius | largest LOD-metric sphere radius at this level |
|
|
142
|
+
| 12 | u32 | cluster_count | ≥ 1 |
|
|
143
|
+
| 16 | u32 | group_count | groups sitting in this band; ≥ 1 |
|
|
144
|
+
| 20 | u32 | triangle_count | |
|
|
145
|
+
| 24 | u64 | reserved | |
|
|
146
|
+
|
|
147
|
+
What it is for: an instance's level range can be **bracketed** from the errors and radii
|
|
148
|
+
alone — the coarsest level that still passes the threshold at the instance's near point,
|
|
149
|
+
the finest that could be wanted at its far one — without reading a cluster record or
|
|
150
|
+
fetching a page. That is what lets a scene of ten thousand identical parts resolve to a
|
|
151
|
+
handful of distinct cuts instead of ten thousand of them, and what lets a prefetch name
|
|
152
|
+
exactly the bands a bracket spans.
|
|
153
|
+
|
|
154
|
+
These are facts about the build, not a policy. In particular **`max_error` is not monotonic
|
|
155
|
+
in the level**: a round merges an error band, and a later round can produce a cluster finer
|
|
156
|
+
than an earlier one did, by finally reaching geometry that had been waiting for a partner.
|
|
157
|
+
A reader that wants a monotonic bound takes a running maximum from the coarsest end; that
|
|
158
|
+
is the reader's choice and not the file's.
|
|
159
|
+
|
|
160
|
+
`cluster_count` and `group_count` sum to the header's `total_clusters` and `total_groups`,
|
|
161
|
+
which is the cross-check that keeps the table from drifting from the pages.
|
|
162
|
+
|
|
163
|
+
**What `asset_id` covers.** The whole file, with these fields treated as zero: `asset_id` itself,
|
|
164
|
+
`header_checksum`, every frame's `checksum` (§5), and the entire `dir_block_checksums` region (§9).
|
|
165
|
+
Excluding the last two is what breaks the circle — the frame checksums are seeded from
|
|
166
|
+
`asset_id_low64` and the directory block checksums from `asset_id_high64`, so covering them would
|
|
167
|
+
make the identity a function of itself. Nothing is lost by the exclusion: every one of those fields
|
|
168
|
+
is a function of content the hash still covers, so any change to the asset still moves `asset_id`.
|
|
169
|
+
|
|
170
|
+
Build order, and the order a verifier repeats: zero those fields → hash → write `asset_id` →
|
|
171
|
+
compute and write the frame and directory-block checksums it seeds → compute and write
|
|
172
|
+
`header_checksum` over bytes 0–255 with only that field zeroed.
|
|
173
|
+
|
|
174
|
+
The asset filename MUST be derived from `asset_id` in streamed deployments (content
|
|
175
|
+
addressing is what makes same-URL version skew impossible; every client-side integrity
|
|
176
|
+
property leans on it). The field is authoritative, the name is the enforcement.
|
|
177
|
+
|
|
178
|
+
A new `payload_encoding` (e.g. quantized positions) is a **per-asset capability gate,
|
|
179
|
+
not a format break**: old readers cleanly reject the asset instead of misreading it;
|
|
180
|
+
`format_version` moves only when the container layout itself changes.
|
|
181
|
+
|
|
182
|
+
## 5. Page frame (stored page)
|
|
183
|
+
|
|
184
|
+
Every page — root included — is stored as a self-delimiting frame:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
[ FrameHeader (24 B) ] [ Child table (plaintext) ] [ blob (codec-encoded) ]
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
| offset | type | field | notes |
|
|
191
|
+
|-------:|------|------------------|-------|
|
|
192
|
+
| 0 | u32 | magic | `'VGPG'` = 0x47504756 |
|
|
193
|
+
| 4 | u8 | codec | 0 = raw, 1 = one LZ4 block; applies to the blob only; readers MUST reject unknown values |
|
|
194
|
+
| 5 | u8 | flags | 0 |
|
|
195
|
+
| 6 | u16 | child_page_count | entries in the child table; 0 for all-leaf pages |
|
|
196
|
+
| 8 | u32 | stored_size | bytes of blob (after the child table) |
|
|
197
|
+
| 12 | u32 | decoded_size | decoded-page bytes (== stored_size when raw); MUST equal the referencing child-table entry's (and the directory record's), else reject |
|
|
198
|
+
| 16 | u64 | checksum | xxh3-64, **seed = asset_id_low64 XOR page_index**, over frame bytes `[0, 16)` followed by `[24, 24 + 48·child_page_count + stored_size)` — everything but this field |
|
|
199
|
+
|
|
200
|
+
**Child table** — `child_page_count` × 48 B, plaintext (never compressed), deduplicated:
|
|
201
|
+
one entry per distinct child page this page's clusters refine into. This is what makes
|
|
202
|
+
traversal self-sufficient — an installed page needs nothing but itself to fetch every
|
|
203
|
+
page one level down — and it is plaintext for two load-bearing reasons: fetch ranges
|
|
204
|
+
are readable before (or without) blob decode, and stored sizes stay independent of
|
|
205
|
+
offset values, which keeps the build's layout computation non-circular (§10).
|
|
206
|
+
|
|
207
|
+
| offset | type | field | notes |
|
|
208
|
+
|-------:|------|---------------|-------|
|
|
209
|
+
| 0 | u64 | frame_offset | absolute; strictly greater than this page's own frame offset (§11.3) |
|
|
210
|
+
| 8 | u32 | page_index | the child page's global index (frame ordinal) — checksum seed, want dedup |
|
|
211
|
+
| 12 | u32 | fetch_size | `24 + 48·child.child_page_count + child.stored_size`, rounded up to 16 — the exact range to fetch |
|
|
212
|
+
| 16 | u32 | decoded_size | RAM budgeting before fetch; MUST equal the child frame's |
|
|
213
|
+
| 20 | u32 | reserved | |
|
|
214
|
+
| 24 | metric | metric | the child page's own metric (§6.2), copied — this is what makes a page testable *before* it is fetched; MUST equal that page's header metric (§11.11) |
|
|
215
|
+
|
|
216
|
+
The identity-seeded checksum binds the frame to *this page of this asset* and covers
|
|
217
|
+
the frame header fields, the child table, and the blob — a well-formed frame of the
|
|
218
|
+
wrong page, wrong asset, or wrong version fails verification instead of installing
|
|
219
|
+
silently. It also guards the traversal path itself: a corrupt child-table entry fetches
|
|
220
|
+
a range whose frame cannot checksum as the expected page index.
|
|
221
|
+
|
|
222
|
+
The next frame starts at `round_up(frame_offset + 24 + 48·child_page_count +
|
|
223
|
+
stored_size, 16)`. **Prefix scanning**: page indices are frame ordinals (file order ==
|
|
224
|
+
index order); scan sequentially and stop when the next aligned offset + 24 exceeds
|
|
225
|
+
`min(bytes_available, directory_offset)` — never rely on magic mismatch as a
|
|
226
|
+
terminator.
|
|
227
|
+
|
|
228
|
+
**Codecs.** `codec` is a property of one frame, not of the file: a writer picks per page
|
|
229
|
+
and an asset may carry a mixture, so a reader that handles the defined codecs handles
|
|
230
|
+
any file without asking what it was written with. That is what makes "compress unless it
|
|
231
|
+
would not shrink" expressible — the LZ4 worst case is about one byte in 255 plus a
|
|
232
|
+
token, and paying it to store bytes verbatim is a straight loss, so a page that does not
|
|
233
|
+
compress is written raw and says so.
|
|
234
|
+
|
|
235
|
+
A new codec id is a **per-asset capability gate, not a format break**, exactly as a new
|
|
236
|
+
`payload_encoding` is: an older reader meets a codec it has no decoder for and refuses
|
|
237
|
+
the asset instead of misreading it. `format_version` moves only when the container
|
|
238
|
+
layout itself changes, and adding a codec does not change it.
|
|
239
|
+
|
|
240
|
+
`1` is a **bare LZ4 block**, not an LZ4 frame: LZ4's own framing carries a magic, a
|
|
241
|
+
checksum and a content size that this frame already carries better, and `decoded_size`
|
|
242
|
+
is what the block is decoded against. Blocks are independent — no match reaches outside
|
|
243
|
+
the page — so a page decodes from its own bytes with no other page involved, which is
|
|
244
|
+
the same property residency already needs.
|
|
245
|
+
|
|
246
|
+
`decoded_size` is untrusted input, and readers allocate against it before anything can
|
|
247
|
+
contradict it. It MUST therefore be checked against what `stored_size` bytes could
|
|
248
|
+
physically produce under `codec` — exactly `stored_size` for raw, at most
|
|
249
|
+
`255·stored_size + 19` for LZ4 — *before* the allocation. A block that then decodes to
|
|
250
|
+
anything other than `decoded_size` MUST be rejected: a page truncated to a plausible
|
|
251
|
+
prefix is the one corruption that reads as a valid page with geometry missing.
|
|
252
|
+
|
|
253
|
+
**What it is worth, measured.** LZ4 over the pages of the Stanford models comes to
|
|
254
|
+
**1.12x on the bunny, 1.18x on the dragon and 1.14x on the 27M-triangle lucy** — pages
|
|
255
|
+
are >99% of a file, so that is very nearly the file ratio. That is modest, and the reason
|
|
256
|
+
is worth writing down because it says where the next win is rather than here:
|
|
257
|
+
|
|
258
|
+
| section | share of page bytes | lz4 |
|
|
259
|
+
|---|---:|---:|
|
|
260
|
+
| page header, group, node and cluster tables | 7% | 1.6x |
|
|
261
|
+
| payload | 93% | 1.09–1.15x |
|
|
262
|
+
|
|
263
|
+
The tables compress, and there are not enough of them to matter. The payload does not,
|
|
264
|
+
because under `SHADE_MESHLET_V1` it is float32 positions and packed attribute words —
|
|
265
|
+
high-entropy at the byte level, with no repetition for an LZ matcher to find. For
|
|
266
|
+
reference, on the same bytes `gzip -9` reaches 1.22x and `xz -9` 1.63x, so this is the
|
|
267
|
+
data resisting rather than the codec failing; an entropy coder buys a little more for a
|
|
268
|
+
lot more time. **The lever is `payload_encoding`, not `codec`** — quantized positions
|
|
269
|
+
(§12) shrink those bytes directly and leave the residue far more compressible.
|
|
270
|
+
|
|
271
|
+
What the reader pays is one block decode per page installed, into the buffer the page was
|
|
272
|
+
going to be copied into anyway: ~350–500 MB/s of decoded output from the JS decoder, so
|
|
273
|
+
about 0.6 ms for a 256 KB page.
|
|
274
|
+
|
|
275
|
+
## 6. Decoded page
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
[ PageHeader (56 B) ] [ Group table ] [ Node table ] [ Cluster records ] [ Payload ]
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
PageHeader:
|
|
282
|
+
|
|
283
|
+
| offset | type | field | notes |
|
|
284
|
+
|-------:|------|-----------------------|-------|
|
|
285
|
+
| 0 | u16 | group_count | ≥ 1; group table immediately follows the header |
|
|
286
|
+
| 2 | u16 | cluster_count | ≥ 1 |
|
|
287
|
+
| 4 | u8 | min_level | page band; non-root pages span one contiguous band |
|
|
288
|
+
| 5 | u8 | max_level | |
|
|
289
|
+
| 6 | u16 | node_count | ≥ 1; ≤ 2·`group_count` (§6.1) |
|
|
290
|
+
| 8 | u32 | cluster_table_offset | |
|
|
291
|
+
| 12 | u32 | payload_offset | |
|
|
292
|
+
| 16 | u32 | payload_size | |
|
|
293
|
+
| 20 | u32 | node_table_offset | = `56 + 8·group_count`; the node table follows the group table |
|
|
294
|
+
| 24 | [u8; 8] | reserved | |
|
|
295
|
+
| 32 | metric | metric | this page's own traversal metric (§6.2) — the root node's, repeated here so an installed page can be tested from itself |
|
|
296
|
+
|
|
297
|
+
Group table — `group_count` × 8 B. Groups are the atomic LOD/residency unit; because a
|
|
298
|
+
group never spans pages, installing/evicting a page carries whole groups by
|
|
299
|
+
construction — no global group index exists or is needed:
|
|
300
|
+
|
|
301
|
+
| offset | type | field | notes |
|
|
302
|
+
|-------:|------|----------------------|-------|
|
|
303
|
+
| 0 | u16 | cluster_first | index into this page's cluster records |
|
|
304
|
+
| 2 | u16 | cluster_count | ≥ 1; ≤ 4096 (format cap, §11.5) |
|
|
305
|
+
| 4 | u16 | parent_cluster_count | number of parent clusters referencing this group, `SAME_PAGE` references included; 0 exactly for the root page's topmost-level groups — drives activation (§10) |
|
|
306
|
+
| 6 | u16 | reserved | |
|
|
307
|
+
|
|
308
|
+
### 6.1 Node table (`node_count` × 32 B)
|
|
309
|
+
|
|
310
|
+
A tree over **this page's groups**, and nothing else. It is the part of the hierarchy below page
|
|
311
|
+
granularity, and it has no paging question of its own: it arrives with the page it describes,
|
|
312
|
+
leaves with it, and can never name anything that is not there.
|
|
313
|
+
|
|
314
|
+
| offset | type | field | notes |
|
|
315
|
+
|-------:|--------|-------------|-------|
|
|
316
|
+
| 0 | metric | metric | bounds everything under this node (§6.2) |
|
|
317
|
+
| 24 | u16 | child_first | first child — a node index when interior, a group index when a leaf |
|
|
318
|
+
| 26 | u16 | child_count | 1..4 |
|
|
319
|
+
| 28 | u16 | flags | bit 0: leaf (children are groups) |
|
|
320
|
+
| 30 | u16 | reserved | |
|
|
321
|
+
|
|
322
|
+
Node 0 is the root, always. Children occupy a **contiguous run**, and the tree is laid out
|
|
323
|
+
breadth-first, so an interior node's `child_first` is strictly greater than its own index — which
|
|
324
|
+
bounds any walk without a reader having to track one. Leaves **partition** the group table: every
|
|
325
|
+
group is reached through exactly one leaf, no group twice and none not at all. A page with a single
|
|
326
|
+
group still has a tree: one leaf node covering it, so a reader always starts at node 0 and never
|
|
327
|
+
special-cases.
|
|
328
|
+
|
|
329
|
+
Cost, measured across sphere assets from 3k to 98k triangles at page sizes from 8 KB to 256 KB: the
|
|
330
|
+
node table plus every metric copy runs **0.3%–1.6% of asset size**, and trees come out one to three
|
|
331
|
+
deep.
|
|
332
|
+
|
|
333
|
+
### 6.2 Traversal metric (24 B)
|
|
334
|
+
|
|
335
|
+
The same three fields wherever they appear — a child-table entry (§5), a page header (§6), a node
|
|
336
|
+
(§6.1):
|
|
337
|
+
|
|
338
|
+
| offset | type | field | notes |
|
|
339
|
+
|-------:|----------|------------------|-------|
|
|
340
|
+
| 0 | [f32; 4] | sphere | contains every bound anything covered carries |
|
|
341
|
+
| 16 | f32 | min_self_error | finest error covered |
|
|
342
|
+
| 20 | f32 | max_parent_error | coarsest parent error covered; `+∞` where the root is covered |
|
|
343
|
+
|
|
344
|
+
One sphere serves both the spatial test and the projection. It is the union of the covered clusters'
|
|
345
|
+
`parent_sphere`s, and monotonicity does the rest: `parent_sphere` contains `self_sphere`, which
|
|
346
|
+
contains the cluster's own vertices, so nothing under the node escapes it.
|
|
347
|
+
|
|
348
|
+
`max_parent_error` is the load-bearing number. A cluster is drawn only while `project(parent) > τ`,
|
|
349
|
+
so if the *largest* parent error under a node still projects to no more than τ, nothing under it can
|
|
350
|
+
be drawn and the entire subtree is skippable. `min_self_error` answers the other question — whether
|
|
351
|
+
anything here is drawable at all, or whether this is only a waypoint on the way to something finer —
|
|
352
|
+
which is what a prefetch ranks its wants by.
|
|
353
|
+
|
|
354
|
+
A group is the natural unit for all of this and needs no new geometry: every cluster of a group is
|
|
355
|
+
consumed by one step and therefore shares that step's `parent_sphere` and `parent_error`, which is
|
|
356
|
+
the same fact that makes the group the atomic LOD decision.
|
|
357
|
+
|
|
358
|
+
**The copy in a child-table entry is the point of the whole thing.** It is what a traversal reads
|
|
359
|
+
*before* fetching a page, and without it the only way to learn a page was not wanted is to fetch and
|
|
360
|
+
decode it. Being a copy, it can drift; §11.11 requires it to match the page's own.
|
|
361
|
+
|
|
362
|
+
## 7. Cluster record (112 bytes)
|
|
363
|
+
|
|
364
|
+
Everything the runtime cut rule, culling, wants, and upload need — denormalized per
|
|
365
|
+
cluster so selection reads one record. Two kinds of spheres, deliberately distinct: the
|
|
366
|
+
**LOD-metric pair** (`self_sphere`/`parent_sphere` — shared per group step so all
|
|
367
|
+
siblings project identical values, monotonically inflated, never a tight fit) and the
|
|
368
|
+
**culling bounds** (`bounds_sphere`/`aabb` — this cluster's own tight fits, never used
|
|
369
|
+
in the cut test):
|
|
370
|
+
|
|
371
|
+
| offset | type | field | notes |
|
|
372
|
+
|-------:|----------|-----------------|-------|
|
|
373
|
+
| 0 | [f32; 4] | self_sphere | LOD-metric sphere (center xyz + radius) of the group step that created this cluster; leaves: equals `bounds_sphere` |
|
|
374
|
+
| 16 | f32 | self_error | object-space `r_e`; leaves: 0 |
|
|
375
|
+
| 20 | f32 | parent_error | error of the step that consumed it; roots: +∞ |
|
|
376
|
+
| 24 | [f32; 4] | parent_sphere | LOD-metric sphere of the consuming step; roots: duplicate of self_sphere |
|
|
377
|
+
| 40 | [f32; 4] | bounds_sphere | this cluster's own minimal bounding sphere (miniball), object-space — culling |
|
|
378
|
+
| 56 | [f32; 6] | aabb | this cluster's object-space AABB — culling, GPU metadata `bounds_box`, and the (future) dequantization grid |
|
|
379
|
+
| 80 | u16 | child_ref | index into this frame's child table; `SAME_PAGE` when the child group is in this page; `NO_CHILD` for leaves |
|
|
380
|
+
| 82 | u16 | child_group | group index within the child page (or this page, for `SAME_PAGE`); `NO_GROUP` for leaves |
|
|
381
|
+
| 84 | u32 | cone_reserved | reserved for backface-cone culling — **write 0**. No cull pass consumes a cone today and the producer needs a `BinaryTopology` port; the sub-encoding is pinned together with that pass, not before |
|
|
382
|
+
| 88 | u32 | encoding_flags | frozen bit table in §8 |
|
|
383
|
+
| 92 | u32 | payload_offset | into this page's payload section; ≡ 0 (mod 4) |
|
|
384
|
+
| 96 | u32 | payload_size | bytes; ≡ 0 (mod 4) |
|
|
385
|
+
| 100 | u8 | vertex_count | 3 ≤ n ≤ 128 |
|
|
386
|
+
| 101 | u8 | triangle_count | 1 ≤ n ≤ 128 |
|
|
387
|
+
| 102 | u16 | reserved | |
|
|
388
|
+
| 104 | u64 | reserved | |
|
|
389
|
+
|
|
390
|
+
Monotonicity (`parent_error ≥ self_error`, `parent_sphere ⊇ self_sphere`) is a build
|
|
391
|
+
invariant, not a reader concern. A single-cluster asset is valid: one root page, one
|
|
392
|
+
group with `parent_cluster_count = 0`, one cluster with `parent_error = +∞`,
|
|
393
|
+
`child_ref = NO_CHILD`, `child_page_count = 0`.
|
|
394
|
+
|
|
395
|
+
## 8. Payload encoding
|
|
396
|
+
|
|
397
|
+
`payload_encoding = 1` (`SHADE_MESHLET_V1`). **Byte-compat scope**: the payload block is
|
|
398
|
+
byte-compatible with `GPUMeshletManager`'s **data pool** — uploading it is a copy. The
|
|
399
|
+
40-byte GPU metadata rows (`MESHLET_METADATA_STRUCT`: bounds_box, address,
|
|
400
|
+
primitive_count, vertex_count, flags) are **synthesized at install** from the cluster
|
|
401
|
+
record (aabb → bounds_box, counts widened to u32, `address = slot_base_word +
|
|
402
|
+
payload_offset/4`, flags = encoding_flags) — a small pack step that is part of the
|
|
403
|
+
design's "VRAM paging mechanism is new work", not an existing patch path.
|
|
404
|
+
|
|
405
|
+
Payload block layout:
|
|
406
|
+
|
|
407
|
+
1. Index section: `triangle_count × 3` local u8 indices, zero-padded to a 4-byte word
|
|
408
|
+
boundary.
|
|
409
|
+
2. Attribute sections, in the frozen order below, each `words × vertex_count` u32
|
|
410
|
+
words — unless its `encoding_flags` bit marks it constant-compressed, in which case
|
|
411
|
+
exactly `words` u32s are stored once.
|
|
412
|
+
|
|
413
|
+
Frozen tables (byte-identical to Shade's `ENCODED_ORDERED_ATTRIBUTES`,
|
|
414
|
+
`ENCODED_ATTRIBUTE_SIZES`, `MESHLET_METADATA_FLAGS` as of this writing — the spec, not
|
|
415
|
+
the source, is now the authority for `.vgeo` files):
|
|
416
|
+
|
|
417
|
+
| # | attribute | words/vertex | encoding | flags bit (constant-compressed) | mask bit |
|
|
418
|
+
|---|-----------|-------------:|----------------------------|-------------------------------:|---------:|
|
|
419
|
+
| 0 | position | 3 | raw f32×3 | — (never compressed) | 0 |
|
|
420
|
+
| 1 | normal | 1 | octahedral u32 | 1 (0x01) | 1 |
|
|
421
|
+
| 2 | tangent | 1 | packed u32 | 2 (0x02) | 2 |
|
|
422
|
+
| 3 | color | 1 | RGBA8 u32 | 4 (0x04) | 3 |
|
|
423
|
+
| 4 | uv0 | 2 | raw f32×2 | 8 (0x08) | 4 |
|
|
424
|
+
| 5 | uv1 | 1 | 2×unorm16 u32 | 16 (0x10) | 5 |
|
|
425
|
+
|
|
426
|
+
- `encoding_flags` bits 5 (0x20, skinning joints) and 6 (0x40, skinning weights) MUST
|
|
427
|
+
be clear, and **no skinning sections are stored** — `SHADE_MESHLET_V1` payloads end
|
|
428
|
+
at uv1. (Load-bearing note: skinning attributes are last in Shade's attribute order
|
|
429
|
+
and the static decode path never addresses them, which is exactly what makes their
|
|
430
|
+
omission safe. VG is static-only, design §9.)
|
|
431
|
+
- All other `encoding_flags` bits are reserved, MUST be 0.
|
|
432
|
+
- An attribute the source lacks still ships its section, constant-compressed to the
|
|
433
|
+
engine default — **sections are never omitted**; `vertex_attribute_mask` is advisory
|
|
434
|
+
(which attributes carry real data). True section omission would shift every following
|
|
435
|
+
offset and is only expressible as a new `payload_encoding` id.
|
|
436
|
+
|
|
437
|
+
Quantized positions land as a **new `payload_encoding` id** (plus a page codec if
|
|
438
|
+
entropy coding pays). The cluster record already carries the dequantization grid
|
|
439
|
+
(`aabb`).
|
|
440
|
+
|
|
441
|
+
## 9. Page directory (auxiliary)
|
|
442
|
+
|
|
443
|
+
Flat array of `total_pages` 32 B records at `directory_offset`; record `i` describes
|
|
444
|
+
page index `i` (page index order == file order == coarse-first). Auxiliary and fully
|
|
445
|
+
derivable from the frames (§3) — standard runtime traversal never reads it.
|
|
446
|
+
|
|
447
|
+
| offset | type | field | notes |
|
|
448
|
+
|-------:|------|----------------|-------|
|
|
449
|
+
| 0 | u64 | frame_offset | absolute; frame per §5 |
|
|
450
|
+
| 8 | u32 | fetch_size | as in the child table: the exact byte range to fetch is `[frame_offset, frame_offset + fetch_size)` |
|
|
451
|
+
| 12 | u32 | decoded_size | MUST equal the frame's |
|
|
452
|
+
| 16 | u8 | min_level | |
|
|
453
|
+
| 17 | u8 | max_level | |
|
|
454
|
+
| 18 | u16 | flags | bit 0: root page |
|
|
455
|
+
| 20 | u16 | group_count | |
|
|
456
|
+
| 22 | u16 | cluster_count | |
|
|
457
|
+
| 24 | u64 | reserved | |
|
|
458
|
+
|
|
459
|
+
**Directory integrity**: `dir_block_checksums` holds one xxh3-64 per 128 directory
|
|
460
|
+
records (one 4 KB block), seed = `asset_id_high64 XOR block_index`. Readers that use
|
|
461
|
+
the directory fetch it at block granularity and MUST verify.
|
|
462
|
+
|
|
463
|
+
## 10. Reader requirements
|
|
464
|
+
|
|
465
|
+
Standard runtime operation is **pure traversal** — the directory is not involved:
|
|
466
|
+
|
|
467
|
+
- Cold start: fetch `[0, 256)`, verify `header_checksum`, magic, versions (§4 reject
|
|
468
|
+
rules), then fetch `[root_page_offset, root_page_offset + root_page_fetch_size)` — the
|
|
469
|
+
level table (§4.1) sits between the two, so a head prefix covering both brings the whole
|
|
470
|
+
always-resident set in one request. The root frame's `decoded_size` MUST equal
|
|
471
|
+
`root_page_decoded_size` and its frame extent MUST match `root_page_fetch_size`, else
|
|
472
|
+
reject. Or speculatively fetch one larger head prefix — coarse-first layout makes every
|
|
473
|
+
prefix byte useful.
|
|
474
|
+
- **Refinement**: a want is a `child_ref` in an installed page; its child-table entry
|
|
475
|
+
carries the exact byte range — one round-trip per cold page, no metadata fetch ever.
|
|
476
|
+
Wants dedup on `page_index` across clusters, groups, and instances. A want whose
|
|
477
|
+
target page is **already installed** resolves as an activation recheck of the
|
|
478
|
+
referenced group (below), never a fetch.
|
|
479
|
+
- **Activation (closure without dependency lists)** — the selectable invariant:
|
|
480
|
+
|
|
481
|
+
*A group `g` is selectable iff every one of its `parent_cluster_count` references is
|
|
482
|
+
live — the referencing cluster's page is installed and that cluster's own group is
|
|
483
|
+
selectable. Groups with `parent_cluster_count = 0` (exactly the root page's topmost
|
|
484
|
+
level) are selectable at install.*
|
|
485
|
+
|
|
486
|
+
By induction, a selectable cluster's entire ancestor cone is installed and
|
|
487
|
+
selectable — the closure the cut rule needs, restored by a per-group counter instead
|
|
488
|
+
of dependency lists. Runtime bookkeeping: each resident group keeps a live-reference
|
|
489
|
+
counter; when a group becomes selectable, its clusters' references (child-table and
|
|
490
|
+
`SAME_PAGE` alike) increment the referenced groups' counters — cascading
|
|
491
|
+
transitively; installing a page counts the existing live references into it (the
|
|
492
|
+
runtime maintains a reverse-reference index for pending pages — the same structure
|
|
493
|
+
that carries wants). Counters only grow while the pages involved stay resident (the
|
|
494
|
+
eviction rule below guarantees referencing parents outlive children). Activation
|
|
495
|
+
flips whole groups; the cut rule's clamp reads *selectable*, not merely resident
|
|
496
|
+
(design §4/§6): resident-but-inactive groups draw nothing, their coarser selectable
|
|
497
|
+
ancestors keep covering that surface — **no holes and no double-draw, in any arrival
|
|
498
|
+
order**, because a group never draws before all pages holding its parents are
|
|
499
|
+
installed and selectable.
|
|
500
|
+
- **In-flight protection**: a fetch discovered through parent page P pins P until the
|
|
501
|
+
child installs — known at queue time, purely local. Arrivals verify the
|
|
502
|
+
identity-seeded frame checksum; activation makes any arrival order safe beyond that.
|
|
503
|
+
- **Eviction**: within each residency tier, a page is evictable only while it has no
|
|
504
|
+
resident child pages in that tier — checked against its own child table (`SAME_PAGE`
|
|
505
|
+
references never pin). Leaves-first order emerges from the rule; the root page is
|
|
506
|
+
pinned.
|
|
507
|
+
- Verify every ranged response is `206` with the requested `Content-Range`; a `200`
|
|
508
|
+
means the server ignored the range — abort the transfer immediately (design §6).
|
|
509
|
+
- Verify frame checksums (identity-seeded, §5) before decode, and `decoded_size`
|
|
510
|
+
against the child-table entry used to fetch and against the codec's decode bound
|
|
511
|
+
(§5) before allocating for it. On mismatch: bounded retries with
|
|
512
|
+
backoff, then **quarantine** the page — the clamped cut keeps a coarse stand-in
|
|
513
|
+
correct indefinitely — and surface telemetry. Never retry-loop: corruption at a
|
|
514
|
+
content-addressed URL is deterministic.
|
|
515
|
+
- After install, stamp each cluster's selection row with its own page index and its
|
|
516
|
+
child page index/group (touch and want emission, design §6/§7).
|
|
517
|
+
- Fetch batching: coalesce adjacent wanted pages into contiguous single ranges; ranges
|
|
518
|
+
never cross a band boundary by construction (coarse-first ordering), so coalescing
|
|
519
|
+
lives within bands — the within-band spatial curve (§12) is what carries fetch
|
|
520
|
+
locality and must be chosen with that as a criterion. Fetching through small unwanted
|
|
521
|
+
gaps is permitted under an implementation waste threshold.
|
|
522
|
+
- Never assume `nominal_page_size`; per-page sizes come from child tables (traversal),
|
|
523
|
+
frames (prefix scan), or the directory (special tasks).
|
|
524
|
+
|
|
525
|
+
Build consequence (accepted): child tables hold downstream offsets — the format is
|
|
526
|
+
optimized for reading, and the builder pays for it. Preferred strategy: emit frames
|
|
527
|
+
with placeholder child tables, then **backpatch** them once all offsets are known, and
|
|
528
|
+
finalize frame checksums last (the checksum covers the child table). Computing the full
|
|
529
|
+
layout up front (compress all blobs → prefix-sum offsets → one forward emit) is equally
|
|
530
|
+
valid. Both are cheap and non-circular **because child tables are plaintext in the
|
|
531
|
+
frame**: a frame's extent (`24 + 48·children + stored_size`, with `stored_size` the
|
|
532
|
+
blob's compressed size) never depends on the offset values, and patching plaintext
|
|
533
|
+
bytes needs no re-compression. Build times are non-interactive by expectation —
|
|
534
|
+
clustering and simplification dominate regardless.
|
|
535
|
+
|
|
536
|
+
## 11. Build invariants (validated at build, assumed by readers)
|
|
537
|
+
|
|
538
|
+
1. A group's clusters are contiguous in one page (`cluster_first/cluster_count`); a
|
|
539
|
+
group never spans pages. Non-root pages span a single contiguous level band.
|
|
540
|
+
2. Child tables are exact: deduplicated, one entry per distinct **other** page
|
|
541
|
+
referenced by this page's clusters (`SAME_PAGE` references appear in no child
|
|
542
|
+
table); every `child_ref`/`child_group` resolves to a valid entry and group;
|
|
543
|
+
`frame_offset`/`fetch_size`/`decoded_size` agree with the referenced frame and the
|
|
544
|
+
directory (all referencing pages agree by construction).
|
|
545
|
+
3. Acyclicity and reachability: every child-table `frame_offset` is strictly greater
|
|
546
|
+
than the owning page's frame offset (file order is topological), and every page is
|
|
547
|
+
reachable from the root page through child tables.
|
|
548
|
+
4. File order (== page index order) is coarse-first: the root page first, bands by
|
|
549
|
+
descending level, spatial locality within a band. The root page contains the
|
|
550
|
+
complete topmost level(s) — at minimum a complete drawable cut of the DAG. A
|
|
551
|
+
cluster's child group is always in a page whose band tops out strictly below its own
|
|
552
|
+
page's, unless the reference is `SAME_PAGE`.
|
|
553
|
+
5. Group size: `1 ≤ cluster_count ≤ 4096` (format cap; builders target far less —
|
|
554
|
+
design §3 grouping is adaptive from ~4). `parent_cluster_count` equals the exact
|
|
555
|
+
number of clusters (across all pages, `SAME_PAGE` included) whose
|
|
556
|
+
`child_ref/child_group` name this group; it is 0 exactly for the root page's
|
|
557
|
+
topmost-level groups. A page holding one indivisible oversized group MAY exceed
|
|
558
|
+
`nominal_page_size`; the hard bound is the frame's u32 `stored_size`.
|
|
559
|
+
6. `1 ≤ triangle_count ≤ 128`, `3 ≤ vertex_count ≤ 128` (Shade meshlet limits);
|
|
560
|
+
`total_clusters ≥ 1`; `source_vertex_count ≥ 3`, `source_face_count ≥ 1`.
|
|
561
|
+
7. Error/sphere monotonicity per design §4; `self_error = 0` and `child_ref = NO_CHILD`
|
|
562
|
+
exactly for leaves; `parent_error = +∞` exactly for **the** root — there is exactly
|
|
563
|
+
one, and it is in page 0. Several parentless clusters would be several entry points,
|
|
564
|
+
and the cut only ever enters at one; it is also what an unconverged build leaves
|
|
565
|
+
behind, which is the likelier cause. All floats NaN-free.
|
|
566
|
+
`bounds_sphere` and `aabb` contain the cluster's decoded vertices; the header's
|
|
567
|
+
`object_sphere` and `object_bounds` contain the normalized source mesh.
|
|
568
|
+
8. Payload offsets and sizes are 4-byte multiples; every payload decodes/uploads
|
|
569
|
+
against `payload_encoding` with no external state beyond its own cluster record.
|
|
570
|
+
A leaf's `self_error` of 0 is only as honest as the simplifier's metric — see design
|
|
571
|
+
§2, boundary constraint quadrics — and no reader-side check can distinguish an
|
|
572
|
+
exact coarse cluster from one whose error went unrecorded.
|
|
573
|
+
9. `asset_id` and `header_checksum` verify per §4 — including its zeroing rule, which excludes
|
|
574
|
+
every derived checksum field; every frame verifies per §5; the directory verifies per §9 and
|
|
575
|
+
byte-for-byte matches what a frame scan reconstructs. `header_checksum` covers bytes 0–255
|
|
576
|
+
only, so the level table's integrity rests on `asset_id`, which covers the whole file.
|
|
577
|
+
10. Every page's node table is a tree over exactly that page's groups: node 0 is the root, an
|
|
578
|
+
interior node's children are a contiguous run at a strictly greater index, `1 ≤ child_count ≤ 4`,
|
|
579
|
+
and the leaves partition the group table — each group reached through exactly one leaf. Each
|
|
580
|
+
node's metric bounds its whole subtree: its sphere contains every child's, its `min_self_error`
|
|
581
|
+
is no greater than any child's, its `max_parent_error` no less. The page header's metric equals
|
|
582
|
+
the root node's.
|
|
583
|
+
11. Every child-table entry's metric equals the header metric of the page it names. It is a copy
|
|
584
|
+
read before that page is fetched, so nothing else can catch it having drifted — and a traversal
|
|
585
|
+
that trusts a stale one skips a page it needed and leaves a hole.
|
|
586
|
+
12. Every frame names a defined `codec` (§5); a raw frame's `stored_size` equals its
|
|
587
|
+
`decoded_size`; and no frame's `decoded_size` exceeds what its codec could produce from
|
|
588
|
+
`stored_size` bytes. Every blob decodes to exactly `decoded_size` — a short decode is a
|
|
589
|
+
truncated page, and a page truncated to a plausible prefix is the one corruption that reads
|
|
590
|
+
as valid geometry with pieces missing.
|
|
591
|
+
13. `root_page_offset = align16(256 + 32 · level_count)`; the level table's `cluster_count` and
|
|
592
|
+
`group_count` columns sum to `total_clusters` and `total_groups`; every level holds at least
|
|
593
|
+
one cluster and one group; `min_error ≤ max_error`, both finite and ≥ 0.
|
|
594
|
+
|
|
595
|
+
## 12. Open
|
|
596
|
+
|
|
597
|
+
- Page codec ids beyond raw and LZ4 (§5). LZ4 is the default and is where the cheap
|
|
598
|
+
ratio is; a slower, denser codec (meshopt-style over the payload, deflate-family over
|
|
599
|
+
the tables) is a per-frame `codec` id away and costs no reader that already handles a
|
|
600
|
+
mixture. The quantized-position `payload_encoding` is the other half of the same
|
|
601
|
+
question, and would take most of what LZ4 currently finds.
|
|
602
|
+
- Default `nominal_page_size` (design §5: order hundreds of KB, measured).
|
|
603
|
+
- Spatial ordering curve within a level band (Morton over group centroids is the
|
|
604
|
+
default candidate; chosen with fetch-coalescing locality as an explicit criterion,
|
|
605
|
+
§10).
|
|
606
|
+
- Backface-cone cull pass and, with it, the `cone_reserved` sub-encoding.
|
|
607
|
+
- Multi-geometry containers (v1: one geometry per file; scenes reference many files).
|