@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,1024 +1,1024 @@
|
|
|
1
|
-
import { assert } from "../../../../core/assert.js";
|
|
2
|
-
import { u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
3
|
-
import { write_gpu_typed_buffer } from "../../shader/type/serde/write_gpu_typed_buffer.js";
|
|
4
|
-
import {
|
|
5
|
-
shader_geometry_sphere_derive,
|
|
6
|
-
WORKGROUP_SIZE as SPHERE_DERIVE_WORKGROUP_SIZE,
|
|
7
|
-
} from "./bounds_refresh/shader_geometry_sphere_derive.js";
|
|
8
|
-
import {
|
|
9
|
-
shader_meshlet_bounds_reduce,
|
|
10
|
-
WORKGROUP_SIZE as BOUNDS_REDUCE_WORKGROUP_SIZE,
|
|
11
|
-
} from "./bounds_refresh/shader_meshlet_bounds_reduce.js";
|
|
12
|
-
import {
|
|
13
|
-
shader_meshlet_bounds_scatter,
|
|
14
|
-
WORKGROUP_SIZE as BOUNDS_SCATTER_WORKGROUP_SIZE,
|
|
15
|
-
} from "./bounds_refresh/shader_meshlet_bounds_scatter.js";
|
|
16
|
-
import {
|
|
17
|
-
shader_skinned_mesh_bounds_refresh,
|
|
18
|
-
WORKGROUP_SIZE as MESH_BOUNDS_REFRESH_WORKGROUP_SIZE,
|
|
19
|
-
} from "./bounds_refresh/shader_skinned_mesh_bounds_refresh.js";
|
|
20
|
-
import {
|
|
21
|
-
SKINNING_BINDING_STRUCT
|
|
22
|
-
} from "./SKINNING_BINDING_STRUCT.js";
|
|
23
|
-
import {
|
|
24
|
-
shader_meshlet_apply_skinning
|
|
25
|
-
} from "./shader_meshlet_apply_skinning.js";
|
|
26
|
-
import {
|
|
27
|
-
MESHLET_METADATA_STRUCT
|
|
28
|
-
} from "../../geometry/meshlet/encoding/MESHLET_METADATA_STRUCT.js";
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Initial bindings-buffer capacity (in binding records). 16 × 16 bytes
|
|
32
|
-
* = 256 bytes — wasteful for a scene with no SkinnedMesh, but the
|
|
33
|
-
* doubling growth absorbs any larger scene cheaply.
|
|
34
|
-
*/
|
|
35
|
-
const BINDINGS_INITIAL_CAPACITY = 16;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Initial dispatch-lookup capacity (in `(binding_index, meshlet_local)`
|
|
39
|
-
* pairs, i.e. 8 bytes per slot). Sized to the same default a small
|
|
40
|
-
* skinned mesh produces.
|
|
41
|
-
*/
|
|
42
|
-
const DISPATCH_LOOKUP_INITIAL_CAPACITY = 256;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Initial `prev_positions_buffer` capacity in vertices. Each vertex
|
|
46
|
-
* is 3 × f32 = 12 bytes. 1024 vertices → 12 KB. Doubles on grow.
|
|
47
|
-
*/
|
|
48
|
-
const PREV_POSITIONS_INITIAL_CAPACITY_VERTICES = 1024;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Initial `prev_position_offsets_buffer` capacity in u32 records
|
|
52
|
-
* (one per meshlet metadata row). 1024 × 4 = 4 KB. Doubles on grow.
|
|
53
|
-
*/
|
|
54
|
-
const PREV_POSITION_OFFSETS_INITIAL_CAPACITY = 1024;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Sentinel value in `prev_position_offsets` for meshlet metadata
|
|
58
|
-
* rows that are NOT skinned clones — sources, static-mesh geometries,
|
|
59
|
-
* pre-skinning clones (rare), etc. The skinning shader sees this
|
|
60
|
-
* value and skips its `position_prev` write; the velocity post-pass
|
|
61
|
-
* sees it and falls back to the rigid per-object math.
|
|
62
|
-
*/
|
|
63
|
-
const PREV_POSITION_OFFSET_INVALID = 0xFFFFFFFF;
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* f32 vertex_count byte offset within MESHLET_METADATA_STRUCT, resolved
|
|
67
|
-
* at module load (after `.pack()` reorders fields). Used by the CPU
|
|
68
|
-
* binding-registration path to walk the source's metadata bytes and
|
|
69
|
-
* sum vertex counts for prev-position side-buffer allocation.
|
|
70
|
-
*/
|
|
71
|
-
const MESHLET_VERTEX_COUNT_BYTE_OFFSET = MESHLET_METADATA_STRUCT.get('vertex_count').offset;
|
|
72
|
-
const MESHLET_STRIDE_BYTES = MESHLET_METADATA_STRUCT.aligned_size;
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Per-scene container for the skinning subsystem's state. Owned by
|
|
76
|
-
* {@link GPUSceneContext}; receives the scene's
|
|
77
|
-
* {@link GPUGeometryManager} so it can allocate per-instance geometry
|
|
78
|
-
* clones for {@link SkinnedMesh} instances and route the skinning
|
|
79
|
-
* compute pass against those clones.
|
|
80
|
-
*
|
|
81
|
-
* Three responsibilities:
|
|
82
|
-
* 1. Geometry-clone routing — `obtain_geometry_index(mesh)` returns
|
|
83
|
-
* the clone id for SkinnedMesh, the source id for everyone else.
|
|
84
|
-
* 2. Skinning binding bookkeeping — each SkinnedMesh with a `skin_id`
|
|
85
|
-
* produces one binding record linking its clone's vertex region
|
|
86
|
-
* back to the source's data and to the skin's matrix range.
|
|
87
|
-
* 3. Per-frame dispatch — `update(cmd_ctx, animation_manager)`
|
|
88
|
-
* uploads any new bindings and dispatches the skinning compute
|
|
89
|
-
* pass that deforms the cloned vertex regions in place.
|
|
90
|
-
*
|
|
91
|
-
* The CPU-side binding records cache `skin_id` rather than
|
|
92
|
-
* `skin_matrix_offset` because the offset is owned by the animation
|
|
93
|
-
* manager. Resolution happens at upload time via
|
|
94
|
-
* `animation_manager.get_skin_matrix_offset(skin_id)`.
|
|
95
|
-
*/
|
|
96
|
-
export class GPUMeshSkinningContext {
|
|
97
|
-
|
|
98
|
-
/** @type {GPUDevice} */
|
|
99
|
-
#device;
|
|
100
|
-
|
|
101
|
-
/** @type {GPUGeometryManager} */
|
|
102
|
-
#geometries;
|
|
103
|
-
|
|
104
|
-
/** @type {GPUAnimationManager} */
|
|
105
|
-
#animation_manager;
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Per-SkinnedMesh clone metadata, cached so repeated lookups
|
|
109
|
-
* (binding-registration, geometry id resolution) hit the same
|
|
110
|
-
* record rather than re-cloning the source. Persists across
|
|
111
|
-
* scene rebuilds (unlike id_mapping).
|
|
112
|
-
*
|
|
113
|
-
* @type {Map<SkinnedMesh, GPUGeometryMetadata>}
|
|
114
|
-
*/
|
|
115
|
-
#clones = new Map();
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Per-mesh skin assignment. Populated by {@link bind}; consumed
|
|
119
|
-
* by {@link #register_binding} when it stamps the GPU binding
|
|
120
|
-
* record. A mesh present here has had a skinning binding
|
|
121
|
-
* registered exactly once — re-binding the same mesh is a
|
|
122
|
-
* no-op (the existing binding stands).
|
|
123
|
-
*
|
|
124
|
-
* Held here rather than on the {@link SkinnedMesh} so the public
|
|
125
|
-
* mesh class doesn't carry GPU-side state; consumers who need
|
|
126
|
-
* to look up "what skin is mesh X bound to?" can query via
|
|
127
|
-
* {@link get_skin_id}.
|
|
128
|
-
*
|
|
129
|
-
* @type {Map<SkinnedMesh, number>}
|
|
130
|
-
*/
|
|
131
|
-
#skin_id_by_mesh = new Map();
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* One CPU record per `(SkinnedMesh, clone)` binding registered via
|
|
135
|
-
* {@link #register_binding}. Resolved into GPU bytes at upload
|
|
136
|
-
* time — `skin_id` becomes `skin_matrix_offset` via
|
|
137
|
-
* {@link GPUAnimationManager#get_skin_matrix_offset}, and `mesh`
|
|
138
|
-
* becomes a meshes-table row via
|
|
139
|
-
* {@link GPUSceneContext#mesh_row_of}. The mesh is held rather
|
|
140
|
-
* than its row because the row is not stable: registration
|
|
141
|
-
* happens before the scene has placed the mesh at all, and the
|
|
142
|
-
* table reuses rows afterwards.
|
|
143
|
-
*
|
|
144
|
-
* Append-only in this MVP — removing a SkinnedMesh leaks its
|
|
145
|
-
* binding (alongside its clone). Acceptable at the lifetime-
|
|
146
|
-
* distinct-instance scale; phase-4 frees both together.
|
|
147
|
-
*
|
|
148
|
-
* @type {{
|
|
149
|
-
* skin_id: number,
|
|
150
|
-
* mesh: SkinnedMesh,
|
|
151
|
-
* source_meshlet_metadata_offset: number,
|
|
152
|
-
* clone_meshlet_metadata_offset: number,
|
|
153
|
-
* meshlet_count: number,
|
|
154
|
-
* clone_geometry_index: number,
|
|
155
|
-
* }[]}
|
|
156
|
-
*/
|
|
157
|
-
#bindings = [];
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Sum of {@link #bindings}[i].meshlet_count — the dispatch-lookup
|
|
161
|
-
* length and the workgroup count for the skinning compute pass.
|
|
162
|
-
* Tracked incrementally to avoid re-summing per frame.
|
|
163
|
-
* @type {number}
|
|
164
|
-
*/
|
|
165
|
-
#total_meshlet_count = 0;
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Set when {@link #bindings} has changed since the last upload.
|
|
169
|
-
* Cleared by {@link update} after re-uploading both the bindings
|
|
170
|
-
* buffer and the dispatch-lookup buffer.
|
|
171
|
-
* @type {boolean}
|
|
172
|
-
*/
|
|
173
|
-
#bindings_dirty = false;
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* The scene context's {@link GPUSceneContext#mesh_rows_version} as of the last bindings upload.
|
|
177
|
-
* The records hold meshes-table rows and that table reuses them, so a difference here means
|
|
178
|
-
* every record's row has to be resolved again.
|
|
179
|
-
*
|
|
180
|
-
* @type {number}
|
|
181
|
-
*/
|
|
182
|
-
#uploaded_mesh_rows_version = -1;
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* GPU mirror of {@link #bindings}, with `skin_id` resolved to
|
|
186
|
-
* `skin_matrix_offset`. `null` until the first binding is
|
|
187
|
-
* registered.
|
|
188
|
-
* @type {GPUBuffer|null}
|
|
189
|
-
*/
|
|
190
|
-
#bindings_buffer = null;
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Capacity of {@link #bindings_buffer} in binding records. Grows
|
|
194
|
-
* by doubling when a new binding pushes past it.
|
|
195
|
-
* @type {number}
|
|
196
|
-
*/
|
|
197
|
-
#bindings_capacity = 0;
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Flat `(binding_index, meshlet_local_index)` u32 pairs — one pair
|
|
201
|
-
* per workgroup. The skinning shader reads `dispatch_lookup[wg_id]`
|
|
202
|
-
* to figure out which (binding, meshlet) it's processing.
|
|
203
|
-
* @type {GPUBuffer|null}
|
|
204
|
-
*/
|
|
205
|
-
#dispatch_lookup_buffer = null;
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Capacity of {@link #dispatch_lookup_buffer} in `(binding,
|
|
209
|
-
* meshlet)` pairs (i.e. half the u32 count). Grows by doubling.
|
|
210
|
-
* @type {number}
|
|
211
|
-
*/
|
|
212
|
-
#dispatch_lookup_capacity = 0;
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Side-buffer holding the previous-frame mesh-local skinned
|
|
216
|
-
* positions for every clone meshlet's vertices. Laid out as
|
|
217
|
-
* tightly-packed `vec3<f32>` (3 × u32 words, f32 bit pattern)
|
|
218
|
-
* per vertex; each clone meshlet owns a contiguous slice of
|
|
219
|
-
* `vertex_count` vec3s starting at the offset recorded in
|
|
220
|
-
* {@link #prev_position_offsets_buffer}.
|
|
221
|
-
*
|
|
222
|
-
* Written by the skinning compute shader (using the manager's
|
|
223
|
-
* `prev_skin_matrices_buffer`), read by the velocity post-pass
|
|
224
|
-
* to interpolate per-vertex skin deformation across the rasterized
|
|
225
|
-
* triangle.
|
|
226
|
-
*
|
|
227
|
-
* Append-only — bindings reserve contiguous vertex ranges via
|
|
228
|
-
* {@link #next_prev_position_vertex_offset}; nothing frees.
|
|
229
|
-
*
|
|
230
|
-
* @type {GPUBuffer|null}
|
|
231
|
-
*/
|
|
232
|
-
#prev_positions_buffer = null;
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Capacity of {@link #prev_positions_buffer} in vertices (each
|
|
236
|
-
* vertex = 3 × u32 words).
|
|
237
|
-
* @type {number}
|
|
238
|
-
*/
|
|
239
|
-
#prev_positions_capacity_vertices = 0;
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Next free vertex slot in {@link #prev_positions_buffer}. Each
|
|
243
|
-
* binding registration reserves `sum(vertex_count)` vertices
|
|
244
|
-
* starting here and advances by that amount. Monotonic.
|
|
245
|
-
* @type {number}
|
|
246
|
-
*/
|
|
247
|
-
#next_prev_position_vertex_offset = 0;
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Per-meshlet base offset (in u32 words) into
|
|
251
|
-
* {@link #prev_positions_buffer}. Indexed by absolute meshlet
|
|
252
|
-
* metadata row — `prev_position_offsets[meshlet_index]` gives
|
|
253
|
-
* either {@link PREV_POSITION_OFFSET_INVALID} (non-clone or
|
|
254
|
-
* not-yet-bound meshlet) or the first u32 word of that
|
|
255
|
-
* meshlet's prev-position slice.
|
|
256
|
-
*
|
|
257
|
-
* Sized to the meshlet metadata buffer's record capacity (or
|
|
258
|
-
* larger). Re-uploaded from the CPU shadow whenever a new
|
|
259
|
-
* binding adds entries.
|
|
260
|
-
*
|
|
261
|
-
* @type {GPUBuffer|null}
|
|
262
|
-
*/
|
|
263
|
-
#prev_position_offsets_buffer = null;
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Capacity of {@link #prev_position_offsets_buffer} in u32
|
|
267
|
-
* records (= one per meshlet metadata row).
|
|
268
|
-
* @type {number}
|
|
269
|
-
*/
|
|
270
|
-
#prev_position_offsets_capacity = 0;
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* CPU shadow of {@link #prev_position_offsets_buffer}. Mutated
|
|
274
|
-
* by {@link #register_binding} when computing per-meshlet offsets;
|
|
275
|
-
* re-uploaded wholesale by {@link #upload_prev_position_offsets}.
|
|
276
|
-
* Entries default to {@link PREV_POSITION_OFFSET_INVALID}.
|
|
277
|
-
*
|
|
278
|
-
* @type {Uint32Array}
|
|
279
|
-
*/
|
|
280
|
-
#prev_position_offsets_cpu = new Uint32Array(0);
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Back-reference to the owning {@link GPUSceneContext} so the
|
|
284
|
-
* bindings-upload path can resolve a mesh to its meshes-table row
|
|
285
|
-
* via {@link GPUSceneContext#mesh_row_of} without the caller
|
|
286
|
-
* threading that lookup through every `bind()` call.
|
|
287
|
-
*
|
|
288
|
-
* Resolution cannot happen at registration time: `bind` and
|
|
289
|
-
* `obtain_geometry_index` both run before `scene.build` has given
|
|
290
|
-
* the mesh a row. Nor does resolving once suffice — the table
|
|
291
|
-
* hands out the lowest free row, so a mesh that leaves and
|
|
292
|
-
* re-enters the scene lands somewhere else, which is what
|
|
293
|
-
* {@link GPUSceneContext#mesh_rows_version} is compared for.
|
|
294
|
-
*
|
|
295
|
-
* @type {GPUSceneContext}
|
|
296
|
-
*/
|
|
297
|
-
#scene_context;
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* @param {{
|
|
301
|
-
* geometries: GPUGeometryManager,
|
|
302
|
-
* animation_manager: GPUAnimationManager,
|
|
303
|
-
* scene_context: GPUSceneContext,
|
|
304
|
-
* device: GPUDevice,
|
|
305
|
-
* }} args
|
|
306
|
-
*/
|
|
307
|
-
constructor({ geometries, animation_manager, scene_context, device }) {
|
|
308
|
-
assert.defined(geometries, 'geometries');
|
|
309
|
-
assert.defined(animation_manager, 'animation_manager');
|
|
310
|
-
assert.defined(scene_context, 'scene_context');
|
|
311
|
-
assert.defined(device, 'device');
|
|
312
|
-
|
|
313
|
-
this.#geometries = geometries;
|
|
314
|
-
this.#animation_manager = animation_manager;
|
|
315
|
-
this.#scene_context = scene_context;
|
|
316
|
-
this.#device = device;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* Side-buffer of previous-frame mesh-local skinned positions for
|
|
321
|
-
* the velocity post-pass. `null` until the first skinning binding
|
|
322
|
-
* has been registered.
|
|
323
|
-
*
|
|
324
|
-
* @returns {GPUBuffer|null}
|
|
325
|
-
*/
|
|
326
|
-
get prev_positions_buffer() {
|
|
327
|
-
return this.#prev_positions_buffer;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
/**
|
|
331
|
-
* The binding records the skinning pass reads — one {@link SKINNING_BINDING_STRUCT} per bound
|
|
332
|
-
* {@link SkinnedMesh}, in {@link #bindings} order. `null` until the first binding has been
|
|
333
|
-
* registered and uploaded.
|
|
334
|
-
*
|
|
335
|
-
* @returns {GPUBuffer|null}
|
|
336
|
-
*/
|
|
337
|
-
get bindings_buffer() {
|
|
338
|
-
return this.#bindings_buffer;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Per-meshlet base offsets into {@link prev_positions_buffer},
|
|
343
|
-
* indexed by absolute meshlet metadata row. Non-clone meshlets
|
|
344
|
-
* hold the sentinel `0xFFFFFFFF`. `null` until the first
|
|
345
|
-
* skinning binding has been registered.
|
|
346
|
-
*
|
|
347
|
-
* @returns {GPUBuffer|null}
|
|
348
|
-
*/
|
|
349
|
-
get prev_position_offsets_buffer() {
|
|
350
|
-
return this.#prev_position_offsets_buffer;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Geometry id to assign to this mesh's instance record. Idempotent.
|
|
355
|
-
*
|
|
356
|
-
* - For a {@link SkinnedMesh}: a per-instance clone of the source's
|
|
357
|
-
* GPU geometry. The first time we see a given mesh, allocate a
|
|
358
|
-
* clone; subsequent calls return the cached id. If the mesh has
|
|
359
|
-
* already been bound to a skin via {@link bind}, the binding's
|
|
360
|
-
* registration also runs here so scene.build's first sight of
|
|
361
|
-
* a pre-bound mesh doesn't strand it without a deformation pass.
|
|
362
|
-
* - For a regular {@link Mesh}: the source's id from the geometry
|
|
363
|
-
* manager.
|
|
364
|
-
*
|
|
365
|
-
* @param {Mesh} mesh
|
|
366
|
-
* @returns {number}
|
|
367
|
-
*/
|
|
368
|
-
obtain_geometry_index(mesh) {
|
|
369
|
-
if (mesh.isSkinnedMesh === true) {
|
|
370
|
-
const clone_metadata = this.#ensure_clone(mesh);
|
|
371
|
-
// If the mesh has already been bound (bind() ran before
|
|
372
|
-
// scene.build for this mesh), register its binding now.
|
|
373
|
-
// No-op if not yet bound or if the binding has already
|
|
374
|
-
// been registered in a previous call.
|
|
375
|
-
this.#try_register_binding(mesh, clone_metadata);
|
|
376
|
-
return clone_metadata.index;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
this.#geometries.add(mesh.geometry);
|
|
380
|
-
return this.#geometries.getAddress(mesh.geometry);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Bind a {@link SkinnedMesh} to a skin. The mesh's clone (if not
|
|
385
|
-
* already allocated) is created on demand; a skinning-pass
|
|
386
|
-
* binding record is registered so the deformation runs each
|
|
387
|
-
* frame. The skin id is stored on the context (not on the mesh
|
|
388
|
-
* — `SkinnedMesh` carries no GPU state).
|
|
389
|
-
*
|
|
390
|
-
* Re-binding the same mesh with a different skin id is rejected
|
|
391
|
-
* (single-binding model in this MVP — use {@link unbind} first if
|
|
392
|
-
* you need to swap). Calling with the same skin id is a no-op.
|
|
393
|
-
*
|
|
394
|
-
* Tolerates being called before `scene.build` registers the mesh;
|
|
395
|
-
* the binding upload happens during the next per-frame
|
|
396
|
-
* {@link update}.
|
|
397
|
-
*
|
|
398
|
-
* @param {SkinnedMesh} mesh
|
|
399
|
-
* @param {number} skin_id
|
|
400
|
-
*/
|
|
401
|
-
bind(mesh, skin_id) {
|
|
402
|
-
assert.defined(mesh, 'mesh');
|
|
403
|
-
assert.equal(mesh.isSkinnedMesh, true, 'mesh.isSkinnedMesh !== true');
|
|
404
|
-
assert.isNonNegativeInteger(skin_id, 'skin_id');
|
|
405
|
-
|
|
406
|
-
const existing = this.#skin_id_by_mesh.get(mesh);
|
|
407
|
-
if (existing !== undefined) {
|
|
408
|
-
assert.equal(
|
|
409
|
-
existing, skin_id,
|
|
410
|
-
`SkinnedMesh '${mesh.name}' is already bound to skin ${existing}; unbind before rebinding`
|
|
411
|
-
);
|
|
412
|
-
return;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
this.#skin_id_by_mesh.set(mesh, skin_id);
|
|
416
|
-
const clone_metadata = this.#ensure_clone(mesh);
|
|
417
|
-
this.#try_register_binding(mesh, clone_metadata);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
/**
|
|
421
|
-
* Skin id currently bound to this mesh, or `undefined` if the
|
|
422
|
-
* mesh hasn't been bound. Read-only accessor — bookkeeping lives
|
|
423
|
-
* here, not on the mesh.
|
|
424
|
-
*
|
|
425
|
-
* @param {SkinnedMesh} mesh
|
|
426
|
-
* @returns {number|undefined}
|
|
427
|
-
*/
|
|
428
|
-
get_skin_id(mesh) {
|
|
429
|
-
return this.#skin_id_by_mesh.get(mesh);
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
/**
|
|
433
|
-
* Drop the binding for a single mesh. The mesh's geometry clone
|
|
434
|
-
* stays allocated (deallocation needs compaction work the MVP
|
|
435
|
-
* doesn't do), but the per-frame deformation no longer runs for
|
|
436
|
-
* it — its vertices freeze at whatever the last skinning pass
|
|
437
|
-
* wrote.
|
|
438
|
-
*
|
|
439
|
-
* No-op if the mesh isn't bound.
|
|
440
|
-
*
|
|
441
|
-
* @param {SkinnedMesh} mesh
|
|
442
|
-
*/
|
|
443
|
-
unbind(mesh) {
|
|
444
|
-
if (!this.#skin_id_by_mesh.has(mesh)) return;
|
|
445
|
-
this.#skin_id_by_mesh.delete(mesh);
|
|
446
|
-
|
|
447
|
-
for (let i = this.#bindings.length - 1; i >= 0; i--) {
|
|
448
|
-
if (this.#bindings[i].mesh === mesh) {
|
|
449
|
-
this.#total_meshlet_count -= this.#bindings[i].meshlet_count;
|
|
450
|
-
this.#bindings.splice(i, 1);
|
|
451
|
-
this.#bindings_dirty = true;
|
|
452
|
-
break;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* Drop every binding that points at the given skin id. Called
|
|
459
|
-
* by {@link GPUAnimationManager#unregister_skin} so freeing the
|
|
460
|
-
* skin's GPU rows also tears down the meshes' deformation
|
|
461
|
-
* registrations (which would otherwise try to look up the freed
|
|
462
|
-
* skin's matrix offset on the next bindings upload and assert).
|
|
463
|
-
*
|
|
464
|
-
* @param {number} skin_id
|
|
465
|
-
*/
|
|
466
|
-
unbind_all_by_skin(skin_id) {
|
|
467
|
-
for (let i = this.#bindings.length - 1; i >= 0; i--) {
|
|
468
|
-
const b = this.#bindings[i];
|
|
469
|
-
if (b.skin_id === skin_id) {
|
|
470
|
-
this.#skin_id_by_mesh.delete(b.mesh);
|
|
471
|
-
this.#total_meshlet_count -= b.meshlet_count;
|
|
472
|
-
this.#bindings.splice(i, 1);
|
|
473
|
-
this.#bindings_dirty = true;
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
/**
|
|
479
|
-
* Lookup-or-create the per-mesh clone metadata. Cached so that
|
|
480
|
-
* repeated lookups (binding-registration, geometry id resolution
|
|
481
|
-
* via obtain_geometry_index) hit the same record without
|
|
482
|
-
* re-cloning the source.
|
|
483
|
-
*
|
|
484
|
-
* @param {SkinnedMesh} mesh
|
|
485
|
-
* @returns {GPUGeometryMetadata}
|
|
486
|
-
*/
|
|
487
|
-
#ensure_clone(mesh) {
|
|
488
|
-
let clone_metadata = this.#clones.get(mesh);
|
|
489
|
-
if (clone_metadata === undefined) {
|
|
490
|
-
clone_metadata = this.#geometries.add_clone(mesh.geometry);
|
|
491
|
-
this.#clones.set(mesh, clone_metadata);
|
|
492
|
-
}
|
|
493
|
-
return clone_metadata;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
/**
|
|
497
|
-
* Register a binding for this mesh if conditions allow:
|
|
498
|
-
* - the mesh has been bound to a skin via {@link bind}, AND
|
|
499
|
-
* - we haven't already registered the binding for this mesh.
|
|
500
|
-
*
|
|
501
|
-
* @param {SkinnedMesh} mesh
|
|
502
|
-
* @param {GPUGeometryMetadata} clone_metadata
|
|
503
|
-
*/
|
|
504
|
-
#try_register_binding(mesh, clone_metadata) {
|
|
505
|
-
const skin_id = this.#skin_id_by_mesh.get(mesh);
|
|
506
|
-
if (skin_id === undefined) return;
|
|
507
|
-
// The binding's presence in #bindings is the source of truth
|
|
508
|
-
// for "already registered". Cheap O(bindings) scan; bindings
|
|
509
|
-
// are O(skinned-mesh-count).
|
|
510
|
-
for (let i = 0; i < this.#bindings.length; i++) {
|
|
511
|
-
if (this.#bindings[i].mesh === mesh) return;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
this.#register_binding(mesh, clone_metadata, skin_id);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
/**
|
|
518
|
-
* Per-frame: upload any new bindings + dispatch the skinning
|
|
519
|
-
* compute pass that deforms cloned vertex regions in place.
|
|
520
|
-
*
|
|
521
|
-
* No-op if no bindings have been registered. Upload is skipped
|
|
522
|
-
* when nothing's changed since the last call. Must run after
|
|
523
|
-
* `shader_skin_matrix_prep` (which fills the skin matrices the
|
|
524
|
-
* deformation reads) and before any pass that consumes the
|
|
525
|
-
* skinned vertex data.
|
|
526
|
-
*
|
|
527
|
-
* The animation manager passed at construction supplies
|
|
528
|
-
* `skin_matrices_buffer` and resolves `skin_id` →
|
|
529
|
-
* `skin_matrix_offset` for the binding records.
|
|
530
|
-
*
|
|
531
|
-
* @param {ShadeGPUCommandContext} cmd_ctx
|
|
532
|
-
*/
|
|
533
|
-
update(cmd_ctx) {
|
|
534
|
-
if (this.#bindings.length === 0) {
|
|
535
|
-
return;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
// Flush any meshlet-clone work that hasn't been drained yet —
|
|
539
|
-
// typically happens on the first frame a fresh SkinnedMesh
|
|
540
|
-
// appears, when scene.build queues a clone in `pending_clones`
|
|
541
|
-
// but the per-frame `graphics.update` flush already ran earlier
|
|
542
|
-
// in the same frame. Without this, the skinning shader would
|
|
543
|
-
// read the cloned meshlet record before its `address` field
|
|
544
|
-
// got memcpy'd + patched (zero-initialized backing buffer →
|
|
545
|
-
// address 0), and writes would land at the start of the data
|
|
546
|
-
// buffer, corrupting whatever geometry sits there. Idempotent /
|
|
547
|
-
// no-op when nothing's pending, so repeat calls in subsequent
|
|
548
|
-
// frames are free.
|
|
549
|
-
//
|
|
550
|
-
// We call directly into `geometries.meshlets.update` rather
|
|
551
|
-
// than `geometries.update`: the latter also rebuilds the
|
|
552
|
-
// geometry metadata buffer (destroying + recreating it) when
|
|
553
|
-
// `__needs_update` is set, but the FrameGraph passes that
|
|
554
|
-
// already encoded into this cmd_ctx have captured the old
|
|
555
|
-
// buffer reference. Destroying it mid-cmd-context produces a
|
|
556
|
-
// "used in submit while destroyed" validation error. The
|
|
557
|
-
// metadata-buffer rebuild is the *next* GraphicsContext.update's
|
|
558
|
-
// job; here we just need the meshlet pending-clone flush.
|
|
559
|
-
this.#geometries.meshlets.update(cmd_ctx);
|
|
560
|
-
|
|
561
|
-
// The binding record carries a meshes-table row, and that table reuses rows: a scene the
|
|
562
|
-
// mesh left and re-entered puts it somewhere else, and every other binding's row can move
|
|
563
|
-
// out from under it too. So the records are re-resolved whenever the table's membership has
|
|
564
|
-
// changed since they were written, not only when a binding was added or dropped.
|
|
565
|
-
const mesh_rows_version = this.#scene_context.mesh_rows_version;
|
|
566
|
-
|
|
567
|
-
if (this.#bindings_dirty || this.#uploaded_mesh_rows_version !== mesh_rows_version) {
|
|
568
|
-
this.#upload_bindings();
|
|
569
|
-
|
|
570
|
-
this.#uploaded_mesh_rows_version = mesh_rows_version;
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
if (this.#bindings_dirty) {
|
|
574
|
-
// Neither of these reads anything outside the binding list, so a scene edit that left
|
|
575
|
-
// the list alone cannot have moved them.
|
|
576
|
-
this.#upload_dispatch_lookup();
|
|
577
|
-
this.#upload_prev_position_offsets();
|
|
578
|
-
this.#bindings_dirty = false;
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
const meshlets = this.#geometries.meshlets;
|
|
582
|
-
const total = this.#total_meshlet_count;
|
|
583
|
-
const binding_count = this.#bindings.length;
|
|
584
|
-
const max_workgroups = this.#device.limits.maxComputeWorkgroupsPerDimension;
|
|
585
|
-
|
|
586
|
-
// ── Skinning: deform the cloned vertex regions ────────────
|
|
587
|
-
//
|
|
588
|
-
// WebGPU's `dispatchWorkgroups` is capped at the device's
|
|
589
|
-
// `maxComputeWorkgroupsPerDimension` (65535 is the spec
|
|
590
|
-
// minimum; modern desktop GPUs typically report higher).
|
|
591
|
-
// With one workgroup per (binding, meshlet) pair, a busy
|
|
592
|
-
// scene (e.g. a grid of skinned characters) can exceed that
|
|
593
|
-
// — 324 dancers × ~220 meshlets each ≈ 71K pairs.
|
|
594
|
-
//
|
|
595
|
-
// Split into sub-dispatches when needed, passing
|
|
596
|
-
// `dispatch_offset` so the shader's lookup-index arithmetic
|
|
597
|
-
// keeps indexing a flat `dispatch_lookup` table. The encoded
|
|
598
|
-
// cost grows linearly in sub-dispatch count, but the GPU
|
|
599
|
-
// work is identical to a single huge dispatch.
|
|
600
|
-
for (let offset = 0; offset < total; offset += max_workgroups) {
|
|
601
|
-
const this_chunk = Math.min(max_workgroups, total - offset);
|
|
602
|
-
const dispatch_offset = cmd_ctx.allocateTransientValueBuffer(u32, offset);
|
|
603
|
-
|
|
604
|
-
shader_meshlet_apply_skinning.dispatch({
|
|
605
|
-
encoder: cmd_ctx,
|
|
606
|
-
group_count_x: this_chunk,
|
|
607
|
-
bindings: {
|
|
608
|
-
dispatch_offset,
|
|
609
|
-
meshlet_data: meshlets.buffer_data,
|
|
610
|
-
meshlet_metadata: meshlets.buffer_metadata,
|
|
611
|
-
skin_matrices: this.#animation_manager.skin_matrices_buffer,
|
|
612
|
-
prev_skin_matrices: this.#animation_manager.prev_skin_matrices_buffer,
|
|
613
|
-
skinning_bindings: this.#bindings_buffer,
|
|
614
|
-
dispatch_lookup: this.#dispatch_lookup_buffer,
|
|
615
|
-
prev_position_offsets: this.#prev_position_offsets_buffer,
|
|
616
|
-
prev_positions: this.#prev_positions_buffer,
|
|
617
|
-
// Skinning shader reads the SkinnedMesh's
|
|
618
|
-
// `transforms` row to source the live
|
|
619
|
-
// mesh.transform_global for the post-DQ
|
|
620
|
-
// position cancellation.
|
|
621
|
-
scene_database: this.#scene_context.scene_database_buffer,
|
|
622
|
-
},
|
|
623
|
-
});
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
// ── Bounds refresh chain ──────────────────────────────────
|
|
627
|
-
//
|
|
628
|
-
// Animated clones move outside their source-encoded bounds;
|
|
629
|
-
// the rasterizer's per-meshlet AABB cull and per-mesh sphere
|
|
630
|
-
// cull would reject them until we refresh both. The chain
|
|
631
|
-
// here runs every frame the skinning dispatched anything
|
|
632
|
-
// (cheap when nothing changed: dispatch overhead only, the
|
|
633
|
-
// shaders early-out on the workgroup boundary).
|
|
634
|
-
//
|
|
635
|
-
// Order is load-bearing:
|
|
636
|
-
// 1. scatter — reset meshlet.bounds_box / geometry.bounding_box to ±inf
|
|
637
|
-
// 2. reduce — atomic-merge per-vertex into meshlet + geometry box
|
|
638
|
-
// 3. derive — geometry box → geometry sphere (per binding)
|
|
639
|
-
// 4. mesh — geometry box+sphere → world-space mesh bounds (per binding)
|
|
640
|
-
//
|
|
641
|
-
// The same `dispatch_lookup` table that drove the skinning
|
|
642
|
-
// dispatch above also drives the scatter and reduce dispatches
|
|
643
|
-
// — every (binding, meshlet) pair gets exactly the same set
|
|
644
|
-
// of workgroups, just running different shaders.
|
|
645
|
-
const geometry_metadata_buffer = this.#geometries.buffer_metadata;
|
|
646
|
-
const scene_database_buffer = this.#scene_context.scene_database_buffer;
|
|
647
|
-
|
|
648
|
-
// ── 1. Scatter: ±inf sentinels into meshlet + geometry bounds.
|
|
649
|
-
// Linear-thread dispatch: WG_SIZE threads per workgroup, one
|
|
650
|
-
// thread per pair. With WG_SIZE = 64 the workgroup count is
|
|
651
|
-
// ceil(total/64) — single sub-dispatch except at extreme
|
|
652
|
-
// scale (~4M pairs).
|
|
653
|
-
{
|
|
654
|
-
const total_workgroups = Math.ceil(total / BOUNDS_SCATTER_WORKGROUP_SIZE);
|
|
655
|
-
for (let offset_wg = 0; offset_wg < total_workgroups; offset_wg += max_workgroups) {
|
|
656
|
-
const this_chunk = Math.min(max_workgroups, total_workgroups - offset_wg);
|
|
657
|
-
// dispatch_offset is in *pair* units for scatter — the
|
|
658
|
-
// shader does `gid.x + dispatch_offset`.
|
|
659
|
-
const dispatch_offset = cmd_ctx.allocateTransientValueBuffer(
|
|
660
|
-
u32,
|
|
661
|
-
offset_wg * BOUNDS_SCATTER_WORKGROUP_SIZE
|
|
662
|
-
);
|
|
663
|
-
const total_pair_count = cmd_ctx.allocateTransientValueBuffer(u32, total);
|
|
664
|
-
shader_meshlet_bounds_scatter.dispatch({
|
|
665
|
-
encoder: cmd_ctx,
|
|
666
|
-
group_count_x: this_chunk,
|
|
667
|
-
bindings: {
|
|
668
|
-
dispatch_offset,
|
|
669
|
-
total_pair_count,
|
|
670
|
-
skinning_bindings: this.#bindings_buffer,
|
|
671
|
-
dispatch_lookup: this.#dispatch_lookup_buffer,
|
|
672
|
-
meshlet_metadata_atomic: meshlets.buffer_metadata,
|
|
673
|
-
geometry_metadata_atomic: geometry_metadata_buffer,
|
|
674
|
-
},
|
|
675
|
-
});
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
// ── 2. Reduce: per-meshlet workgroup, merges into meshlet +
|
|
680
|
-
// geometry box atomically. Same workgroup-per-pair pattern as
|
|
681
|
-
// skinning; same pagination.
|
|
682
|
-
for (let offset = 0; offset < total; offset += max_workgroups) {
|
|
683
|
-
const this_chunk = Math.min(max_workgroups, total - offset);
|
|
684
|
-
const dispatch_offset = cmd_ctx.allocateTransientValueBuffer(u32, offset);
|
|
685
|
-
|
|
686
|
-
shader_meshlet_bounds_reduce.dispatch({
|
|
687
|
-
encoder: cmd_ctx,
|
|
688
|
-
group_count_x: this_chunk,
|
|
689
|
-
bindings: {
|
|
690
|
-
dispatch_offset,
|
|
691
|
-
skinning_bindings: this.#bindings_buffer,
|
|
692
|
-
dispatch_lookup: this.#dispatch_lookup_buffer,
|
|
693
|
-
meshlet_data: meshlets.buffer_data,
|
|
694
|
-
meshlet_metadata_atomic: meshlets.buffer_metadata,
|
|
695
|
-
geometry_metadata_atomic: geometry_metadata_buffer,
|
|
696
|
-
},
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
// ── 3. Sphere derive: per binding, geometry box → sphere.
|
|
701
|
-
// Linear-thread dispatch, sized to ceil(binding_count/64).
|
|
702
|
-
// Binding count is small (one per active SkinnedMesh, so
|
|
703
|
-
// hundreds at most), single sub-dispatch always suffices.
|
|
704
|
-
{
|
|
705
|
-
const total_workgroups = Math.ceil(binding_count / SPHERE_DERIVE_WORKGROUP_SIZE);
|
|
706
|
-
if (total_workgroups > 0) {
|
|
707
|
-
const binding_count_u = cmd_ctx.allocateTransientValueBuffer(u32, binding_count);
|
|
708
|
-
shader_geometry_sphere_derive.dispatch({
|
|
709
|
-
encoder: cmd_ctx,
|
|
710
|
-
group_count_x: total_workgroups,
|
|
711
|
-
bindings: {
|
|
712
|
-
binding_count: binding_count_u,
|
|
713
|
-
skinning_bindings: this.#bindings_buffer,
|
|
714
|
-
geometry_metadata_atomic: geometry_metadata_buffer,
|
|
715
|
-
},
|
|
716
|
-
});
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
// ── 4. Mesh-instance bounds: per binding, geometry → world
|
|
721
|
-
// mesh bounds. Reuses the existing per-mesh bounds chunk
|
|
722
|
-
// (sphere radius scaled by max-column-length of the
|
|
723
|
-
// transform 3×3, conservative under non-uniform scale).
|
|
724
|
-
{
|
|
725
|
-
const total_workgroups = Math.ceil(binding_count / MESH_BOUNDS_REFRESH_WORKGROUP_SIZE);
|
|
726
|
-
if (total_workgroups > 0) {
|
|
727
|
-
const binding_count_u = cmd_ctx.allocateTransientValueBuffer(u32, binding_count);
|
|
728
|
-
shader_skinned_mesh_bounds_refresh.dispatch({
|
|
729
|
-
encoder: cmd_ctx,
|
|
730
|
-
group_count_x: total_workgroups,
|
|
731
|
-
bindings: {
|
|
732
|
-
binding_count: binding_count_u,
|
|
733
|
-
skinning_bindings: this.#bindings_buffer,
|
|
734
|
-
scene_database: scene_database_buffer,
|
|
735
|
-
geometries: geometry_metadata_buffer,
|
|
736
|
-
},
|
|
737
|
-
});
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
/**
|
|
743
|
-
* @param {SkinnedMesh} mesh
|
|
744
|
-
* @param {GPUGeometryMetadata} clone_metadata
|
|
745
|
-
* @param {number} skin_id
|
|
746
|
-
*/
|
|
747
|
-
#register_binding(mesh, clone_metadata, skin_id) {
|
|
748
|
-
const source_metadata = this.#geometries.get_metadata(mesh.geometry);
|
|
749
|
-
assert.defined(source_metadata, 'source_metadata');
|
|
750
|
-
|
|
751
|
-
const meshlet_count = clone_metadata.meshlets.meshlet_count;
|
|
752
|
-
const clone_meshlet_metadata_offset = clone_metadata.meshlets.metadata.offset;
|
|
753
|
-
|
|
754
|
-
this.#bindings.push({
|
|
755
|
-
skin_id,
|
|
756
|
-
mesh,
|
|
757
|
-
source_meshlet_metadata_offset: source_metadata.meshlets.metadata.offset,
|
|
758
|
-
clone_meshlet_metadata_offset,
|
|
759
|
-
meshlet_count,
|
|
760
|
-
clone_geometry_index: clone_metadata.index,
|
|
761
|
-
});
|
|
762
|
-
this.#total_meshlet_count += meshlet_count;
|
|
763
|
-
this.#bindings_dirty = true;
|
|
764
|
-
|
|
765
|
-
// ── Prev-position side-buffer bookkeeping ────────────────
|
|
766
|
-
//
|
|
767
|
-
// Walk the source's CPU metadata bytes to sum vertex counts
|
|
768
|
-
// (source and clone share the same vertex counts per
|
|
769
|
-
// meshlet — the clone is a memcpy of the source data). Each
|
|
770
|
-
// clone meshlet gets a contiguous (vertex_count × 3 u32)
|
|
771
|
-
// slot in the prev_positions side-buffer; record its base
|
|
772
|
-
// word offset in the per-meshlet offsets table indexed by
|
|
773
|
-
// absolute clone meshlet metadata row.
|
|
774
|
-
//
|
|
775
|
-
// `metadata_buffer_original` comes from `BinaryBuffer.data`
|
|
776
|
-
// and IS the raw `ArrayBuffer` (not a typed-array view), so
|
|
777
|
-
// we wrap it in a DataView directly without dereferencing
|
|
778
|
-
// a `.buffer` property.
|
|
779
|
-
const metadata_bytes = source_metadata.meshlets.metadata_buffer_original;
|
|
780
|
-
const view = new DataView(metadata_bytes);
|
|
781
|
-
|
|
782
|
-
// Phase 1: sum total vertices so we can grow the side-buffer
|
|
783
|
-
// up front, before recording per-meshlet offsets.
|
|
784
|
-
let total_vertices = 0;
|
|
785
|
-
for (let i = 0; i < meshlet_count; i++) {
|
|
786
|
-
const vc = view.getUint32(i * MESHLET_STRIDE_BYTES + MESHLET_VERTEX_COUNT_BYTE_OFFSET, true);
|
|
787
|
-
total_vertices += vc;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
const base_vertex_offset = this.#next_prev_position_vertex_offset;
|
|
791
|
-
this.#next_prev_position_vertex_offset += total_vertices;
|
|
792
|
-
|
|
793
|
-
this.#ensure_prev_positions_capacity_vertices(this.#next_prev_position_vertex_offset);
|
|
794
|
-
this.#ensure_prev_position_offsets_capacity(clone_meshlet_metadata_offset + meshlet_count);
|
|
795
|
-
|
|
796
|
-
// Phase 2: per-meshlet offsets. Convert (vertex slot)
|
|
797
|
-
// to u32-word offset (× 3) since the side-buffer stores
|
|
798
|
-
// 3 × f32 per vertex back-to-back.
|
|
799
|
-
let cumulative_vertex_offset = 0;
|
|
800
|
-
for (let i = 0; i < meshlet_count; i++) {
|
|
801
|
-
const vc = view.getUint32(i * MESHLET_STRIDE_BYTES + MESHLET_VERTEX_COUNT_BYTE_OFFSET, true);
|
|
802
|
-
const meshlet_word_offset = (base_vertex_offset + cumulative_vertex_offset) * 3;
|
|
803
|
-
this.#prev_position_offsets_cpu[clone_meshlet_metadata_offset + i] = meshlet_word_offset;
|
|
804
|
-
cumulative_vertex_offset += vc;
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
/**
|
|
809
|
-
* Grow {@link #prev_positions_buffer} to fit at least
|
|
810
|
-
* `required_vertices` vertices. Doubles from
|
|
811
|
-
* {@link PREV_POSITIONS_INITIAL_CAPACITY_VERTICES}. The buffer's
|
|
812
|
-
* contents are scratch (rewritten every frame by the skinning
|
|
813
|
-
* compute pass), so growth doesn't copy data — but the reference
|
|
814
|
-
* is invalidated, so callers must re-fetch through the getter.
|
|
815
|
-
*
|
|
816
|
-
* @param {number} required_vertices
|
|
817
|
-
*/
|
|
818
|
-
#ensure_prev_positions_capacity_vertices(required_vertices) {
|
|
819
|
-
if (this.#prev_positions_buffer !== null && required_vertices <= this.#prev_positions_capacity_vertices) {
|
|
820
|
-
return;
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
let new_capacity = Math.max(
|
|
824
|
-
this.#prev_positions_capacity_vertices,
|
|
825
|
-
PREV_POSITIONS_INITIAL_CAPACITY_VERTICES,
|
|
826
|
-
);
|
|
827
|
-
while (new_capacity < required_vertices) {
|
|
828
|
-
new_capacity *= 2;
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
if (this.#prev_positions_buffer !== null) {
|
|
832
|
-
this.#prev_positions_buffer.destroy();
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
// 3 × u32 per vertex (each u32 carries an f32 bit pattern).
|
|
836
|
-
this.#prev_positions_buffer = this.#device.createBuffer({
|
|
837
|
-
label: 'GPUMeshSkinningContext/PrevPositions',
|
|
838
|
-
size: new_capacity * 3 * 4,
|
|
839
|
-
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
|
|
840
|
-
});
|
|
841
|
-
this.#prev_positions_capacity_vertices = new_capacity;
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
/**
|
|
845
|
-
* Grow {@link #prev_position_offsets_buffer} (and its CPU
|
|
846
|
-
* shadow) to cover at least `required_records` meshlet metadata
|
|
847
|
-
* rows. Entries beyond previously written ones default to
|
|
848
|
-
* {@link PREV_POSITION_OFFSET_INVALID} so non-clone meshlets
|
|
849
|
-
* read as "no prev-position data, fall back".
|
|
850
|
-
*
|
|
851
|
-
* @param {number} required_records
|
|
852
|
-
*/
|
|
853
|
-
#ensure_prev_position_offsets_capacity(required_records) {
|
|
854
|
-
if (this.#prev_position_offsets_buffer !== null && required_records <= this.#prev_position_offsets_capacity) {
|
|
855
|
-
return;
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
let new_capacity = Math.max(
|
|
859
|
-
this.#prev_position_offsets_capacity,
|
|
860
|
-
PREV_POSITION_OFFSETS_INITIAL_CAPACITY,
|
|
861
|
-
);
|
|
862
|
-
while (new_capacity < required_records) {
|
|
863
|
-
new_capacity *= 2;
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
// Re-allocate CPU shadow, copy old entries, fill new with
|
|
867
|
-
// sentinel.
|
|
868
|
-
const new_cpu = new Uint32Array(new_capacity);
|
|
869
|
-
new_cpu.fill(PREV_POSITION_OFFSET_INVALID);
|
|
870
|
-
new_cpu.set(this.#prev_position_offsets_cpu);
|
|
871
|
-
this.#prev_position_offsets_cpu = new_cpu;
|
|
872
|
-
|
|
873
|
-
if (this.#prev_position_offsets_buffer !== null) {
|
|
874
|
-
this.#prev_position_offsets_buffer.destroy();
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
this.#prev_position_offsets_buffer = this.#device.createBuffer({
|
|
878
|
-
label: 'GPUMeshSkinningContext/PrevPositionOffsets',
|
|
879
|
-
size: new_capacity * 4,
|
|
880
|
-
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
881
|
-
});
|
|
882
|
-
this.#prev_position_offsets_capacity = new_capacity;
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
/**
|
|
886
|
-
* Re-upload the entire {@link #prev_position_offsets_cpu} shadow
|
|
887
|
-
* to the GPU offsets buffer. Called when a new binding has
|
|
888
|
-
* registered new entries (rare — bindings register once, not
|
|
889
|
-
* per frame). Whole-buffer upload because the buffer is small
|
|
890
|
-
* (one u32 per meshlet metadata row, hundreds of KB at typical
|
|
891
|
-
* stress-test scale).
|
|
892
|
-
*/
|
|
893
|
-
#upload_prev_position_offsets() {
|
|
894
|
-
if (this.#prev_position_offsets_buffer === null) {
|
|
895
|
-
return;
|
|
896
|
-
}
|
|
897
|
-
this.#device.queue.writeBuffer(
|
|
898
|
-
this.#prev_position_offsets_buffer,
|
|
899
|
-
0,
|
|
900
|
-
this.#prev_position_offsets_cpu.buffer,
|
|
901
|
-
0,
|
|
902
|
-
this.#prev_position_offsets_capacity * 4,
|
|
903
|
-
);
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
/**
|
|
907
|
-
* Resolve every CPU binding into GPU bytes (looking up
|
|
908
|
-
* `skin_matrix_offset` from the animation manager) and upload to
|
|
909
|
-
* the bindings buffer. Grows the buffer first if the binding
|
|
910
|
-
* count has outgrown its capacity.
|
|
911
|
-
*/
|
|
912
|
-
#upload_bindings() {
|
|
913
|
-
const binding_count = this.#bindings.length;
|
|
914
|
-
const struct_size = SKINNING_BINDING_STRUCT.aligned_size;
|
|
915
|
-
|
|
916
|
-
if (binding_count > this.#bindings_capacity) {
|
|
917
|
-
let new_capacity = Math.max(this.#bindings_capacity, BINDINGS_INITIAL_CAPACITY);
|
|
918
|
-
while (new_capacity < binding_count) {
|
|
919
|
-
new_capacity *= 2;
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
if (this.#bindings_buffer !== null) {
|
|
923
|
-
this.#bindings_buffer.destroy();
|
|
924
|
-
}
|
|
925
|
-
|
|
926
|
-
this.#bindings_buffer = this.#device.createBuffer({
|
|
927
|
-
label: 'GPUMeshSkinningContext/Bindings',
|
|
928
|
-
size: new_capacity * struct_size,
|
|
929
|
-
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
930
|
-
});
|
|
931
|
-
this.#bindings_capacity = new_capacity;
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
const data = new ArrayBuffer(binding_count * struct_size);
|
|
935
|
-
for (let i = 0; i < binding_count; i++) {
|
|
936
|
-
const b = this.#bindings[i];
|
|
937
|
-
|
|
938
|
-
// The meshes table is asked for the row rather than having it
|
|
939
|
-
// derived from the transforms row: every node earns a
|
|
940
|
-
// transforms row and only the geometry-bearing ones earn a
|
|
941
|
-
// mesh row, so the two tables run at different rates as soon
|
|
942
|
-
// as the scene holds a group, an anchor or a joint — which is
|
|
943
|
-
// every glTF. A bound mesh is in the scene: assertion catches
|
|
944
|
-
// both a SkinnedMesh scene.build has not seen yet and one that
|
|
945
|
-
// left the scene without being unbound, either of which would
|
|
946
|
-
// otherwise reach the shader as a garbage row.
|
|
947
|
-
const mesh_instance_index = this.#scene_context.mesh_row_of(b.mesh);
|
|
948
|
-
assert.isNonNegativeInteger(
|
|
949
|
-
mesh_instance_index,
|
|
950
|
-
`SkinnedMesh '${b.mesh.name}' (id=${b.mesh.id}) has no meshes-table row — scene.build must run before skinning bindings upload`
|
|
951
|
-
);
|
|
952
|
-
|
|
953
|
-
write_gpu_typed_buffer({
|
|
954
|
-
skin_matrix_offset: this.#animation_manager.get_skin_matrix_offset(b.skin_id),
|
|
955
|
-
source_meshlet_metadata_offset: b.source_meshlet_metadata_offset,
|
|
956
|
-
clone_meshlet_metadata_offset: b.clone_meshlet_metadata_offset,
|
|
957
|
-
meshlet_count: b.meshlet_count,
|
|
958
|
-
clone_geometry_index: b.clone_geometry_index,
|
|
959
|
-
mesh_instance_index,
|
|
960
|
-
}, SKINNING_BINDING_STRUCT, data, i * struct_size);
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
this.#device.queue.writeBuffer(this.#bindings_buffer, 0, data);
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
/**
|
|
967
|
-
* Build the flat `(binding_index, meshlet_local_index)` table —
|
|
968
|
-
* one pair per workgroup the skinning dispatch will spawn — and
|
|
969
|
-
* upload to the dispatch-lookup buffer (growing it if needed).
|
|
970
|
-
*/
|
|
971
|
-
#upload_dispatch_lookup() {
|
|
972
|
-
const total = this.#total_meshlet_count;
|
|
973
|
-
|
|
974
|
-
if (total > this.#dispatch_lookup_capacity) {
|
|
975
|
-
let new_capacity = Math.max(this.#dispatch_lookup_capacity, DISPATCH_LOOKUP_INITIAL_CAPACITY);
|
|
976
|
-
while (new_capacity < total) {
|
|
977
|
-
new_capacity *= 2;
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
if (this.#dispatch_lookup_buffer !== null) {
|
|
981
|
-
this.#dispatch_lookup_buffer.destroy();
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
this.#dispatch_lookup_buffer = this.#device.createBuffer({
|
|
985
|
-
label: 'GPUMeshSkinningContext/DispatchLookup',
|
|
986
|
-
// 8 bytes per pair (two u32s).
|
|
987
|
-
size: new_capacity * 8,
|
|
988
|
-
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
989
|
-
});
|
|
990
|
-
this.#dispatch_lookup_capacity = new_capacity;
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
const data = new Uint32Array(total * 2);
|
|
994
|
-
let cursor = 0;
|
|
995
|
-
for (let b = 0; b < this.#bindings.length; b++) {
|
|
996
|
-
const binding = this.#bindings[b];
|
|
997
|
-
for (let m = 0; m < binding.meshlet_count; m++) {
|
|
998
|
-
data[cursor++] = b;
|
|
999
|
-
data[cursor++] = m;
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
this.#device.queue.writeBuffer(this.#dispatch_lookup_buffer, 0, data);
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
destroy() {
|
|
1007
|
-
if (this.#bindings_buffer !== null) {
|
|
1008
|
-
this.#bindings_buffer.destroy();
|
|
1009
|
-
this.#bindings_buffer = null;
|
|
1010
|
-
}
|
|
1011
|
-
if (this.#dispatch_lookup_buffer !== null) {
|
|
1012
|
-
this.#dispatch_lookup_buffer.destroy();
|
|
1013
|
-
this.#dispatch_lookup_buffer = null;
|
|
1014
|
-
}
|
|
1015
|
-
if (this.#prev_positions_buffer !== null) {
|
|
1016
|
-
this.#prev_positions_buffer.destroy();
|
|
1017
|
-
this.#prev_positions_buffer = null;
|
|
1018
|
-
}
|
|
1019
|
-
if (this.#prev_position_offsets_buffer !== null) {
|
|
1020
|
-
this.#prev_position_offsets_buffer.destroy();
|
|
1021
|
-
this.#prev_position_offsets_buffer = null;
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
import { u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
3
|
+
import { write_gpu_typed_buffer } from "../../shader/type/serde/write_gpu_typed_buffer.js";
|
|
4
|
+
import {
|
|
5
|
+
shader_geometry_sphere_derive,
|
|
6
|
+
WORKGROUP_SIZE as SPHERE_DERIVE_WORKGROUP_SIZE,
|
|
7
|
+
} from "./bounds_refresh/shader_geometry_sphere_derive.js";
|
|
8
|
+
import {
|
|
9
|
+
shader_meshlet_bounds_reduce,
|
|
10
|
+
WORKGROUP_SIZE as BOUNDS_REDUCE_WORKGROUP_SIZE,
|
|
11
|
+
} from "./bounds_refresh/shader_meshlet_bounds_reduce.js";
|
|
12
|
+
import {
|
|
13
|
+
shader_meshlet_bounds_scatter,
|
|
14
|
+
WORKGROUP_SIZE as BOUNDS_SCATTER_WORKGROUP_SIZE,
|
|
15
|
+
} from "./bounds_refresh/shader_meshlet_bounds_scatter.js";
|
|
16
|
+
import {
|
|
17
|
+
shader_skinned_mesh_bounds_refresh,
|
|
18
|
+
WORKGROUP_SIZE as MESH_BOUNDS_REFRESH_WORKGROUP_SIZE,
|
|
19
|
+
} from "./bounds_refresh/shader_skinned_mesh_bounds_refresh.js";
|
|
20
|
+
import {
|
|
21
|
+
SKINNING_BINDING_STRUCT
|
|
22
|
+
} from "./SKINNING_BINDING_STRUCT.js";
|
|
23
|
+
import {
|
|
24
|
+
shader_meshlet_apply_skinning
|
|
25
|
+
} from "./shader_meshlet_apply_skinning.js";
|
|
26
|
+
import {
|
|
27
|
+
MESHLET_METADATA_STRUCT
|
|
28
|
+
} from "../../geometry/meshlet/encoding/MESHLET_METADATA_STRUCT.js";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Initial bindings-buffer capacity (in binding records). 16 × 16 bytes
|
|
32
|
+
* = 256 bytes — wasteful for a scene with no SkinnedMesh, but the
|
|
33
|
+
* doubling growth absorbs any larger scene cheaply.
|
|
34
|
+
*/
|
|
35
|
+
const BINDINGS_INITIAL_CAPACITY = 16;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Initial dispatch-lookup capacity (in `(binding_index, meshlet_local)`
|
|
39
|
+
* pairs, i.e. 8 bytes per slot). Sized to the same default a small
|
|
40
|
+
* skinned mesh produces.
|
|
41
|
+
*/
|
|
42
|
+
const DISPATCH_LOOKUP_INITIAL_CAPACITY = 256;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Initial `prev_positions_buffer` capacity in vertices. Each vertex
|
|
46
|
+
* is 3 × f32 = 12 bytes. 1024 vertices → 12 KB. Doubles on grow.
|
|
47
|
+
*/
|
|
48
|
+
const PREV_POSITIONS_INITIAL_CAPACITY_VERTICES = 1024;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Initial `prev_position_offsets_buffer` capacity in u32 records
|
|
52
|
+
* (one per meshlet metadata row). 1024 × 4 = 4 KB. Doubles on grow.
|
|
53
|
+
*/
|
|
54
|
+
const PREV_POSITION_OFFSETS_INITIAL_CAPACITY = 1024;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Sentinel value in `prev_position_offsets` for meshlet metadata
|
|
58
|
+
* rows that are NOT skinned clones — sources, static-mesh geometries,
|
|
59
|
+
* pre-skinning clones (rare), etc. The skinning shader sees this
|
|
60
|
+
* value and skips its `position_prev` write; the velocity post-pass
|
|
61
|
+
* sees it and falls back to the rigid per-object math.
|
|
62
|
+
*/
|
|
63
|
+
const PREV_POSITION_OFFSET_INVALID = 0xFFFFFFFF;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* f32 vertex_count byte offset within MESHLET_METADATA_STRUCT, resolved
|
|
67
|
+
* at module load (after `.pack()` reorders fields). Used by the CPU
|
|
68
|
+
* binding-registration path to walk the source's metadata bytes and
|
|
69
|
+
* sum vertex counts for prev-position side-buffer allocation.
|
|
70
|
+
*/
|
|
71
|
+
const MESHLET_VERTEX_COUNT_BYTE_OFFSET = MESHLET_METADATA_STRUCT.get('vertex_count').offset;
|
|
72
|
+
const MESHLET_STRIDE_BYTES = MESHLET_METADATA_STRUCT.aligned_size;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Per-scene container for the skinning subsystem's state. Owned by
|
|
76
|
+
* {@link GPUSceneContext}; receives the scene's
|
|
77
|
+
* {@link GPUGeometryManager} so it can allocate per-instance geometry
|
|
78
|
+
* clones for {@link SkinnedMesh} instances and route the skinning
|
|
79
|
+
* compute pass against those clones.
|
|
80
|
+
*
|
|
81
|
+
* Three responsibilities:
|
|
82
|
+
* 1. Geometry-clone routing — `obtain_geometry_index(mesh)` returns
|
|
83
|
+
* the clone id for SkinnedMesh, the source id for everyone else.
|
|
84
|
+
* 2. Skinning binding bookkeeping — each SkinnedMesh with a `skin_id`
|
|
85
|
+
* produces one binding record linking its clone's vertex region
|
|
86
|
+
* back to the source's data and to the skin's matrix range.
|
|
87
|
+
* 3. Per-frame dispatch — `update(cmd_ctx, animation_manager)`
|
|
88
|
+
* uploads any new bindings and dispatches the skinning compute
|
|
89
|
+
* pass that deforms the cloned vertex regions in place.
|
|
90
|
+
*
|
|
91
|
+
* The CPU-side binding records cache `skin_id` rather than
|
|
92
|
+
* `skin_matrix_offset` because the offset is owned by the animation
|
|
93
|
+
* manager. Resolution happens at upload time via
|
|
94
|
+
* `animation_manager.get_skin_matrix_offset(skin_id)`.
|
|
95
|
+
*/
|
|
96
|
+
export class GPUMeshSkinningContext {
|
|
97
|
+
|
|
98
|
+
/** @type {GPUDevice} */
|
|
99
|
+
#device;
|
|
100
|
+
|
|
101
|
+
/** @type {GPUGeometryManager} */
|
|
102
|
+
#geometries;
|
|
103
|
+
|
|
104
|
+
/** @type {GPUAnimationManager} */
|
|
105
|
+
#animation_manager;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Per-SkinnedMesh clone metadata, cached so repeated lookups
|
|
109
|
+
* (binding-registration, geometry id resolution) hit the same
|
|
110
|
+
* record rather than re-cloning the source. Persists across
|
|
111
|
+
* scene rebuilds (unlike id_mapping).
|
|
112
|
+
*
|
|
113
|
+
* @type {Map<SkinnedMesh, GPUGeometryMetadata>}
|
|
114
|
+
*/
|
|
115
|
+
#clones = new Map();
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Per-mesh skin assignment. Populated by {@link bind}; consumed
|
|
119
|
+
* by {@link #register_binding} when it stamps the GPU binding
|
|
120
|
+
* record. A mesh present here has had a skinning binding
|
|
121
|
+
* registered exactly once — re-binding the same mesh is a
|
|
122
|
+
* no-op (the existing binding stands).
|
|
123
|
+
*
|
|
124
|
+
* Held here rather than on the {@link SkinnedMesh} so the public
|
|
125
|
+
* mesh class doesn't carry GPU-side state; consumers who need
|
|
126
|
+
* to look up "what skin is mesh X bound to?" can query via
|
|
127
|
+
* {@link get_skin_id}.
|
|
128
|
+
*
|
|
129
|
+
* @type {Map<SkinnedMesh, number>}
|
|
130
|
+
*/
|
|
131
|
+
#skin_id_by_mesh = new Map();
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* One CPU record per `(SkinnedMesh, clone)` binding registered via
|
|
135
|
+
* {@link #register_binding}. Resolved into GPU bytes at upload
|
|
136
|
+
* time — `skin_id` becomes `skin_matrix_offset` via
|
|
137
|
+
* {@link GPUAnimationManager#get_skin_matrix_offset}, and `mesh`
|
|
138
|
+
* becomes a meshes-table row via
|
|
139
|
+
* {@link GPUSceneContext#mesh_row_of}. The mesh is held rather
|
|
140
|
+
* than its row because the row is not stable: registration
|
|
141
|
+
* happens before the scene has placed the mesh at all, and the
|
|
142
|
+
* table reuses rows afterwards.
|
|
143
|
+
*
|
|
144
|
+
* Append-only in this MVP — removing a SkinnedMesh leaks its
|
|
145
|
+
* binding (alongside its clone). Acceptable at the lifetime-
|
|
146
|
+
* distinct-instance scale; phase-4 frees both together.
|
|
147
|
+
*
|
|
148
|
+
* @type {{
|
|
149
|
+
* skin_id: number,
|
|
150
|
+
* mesh: SkinnedMesh,
|
|
151
|
+
* source_meshlet_metadata_offset: number,
|
|
152
|
+
* clone_meshlet_metadata_offset: number,
|
|
153
|
+
* meshlet_count: number,
|
|
154
|
+
* clone_geometry_index: number,
|
|
155
|
+
* }[]}
|
|
156
|
+
*/
|
|
157
|
+
#bindings = [];
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Sum of {@link #bindings}[i].meshlet_count — the dispatch-lookup
|
|
161
|
+
* length and the workgroup count for the skinning compute pass.
|
|
162
|
+
* Tracked incrementally to avoid re-summing per frame.
|
|
163
|
+
* @type {number}
|
|
164
|
+
*/
|
|
165
|
+
#total_meshlet_count = 0;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Set when {@link #bindings} has changed since the last upload.
|
|
169
|
+
* Cleared by {@link update} after re-uploading both the bindings
|
|
170
|
+
* buffer and the dispatch-lookup buffer.
|
|
171
|
+
* @type {boolean}
|
|
172
|
+
*/
|
|
173
|
+
#bindings_dirty = false;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* The scene context's {@link GPUSceneContext#mesh_rows_version} as of the last bindings upload.
|
|
177
|
+
* The records hold meshes-table rows and that table reuses them, so a difference here means
|
|
178
|
+
* every record's row has to be resolved again.
|
|
179
|
+
*
|
|
180
|
+
* @type {number}
|
|
181
|
+
*/
|
|
182
|
+
#uploaded_mesh_rows_version = -1;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* GPU mirror of {@link #bindings}, with `skin_id` resolved to
|
|
186
|
+
* `skin_matrix_offset`. `null` until the first binding is
|
|
187
|
+
* registered.
|
|
188
|
+
* @type {GPUBuffer|null}
|
|
189
|
+
*/
|
|
190
|
+
#bindings_buffer = null;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Capacity of {@link #bindings_buffer} in binding records. Grows
|
|
194
|
+
* by doubling when a new binding pushes past it.
|
|
195
|
+
* @type {number}
|
|
196
|
+
*/
|
|
197
|
+
#bindings_capacity = 0;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Flat `(binding_index, meshlet_local_index)` u32 pairs — one pair
|
|
201
|
+
* per workgroup. The skinning shader reads `dispatch_lookup[wg_id]`
|
|
202
|
+
* to figure out which (binding, meshlet) it's processing.
|
|
203
|
+
* @type {GPUBuffer|null}
|
|
204
|
+
*/
|
|
205
|
+
#dispatch_lookup_buffer = null;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Capacity of {@link #dispatch_lookup_buffer} in `(binding,
|
|
209
|
+
* meshlet)` pairs (i.e. half the u32 count). Grows by doubling.
|
|
210
|
+
* @type {number}
|
|
211
|
+
*/
|
|
212
|
+
#dispatch_lookup_capacity = 0;
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Side-buffer holding the previous-frame mesh-local skinned
|
|
216
|
+
* positions for every clone meshlet's vertices. Laid out as
|
|
217
|
+
* tightly-packed `vec3<f32>` (3 × u32 words, f32 bit pattern)
|
|
218
|
+
* per vertex; each clone meshlet owns a contiguous slice of
|
|
219
|
+
* `vertex_count` vec3s starting at the offset recorded in
|
|
220
|
+
* {@link #prev_position_offsets_buffer}.
|
|
221
|
+
*
|
|
222
|
+
* Written by the skinning compute shader (using the manager's
|
|
223
|
+
* `prev_skin_matrices_buffer`), read by the velocity post-pass
|
|
224
|
+
* to interpolate per-vertex skin deformation across the rasterized
|
|
225
|
+
* triangle.
|
|
226
|
+
*
|
|
227
|
+
* Append-only — bindings reserve contiguous vertex ranges via
|
|
228
|
+
* {@link #next_prev_position_vertex_offset}; nothing frees.
|
|
229
|
+
*
|
|
230
|
+
* @type {GPUBuffer|null}
|
|
231
|
+
*/
|
|
232
|
+
#prev_positions_buffer = null;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Capacity of {@link #prev_positions_buffer} in vertices (each
|
|
236
|
+
* vertex = 3 × u32 words).
|
|
237
|
+
* @type {number}
|
|
238
|
+
*/
|
|
239
|
+
#prev_positions_capacity_vertices = 0;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Next free vertex slot in {@link #prev_positions_buffer}. Each
|
|
243
|
+
* binding registration reserves `sum(vertex_count)` vertices
|
|
244
|
+
* starting here and advances by that amount. Monotonic.
|
|
245
|
+
* @type {number}
|
|
246
|
+
*/
|
|
247
|
+
#next_prev_position_vertex_offset = 0;
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Per-meshlet base offset (in u32 words) into
|
|
251
|
+
* {@link #prev_positions_buffer}. Indexed by absolute meshlet
|
|
252
|
+
* metadata row — `prev_position_offsets[meshlet_index]` gives
|
|
253
|
+
* either {@link PREV_POSITION_OFFSET_INVALID} (non-clone or
|
|
254
|
+
* not-yet-bound meshlet) or the first u32 word of that
|
|
255
|
+
* meshlet's prev-position slice.
|
|
256
|
+
*
|
|
257
|
+
* Sized to the meshlet metadata buffer's record capacity (or
|
|
258
|
+
* larger). Re-uploaded from the CPU shadow whenever a new
|
|
259
|
+
* binding adds entries.
|
|
260
|
+
*
|
|
261
|
+
* @type {GPUBuffer|null}
|
|
262
|
+
*/
|
|
263
|
+
#prev_position_offsets_buffer = null;
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Capacity of {@link #prev_position_offsets_buffer} in u32
|
|
267
|
+
* records (= one per meshlet metadata row).
|
|
268
|
+
* @type {number}
|
|
269
|
+
*/
|
|
270
|
+
#prev_position_offsets_capacity = 0;
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* CPU shadow of {@link #prev_position_offsets_buffer}. Mutated
|
|
274
|
+
* by {@link #register_binding} when computing per-meshlet offsets;
|
|
275
|
+
* re-uploaded wholesale by {@link #upload_prev_position_offsets}.
|
|
276
|
+
* Entries default to {@link PREV_POSITION_OFFSET_INVALID}.
|
|
277
|
+
*
|
|
278
|
+
* @type {Uint32Array}
|
|
279
|
+
*/
|
|
280
|
+
#prev_position_offsets_cpu = new Uint32Array(0);
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Back-reference to the owning {@link GPUSceneContext} so the
|
|
284
|
+
* bindings-upload path can resolve a mesh to its meshes-table row
|
|
285
|
+
* via {@link GPUSceneContext#mesh_row_of} without the caller
|
|
286
|
+
* threading that lookup through every `bind()` call.
|
|
287
|
+
*
|
|
288
|
+
* Resolution cannot happen at registration time: `bind` and
|
|
289
|
+
* `obtain_geometry_index` both run before `scene.build` has given
|
|
290
|
+
* the mesh a row. Nor does resolving once suffice — the table
|
|
291
|
+
* hands out the lowest free row, so a mesh that leaves and
|
|
292
|
+
* re-enters the scene lands somewhere else, which is what
|
|
293
|
+
* {@link GPUSceneContext#mesh_rows_version} is compared for.
|
|
294
|
+
*
|
|
295
|
+
* @type {GPUSceneContext}
|
|
296
|
+
*/
|
|
297
|
+
#scene_context;
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* @param {{
|
|
301
|
+
* geometries: GPUGeometryManager,
|
|
302
|
+
* animation_manager: GPUAnimationManager,
|
|
303
|
+
* scene_context: GPUSceneContext,
|
|
304
|
+
* device: GPUDevice,
|
|
305
|
+
* }} args
|
|
306
|
+
*/
|
|
307
|
+
constructor({ geometries, animation_manager, scene_context, device }) {
|
|
308
|
+
assert.defined(geometries, 'geometries');
|
|
309
|
+
assert.defined(animation_manager, 'animation_manager');
|
|
310
|
+
assert.defined(scene_context, 'scene_context');
|
|
311
|
+
assert.defined(device, 'device');
|
|
312
|
+
|
|
313
|
+
this.#geometries = geometries;
|
|
314
|
+
this.#animation_manager = animation_manager;
|
|
315
|
+
this.#scene_context = scene_context;
|
|
316
|
+
this.#device = device;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Side-buffer of previous-frame mesh-local skinned positions for
|
|
321
|
+
* the velocity post-pass. `null` until the first skinning binding
|
|
322
|
+
* has been registered.
|
|
323
|
+
*
|
|
324
|
+
* @returns {GPUBuffer|null}
|
|
325
|
+
*/
|
|
326
|
+
get prev_positions_buffer() {
|
|
327
|
+
return this.#prev_positions_buffer;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* The binding records the skinning pass reads — one {@link SKINNING_BINDING_STRUCT} per bound
|
|
332
|
+
* {@link SkinnedMesh}, in {@link #bindings} order. `null` until the first binding has been
|
|
333
|
+
* registered and uploaded.
|
|
334
|
+
*
|
|
335
|
+
* @returns {GPUBuffer|null}
|
|
336
|
+
*/
|
|
337
|
+
get bindings_buffer() {
|
|
338
|
+
return this.#bindings_buffer;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Per-meshlet base offsets into {@link prev_positions_buffer},
|
|
343
|
+
* indexed by absolute meshlet metadata row. Non-clone meshlets
|
|
344
|
+
* hold the sentinel `0xFFFFFFFF`. `null` until the first
|
|
345
|
+
* skinning binding has been registered.
|
|
346
|
+
*
|
|
347
|
+
* @returns {GPUBuffer|null}
|
|
348
|
+
*/
|
|
349
|
+
get prev_position_offsets_buffer() {
|
|
350
|
+
return this.#prev_position_offsets_buffer;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Geometry id to assign to this mesh's instance record. Idempotent.
|
|
355
|
+
*
|
|
356
|
+
* - For a {@link SkinnedMesh}: a per-instance clone of the source's
|
|
357
|
+
* GPU geometry. The first time we see a given mesh, allocate a
|
|
358
|
+
* clone; subsequent calls return the cached id. If the mesh has
|
|
359
|
+
* already been bound to a skin via {@link bind}, the binding's
|
|
360
|
+
* registration also runs here so scene.build's first sight of
|
|
361
|
+
* a pre-bound mesh doesn't strand it without a deformation pass.
|
|
362
|
+
* - For a regular {@link Mesh}: the source's id from the geometry
|
|
363
|
+
* manager.
|
|
364
|
+
*
|
|
365
|
+
* @param {Mesh} mesh
|
|
366
|
+
* @returns {number}
|
|
367
|
+
*/
|
|
368
|
+
obtain_geometry_index(mesh) {
|
|
369
|
+
if (mesh.isSkinnedMesh === true) {
|
|
370
|
+
const clone_metadata = this.#ensure_clone(mesh);
|
|
371
|
+
// If the mesh has already been bound (bind() ran before
|
|
372
|
+
// scene.build for this mesh), register its binding now.
|
|
373
|
+
// No-op if not yet bound or if the binding has already
|
|
374
|
+
// been registered in a previous call.
|
|
375
|
+
this.#try_register_binding(mesh, clone_metadata);
|
|
376
|
+
return clone_metadata.index;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
this.#geometries.add(mesh.geometry);
|
|
380
|
+
return this.#geometries.getAddress(mesh.geometry);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Bind a {@link SkinnedMesh} to a skin. The mesh's clone (if not
|
|
385
|
+
* already allocated) is created on demand; a skinning-pass
|
|
386
|
+
* binding record is registered so the deformation runs each
|
|
387
|
+
* frame. The skin id is stored on the context (not on the mesh
|
|
388
|
+
* — `SkinnedMesh` carries no GPU state).
|
|
389
|
+
*
|
|
390
|
+
* Re-binding the same mesh with a different skin id is rejected
|
|
391
|
+
* (single-binding model in this MVP — use {@link unbind} first if
|
|
392
|
+
* you need to swap). Calling with the same skin id is a no-op.
|
|
393
|
+
*
|
|
394
|
+
* Tolerates being called before `scene.build` registers the mesh;
|
|
395
|
+
* the binding upload happens during the next per-frame
|
|
396
|
+
* {@link update}.
|
|
397
|
+
*
|
|
398
|
+
* @param {SkinnedMesh} mesh
|
|
399
|
+
* @param {number} skin_id
|
|
400
|
+
*/
|
|
401
|
+
bind(mesh, skin_id) {
|
|
402
|
+
assert.defined(mesh, 'mesh');
|
|
403
|
+
assert.equal(mesh.isSkinnedMesh, true, 'mesh.isSkinnedMesh !== true');
|
|
404
|
+
assert.isNonNegativeInteger(skin_id, 'skin_id');
|
|
405
|
+
|
|
406
|
+
const existing = this.#skin_id_by_mesh.get(mesh);
|
|
407
|
+
if (existing !== undefined) {
|
|
408
|
+
assert.equal(
|
|
409
|
+
existing, skin_id,
|
|
410
|
+
`SkinnedMesh '${mesh.name}' is already bound to skin ${existing}; unbind before rebinding`
|
|
411
|
+
);
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
this.#skin_id_by_mesh.set(mesh, skin_id);
|
|
416
|
+
const clone_metadata = this.#ensure_clone(mesh);
|
|
417
|
+
this.#try_register_binding(mesh, clone_metadata);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Skin id currently bound to this mesh, or `undefined` if the
|
|
422
|
+
* mesh hasn't been bound. Read-only accessor — bookkeeping lives
|
|
423
|
+
* here, not on the mesh.
|
|
424
|
+
*
|
|
425
|
+
* @param {SkinnedMesh} mesh
|
|
426
|
+
* @returns {number|undefined}
|
|
427
|
+
*/
|
|
428
|
+
get_skin_id(mesh) {
|
|
429
|
+
return this.#skin_id_by_mesh.get(mesh);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Drop the binding for a single mesh. The mesh's geometry clone
|
|
434
|
+
* stays allocated (deallocation needs compaction work the MVP
|
|
435
|
+
* doesn't do), but the per-frame deformation no longer runs for
|
|
436
|
+
* it — its vertices freeze at whatever the last skinning pass
|
|
437
|
+
* wrote.
|
|
438
|
+
*
|
|
439
|
+
* No-op if the mesh isn't bound.
|
|
440
|
+
*
|
|
441
|
+
* @param {SkinnedMesh} mesh
|
|
442
|
+
*/
|
|
443
|
+
unbind(mesh) {
|
|
444
|
+
if (!this.#skin_id_by_mesh.has(mesh)) return;
|
|
445
|
+
this.#skin_id_by_mesh.delete(mesh);
|
|
446
|
+
|
|
447
|
+
for (let i = this.#bindings.length - 1; i >= 0; i--) {
|
|
448
|
+
if (this.#bindings[i].mesh === mesh) {
|
|
449
|
+
this.#total_meshlet_count -= this.#bindings[i].meshlet_count;
|
|
450
|
+
this.#bindings.splice(i, 1);
|
|
451
|
+
this.#bindings_dirty = true;
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Drop every binding that points at the given skin id. Called
|
|
459
|
+
* by {@link GPUAnimationManager#unregister_skin} so freeing the
|
|
460
|
+
* skin's GPU rows also tears down the meshes' deformation
|
|
461
|
+
* registrations (which would otherwise try to look up the freed
|
|
462
|
+
* skin's matrix offset on the next bindings upload and assert).
|
|
463
|
+
*
|
|
464
|
+
* @param {number} skin_id
|
|
465
|
+
*/
|
|
466
|
+
unbind_all_by_skin(skin_id) {
|
|
467
|
+
for (let i = this.#bindings.length - 1; i >= 0; i--) {
|
|
468
|
+
const b = this.#bindings[i];
|
|
469
|
+
if (b.skin_id === skin_id) {
|
|
470
|
+
this.#skin_id_by_mesh.delete(b.mesh);
|
|
471
|
+
this.#total_meshlet_count -= b.meshlet_count;
|
|
472
|
+
this.#bindings.splice(i, 1);
|
|
473
|
+
this.#bindings_dirty = true;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Lookup-or-create the per-mesh clone metadata. Cached so that
|
|
480
|
+
* repeated lookups (binding-registration, geometry id resolution
|
|
481
|
+
* via obtain_geometry_index) hit the same record without
|
|
482
|
+
* re-cloning the source.
|
|
483
|
+
*
|
|
484
|
+
* @param {SkinnedMesh} mesh
|
|
485
|
+
* @returns {GPUGeometryMetadata}
|
|
486
|
+
*/
|
|
487
|
+
#ensure_clone(mesh) {
|
|
488
|
+
let clone_metadata = this.#clones.get(mesh);
|
|
489
|
+
if (clone_metadata === undefined) {
|
|
490
|
+
clone_metadata = this.#geometries.add_clone(mesh.geometry);
|
|
491
|
+
this.#clones.set(mesh, clone_metadata);
|
|
492
|
+
}
|
|
493
|
+
return clone_metadata;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Register a binding for this mesh if conditions allow:
|
|
498
|
+
* - the mesh has been bound to a skin via {@link bind}, AND
|
|
499
|
+
* - we haven't already registered the binding for this mesh.
|
|
500
|
+
*
|
|
501
|
+
* @param {SkinnedMesh} mesh
|
|
502
|
+
* @param {GPUGeometryMetadata} clone_metadata
|
|
503
|
+
*/
|
|
504
|
+
#try_register_binding(mesh, clone_metadata) {
|
|
505
|
+
const skin_id = this.#skin_id_by_mesh.get(mesh);
|
|
506
|
+
if (skin_id === undefined) return;
|
|
507
|
+
// The binding's presence in #bindings is the source of truth
|
|
508
|
+
// for "already registered". Cheap O(bindings) scan; bindings
|
|
509
|
+
// are O(skinned-mesh-count).
|
|
510
|
+
for (let i = 0; i < this.#bindings.length; i++) {
|
|
511
|
+
if (this.#bindings[i].mesh === mesh) return;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
this.#register_binding(mesh, clone_metadata, skin_id);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Per-frame: upload any new bindings + dispatch the skinning
|
|
519
|
+
* compute pass that deforms cloned vertex regions in place.
|
|
520
|
+
*
|
|
521
|
+
* No-op if no bindings have been registered. Upload is skipped
|
|
522
|
+
* when nothing's changed since the last call. Must run after
|
|
523
|
+
* `shader_skin_matrix_prep` (which fills the skin matrices the
|
|
524
|
+
* deformation reads) and before any pass that consumes the
|
|
525
|
+
* skinned vertex data.
|
|
526
|
+
*
|
|
527
|
+
* The animation manager passed at construction supplies
|
|
528
|
+
* `skin_matrices_buffer` and resolves `skin_id` →
|
|
529
|
+
* `skin_matrix_offset` for the binding records.
|
|
530
|
+
*
|
|
531
|
+
* @param {ShadeGPUCommandContext} cmd_ctx
|
|
532
|
+
*/
|
|
533
|
+
update(cmd_ctx) {
|
|
534
|
+
if (this.#bindings.length === 0) {
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// Flush any meshlet-clone work that hasn't been drained yet —
|
|
539
|
+
// typically happens on the first frame a fresh SkinnedMesh
|
|
540
|
+
// appears, when scene.build queues a clone in `pending_clones`
|
|
541
|
+
// but the per-frame `graphics.update` flush already ran earlier
|
|
542
|
+
// in the same frame. Without this, the skinning shader would
|
|
543
|
+
// read the cloned meshlet record before its `address` field
|
|
544
|
+
// got memcpy'd + patched (zero-initialized backing buffer →
|
|
545
|
+
// address 0), and writes would land at the start of the data
|
|
546
|
+
// buffer, corrupting whatever geometry sits there. Idempotent /
|
|
547
|
+
// no-op when nothing's pending, so repeat calls in subsequent
|
|
548
|
+
// frames are free.
|
|
549
|
+
//
|
|
550
|
+
// We call directly into `geometries.meshlets.update` rather
|
|
551
|
+
// than `geometries.update`: the latter also rebuilds the
|
|
552
|
+
// geometry metadata buffer (destroying + recreating it) when
|
|
553
|
+
// `__needs_update` is set, but the FrameGraph passes that
|
|
554
|
+
// already encoded into this cmd_ctx have captured the old
|
|
555
|
+
// buffer reference. Destroying it mid-cmd-context produces a
|
|
556
|
+
// "used in submit while destroyed" validation error. The
|
|
557
|
+
// metadata-buffer rebuild is the *next* GraphicsContext.update's
|
|
558
|
+
// job; here we just need the meshlet pending-clone flush.
|
|
559
|
+
this.#geometries.meshlets.update(cmd_ctx);
|
|
560
|
+
|
|
561
|
+
// The binding record carries a meshes-table row, and that table reuses rows: a scene the
|
|
562
|
+
// mesh left and re-entered puts it somewhere else, and every other binding's row can move
|
|
563
|
+
// out from under it too. So the records are re-resolved whenever the table's membership has
|
|
564
|
+
// changed since they were written, not only when a binding was added or dropped.
|
|
565
|
+
const mesh_rows_version = this.#scene_context.mesh_rows_version;
|
|
566
|
+
|
|
567
|
+
if (this.#bindings_dirty || this.#uploaded_mesh_rows_version !== mesh_rows_version) {
|
|
568
|
+
this.#upload_bindings();
|
|
569
|
+
|
|
570
|
+
this.#uploaded_mesh_rows_version = mesh_rows_version;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
if (this.#bindings_dirty) {
|
|
574
|
+
// Neither of these reads anything outside the binding list, so a scene edit that left
|
|
575
|
+
// the list alone cannot have moved them.
|
|
576
|
+
this.#upload_dispatch_lookup();
|
|
577
|
+
this.#upload_prev_position_offsets();
|
|
578
|
+
this.#bindings_dirty = false;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const meshlets = this.#geometries.meshlets;
|
|
582
|
+
const total = this.#total_meshlet_count;
|
|
583
|
+
const binding_count = this.#bindings.length;
|
|
584
|
+
const max_workgroups = this.#device.limits.maxComputeWorkgroupsPerDimension;
|
|
585
|
+
|
|
586
|
+
// ── Skinning: deform the cloned vertex regions ────────────
|
|
587
|
+
//
|
|
588
|
+
// WebGPU's `dispatchWorkgroups` is capped at the device's
|
|
589
|
+
// `maxComputeWorkgroupsPerDimension` (65535 is the spec
|
|
590
|
+
// minimum; modern desktop GPUs typically report higher).
|
|
591
|
+
// With one workgroup per (binding, meshlet) pair, a busy
|
|
592
|
+
// scene (e.g. a grid of skinned characters) can exceed that
|
|
593
|
+
// — 324 dancers × ~220 meshlets each ≈ 71K pairs.
|
|
594
|
+
//
|
|
595
|
+
// Split into sub-dispatches when needed, passing
|
|
596
|
+
// `dispatch_offset` so the shader's lookup-index arithmetic
|
|
597
|
+
// keeps indexing a flat `dispatch_lookup` table. The encoded
|
|
598
|
+
// cost grows linearly in sub-dispatch count, but the GPU
|
|
599
|
+
// work is identical to a single huge dispatch.
|
|
600
|
+
for (let offset = 0; offset < total; offset += max_workgroups) {
|
|
601
|
+
const this_chunk = Math.min(max_workgroups, total - offset);
|
|
602
|
+
const dispatch_offset = cmd_ctx.allocateTransientValueBuffer(u32, offset);
|
|
603
|
+
|
|
604
|
+
shader_meshlet_apply_skinning.dispatch({
|
|
605
|
+
encoder: cmd_ctx,
|
|
606
|
+
group_count_x: this_chunk,
|
|
607
|
+
bindings: {
|
|
608
|
+
dispatch_offset,
|
|
609
|
+
meshlet_data: meshlets.buffer_data,
|
|
610
|
+
meshlet_metadata: meshlets.buffer_metadata,
|
|
611
|
+
skin_matrices: this.#animation_manager.skin_matrices_buffer,
|
|
612
|
+
prev_skin_matrices: this.#animation_manager.prev_skin_matrices_buffer,
|
|
613
|
+
skinning_bindings: this.#bindings_buffer,
|
|
614
|
+
dispatch_lookup: this.#dispatch_lookup_buffer,
|
|
615
|
+
prev_position_offsets: this.#prev_position_offsets_buffer,
|
|
616
|
+
prev_positions: this.#prev_positions_buffer,
|
|
617
|
+
// Skinning shader reads the SkinnedMesh's
|
|
618
|
+
// `transforms` row to source the live
|
|
619
|
+
// mesh.transform_global for the post-DQ
|
|
620
|
+
// position cancellation.
|
|
621
|
+
scene_database: this.#scene_context.scene_database_buffer,
|
|
622
|
+
},
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// ── Bounds refresh chain ──────────────────────────────────
|
|
627
|
+
//
|
|
628
|
+
// Animated clones move outside their source-encoded bounds;
|
|
629
|
+
// the rasterizer's per-meshlet AABB cull and per-mesh sphere
|
|
630
|
+
// cull would reject them until we refresh both. The chain
|
|
631
|
+
// here runs every frame the skinning dispatched anything
|
|
632
|
+
// (cheap when nothing changed: dispatch overhead only, the
|
|
633
|
+
// shaders early-out on the workgroup boundary).
|
|
634
|
+
//
|
|
635
|
+
// Order is load-bearing:
|
|
636
|
+
// 1. scatter — reset meshlet.bounds_box / geometry.bounding_box to ±inf
|
|
637
|
+
// 2. reduce — atomic-merge per-vertex into meshlet + geometry box
|
|
638
|
+
// 3. derive — geometry box → geometry sphere (per binding)
|
|
639
|
+
// 4. mesh — geometry box+sphere → world-space mesh bounds (per binding)
|
|
640
|
+
//
|
|
641
|
+
// The same `dispatch_lookup` table that drove the skinning
|
|
642
|
+
// dispatch above also drives the scatter and reduce dispatches
|
|
643
|
+
// — every (binding, meshlet) pair gets exactly the same set
|
|
644
|
+
// of workgroups, just running different shaders.
|
|
645
|
+
const geometry_metadata_buffer = this.#geometries.buffer_metadata;
|
|
646
|
+
const scene_database_buffer = this.#scene_context.scene_database_buffer;
|
|
647
|
+
|
|
648
|
+
// ── 1. Scatter: ±inf sentinels into meshlet + geometry bounds.
|
|
649
|
+
// Linear-thread dispatch: WG_SIZE threads per workgroup, one
|
|
650
|
+
// thread per pair. With WG_SIZE = 64 the workgroup count is
|
|
651
|
+
// ceil(total/64) — single sub-dispatch except at extreme
|
|
652
|
+
// scale (~4M pairs).
|
|
653
|
+
{
|
|
654
|
+
const total_workgroups = Math.ceil(total / BOUNDS_SCATTER_WORKGROUP_SIZE);
|
|
655
|
+
for (let offset_wg = 0; offset_wg < total_workgroups; offset_wg += max_workgroups) {
|
|
656
|
+
const this_chunk = Math.min(max_workgroups, total_workgroups - offset_wg);
|
|
657
|
+
// dispatch_offset is in *pair* units for scatter — the
|
|
658
|
+
// shader does `gid.x + dispatch_offset`.
|
|
659
|
+
const dispatch_offset = cmd_ctx.allocateTransientValueBuffer(
|
|
660
|
+
u32,
|
|
661
|
+
offset_wg * BOUNDS_SCATTER_WORKGROUP_SIZE
|
|
662
|
+
);
|
|
663
|
+
const total_pair_count = cmd_ctx.allocateTransientValueBuffer(u32, total);
|
|
664
|
+
shader_meshlet_bounds_scatter.dispatch({
|
|
665
|
+
encoder: cmd_ctx,
|
|
666
|
+
group_count_x: this_chunk,
|
|
667
|
+
bindings: {
|
|
668
|
+
dispatch_offset,
|
|
669
|
+
total_pair_count,
|
|
670
|
+
skinning_bindings: this.#bindings_buffer,
|
|
671
|
+
dispatch_lookup: this.#dispatch_lookup_buffer,
|
|
672
|
+
meshlet_metadata_atomic: meshlets.buffer_metadata,
|
|
673
|
+
geometry_metadata_atomic: geometry_metadata_buffer,
|
|
674
|
+
},
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// ── 2. Reduce: per-meshlet workgroup, merges into meshlet +
|
|
680
|
+
// geometry box atomically. Same workgroup-per-pair pattern as
|
|
681
|
+
// skinning; same pagination.
|
|
682
|
+
for (let offset = 0; offset < total; offset += max_workgroups) {
|
|
683
|
+
const this_chunk = Math.min(max_workgroups, total - offset);
|
|
684
|
+
const dispatch_offset = cmd_ctx.allocateTransientValueBuffer(u32, offset);
|
|
685
|
+
|
|
686
|
+
shader_meshlet_bounds_reduce.dispatch({
|
|
687
|
+
encoder: cmd_ctx,
|
|
688
|
+
group_count_x: this_chunk,
|
|
689
|
+
bindings: {
|
|
690
|
+
dispatch_offset,
|
|
691
|
+
skinning_bindings: this.#bindings_buffer,
|
|
692
|
+
dispatch_lookup: this.#dispatch_lookup_buffer,
|
|
693
|
+
meshlet_data: meshlets.buffer_data,
|
|
694
|
+
meshlet_metadata_atomic: meshlets.buffer_metadata,
|
|
695
|
+
geometry_metadata_atomic: geometry_metadata_buffer,
|
|
696
|
+
},
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// ── 3. Sphere derive: per binding, geometry box → sphere.
|
|
701
|
+
// Linear-thread dispatch, sized to ceil(binding_count/64).
|
|
702
|
+
// Binding count is small (one per active SkinnedMesh, so
|
|
703
|
+
// hundreds at most), single sub-dispatch always suffices.
|
|
704
|
+
{
|
|
705
|
+
const total_workgroups = Math.ceil(binding_count / SPHERE_DERIVE_WORKGROUP_SIZE);
|
|
706
|
+
if (total_workgroups > 0) {
|
|
707
|
+
const binding_count_u = cmd_ctx.allocateTransientValueBuffer(u32, binding_count);
|
|
708
|
+
shader_geometry_sphere_derive.dispatch({
|
|
709
|
+
encoder: cmd_ctx,
|
|
710
|
+
group_count_x: total_workgroups,
|
|
711
|
+
bindings: {
|
|
712
|
+
binding_count: binding_count_u,
|
|
713
|
+
skinning_bindings: this.#bindings_buffer,
|
|
714
|
+
geometry_metadata_atomic: geometry_metadata_buffer,
|
|
715
|
+
},
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// ── 4. Mesh-instance bounds: per binding, geometry → world
|
|
721
|
+
// mesh bounds. Reuses the existing per-mesh bounds chunk
|
|
722
|
+
// (sphere radius scaled by max-column-length of the
|
|
723
|
+
// transform 3×3, conservative under non-uniform scale).
|
|
724
|
+
{
|
|
725
|
+
const total_workgroups = Math.ceil(binding_count / MESH_BOUNDS_REFRESH_WORKGROUP_SIZE);
|
|
726
|
+
if (total_workgroups > 0) {
|
|
727
|
+
const binding_count_u = cmd_ctx.allocateTransientValueBuffer(u32, binding_count);
|
|
728
|
+
shader_skinned_mesh_bounds_refresh.dispatch({
|
|
729
|
+
encoder: cmd_ctx,
|
|
730
|
+
group_count_x: total_workgroups,
|
|
731
|
+
bindings: {
|
|
732
|
+
binding_count: binding_count_u,
|
|
733
|
+
skinning_bindings: this.#bindings_buffer,
|
|
734
|
+
scene_database: scene_database_buffer,
|
|
735
|
+
geometries: geometry_metadata_buffer,
|
|
736
|
+
},
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* @param {SkinnedMesh} mesh
|
|
744
|
+
* @param {GPUGeometryMetadata} clone_metadata
|
|
745
|
+
* @param {number} skin_id
|
|
746
|
+
*/
|
|
747
|
+
#register_binding(mesh, clone_metadata, skin_id) {
|
|
748
|
+
const source_metadata = this.#geometries.get_metadata(mesh.geometry);
|
|
749
|
+
assert.defined(source_metadata, 'source_metadata');
|
|
750
|
+
|
|
751
|
+
const meshlet_count = clone_metadata.meshlets.meshlet_count;
|
|
752
|
+
const clone_meshlet_metadata_offset = clone_metadata.meshlets.metadata.offset;
|
|
753
|
+
|
|
754
|
+
this.#bindings.push({
|
|
755
|
+
skin_id,
|
|
756
|
+
mesh,
|
|
757
|
+
source_meshlet_metadata_offset: source_metadata.meshlets.metadata.offset,
|
|
758
|
+
clone_meshlet_metadata_offset,
|
|
759
|
+
meshlet_count,
|
|
760
|
+
clone_geometry_index: clone_metadata.index,
|
|
761
|
+
});
|
|
762
|
+
this.#total_meshlet_count += meshlet_count;
|
|
763
|
+
this.#bindings_dirty = true;
|
|
764
|
+
|
|
765
|
+
// ── Prev-position side-buffer bookkeeping ────────────────
|
|
766
|
+
//
|
|
767
|
+
// Walk the source's CPU metadata bytes to sum vertex counts
|
|
768
|
+
// (source and clone share the same vertex counts per
|
|
769
|
+
// meshlet — the clone is a memcpy of the source data). Each
|
|
770
|
+
// clone meshlet gets a contiguous (vertex_count × 3 u32)
|
|
771
|
+
// slot in the prev_positions side-buffer; record its base
|
|
772
|
+
// word offset in the per-meshlet offsets table indexed by
|
|
773
|
+
// absolute clone meshlet metadata row.
|
|
774
|
+
//
|
|
775
|
+
// `metadata_buffer_original` comes from `BinaryBuffer.data`
|
|
776
|
+
// and IS the raw `ArrayBuffer` (not a typed-array view), so
|
|
777
|
+
// we wrap it in a DataView directly without dereferencing
|
|
778
|
+
// a `.buffer` property.
|
|
779
|
+
const metadata_bytes = source_metadata.meshlets.metadata_buffer_original;
|
|
780
|
+
const view = new DataView(metadata_bytes);
|
|
781
|
+
|
|
782
|
+
// Phase 1: sum total vertices so we can grow the side-buffer
|
|
783
|
+
// up front, before recording per-meshlet offsets.
|
|
784
|
+
let total_vertices = 0;
|
|
785
|
+
for (let i = 0; i < meshlet_count; i++) {
|
|
786
|
+
const vc = view.getUint32(i * MESHLET_STRIDE_BYTES + MESHLET_VERTEX_COUNT_BYTE_OFFSET, true);
|
|
787
|
+
total_vertices += vc;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
const base_vertex_offset = this.#next_prev_position_vertex_offset;
|
|
791
|
+
this.#next_prev_position_vertex_offset += total_vertices;
|
|
792
|
+
|
|
793
|
+
this.#ensure_prev_positions_capacity_vertices(this.#next_prev_position_vertex_offset);
|
|
794
|
+
this.#ensure_prev_position_offsets_capacity(clone_meshlet_metadata_offset + meshlet_count);
|
|
795
|
+
|
|
796
|
+
// Phase 2: per-meshlet offsets. Convert (vertex slot)
|
|
797
|
+
// to u32-word offset (× 3) since the side-buffer stores
|
|
798
|
+
// 3 × f32 per vertex back-to-back.
|
|
799
|
+
let cumulative_vertex_offset = 0;
|
|
800
|
+
for (let i = 0; i < meshlet_count; i++) {
|
|
801
|
+
const vc = view.getUint32(i * MESHLET_STRIDE_BYTES + MESHLET_VERTEX_COUNT_BYTE_OFFSET, true);
|
|
802
|
+
const meshlet_word_offset = (base_vertex_offset + cumulative_vertex_offset) * 3;
|
|
803
|
+
this.#prev_position_offsets_cpu[clone_meshlet_metadata_offset + i] = meshlet_word_offset;
|
|
804
|
+
cumulative_vertex_offset += vc;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/**
|
|
809
|
+
* Grow {@link #prev_positions_buffer} to fit at least
|
|
810
|
+
* `required_vertices` vertices. Doubles from
|
|
811
|
+
* {@link PREV_POSITIONS_INITIAL_CAPACITY_VERTICES}. The buffer's
|
|
812
|
+
* contents are scratch (rewritten every frame by the skinning
|
|
813
|
+
* compute pass), so growth doesn't copy data — but the reference
|
|
814
|
+
* is invalidated, so callers must re-fetch through the getter.
|
|
815
|
+
*
|
|
816
|
+
* @param {number} required_vertices
|
|
817
|
+
*/
|
|
818
|
+
#ensure_prev_positions_capacity_vertices(required_vertices) {
|
|
819
|
+
if (this.#prev_positions_buffer !== null && required_vertices <= this.#prev_positions_capacity_vertices) {
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
let new_capacity = Math.max(
|
|
824
|
+
this.#prev_positions_capacity_vertices,
|
|
825
|
+
PREV_POSITIONS_INITIAL_CAPACITY_VERTICES,
|
|
826
|
+
);
|
|
827
|
+
while (new_capacity < required_vertices) {
|
|
828
|
+
new_capacity *= 2;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
if (this.#prev_positions_buffer !== null) {
|
|
832
|
+
this.#prev_positions_buffer.destroy();
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// 3 × u32 per vertex (each u32 carries an f32 bit pattern).
|
|
836
|
+
this.#prev_positions_buffer = this.#device.createBuffer({
|
|
837
|
+
label: 'GPUMeshSkinningContext/PrevPositions',
|
|
838
|
+
size: new_capacity * 3 * 4,
|
|
839
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
|
|
840
|
+
});
|
|
841
|
+
this.#prev_positions_capacity_vertices = new_capacity;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Grow {@link #prev_position_offsets_buffer} (and its CPU
|
|
846
|
+
* shadow) to cover at least `required_records` meshlet metadata
|
|
847
|
+
* rows. Entries beyond previously written ones default to
|
|
848
|
+
* {@link PREV_POSITION_OFFSET_INVALID} so non-clone meshlets
|
|
849
|
+
* read as "no prev-position data, fall back".
|
|
850
|
+
*
|
|
851
|
+
* @param {number} required_records
|
|
852
|
+
*/
|
|
853
|
+
#ensure_prev_position_offsets_capacity(required_records) {
|
|
854
|
+
if (this.#prev_position_offsets_buffer !== null && required_records <= this.#prev_position_offsets_capacity) {
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
let new_capacity = Math.max(
|
|
859
|
+
this.#prev_position_offsets_capacity,
|
|
860
|
+
PREV_POSITION_OFFSETS_INITIAL_CAPACITY,
|
|
861
|
+
);
|
|
862
|
+
while (new_capacity < required_records) {
|
|
863
|
+
new_capacity *= 2;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// Re-allocate CPU shadow, copy old entries, fill new with
|
|
867
|
+
// sentinel.
|
|
868
|
+
const new_cpu = new Uint32Array(new_capacity);
|
|
869
|
+
new_cpu.fill(PREV_POSITION_OFFSET_INVALID);
|
|
870
|
+
new_cpu.set(this.#prev_position_offsets_cpu);
|
|
871
|
+
this.#prev_position_offsets_cpu = new_cpu;
|
|
872
|
+
|
|
873
|
+
if (this.#prev_position_offsets_buffer !== null) {
|
|
874
|
+
this.#prev_position_offsets_buffer.destroy();
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
this.#prev_position_offsets_buffer = this.#device.createBuffer({
|
|
878
|
+
label: 'GPUMeshSkinningContext/PrevPositionOffsets',
|
|
879
|
+
size: new_capacity * 4,
|
|
880
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
881
|
+
});
|
|
882
|
+
this.#prev_position_offsets_capacity = new_capacity;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Re-upload the entire {@link #prev_position_offsets_cpu} shadow
|
|
887
|
+
* to the GPU offsets buffer. Called when a new binding has
|
|
888
|
+
* registered new entries (rare — bindings register once, not
|
|
889
|
+
* per frame). Whole-buffer upload because the buffer is small
|
|
890
|
+
* (one u32 per meshlet metadata row, hundreds of KB at typical
|
|
891
|
+
* stress-test scale).
|
|
892
|
+
*/
|
|
893
|
+
#upload_prev_position_offsets() {
|
|
894
|
+
if (this.#prev_position_offsets_buffer === null) {
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
this.#device.queue.writeBuffer(
|
|
898
|
+
this.#prev_position_offsets_buffer,
|
|
899
|
+
0,
|
|
900
|
+
this.#prev_position_offsets_cpu.buffer,
|
|
901
|
+
0,
|
|
902
|
+
this.#prev_position_offsets_capacity * 4,
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
/**
|
|
907
|
+
* Resolve every CPU binding into GPU bytes (looking up
|
|
908
|
+
* `skin_matrix_offset` from the animation manager) and upload to
|
|
909
|
+
* the bindings buffer. Grows the buffer first if the binding
|
|
910
|
+
* count has outgrown its capacity.
|
|
911
|
+
*/
|
|
912
|
+
#upload_bindings() {
|
|
913
|
+
const binding_count = this.#bindings.length;
|
|
914
|
+
const struct_size = SKINNING_BINDING_STRUCT.aligned_size;
|
|
915
|
+
|
|
916
|
+
if (binding_count > this.#bindings_capacity) {
|
|
917
|
+
let new_capacity = Math.max(this.#bindings_capacity, BINDINGS_INITIAL_CAPACITY);
|
|
918
|
+
while (new_capacity < binding_count) {
|
|
919
|
+
new_capacity *= 2;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
if (this.#bindings_buffer !== null) {
|
|
923
|
+
this.#bindings_buffer.destroy();
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
this.#bindings_buffer = this.#device.createBuffer({
|
|
927
|
+
label: 'GPUMeshSkinningContext/Bindings',
|
|
928
|
+
size: new_capacity * struct_size,
|
|
929
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
930
|
+
});
|
|
931
|
+
this.#bindings_capacity = new_capacity;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
const data = new ArrayBuffer(binding_count * struct_size);
|
|
935
|
+
for (let i = 0; i < binding_count; i++) {
|
|
936
|
+
const b = this.#bindings[i];
|
|
937
|
+
|
|
938
|
+
// The meshes table is asked for the row rather than having it
|
|
939
|
+
// derived from the transforms row: every node earns a
|
|
940
|
+
// transforms row and only the geometry-bearing ones earn a
|
|
941
|
+
// mesh row, so the two tables run at different rates as soon
|
|
942
|
+
// as the scene holds a group, an anchor or a joint — which is
|
|
943
|
+
// every glTF. A bound mesh is in the scene: assertion catches
|
|
944
|
+
// both a SkinnedMesh scene.build has not seen yet and one that
|
|
945
|
+
// left the scene without being unbound, either of which would
|
|
946
|
+
// otherwise reach the shader as a garbage row.
|
|
947
|
+
const mesh_instance_index = this.#scene_context.mesh_row_of(b.mesh);
|
|
948
|
+
assert.isNonNegativeInteger(
|
|
949
|
+
mesh_instance_index,
|
|
950
|
+
`SkinnedMesh '${b.mesh.name}' (id=${b.mesh.id}) has no meshes-table row — scene.build must run before skinning bindings upload`
|
|
951
|
+
);
|
|
952
|
+
|
|
953
|
+
write_gpu_typed_buffer({
|
|
954
|
+
skin_matrix_offset: this.#animation_manager.get_skin_matrix_offset(b.skin_id),
|
|
955
|
+
source_meshlet_metadata_offset: b.source_meshlet_metadata_offset,
|
|
956
|
+
clone_meshlet_metadata_offset: b.clone_meshlet_metadata_offset,
|
|
957
|
+
meshlet_count: b.meshlet_count,
|
|
958
|
+
clone_geometry_index: b.clone_geometry_index,
|
|
959
|
+
mesh_instance_index,
|
|
960
|
+
}, SKINNING_BINDING_STRUCT, data, i * struct_size);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
this.#device.queue.writeBuffer(this.#bindings_buffer, 0, data);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* Build the flat `(binding_index, meshlet_local_index)` table —
|
|
968
|
+
* one pair per workgroup the skinning dispatch will spawn — and
|
|
969
|
+
* upload to the dispatch-lookup buffer (growing it if needed).
|
|
970
|
+
*/
|
|
971
|
+
#upload_dispatch_lookup() {
|
|
972
|
+
const total = this.#total_meshlet_count;
|
|
973
|
+
|
|
974
|
+
if (total > this.#dispatch_lookup_capacity) {
|
|
975
|
+
let new_capacity = Math.max(this.#dispatch_lookup_capacity, DISPATCH_LOOKUP_INITIAL_CAPACITY);
|
|
976
|
+
while (new_capacity < total) {
|
|
977
|
+
new_capacity *= 2;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
if (this.#dispatch_lookup_buffer !== null) {
|
|
981
|
+
this.#dispatch_lookup_buffer.destroy();
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
this.#dispatch_lookup_buffer = this.#device.createBuffer({
|
|
985
|
+
label: 'GPUMeshSkinningContext/DispatchLookup',
|
|
986
|
+
// 8 bytes per pair (two u32s).
|
|
987
|
+
size: new_capacity * 8,
|
|
988
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
989
|
+
});
|
|
990
|
+
this.#dispatch_lookup_capacity = new_capacity;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
const data = new Uint32Array(total * 2);
|
|
994
|
+
let cursor = 0;
|
|
995
|
+
for (let b = 0; b < this.#bindings.length; b++) {
|
|
996
|
+
const binding = this.#bindings[b];
|
|
997
|
+
for (let m = 0; m < binding.meshlet_count; m++) {
|
|
998
|
+
data[cursor++] = b;
|
|
999
|
+
data[cursor++] = m;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
this.#device.queue.writeBuffer(this.#dispatch_lookup_buffer, 0, data);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
destroy() {
|
|
1007
|
+
if (this.#bindings_buffer !== null) {
|
|
1008
|
+
this.#bindings_buffer.destroy();
|
|
1009
|
+
this.#bindings_buffer = null;
|
|
1010
|
+
}
|
|
1011
|
+
if (this.#dispatch_lookup_buffer !== null) {
|
|
1012
|
+
this.#dispatch_lookup_buffer.destroy();
|
|
1013
|
+
this.#dispatch_lookup_buffer = null;
|
|
1014
|
+
}
|
|
1015
|
+
if (this.#prev_positions_buffer !== null) {
|
|
1016
|
+
this.#prev_positions_buffer.destroy();
|
|
1017
|
+
this.#prev_positions_buffer = null;
|
|
1018
|
+
}
|
|
1019
|
+
if (this.#prev_position_offsets_buffer !== null) {
|
|
1020
|
+
this.#prev_position_offsets_buffer.destroy();
|
|
1021
|
+
this.#prev_position_offsets_buffer = null;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|