@woosh/meep-engine 2.169.1 → 2.169.2
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/editor/ecs/component/editors/NumericIntervalEditor.js +18 -35
- package/editor/ecs/component/editors/ObservedIntegerEditor.js +22 -43
- package/editor/ecs/component/editors/ObservedStringEditor.js +34 -51
- package/editor/ecs/component/editors/common/makeV3_editor.js +12 -30
- package/editor/ecs/component/editors/common/two_way_sync.js +50 -0
- package/editor/ecs/component/editors/geom/QuaternionEditor.js +20 -35
- package/editor/ecs/component/editors/geom/Vector1Editor.js +5 -28
- package/editor/ecs/component/editors/primitive/NumberEditor.js +15 -31
- package/editor/tools/paint/TerrainHeightPaintTool.js +22 -31
- package/editor/tools/paint/TerrainPaintTool.js +85 -13
- package/editor/tools/paint/TerrainTexturePaintTool.js +18 -29
- package/editor/view/ecs/components/TerrainController.js +1 -4
- package/package.json +1 -1
- package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +738 -0
- package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +79 -0
- package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +93 -0
- package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +80 -0
- package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +164 -0
- package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +69 -0
- package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +102 -0
- package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +129 -0
- package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +72 -0
- package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +74 -0
- package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +169 -0
- package/src/DUPLICATION_AUDIT_2026_08_07.md +254 -0
- package/src/DUPLICATION_AUDIT_REMEDIATION.md +250 -0
- package/src/core/bvh2/bvh3/query/bvh_collect_user_data.js +2 -2
- 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_aabb.js +2 -2
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_capsule.js +2 -2
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_frustum.js +2 -2
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_sphere.js +2 -2
- 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/bvh3/query/compute_tight_near_far_clipping_planes.js +2 -2
- package/src/core/bvh8/aabb3_round_to_float32.d.ts +16 -0
- package/src/core/bvh8/aabb3_round_to_float32.d.ts.map +1 -0
- package/src/core/bvh8/aabb3_round_to_float32.js +22 -0
- package/src/core/bvh8/bvh8_geometry_validate.d.ts.map +1 -1
- package/src/core/bvh8/bvh8_geometry_validate.js +1 -12
- package/src/core/bvh8/bvh8_geometry_validate_indirect.d.ts.map +1 -1
- package/src/core/bvh8/bvh8_geometry_validate_indirect.js +1 -12
- package/src/core/cache/Cache.d.ts +13 -0
- package/src/core/cache/Cache.d.ts.map +1 -1
- package/src/core/cache/Cache.js +13 -0
- package/src/core/color/operations/color_darken.d.ts +5 -2
- package/src/core/color/operations/color_darken.d.ts.map +1 -1
- package/src/core/color/operations/color_darken.js +24 -33
- package/src/core/color/operations/color_desaturate.d.ts +5 -2
- package/src/core/color/operations/color_desaturate.d.ts.map +1 -1
- package/src/core/color/operations/color_desaturate.js +24 -33
- package/src/core/color/operations/color_lighten.d.ts +5 -2
- package/src/core/color/operations/color_lighten.d.ts.map +1 -1
- package/src/core/color/operations/color_lighten.js +24 -33
- package/src/core/color/operations/color_saturate.d.ts +5 -2
- package/src/core/color/operations/color_saturate.d.ts.map +1 -1
- package/src/core/color/operations/color_saturate.js +24 -33
- package/src/core/color/operations/color_scale_okhsv_channel.d.ts +28 -0
- package/src/core/color/operations/color_scale_okhsv_channel.d.ts.map +1 -0
- package/src/core/color/operations/color_scale_okhsv_channel.js +45 -0
- package/src/core/geom/2d/hash-grid/SpatialHashGrid.d.ts.map +1 -1
- package/src/core/geom/2d/hash-grid/SpatialHashGrid.js +12 -0
- package/src/core/geom/2d/line/segment2_intersects_segment2_2d.d.ts.map +1 -1
- package/src/core/geom/2d/line/segment2_intersects_segment2_2d.js +25 -29
- package/src/core/geom/2d/line/segment2_segment_compute_intersection_array_2d.d.ts.map +1 -1
- package/src/core/geom/2d/line/segment2_segment_compute_intersection_array_2d.js +46 -51
- package/src/core/geom/2d/line/segment2_segment_intersection_fractions.d.ts +31 -0
- package/src/core/geom/2d/line/segment2_segment_intersection_fractions.d.ts.map +1 -0
- package/src/core/geom/2d/line/segment2_segment_intersection_fractions.js +52 -0
- package/src/core/geom/2d/quad-tree/qt_collect_by_circle.d.ts +6 -1
- package/src/core/geom/2d/quad-tree/qt_collect_by_circle.d.ts.map +1 -1
- package/src/core/geom/2d/quad-tree/qt_collect_by_circle.js +39 -65
- package/src/core/geom/2d/quad-tree/qt_match_data_by_circle.d.ts +15 -5
- package/src/core/geom/2d/quad-tree/qt_match_data_by_circle.d.ts.map +1 -1
- package/src/core/geom/2d/quad-tree/qt_match_data_by_circle.js +101 -70
- package/src/core/geom/2d/r-tree/StaticR2Tree.d.ts.map +1 -1
- package/src/core/geom/2d/r-tree/StaticR2Tree.js +7 -3
- package/src/core/geom/3d/aabb/aabb3_intersects_ray_segment.d.ts +7 -8
- package/src/core/geom/3d/aabb/aabb3_intersects_ray_segment.d.ts.map +1 -1
- package/src/core/geom/3d/aabb/aabb3_intersects_ray_segment.js +15 -51
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.d.ts.map +1 -1
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.js +13 -14
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.d.ts.map +1 -1
- package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.js +2 -17
- package/src/core/geom/3d/atlas/segment/atlas_chart_roundness_delta.d.ts +22 -0
- package/src/core/geom/3d/atlas/segment/atlas_chart_roundness_delta.d.ts.map +1 -0
- package/src/core/geom/3d/atlas/segment/atlas_chart_roundness_delta.js +30 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts.d.ts +19 -0
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts.d.ts.map +1 -1
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts.js +5 -9
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.d.ts.map +1 -1
- package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.js +4 -12
- package/src/core/geom/3d/frustum/read_frustum_corner.d.ts +5 -0
- package/src/core/geom/3d/frustum/read_frustum_corner.d.ts.map +1 -1
- package/src/core/geom/3d/frustum/read_frustum_corner.js +8 -5
- package/src/core/geom/3d/line/line3_segment_segment_closest_point_pair.d.ts +33 -0
- package/src/core/geom/3d/line/line3_segment_segment_closest_point_pair.d.ts.map +1 -0
- package/src/core/geom/3d/line/line3_segment_segment_closest_point_pair.js +71 -0
- package/src/core/geom/3d/mat4/m4_compose.d.ts +5 -0
- package/src/core/geom/3d/mat4/m4_compose.d.ts.map +1 -1
- package/src/core/geom/3d/mat4/m4_compose.js +22 -53
- package/src/core/geom/3d/mat4/m4_decompose.d.ts +8 -0
- package/src/core/geom/3d/mat4/m4_decompose.d.ts.map +1 -1
- package/src/core/geom/3d/mat4/m4_decompose.js +84 -76
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.d.ts +2 -0
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.d.ts.map +1 -1
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.js +10 -44
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale_scalar.d.ts +27 -0
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale_scalar.d.ts.map +1 -0
- package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale_scalar.js +67 -0
- package/src/core/geom/3d/plane/orient3d_fast.d.ts.map +1 -1
- package/src/core/geom/3d/plane/orient3d_fast.js +2 -22
- package/src/core/geom/3d/plane/orient3d_fast_point.d.ts +28 -0
- package/src/core/geom/3d/plane/orient3d_fast_point.d.ts.map +1 -0
- package/src/core/geom/3d/plane/orient3d_fast_point.js +47 -0
- package/src/core/geom/3d/quaternion/quat3_nlerp.d.ts +48 -0
- package/src/core/geom/3d/quaternion/quat3_nlerp.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/quat3_nlerp.js +72 -0
- package/src/core/geom/3d/shape/AbstractShape3D.d.ts +9 -0
- package/src/core/geom/3d/shape/AbstractShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/AbstractShape3D.js +44 -1
- package/src/core/geom/3d/shape/BoxShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/BoxShape3D.js +2 -1
- package/src/core/geom/3d/shape/CapsuleShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/CapsuleShape3D.js +2 -1
- package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts +0 -1
- package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/ConvexHullShape3D.js +25 -56
- package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/CylinderShape3D.js +2 -1
- package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/HeightMapShape3D.js +3 -5
- package/src/core/geom/3d/shape/MeshShape3D.d.ts +0 -11
- package/src/core/geom/3d/shape/MeshShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/MeshShape3D.js +27 -106
- package/src/core/geom/3d/shape/Triangle3D.d.ts +1 -1
- package/src/core/geom/3d/shape/Triangle3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/Triangle3D.js +10 -31
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts.map +1 -1
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +8 -57
- package/src/core/geom/3d/topology/simplify/decimate_edge_collapse_snap.d.ts +8 -1
- package/src/core/geom/3d/topology/simplify/decimate_edge_collapse_snap.d.ts.map +1 -1
- package/src/core/geom/3d/topology/simplify/decimate_edge_collapse_snap.js +281 -272
- package/src/core/geom/3d/topology/simplify/quadratic/build_vertex_quadrics.d.ts.map +1 -1
- package/src/core/geom/3d/topology/simplify/quadratic/build_vertex_quadrics.js +3 -4
- package/src/core/geom/3d/topology/simplify/quadratic/quadric3_set_from_plane_through_point.d.ts +22 -0
- package/src/core/geom/3d/topology/simplify/quadratic/quadric3_set_from_plane_through_point.d.ts.map +1 -0
- package/src/core/geom/3d/topology/simplify/quadratic/quadric3_set_from_plane_through_point.js +27 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts +24 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +73 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +2 -53
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.js +3 -4
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +3 -33
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_from_indexed_geometry.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_from_indexed_geometry.js +4 -37
- package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_poke.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_poke.js +3 -32
- package/src/core/geom/3d/topology/struct/binary/query/bt_face_read_triangle.d.ts +32 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_face_read_triangle.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_face_read_triangle.js +66 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path.js +703 -728
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.js +13 -24
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +8 -54
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_surface_ray_parity.d.ts +35 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_surface_ray_parity.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_surface_ray_parity.js +82 -0
- package/src/core/geom/3d/triangle/tri3_closest_point.d.ts +29 -0
- package/src/core/geom/3d/triangle/tri3_closest_point.d.ts.map +1 -0
- package/src/core/geom/3d/triangle/tri3_closest_point.js +65 -0
- package/src/core/geom/3d/triangle/tri3_flatten_isometric.d.ts +42 -0
- package/src/core/geom/3d/triangle/tri3_flatten_isometric.d.ts.map +1 -0
- package/src/core/geom/3d/triangle/tri3_flatten_isometric.js +79 -0
- package/src/core/geom/Vector2.d.ts.map +1 -1
- package/src/core/geom/Vector2.js +2 -1
- package/src/core/geom/random/random_orthonormal_basis.d.ts +21 -0
- package/src/core/geom/random/random_orthonormal_basis.d.ts.map +1 -0
- package/src/core/geom/random/random_orthonormal_basis.js +31 -0
- package/src/core/geom/vec2/v2_rotate.d.ts +18 -0
- package/src/core/geom/vec2/v2_rotate.d.ts.map +1 -0
- package/src/core/geom/vec2/v2_rotate.js +21 -0
- package/src/core/geom/vec2/v2_rotate_cos_sin.d.ts +19 -0
- package/src/core/geom/vec2/v2_rotate_cos_sin.d.ts.map +1 -0
- package/src/core/geom/vec2/v2_rotate_cos_sin.js +21 -0
- package/src/core/graph/csr/csr_graph_from_undirected_edge_list.d.ts +30 -0
- package/src/core/graph/csr/csr_graph_from_undirected_edge_list.d.ts.map +1 -0
- package/src/core/graph/csr/csr_graph_from_undirected_edge_list.js +94 -0
- package/src/core/graph/layout/CircleLayout.d.ts.map +1 -1
- package/src/core/graph/layout/CircleLayout.js +6 -29
- package/src/core/graph/layout/box/BoxLayouter.d.ts.map +1 -1
- package/src/core/graph/layout/box/BoxLayouter.js +2 -26
- package/src/core/graph/layout/box/position_box_next_to_box.d.ts.map +1 -1
- package/src/core/graph/layout/box/position_box_next_to_box.js +2 -1
- package/src/core/graph/layout/computeDisconnectedSubGraphs.d.ts.map +1 -1
- package/src/core/graph/layout/computeDisconnectedSubGraphs.js +14 -3
- package/src/core/graph/layout/graph_peel_topological_layer.d.ts +25 -0
- package/src/core/graph/layout/graph_peel_topological_layer.d.ts.map +1 -0
- package/src/core/graph/layout/graph_peel_topological_layer.js +45 -0
- package/src/core/math/hash/hash_mix2.d.ts +21 -0
- package/src/core/math/hash/hash_mix2.d.ts.map +1 -0
- package/src/core/math/hash/hash_mix2.js +22 -0
- package/src/core/math/hash/hash_mix3.d.ts +16 -0
- package/src/core/math/hash/hash_mix3.d.ts.map +1 -0
- package/src/core/math/hash/hash_mix3.js +19 -0
- package/src/core/math/lookup/LUT_HEATMAP.d.ts +17 -0
- package/src/core/math/lookup/LUT_HEATMAP.d.ts.map +1 -0
- package/src/core/math/lookup/LUT_HEATMAP.js +30 -0
- package/src/core/math/noise/curl_noise_3d.d.ts +6 -0
- package/src/core/math/noise/curl_noise_3d.d.ts.map +1 -1
- package/src/core/math/noise/curl_noise_3d.js +18 -27
- package/src/core/math/statistics/hammersley_sequence.d.ts +28 -16
- package/src/core/math/statistics/hammersley_sequence.d.ts.map +1 -1
- package/src/core/math/statistics/hammersley_sequence.js +53 -34
- package/src/core/science/units/MEASUREMENT_UNITS_SI.d.ts +3 -0
- package/src/core/science/units/MEASUREMENT_UNITS_SI.d.ts.map +1 -1
- package/src/core/science/units/MEASUREMENT_UNITS_SI.js +5 -16
- package/src/engine/animation/TransitionFunctions.d.ts +31 -0
- package/src/engine/animation/TransitionFunctions.d.ts.map +1 -1
- package/src/engine/animation/TransitionFunctions.js +44 -0
- package/src/engine/animation/curve/animation_curve_binary_codec.d.ts +29 -0
- package/src/engine/animation/curve/animation_curve_binary_codec.d.ts.map +1 -0
- package/src/engine/animation/curve/animation_curve_binary_codec.js +60 -0
- package/src/engine/animation/curve/draw/canvas_point_to_curve.d.ts +16 -0
- package/src/engine/animation/curve/draw/canvas_point_to_curve.d.ts.map +1 -0
- package/src/engine/animation/curve/draw/canvas_point_to_curve.js +22 -0
- package/src/engine/animation/curve/draw/curve_point_to_canvas.d.ts +27 -0
- package/src/engine/animation/curve/draw/curve_point_to_canvas.d.ts.map +1 -0
- package/src/engine/animation/curve/draw/curve_point_to_canvas.js +38 -0
- package/src/engine/animation/curve/draw/position_canvas_to_curve.d.ts +2 -0
- package/src/engine/animation/curve/draw/position_canvas_to_curve.d.ts.map +1 -1
- package/src/engine/animation/curve/draw/position_canvas_to_curve.js +22 -24
- package/src/engine/animation/curve/draw/position_curve_to_canvas.d.ts +2 -0
- package/src/engine/animation/curve/draw/position_curve_to_canvas.d.ts.map +1 -1
- package/src/engine/animation/curve/draw/position_curve_to_canvas.js +22 -25
- package/src/engine/animation/curve/editor/canvas2dDrawWorldAxisLabels.d.ts.map +1 -1
- package/src/engine/animation/curve/editor/canvas2dDrawWorldAxisLabels.js +3 -2
- package/src/engine/animation/curve/editor/canvas2dPlotCurvePoints.d.ts.map +1 -1
- package/src/engine/animation/curve/editor/canvas2dPlotCurvePoints.js +14 -14
- package/src/engine/animation/removeEntityWithMeshParticlesEffect.d.ts.map +1 -1
- package/src/engine/animation/removeEntityWithMeshParticlesEffect.js +5 -0
- package/src/engine/asset/loaders/GLTFAssetLoader.d.ts.map +1 -1
- package/src/engine/asset/loaders/GLTFAssetLoader.js +25 -51
- package/src/engine/asset/loaders/material/StaticMaterialCache.d.ts +3 -2
- package/src/engine/asset/loaders/material/StaticMaterialCache.d.ts.map +1 -1
- package/src/engine/asset/loaders/material/StaticMaterialCache.js +16 -55
- package/src/engine/asset/loaders/material/TextureCoalescer.d.ts +32 -0
- package/src/engine/asset/loaders/material/TextureCoalescer.d.ts.map +1 -0
- package/src/engine/asset/loaders/material/TextureCoalescer.js +68 -0
- package/src/engine/asset/loaders/material/traverseMaterialTextures.d.ts +10 -2
- package/src/engine/asset/loaders/material/traverseMaterialTextures.d.ts.map +1 -1
- package/src/engine/asset/loaders/material/traverseMaterialTextures.js +10 -2
- package/src/engine/control/first-person/abilities/Mantle.d.ts.map +1 -1
- package/src/engine/control/first-person/abilities/Mantle.js +10 -26
- package/src/engine/ecs/dynamic_actions/actions/definition/WeightedRandomActionDescription.d.ts.map +1 -1
- package/src/engine/ecs/dynamic_actions/actions/definition/WeightedRandomActionDescription.js +5 -0
- package/src/engine/ecs/evaluation/complex/PointFitnessGaussianBlur.d.ts +22 -2
- package/src/engine/ecs/evaluation/complex/PointFitnessGaussianBlur.d.ts.map +1 -1
- package/src/engine/ecs/evaluation/complex/PointFitnessGaussianBlur.js +92 -41
- package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.d.ts +3 -1
- package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.d.ts.map +1 -1
- package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +14 -16
- package/src/engine/ecs/gui/parallax/GuiElementParallaxSystem.d.ts.map +1 -1
- package/src/engine/ecs/gui/parallax/GuiElementParallaxSystem.js +16 -29
- package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.d.ts.map +1 -1
- package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +12 -74
- package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.d.ts.map +1 -1
- package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +10 -73
- package/src/engine/ecs/ik/ik_probe_terrain_contact.d.ts +38 -0
- package/src/engine/ecs/ik/ik_probe_terrain_contact.d.ts.map +1 -0
- package/src/engine/ecs/ik/ik_probe_terrain_contact.js +119 -0
- package/src/engine/ecs/terrain/util/paintTerrainOverlayViaLookupTable.d.ts +0 -1
- package/src/engine/ecs/terrain/util/paintTerrainOverlayViaLookupTable.d.ts.map +1 -1
- package/src/engine/ecs/terrain/util/paintTerrainOverlayViaLookupTable.js +2 -14
- package/src/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.d.ts +12 -1
- package/src/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.d.ts.map +1 -1
- package/src/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js +14 -10
- package/src/engine/graphics/ecs/camera/auto_set_camera_clipping_planes.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/auto_set_camera_clipping_planes.js +7 -28
- package/src/engine/graphics/ecs/highlight/renderer/HighlightDecodeShader.d.ts +1 -2
- package/src/engine/graphics/ecs/highlight/renderer/HighlightDecodeShader.d.ts.map +1 -1
- package/src/engine/graphics/ecs/highlight/renderer/HighlightDecodeShader.js +4 -12
- package/src/engine/graphics/ecs/highlight/renderer/OutlineRenderer.d.ts.map +1 -1
- package/src/engine/graphics/ecs/highlight/renderer/OutlineRenderer.js +2 -11
- package/src/engine/graphics/ecs/highlight/renderer/makeBlurShader_9.d.ts +1 -2
- package/src/engine/graphics/ecs/highlight/renderer/makeBlurShader_9.d.ts.map +1 -1
- package/src/engine/graphics/ecs/highlight/renderer/makeBlurShader_9.js +3 -11
- package/src/engine/graphics/ecs/highlight/renderer/makeDilationShader.d.ts +1 -2
- package/src/engine/graphics/ecs/highlight/renderer/makeDilationShader.d.ts.map +1 -1
- package/src/engine/graphics/ecs/highlight/renderer/makeDilationShader.js +3 -11
- package/src/engine/graphics/ecs/highlight/renderer/make_screen_space_quad_material.d.ts +33 -0
- package/src/engine/graphics/ecs/highlight/renderer/make_screen_space_quad_material.d.ts.map +1 -0
- package/src/engine/graphics/ecs/highlight/renderer/make_screen_space_quad_material.js +44 -0
- package/src/engine/graphics/ecs/highlight/system/HighlightSystemBase.d.ts +55 -0
- package/src/engine/graphics/ecs/highlight/system/HighlightSystemBase.d.ts.map +1 -0
- package/src/engine/graphics/ecs/highlight/system/HighlightSystemBase.js +205 -0
- package/src/engine/graphics/ecs/highlight/system/MeshHighlightSystem.d.ts +4 -45
- package/src/engine/graphics/ecs/highlight/system/MeshHighlightSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/highlight/system/MeshHighlightSystem.js +39 -162
- package/src/engine/graphics/ecs/highlight/system/RenderableHighlightSystem.d.ts +4 -51
- package/src/engine/graphics/ecs/highlight/system/RenderableHighlightSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/highlight/system/RenderableHighlightSystem.js +34 -164
- package/src/engine/graphics/ecs/highlight/system/ShadedGeometryHighlightSystem.d.ts +5 -57
- package/src/engine/graphics/ecs/highlight/system/ShadedGeometryHighlightSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/highlight/system/ShadedGeometryHighlightSystem.js +48 -175
- package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.d.ts.map +1 -1
- package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.js +7 -25
- package/src/engine/graphics/ecs/make_bvh_depth_range_computer.d.ts +26 -0
- package/src/engine/graphics/ecs/make_bvh_depth_range_computer.d.ts.map +1 -0
- package/src/engine/graphics/ecs/make_bvh_depth_range_computer.js +33 -0
- package/src/engine/graphics/ecs/mesh/MeshSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/mesh/MeshSystem.js +2 -5
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +2 -5
- package/src/engine/graphics/ecs/render_layers_compute_depth_range.d.ts +35 -0
- package/src/engine/graphics/ecs/render_layers_compute_depth_range.d.ts.map +1 -0
- package/src/engine/graphics/ecs/render_layers_compute_depth_range.js +64 -0
- package/src/engine/graphics/ecs/trail2d/Trail2DSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/trail2d/Trail2DSystem.js +2 -5
- package/src/engine/graphics/ecs/trail3d/Trail3DSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/trail3d/Trail3DSystem.js +2 -5
- package/src/engine/graphics/ecs/water/WaterSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/water/WaterSystem.js +2 -5
- package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_nearest.d.ts.map +1 -1
- package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_nearest.js +22 -94
- package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_overlap_clipping_volume.d.ts.map +1 -1
- package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_overlap_clipping_volume.js +17 -57
- package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_raycast.d.ts.map +1 -1
- package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_raycast.js +17 -57
- package/src/engine/graphics/geometry/buffered/query/nearest_point_on_triangle_record.d.ts +30 -0
- package/src/engine/graphics/geometry/buffered/query/nearest_point_on_triangle_record.d.ts.map +1 -0
- package/src/engine/graphics/geometry/buffered/query/nearest_point_on_triangle_record.js +87 -0
- package/src/engine/graphics/geometry/buffered/query/query_bvh_geometry_nearest.d.ts.map +1 -1
- package/src/engine/graphics/geometry/buffered/query/query_bvh_geometry_nearest.js +11 -55
- package/src/engine/graphics/geometry/buffered/read_triangle_vertices.d.ts +29 -0
- package/src/engine/graphics/geometry/buffered/read_triangle_vertices.d.ts.map +1 -0
- package/src/engine/graphics/geometry/buffered/read_triangle_vertices.js +102 -0
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderDepthV0.d.ts.map +1 -1
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderDepthV0.js +17 -122
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderLitV0.d.ts.map +1 -1
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderLitV0.js +15 -194
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderNormalsV0.d.ts.map +1 -1
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderNormalsV0.js +12 -108
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderPerPixelV0.d.ts.map +1 -1
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderPerPixelV0.js +14 -183
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderV0.d.ts.map +1 -1
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderV0.js +12 -154
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderViewportDepthV0.d.ts.map +1 -1
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderViewportDepthV0.js +10 -94
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderWireframeV0.d.ts.map +1 -1
- package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderWireframeV0.js +8 -72
- package/src/engine/graphics/impostors/octahedral/shader/glsl/common.glsl +10 -0
- package/src/engine/graphics/impostors/voxel/bake/read_atlas_to_samples.d.ts.map +1 -1
- package/src/engine/graphics/impostors/voxel/bake/read_atlas_to_samples.js +79 -58
- package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderDepthV0.d.ts.map +1 -1
- package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderDepthV0.js +11 -22
- package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderLitV0.d.ts.map +1 -1
- package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderLitV0.js +7 -16
- package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderNormalsV0.d.ts.map +1 -1
- package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderNormalsV0.js +5 -9
- package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderV0.d.ts.map +1 -1
- package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderV0.js +4 -19
- package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderViewportDepthV0.d.ts.map +1 -1
- package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderViewportDepthV0.js +5 -9
- package/src/engine/graphics/material/SplatMaterial.d.ts.map +1 -1
- package/src/engine/graphics/material/SplatMaterial.js +2 -17
- package/src/engine/graphics/material/WaterMaterial.d.ts.map +1 -1
- package/src/engine/graphics/material/WaterMaterial.js +3 -18
- package/src/engine/graphics/material/manager/compilers/CoalesceTextures.d.ts +4 -4
- package/src/engine/graphics/material/manager/compilers/CoalesceTextures.d.ts.map +1 -1
- package/src/engine/graphics/material/manager/compilers/CoalesceTextures.js +25 -70
- package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.js +2 -5
- package/src/engine/graphics/particles/node-based/codegen/glsl/getTypeByteSize.d.ts +8 -11
- package/src/engine/graphics/particles/node-based/codegen/glsl/getTypeByteSize.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/codegen/glsl/getTypeByteSize.js +20 -21
- package/src/engine/graphics/particles/node-based/nodes/particle_data_type_component_count.d.ts +39 -0
- package/src/engine/graphics/particles/node-based/nodes/particle_data_type_component_count.d.ts.map +1 -0
- package/src/engine/graphics/particles/node-based/nodes/particle_data_type_component_count.js +45 -0
- package/src/engine/graphics/particles/node-based/particle/ParticleAttributeSpecification.d.ts +6 -8
- package/src/engine/graphics/particles/node-based/particle/ParticleAttributeSpecification.d.ts.map +1 -1
- package/src/engine/graphics/particles/node-based/particle/ParticleAttributeSpecification.js +2 -13
- package/src/engine/graphics/particles/particular/engine/utils/distributeParticlesOnObject3D.d.ts.map +1 -1
- package/src/engine/graphics/particles/particular/engine/utils/distributeParticlesOnObject3D.js +16 -78
- package/src/engine/graphics/particles/particular/engine/utils/distribute_points_on_indexed_triangles.d.ts +45 -0
- package/src/engine/graphics/particles/particular/engine/utils/distribute_points_on_indexed_triangles.d.ts.map +1 -0
- package/src/engine/graphics/particles/particular/engine/utils/distribute_points_on_indexed_triangles.js +168 -0
- package/src/engine/graphics/particles/particular/engine/utils/distrubuteParticlesOnMesh.d.ts.map +1 -1
- package/src/engine/graphics/particles/particular/engine/utils/distrubuteParticlesOnMesh.js +11 -115
- package/src/engine/graphics/postprocess/threejs/shaders/CopyShader.d.ts +24 -16
- package/src/engine/graphics/postprocess/threejs/shaders/CopyShader.d.ts.map +1 -1
- package/src/engine/graphics/postprocess/threejs/shaders/CopyShader.js +15 -47
- package/src/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.d.ts +4 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.d.ts.map +1 -1
- package/src/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +4 -0
- package/src/engine/graphics/sh3/build_injected_shader.d.ts +51 -0
- package/src/engine/graphics/sh3/build_injected_shader.d.ts.map +1 -0
- package/src/engine/graphics/sh3/build_injected_shader.js +56 -0
- package/src/engine/graphics/sh3/gi/material/MaterialTransformer.d.ts.map +1 -1
- package/src/engine/graphics/sh3/gi/material/MaterialTransformer.js +10 -1
- package/src/engine/graphics/sh3/gi/material/chunk_lpv_get_irradiance_at.d.ts.map +1 -1
- package/src/engine/graphics/sh3/gi/material/chunk_lpv_get_irradiance_at.js +17 -0
- package/src/engine/graphics/sh3/gi/material/common.d.ts +1 -1
- package/src/engine/graphics/sh3/gi/material/common.js +6 -222
- package/src/engine/graphics/sh3/gi/material/space_fragment/build_fragment_shader.d.ts.map +1 -1
- package/src/engine/graphics/sh3/gi/material/space_fragment/build_fragment_shader.js +7 -11
- package/src/engine/graphics/sh3/gi/material/space_fragment/build_vertex_shader.d.ts.map +1 -1
- package/src/engine/graphics/sh3/gi/material/space_fragment/build_vertex_shader.js +27 -29
- package/src/engine/graphics/sh3/gi/material/space_vertex/build_fragment_shader.d.ts.map +1 -1
- package/src/engine/graphics/sh3/gi/material/space_vertex/build_fragment_shader.js +7 -11
- package/src/engine/graphics/sh3/gi/material/space_vertex/build_vertex_shader.d.ts.map +1 -1
- package/src/engine/graphics/sh3/gi/material/space_vertex/build_vertex_shader.js +7 -12
- package/src/engine/graphics/sh3/grid_dilate_average.d.ts +38 -0
- package/src/engine/graphics/sh3/grid_dilate_average.d.ts.map +1 -0
- package/src/engine/graphics/sh3/grid_dilate_average.js +175 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_dilate.d.ts +4 -0
- package/src/engine/graphics/sh3/lightmap/lightmap_dilate.d.ts.map +1 -1
- package/src/engine/graphics/sh3/lightmap/lightmap_dilate.js +7 -70
- package/src/engine/graphics/sh3/lpg/light_probe_grid_dilate.d.ts +6 -0
- package/src/engine/graphics/sh3/lpg/light_probe_grid_dilate.d.ts.map +1 -1
- package/src/engine/graphics/sh3/lpg/light_probe_grid_dilate.js +14 -113
- package/src/engine/graphics/sh3/lpg/material/chunk_lpg_get_irradiance_at.d.ts.map +1 -1
- package/src/engine/graphics/sh3/lpg/material/chunk_lpg_get_irradiance_at.js +7 -0
- package/src/engine/graphics/sh3/lpg/material/space_fragment/build_fragment_shader.d.ts.map +1 -1
- package/src/engine/graphics/sh3/lpg/material/space_fragment/build_fragment_shader.js +5 -8
- package/src/engine/graphics/sh3/lpg/material/space_fragment/build_vertex_shader.d.ts.map +1 -1
- package/src/engine/graphics/sh3/lpg/material/space_fragment/build_vertex_shader.js +5 -8
- package/src/engine/graphics/sh3/lpg/material/space_vertex/build_fragment_shader.d.ts.map +1 -1
- package/src/engine/graphics/sh3/lpg/material/space_vertex/build_fragment_shader.js +5 -8
- package/src/engine/graphics/sh3/lpg/material/space_vertex/build_vertex_shader.d.ts.map +1 -1
- package/src/engine/graphics/sh3/lpg/material/space_vertex/build_vertex_shader.js +5 -8
- package/src/engine/graphics/sh3/lpv/depth/chunk_probe_depth_sampling.d.ts +38 -0
- package/src/engine/graphics/sh3/lpv/depth/chunk_probe_depth_sampling.d.ts.map +1 -0
- package/src/engine/graphics/sh3/lpv/depth/chunk_probe_depth_sampling.js +265 -0
- package/src/engine/graphics/sh3/lpv/depth/octahedral/shader/visualize.frag.glsl +11 -0
- package/src/engine/graphics/sh3/lpv/depth/octahedral/v2/VLPDepthMapVisualisation.d.ts.map +1 -1
- package/src/engine/graphics/sh3/lpv/depth/octahedral/v2/VLPDepthMapVisualisation.js +5 -1
- package/src/engine/graphics/sh3/lpv/depth/octahedral/v2/visualise.frag.glsl +189 -419
- package/src/engine/graphics/sh3/shader/visualize.frag.d.ts +1 -1
- package/src/engine/graphics/sh3/shader/visualize.frag.js +7 -0
- package/src/engine/graphics/shaders/chunks/glsl_octahedral_impostor.d.ts +102 -0
- package/src/engine/graphics/shaders/chunks/glsl_octahedral_impostor.d.ts.map +1 -0
- package/src/engine/graphics/shaders/chunks/glsl_octahedral_impostor.js +277 -0
- package/src/engine/graphics/shaders/chunks/glsl_packing.d.ts +29 -0
- package/src/engine/graphics/shaders/chunks/glsl_packing.d.ts.map +1 -0
- package/src/engine/graphics/shaders/chunks/glsl_packing.js +30 -0
- package/src/engine/graphics/shaders/chunks/glsl_voxel_impostor_splat.d.ts +40 -0
- package/src/engine/graphics/shaders/chunks/glsl_voxel_impostor_splat.d.ts.map +1 -0
- package/src/engine/graphics/shaders/chunks/glsl_voxel_impostor_splat.js +57 -0
- package/src/engine/graphics/shaders/lib/make_clouds_uniforms.d.ts +22 -0
- package/src/engine/graphics/shaders/lib/make_clouds_uniforms.d.ts.map +1 -0
- package/src/engine/graphics/shaders/lib/make_clouds_uniforms.js +39 -0
- package/src/engine/graphics/texture/attribute_spec_to_three_format.d.ts +6 -0
- package/src/engine/graphics/texture/attribute_spec_to_three_format.d.ts.map +1 -1
- package/src/engine/graphics/texture/attribute_spec_to_three_format.js +9 -9
- package/src/engine/graphics/texture/channel_count_to_format_prefix.d.ts +14 -0
- package/src/engine/graphics/texture/channel_count_to_format_prefix.d.ts.map +1 -0
- package/src/engine/graphics/texture/channel_count_to_format_prefix.js +26 -0
- package/src/engine/graphics/texture/computeThreeTextureInternalFormatFromDataType.d.ts.map +1 -1
- package/src/engine/graphics/texture/computeThreeTextureInternalFormatFromDataType.js +2 -20
- package/src/engine/graphics/texture/normalized_internal_format.d.ts.map +1 -1
- package/src/engine/graphics/texture/normalized_internal_format.js +2 -20
- package/src/engine/graphics/texture/sampler/convertTexture2Sampler2D.d.ts.map +1 -1
- package/src/engine/graphics/texture/sampler/convertTexture2Sampler2D.js +9 -3
- package/src/engine/input/devices/gamepad/GamepadDeviceLayout.d.ts +54 -0
- package/src/engine/input/devices/gamepad/GamepadDeviceLayout.d.ts.map +1 -0
- package/src/engine/input/devices/gamepad/GamepadDeviceLayout.js +323 -0
- package/src/engine/input/devices/gamepad/GamepadHandle.d.ts +21 -2
- package/src/engine/input/devices/gamepad/GamepadHandle.d.ts.map +1 -1
- package/src/engine/input/devices/gamepad/GamepadHandle.js +39 -11
- package/src/engine/input/devices/gamepad/GamepadLayout.d.ts +128 -0
- package/src/engine/input/devices/gamepad/GamepadLayout.d.ts.map +1 -0
- package/src/engine/input/devices/gamepad/GamepadLayout.js +160 -0
- package/src/engine/input/devices/gamepad/GamepadStandardMapping.d.ts +10 -0
- package/src/engine/input/devices/gamepad/GamepadStandardMapping.d.ts.map +1 -1
- package/src/engine/input/devices/gamepad/GamepadStandardMapping.js +11 -0
- package/src/engine/input/devices/gamepad/GamepadStick.d.ts +5 -1
- package/src/engine/input/devices/gamepad/GamepadStick.d.ts.map +1 -1
- package/src/engine/input/devices/gamepad/GamepadStick.js +5 -1
- package/src/engine/input/devices/gamepad/gamepad_layout_database.d.ts +27 -0
- package/src/engine/input/devices/gamepad/gamepad_layout_database.d.ts.map +1 -0
- package/src/engine/input/devices/gamepad/gamepad_layout_database.js +144 -0
- package/src/engine/input/devices/gamepad/gamepad_read_hat_axis.d.ts +25 -0
- package/src/engine/input/devices/gamepad/gamepad_read_hat_axis.d.ts.map +1 -0
- package/src/engine/input/devices/gamepad/gamepad_read_hat_axis.js +61 -0
- package/src/engine/input/devices/gamepad/prototypeGamepadTester.d.ts +2 -0
- package/src/engine/input/devices/gamepad/prototypeGamepadTester.d.ts.map +1 -0
- package/src/engine/input/devices/gamepad/prototypeGamepadTester.js +2124 -0
- package/src/engine/input/ecs/util/TopDownCameraControllerHelper.d.ts.map +1 -1
- package/src/engine/input/ecs/util/TopDownCameraControllerHelper.js +3 -33
- package/src/engine/intelligence/behavior/util/RandomDelayBehavior.d.ts.map +1 -1
- package/src/engine/intelligence/behavior/util/RandomDelayBehavior.js +5 -0
- package/src/engine/network/adapters/QuaternionInterpolationAdapter.d.ts.map +1 -1
- package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +18 -19
- package/src/engine/network/adapters/TransformInterpolationAdapter.d.ts.map +1 -1
- package/src/engine/network/adapters/TransformInterpolationAdapter.js +18 -13
- package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/NetworkPeer.js +2 -1
- package/src/engine/network/sim/ActionLog.d.ts +9 -6
- package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
- package/src/engine/network/sim/ActionLog.js +43 -80
- package/src/engine/network/sim/SmoothingState.d.ts.map +1 -1
- package/src/engine/network/sim/SmoothingState.js +27 -28
- package/src/engine/network/state/FrameBufferRing.d.ts +84 -0
- package/src/engine/network/state/FrameBufferRing.d.ts.map +1 -0
- package/src/engine/network/state/FrameBufferRing.js +168 -0
- package/src/engine/network/state/InputRing.d.ts +14 -12
- package/src/engine/network/state/InputRing.d.ts.map +1 -1
- package/src/engine/network/state/InputRing.js +37 -76
- package/src/engine/network/transport/LoopbackTransport.d.ts.map +1 -1
- package/src/engine/network/transport/LoopbackTransport.js +10 -31
- package/src/engine/network/transport/Transport.d.ts +42 -2
- package/src/engine/network/transport/Transport.d.ts.map +1 -1
- package/src/engine/network/transport/Transport.js +87 -3
- package/src/engine/network/transport/adapters/NodeUDPTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/NodeUDPTransport.js +7 -33
- package/src/engine/network/transport/adapters/SimulatedTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/SimulatedTransport.js +17 -28
- package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +6 -32
- package/src/engine/network/transport/adapters/WebSocketTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/WebSocketTransport.js +6 -32
- package/src/engine/network/transport/adapters/WebTransportTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/WebTransportTransport.js +11 -22
- package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
- package/src/engine/physics/constraint/solve_constraints.js +18 -48
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
- package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.js +7 -0
- package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.js +11 -18
- package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.js +7 -0
- package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.js +15 -57
- package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.js +7 -0
- package/src/engine/physics/fluid/solver/v3_grid_limit8_at_indices.d.ts +28 -0
- package/src/engine/physics/fluid/solver/v3_grid_limit8_at_indices.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_limit8_at_indices.js +38 -0
- package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.js +12 -14
- package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.js +9 -0
- package/src/engine/physics/mls-mpm/MLS_MPM.d.ts +13 -1
- package/src/engine/physics/mls-mpm/MLS_MPM.d.ts.map +1 -1
- package/src/engine/physics/mls-mpm/MLS_MPM.js +15 -4
- package/src/engine/physics/narrowphase/box_triangle_contact.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/box_triangle_contact.js +9 -0
- package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/capsule_contacts.js +10 -11
- package/src/engine/physics/narrowphase/sphere_triangle_contact.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/sphere_triangle_contact.js +7 -12
- package/src/engine/physics/solver/apply_impulse_to_body.d.ts +36 -0
- package/src/engine/physics/solver/apply_impulse_to_body.d.ts.map +1 -0
- package/src/engine/physics/solver/apply_impulse_to_body.js +86 -0
- package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -1
- package/src/engine/physics/solver/solve_contacts.js +1 -53
- package/src/engine/plugin/EnginePlugin.d.ts +3 -0
- package/src/engine/plugin/EnginePlugin.d.ts.map +1 -1
- package/src/engine/plugin/EnginePlugin.js +3 -0
- package/src/engine/save/storage/IndexedDBStorage.d.ts +1 -0
- package/src/engine/save/storage/IndexedDBStorage.d.ts.map +1 -1
- package/src/engine/save/storage/IndexedDBStorage.js +50 -50
- package/src/engine/sound/ecs/SoundControllerSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/SoundControllerSystem.js +2 -10
- package/src/engine/sound/simulation/AcousticSimulator.d.ts.map +1 -1
- package/src/engine/sound/simulation/AcousticSimulator.js +2 -1
- package/src/engine/sound/simulation/core/AcousticOccluderIndex.d.ts.map +1 -1
- package/src/engine/sound/simulation/core/AcousticOccluderIndex.js +4 -6
- package/src/engine/sound/simulation/core/OcclusionSolver.d.ts.map +1 -1
- package/src/engine/sound/simulation/core/OcclusionSolver.js +2 -9
- package/src/engine/sound/simulation/probe/ProbeVisibilityRecheck.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/ProbeVisibilityRecheck.js +9 -14
- package/src/engine/sound/simulation/probe/bakeReverbBands.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/bakeReverbBands.js +2 -6
- package/src/engine/sound/simulation/probe/bakeVisibility.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/bakeVisibility.js +4 -34
- package/src/engine/sound/simulation/probe/probe_densify_portals.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/probe_densify_portals.js +3 -6
- package/src/engine/sound/simulation/probe/probe_edge_key.d.ts +31 -0
- package/src/engine/sound/simulation/probe/probe_edge_key.d.ts.map +1 -0
- package/src/engine/sound/simulation/probe/probe_edge_key.js +38 -0
- package/src/engine/sound/simulation/probe/probe_sdf_grid.d.ts +10 -3
- package/src/engine/sound/simulation/probe/probe_sdf_grid.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/probe_sdf_grid.js +10 -22
- package/src/engine/sound/simulation/probe/probe_visibility_augment.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/probe_visibility_augment.js +12 -48
- package/src/engine/sound/simulation/probe/probe_visibility_bridge_components.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/probe_visibility_bridge_components.js +4 -3
- package/src/engine/sound/simulation/render/foaReverbImpulseResponse.d.ts +5 -4
- package/src/engine/sound/simulation/render/foaReverbImpulseResponse.d.ts.map +1 -1
- package/src/engine/sound/simulation/render/foaReverbImpulseResponse.js +23 -31
- package/src/engine/sound/simulation/render/reverbImpulseResponse.d.ts +1 -8
- package/src/engine/sound/simulation/render/reverbImpulseResponse.d.ts.map +1 -1
- package/src/engine/sound/simulation/render/reverbImpulseResponse.js +21 -31
- package/src/engine/sound/simulation/render/reverb_band_tails.d.ts +55 -0
- package/src/engine/sound/simulation/render/reverb_band_tails.d.ts.map +1 -0
- package/src/engine/sound/simulation/render/reverb_band_tails.js +93 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +6 -22
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.js +7 -3
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.js +7 -22
- package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.js +28 -0
- package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.js +1 -5
- package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.js +1 -13
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.js +2 -8
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts +3 -0
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +26 -14
- package/src/engine/sound/sopra/runtime/BusGraph.d.ts.map +1 -1
- package/src/engine/sound/sopra/runtime/BusGraph.js +21 -33
- package/src/engine/sound/sopra/runtime/EventInstance.js +1 -1
- package/src/engine/ui/apply_pointer_tilt_3d.d.ts +25 -0
- package/src/engine/ui/apply_pointer_tilt_3d.d.ts.map +1 -0
- package/src/engine/ui/apply_pointer_tilt_3d.js +50 -0
- package/src/engine/ui/bindings/processors/DomElementProcessorTilt3D.d.ts.map +1 -1
- package/src/engine/ui/bindings/processors/DomElementProcessorTilt3D.js +9 -26
- package/src/generation/filtering/numeric/CellFilterCache.d.ts.map +1 -1
- package/src/generation/filtering/numeric/CellFilterCache.js +4 -21
- package/src/generation/filtering/numeric/complex/CellFilterSobel.d.ts.map +1 -1
- package/src/generation/filtering/numeric/complex/CellFilterSobel.js +11 -20
- package/src/generation/filtering/numeric/math/CellFilterPower.d.ts +1 -1
- package/src/generation/filtering/numeric/math/CellFilterPower.d.ts.map +1 -1
- package/src/generation/filtering/numeric/math/CellFilterPower.js +1 -5
- package/src/generation/filtering/numeric/process/computeCellFilterGradient.d.ts.map +1 -1
- package/src/generation/filtering/numeric/process/computeCellFilterGradient.js +13 -15
- package/src/generation/filtering/numeric/process/computeCellFilterSobel.d.ts +20 -0
- package/src/generation/filtering/numeric/process/computeCellFilterSobel.d.ts.map +1 -0
- package/src/generation/filtering/numeric/process/computeCellFilterSobel.js +36 -0
- package/src/generation/filtering/numeric/util/CellFilterDisplaced.d.ts.map +1 -1
- package/src/generation/filtering/numeric/util/CellFilterDisplaced.js +11 -6
- package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.d.ts.map +1 -1
- package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.js +18 -36
- package/src/generation/filtering/numeric/util/write_cell_filter_to_sampler2d.d.ts +21 -0
- package/src/generation/filtering/numeric/util/write_cell_filter_to_sampler2d.d.ts.map +1 -0
- package/src/generation/filtering/numeric/util/write_cell_filter_to_sampler2d.js +47 -0
- package/src/generation/filtering/util/cell_filter_weights_pick.d.ts +25 -0
- package/src/generation/filtering/util/cell_filter_weights_pick.d.ts.map +1 -0
- package/src/generation/filtering/util/cell_filter_weights_pick.js +54 -0
- package/src/generation/grid/generation/discrete/GridTaskConnectRooms.d.ts.map +1 -1
- package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +14 -1
- package/src/generation/markers/GridActionRuleSet.d.ts.map +1 -1
- package/src/generation/markers/GridActionRuleSet.js +10 -7
- package/src/generation/markers/GridCellActionPlaceMarker.d.ts.map +1 -1
- package/src/generation/markers/GridCellActionPlaceMarker.js +10 -12
- package/src/generation/markers/actions/probability/MarkerNodeActionSelectWeighted.d.ts.map +1 -1
- package/src/generation/markers/actions/probability/MarkerNodeActionSelectWeighted.js +7 -42
- package/src/generation/markers/transform/MarkerNodeTransformerOffsetPosition.d.ts.map +1 -1
- package/src/generation/markers/transform/MarkerNodeTransformerOffsetPosition.js +11 -6
- package/src/generation/placement/GridCellPlacementRule.d.ts.map +1 -1
- package/src/generation/placement/GridCellPlacementRule.js +10 -7
- package/src/generation/placement/action/GridCellActionPlaceTags.d.ts.map +1 -1
- package/src/generation/placement/action/GridCellActionPlaceTags.js +10 -4
- package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.d.ts.map +1 -1
- package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.js +2 -38
- package/src/generation/placement/action/util/GridCellDisplacedAction.d.ts.map +1 -1
- package/src/generation/placement/action/util/GridCellDisplacedAction.js +11 -6
- package/src/generation/rules/cell/CellMatcherGridPattern.d.ts.map +1 -1
- package/src/generation/rules/cell/CellMatcherGridPattern.js +11 -4
- package/src/generation/theme/ThemeEngine.d.ts.map +1 -1
- package/src/generation/theme/ThemeEngine.js +7 -12
- package/src/view/elements/Group.d.ts +24 -3
- package/src/view/elements/Group.d.ts.map +1 -1
- package/src/view/elements/Group.js +56 -34
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Domain K — cross-cutting reuse failures
|
|
2
|
+
|
|
3
|
+
Scope: concerns that cut across packages. Every count below comes from a grep/AST census run over
|
|
4
|
+
`H:/git/moh/app/src/mir-engine/meep/src/` excluding `*.spec.js`, `prototype*.js`, `test*.js`.
|
|
5
|
+
Census scripts are in the scratchpad (`grow.mjs`, `sys.mjs`, `sys2.mjs`, `census.mjs`).
|
|
6
|
+
|
|
7
|
+
## Findings
|
|
8
|
+
|
|
9
|
+
| # | Severity | Concept | # of independent impls | Representative sites | Existing primitive (if any) | Verdict | Proposed common path | Effort/Risk |
|
|
10
|
+
|---|---|---|---|---|---|---|---|---|
|
|
11
|
+
| K1 | **HIGH** ⚠ **INCONSISTENT** | 32-bit hash *combine* (`h*31 + v`) | **33 files** hand-roll the mix (74 mix statements) while **62 files** import the primitive | `engine/physics/ecs/Joint.js:444`, `engine/physics/ecs/RigidBody.js:281`, `engine/physics/ecs/Collider.js:159`, `core/geom/3d/shape/HeightMapShape3D.js:461`, `core/model/BoundedValue.js:180`, `core/geom/Vector2.js:640`, `core/graph/csr/CSRGraph.js:281` | `core/collection/array/combine_hash.js:9` (variadic); `core/math/hash/lowbias32.js`, `murmur3_32.js`, `squirrel3.js` | **UNJUSTIFIED** — but see K1a: the mixes are not the same function | Add a non-variadic, allocation-free `hash_combine(h, v)` in `core/math/hash/` (2 args, `|0`-truncating) and route both `combine_hash` and the 33 hand-rolled chains through it | M / M — every changed `hash()` changes its value; any persisted hash must be re-baselined |
|
|
12
|
+
| K1a | **HIGH** ⚠ **INCONSISTENT** | integer-domain discipline of the *same* hash | **4 mutually-incompatible disciplines** across 5 sibling functions | `core/collection/array/computeHashArray.js:24` (`hash \|= 0` every iteration) vs `core/collection/array/typed/uint32_array_hash.js:15` (**never truncates**) vs `core/collection/array/computeStridedIntegerArrayHash.js:27` (`>>> 0` at the end only) vs `core/primitives/strings/computeStringHash.js:40` (`>>> 0`) vs `core/geom/Vector2.js:640` (no truncation, returns a non-int32) | — | **UNJUSTIFIED / correctness hazard** | One truncation rule (`\| 0` per step) applied by the shared `hash_combine`; `uint32_array_hash` currently returns an ever-widening float (its accumulator escapes int32 on the first ≥2³¹ element and drifts as a ±random walk — the exact workload `CSRGraph.hash()` feeds it at `CSRGraph.js:285-292`) | S / M |
|
|
13
|
+
| K2 | **HIGH** ⚠ **INCONSISTENT** | `(array, offset, length)` array-hash contract | latent off-by-semantics replicated into **5** clones | `core/collection/array/typed/uint32_array_hash.js:11`, `uint8_array_hash.js:19`, `uint16_array_hash.js:17`, `core/collection/array/computeStridedIntegerArrayHash.js:14`, `computeStridedArrayHash.js:23` — all loop `i < length` while the JSDoc and `array_buffer_hash.js:12` treat `length` as a **count**, so any `offset > 0` silently hashes the wrong (short) range | — | **UNJUSTIFIED** — copy-paste propagated the defect into every clone | Fix once in a shared `hash_combine`-based loop; `uint8_array_hash.js:15` is even self-contradictory (head loop `i < offset + overflow`, body loop `i < length`). All current callers pass `offset === 0`, so nothing is broken **today**, but `offset` is public library surface | S / L |
|
|
14
|
+
| K3 | LOW ⚠ **INCONSISTENT** | word packing in sibling array hashes | 2 | `core/collection/array/typed/uint8_array_hash.js:26-29` packs **little-endian** (`v0 \| v1<<8 \| v2<<16 \| v3<<24`); `uint16_array_hash.js:22` packs **big-endian** (`(v0 << 16) \| v1`) | — | UNJUSTIFIED (cosmetic) | Pick one byte order across the family | S / L |
|
|
15
|
+
| K4 | **HIGH** ⚠ **INCONSISTENT** | explicit-stack quicksort partition | **9** (4 in `core`, 5 hand-rolled) | core: `core/collection/array/array_sort_quick.js:45`, `array_quick_sort_by_comparator.js:36`, `array_quick_sort_by_lookup_map.js:39`, `array_quick_sort_by_lookup_uint.js:38`; hand-rolled: `engine/graphics/render/forward_plus/sort_decal_data.js:65`, `view/minimap/gl/MinimapMarkersGL.js:165`, `engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js:756`, `core/bvh2/binary/2/BinaryUint32BVH.js:364`, `core/geom/2d/r-tree/StaticR2Tree.js:250` | `core/collection/array/array_quick_sort_by_comparator.js` | **UNJUSTIFIED for `sort_decal_data`; JUSTIFIED for the 4 others** (BVH/R-Tree/particles partition a *parallel* index array by a derived key with an inline swap — no existing signature covers that) | Give `core/collection/array/` a `quick_sort_indices(lookup, count, less_fn)` that partitions an index array; port `sort_decal_data` + `MinimapMarkersGL` onto it | M / M |
|
|
16
|
+
| K4a | **HIGH** | pivot capture in the copied quicksort | 1 divergent copy of 9 | `engine/graphics/render/forward_plus/sort_decal_data.js:70,74` compares `compare_decals(i, pivotIndex, …)` against the **live pivot index**; every other copy captures the pivot **value** first (`array_quick_sort_by_comparator.js:38`, `ParticleEmitter.js:758`, `MinimapMarkersGL.js:168`) | — | **UNJUSTIFIED / correctness hazard** | Once the element at `pivotIndex` is swapped the partition invariant breaks and decals come out in a wrong blend order. Fix by capturing the pivot's encoded value before the partition loop | S / L |
|
|
17
|
+
| K5 | **MED** ⚠ **INCONSISTENT** | binary search / lower bound | **6** (2 in `core`, 4 hand-rolled) with **4 different miss/tie semantics** | `core/collection/array/binarySearchLowIndex.js:10` (floor index, `-1` if below range, arbitrary index inside an equal run); `binarySearchHighIndex.js:10` (exact index, else insertion point `min`); `engine/animation/async/table_find_min_index_in_ordered_column.js:14` (returns `min2(minIndex,maxIndex)`; its JSDoc claims "low index of matching value" but it returns an **arbitrary** index of an equal run); `engine/animation/curve/AnimationCurve.js:233` (last index with `time ≤ t`, then explicitly fast-forwards over duplicates); `engine/graphics/sh3/lpg/bake_probe_sh3_resampled.js:61` (true `lower_bound`: `low < high`, `> value → high = mid`); `engine/sound/simulation/probe/probe_visibility_augment.js:170` (membership only) | `core/collection/array/binarySearch{Low,High}Index.js` | **UNJUSTIFIED for the semantics; JUSTIFIED for the typed-array/CSR ones** (`probe_visibility_augment` searches a `Uint32Array` slice, the core helpers take a comparator closure) | Document + name the two semantics explicitly (`array_lower_bound` = first index with `arr[i] >= v`, `array_upper_bound` = first index with `arr[i] > v`), fix `table_find_min_index_in_ordered_column`'s JSDoc-vs-behaviour mismatch, and give `core/graph/csr/` a `csr_adjacency_contains(adj, addr, u, v)` for the CSR case | M / M |
|
|
18
|
+
| K6 | **MED** | typed-array capacity growth (`new T(newCap)` + `.set(old)`) | **22** independent implementations, **5 different growth policies** | `core/collection/heap/Uint32Heap.js:103` (`max(cap*F, cap+MIN)`), `engine/physics/broadphase/PairList.js:91` (`cap << 1`), `engine/physics/events/ContactEventBuffer.js:65` (`cap << 1`, inlined in `push`), `engine/network/state/ReplicationSlotTable.js:198` (`max(cap*2, cap+64)`), `engine/sound/simulation/probe/AcousticProbeField.js:160` (`do{cap = max(cap*2, DEFAULT)}while`), `core/geom/2d/packing/skyline.js:90` (`while(cap<n) cap*=2`), plus `core/graph/csr/CSRGraph.js:191`, `core/collection/table/RowFirstTable.js:185`, `engine/graphics/sh3/lpv/LightProbeVolume.js:137`, `engine/physics/contact/ManifoldStore.js:742`, `engine/physics/body/BodyStorage.js:400`, `core/binary/BitSet.js:152` … | **none** — `core/collection/array/typed/` has copy/hash/convert helpers but no grow | **PROMOTION** | Add `core/collection/array/typed/typed_array_grow(array, min_capacity)` returning a new array of the same constructor with the old contents copied, using one geometric policy. Callers that keep several parallel arrays (CSRGraph, ManifoldStore, LightProbeVolume) call it once per array | M / L — pure refactor, growth policy change is a perf-only delta |
|
|
19
|
+
| K7 | LOW | defensive byte-slice copy (`new Uint8Array(len)` + `.set(src.subarray(0,len))`) | **6**, byte-identical | `engine/network/diagnostics/ReplayLog.js:42`, `engine/network/transport/LoopbackTransport.js:95`, `engine/network/transport/adapters/SimulatedTransport.js:157`, `engine/network/transport/fragments/FragmentAssembler.js:188`, `engine/network/transport/fragments/FragmentRetention.js:108`, `engine/network/transport/ReliableCommandPipeline.js:226` | `core/collection/array/typed/typed_array_copy.js` (copies into an *existing* destination, doesn't allocate) | **PROMOTION** | `core/collection/array/typed/typed_array_slice_copy(source, length)` → fresh same-type array. 6 call sites, 2 lines each | S / L |
|
|
20
|
+
| K8 | **HIGH** | ECS per-entity link/unlink bookkeeping | **17** hand-rolled vs **7** using the existing base class | hand-rolled: `engine/sound/simulation/ecs/AcousticVolumeSystem.js:40/55`, `engine/sound/simulation/ecs/AcousticSimulationSystem.js:45/62`, `engine/grid/grid2transform/GridPosition2TransformSystem.js:40/79`, `engine/graphics/ecs/mesh/MeshSystem.js:256/296`, `engine/interpolation/InterpolationSystem.js:119/132`, `engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js:307/356`, `engine/sound/ecs/audio/AudioEmitterSystem.js:129/162` (+10 more) | `engine/ecs/system/AbstractContextSystem.js` (+ `SystemEntityContext`), used by `LightSystem`, `FPDecalSystem`, `PathDisplaySystem`, `SpriteSystemPE`, `VoiceSystem`, `ParentEntitySystem`, `DynamicActorSystem` | **UNJUSTIFIED at the census level** — the shape is identical: build a record in `link`, store at `this.data[entity]`, subscribe signals, `delete this.data[entity]` + unsubscribe in `unlink` | See notes: the blocker is that `AbstractContextSystem.link()` dispatches through `arguments` (`AbstractContextSystem.js:69-90`), which is exactly the "magic" the house style rejects. Propose typed arity-specific bases (`ContextSystem1`/`ContextSystem2`/`ContextSystem3` with real named parameters) and migrate the 17 | L / M |
|
|
21
|
+
| K8a | LOW | `delete this.data[entity]` on a dense array | 17 (same files as K8) | `engine/sound/simulation/ecs/AcousticVolumeSystem.js:60`, `engine/grid/grid2transform/GridPosition2TransformSystem.js:85`, `engine/graphics/ecs/mesh/MeshSystem.js` unlink | — | UNJUSTIFIED (perf, folds into K8) | `delete` on an array index forces the backing store to dictionary mode. Whatever K8 lands should store contexts in a `Uint32Map`/plain array + tombstone instead | folds into K8 |
|
|
22
|
+
| K9 | **MED** ⚠ **INCONSISTENT** | linear scan for an element by `.id`/`.name` | **22** explicit loops (plus ~20 more using `Array.prototype.find`) | `core/binary/type/Type.js:44` (returns **`null`**), `engine/graphics/geometry/AttributeGroupSpec.js:56` (returns **`undefined`**), `generation/grid/GridData.js:82` (returns **`undefined`**), `engine/scene/SceneManager.js:101` (returns **`-1`**), `core/model/node-graph/node/NodeDescription.js:169`, `engine/graphics/particles/particular/group/ParticleSpecification.js:26`, `engine/plugin/EnginePluginManager.js:311` | `core/collection/array/array_index_by_equality.js` | **JUSTIFIED for the loop; UNJUSTIFIED for the sentinel** — a generic `find_by(array, key, value)` would be a **string-keyed** lookup, which the house style forbids; the closure form is already `Array.prototype.find`. The real defect is that the "not found" answer is three different values across sibling APIs | Do **not** extract a helper. Instead standardise the miss sentinel per return kind (element-returning → `undefined`, index-returning → `-1`) and drop the `null` returns (`Type.js:50`) per the no-null house rule | S / L |
|
|
23
|
+
| K10 | **HIGH** | raw `Math.random()` on paths that must be deterministic | **11** sites; 2 are simulation-authoritative | `engine/ecs/dynamic_actions/actions/definition/WeightedRandomActionDescription.js:31` (**seeds an AI behaviour tree** — `actor_seed ^ computeHashFloat(Math.random())`), `engine/intelligence/behavior/util/RandomDelayBehavior.js:9` (**seeds behaviour-tree delays** — `Date.now() ^ Math.random()*UINT32_MAX`), `engine/physics/mls-mpm/MLS_MPM.js:388`, `engine/sound/sopra/definition/effect/ReverbEffect.js:59` (reverb IR differs every session), `engine/animation/removeEntityWithMeshParticlesEffect.js:167`, `view/minimap/dom/MinimapCameraView.js:110`, `engine/ecs/terrain/tiles/TerrainTileManager.js:208` (debug-only), `engine/sound/ecs/SoundControllerSystem.js:15` (`@deprecated`) | `core/math/random/seededRandom.js`, `randomSeed.js`, `randomFromArray.js` (63 files already use them) | **UNJUSTIFIED for the top 4; JUSTIFIED (cosmetic) for minimap jitter, VFX seed, debug tile colour** | Route the two behaviour-tree seeds off a run-level seeded stream (the engine already threads seeds — `MarkerNodeActionSelectWeighted.js:92` shows the pattern). `MLS_MPM.add_rnd_square` should take a `random` argument like every other `sample_random_point_in_volume` in `core/geom/3d/shape/`. `ReverbEffect` should hash its own parameters into a `seededRandom` | M / M |
|
|
24
|
+
| K11 | — | seeded RNG algorithm count | **2** (`seededRandom_Mulberry32.js`, `seededRandom_MersenneTwister.js`; `seededRandom.js` is an alias for the former) | `core/math/random/seededRandom.js:4` | — | **CLEAN — no finding.** There are *not* several competing RNGs. Stateless mixers (`lowbias32`, `murmur3_32`, `squirrel3`) are a different concept and each has one implementation | — | — |
|
|
25
|
+
| K12 | LOW ⚠ **INCONSISTENT** | weighted (cumulative) random selection | **3 core entry points + 1 hand-rolled** | `core/math/random/random_pick_weighted_index.js:12`, `core/collection/array/weightedRandomFromArray.js:21`, `core/geom/3d/shape/UnionShape3D.js:131,257` (both call the core `binarySearchHighIndex`), hand-rolled: `engine/graphics/sh3/lpg/bake_probe_sh3_resampled.js:53` (`pick_candidate`, a true `lower_bound`) | `core/math/random/random_pick_weighted_index.js` | **JUSTIFIED (`pick_candidate` works on a module-static `Float64Array` with no comparator closure, in a per-probe inner loop) — but the tie-break disagrees** | `binarySearchHighIndex` returns an **arbitrary** index inside an equal cumulative run, so `random_pick_weighted_index` can select a **zero-weight** entry when `random()*total` lands exactly on a boundary (reachable: Mulberry32 returns exact `0`). `pick_candidate` cannot. Make the shared path use `lower_bound` semantics | S / L |
|
|
26
|
+
| K13 | **MED** ⚠ **INCONSISTENT** | three.js material `transform()` / `onBeforeCompile` marker injection | **3** near-identical copies with **3 different clone semantics** | `engine/graphics/render/forward_plus/plugin/MaterialTransformer.js:91` (`result = source.clone()` — clones, source untouched), `engine/graphics/sh3/gi/material/MaterialTransformer.js:294` (**`result.clone();` — return value discarded**, then mutates `source` in place: a dead statement, clear copy-paste artifact), `engine/graphics/sh3/lpg/material/LightProbeGridMaterialTransformer.js:207` (no clone at all, mutates `source`) | `engine/graphics/material/composeCompile.js`, `…/forward_plus/plugin/isLitMaterial.js` — the *pieces* are already shared; the ~25-line guard/clone/mark envelope is not | **UNJUSTIFIED / correctness hazard** | Extract `material_transform_once(source, marker, on_before_compile, {clone})` — or, house-style, a small `AbstractMaterialTransformer` base with an explicit `clone` policy decided once. Also: two of the three declare a **module-local `const PROPERTY_TRANSFORMER_MARKER`** with *different values* (`MaterialTransformer.js:19` vs `LightProbeGridMaterialTransformer.js:15`) — same identifier, different meaning | M / M |
|
|
27
|
+
| K14 | LOW ⚠ **INCONSISTENT** | the identifier `EPSILON` | **5 different values** live under one name | `core/math/EPSILON.js:5` = `1e-7` (imported by 21 files) vs module-local `const EPSILON` = `1e-10` in `core/math/linalg/eigen/matrix_qr_in_place.js:1` and `matrix_householder_in_place.js:1`, `1e-9` in `engine/animation/curve/animation_curve_optimize.js:106`, `1e-17` in `core/geom/3d/topology/struct/binary/io/bt_mesh_face_island_erode.js:427` | `core/math/EPSILON.js`, `FLT_EPSILON_{16,32,64}.js` | **JUSTIFIED (the tolerances are algorithm-specific) / UNJUSTIFIED (the name is not)** | Rename the locals to domain names, as ~20 other files already do (`MPR_EPSILON`, `PLANE_EPS`, `BARY_EPS`, `EPA_EPS`, `STALE_EPSILON`) | S / L |
|
|
28
|
+
| K15 | LOW | `Math.abs(a - b) < eps` inline | 23 sites; `epsilonEquals` used by 10 files | `core/geom/mat2/m2_is_orthogonal.js:18`, `engine/sound/simulation/render/ProbeReverbRenderer.js:198-200`, `engine/physics/fluid/ecs/FluidSystem.js:232-234`, `core/math/spline/spline3_hermite_nearest_point.js:103` | `core/math/epsilonEquals.js:11` | **JUSTIFIED** — every site passes its own domain tolerance; `epsilonEquals(a,b,tol)` adds only asserts, and half the sites are `>` (not-equal) tests that `epsilonEquals` cannot express without a negation. `roughlyEquals`/`_roughlyEquals` on `Vector2/3/Quaternion/ConicRay` is already the shared vector-level primitive | — | — |
|
|
29
|
+
| K16 | LOW | AABB accumulation over a point set (`x0 = Infinity` … min/max) | **10** hand-rolled + 4 primitives | hand-rolled: `core/bvh8/build/TriangleCluster.js:13`, `core/geom/2d/quad-tree-binary/QuadTree.js:142`, `core/geom/3d/shape/MeshShape3D.js:251`, `core/geom/3d/topology/struct/binary/query/bt_mesh_build_face_bvh.js:24`, `engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js:158`, `engine/sound/simulation/probe/probe_delaunay_edges.js:156`, `engine/sound/simulation/probe/probe_visibility_bridge_components.js` | `core/geom/3d/aabb/aabb3_from_v3_array.js`, `aabb3_from_v3_array_transformed.js`, `aabb_nd_from_points.js`, `core/geom/2d/aabb/aabb2_from_v2_buffer.js` | **PARTIALLY JUSTIFIED** — the *iteration source* genuinely differs (flat float buffer vs accessor methods vs half-edge loop walk), so one function cannot cover all. The reusable part is the 6-line accumulate step | Add `aabb3_array_expand_by_point(aabb, x, y, z)` next to the existing `aabb3_expand_array.js` and use it as the inner step; `probe_delaunay_edges` and `TriangleCluster` can call `aabb3_from_v3_array` outright | S / L |
|
|
30
|
+
| K17 | LOW | `traverseThreeObject` | 1 helper that reimplements `THREE.Object3D.prototype.traverse` | `engine/graphics/ecs/highlight/renderer/traverseThreeObject.js:7`; imported by `engine/asset/loaders/GLTFAssetLoader.js:9` and `engine/graphics/material/optimization/MaterialOptimizationContext.js:25`, while ~28 other sites call three's native `.traverse()` | `THREE.Object3D.traverse` | **JUSTIFIED (it adds a `thisArg`, which three's does not) / but misplaced** | Move it to `engine/graphics/three/` — the package's declared three-adapter boundary — rather than living under `highlight/renderer/` and being reached by a 4-level relative import from the asset loader | S / L |
|
|
31
|
+
| K18 | LOW | `WebGLRenderTarget` option bags | 15 construction sites, each repeating `depthBuffer/stencilBuffer/generateMipmaps/minFilter/magFilter` | `engine/graphics/ecs/highlight/renderer/OutlineRenderer.js:232,241,250,259,268`, `engine/graphics/render/visibility/hiz/query/BatchOcclusionQuery.js:41`, `engine/graphics/texture/virtual/VirtualTextureUsageUpdater.js:105`, `engine/graphics/render/visibility/hiz/buffer/HierarchicalZBuffer.js:94` | — | **JUSTIFIED** — three's constructor *is* the primitive; a wrapper would need per-field override sentinels, which the "uniform control flow" rule forbids. Only `OutlineRenderer`'s 5 adjacent near-identical bags are worth a local named-constant pair | — | — |
|
|
32
|
+
| K19 | — | three.js texture format / type / wrap translation | 1 composed family, no duplicates | `engine/graphics/texture/channelCountToThreeTextureFormat.js:9`, `computeThreeTextureFormat.js:10`, `attribute_spec_to_three_format.js:12`, `formatToChannelCount.js:19`, `computeThreeTextureFormatFromDataType.js` (`@deprecated`, delegates) | — | **CLEAN — no finding**, and the counter-example that proves the pattern works: one `switch`, everything else composes onto it | — | — |
|
|
33
|
+
| K20 | LOW | `document.createElement('canvas')` + size + `getContext` | 10 production sites | `engine/graphics/GraphicsEngine.js:492`, `engine/graphics/makeModelView.js:15`, `engine/graphics/render/RendererPool.js:9`, `engine/graphics/texture/sampler/sampler2d_to_data_url.js:14`, `engine/graphics/texture/sampler/convertTexture2Sampler2D.js:57`, `engine/asset/loaders/image/codec/NativeImageDecoder.js:14`, `engine/asset/loaders/material/computeImageBitmapEquality.js:61` | — | **JUSTIFIED** — 3 lines, and the contexts requested differ (`2d` vs `webgl2` vs none) | — | — |
|
|
34
|
+
| K21 | — | `clamp` / `lerp` / `DEG_TO_RAD` adoption | 1 inline clamp in the whole tree | only `core/graph/metis/native/bisection/fm_2way.js:50` nests `Math.min(Math.max(…))`; `Math.PI/180` appears inline 3× and all 3 are named constants for a fixed angle | `core/math/clamp.js`, `lerp.js`, `DEG_TO_RAD.js` | **CLEAN — no finding.** The 129 "inline lerp" pattern hits are flat-array vector math (`a + (b-a)*t` on `Float32Array` offsets), where a scalar `lerp` call is not the same operation | — | — |
|
|
35
|
+
| K22 | — | grid index ↔ coordinate (`y*width + x`) | ~25 inline sites | `engine/graphics/texture/sampler/Sampler2D.js:488`, `engine/graphics/sh3/lightmap/lightmap_denoise.js:60`, `engine/physics/fluid/ecs/FluidObstacleSystem.js:335` | — | **JUSTIFIED** — one arithmetic expression in hot per-texel loops; extracting it is a pure pessimisation with no correctness payoff | — | — |
|
|
36
|
+
|
|
37
|
+
## Per-concern detail
|
|
38
|
+
|
|
39
|
+
### 1. Hash combination
|
|
40
|
+
`core/collection/array/combine_hash.js` is the house primitive and is **well adopted — 62 importing files**.
|
|
41
|
+
Against that, **33 files** still hand-roll `h = h*31 + v` (74 statements). The worst concentrations are
|
|
42
|
+
`engine/physics/ecs` (Joint 13, RigidBody 12, Collider 4) and `core/geom/3d/shape` (7 files). These are
|
|
43
|
+
determinism/dedup hashes, called at checkpoints, not in inner loops — `combine_hash` is variadic (rest-arg
|
|
44
|
+
allocation), which is a fair reason to avoid it *there*, but not a reason to hand-inline a mix: the fix is a
|
|
45
|
+
2-arg `hash_combine(h, v)`. The mixes are **not** the same function once you account for truncation
|
|
46
|
+
(K1a): `|0` per step, `>>>0` at the end, or never — four disciplines in five sibling functions, and
|
|
47
|
+
`uint32_array_hash` leaks out of int32 entirely. Two further shared defects (K2 `offset` handling, K3
|
|
48
|
+
endianness) were copied into every clone, which is the clearest evidence in this audit that duplication here
|
|
49
|
+
propagates bugs rather than merely wasting lines.
|
|
50
|
+
|
|
51
|
+
### 2. `equals()` / epsilon comparison
|
|
52
|
+
`core/math/epsilonEquals.js` exists (10 importers) and `EPSILON = 1e-7`, `FLT_EPSILON_{16,32,64}` are all
|
|
53
|
+
provided. 23 inline `Math.abs(a-b) < eps` sites remain, but **every one passes a domain tolerance** chosen for
|
|
54
|
+
its algorithm (`PLANE_EPS = 1e-3`, `BARY_EPS = 1e-6`, `SEGMENT_EPS = 1e-12`, `DIR_EPS = 1e-18`), and about
|
|
55
|
+
half are `>` not-equal tests. This is **not** a reuse failure. The one real hazard is K14: four modules declare
|
|
56
|
+
a local `const EPSILON` with values from `1e-9` to `1e-17`, colliding with the imported `1e-7` name. Vector-level
|
|
57
|
+
tolerant comparison is already consolidated on `roughlyEquals`/`_roughlyEquals` (`Vector2.js:696`,
|
|
58
|
+
`Vector3.js:867`, `Quaternion.js:1479`, `ConicRay.js:83`).
|
|
59
|
+
|
|
60
|
+
### 3. Linear scan by id
|
|
61
|
+
**22** explicit for-loops that scan for `.id`/`.name`/`.key` and return the match, plus ~20 more written as
|
|
62
|
+
`Array.prototype.find`. Verdict is deliberately **not** "extract a helper": the only generic form is either
|
|
63
|
+
string-keyed (`find_by(array, 'name', x)` — forbidden by the typed-over-magic rule) or a closure, which
|
|
64
|
+
`Array.prototype.find` and `core/collection/array/array_index_by_equality.js` already are. The finding that
|
|
65
|
+
survives is the **miss sentinel**: `Type.getFieldByName` returns `null`, `AttributeGroupSpec.getAttribute` and
|
|
66
|
+
`GridData.getLayerById` return `undefined`, index-returning variants return `-1`. Three conventions for the
|
|
67
|
+
same question, and the `null` returns contradict the no-null-defaults house rule.
|
|
68
|
+
|
|
69
|
+
### 4. Binary search / lower bound
|
|
70
|
+
Six real implementations (the 30 `binary_search_inline` pattern hits are mostly `>> 1` bit arithmetic and
|
|
71
|
+
quicksort pivots — false positives). `core` provides two, `engine` hand-rolls four. They disagree on the two
|
|
72
|
+
questions that matter: what is returned on a **miss**, and which index is returned inside an **equal run**.
|
|
73
|
+
`AnimationCurve.js:238` is the only one that explicitly handles duplicate keys (it fast-forwards past the equal
|
|
74
|
+
run at `:249`) — and it had to, because the shared `binarySearchHighIndex` would have handed it an arbitrary
|
|
75
|
+
one. `table_find_min_index_in_ordered_column`'s JSDoc claims "low index of matching value"; the code does not
|
|
76
|
+
deliver that. `bake_probe_sh3_resampled.pick_candidate` is the only correct `lower_bound` in the tree.
|
|
77
|
+
|
|
78
|
+
### 5. Seeded vs unseeded randomness
|
|
79
|
+
Two questions, two different answers. **How many RNGs?** Only two (Mulberry32, Mersenne Twister), with
|
|
80
|
+
`seededRandom` aliasing the former — this is clean, no finding. **How many raw `Math.random()`?** Eleven, of
|
|
81
|
+
which four matter. `WeightedRandomActionDescription.js:31` and `RandomDelayBehavior.js:9` seed *behaviour trees*
|
|
82
|
+
from wall-clock/`Math.random()`, which defeats replay, rewind (`engine/network/sim/RewindEngine.js`) and the
|
|
83
|
+
action-log replication model. `MLS_MPM.add_rnd_square` (`:388`) is the only shape-sampling function in the tree
|
|
84
|
+
that does not take a `random` argument — every `sample_random_point_in_volume` in `core/geom/3d/shape/` does.
|
|
85
|
+
`ReverbEffect.js:59` bakes a fresh noise impulse response each session, so the same event sounds different run
|
|
86
|
+
to run. The remaining seven (minimap jitter, VFX seed, debug tile colour, a `@deprecated` sound picker) are
|
|
87
|
+
cosmetic and fine.
|
|
88
|
+
|
|
89
|
+
### 6. Weighted random selection
|
|
90
|
+
Better consolidated than the brief suggested: `random_pick_weighted_index`, `weightedRandomFromArray` and the
|
|
91
|
+
two `UnionShape3D` sites all funnel into `binarySearchHighIndex`, and `MarkerNodeActionSelectWeighted.js:92`
|
|
92
|
+
already uses the core helper. Only one hand-rolled selector remains — `pick_candidate` in
|
|
93
|
+
`bake_probe_sh3_resampled.js:53` — and it is justified (module-static `Float64Array`, no comparator closure, per-probe
|
|
94
|
+
inner loop). The finding is not duplication but disagreement: `pick_candidate` is a true `lower_bound` and so can
|
|
95
|
+
never select a zero-weight entry; the shared path can, because `binarySearchHighIndex` returns an arbitrary index
|
|
96
|
+
inside an equal cumulative run.
|
|
97
|
+
|
|
98
|
+
### 7. Typed-array growth
|
|
99
|
+
**22 independent grow implementations, 5 distinct growth policies**, and `core/collection/array/typed/` has no
|
|
100
|
+
grow helper despite holding copy/hash/convert/normalise helpers. Policies range from `cap << 1` (unbounded
|
|
101
|
+
doubling from a possibly-zero start — `PairList.js:91` would loop forever at `cap === 0`) to
|
|
102
|
+
`max(cap*1.5, cap+64)`. This is the cleanest **PROMOTION** in the audit: one function, no semantic choice to
|
|
103
|
+
make, and every call site is already isolated inside a private `#grow`/`__grow_capacity`/`ensureCapacity`.
|
|
104
|
+
Six further sites in `engine/network/transport` do exact-size defensive byte-slice copies (K7) — a different,
|
|
105
|
+
equally trivial promotion.
|
|
106
|
+
|
|
107
|
+
### 8. Object pooling
|
|
108
|
+
`core/model/object/ObjectPoolFactory.js` has 6 importers. Applying the brief's own distinction: the
|
|
109
|
+
module-static scratch objects (`weightedRandomFromArray.js:10`, `sort_decal_data.js:1`,
|
|
110
|
+
`bake_probe_sh3_resampled.js:37`) are idiomatic and **not** findings. The free-list allocators
|
|
111
|
+
(`core/bvh2/bvh3/BVH.js:156`, `core/geom/2d/bvh/BVH2D.js:111`, `core/geom/3d/tetrahedra/TetrahedralMesh.js:127`,
|
|
112
|
+
`core/geom/3d/topology/struct/binary/BinaryElementPool.js:40`) are **slot** allocators over typed arrays —
|
|
113
|
+
a different concept from `ObjectPoolFactory`'s object recycling, and three of them already delegate to
|
|
114
|
+
`BinaryElementPool`. **No genuine hand-rolled duplicate of `ObjectPoolFactory` was found.** The one soft spot
|
|
115
|
+
is `core/cache/wtinylfu/CacheWTinylfu.js:757` (`pool.length > 0 ? pool.pop() : new CacheElementWTinylfu()`),
|
|
116
|
+
a 1-line inline pool in a hot cache path — justified.
|
|
117
|
+
|
|
118
|
+
### 9. three.js translation at non-boundary sites
|
|
119
|
+
The 208 `from 'three'` imports are *not* the story: 26 of them are in `engine/graphics/ecs`, which is a
|
|
120
|
+
rendering-binding layer by design. Checking the four candidate translations named in the brief:
|
|
121
|
+
texture format/type/wrap enum mapping is **cleanly factored** (K19) — one `switch`, everything composes;
|
|
122
|
+
`WebGLRenderTarget` construction is 15 vendor option bags with no shared logic to extract (K18);
|
|
123
|
+
`BufferGeometry` attribute setup (179 `setAttribute`/`BufferAttribute` sites) is genuinely per-geometry;
|
|
124
|
+
`Object3D` traversal has one helper that duplicates three's own but adds `thisArg`, merely misplaced (K17).
|
|
125
|
+
The one real repeat is **material `onBeforeCompile` marker injection** (K13): three copies of a 25-line
|
|
126
|
+
guard/clone/mark envelope that disagree on whether they clone, one of which contains a dead `result.clone();`.
|
|
127
|
+
|
|
128
|
+
### 10. ECS System lifecycle boilerplate
|
|
129
|
+
58 `extends System` classes tree-wide: 44 define `link`, 43 `unlink`, 23 `startup`, 18 `shutdown`.
|
|
130
|
+
Signal subscribe/unsubscribe is **balanced in all 17 systems that subscribe** — no leak pattern at the census
|
|
131
|
+
level. The duplication is the per-entity record: **17 systems** build a record in `link`, store it at
|
|
132
|
+
`this.data[entity]`, and `delete this.data[entity]` in `unlink`, while **7 systems** get exactly that from
|
|
133
|
+
`engine/ecs/system/AbstractContextSystem.js`. A typed shared helper is viable, but the existing one is not the
|
|
134
|
+
one to spread: its `link()` reads `arguments` positionally and copies components into `ctx.components[i]`
|
|
135
|
+
(`AbstractContextSystem.js:69-90`), i.e. untyped variadic dispatch — the house style's stated objection. The
|
|
136
|
+
honest recommendation is arity-specific typed bases with named parameters, then migrate.
|
|
137
|
+
|
|
138
|
+
### 11. Other systemic patterns checked
|
|
139
|
+
Checked and **clean, no finding**: `clamp` (1 inline site tree-wide), `lerp`, `smoothStep`,
|
|
140
|
+
`DEG_TO_RAD`/`RAD_TO_DEG` (3 inline `Math.PI/180`, all named angle constants), dB↔linear
|
|
141
|
+
(`engine/sound/dB2Volume.js` + `volume2dB.js` are the single pair; `EventInstance.js:34` and
|
|
142
|
+
`echogram_band_rt60.js:49` are distinct formulas, not copies), sRGB↔linear (`core/color/sRGB/`, one impl;
|
|
143
|
+
the shader-side uses three's own), string padding/`toFixed` (no repeated formatter), grid index↔coord (K22),
|
|
144
|
+
`Object.assign` shallow clone (9 sites, all genuinely different objects), `JSON.parse(JSON.stringify())`
|
|
145
|
+
deep clone (3 sites, all in cold paths).
|
|
146
|
+
|
|
147
|
+
## Notes — what structurally causes cross-cutting reuse failure here
|
|
148
|
+
|
|
149
|
+
1. **The primitives exist and are known; the gap is at the *last mile*.** `combine_hash` has 62 importers,
|
|
150
|
+
`seededRandom` 63, `clamp`/`lerp` are near-universal. Reuse failure is not ignorance of `core/` — it
|
|
151
|
+
concentrates in the last two lines of an otherwise-reusing function (`h = h*31 + v` written inline inside a
|
|
152
|
+
`hash()` that already imports three other core helpers).
|
|
153
|
+
2. **The missing primitives are the ones nobody thought to name.** Typed-array growth (22 impls) and
|
|
154
|
+
defensive byte-slice copy (6 impls) have no `core/` home at all — and both are single-signature functions
|
|
155
|
+
with zero design choices. Where `core/` names a concept, the codebase converges on it; where it does not,
|
|
156
|
+
it diverges 22 ways.
|
|
157
|
+
3. **Copy-paste is the propagation vector for defects, not just for lines.** The `offset`/`length` confusion
|
|
158
|
+
(K2) exists identically in five hash functions; the four-way truncation disagreement (K1a) exists because
|
|
159
|
+
each was typed fresh; the live-pivot quicksort (K4a) is a copy that dropped one line
|
|
160
|
+
(`const pivot = data[pivotIndex]`); the dead `result.clone();` in the GI material transformer (K13) is a
|
|
161
|
+
copy that dropped an assignment. Every ⚠ in this report is a *divergence introduced by copying*, not an
|
|
162
|
+
independently-invented alternative.
|
|
163
|
+
4. **When a shared abstraction violates the house style, adoption stalls and the duplication grows around it.**
|
|
164
|
+
`AbstractContextSystem` is the correct abstraction for 24 systems and has 7 users; the other 17 hand-roll it.
|
|
165
|
+
Its `link()` is `arguments`-based magic. This is the codebase telling you which rule wins.
|
|
166
|
+
5. **Family functions written as siblings rather than as one function plus adapters drift.** The five array-hash
|
|
167
|
+
functions, the four quicksorts in `core/collection/array/`, the two binary searches — each family was written
|
|
168
|
+
as N parallel files, and each family now disagrees internally. The texture-format family (K19), written as
|
|
169
|
+
one `switch` plus composing wrappers, is the counter-example and has no drift at all.
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# meep — unjustified code duplication audit
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-08-07
|
|
4
|
+
**Scope:** `meep/src/**` (+ `meep/editor/**` for the view domain). 5,321 `.js` files.
|
|
5
|
+
**Excluded from findings:** `*.spec.js`, `prototype*.js` / `test*.js` browser harnesses, `samples/**`.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. The headline
|
|
10
|
+
|
|
11
|
+
The interesting result is not that meep repeats itself. It is **what the repetition costs**.
|
|
12
|
+
|
|
13
|
+
Across 241 verified findings, the recurring failure mode is not wasted lines — it is **fixes that
|
|
14
|
+
reach one copy and not the others**. In every pair below, someone found a bug, reasoned about it,
|
|
15
|
+
often wrote a comment explaining it, and fixed the copy in front of them. The twin still has the bug.
|
|
16
|
+
|
|
17
|
+
✔ = re-verified against source during the adversarial pass on this document; the rest are as reported
|
|
18
|
+
by the domain reviewers and carry their evidence in §8.
|
|
19
|
+
|
|
20
|
+
| ✔ | Fix that landed | Twin that never got it | Consequence |
|
|
21
|
+
|---|---|---|---|
|
|
22
|
+
| ✔ | `IndexedDBStorage.store()` (`engine/save/storage/IndexedDBStorage.js:98`) resolves on transaction **commit**, with a comment: reporting success off the request "turns a lost save into a reported save" | `IndexedDBStorage.remove()` (same file, `:45`) still resolves on `idbRequest` `success` (`:57`) | A delete is reported durable when its transaction later aborts |
|
|
23
|
+
| ✔ | `inOpen` BitSet mirror — *"O(1) replacement for linear heap.contains scans"* — in `GridTaskBuildSourceDistanceMap.js:103` and `GridTaskGenerateRoads.js:125` | `GridTaskConnectRooms.js:292` still calls `open.contains(...)` | The optimisation reached 2 of 3 grid searches |
|
|
24
|
+
| ✔ | `canvas2d_draw_linear_scale.js:46` uses `Math.floor`, with a comment: *"using ceil would place a final tick past position_1 with an extrapolated value"* | `canvas2dDrawWorldAxisLabels.js:44` still `Math.ceil`, commented only *"// number of marks"* | Over-extrapolated axis ticks |
|
|
25
|
+
| ✔ | `removeEntityWithEffect` (`engine/animation/AnimationUtils.js:179`) adds `SerializationMetadata.Transient` | `engine/animation/removeEntityWithMeshParticlesEffect.js` — no `SerializationMetadata` reference at all | Effect entities leak into saves |
|
|
26
|
+
| ✔ | `CellFilterGaussianBlur.js:99` centres taps at `(samples - 1) * 0.5`, commented *"the kernel spans ±(samples-1)/2 indices"* | `PointFitnessGaussianBlur.js:67` uses `(samples / 2)` | Off-centre by half a sample: for 5 taps the window runs −2.5…+1.5 instead of −2…+2 |
|
|
27
|
+
| ✔ | `array_quick_sort_by_lookup_uint.js:40` captures the pivot **value** before partitioning | `sort_decal_data.js:70,74` compares against the live pivot **index** through the array it is swapping | Partition invariant breaks once the pivot element moves |
|
|
28
|
+
| ✔ | `forward_plus/plugin/MaterialTransformer.js:105` — `result = source.clone()` | `sh3/gi/material/MaterialTransformer.js:311` — `result.clone();`, **return value discarded** | Mutates the caller's material |
|
|
29
|
+
| | BVH `balance_rotate` (Box2D-v3 SAH rotation) | `BVH2D` still on height-only AVL rotation | 2D tree builds worse-quality trees |
|
|
30
|
+
| | `Trail3DSystem.js:31-45` documents a head-seeding bug | `Trail2DSystem.js:157` still exhibits it under rotation/scale | Wrong trail head under transform |
|
|
31
|
+
| | `BinaryUint32BVH` scratch-stack seeding | `StaticR2Tree` fork carries an indexing bug the original lacks | 2D static tree mis-builds |
|
|
32
|
+
| | `bt_radial_loop_add` performs the self-link | one of its 3 copies omits it | Works only via an undocumented `loop_initialize` dependency |
|
|
33
|
+
| ✔ | Bounds-checked action-header read `in_buffer.position + ACTION_HEADER_BYTES > in_buffer_end`, guarding against "stale/out-of-bounds bytes — process crash on OOB" (`replication/Replicator.js:222` comment) | Written **three times in one method**: `:224`, `:256`, `:272`, each with its own paired payload-length check at `:229`, `:261`, `:277` | Security-relevant bounds check hand-repeated; a hardening change must land in all six |
|
|
34
|
+
|
|
35
|
+
**That is the argument for acting on this report.** The line-count savings are secondary; the
|
|
36
|
+
divergence risk is not. A useful heuristic fell out of the audit: *in a duplicated pair, the file
|
|
37
|
+
carrying the explanatory comment is the fixed one, and its twin still has the defect.* That heuristic
|
|
38
|
+
held in every re-verified row above.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 2. How this was found
|
|
43
|
+
|
|
44
|
+
Five layers, because no single technique finds all of it:
|
|
45
|
+
|
|
46
|
+
| Layer | Technique | Yield |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| 1 | Custom JS tokeniser + brace-matched function extraction; identifiers blinded; SHA-1 grouping | 110 token-identical clone groups; 79 more identical incl. member names |
|
|
49
|
+
| 2 | MinHash (64 hashes) + 16-band LSH over 6-gram shingles, Jaccard ≥ 0.70 | 241 near-duplicate function *pairs* (coincidentally equal to the final finding count — unrelated numbers); 23 whole-file pairs |
|
|
50
|
+
| 3 | 30 hand-written semantic patterns (inline lerp / length / clamp / hash-mix / binary search) | 129 inline-lerp, 78 inline-length3, 74 hash-mix, 30 binary-search hits |
|
|
51
|
+
| 4 | Import graph, orphan detection, basename + camel/snake collision sweep | 27 basename collisions, 598 files with no importer, 21 rename-alias pairs |
|
|
52
|
+
| 5 | 11 agents verifying by reading the code, one per domain + one cross-cutting | 241 findings; ~90 leads dismissed |
|
|
53
|
+
|
|
54
|
+
**Layers 1–2 are blind to GLSL inside template literals.** The single largest duplication in the
|
|
55
|
+
graphics domain — the octahedral impostor shader library — was found only in layer 5. Any future
|
|
56
|
+
sweep of this codebase must treat shader source as a first-class corpus.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 3. Findings — CRITICAL
|
|
61
|
+
|
|
62
|
+
| # | Concept | Sites | Evidence | Proposed common path | Effort |
|
|
63
|
+
|---|---|---|---|---|---|
|
|
64
|
+
| C1 | **Dynamic AABB tree (Box2D-style) implemented twice; the 2D fork has diverged.** Node allocator, free list, capacity growth, SAH insertion, rotation, refit, node swap, traversal. | `core/bvh2/bvh3/BVH.js` (class `BVH`) ⟷ `core/geom/2d/bvh/BVH2D.js` (class `BVH2D`) | **32 of BVH2D's 33 methods share a name with BVH's 37** (method-name census, this audit). Only `balance` differs (`balance_height`/`balance_rotate` in 3D). Column constants (`COLUMN_PARENT`, `NULL_NODE`, `ELEMENT_WORD_COUNT`…) are duplicated exports. 2D lacks `balance_rotate`, `allocate_linear`, `node_assign_children*`, the `data_buffer` serialisation accessors, and `size`. | Extract the dimension-independent tree over an abstract "AABB word count + surface-area metric" seam; keep 2D/3D AABB ops specialised. | **L** |
|
|
65
|
+
| C2 | **Octahedral impostor GLSL library copy-pasted.** `VecToSphereOct` + `VecToHemiSphereOct` + sampling helpers. | `VecToSphereOct` declared **10×** across **8 files**: `ImpostorShader{V0:71, DepthV0:59, NormalsV0:52, ViewportDepthV0:46, WireframeV0:31}`, `ImpostorShaderLitV0.js:65` **and** `:328`, `ImpostorShaderPerPixelV0.js:39` **and** `:178`, `sh3/gi/material/common.js:118` | **2 distinct bodies** (counts verified in this audit — see §7 for the correction). 9 impostor copies are byte-identical and use GLSL `sign()`, which returns **0.0** at exactly 0.0 and collapses the mapping on axis-aligned directions. `common.js` and the CPU bake reference `octahedral_direction_to_uv.js` use `sign_not_zero()` (±1). The two disagree precisely on the axis-aligned cases. | `engine/graphics/shaders/chunks/octahedral.js` as named string exports. The raw-loader path already works — `ImpostorShaderV1.js:10` imports a `.glsl` file. | **M** |
|
|
66
|
+
| C3 | **Production GI probe-depth GLSL copied into its own debug visualiser.** | `sh3/gi/material/common.js:76-298` ⟷ `sh3/lpv/depth/octahedral/v2/visualise.frag.glsl:26-408` ⟷ `.../shader/visualize.frag.js` | 220 of 320 lines verbatim, shared typo `quadBlendWieghts` included. A visualiser that has forked from the thing it visualises can silently lie. | Same shader-chunk module as C2. | **M** |
|
|
67
|
+
| C4 | **ActionLog record wire-format hand-parsed in 5 independent readers; written in 1.** Format exists only as a docblock comment. | writer `sim/SimActionExecutor.js:242-302`; readers `replication/Replicator.js:335` `#scan_record_in_scope`, `:376` `#copy_action_to`, `sim/RewindEngine.js` `#skip_record` + `#restore_prior_state`, `orchestrator/ServerAuthoritativeServer.js` `#read_historical` | Six coordinated edits for any format change, with zero compile-time coupling. | A single typed record cursor (`ActionRecordReader`) with `next()`/field accessors; all five readers drive it. Not a registry — a typed class. | **M** |
|
|
68
|
+
| C5 | **Two complete ECS animation runtimes over three.js `AnimationMixer`.** | `engine/ecs/systems/AnimationSystem.js:179` (+`ecs/animation/{Animation,AnimationClip,AnimationClipFlag}.js`) ⟷ `engine/graphics/ecs/animation/**` (`AnimationGraphSystem`, `AnimationGraph`) | `screenSpaceSize` and `shouldEntityBeAnimated` copy-pasted verbatim including the `areaInPixel < 32` threshold. **`AnimationClipFlag` exists twice, both assigning `1`** — `ClampWhenFinished` in `engine/ecs/animation/AnimationClipFlag.js` vs `Repeat` in `engine/graphics/ecs/animation/animator/AnimationClipFlag.js` (both verified). That byte is serialised: `engine/ecs/animation/AnimationClip.js:124` `buffer.writeUint8(this.flags)`. | Decide which runtime is canonical; at minimum give the two flag enums non-colliding values **before** more saves are written. | **L** |
|
|
69
|
+
| C6 | **No canonical `hash_combine`, and the hand-rolled mixes disagree.** ⚠ INCONSISTENT | `combine_hash` has **62** importers, yet **33** files still hand-roll `h*31+v` (74 hits project-wide) — both counts re-verified. Five sibling array-hash functions use **four different int32-truncation disciplines** (`\|0` per step / `>>>0` at end / never). | `uint32_array_hash` never truncates; its accumulator escapes int32 into a double — on exactly the workload `CSRGraph.hash()` feeds it. Separately, all five loop `i < length` while their JSDoc treats `length` as a **count**; `uint8_array_hash` contradicts itself between its head and body loops. | Make `combine_hash` the only mixer; fix the five array hashes to one truncation discipline and one `(array, offset, length)` contract. | **M** |
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 4. Findings — HIGH (selected; 51 total)
|
|
74
|
+
|
|
75
|
+
| # | Concept | Sites | Verdict | Proposed common path |
|
|
76
|
+
|---|---|---|---|---|
|
|
77
|
+
| H1 | Boolean and distance-returning AABB-vs-ray-segment slab tests whose **docs state they must agree** are independent copies of subtle NaN handling | `core/geom/3d/aabb/aabb3_intersects_ray_segment.js:35` ⟷ `aabb3_ray_segment_entry_distance.js:40` | UNJUSTIFIED | 45 lines character-identical; differ only in the last 4. Boolean delegates to the distance version. **S** |
|
|
78
|
+
| H2 | BVH traversal-order invariant duplicated and drifted ⚠ INCONSISTENT | 8 files carry the byte-identical comment *"write to stack in reverse order, so that fist child ends up being visited first"* (typo included). **2 match it** (`bvh_query_leaves_generic.js:65`, `bvh_query_user_data_generic.js:74`); **6 contradict it** (`bvh_collect_user_data.js:52`, `..._intersects_aabb.js:74`, `..._capsule.js:92`, `..._frustum.js:73`, `..._sphere.js:83`, `compute_tight_near_far_clipping_planes.js:182`) | UNJUSTIFIED | Specialised queries emit the same result **set** in the opposite **order** from the generic ones. Result order is observable and `determinism.spec.js` is a standing gate. Pick one order, fix the comment, add a test asserting generic and specialised agree. **M** |
|
|
79
|
+
| H3 | Solver impulse application written twice | `physics/constraint/solve_constraints.js:250` `apply_impulse` ⟷ `physics/solver/solve_contacts.js:401` `apply_impulse_to_body` | UNJUSTIFIED | Arithmetic identical statement-for-statement. **Signatures differ**: 10 params + module-scope `scratch_inertia` vs 11 params with scratch passed in (verified — see §7). Keep the caller-provided form; the module-scope one shares state between call sites. **S**, determinism-safe if copied verbatim |
|
|
80
|
+
| H4 | SAT minimum-overlap computed three ways, one diverging ⚠ INCONSISTENT | `narrowphase/box_box_manifold.js:135` `(rA+rB)-dist`; `box_triangle_contact.js:209` `min(bmax-tmin, tmax-bmin)`; `convex_convex_manifold.js:261` | UNJUSTIFIED | `convex_convex_manifold` uses interval-**intersection length** where the others use **push-out distance**. These differ under projection containment (a thin decomposed piece inside a fat one), and SAT takes the minimum — so it likely under-reports depth. **Needs a correctness decision, not a merge.** **M** |
|
|
81
|
+
| H5 | Point-in-closed-surface classifier (BVH build + 3-ray parity vote) copy-pasted | `core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js:19,33,81,127` ⟷ `core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js:12,29,78` | UNJUSTIFIED | `build_surface_bvh` token-identical (435 tokens), including the magic ray directions. Promote to `core/geom/3d/query/point_in_closed_surface.js`. **M** |
|
|
82
|
+
| H6 | Radial-cycle splice (half-edge face-ring invariant) written 3×, two behaviourally different ⚠ INCONSISTENT | `bt_radial_loop_add.js:9` (exported, canonical) ⟷ `face/bt_face_poke.js:130` `_link_loop_to_edge_local` ⟷ `bt_mesh_from_indexed_geometry.js` `link_loop_to_edge` | UNJUSTIFIED | Opposite insertion side; one copy omits the self-link. One copy's comment claims the canonical function "is not exported" — **it is**. **S** |
|
|
83
|
+
| H7 | `StaticR2Tree` is a 2D fork of `BinaryUint32BVH` | `core/bvh2/binary/2/BinaryUint32BVH.js:336,411,426` ⟷ `core/geom/2d/r-tree/StaticR2Tree.js:210,296,313` | UNJUSTIFIED | `build` token-identical (289 tokens). Fork carries a bounds-copy bug (`array_copy(...,6)` on a 4-float 2D box) documented in an in-tree comment. **M** |
|
|
84
|
+
| H8 | Relative-epsilon quadratic solver written 3×, deliberately bypassing `solveQuadratic` | `core/math/spline/spline3_hermite_bounds.js:22`, `spline3_hermite_bounds_t.js:26`, `spline3_bezier_bounds.js:20` vs `core/math/solveQuadratic.js:15` | UNJUSTIFIED | The bypass is *reasonable* — `solveQuadratic` still uses an absolute epsilon — but it makes 4 places to fix, with the justifying comment copy-pasted verbatim. Fix `solveQuadratic` to relative epsilon, then collapse. **M** |
|
|
85
|
+
| H9 | `Uint32Heap4` is a whole-file copy of `Uint32Heap` | `core/collection/heap/Uint32Heap.js:56` ⟷ `Uint32Heap4.js:59` | UNJUSTIFIED | 194/208 lines identical; only 4 of 22 members carry the arity difference. **M** |
|
|
86
|
+
| H10 | Triangle-vertex fetch from a normalised/implicitly-indexed buffer copy-pasted 3×, comment-for-comment | `geometry/buffered/query/bvh32_geometry_{nearest.js:151, raycast.js:59, overlap_clipping_volume.js}` | UNJUSTIFIED | ~45 lines each: index resolve → 3 addresses → 9 reads → 9 denormalisations. **S** |
|
|
87
|
+
| H11 | Nearest-point-on-mesh implemented twice against two BVH layouts | `bvh32_geometry_nearest.js:37-247` ⟷ `query_bvh_geometry_nearest.js:35-208` | UNJUSTIFIED | Leaf bodies token-identical. **M** |
|
|
88
|
+
| H12 | Material-texture coalescing loop duplicated — **and the extracted helper already exists, unused by both** | `material/manager/compilers/CoalesceTextures.js:25-69` ⟷ `asset/loaders/material/StaticMaterialCache.js:48-89`; helper at `asset/loaders/material/traverseMaterialTextures.js:9` | UNJUSTIFIED | 40 byte-identical lines. **S** |
|
|
89
|
+
| H13 | Shadow-ray "segment clear of occluders" test written 3× | `sound/simulation/probe/probe_edge_visible.js:20`, `probe_refine_connectivity.js:168` `segment_clear`, `AcousticProbeField.js:328` | UNJUSTIFIED | `probe_edge_visible`'s own doc **falsely claims** it is the single shared test. **S** |
|
|
90
|
+
| H14 | Listener resolution + `sopra.update()` duplicated in two ECS systems sharing **one** `SopraEngine` | `sound/ecs/emitter/SoundEmitterSystem.js:137-158` ⟷ `sound/ecs/audio/AudioEmitterSystem.js:246-315` | UNJUSTIFIED | Co-registering both (the documented design intent) **double-ticks the shared engine**. This is a bug, not hygiene. **M** |
|
|
91
|
+
| H15 | Container child-hash fold copy-pasted into 4 subclasses; base owns `children` but has **no `hash()`** ⚠ INCONSISTENT | `sopra/definition/clip/ContainerAudioClip.js:80` `equals` (no `hash`); `BlendContainerAudioClip.js:108` `equals` / `:126` `hash` | UNJUSTIFIED | Verified: `BlendContainerAudioClip.equals()` compares `blends`; `hash()` does **not** fold them. Two objects differing only in `blends` compare unequal but hash equal. **S** |
|
|
92
|
+
| H16 | Collocated `v3_grid_advect_*` family (5 files, ~555 LOC) shadows the MAC family and has **zero importers** | `v3_grid_advect_sl_velocity.js`, `v3_grid_apply_advection_forward.js`, `v3_grid_apply_scalar_advection.js`, `v3_grid_advect_maccormack_{scalar,velocity}.js` | UNJUSTIFIED | Full shadow copy of SL/MacCormack/limiter/solid handling; copies have already drifted. **meep is a library, so this is not a deletion recommendation** — collapse the internal redundancy. **M** |
|
|
93
|
+
| H17 | `AbstractContextSystem` is the engine's own typed answer to per-entity link/unlink — adopted by 7 systems, hand-rolled by 17 more in 3 incompatible conventions | e.g. `ViewportPositionSystem` subscribes **six** listeners and unsubscribes **five** | UNJUSTIFIED | The blocker is genuine: the existing base dispatches through `arguments`, i.e. exactly the "magic" the house style rejects. Recommendation is **typed arity-specific bases**, not spreading the current one. **L** |
|
|
94
|
+
| H18 | Transport adapters copy-paste `getStats()` (×6) and the disconnect latch (×3) instead of using the base | `transport/{Loopback,WebSocket,WebRTCDataChannel,Simulated,WebTransport}Transport.js` | UNJUSTIFIED | `WebTransportTransport` is **missing** the latch the other three independently invented. **S** |
|
|
95
|
+
| H19 | `send_fragmented` / `resend_fragment_chunk` duplicate the header write with **two different `total_chunks` formulas** ⚠ INCONSISTENT | `network/transport/fragments/fragment_send.js` | UNJUSTIFIED | **S** |
|
|
96
|
+
| H20 | Trail 2D/3D whole-file fork | `ecs/trail2d/Trail2DSystem.js` (274 ln) ⟷ `ecs/trail3d/Trail3DSystem.js` (280 ln); `Trail2D.js:210,298` ⟷ `Trail3D.js:275,417` | UNJUSTIFIED | ~85% shared; the 3D copy documents a head-seeding bug the 2D copy still has. **M** |
|
|
97
|
+
|
|
98
|
+
*(Remaining HIGH rows — SH sign-convention divergence across 4 evaluators, voxel-impostor GLSL ×5, CSR-builder absence, `AnimationClipFlag`, quicksort family, Robin-Hood map machinery, LPG/gi fork, grid-Dijkstra ×3, `ImageView`/`VideoView`, `GroupView` link bug, `NumericInterval` invariant ×3 — are in the per-domain files listed in §8.)*
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 5. Promotion opportunities — primitives that should exist and don't
|
|
103
|
+
|
|
104
|
+
These are the cheapest wins: additive, no behaviour change, and each already has ≥2 consumers
|
|
105
|
+
re-deriving it.
|
|
106
|
+
|
|
107
|
+
| # | Missing primitive | Proposed home | Consumers re-deriving it today |
|
|
108
|
+
|---|---|---|---|
|
|
109
|
+
| P1 | **Typed-array growth / capacity doubling** | `core/collection/array/typed/typed_array_grow.js` | **22 independent implementations, 5 different growth policies, no core helper at all.** Heaps, CSR graphs, BVH, particle pools, trail buffers, action logs. Single signature, no design choices — the cleanest promotion in the audit. |
|
|
110
|
+
| P2 | **`hash_combine` as the only mixer** | `core/math/hash/` (exists; enforce it) | 33 files hand-roll `h*31+v`; 5 array hashes disagree on truncation (see C6) |
|
|
111
|
+
| P3 | **Edge-list → CSR builder** | `core/graph/csr/` | `core/graph/csr` ships *consumers* but no *builder*; `sound/simulation/probe/bakeVisibility.js:109` and `probe_visibility_augment.js:50` each wrote one. This single gap spawned 4 findings. |
|
|
112
|
+
| P4 | **`v2_rotate(out, x, y, radians)`** | `core/geom/vec2/` | The 2D rotate-a-local-offset formula is inlined **8×** in `generation/`; `core/geom/vec2/` has no `v2_rotate` |
|
|
113
|
+
| P5 | **`tri3_closest_point_barycentric` world-point variant** | `core/geom/3d/triangle/` | Returns barycentrics; **every caller** immediately writes the same reconstruction arithmetic. (Count reported inconsistently as 12 vs 16 across physics/core/graphics — enumerate before acting.) |
|
|
114
|
+
| P6 | **`line3_segment_segment_closest_points` point variant** | `core/geom/3d/line/` | Returns `(s,t)`; all 4 physics callers immediately lerp both segments |
|
|
115
|
+
| P7 | **`quat3_nlerp`** | `core/geom/3d/quaternion/` | Genuinely absent; inlined 3× in network adapters — one site comments *"use the static helper variant if available"* |
|
|
116
|
+
| P8 | **GLSL chunk module** | `engine/graphics/shaders/chunks/` | Octahedral, SH, packing, frame primitives. Retires C2, C3 and ~4 more findings — on the order of **1,400 lines** of copied shader source (reviewer estimate, not counted by tooling, since layers 1–2 cannot see GLSL). `ShaderChunks.js` already proves the pattern; the clouds feature uses it correctly. |
|
|
117
|
+
| P9 | **`FrameBufferRing`** (per-frame `BinaryBuffer` ring) | `core/collection/` | `network/sim/ActionLog.js:49` ⟷ `network/state/InputRing.js:37` — constructors 97% identical, `buffer_for`/`write_end_for` token-identical; only the framing policy differs |
|
|
118
|
+
| P10 | **Binary codec for engine value types** | `core/geom/*/serialization/` | `Transform` has **5** hand-maintained encodings, `Vector3` ~14, `Quaternion` 6, coupled by nothing. `Vector3.toBinaryBuffer` is `@deprecated` in favour of *nothing*, so 9 adapters regressed to inline `writeFloat64(v.x/y/z)`. The one primitive that does exist (`v3_binary_equality_encode`) is reused by 3 adapters — proving the shape works. |
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 6. Leads ruled out — and three false-positive classes
|
|
123
|
+
|
|
124
|
+
Roughly 90 mechanical leads were checked and rejected. Three classes would have produced confident,
|
|
125
|
+
wrong rows, and are documented so the next sweep skips them:
|
|
126
|
+
|
|
127
|
+
**(a) Re-export shims.** The earlier core→engine decoupling left deliberate 2-line shims. Verified:
|
|
128
|
+
`engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.js`,
|
|
129
|
+
`engine/graphics/render/forward_plus/read_frustum_corner.js`,
|
|
130
|
+
`engine/graphics/texture/isImageBitmap.js`, `engine/network/convertPathToURL.js`,
|
|
131
|
+
`engine/graphics/particles/particular/engine/parameter/ParameterLookupTable{,Flags}.js`.
|
|
132
|
+
*Rule: engine-side copy ≤ 3 lines ⇒ shim.*
|
|
133
|
+
|
|
134
|
+
**(b) `@deprecated` rename aliases.** A camelCase→snake_case migration (plus `vert`→`vertex`,
|
|
135
|
+
`quat`→`quat3`, `shape`→`shape3`, `frustum`→`frustum3`) left ~21 old-name files, each
|
|
136
|
+
`import X` + `@deprecated` + `export const oldName = X`, kept because **meep is a library and old
|
|
137
|
+
names are public surface**.
|
|
138
|
+
|
|
139
|
+
**(c) Same name, different function.** `core/math/gaussian(sigma, distance)` (un-normalised bell) vs
|
|
140
|
+
`engine/graphics/texture/sampler/filter/gaussian(x)` (`sqrt(2/π)·exp(-2x²)`, with `.support = 1.25`)
|
|
141
|
+
are genuinely different maths. A name hazard, not duplication — do **not** merge.
|
|
142
|
+
|
|
143
|
+
Other notable rejections, with reasons:
|
|
144
|
+
|
|
145
|
+
- **`TwoBoneInverseKinematicsSolver` vs `two_joint_ik` are not rivals.** This audit seeded that lead
|
|
146
|
+
and it was wrong: `engine/ecs/ik/TwoBoneInverseKinematicsSolver.js:11` imports `two_joint_ik` and
|
|
147
|
+
calls it at `:157`. It is a wrapper. *(The real duplication in those files is a ~75-line
|
|
148
|
+
terrain-probe prologue shared with `OneBoneSurfaceAlignmentSolver` — reported separately.)*
|
|
149
|
+
- **Three `AnimationClip` classes are a naming problem, not code duplication** — three genuinely
|
|
150
|
+
different data models sharing a name.
|
|
151
|
+
- **`node-based` vs `particular` particles**: an unfinished parallel system plus an export-name
|
|
152
|
+
collision, not a fork. `TubeX`/`RibbonX`: a genuine rewrite.
|
|
153
|
+
- **Shape-boilerplate is deliberate.** Per-class `from()`/`hash()`/`equals()`/`fromJSON()` and the
|
|
154
|
+
sopra `serialize`/`deserialize` adapters were dismissed under the *typed over magic* rule. The
|
|
155
|
+
three sopra type-tag `switch` dispatchers are JUSTIFIED — core's `abstractJSONDeserializer` is
|
|
156
|
+
exactly the string-keyed registry the house style rejects.
|
|
157
|
+
- **2D/3D and row/column-major scalar pairs** (`v2_*`/`v3_*`, `m3_cm_*`/`m3_rm_*`, `aabb2_*`/`aabb3_*`)
|
|
158
|
+
are justified specialisation.
|
|
159
|
+
- **`IndexedFloatMin/MaxHeap`**: documented monomorphism choice.
|
|
160
|
+
- **`PosedShape3D`'s inlined quaternion math**: measured, documented hot-loop carve-out.
|
|
161
|
+
- **The 78 `inline_length3` / 129 `inline_lerp` pattern hits**: mostly misclassified dot products or
|
|
162
|
+
genuine per-triangle inner loops. Pattern 3's `binary_search_inline` was ~all false positives
|
|
163
|
+
(quicksort pivot arithmetic).
|
|
164
|
+
- **`end_in_solid` triplication in the fluid solver**: carries a *measured* 8.6× perf contract.
|
|
165
|
+
- **three.js texture-format translation**: written as one `switch` plus composing wrappers, it has
|
|
166
|
+
**no drift** — the useful counter-example to every family written as N parallel sibling files.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 7. Corrections applied to agent findings
|
|
171
|
+
|
|
172
|
+
Verified against the source; the report uses the corrected version:
|
|
173
|
+
|
|
174
|
+
| Claim as reported | Correction |
|
|
175
|
+
|---|---|
|
|
176
|
+
| `VecToSphereOct` "declared **17 times** in **four** mutually incompatible conventions" | **10 declarations across 8 files, 2 distinct bodies.** (11 of the 21 occurrences are call sites; 2 files declare it twice, once per shader stage.) The substantive hazard — GPU copies use `sign()`, reference uses `sign_not_zero()` — is real and stated in C2. |
|
|
177
|
+
| `apply_impulse` / `apply_impulse_to_body` "line-for-line identical" | Arithmetic is identical; **signatures are not** (10 params + module-scope scratch vs 11 params with scratch passed in). This changes the recommendation — keep the caller-provided form. |
|
|
178
|
+
| BVH2D overlap: "521 of 576 code lines" (domain B) vs "~1000 lines" (domain A) | Three methods gave three numbers. Report uses the reproducible measure: **32 of 33 methods share a name**, overlap ≈ 90% of BVH2D. |
|
|
179
|
+
| "Six files carry the comment while pushing `child1` first" | Right count, inverted description. Precisely: 8 files carry it, **2 match, 6 contradict** — the 6 push `child1` first in source order, which makes `child2` visited first. |
|
|
180
|
+
| "Recommend **deletion** of `BinaryObjectSerializationAdapter2.js`" (493 ln, zero importers) | Downgraded to **removal candidate, owner's call** — collides with the standing rule that unreferenced exports in meep are public surface. Same for the "fully dead" `engine/sound/material/**`. |
|
|
181
|
+
| `removeEntityWithEffect` cited as though it were its own file | **No such file exists.** The function is `engine/animation/AnimationUtils.js:168`, and the `SerializationMetadata.Transient` call is at `:179`. The finding is correct; the citation would have failed a spot-check. |
|
|
182
|
+
| `PointFitnessGaussianBlur` "has the centring bug" | Correct, and sharper than stated: `CellFilterGaussianBlur.js:99` uses `(samples - 1) * 0.5`, the twin at `PointFitnessGaussianBlur.js:67` uses `(samples / 2)`. Note the two are 2D vs 3D and share no code — this is **re-derivation**, not copy-paste, so it would never have surfaced from clone detection alone. |
|
|
183
|
+
|
|
184
|
+
**Error rate of the source material.** Eight §1 rows plus the C6 counts were re-verified:
|
|
185
|
+
**every one was substantively true**, and the two independently-verified counts (`combine_hash`
|
|
186
|
+
62 importers, 33 hand-rolled sites) were exact. But **2 of 8 carried a wrong or unciteable file
|
|
187
|
+
reference**, and 3 of the sharpest claims elsewhere (`VecToSphereOct` counts, `apply_impulse`
|
|
188
|
+
"line-for-line", the traversal-order direction) were overstated or inverted.
|
|
189
|
+
|
|
190
|
+
The pattern is consistent: **the reviewers were reliable about *what* is duplicated and unreliable
|
|
191
|
+
about *where* and *how much*.** Trust the per-domain files for the finding; spot-check the citation
|
|
192
|
+
before acting.
|
|
193
|
+
|
|
194
|
+
Two additional items found by this audit directly, with no agent assigned:
|
|
195
|
+
|
|
196
|
+
- **Two mesh-simplification drivers.** `Quadric3` is correctly shared, but the driver is not: the
|
|
197
|
+
`TopoMesh`/`tm_*` stack (`simplifyTopoMesh.js` 263 ln — **no importer**; `simplifyTopoMesh2.js`
|
|
198
|
+
119 ln — imported **only by a prototype harness**; `decimate_edge_collapse_snap.js` 272 ln;
|
|
199
|
+
`edge_collapse_quadratic.js` 71 ln) parallels the live `bt_*` stack
|
|
200
|
+
(`bt_mesh_simplify_by_error.js` 590 ln, used by `engine/navigation/mesh/build/navmesh_build_topology.js:29`).
|
|
201
|
+
The two quadric *accumulation* loops walk different mesh representations, so **that** part is
|
|
202
|
+
justified; the driver is not.
|
|
203
|
+
- **`core/geom/3d/sphere/harmonics/compute_legendre_polynomial.js` is a 0-byte file**, colliding by
|
|
204
|
+
name with the live `core/math/compute_legendre_polynomial.js` (50 ln). Cruft, not duplication.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## 8. Where the detail lives
|
|
209
|
+
|
|
210
|
+
241 verified findings with full evidence, dismissed-lead lists and per-domain notes, in
|
|
211
|
+
`src/DUPLICATION_AUDIT_2026_08_07/`:
|
|
212
|
+
|
|
213
|
+
| Domain | Findings | File |
|
|
214
|
+
|---|---|---|
|
|
215
|
+
| `core/geom` + `core/math` | 30 | `A_core_math_geom.md` |
|
|
216
|
+
| `core/` data structures, binary, graph, cache, parser, colour | 21 | `B_core_data.md` |
|
|
217
|
+
| `engine/graphics` render / material / texture / geometry | 28 | `C_gfx_render.md` |
|
|
218
|
+
| `engine/graphics` ecs / particles / trail / impostors / sh3 | 29 | `D_gfx_features.md` |
|
|
219
|
+
| `engine/physics` | 22 | `E_physics.md` |
|
|
220
|
+
| `engine/sound` (legacy + sopra + simulation) | 23 | `F_sound.md` |
|
|
221
|
+
| `engine/network` + `engine/save` + `ecs/storage` | 25 | `G_net_save.md` |
|
|
222
|
+
| `engine/` ecs / intelligence / animation / input / control / asset | 29 | `H_engine_misc.md` |
|
|
223
|
+
| `generation/` + `view/` + `editor/` | 17 | `I_generation_view.md` |
|
|
224
|
+
| Cross-cutting concerns | 17 | `K_crosscutting.md` |
|
|
225
|
+
|
|
226
|
+
Also `00_core_reuse_surface.md` — a 598-row inventory of what `core/` already provides, built as the
|
|
227
|
+
reference against which re-derivation was judged. Useful independently of this audit.
|
|
228
|
+
|
|
229
|
+
### Confidence
|
|
230
|
+
|
|
231
|
+
Severity split: 6 CRITICAL, 51 HIGH, 107 MEDIUM, 71 LOW, 2 explicit PROMOTION (plus 24 rows carrying
|
|
232
|
+
a PROMOTION verdict inside other tiers). 158 rows are verdict `UNJUSTIFIED`, 11 explicitly
|
|
233
|
+
`JUSTIFIED` (kept deliberately, so the reasoning isn't re-litigated later).
|
|
234
|
+
|
|
235
|
+
Every row was produced by an agent that opened the files. Everything in §1, §3 and §7 of *this*
|
|
236
|
+
document was additionally re-read during the adversarial pass. The MEDIUM and LOW tiers in the
|
|
237
|
+
per-domain files have **not** been independently re-verified — treat the specific line numbers there
|
|
238
|
+
as needing a spot-check before acting, and see §7 for the error rate that pass actually found.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## 9. Recommended order of work
|
|
243
|
+
|
|
244
|
+
1. **C6 + P2 (hash consistency)** and **H2 (traversal order)** — correctness hazards under a standing
|
|
245
|
+
determinism gate, both cheap.
|
|
246
|
+
2. **The fix-divergence table in §1** — each row is a known bug sitting in a known file. Mostly **S**.
|
|
247
|
+
3. **P1, P3, P4, P7 (missing primitives)** — additive, no behaviour change, retire many findings.
|
|
248
|
+
4. **P8 (GLSL chunk module)** — highest line-count leverage: ~1,400 lines, retires C2 + C3.
|
|
249
|
+
5. **C5 flag collision** — do this *before* more saves are written.
|
|
250
|
+
6. **C1 (BVH/BVH2D)** and **H17 (ECS lifecycle bases)** — largest and riskiest; schedule deliberately.
|
|
251
|
+
|
|
252
|
+
**Two items need a decision, not a refactor:** H4 (SAT overlap semantics — which definition is
|
|
253
|
+
correct?) and the C2 `sign`/`sign_not_zero` convention (unifying changes rendered output and needs a
|
|
254
|
+
bake-vs-shader A/B first).
|