@woosh/meep-engine 2.155.0 → 2.157.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -4
- package/build/bundle-worker-image-decoder.js +1 -1
- package/build/bundle-worker-terrain.js +1 -1
- package/editor/view/ecs/ComponentControlView.d.ts +0 -9
- package/editor/view/ecs/ComponentControlView.js +2 -98
- package/editor/view/ecs/components/common/AutoCanvasView.js +100 -53
- package/editor/view/ecs/components/common/TextController.js +59 -0
- package/editor/view/node-graph/NodeGraphCamera.js +90 -0
- package/editor/view/node-graph/NodeGraphEditorView.js +121 -22
- package/editor/view/node-graph/NodeGraphSelection.js +89 -0
- package/editor/view/node-graph/NodeGraphView.js +669 -453
- package/editor/view/node-graph/NodeView.js +211 -135
- package/editor/view/node-graph/actions/ConnectionCreateAction.js +53 -0
- package/editor/view/node-graph/actions/ConnectionDeleteAction.js +36 -0
- package/editor/view/node-graph/actions/NodeDeleteAction.js +88 -0
- package/editor/view/node-graph/actions/NodeParameterSetAction.js +52 -0
- package/editor/view/node-graph/actions/NodesMoveAction.js +41 -0
- package/editor/view/node-graph/actions/SelectionSetAction.js +60 -0
- package/editor/view/node-graph/connection_wire_geometry.js +107 -0
- package/package.json +1 -1
- package/samples/generation/SampleGenerator0.js +8 -1
- package/src/core/binary/32BitEncoder.js +1 -1
- package/src/core/binary/reinterpret_float32_as_uint32.d.ts +7 -0
- package/src/core/binary/reinterpret_float32_as_uint32.d.ts.map +1 -0
- package/src/core/binary/reinterpret_float32_as_uint32.js +13 -0
- package/src/core/binary/reinterpret_uint32_as_float32.d.ts +7 -0
- package/src/core/binary/reinterpret_uint32_as_float32.d.ts.map +1 -0
- package/src/core/binary/reinterpret_uint32_as_float32.js +14 -0
- package/src/core/binary/to_half_float_uint16.js +3 -3
- package/src/core/bvh2/bvh3/ebvh_build_for_geometry_incremental.d.ts.map +1 -1
- package/src/core/bvh2/bvh3/ebvh_build_for_geometry_incremental.js +1 -3
- package/src/core/bvh2/bvh3/ebvh_build_hierarchy_radix.d.ts.map +1 -1
- package/src/core/bvh2/bvh3/ebvh_build_hierarchy_radix.js +275 -253
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_sphere.d.ts +12 -0
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_sphere.d.ts.map +1 -0
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_sphere.js +92 -0
- package/src/core/bvh8/BVH8.d.ts +127 -0
- package/src/core/bvh8/BVH8.d.ts.map +1 -0
- package/src/core/bvh8/BVH8.js +436 -0
- package/src/core/bvh8/NOTES.md +63 -0
- package/src/core/bvh8/build/BVH8Converter.d.ts +59 -0
- package/src/core/bvh8/build/BVH8Converter.d.ts.map +1 -0
- package/src/core/bvh8/build/BVH8Converter.js +588 -0
- package/src/core/bvh8/build/NodeProxy.d.ts +66 -0
- package/src/core/bvh8/build/NodeProxy.d.ts.map +1 -0
- package/src/core/bvh8/build/NodeProxy.js +308 -0
- package/src/core/bvh8/build/TriangleCluster.d.ts +29 -0
- package/src/core/bvh8/build/TriangleCluster.d.ts.map +1 -0
- package/src/core/bvh8/build/TriangleCluster.js +123 -0
- package/src/core/bvh8/build/aabb3_compute_merge_cost.d.ts +8 -0
- package/src/core/bvh8/build/aabb3_compute_merge_cost.d.ts.map +1 -0
- package/src/core/bvh8/build/aabb3_compute_merge_cost.js +29 -0
- package/src/core/bvh8/build/aabb3_from_triangle_by_index.d.ts +10 -0
- package/src/core/bvh8/build/aabb3_from_triangle_by_index.d.ts.map +1 -0
- package/src/core/bvh8/build/aabb3_from_triangle_by_index.js +18 -0
- package/src/core/bvh8/build/bvh8_build_for_geometry.d.ts +10 -0
- package/src/core/bvh8/build/bvh8_build_for_geometry.d.ts.map +1 -0
- package/src/core/bvh8/build/bvh8_build_for_geometry.js +303 -0
- package/src/core/bvh8/build/bvh8_from_proxy.d.ts +9 -0
- package/src/core/bvh8/build/bvh8_from_proxy.d.ts.map +1 -0
- package/src/core/bvh8/build/bvh8_from_proxy.js +256 -0
- package/src/core/bvh8/build/byte.d.ts +7 -0
- package/src/core/bvh8/build/byte.d.ts.map +1 -0
- package/src/core/bvh8/build/byte.js +10 -0
- package/src/core/bvh8/build/encode_bounds_e.d.ts +9 -0
- package/src/core/bvh8/build/encode_bounds_e.d.ts.map +1 -0
- package/src/core/bvh8/build/encode_bounds_e.js +12 -0
- package/src/core/bvh8/bvh8_convert_to_dot.d.ts +11 -0
- package/src/core/bvh8/bvh8_convert_to_dot.d.ts.map +1 -0
- package/src/core/bvh8/bvh8_convert_to_dot.js +133 -0
- package/src/core/bvh8/bvh8_count_primitives.d.ts +22 -0
- package/src/core/bvh8/bvh8_count_primitives.d.ts.map +1 -0
- package/src/core/bvh8/bvh8_count_primitives.js +98 -0
- package/src/core/bvh8/bvh8_geometry_validate.d.ts +16 -0
- package/src/core/bvh8/bvh8_geometry_validate.d.ts.map +1 -0
- package/src/core/bvh8/bvh8_geometry_validate.js +149 -0
- package/src/core/bvh8/bvh8_geometry_validate_indirect.d.ts +16 -0
- package/src/core/bvh8/bvh8_geometry_validate_indirect.d.ts.map +1 -0
- package/src/core/bvh8/bvh8_geometry_validate_indirect.js +177 -0
- package/src/core/bvh8/bvh8_get_node_bounds.d.ts +9 -0
- package/src/core/bvh8/bvh8_get_node_bounds.d.ts.map +1 -0
- package/src/core/bvh8/bvh8_get_node_bounds.js +35 -0
- package/src/core/bvh8/bvh8_get_node_child_bounds.d.ts +10 -0
- package/src/core/bvh8/bvh8_get_node_child_bounds.d.ts.map +1 -0
- package/src/core/bvh8/bvh8_get_node_child_bounds.js +53 -0
- package/src/core/bvh8/bvh8_node_child_surface_area.d.ts +9 -0
- package/src/core/bvh8/bvh8_node_child_surface_area.d.ts.map +1 -0
- package/src/core/bvh8/bvh8_node_child_surface_area.js +18 -0
- package/src/core/bvh8/bvh8_node_count_triangles.d.ts +8 -0
- package/src/core/bvh8/bvh8_node_count_triangles.d.ts.map +1 -0
- package/src/core/bvh8/bvh8_node_count_triangles.js +28 -0
- package/src/core/bvh8/bvh8_quality.d.ts +8 -0
- package/src/core/bvh8/bvh8_quality.d.ts.map +1 -0
- package/src/core/bvh8/bvh8_quality.js +73 -0
- package/src/core/bvh8/bvh8_validate_structure.d.ts +15 -0
- package/src/core/bvh8/bvh8_validate_structure.d.ts.map +1 -0
- package/src/core/bvh8/bvh8_validate_structure.js +87 -0
- package/src/core/cache/Cache.d.ts.map +1 -1
- package/src/core/cache/Cache.js +7 -0
- package/src/core/cache/FrequencySketch.d.ts.map +1 -1
- package/src/core/cache/FrequencySketch.js +8 -4
- package/src/core/clipboard/obtainClipBoard.d.ts +6 -0
- package/src/core/clipboard/obtainClipBoard.d.ts.map +1 -0
- package/src/core/clipboard/obtainClipBoard.js +29 -0
- package/src/core/clipboard/safeClipboardReadText.d.ts +6 -0
- package/src/core/clipboard/safeClipboardReadText.d.ts.map +1 -0
- package/src/core/clipboard/safeClipboardReadText.js +55 -0
- package/src/core/clipboard/safeClipboardWriteText.d.ts +8 -0
- package/src/core/clipboard/safeClipboardWriteText.d.ts.map +1 -0
- package/src/core/clipboard/safeClipboardWriteText.js +23 -0
- package/src/core/collection/Uint32MinHeap.d.ts +56 -0
- package/src/core/collection/Uint32MinHeap.d.ts.map +1 -0
- package/src/core/collection/Uint32MinHeap.js +109 -0
- package/src/core/collection/array/array_quick_sort_by_lookup_map.js +1 -1
- package/src/core/collection/array/array_set_diff_sorting.d.ts.map +1 -1
- package/src/core/collection/array/array_set_diff_sorting.js +4 -1
- package/src/core/collection/array/array_shuffle.d.ts.map +1 -1
- package/src/core/collection/array/array_shuffle.js +30 -27
- package/src/core/collection/array/binarySearchLowIndex.d.ts.map +1 -1
- package/src/core/collection/array/binarySearchLowIndex.js +4 -3
- package/src/core/collection/array/typed/array_buffer_hash.js +1 -1
- package/src/core/collection/array/typed/is_typed_array_equals.d.ts.map +1 -1
- package/src/core/collection/array/typed/is_typed_array_equals.js +12 -2
- package/src/core/collection/heap/BinaryHeap.d.ts.map +1 -1
- package/src/core/collection/heap/BinaryHeap.js +12 -2
- package/src/core/collection/list/FilteredListProjection.js +1 -1
- package/src/core/collection/queue/Deque.d.ts.map +1 -1
- package/src/core/collection/queue/Deque.js +10 -8
- package/src/core/collection/table/RowFirstTable.d.ts.map +1 -1
- package/src/core/collection/table/RowFirstTable.js +4 -2
- package/src/core/collection/table/RowFirstTableSpec.js +2 -2
- package/src/{engine/physics/island → core/collection/union-find}/union_find.d.ts +8 -5
- package/src/core/collection/union-find/union_find.d.ts.map +1 -0
- package/src/{engine/physics/island → core/collection/union-find}/union_find.js +8 -5
- package/src/core/color/operations/color_lerp.d.ts.map +1 -1
- package/src/core/color/operations/color_lerp.js +10 -3
- package/src/core/color/rgb2uint32.js +1 -1
- package/src/core/color/rgbe9995_to_rgb.js +1 -1
- package/src/core/dom/isImageBitmap.d.ts +7 -0
- package/src/core/dom/isImageBitmap.d.ts.map +1 -0
- package/src/core/dom/isImageBitmap.js +12 -0
- package/src/core/function/frameThrottle.d.ts +8 -0
- package/src/core/function/frameThrottle.d.ts.map +1 -0
- package/src/core/function/frameThrottle.js +23 -0
- package/src/core/function/objectsEqual.d.ts.map +1 -1
- package/src/core/function/objectsEqual.js +2 -1
- package/src/core/geom/2d/aabb/AABB2.d.ts.map +1 -1
- package/src/core/geom/2d/aabb/AABB2.js +12 -11
- package/src/core/geom/2d/convex-hull/convex_hull_jarvis_2d.d.ts.map +1 -1
- package/src/core/geom/2d/convex-hull/convex_hull_jarvis_2d.js +30 -4
- package/src/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.d.ts.map +1 -1
- package/src/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +6 -2
- package/src/core/geom/2d/hash-grid/SpatialHashGrid.d.ts.map +1 -1
- package/src/core/geom/2d/hash-grid/SpatialHashGrid.js +388 -386
- package/src/core/geom/2d/hash-grid/shg_query_elements_line.d.ts.map +1 -1
- package/src/core/geom/2d/hash-grid/shg_query_elements_line.js +8 -3
- package/src/{engine/physics/narrowphase/clip_against_axis_uv.d.ts → core/geom/2d/polygon/polygon2_clip_axis_halfplane.d.ts} +3 -3
- package/src/core/geom/2d/polygon/polygon2_clip_axis_halfplane.d.ts.map +1 -0
- package/src/{engine/physics/narrowphase/clip_against_axis_uv.js → core/geom/2d/polygon/polygon2_clip_axis_halfplane.js} +51 -51
- package/src/core/geom/2d/quad-tree/QuadTreeDatum.d.ts.map +1 -1
- package/src/core/geom/2d/quad-tree/QuadTreeDatum.js +9 -1
- package/src/core/geom/2d/quad-tree/qt_query_data_nearest_to_point.d.ts +3 -1
- package/src/core/geom/2d/quad-tree/qt_query_data_nearest_to_point.d.ts.map +1 -1
- package/src/core/geom/2d/quad-tree/qt_query_data_nearest_to_point.js +3 -1
- package/src/core/geom/2d/quad-tree-binary/QuadTree.js +714 -714
- package/src/core/geom/2d/r-tree/StaticR2Tree.d.ts.map +1 -1
- package/src/core/geom/2d/r-tree/StaticR2Tree.js +5 -4
- package/src/core/geom/3d/aabb/aabb3_detailed_volume_intersection.d.ts.map +1 -1
- package/src/core/geom/3d/aabb/aabb3_detailed_volume_intersection.js +33 -29
- package/src/core/geom/3d/aabb/aabb3_near_distance_to_intersection_ray_segment.d.ts.map +1 -1
- package/src/core/geom/3d/aabb/aabb3_near_distance_to_intersection_ray_segment.js +3 -1
- package/src/core/geom/3d/aabb/aabb3_signed_distance_to_aabb3.d.ts.map +1 -1
- package/src/core/geom/3d/aabb/aabb3_signed_distance_to_aabb3.js +10 -7
- package/src/{engine/physics/narrowphase/decomposition/aabb_world_to_local.d.ts → core/geom/3d/aabb/aabb3_transform_oriented_inverse.d.ts} +9 -7
- package/src/core/geom/3d/aabb/aabb3_transform_oriented_inverse.d.ts.map +1 -0
- package/src/{engine/physics/narrowphase/decomposition/aabb_world_to_local.js → core/geom/3d/aabb/aabb3_transform_oriented_inverse.js} +9 -7
- package/src/core/geom/3d/aabb/aabb3_transformed_compute_plane_side.d.ts.map +1 -1
- package/src/core/geom/3d/aabb/aabb3_transformed_compute_plane_side.js +30 -9
- package/src/core/geom/3d/aabb/compute_aabb_from_points.js +3 -3
- package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.d.ts +12 -0
- package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.d.ts.map +1 -0
- package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.js +46 -0
- package/src/core/geom/3d/box/box3_projected_half_extent.d.ts +28 -0
- package/src/core/geom/3d/box/box3_projected_half_extent.d.ts.map +1 -0
- package/src/core/geom/3d/box/box3_projected_half_extent.js +35 -0
- package/src/core/geom/3d/box/box3_raycast.d.ts +37 -0
- package/src/core/geom/3d/box/box3_raycast.d.ts.map +1 -0
- package/src/core/geom/3d/box/box3_raycast.js +81 -0
- package/src/core/geom/3d/capsule/capsule_raycast.d.ts +35 -0
- package/src/core/geom/3d/capsule/capsule_raycast.d.ts.map +1 -0
- package/src/core/geom/3d/capsule/capsule_raycast.js +93 -0
- package/src/core/geom/3d/cone/compute_bounding_cone_of_2_cones.d.ts.map +1 -1
- package/src/core/geom/3d/cone/compute_bounding_cone_of_2_cones.js +4 -0
- package/src/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +1 -1
- package/src/core/geom/3d/frustum/read_cluster_frustum_corners.js +1 -1
- package/src/core/geom/3d/frustum/read_frustum_corner.d.ts +9 -0
- package/src/core/geom/3d/frustum/read_frustum_corner.d.ts.map +1 -0
- package/src/core/geom/3d/frustum/read_frustum_corner.js +14 -0
- package/src/core/geom/3d/gjk/gjk.d.ts.map +1 -0
- package/src/{engine/physics → core/geom/3d}/gjk/gjk.js +430 -372
- package/src/{engine/physics → core/geom/3d}/gjk/gjk_epa_penetration.d.ts +8 -5
- package/src/core/geom/3d/gjk/gjk_epa_penetration.d.ts.map +1 -0
- package/src/{engine/physics → core/geom/3d}/gjk/gjk_epa_penetration.js +520 -548
- package/src/{engine/physics → core/geom/3d}/gjk/minkowski_support.d.ts +5 -4
- package/src/core/geom/3d/gjk/minkowski_support.d.ts.map +1 -0
- package/src/{engine/physics → core/geom/3d}/gjk/minkowski_support.js +71 -70
- package/src/{engine/physics → core/geom/3d}/gjk/mpr.d.ts +3 -3
- package/src/core/geom/3d/gjk/mpr.d.ts.map +1 -0
- package/src/{engine/physics → core/geom/3d}/gjk/mpr.js +368 -362
- package/src/core/geom/3d/line/line3_compute_segment_point_distance_eikonal.d.ts.map +1 -1
- package/src/core/geom/3d/line/line3_compute_segment_point_distance_eikonal.js +3 -2
- package/src/core/geom/3d/mat4/decompose_matrix_4_array.d.ts.map +1 -1
- package/src/core/geom/3d/mat4/decompose_matrix_4_array.js +12 -2
- package/src/core/geom/3d/mat4/eulerAnglesFromMatrix.js +2 -2
- package/src/core/geom/3d/mat4/m4_multiply_alphatensor.d.ts +1 -1
- package/src/core/geom/3d/mat4/m4_multiply_alphatensor.d.ts.map +1 -1
- package/src/core/geom/3d/mat4/m4_multiply_alphatensor.js +19 -13
- package/src/core/geom/3d/octahedra/octahedral_direction_to_uv.d.ts.map +1 -1
- package/src/core/geom/3d/octahedra/octahedral_direction_to_uv.js +3 -2
- package/src/core/geom/3d/plane/plane3_compute_plane_intersection.js +3 -2
- package/src/{engine/physics/integration/quat_integrate.d.ts → core/geom/3d/quaternion/quat3_integrate.d.ts} +2 -2
- package/src/core/geom/3d/quaternion/quat3_integrate.d.ts.map +1 -0
- package/src/{engine/physics/integration/quat_integrate.js → core/geom/3d/quaternion/quat3_integrate.js} +1 -1
- package/src/core/geom/3d/shape/MeshShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/MeshShape3D.js +7 -0
- package/src/{engine/physics/narrowphase/PosedShape.d.ts → core/geom/3d/shape/PosedShape3D.d.ts} +9 -8
- package/src/{engine/physics/narrowphase/PosedShape.d.ts.map → core/geom/3d/shape/PosedShape3D.d.ts.map} +1 -1
- package/src/{engine/physics/narrowphase/PosedShape.js → core/geom/3d/shape/PosedShape3D.js} +10 -9
- package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/TransformedShape3D.js +15 -11
- package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/UnionShape3D.js +3 -2
- package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.d.ts.map +1 -1
- package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +153 -148
- package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.d.ts.map +1 -1
- package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.js +7 -0
- package/src/core/geom/3d/sphere/harmonics/sh3_sample_by_direction.d.ts.map +1 -1
- package/src/core/geom/3d/sphere/harmonics/sh3_sample_by_direction.js +13 -10
- package/src/core/geom/3d/sphere/sphere_projected_sphere_radius_sqr.d.ts +1 -1
- package/src/core/geom/3d/sphere/sphere_projected_sphere_radius_sqr.js +2 -2
- package/src/core/geom/3d/sphere/sphere_raycast.d.ts +33 -0
- package/src/core/geom/3d/sphere/sphere_raycast.d.ts.map +1 -0
- package/src/core/geom/3d/sphere/sphere_raycast.js +47 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_tet_get_neighbours.d.ts +24 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_tet_get_neighbours.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_tet_get_neighbours.js +39 -0
- package/src/core/geom/3d/tetrahedra/triangle/trace_triangular_depth_map.d.ts.map +1 -1
- package/src/core/geom/3d/tetrahedra/triangle/trace_triangular_depth_map.js +4 -2
- package/src/core/geom/3d/topology/bounds/computeTriangleClusterNormalBoundingCone.js +3 -3
- package/src/core/geom/3d/topology/simplify/decimate_edge_collapse_snap.js +1 -1
- package/src/core/geom/3d/topology/tm_vertex_compute_normal.d.ts.map +1 -1
- package/src/core/geom/3d/topology/tm_vertex_compute_normal.js +4 -2
- package/src/core/geom/3d/util/make_justified_point_grid.d.ts.map +1 -1
- package/src/core/geom/3d/util/make_justified_point_grid.js +18 -10
- package/src/core/geom/ConicRay.d.ts.map +1 -1
- package/src/core/geom/ConicRay.js +11 -13
- package/src/core/geom/packing/max-rect/removeRedundantBoxes.d.ts.map +1 -1
- package/src/core/geom/packing/max-rect/removeRedundantBoxes.js +19 -4
- package/src/core/geom/vec3/v3_orthonormal_matrix_from_normal.d.ts.map +1 -0
- package/src/{engine/graphics/sh3/path_tracer/sampling → core/geom/vec3}/v3_orthonormal_matrix_from_normal.js +1 -1
- package/src/core/geom/vec3/v3_quat3_apply_inverse.d.ts +1 -1
- package/src/core/geom/vec3/v3_quat3_apply_inverse.js +1 -1
- package/src/core/graph/coloring/colorizeGraph.js +2 -2
- package/src/core/graph/csr/CSRGraph.d.ts.map +1 -1
- package/src/core/graph/csr/CSRGraph.js +325 -319
- package/src/core/graph/layout/CircleLayout.d.ts.map +1 -1
- package/src/core/graph/layout/CircleLayout.js +8 -6
- package/src/core/graph/metis/native/refine/compute_kway_params.d.ts.map +1 -1
- package/src/core/graph/metis/native/refine/compute_kway_params.js +139 -138
- package/src/core/graph/mn_graph_coarsen.d.ts.map +1 -1
- package/src/core/graph/mn_graph_coarsen.js +4 -2
- package/src/core/graph/v2/NodeContainer.js +7 -7
- package/src/core/localization/LocalizationEngine.js +1 -1
- package/src/core/math/bell_membership_function.d.ts.map +1 -1
- package/src/core/math/bell_membership_function.js +3 -1
- package/src/core/math/complex/complex_add.d.ts +4 -4
- package/src/core/math/complex/complex_add.d.ts.map +1 -1
- package/src/core/math/complex/complex_add.js +14 -5
- package/src/core/math/complex/complex_div.d.ts +4 -4
- package/src/core/math/complex/complex_div.d.ts.map +1 -1
- package/src/core/math/complex/complex_div.js +13 -6
- package/src/core/math/complex/complex_mul.d.ts +4 -4
- package/src/core/math/complex/complex_mul.d.ts.map +1 -1
- package/src/core/math/complex/complex_mul.js +12 -5
- package/src/core/math/complex/complex_sub.d.ts +4 -4
- package/src/core/math/complex/complex_sub.d.ts.map +1 -1
- package/src/core/math/complex/complex_sub.js +14 -5
- package/src/core/math/idct_1d.d.ts +4 -4
- package/src/core/math/idct_1d.d.ts.map +1 -1
- package/src/core/math/idct_1d.js +3 -3
- package/src/{engine/physics/fluid/solver/optimal_sor_omega.d.ts → core/math/linalg/sor_optimal_omega.d.ts} +4 -3
- package/src/core/math/linalg/sor_optimal_omega.d.ts.map +1 -0
- package/src/{engine/physics/fluid/solver/optimal_sor_omega.js → core/math/linalg/sor_optimal_omega.js} +4 -3
- package/src/core/math/lookup/ParameterLookupTable.d.ts +123 -0
- package/src/core/math/lookup/ParameterLookupTable.d.ts.map +1 -0
- package/src/core/math/lookup/ParameterLookupTable.js +495 -0
- package/src/core/math/lookup/ParameterLookupTableFlags.d.ts +5 -0
- package/src/core/math/lookup/ParameterLookupTableFlags.d.ts.map +1 -0
- package/src/core/math/lookup/ParameterLookupTableFlags.js +6 -0
- package/src/core/math/noise/create_simplex_noise_2d.d.ts.map +1 -1
- package/src/core/math/noise/create_simplex_noise_2d.js +4 -2
- package/src/core/math/noise/sdnoise.d.ts.map +1 -1
- package/src/core/math/noise/sdnoise.js +12 -9
- package/src/core/math/physics/kinematics/computeInterceptPoint.d.ts.map +1 -0
- package/src/{engine/physics → core/math/physics/kinematics}/computeInterceptPoint.js +79 -79
- package/src/core/math/physics/mie/compute_bhmie_optical_properties.d.ts.map +1 -1
- package/src/core/math/physics/mie/compute_bhmie_optical_properties.js +94 -50
- package/src/core/math/physics/mie/lorenz_mie_coefs.d.ts +3 -6
- package/src/core/math/physics/mie/lorenz_mie_coefs.d.ts.map +1 -1
- package/src/core/math/physics/mie/lorenz_mie_coefs.js +180 -157
- package/src/core/math/physics/mie/mie_ab_to_optical_properties.d.ts +3 -4
- package/src/core/math/physics/mie/mie_ab_to_optical_properties.d.ts.map +1 -1
- package/src/core/math/physics/mie/mie_ab_to_optical_properties.js +47 -21
- package/src/core/math/physics/mie/ri_air.d.ts.map +1 -1
- package/src/core/math/physics/mie/ri_air.js +1 -3
- package/src/core/math/physics/mie/ri_ammonium_sulfate.d.ts.map +1 -1
- package/src/core/math/physics/mie/ri_ammonium_sulfate.js +1 -3
- package/src/core/math/physics/mie/ri_brine.d.ts.map +1 -1
- package/src/core/math/physics/mie/ri_brine.js +1 -3
- package/src/core/math/physics/mie/ri_dust.d.ts.map +1 -1
- package/src/core/math/physics/mie/ri_dust.js +1 -3
- package/src/core/math/physics/mie/ri_pollen.d.ts.map +1 -1
- package/src/core/math/physics/mie/ri_pollen.js +1 -3
- package/src/core/math/physics/mie/ri_smoke.d.ts.map +1 -1
- package/src/core/math/physics/mie/ri_smoke.js +1 -3
- package/src/core/math/physics/mie/ri_soot.d.ts.map +1 -1
- package/src/core/math/physics/mie/ri_soot.js +1 -3
- package/src/core/math/physics/mie/ri_water.d.ts.map +1 -1
- package/src/core/math/physics/mie/ri_water.js +1 -3
- package/src/core/math/random/randomIntegerBetween.d.ts.map +1 -1
- package/src/core/math/random/randomIntegerBetween.js +4 -1
- package/src/core/math/random/random_pick_weighted_index.d.ts +10 -0
- package/src/core/math/random/random_pick_weighted_index.d.ts.map +1 -0
- package/src/core/math/random/random_pick_weighted_index.js +26 -0
- package/src/core/math/solveCubic.d.ts.map +1 -1
- package/src/core/math/solveCubic.js +95 -82
- package/src/core/math/spline/computeCatmullRomSplineUniformDistance.d.ts.map +1 -1
- package/src/core/math/spline/computeCatmullRomSplineUniformDistance.js +13 -0
- package/src/core/math/statistics/softmax.js +1 -1
- package/src/core/model/node-graph/NodeGraph.d.ts +9 -0
- package/src/core/model/node-graph/NodeGraph.d.ts.map +1 -1
- package/src/core/model/node-graph/NodeGraph.js +38 -0
- package/src/core/model/node-graph/visual/NodeGraphVisualData.d.ts +24 -0
- package/src/core/model/node-graph/visual/NodeGraphVisualData.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/NodeGraphVisualData.js +56 -1
- package/src/core/model/node-graph/visual/NodeVisualData.js +1 -1
- package/src/core/model/object/ImmutableObjectPool.d.ts +7 -0
- package/src/core/model/object/ImmutableObjectPool.d.ts.map +1 -1
- package/src/core/model/object/ImmutableObjectPool.js +20 -10
- package/src/core/model/reactive/evaluation/MultiPredicateEvaluator.d.ts.map +1 -1
- package/src/core/model/reactive/evaluation/MultiPredicateEvaluator.js +39 -2
- package/src/core/model/reactive/model/terminal/ReactiveReference.d.ts.map +1 -1
- package/src/core/model/reactive/model/terminal/ReactiveReference.js +2 -0
- package/src/core/parser/simple/readHexToken.d.ts.map +1 -1
- package/src/core/parser/simple/readHexToken.js +6 -0
- package/src/core/path/convertPathToURL.d.ts +9 -0
- package/src/core/path/convertPathToURL.d.ts.map +1 -0
- package/src/core/path/convertPathToURL.js +107 -0
- package/src/core/primitives/numbers/number_pretty_print.d.ts.map +1 -1
- package/src/core/primitives/numbers/number_pretty_print.js +4 -1
- package/src/core/primitives/strings/string_jaro_winkler.js +1 -1
- package/src/core/process/CompositeProcess.js +1 -1
- package/src/core/process/executor/ConcurrentExecutor.d.ts.map +1 -1
- package/src/core/process/executor/ConcurrentExecutor.js +3 -2
- package/src/core/process/task/util/randomCountTask.d.ts.map +1 -1
- package/src/core/process/task/util/randomCountTask.js +3 -1
- package/src/core/process/undo/ActionProcessor.d.ts.map +1 -1
- package/src/core/process/undo/ActionProcessor.js +5 -3
- package/src/core/process/worker/WorkerBuilder.js +4 -4
- package/src/core/process/worker/extractTransferables.js +1 -1
- package/src/engine/animation/curve/AnimationCurve.d.ts.map +1 -1
- package/src/engine/animation/curve/AnimationCurve.js +4 -2
- package/src/engine/animation/curve/draw/build_tangent_editor.d.ts.map +1 -1
- package/src/engine/animation/curve/draw/build_tangent_editor.js +8 -1
- package/src/engine/animation/curve/editor/createKeyframeDraggableAspect.d.ts.map +1 -1
- package/src/engine/animation/curve/editor/createKeyframeDraggableAspect.js +11 -5
- package/src/engine/asset/Asset.d.ts.map +1 -1
- package/src/engine/asset/Asset.js +16 -6
- package/src/engine/asset/AssetManager.d.ts +61 -52
- package/src/engine/asset/AssetManager.d.ts.map +1 -1
- package/src/engine/asset/AssetManager.js +1411 -1045
- package/src/engine/asset/AssetRequest.d.ts +1 -1
- package/src/engine/asset/AssetRequest.d.ts.map +1 -1
- package/src/engine/asset/AssetRequest.js +1 -1
- package/src/engine/asset/AssetRequestScope.d.ts.map +1 -1
- package/src/engine/asset/AssetRequestScope.js +7 -0
- package/src/engine/asset/PendingAsset.d.ts +32 -1
- package/src/engine/asset/PendingAsset.d.ts.map +1 -1
- package/src/engine/asset/PendingAsset.js +108 -61
- package/src/engine/asset/loaders/ArrayBufferLoader.js +2 -2
- package/src/engine/asset/loaders/AssetLoader.d.ts.map +1 -1
- package/src/engine/asset/loaders/AssetLoader.js +19 -2
- package/src/engine/asset/loaders/GLTFAssetLoader.d.ts.map +1 -1
- package/src/engine/asset/loaders/GLTFAssetLoader.js +123 -114
- package/src/engine/asset/loaders/JavascriptAssetLoader.d.ts +1 -1
- package/src/engine/asset/loaders/JavascriptAssetLoader.d.ts.map +1 -1
- package/src/engine/asset/loaders/JavascriptAssetLoader.js +31 -47
- package/src/engine/asset/loaders/JsonAssetLoader.js +1 -1
- package/src/engine/asset/loaders/SVGAssetLoader.js +2 -2
- package/src/engine/asset/loaders/SoundAssetLoader.js +1 -1
- package/src/engine/asset/loaders/TextAssetLoader.js +2 -2
- package/src/{core → engine/asset/loaders}/font/FontAsset.d.ts +1 -1
- package/src/engine/asset/loaders/font/FontAsset.d.ts.map +1 -0
- package/src/{core → engine/asset/loaders}/font/FontAsset.js +21 -21
- package/src/{core → engine/asset/loaders}/font/FontAssetLoader.d.ts +1 -1
- package/src/engine/asset/loaders/font/FontAssetLoader.d.ts.map +1 -0
- package/src/{core → engine/asset/loaders}/font/FontAssetLoader.js +20 -20
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts +1 -1
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts.map +1 -1
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +11 -20
- package/src/engine/asset/loaders/texture/TextureAssetLoader.d.ts.map +1 -1
- package/src/engine/asset/loaders/texture/TextureAssetLoader.js +8 -2
- package/src/engine/asset/preloader/AssetPreloader.js +1 -1
- package/src/engine/control/first-person/DESIGN.md +1 -1
- package/src/engine/control/first-person/FirstPersonMotionPhase.d.ts +55 -0
- package/src/engine/control/first-person/FirstPersonMotionPhase.d.ts.map +1 -0
- package/src/engine/control/first-person/FirstPersonMotionPhase.js +134 -0
- package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +23 -2
- package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerController.js +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +168 -0
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +115 -0
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts +71 -0
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +255 -55
- package/src/engine/control/first-person/abilities/LedgeGrab.d.ts +82 -43
- package/src/engine/control/first-person/abilities/LedgeGrab.d.ts.map +1 -1
- package/src/engine/control/first-person/abilities/LedgeGrab.js +405 -213
- package/src/engine/control/first-person/abilities/Mantle.d.ts +6 -0
- package/src/engine/control/first-person/abilities/Mantle.d.ts.map +1 -1
- package/src/engine/control/first-person/abilities/Mantle.js +104 -45
- package/src/engine/control/first-person/abilities/ScrambleUp.d.ts +61 -0
- package/src/engine/control/first-person/abilities/ScrambleUp.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/ScrambleUp.js +182 -0
- package/src/engine/control/first-person/math/jumpDynamics.d.ts +84 -0
- package/src/engine/control/first-person/math/jumpDynamics.d.ts.map +1 -0
- package/src/engine/control/first-person/math/jumpDynamics.js +108 -0
- package/src/engine/control/first-person/prototype_first_person_controller.js +45 -1
- package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts +1 -1
- package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts.map +1 -1
- package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.js +19 -22
- package/src/engine/graphics/FrameThrottle.d.ts +1 -7
- package/src/engine/graphics/FrameThrottle.d.ts.map +1 -1
- package/src/engine/graphics/FrameThrottle.js +2 -24
- package/src/engine/graphics/camera/testClippingPlaneComputation.js +1 -1
- package/src/{core/geom/3d/shape/util → engine/graphics/debug}/shape_to_visual_entity.d.ts +1 -1
- package/src/engine/graphics/debug/shape_to_visual_entity.d.ts.map +1 -0
- package/src/{core/geom/3d/shape/util → engine/graphics/debug}/shape_to_visual_entity.js +159 -159
- package/src/{core/geom/3d/tetrahedra → engine/graphics/debug}/visualize_tetrahedral_mesh.d.ts +1 -1
- package/src/engine/graphics/debug/visualize_tetrahedral_mesh.d.ts.map +1 -0
- package/src/{core/geom/3d/tetrahedra → engine/graphics/debug}/visualize_tetrahedral_mesh.js +46 -46
- package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.d.ts +1 -1
- package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.d.ts.map +1 -1
- package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.js +22 -32
- package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +1 -1
- package/src/engine/graphics/particles/particular/engine/emitter/serde/ParameterLookupTableSerializationAdapter.d.ts.map +1 -1
- package/src/engine/graphics/particles/particular/engine/emitter/serde/ParameterLookupTableSerializationAdapter.js +2 -76
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.d.ts.map +1 -1
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +2 -427
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.d.ts +1 -4
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.d.ts.map +1 -1
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.js +2 -6
- package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +2 -2
- package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +1 -1
- package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +1 -1
- package/src/engine/graphics/render/forward_plus/read_frustum_corner.d.ts +1 -8
- package/src/engine/graphics/render/forward_plus/read_frustum_corner.d.ts.map +1 -1
- package/src/engine/graphics/render/forward_plus/read_frustum_corner.js +2 -14
- package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +1 -1
- package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.d.ts +1 -11
- package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.d.ts.map +1 -1
- package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.js +2 -46
- package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +1 -1
- package/src/engine/graphics/sh3/prototypeSH3Probe.js +1 -1
- package/src/engine/graphics/shadows/testShadowMapRendering.js +1 -1
- package/src/engine/graphics/texture/3d/scs3d_sample_linear3.d.ts +27 -0
- package/src/engine/graphics/texture/3d/scs3d_sample_linear3.d.ts.map +1 -0
- package/src/engine/graphics/texture/3d/scs3d_sample_linear3.js +81 -0
- package/src/engine/graphics/texture/isImageBitmap.d.ts +1 -6
- package/src/engine/graphics/texture/isImageBitmap.d.ts.map +1 -1
- package/src/engine/graphics/texture/isImageBitmap.js +2 -12
- package/src/{core/process/action → engine/intelligence/behavior/util}/AsynchronousDelayAction.d.ts +2 -2
- package/src/engine/intelligence/behavior/util/AsynchronousDelayAction.d.ts.map +1 -0
- package/src/{core/process/action → engine/intelligence/behavior/util}/AsynchronousDelayAction.js +55 -52
- package/src/engine/network/NetworkSession.d.ts +12 -1
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +52 -1
- package/src/engine/network/README.md +45 -0
- package/src/engine/network/convertPathToURL.d.ts +1 -8
- package/src/engine/network/convertPathToURL.d.ts.map +1 -1
- package/src/engine/network/convertPathToURL.js +2 -107
- package/src/engine/network/core/quantize/quantize_float.d.ts.map +1 -1
- package/src/engine/network/core/quantize/quantize_float.js +7 -0
- package/src/engine/network/core/quantize/quantize_position.d.ts.map +1 -1
- package/src/engine/network/core/quantize/quantize_position.js +12 -1
- package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/NetworkPeer.js +15 -1
- package/src/engine/network/replication/Replicator.d.ts +8 -0
- package/src/engine/network/replication/Replicator.d.ts.map +1 -1
- package/src/engine/network/replication/Replicator.js +48 -0
- package/src/engine/network/transport/Channel.d.ts.map +1 -1
- package/src/engine/network/transport/Channel.js +46 -12
- package/src/engine/network/transport/ReliableCommandPipeline.d.ts +16 -0
- package/src/engine/network/transport/ReliableCommandPipeline.d.ts.map +1 -1
- package/src/engine/network/transport/ReliableCommandPipeline.js +29 -0
- package/src/engine/network/transport/adapters/NodeUDPTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/NodeUDPTransport.js +7 -1
- package/src/engine/network/transport/fragments/packet_size.d.ts +5 -5
- package/src/engine/network/transport/fragments/packet_size.d.ts.map +1 -1
- package/src/engine/network/transport/fragments/packet_size.js +5 -5
- package/src/engine/physics/BULLET_REVIEW.md +1 -1
- package/src/engine/physics/CONSTRAINT_SOLVER_BENCH_LOG.md +208 -0
- package/src/engine/physics/CONSTRAINT_SOLVER_IMPROVEMENTS_PLAN.md +364 -0
- package/src/engine/physics/JOLT_REVIEW.md +2 -2
- package/src/engine/physics/PLAN.md +1094 -944
- package/src/engine/physics/RAPIER_REVIEW.md +2 -2
- package/src/engine/physics/body/BodyStorage.d.ts +2 -12
- package/src/engine/physics/body/BodyStorage.d.ts.map +1 -1
- package/src/engine/physics/body/BodyStorage.js +406 -452
- package/src/engine/physics/body/SolverBodyState.d.ts.map +1 -1
- package/src/engine/physics/body/SolverBodyState.js +12 -3
- package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +28 -3
- package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -1
- package/src/engine/physics/broadphase/compute_fat_world_aabb.js +60 -24
- package/src/engine/physics/broadphase/generate_pairs.d.ts +9 -5
- package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
- package/src/engine/physics/broadphase/generate_pairs.js +52 -37
- package/src/engine/physics/ccd/linear_sweep.d.ts +15 -5
- package/src/engine/physics/ccd/linear_sweep.d.ts.map +1 -1
- package/src/engine/physics/ccd/linear_sweep.js +122 -40
- package/src/engine/physics/constraint/solve_constraints.d.ts +4 -1
- package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
- package/src/engine/physics/constraint/solve_constraints.js +830 -691
- package/src/engine/physics/contact/ManifoldStore.d.ts +91 -16
- package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -1
- package/src/engine/physics/contact/ManifoldStore.js +204 -60
- package/src/engine/physics/ecs/BodyKind.d.ts +7 -3
- package/src/engine/physics/ecs/BodyKind.d.ts.map +1 -1
- package/src/engine/physics/ecs/BodyKind.js +29 -25
- package/src/engine/physics/ecs/Collider.d.ts +7 -0
- package/src/engine/physics/ecs/Collider.d.ts.map +1 -1
- package/src/engine/physics/ecs/Collider.js +7 -0
- package/src/engine/physics/ecs/ColliderSerializationAdapter.js +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +110 -6
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +2172 -1747
- package/src/engine/physics/ecs/RigidBody.d.ts +20 -5
- package/src/engine/physics/ecs/RigidBody.d.ts.map +1 -1
- package/src/engine/physics/ecs/RigidBody.js +307 -286
- package/src/engine/physics/ecs/RigidBodyFlags.d.ts +6 -3
- package/src/engine/physics/ecs/RigidBodyFlags.d.ts.map +1 -1
- package/src/engine/physics/ecs/RigidBodyFlags.js +31 -28
- package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts +12 -4
- package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts.map +1 -1
- package/src/engine/physics/ecs/RigidBodySerializationAdapter.js +19 -5
- package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.d.ts +10 -0
- package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.js +37 -0
- package/src/engine/physics/ecs/find_non_finite_physics_state.d.ts +28 -0
- package/src/engine/physics/ecs/find_non_finite_physics_state.d.ts.map +1 -0
- package/src/engine/physics/ecs/find_non_finite_physics_state.js +76 -0
- package/src/engine/physics/events/ContactEventBuffer.d.ts +11 -0
- package/src/engine/physics/events/ContactEventBuffer.d.ts.map +1 -1
- package/src/engine/physics/events/ContactEventBuffer.js +40 -0
- package/src/engine/physics/events/diff_manifolds.d.ts +30 -13
- package/src/engine/physics/events/diff_manifolds.d.ts.map +1 -1
- package/src/engine/physics/events/diff_manifolds.js +87 -50
- package/src/engine/physics/fluid/FluidField.d.ts +45 -17
- package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
- package/src/engine/physics/fluid/FluidField.js +53 -23
- package/src/engine/physics/fluid/FluidSimulator.d.ts +141 -5
- package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
- package/src/engine/physics/fluid/FluidSimulator.js +336 -43
- package/src/engine/physics/fluid/REVIEW_02_PLAN.md +114 -0
- package/src/engine/physics/fluid/ecs/FluidComponent.d.ts +4 -3
- package/src/engine/physics/fluid/ecs/FluidComponent.d.ts.map +1 -1
- package/src/engine/physics/fluid/ecs/FluidComponent.js +4 -3
- package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
- package/src/engine/physics/fluid/effector/AmbientWindFluidEffector.d.ts +41 -0
- package/src/engine/physics/fluid/effector/AmbientWindFluidEffector.d.ts.map +1 -0
- package/src/engine/physics/fluid/effector/AmbientWindFluidEffector.js +124 -0
- package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts +27 -8
- package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts.map +1 -1
- package/src/engine/physics/fluid/effector/WakeFluidEffector.js +67 -18
- package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.d.ts +42 -0
- package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.js +136 -0
- package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.d.ts +37 -0
- package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.js +169 -0
- package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.d.ts +36 -0
- package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.js +100 -0
- package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts +6 -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 +6 -0
- package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts +7 -2
- package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.js +17 -12
- package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.d.ts +42 -0
- package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.js +131 -0
- package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts +32 -22
- package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +43 -26
- package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.d.ts +31 -0
- package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.js +77 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts +26 -19
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +46 -42
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts +38 -10
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +158 -75
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts +22 -17
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +108 -96
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts +30 -1
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -1
- package/src/engine/physics/inertia/world_inverse_inertia.js +160 -116
- package/src/engine/physics/integration/integrate_position.js +97 -97
- package/src/engine/physics/island/IslandBuilder.d.ts +49 -8
- package/src/engine/physics/island/IslandBuilder.d.ts.map +1 -1
- package/src/engine/physics/island/IslandBuilder.js +93 -14
- package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/box_box_manifold.js +683 -673
- package/src/engine/physics/narrowphase/box_triangle_contact.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/box_triangle_contact.js +899 -749
- package/src/engine/physics/narrowphase/capsule_contacts.d.ts +27 -0
- package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/capsule_contacts.js +624 -459
- package/src/engine/physics/narrowphase/capsule_triangle_contact.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/capsule_triangle_contact.js +58 -38
- package/src/engine/physics/narrowphase/compute_penetration.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/compute_penetration.js +369 -325
- package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts +3 -1
- package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/convex_convex_manifold.js +568 -425
- package/src/engine/physics/narrowphase/convex_decomposition.d.ts +32 -13
- package/src/engine/physics/narrowphase/convex_decomposition.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/convex_decomposition.js +61 -65
- package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts +6 -3
- package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.js +66 -10
- package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts +4 -1
- package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.js +97 -94
- package/src/engine/physics/narrowphase/mesh_convex_hull.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/mesh_convex_hull.js +13 -8
- package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.js +117 -117
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/narrowphase_step.js +1738 -1739
- package/src/engine/physics/narrowphase/reduce_manifold_contacts.d.ts +14 -7
- package/src/engine/physics/narrowphase/reduce_manifold_contacts.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/reduce_manifold_contacts.js +74 -69
- package/src/engine/physics/narrowphase/refine_ray_concave.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/refine_ray_concave.js +5 -3
- package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/refine_ray_hit.js +81 -78
- package/src/engine/physics/persistence/solver_caches.d.ts +20 -0
- package/src/engine/physics/persistence/solver_caches.d.ts.map +1 -0
- package/src/engine/physics/persistence/solver_caches.js +309 -0
- package/src/engine/physics/queries/overlap_shape.d.ts.map +1 -1
- package/src/engine/physics/queries/overlap_shape.js +187 -184
- package/src/engine/physics/queries/raycast.d.ts +3 -2
- package/src/engine/physics/queries/raycast.d.ts.map +1 -1
- package/src/engine/physics/queries/raycast.js +37 -11
- package/src/engine/physics/queries/shape_cast.d.ts +18 -5
- package/src/engine/physics/queries/shape_cast.d.ts.map +1 -1
- package/src/engine/physics/queries/shape_cast.js +417 -393
- package/src/engine/physics/solver/solve_contacts.d.ts +22 -6
- package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -1
- package/src/engine/physics/solver/solve_contacts.js +1482 -1338
- package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -1
- package/src/engine/physics/vehicle/RaycastVehicle.js +344 -339
- package/src/engine/sound/SoundEngine.d.ts.map +1 -1
- package/src/engine/sound/SoundEngine.js +28 -0
- package/src/engine/sound/dB2Volume.d.ts +1 -1
- package/src/engine/sound/dB2Volume.d.ts.map +1 -1
- package/src/engine/sound/dB2Volume.js +1 -1
- package/src/engine/sound/ecs/SoundController.d.ts +4 -0
- package/src/engine/sound/ecs/SoundController.d.ts.map +1 -1
- package/src/engine/sound/ecs/SoundController.js +4 -0
- package/src/engine/sound/ecs/SoundControllerSystem.d.ts +5 -0
- package/src/engine/sound/ecs/SoundControllerSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/SoundControllerSystem.js +5 -0
- package/src/engine/sound/ecs/audio/AudioEmitter.d.ts +69 -0
- package/src/engine/sound/ecs/audio/AudioEmitter.d.ts.map +1 -0
- package/src/engine/sound/ecs/audio/AudioEmitter.js +83 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts +97 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts.map +1 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.js +238 -0
- package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts +90 -0
- package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts.map +1 -0
- package/src/engine/sound/ecs/audio/LiveEmitterSet.js +324 -0
- package/src/engine/sound/ecs/audio/SpatialAudioIndex.d.ts +59 -0
- package/src/engine/sound/ecs/audio/SpatialAudioIndex.d.ts.map +1 -0
- package/src/engine/sound/ecs/audio/SpatialAudioIndex.js +140 -0
- package/src/engine/sound/ecs/emitter/SoundEmitter.d.ts +16 -65
- package/src/engine/sound/ecs/emitter/SoundEmitter.d.ts.map +1 -1
- package/src/engine/sound/ecs/emitter/SoundEmitter.js +19 -224
- package/src/engine/sound/ecs/emitter/SoundEmitterComponentContext.d.ts +26 -29
- package/src/engine/sound/ecs/emitter/SoundEmitterComponentContext.d.ts.map +1 -1
- package/src/engine/sound/ecs/emitter/SoundEmitterComponentContext.js +168 -135
- package/src/engine/sound/ecs/emitter/SoundEmitterSystem.d.ts +36 -59
- package/src/engine/sound/ecs/emitter/SoundEmitterSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/emitter/SoundEmitterSystem.js +154 -390
- package/src/engine/sound/ecs/emitter/SoundTrack.d.ts +20 -23
- package/src/engine/sound/ecs/emitter/SoundTrack.d.ts.map +1 -1
- package/src/engine/sound/ecs/emitter/SoundTrack.js +34 -152
- package/src/engine/sound/sopra/IMPLEMENTATION_PLAN.md +993 -0
- package/src/engine/sound/sopra/README.md +643 -7
- package/src/engine/sound/sopra/SopraEngine.d.ts +229 -0
- package/src/engine/sound/sopra/SopraEngine.d.ts.map +1 -0
- package/src/engine/sound/sopra/SopraEngine.js +423 -0
- package/src/engine/sound/sopra/asset/AssetManagerBufferProvider.d.ts +26 -0
- package/src/engine/sound/sopra/asset/AssetManagerBufferProvider.d.ts.map +1 -0
- package/src/engine/sound/sopra/asset/AssetManagerBufferProvider.js +71 -0
- package/src/engine/sound/sopra/asset/BufferProvider.d.ts +24 -0
- package/src/engine/sound/sopra/asset/BufferProvider.d.ts.map +1 -0
- package/src/engine/sound/sopra/asset/BufferProvider.js +29 -0
- package/src/engine/sound/sopra/asset/StubBufferProvider.d.ts +31 -0
- package/src/engine/sound/sopra/asset/StubBufferProvider.d.ts.map +1 -0
- package/src/engine/sound/sopra/asset/StubBufferProvider.js +58 -0
- package/src/engine/sound/sopra/definition/BusDefinition.d.ts +83 -0
- package/src/engine/sound/sopra/definition/BusDefinition.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/BusDefinition.js +142 -0
- package/src/engine/sound/sopra/definition/BusDefinitionSerializationAdapter.d.ts +17 -0
- package/src/engine/sound/sopra/definition/BusDefinitionSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/BusDefinitionSerializationAdapter.js +54 -0
- package/src/engine/sound/sopra/definition/DuckingRule.d.ts +71 -0
- package/src/engine/sound/sopra/definition/DuckingRule.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/DuckingRule.js +106 -0
- package/src/engine/sound/sopra/definition/DuckingRuleSerializationAdapter.d.ts +18 -0
- package/src/engine/sound/sopra/definition/DuckingRuleSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/DuckingRuleSerializationAdapter.js +31 -0
- package/src/engine/sound/sopra/definition/EventDescription.d.ts +132 -0
- package/src/engine/sound/sopra/definition/EventDescription.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/EventDescription.js +259 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts +17 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +71 -0
- package/src/engine/sound/sopra/definition/MixerSnapshot.d.ts +51 -0
- package/src/engine/sound/sopra/definition/MixerSnapshot.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/MixerSnapshot.js +83 -0
- package/src/engine/sound/sopra/definition/MixerSnapshotSerializationAdapter.d.ts +18 -0
- package/src/engine/sound/sopra/definition/MixerSnapshotSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/MixerSnapshotSerializationAdapter.js +39 -0
- package/src/engine/sound/sopra/definition/ParameterDefinition.d.ts +72 -0
- package/src/engine/sound/sopra/definition/ParameterDefinition.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/ParameterDefinition.js +117 -0
- package/src/engine/sound/sopra/definition/ParameterDefinitionSerializationAdapter.d.ts +18 -0
- package/src/engine/sound/sopra/definition/ParameterDefinitionSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/ParameterDefinitionSerializationAdapter.js +31 -0
- package/src/engine/sound/sopra/definition/SopraPanningModel.d.ts +14 -0
- package/src/engine/sound/sopra/definition/SopraPanningModel.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/SopraPanningModel.js +20 -0
- package/src/engine/sound/sopra/definition/VoiceStealMode.d.ts +10 -0
- package/src/engine/sound/sopra/definition/VoiceStealMode.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/VoiceStealMode.js +18 -0
- package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.d.ts +93 -0
- package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.js +109 -0
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.d.ts +80 -0
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.js +181 -0
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.d.ts +17 -0
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.js +74 -0
- package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.d.ts +34 -0
- package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.js +100 -0
- package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.d.ts +101 -0
- package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.js +230 -0
- package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClipSerializationAdapter.d.ts +17 -0
- package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClipSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClipSerializationAdapter.js +54 -0
- package/src/engine/sound/sopra/definition/clip/SampleAudioClip.d.ts +103 -0
- package/src/engine/sound/sopra/definition/clip/SampleAudioClip.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/SampleAudioClip.js +191 -0
- package/src/engine/sound/sopra/definition/clip/SampleAudioClipSerializationAdapter.d.ts +18 -0
- package/src/engine/sound/sopra/definition/clip/SampleAudioClipSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/SampleAudioClipSerializationAdapter.js +39 -0
- package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.d.ts +40 -0
- package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.js +91 -0
- package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClipSerializationAdapter.d.ts +17 -0
- package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClipSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClipSerializationAdapter.js +42 -0
- package/src/engine/sound/sopra/definition/clip/SilenceAudioClip.d.ts +44 -0
- package/src/engine/sound/sopra/definition/clip/SilenceAudioClip.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/SilenceAudioClip.js +77 -0
- package/src/engine/sound/sopra/definition/clip/SilenceAudioClipSerializationAdapter.d.ts +18 -0
- package/src/engine/sound/sopra/definition/clip/SilenceAudioClipSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/SilenceAudioClipSerializationAdapter.js +27 -0
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts +65 -0
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.js +131 -0
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClipSerializationAdapter.d.ts +17 -0
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClipSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClipSerializationAdapter.js +41 -0
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts +24 -0
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +24 -0
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts +70 -0
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +120 -0
- package/src/engine/sound/sopra/definition/effect/CompressorEffectSerializationAdapter.d.ts +18 -0
- package/src/engine/sound/sopra/definition/effect/CompressorEffectSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/effect/CompressorEffectSerializationAdapter.js +31 -0
- package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts +74 -0
- package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/effect/EqEffect.js +128 -0
- package/src/engine/sound/sopra/definition/effect/EqEffectSerializationAdapter.d.ts +18 -0
- package/src/engine/sound/sopra/definition/effect/EqEffectSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/effect/EqEffectSerializationAdapter.js +29 -0
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts +49 -0
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +101 -0
- package/src/engine/sound/sopra/definition/effect/ReverbEffectSerializationAdapter.d.ts +18 -0
- package/src/engine/sound/sopra/definition/effect/ReverbEffectSerializationAdapter.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/effect/ReverbEffectSerializationAdapter.js +25 -0
- package/src/engine/sound/sopra/legacy/soundEmitterToEventDescription.d.ts +31 -0
- package/src/engine/sound/sopra/legacy/soundEmitterToEventDescription.d.ts.map +1 -0
- package/src/engine/sound/sopra/legacy/soundEmitterToEventDescription.js +106 -0
- package/src/engine/sound/sopra/runtime/BusGraph.d.ts +79 -0
- package/src/engine/sound/sopra/runtime/BusGraph.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/BusGraph.js +227 -0
- package/src/engine/sound/sopra/runtime/EventInstance.d.ts +144 -0
- package/src/engine/sound/sopra/runtime/EventInstance.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/EventInstance.js +579 -0
- package/src/engine/sound/sopra/runtime/ParameterStore.d.ts +42 -0
- package/src/engine/sound/sopra/runtime/ParameterStore.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/ParameterStore.js +98 -0
- package/src/engine/sound/sopra/runtime/SopraPlaybackContext.d.ts +42 -0
- package/src/engine/sound/sopra/runtime/SopraPlaybackContext.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/SopraPlaybackContext.js +68 -0
- package/src/engine/sound/sopra/runtime/Voice.d.ts +67 -0
- package/src/engine/sound/sopra/runtime/Voice.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/Voice.js +145 -0
- package/src/engine/sound/sopra/runtime/VoiceManager.d.ts +38 -0
- package/src/engine/sound/sopra/runtime/VoiceManager.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/VoiceManager.js +136 -0
- package/src/engine/sound/sopra/runtime/VoicePool.d.ts +12 -0
- package/src/engine/sound/sopra/runtime/VoicePool.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/VoicePool.js +17 -0
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts +11 -0
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts.map +1 -0
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +42 -0
- package/src/engine/sound/sopra/serialization/sopraJSON.d.ts +33 -0
- package/src/engine/sound/sopra/serialization/sopraJSON.d.ts.map +1 -0
- package/src/engine/sound/sopra/serialization/sopraJSON.js +99 -0
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts +27 -0
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts.map +1 -0
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +49 -0
- package/src/engine/sound/sopra/util/MockAudioContext.d.ts +74 -0
- package/src/engine/sound/sopra/util/MockAudioContext.d.ts.map +1 -0
- package/src/engine/sound/sopra/util/MockAudioContext.js +215 -0
- package/src/engine/sound/sopra/util/buildAttenuationCurve.d.ts +15 -0
- package/src/engine/sound/sopra/util/buildAttenuationCurve.d.ts.map +1 -0
- package/src/engine/sound/sopra/util/buildAttenuationCurve.js +40 -0
- package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts +34 -0
- package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts.map +1 -0
- package/src/engine/sound/sopra/util/fadeOutAndStop.js +60 -0
- package/src/engine/sound/volume2dB.d.ts +1 -1
- package/src/engine/sound/volume2dB.d.ts.map +1 -1
- package/src/engine/sound/volume2dB.js +1 -1
- package/src/engine/ui/DraggableAspect.d.ts +12 -3
- package/src/engine/ui/DraggableAspect.d.ts.map +1 -1
- package/src/engine/ui/DraggableAspect.js +115 -83
- package/src/generation/COORDINATES.md +54 -0
- package/src/generation/GridTaskGroup.js +2 -2
- package/src/generation/REVIEW_01_ACTION_PLAN.md +628 -0
- package/src/generation/automata/CaveGeneratorCellularAutomata.d.ts +9 -1
- package/src/generation/automata/CaveGeneratorCellularAutomata.d.ts.map +1 -1
- package/src/generation/automata/CaveGeneratorCellularAutomata.js +79 -59
- package/src/generation/automata/CellularAutomata.d.ts +6 -3
- package/src/generation/automata/CellularAutomata.d.ts.map +1 -1
- package/src/generation/automata/CellularAutomata.js +22 -19
- package/src/generation/filtering/CellFilter.d.ts +17 -0
- package/src/generation/filtering/CellFilter.d.ts.map +1 -1
- package/src/generation/filtering/CellFilter.js +117 -77
- package/src/generation/filtering/CellFilterCellMatcher.d.ts.map +1 -1
- package/src/generation/filtering/CellFilterCellMatcher.js +2 -0
- package/src/generation/filtering/boolean/CellFilterLiteralBoolean.d.ts +5 -0
- package/src/generation/filtering/boolean/CellFilterLiteralBoolean.d.ts.map +1 -1
- package/src/generation/filtering/boolean/CellFilterLiteralBoolean.js +15 -0
- package/src/generation/filtering/core/CellFilterBinaryOperation.d.ts +0 -1
- package/src/generation/filtering/core/CellFilterBinaryOperation.d.ts.map +1 -1
- package/src/generation/filtering/core/CellFilterBinaryOperation.js +37 -50
- package/src/generation/filtering/core/CellFilterOperationTertiary.d.ts +0 -1
- package/src/generation/filtering/core/CellFilterOperationTertiary.d.ts.map +1 -1
- package/src/generation/filtering/core/CellFilterOperationTertiary.js +43 -59
- package/src/generation/filtering/core/CellFilterUnaryOperation.d.ts +0 -1
- package/src/generation/filtering/core/CellFilterUnaryOperation.d.ts.map +1 -1
- package/src/generation/filtering/core/CellFilterUnaryOperation.js +29 -33
- package/src/generation/filtering/numeric/CellFilterCache.d.ts +1 -0
- package/src/generation/filtering/numeric/CellFilterCache.d.ts.map +1 -1
- package/src/generation/filtering/numeric/complex/CellFilterAngleToNormal.d.ts +3 -2
- package/src/generation/filtering/numeric/complex/CellFilterAngleToNormal.d.ts.map +1 -1
- package/src/generation/filtering/numeric/complex/CellFilterAngleToNormal.js +9 -35
- package/src/generation/filtering/numeric/complex/CellFilterCurvature.d.ts +0 -1
- package/src/generation/filtering/numeric/complex/CellFilterCurvature.d.ts.map +1 -1
- package/src/generation/filtering/numeric/complex/CellFilterCurvature.js +19 -43
- package/src/generation/filtering/numeric/complex/CellFilterFXAA.d.ts +0 -1
- package/src/generation/filtering/numeric/complex/CellFilterFXAA.d.ts.map +1 -1
- package/src/generation/filtering/numeric/complex/CellFilterFXAA.js +2 -6
- package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.d.ts.map +1 -1
- package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +9 -12
- package/src/generation/filtering/numeric/complex/CellFilterSimplexNoise.d.ts.map +1 -1
- package/src/generation/filtering/numeric/complex/CellFilterSimplexNoise.js +2 -1
- package/src/generation/filtering/numeric/complex/CellFilterSobel.d.ts +0 -1
- package/src/generation/filtering/numeric/complex/CellFilterSobel.d.ts.map +1 -1
- package/src/generation/filtering/numeric/complex/CellFilterSobel.js +2 -6
- package/src/generation/filtering/numeric/math/CellFilterInverseLerp.d.ts +5 -4
- package/src/generation/filtering/numeric/math/CellFilterInverseLerp.d.ts.map +1 -1
- package/src/generation/filtering/numeric/math/CellFilterInverseLerp.js +5 -4
- package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.d.ts +17 -0
- package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.d.ts.map +1 -0
- package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.js +42 -0
- package/src/generation/filtering/numeric/sampling/AbstractCellFilterSampleGridLayer.d.ts.map +1 -1
- package/src/generation/filtering/numeric/sampling/AbstractCellFilterSampleGridLayer.js +7 -1
- package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.d.ts.map +1 -1
- package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.js +7 -10
- package/src/generation/filtering/numeric/util/sampler_from_filter.d.ts.map +1 -1
- package/src/generation/filtering/numeric/util/sampler_from_filter.js +2 -1
- package/src/generation/grid/GridData.d.ts.map +1 -1
- package/src/generation/grid/GridData.js +14 -1
- package/src/generation/grid/actions/ContinuousGridCellAction.d.ts +10 -3
- package/src/generation/grid/actions/ContinuousGridCellAction.d.ts.map +1 -1
- package/src/generation/grid/actions/ContinuousGridCellAction.js +18 -3
- package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainHeight.d.ts +11 -1
- package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainHeight.d.ts.map +1 -1
- package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainHeight.js +13 -3
- package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainObstacle.d.ts +1 -1
- package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainObstacle.js +2 -2
- package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.d.ts +1 -1
- package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.d.ts.map +1 -1
- package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.js +4 -6
- package/src/generation/grid/coords/grid_to_texel.d.ts +9 -0
- package/src/generation/grid/coords/grid_to_texel.d.ts.map +1 -0
- package/src/generation/grid/coords/grid_to_texel.js +10 -0
- package/src/generation/grid/coords/texel_to_grid.d.ts +9 -0
- package/src/generation/grid/coords/texel_to_grid.d.ts.map +1 -0
- package/src/generation/grid/coords/texel_to_grid.js +10 -0
- package/src/generation/grid/generation/GridTaskApplyActionToCells.d.ts +2 -2
- package/src/generation/grid/generation/GridTaskApplyActionToCells.d.ts.map +1 -1
- package/src/generation/grid/generation/GridTaskApplyActionToCells.js +10 -6
- package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.d.ts.map +1 -1
- package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +20 -21
- package/src/generation/grid/generation/GridTaskExecuteRuleTimes.d.ts +7 -0
- package/src/generation/grid/generation/GridTaskExecuteRuleTimes.d.ts.map +1 -1
- package/src/generation/grid/generation/GridTaskExecuteRuleTimes.js +18 -10
- package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.d.ts.map +1 -1
- package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.js +16 -7
- package/src/generation/grid/generation/discrete/GridTaskConnectRooms.d.ts +5 -3
- package/src/generation/grid/generation/discrete/GridTaskConnectRooms.d.ts.map +1 -1
- package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +26 -23
- package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.d.ts.map +1 -1
- package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +10 -1
- package/src/generation/grid/generation/grid/select/CellSupplierBestN.d.ts.map +1 -1
- package/src/generation/grid/generation/grid/select/CellSupplierBestN.js +4 -0
- package/src/generation/grid/generation/road/GridTaskGenerateRoads.d.ts +15 -8
- package/src/generation/grid/generation/road/GridTaskGenerateRoads.d.ts.map +1 -1
- package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +89 -92
- package/src/generation/markers/GridActionRuleSet.d.ts.map +1 -1
- package/src/generation/markers/GridActionRuleSet.js +10 -2
- package/src/generation/markers/GridCellActionPlaceMarker.d.ts +11 -0
- package/src/generation/markers/GridCellActionPlaceMarker.d.ts.map +1 -1
- package/src/generation/markers/GridCellActionPlaceMarker.js +20 -3
- package/src/generation/markers/GridCellActionPlaceMarkerGroup.d.ts +3 -1
- package/src/generation/markers/GridCellActionPlaceMarkerGroup.d.ts.map +1 -1
- package/src/generation/markers/GridCellActionPlaceMarkerGroup.js +9 -2
- package/src/generation/markers/MarkerNode.d.ts +8 -3
- package/src/generation/markers/MarkerNode.d.ts.map +1 -1
- package/src/generation/markers/MarkerNode.js +12 -5
- package/src/generation/markers/actions/MarkerNodeActionEntityPlacement.js +1 -1
- package/src/generation/markers/actions/placement/MarkerNodeEntityProcessor.d.ts +1 -1
- package/src/generation/markers/actions/placement/MarkerNodeEntityProcessor.d.ts.map +1 -1
- package/src/generation/markers/actions/placement/MarkerNodeEntityProcessor.js +1 -1
- package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.d.ts +1 -1
- package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.d.ts.map +1 -1
- package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.js +1 -1
- package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorRandomRotation.d.ts +1 -1
- package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorRandomRotation.d.ts.map +1 -1
- package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorRandomRotation.js +2 -2
- package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorSequence.d.ts +1 -1
- package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorSequence.d.ts.map +1 -1
- package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorSequence.js +2 -2
- package/src/generation/markers/actions/probability/MarkerNodeActionSelectWeighted.d.ts.map +1 -1
- package/src/generation/markers/actions/probability/MarkerNodeActionSelectWeighted.js +6 -4
- package/src/generation/markers/actions/probability/MarkerNodeActionWeightedElement.d.ts.map +1 -1
- package/src/generation/markers/actions/probability/MarkerNodeActionWeightedElement.js +1 -3
- package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.d.ts.map +1 -1
- package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.js +12 -11
- package/src/generation/markers/matcher/MarkerNodeMatcherAnd.js +2 -2
- package/src/generation/markers/transform/MarkerNodeTransformer.d.ts +4 -1
- package/src/generation/markers/transform/MarkerNodeTransformer.d.ts.map +1 -1
- package/src/generation/markers/transform/MarkerNodeTransformer.js +4 -1
- package/src/generation/markers/transform/MarkerNodeTransformerAddPositionYFromFilter.d.ts.map +1 -1
- package/src/generation/markers/transform/MarkerNodeTransformerAddPositionYFromFilter.js +1 -3
- package/src/generation/markers/transform/MarkerNodeTransformerOffsetPosition.d.ts +5 -0
- package/src/generation/markers/transform/MarkerNodeTransformerOffsetPosition.d.ts.map +1 -1
- package/src/generation/markers/transform/MarkerNodeTransformerOffsetPosition.js +15 -0
- package/src/generation/markers/transform/MarkerNodeTransformerRecordProperty.d.ts.map +1 -1
- package/src/generation/markers/transform/MarkerNodeTransformerRecordProperty.js +1 -3
- package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilter.d.ts.map +1 -1
- package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilter.js +2 -4
- package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilterGradient.d.ts.map +1 -1
- package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilterGradient.js +1 -3
- package/src/generation/placement/GridCellPlacementRule.d.ts.map +1 -1
- package/src/generation/placement/GridCellPlacementRule.js +1 -3
- package/src/generation/placement/action/GridCellActionWriteFilterToLayer.d.ts.map +1 -1
- package/src/generation/placement/action/GridCellActionWriteFilterToLayer.js +8 -10
- package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.d.ts.map +1 -1
- package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.js +6 -4
- package/src/generation/placement/action/random/weighted/WeightedGridCellAction.d.ts.map +1 -1
- package/src/generation/placement/action/random/weighted/WeightedGridCellAction.js +1 -3
- package/src/generation/rules/CellMatcher.d.ts +3 -1
- package/src/generation/rules/CellMatcher.d.ts.map +1 -1
- package/src/generation/rules/CellMatcher.js +3 -1
- package/src/generation/rules/CellMatcherFromFilter.d.ts.map +1 -1
- package/src/generation/rules/CellMatcherFromFilter.js +1 -3
- package/src/generation/rules/CellMatcherLayerBitMaskTest.d.ts.map +1 -1
- package/src/generation/rules/CellMatcherLayerBitMaskTest.js +6 -20
- package/src/generation/test_support/executeTaskTreeSync.d.ts +9 -0
- package/src/generation/test_support/executeTaskTreeSync.d.ts.map +1 -0
- package/src/generation/test_support/executeTaskTreeSync.js +78 -0
- package/src/generation/theme/TerrainLayerRuleAggregator.d.ts +2 -1
- package/src/generation/theme/TerrainLayerRuleAggregator.d.ts.map +1 -1
- package/src/generation/theme/TerrainLayerRuleAggregator.js +9 -6
- package/src/generation/theme/Theme.d.ts +1 -1
- package/src/generation/theme/Theme.d.ts.map +1 -1
- package/src/generation/theme/Theme.js +2 -2
- package/src/generation/theme/ThemeEngine.d.ts +3 -3
- package/src/generation/theme/ThemeEngine.d.ts.map +1 -1
- package/src/generation/theme/ThemeEngine.js +26 -16
- package/src/generation/theme/cell/CellProcessingRule.d.ts +3 -3
- package/src/generation/theme/cell/CellProcessingRule.d.ts.map +1 -1
- package/src/generation/theme/cell/CellProcessingRule.js +6 -10
- package/src/generation/theme/cell/CellProcessingRuleSet.d.ts +1 -1
- package/src/generation/theme/cell/CellProcessingRuleSet.d.ts.map +1 -1
- package/src/generation/theme/cell/CellProcessingRuleSet.js +2 -2
- package/src/view/common/ListView.js +1 -1
- package/src/view/elements/BottomLeftResizeHandleView.d.ts.map +1 -1
- package/src/view/elements/BottomLeftResizeHandleView.js +13 -5
- package/src/core/font/FontAsset.d.ts.map +0 -1
- package/src/core/font/FontAssetLoader.d.ts.map +0 -1
- package/src/core/geom/3d/shape/util/shape_to_visual_entity.d.ts.map +0 -1
- package/src/core/geom/3d/tetrahedra/visualize_tetrahedral_mesh.d.ts.map +0 -1
- package/src/core/process/action/AsynchronousDelayAction.d.ts.map +0 -1
- package/src/engine/graphics/sh3/path_tracer/sampling/v3_orthonormal_matrix_from_normal.d.ts.map +0 -1
- package/src/engine/physics/computeInterceptPoint.d.ts.map +0 -1
- package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts.map +0 -1
- package/src/engine/physics/gjk/gjk.d.ts.map +0 -1
- package/src/engine/physics/gjk/gjk_epa_penetration.d.ts.map +0 -1
- package/src/engine/physics/gjk/minkowski_support.d.ts.map +0 -1
- package/src/engine/physics/gjk/mpr.d.ts.map +0 -1
- package/src/engine/physics/integration/quat_integrate.d.ts.map +0 -1
- package/src/engine/physics/island/union_find.d.ts.map +0 -1
- package/src/engine/physics/narrowphase/clip_against_axis_uv.d.ts.map +0 -1
- package/src/engine/physics/narrowphase/decomposition/aabb_world_to_local.d.ts.map +0 -1
- package/src/engine/physics/narrowphase/ray_shapes.d.ts +0 -66
- package/src/engine/physics/narrowphase/ray_shapes.d.ts.map +0 -1
- package/src/engine/physics/narrowphase/ray_shapes.js +0 -187
- package/src/engine/sound/ecs/emitter/SoundEmitterChannel.d.ts +0 -23
- package/src/engine/sound/ecs/emitter/SoundEmitterChannel.d.ts.map +0 -1
- package/src/engine/sound/ecs/emitter/SoundEmitterChannel.js +0 -32
- package/src/engine/sound/ecs/emitter/SoundTrackNodes.d.ts +0 -18
- package/src/engine/sound/ecs/emitter/SoundTrackNodes.d.ts.map +0 -1
- package/src/engine/sound/ecs/emitter/SoundTrackNodes.js +0 -18
- package/src/engine/sound/sopra/AbstractAudioClip.d.ts +0 -26
- package/src/engine/sound/sopra/AbstractAudioClip.d.ts.map +0 -1
- package/src/engine/sound/sopra/AbstractAudioClip.js +0 -29
- package/src/engine/sound/sopra/ContainerAudioClip.d.ts +0 -12
- package/src/engine/sound/sopra/ContainerAudioClip.d.ts.map +0 -1
- package/src/engine/sound/sopra/ContainerAudioClip.js +0 -13
- package/src/engine/sound/sopra/RandomContainerAudioClip.d.ts +0 -12
- package/src/engine/sound/sopra/RandomContainerAudioClip.d.ts.map +0 -1
- package/src/engine/sound/sopra/RandomContainerAudioClip.js +0 -15
- package/src/engine/sound/sopra/SequenceContainerAudioClip.d.ts +0 -7
- package/src/engine/sound/sopra/SequenceContainerAudioClip.d.ts.map +0 -1
- package/src/engine/sound/sopra/SequenceContainerAudioClip.js +0 -8
- package/src/engine/sound/sopra/SilenceAudioClip.d.ts +0 -13
- package/src/engine/sound/sopra/SilenceAudioClip.d.ts.map +0 -1
- package/src/engine/sound/sopra/SilenceAudioClip.js +0 -15
- package/src/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.d.ts +0 -21
- package/src/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.d.ts.map +0 -1
- package/src/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.js +0 -68
- package/src/generation/grid/generation/grid/GridTaskGridAlignedNodeGenerator.d.ts +0 -10
- package/src/generation/grid/generation/grid/GridTaskGridAlignedNodeGenerator.d.ts.map +0 -1
- package/src/generation/grid/generation/grid/GridTaskGridAlignedNodeGenerator.js +0 -17
- /package/src/{engine/physics → core/geom/3d}/gjk/NOTES.md +0 -0
- /package/src/{engine/physics → core/geom/3d}/gjk/gjk.d.ts +0 -0
- /package/src/{engine/graphics/sh3/path_tracer/sampling → core/geom/vec3}/v3_orthonormal_matrix_from_normal.d.ts +0 -0
- /package/src/{engine/physics → core/math/physics/kinematics}/computeInterceptPoint.d.ts +0 -0
|
@@ -1,1747 +1,2172 @@
|
|
|
1
|
-
import { assert } from "../../../core/assert.js";
|
|
2
|
-
import { BinaryBuffer } from "../../../core/binary/BinaryBuffer.js";
|
|
3
|
-
import { BVH } from "../../../core/bvh2/bvh3/BVH.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
45
|
-
import {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
* @
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
*
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
* @type {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
*
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
*
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
*
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
*
|
|
216
|
-
* @
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
* @type {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
*
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
* @type {
|
|
251
|
-
*/
|
|
252
|
-
this.
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
*
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
*
|
|
293
|
-
* @
|
|
294
|
-
*/
|
|
295
|
-
this.
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
* @
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
*
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
*
|
|
501
|
-
* @param {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
this.
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
this.
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
*
|
|
572
|
-
*
|
|
573
|
-
*
|
|
574
|
-
*
|
|
575
|
-
*
|
|
576
|
-
* @
|
|
577
|
-
* @param {
|
|
578
|
-
* @param {number}
|
|
579
|
-
*/
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
*
|
|
603
|
-
*
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
*
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
//
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
*
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
);
|
|
764
|
-
|
|
765
|
-
this.
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
*
|
|
792
|
-
*
|
|
793
|
-
*
|
|
794
|
-
*
|
|
795
|
-
*
|
|
796
|
-
*
|
|
797
|
-
*
|
|
798
|
-
* @param {
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
*
|
|
862
|
-
*
|
|
863
|
-
*
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
*
|
|
906
|
-
*
|
|
907
|
-
* @param {
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
rigidBody.
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
*
|
|
973
|
-
*
|
|
974
|
-
*
|
|
975
|
-
*
|
|
976
|
-
*
|
|
977
|
-
*
|
|
978
|
-
*
|
|
979
|
-
*
|
|
980
|
-
* @
|
|
981
|
-
* @param {
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
*
|
|
1036
|
-
*
|
|
1037
|
-
* @
|
|
1038
|
-
*
|
|
1039
|
-
*
|
|
1040
|
-
*
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
*
|
|
1048
|
-
*
|
|
1049
|
-
*
|
|
1050
|
-
*
|
|
1051
|
-
*
|
|
1052
|
-
*
|
|
1053
|
-
*
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
*
|
|
1107
|
-
*
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
*
|
|
1116
|
-
*
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
*
|
|
1143
|
-
*
|
|
1144
|
-
*
|
|
1145
|
-
*
|
|
1146
|
-
*
|
|
1147
|
-
*
|
|
1148
|
-
*
|
|
1149
|
-
*
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
*
|
|
1190
|
-
*
|
|
1191
|
-
*
|
|
1192
|
-
*
|
|
1193
|
-
*
|
|
1194
|
-
*
|
|
1195
|
-
*
|
|
1196
|
-
*
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
const
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
|
-
/**
|
|
1265
|
-
*
|
|
1266
|
-
*
|
|
1267
|
-
*
|
|
1268
|
-
*
|
|
1269
|
-
*
|
|
1270
|
-
*
|
|
1271
|
-
*
|
|
1272
|
-
*
|
|
1273
|
-
*
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
*
|
|
1345
|
-
*
|
|
1346
|
-
*
|
|
1347
|
-
*
|
|
1348
|
-
*
|
|
1349
|
-
*
|
|
1350
|
-
*
|
|
1351
|
-
* @
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
const
|
|
1364
|
-
const
|
|
1365
|
-
const
|
|
1366
|
-
|
|
1367
|
-
for (let i = 0; i <
|
|
1368
|
-
const
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
//
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
const
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
const
|
|
1441
|
-
const
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
const
|
|
1445
|
-
const
|
|
1446
|
-
const
|
|
1447
|
-
const
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
const
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
const
|
|
1559
|
-
|
|
1560
|
-
if (
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
const
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
}
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
this.
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1
|
+
import { assert } from "../../../core/assert.js";
|
|
2
|
+
import { BinaryBuffer } from "../../../core/binary/BinaryBuffer.js";
|
|
3
|
+
import { BVH } from "../../../core/bvh2/bvh3/BVH.js";
|
|
4
|
+
import { bvh_query_user_data_overlaps_aabb } from "../../../core/bvh2/bvh3/query/bvh_query_user_data_overlaps_aabb.js";
|
|
5
|
+
import { returnTrue } from "../../../core/function/returnTrue.js";
|
|
6
|
+
import { aabb3_transform_oriented } from "../../../core/geom/3d/aabb/aabb3_transform_oriented.js";
|
|
7
|
+
import Vector3 from "../../../core/geom/Vector3.js";
|
|
8
|
+
import { ResourceAccessKind } from "../../../core/model/ResourceAccessKind.js";
|
|
9
|
+
import { ResourceAccessSpecification } from "../../../core/model/ResourceAccessSpecification.js";
|
|
10
|
+
import { System } from "../../ecs/System.js";
|
|
11
|
+
import { Transform } from "../../ecs/transform/Transform.js";
|
|
12
|
+
import { Interpolated } from "../../interpolation/Interpolated.js";
|
|
13
|
+
import { body_id_index, BodyStorage } from "../body/BodyStorage.js";
|
|
14
|
+
import { SBS_STRIDE, SolverBodyState } from "../body/SolverBodyState.js";
|
|
15
|
+
import { compute_world_aabb, fatten_world_aabb } from "../broadphase/compute_fat_world_aabb.js";
|
|
16
|
+
import { generate_pairs } from "../broadphase/generate_pairs.js";
|
|
17
|
+
import { PairList } from "../broadphase/PairList.js";
|
|
18
|
+
import { ccd_resolve } from "../ccd/linear_sweep.js";
|
|
19
|
+
import { solve_joints } from "../constraint/solve_constraints.js";
|
|
20
|
+
import { ManifoldStore } from "../contact/ManifoldStore.js";
|
|
21
|
+
import { ContactEventBuffer, ContactEventKind } from "../events/ContactEventBuffer.js";
|
|
22
|
+
import { diff_manifolds } from "../events/diff_manifolds.js";
|
|
23
|
+
import { world_inverse_inertia_apply } from "../inertia/world_inverse_inertia.js";
|
|
24
|
+
import { integrate_position } from "../integration/integrate_position.js";
|
|
25
|
+
import { integrate_velocity_forces, integrate_velocity_gravity } from "../integration/integrate_velocity.js";
|
|
26
|
+
import { IslandBuilder } from "../island/IslandBuilder.js";
|
|
27
|
+
import { narrowphase_step } from "../narrowphase/narrowphase_step.js";
|
|
28
|
+
import { overlap_shape as overlap_shape_query } from "../queries/overlap_shape.js";
|
|
29
|
+
import { raycast as raycast_query } from "../queries/raycast.js";
|
|
30
|
+
import { shape_cast as shape_cast_query } from "../queries/shape_cast.js";
|
|
31
|
+
import {
|
|
32
|
+
apply_restitution,
|
|
33
|
+
prepare_contacts,
|
|
34
|
+
redetect_concave_contacts,
|
|
35
|
+
refresh_contacts,
|
|
36
|
+
solve_position,
|
|
37
|
+
solve_velocity,
|
|
38
|
+
warm_start_contacts,
|
|
39
|
+
} from "../solver/solve_contacts.js";
|
|
40
|
+
import { BodyKind } from "./BodyKind.js";
|
|
41
|
+
import { Collider, COLLIDER_UNBOUND } from "./Collider.js";
|
|
42
|
+
import { find_non_finite_physics_state } from "./find_non_finite_physics_state.js";
|
|
43
|
+
import { JOINT_UNALLOCATED, JOINT_WORLD } from "./Joint.js";
|
|
44
|
+
import { PhysicsEvents } from "./PhysicsEvents.js";
|
|
45
|
+
import { RIGID_BODY_UNALLOCATED, RigidBody } from "./RigidBody.js";
|
|
46
|
+
import { RigidBodyFlags } from "./RigidBodyFlags.js";
|
|
47
|
+
import { SleepState } from "./SleepState.js";
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Scratch for {@link applyImpulseAt}'s angular delta calculation.
|
|
51
|
+
* @type {Float64Array}
|
|
52
|
+
*/
|
|
53
|
+
const scratch_angular_delta = new Float64Array(3);
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Scratch for {@link applyImpulseAt}'s LockRot*-masked inverse-inertia
|
|
57
|
+
* diagonal (the same mask {@link SolverBodyState#gather} applies).
|
|
58
|
+
* @type {{x: number, y: number, z: number}}
|
|
59
|
+
*/
|
|
60
|
+
const scratch_locked_inertia = { x: 0, y: 0, z: 0 };
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Reusable scratch buffer for world-AABB construction so the link path is
|
|
64
|
+
* allocation-free in steady state.
|
|
65
|
+
* @type {Float64Array}
|
|
66
|
+
*/
|
|
67
|
+
const scratch_world_aabb = new Float64Array(6);
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Reusable scratch buffer for the local AABB returned by
|
|
71
|
+
* {@link AbstractShape3D#compute_bounding_box}.
|
|
72
|
+
* @type {Float64Array}
|
|
73
|
+
*/
|
|
74
|
+
const scratch_local_aabb = new Float64Array(6);
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Candidate buffer for {@link PhysicsSystem#__wake_sleepers_overlapping_leaf}.
|
|
78
|
+
* Grows by doubling: a large removed support (a level floor) can overlap many
|
|
79
|
+
* sleeping bodies, all of which must wake.
|
|
80
|
+
* @type {Uint32Array}
|
|
81
|
+
*/
|
|
82
|
+
let scratch_wake_candidates = new Uint32Array(64);
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Scratch for a leaf's currently-stored fat AABB during the stage-2
|
|
86
|
+
* containment test (refit skip).
|
|
87
|
+
* @type {Float64Array}
|
|
88
|
+
*/
|
|
89
|
+
const scratch_stored_aabb = new Float64Array(6);
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Scratch boxes for {@link PhysicsSystem#__swept_proximity} — the mover's
|
|
93
|
+
* velocity-swept tight AABB and the sleeper's tight AABB.
|
|
94
|
+
* @type {Float64Array}
|
|
95
|
+
*/
|
|
96
|
+
const scratch_prox_mover = new Float64Array(6);
|
|
97
|
+
const scratch_prox_sleeper = new Float64Array(6);
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Rigid-body physics system.
|
|
101
|
+
*
|
|
102
|
+
* v1 scope: pool + active list + two BVHs (static / dynamic), Transform sync
|
|
103
|
+
* contract, and the user-facing API surface (gravity, force / impulse, layer
|
|
104
|
+
* filtering, wake / sleep, contact filter). The per-step simulation pipeline
|
|
105
|
+
* (broadphase pair generation, narrowphase, solver, islands, sleep test,
|
|
106
|
+
* contact-event emission) is built on top of this skeleton in subsequent
|
|
107
|
+
* iterations.
|
|
108
|
+
*
|
|
109
|
+
* Dependency tuple is `(RigidBody, Collider, Transform)` — every body has
|
|
110
|
+
* exactly one collider on the same entity. Compound bodies via child collider
|
|
111
|
+
* entities are an extension point handled by a follow-up sub-observer.
|
|
112
|
+
*
|
|
113
|
+
* @author Alex Goldring
|
|
114
|
+
* @copyright Company Named Limited (c) 2026
|
|
115
|
+
*/
|
|
116
|
+
export class PhysicsSystem extends System {
|
|
117
|
+
|
|
118
|
+
constructor() {
|
|
119
|
+
super();
|
|
120
|
+
|
|
121
|
+
this.dependencies = [RigidBody, Transform];
|
|
122
|
+
|
|
123
|
+
this.components_used = [
|
|
124
|
+
ResourceAccessSpecification.from(RigidBody, ResourceAccessKind.Read | ResourceAccessKind.Write),
|
|
125
|
+
ResourceAccessSpecification.from(Collider, ResourceAccessKind.Read),
|
|
126
|
+
ResourceAccessSpecification.from(Transform, ResourceAccessKind.Read | ResourceAccessKind.Write),
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @type {BodyStorage}
|
|
131
|
+
* @readonly
|
|
132
|
+
*/
|
|
133
|
+
this.storage = new BodyStorage();
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @type {BVH}
|
|
137
|
+
*/
|
|
138
|
+
this.staticBvh = new BVH();
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @type {BVH}
|
|
142
|
+
*/
|
|
143
|
+
this.dynamicBvh = new BVH();
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Persistent contact-manifold cache. One slot per active pair.
|
|
147
|
+
* @type {ManifoldStore}
|
|
148
|
+
* @readonly
|
|
149
|
+
*/
|
|
150
|
+
this.manifolds = new ManifoldStore();
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Per-frame list of broadphase-overlapping pairs, each in
|
|
154
|
+
* entity-canonical role order (A = the smaller entity id — see
|
|
155
|
+
* generate_pairs). Cleared at the top of each step; purely
|
|
156
|
+
* intra-step state.
|
|
157
|
+
* @type {PairList}
|
|
158
|
+
*/
|
|
159
|
+
this.pairs = new PairList();
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Per-frame contact-event buffer. Populated by the manifold diff
|
|
163
|
+
* pass at end-of-step and consumed by the dispatch pass.
|
|
164
|
+
* @type {ContactEventBuffer}
|
|
165
|
+
*/
|
|
166
|
+
this.contactEvents = new ContactEventBuffer();
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Per-frame island partitioning of the awake-body + contact graph.
|
|
170
|
+
* Rebuilt after narrowphase, consumed by the solver (and, in the
|
|
171
|
+
* follow-up slice, by the per-island atomic sleep test). Bodies
|
|
172
|
+
* static and kinematic act as constraint anchors and do not enlarge
|
|
173
|
+
* islands.
|
|
174
|
+
* @type {IslandBuilder}
|
|
175
|
+
*/
|
|
176
|
+
this.islands = new IslandBuilder();
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Data-oriented mirror of the per-body solver hot state (velocity,
|
|
180
|
+
* inverse mass / inertia, orientation), packed into one ArrayBuffer
|
|
181
|
+
* and indexed by body slot. Gathered from the `RigidBody` /
|
|
182
|
+
* `Transform` components once per step (after islands are built),
|
|
183
|
+
* mutated in place by the TGS substep loop, and the persistent
|
|
184
|
+
* velocity scattered back at the end. Keeps the solver's hottest inner
|
|
185
|
+
* loop free of component-object dereferences.
|
|
186
|
+
* @type {SolverBodyState}
|
|
187
|
+
*/
|
|
188
|
+
this.__solver_state = new SolverBodyState();
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Velocity-squared threshold below which a body is eligible to start
|
|
192
|
+
* accumulating sleep time. Combined linear + angular kinetic-ish
|
|
193
|
+
* metric: `vx²+vy²+vz² + ωx²+ωy²+ωz²`. Default 0.01 corresponds to
|
|
194
|
+
* ~0.1 m/s linear or ~0.1 rad/s angular.
|
|
195
|
+
* @type {number}
|
|
196
|
+
*/
|
|
197
|
+
this.sleepVelocitySqrThreshold = 0.01;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Seconds of below-threshold motion before a body is moved to the
|
|
201
|
+
* sleeping set. Box2D default is 0.5 s.
|
|
202
|
+
* @type {number}
|
|
203
|
+
*/
|
|
204
|
+
this.sleepTimeThreshold = 0.5;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Number of TGS substeps per `fixedUpdate`. Each substep re-runs the
|
|
208
|
+
* velocity + position solve at `dt / substeps` against contacts whose
|
|
209
|
+
* penetration is re-derived analytically from the bodies' moved poses
|
|
210
|
+
* — narrowphase still runs once per outer step. Higher counts buy
|
|
211
|
+
* stack stability, high-mass-ratio robustness, and smoother
|
|
212
|
+
* trajectories at a near-linear solver cost (sleeping islands are
|
|
213
|
+
* unaffected — they never enter the loop).
|
|
214
|
+
*
|
|
215
|
+
* `1` reproduces the non-substepped (single-step) solve.
|
|
216
|
+
* @type {number}
|
|
217
|
+
*/
|
|
218
|
+
this.substeps = 4;
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Velocity iterations per substep. Lower than a single-step solver
|
|
222
|
+
* would need, because the substep loop revisits the contact set
|
|
223
|
+
* `substeps` times.
|
|
224
|
+
* @type {number}
|
|
225
|
+
*/
|
|
226
|
+
this.velocityIterations = 4;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Position (split-impulse) iterations per substep.
|
|
230
|
+
* @type {number}
|
|
231
|
+
*/
|
|
232
|
+
this.positionIterations = 1;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Contact softness frequency, Hz (Box2D-v3 soft step, hybrid form:
|
|
236
|
+
* the velocity rows get the hertz/ζ-derived mass + impulse-decay
|
|
237
|
+
* scales; penetration recovery stays in the split-impulse position
|
|
238
|
+
* pass). The decay term is what lets resting stacks converge
|
|
239
|
+
* asymptotically instead of ringing in the hard form's limit cycle
|
|
240
|
+
* just above the sleep threshold. Clamped per step to an eighth of
|
|
241
|
+
* the substep rate. `0` = hard contacts (bit-exact legacy rows).
|
|
242
|
+
* Pairs with a non-dynamic side use 2× this frequency (stiffer, so
|
|
243
|
+
* piles don't sag into the ground). @type {number}
|
|
244
|
+
*/
|
|
245
|
+
this.contactHertz = 30;
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Contact damping ratio ζ for the soft scales — heavily over-damped
|
|
249
|
+
* by design (Box2D v3 default), so contacts never oscillate.
|
|
250
|
+
* @type {number}
|
|
251
|
+
*/
|
|
252
|
+
this.contactDampingRatio = 10;
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Reusable contact-event payload. Listeners must copy any fields they
|
|
256
|
+
* intend to retain past their own scope. Reset before each dispatch.
|
|
257
|
+
* @private
|
|
258
|
+
*/
|
|
259
|
+
this.__contact_payload = {
|
|
260
|
+
entityA: -1,
|
|
261
|
+
entityB: -1,
|
|
262
|
+
kind: 0,
|
|
263
|
+
depth: 0,
|
|
264
|
+
normal: new Vector3(),
|
|
265
|
+
point: new Vector3(),
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* World gravity, m/s². Applied each step scaled by per-body gravityScale.
|
|
270
|
+
* @readonly
|
|
271
|
+
* @type {Vector3}
|
|
272
|
+
*/
|
|
273
|
+
this.gravity = new Vector3(0, -9.81, 0);
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Optional global contact filter. Called for each surviving broadphase
|
|
277
|
+
* pair; returning `false` discards the pair.
|
|
278
|
+
* @type {((entityA: number, entityB: number, colliderA: Collider, colliderB: Collider) => boolean) | null}
|
|
279
|
+
* @private
|
|
280
|
+
*/
|
|
281
|
+
this.__contact_filter = null;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Per-body component side-tables indexed by body index (NOT packed id).
|
|
285
|
+
* Sparse arrays — populated at link, cleared at unlink. The hot loop
|
|
286
|
+
* iterates `storage.awake_at(i)` and dereferences these.
|
|
287
|
+
* @type {RigidBody[]}
|
|
288
|
+
*/
|
|
289
|
+
this.__bodies = [];
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* @type {Transform[]}
|
|
293
|
+
* @readonly
|
|
294
|
+
*/
|
|
295
|
+
this.__transforms = [];
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Per-body list of attached colliders. Each entry stores the
|
|
299
|
+
* Collider component, its world Transform, the entity that owns
|
|
300
|
+
* it (the body entity for same-entity attachments, a child entity
|
|
301
|
+
* for compound bodies), and the BVH leaf id assigned at attach
|
|
302
|
+
* time. A body may have zero or more attached colliders.
|
|
303
|
+
*
|
|
304
|
+
* @type {Array<Array<{collider: Collider, transform: Transform, entity: number, bvhNode: number}>>}
|
|
305
|
+
*/
|
|
306
|
+
this.__body_collider_lists = [];
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Live {@link Joint} (6-DOF constraint) instances, in a sparse array
|
|
310
|
+
* indexed by joint id. Solved alongside contacts inside the TGS
|
|
311
|
+
* substep loop. Holes (unlinked joints) are `undefined`.
|
|
312
|
+
* @type {Joint[]}
|
|
313
|
+
*/
|
|
314
|
+
this.__joints = [];
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Lowest free index in {@link __joints} for slot reuse on link.
|
|
318
|
+
* @private
|
|
319
|
+
* @type {number}
|
|
320
|
+
*/
|
|
321
|
+
this.__joint_free = [];
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Live joints in CANONICAL SOLVE ORDER: ascending `(entityA,
|
|
325
|
+
* entityB)`, equal keys in link order. The id-indexed
|
|
326
|
+
* {@link __joints} registry reflects link/unlink HISTORY (slot
|
|
327
|
+
* reuse), which two engines holding identical joints need not
|
|
328
|
+
* share — the joint solver's Gauss-Seidel sweep must consume
|
|
329
|
+
* joints in an order derivable from state alone or the engines
|
|
330
|
+
* diverge. Maintained by {@link link_joint} / {@link unlink_joint};
|
|
331
|
+
* consumed by the substep loop. Multiple joints between the SAME
|
|
332
|
+
* entity pair keep their relative link order — reconstruction
|
|
333
|
+
* replays links in the same order, so that too is state-derived.
|
|
334
|
+
* @private
|
|
335
|
+
* @type {Joint[]}
|
|
336
|
+
*/
|
|
337
|
+
this.__joints_sorted = [];
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Velocity iterations per substep for the joint solver. Joints (and
|
|
341
|
+
* especially joint chains) want a few more iterations than contacts to
|
|
342
|
+
* propagate impulses along the chain; cheap because joints are far
|
|
343
|
+
* fewer than contacts.
|
|
344
|
+
* @type {number}
|
|
345
|
+
*/
|
|
346
|
+
this.jointIterations = 8;
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Per-body pseudo-velocity for the Catto split-impulse position
|
|
350
|
+
* pass (TGS Phase 1). Flat layout, 6 doubles per body slot index:
|
|
351
|
+
* `[lin.x, lin.y, lin.z, ang.x, ang.y, ang.z]`. Sized to
|
|
352
|
+
* `storage.high_water_mark * 6` at the top of each fixedUpdate
|
|
353
|
+
* and zeroed in place so unwritten slots contribute nothing to
|
|
354
|
+
* `integrate_position`.
|
|
355
|
+
*
|
|
356
|
+
* The solver writes during its position pass; `integrate_position`
|
|
357
|
+
* reads and folds into the pose update on the same tick, then
|
|
358
|
+
* the next tick's zero-pass wipes the state. It NEVER lands in
|
|
359
|
+
* `linearVelocity` / `angularVelocity` — that's the point of
|
|
360
|
+
* split impulse: depth correction does not contaminate persistent
|
|
361
|
+
* velocity (so a `restitution = 0` impact stops cleanly).
|
|
362
|
+
*
|
|
363
|
+
* @type {Float64Array}
|
|
364
|
+
*/
|
|
365
|
+
this.__pseudo_velocity = new Float64Array(0);
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Master switch for the continuous-collision pass. When false the
|
|
369
|
+
* {@link RigidBodyFlags.CCD} flag is ignored and no swept queries run.
|
|
370
|
+
* @type {boolean}
|
|
371
|
+
*/
|
|
372
|
+
this.ccdEnabled = true;
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Start-of-step world positions for CCD-flagged bodies — 3 doubles per
|
|
376
|
+
* body slot index (`[x, y, z]`). Captured in Stage 1 before the substep
|
|
377
|
+
* loop integrates poses; the CCD pass ({@link ccd_resolve}) sweeps from
|
|
378
|
+
* here to the final pose. Grows to `storage.high_water_mark * 3`; only
|
|
379
|
+
* CCD-flagged slots are written each step.
|
|
380
|
+
* @type {Float64Array}
|
|
381
|
+
*/
|
|
382
|
+
this.__ccd_start_pos = new Float64Array(0);
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Optional shared interpolation log to produce per-step pose snapshots
|
|
387
|
+
* into (the {@link InterpolationSystem}'s log). When set — and only then —
|
|
388
|
+
* each fixedUpdate restores every awake {@link Interpolated} body's live
|
|
389
|
+
* components from the previous tick (undoing render-time interpolation so
|
|
390
|
+
* the sim reads authoritative state), then records the post-step state
|
|
391
|
+
* under the current `entityManager.fixedStepTick`. Null on a headless /
|
|
392
|
+
* non-rendering world, where the producer work is skipped entirely.
|
|
393
|
+
* @type {InterpolationLog|null}
|
|
394
|
+
*/
|
|
395
|
+
this.interpolationLog = null;
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Reusable decode buffer for restoring interpolated snapshots.
|
|
399
|
+
* @private
|
|
400
|
+
* @type {BinaryBuffer}
|
|
401
|
+
*/
|
|
402
|
+
this.__interp_scratch = new BinaryBuffer();
|
|
403
|
+
this.__interp_scratch.fromArrayBuffer(new ArrayBuffer(256));
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Symmetric layer/mask check + optional user callback. Called per
|
|
408
|
+
* candidate pair during broadphase. Returns `true` to accept the pair.
|
|
409
|
+
*
|
|
410
|
+
* Layer/mask rule: pair (A, B) collides iff
|
|
411
|
+
* `(A.layer & B.mask) !== 0 && (B.layer & A.mask) !== 0`.
|
|
412
|
+
* The user's contact-filter callback is consulted only for pairs that
|
|
413
|
+
* pass the bitmask test (cheap gate first).
|
|
414
|
+
*
|
|
415
|
+
* @private
|
|
416
|
+
* @param {number} idA packed body id
|
|
417
|
+
* @param {number} idB packed body id
|
|
418
|
+
* @returns {boolean}
|
|
419
|
+
*/
|
|
420
|
+
__pair_filter(idA, idB) {
|
|
421
|
+
const idxA = body_id_index(idA);
|
|
422
|
+
const idxB = body_id_index(idB);
|
|
423
|
+
|
|
424
|
+
const rbA = this.__bodies[idxA];
|
|
425
|
+
const rbB = this.__bodies[idxB];
|
|
426
|
+
|
|
427
|
+
if (rbA === undefined || rbB === undefined) {
|
|
428
|
+
return false;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Layer/mask gate (symmetric).
|
|
432
|
+
if (((rbA.layer & rbB.mask) | 0) === 0) {
|
|
433
|
+
return false;
|
|
434
|
+
}
|
|
435
|
+
if (((rbB.layer & rbA.mask) | 0) === 0) {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// User callback gate, if installed.
|
|
440
|
+
const fn = this.__contact_filter;
|
|
441
|
+
if (fn !== null) {
|
|
442
|
+
const entA = this.storage.entity_at(idxA);
|
|
443
|
+
const entB = this.storage.entity_at(idxB);
|
|
444
|
+
const colA = this.__primary_collider(idxA);
|
|
445
|
+
const colB = this.__primary_collider(idxB);
|
|
446
|
+
if (!fn(entA, entB, colA, colB)) return false;
|
|
447
|
+
}
|
|
448
|
+
return true;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* First attached collider of a body, or `null` if none. Used for
|
|
453
|
+
* body-level checks that aren't yet per-collider: the sensor flag, the
|
|
454
|
+
* concave-shape dispatch flag, and the contact-filter callback's
|
|
455
|
+
* `colliderA` / `colliderB` arguments. Contact **materials** (friction /
|
|
456
|
+
* restitution) are NOT read here — the narrowphase tracks the specific
|
|
457
|
+
* source collider on each side of every contact and stamps the combined
|
|
458
|
+
* coefficients into the manifold per contact, so mixed-material compound
|
|
459
|
+
* bodies are accurate. (Per-contact source colliders for the filter
|
|
460
|
+
* callback / sensor flag remain a follow-up.)
|
|
461
|
+
*
|
|
462
|
+
* @private
|
|
463
|
+
* @param {number} body_idx
|
|
464
|
+
* @returns {Collider|null}
|
|
465
|
+
*/
|
|
466
|
+
__primary_collider(body_idx) {
|
|
467
|
+
const list = this.__body_collider_lists[body_idx];
|
|
468
|
+
return (list !== undefined && list.length > 0) ? list[0].collider : null;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Resize {@link __pseudo_velocity} to cover every live body slot and
|
|
473
|
+
* zero its contents. Called at the top of each fixedUpdate so the
|
|
474
|
+
* split-impulse position pass starts from a clean state — bodies the
|
|
475
|
+
* solver doesn't touch contribute zero pseudo-velocity to
|
|
476
|
+
* {@link integrate_position}.
|
|
477
|
+
*
|
|
478
|
+
* Doubles on growth like the other physics scratches; never shrinks.
|
|
479
|
+
*
|
|
480
|
+
* @private
|
|
481
|
+
*/
|
|
482
|
+
__reset_pseudo_velocity() {
|
|
483
|
+
const required = this.storage.high_water_mark * 6;
|
|
484
|
+
if (this.__pseudo_velocity.length < required) {
|
|
485
|
+
this.__pseudo_velocity = new Float64Array(required * 2);
|
|
486
|
+
} else if (required > 0) {
|
|
487
|
+
this.__pseudo_velocity.fill(0, 0, required);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Replace the world gravity vector. Effective on the next step.
|
|
493
|
+
* @param {Vector3|{x:number,y:number,z:number}} v
|
|
494
|
+
*/
|
|
495
|
+
setGravity(v) {
|
|
496
|
+
this.gravity.set(v.x, v.y, v.z);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Install (or remove with `null`) the contact filter callback.
|
|
501
|
+
* @param {((entityA:number, entityB:number, colliderA:Collider, colliderB:Collider) => boolean) | null} fn
|
|
502
|
+
*/
|
|
503
|
+
setContactFilter(fn) {
|
|
504
|
+
this.__contact_filter = fn;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* @returns {((entityA:number, entityB:number, colliderA:Collider, colliderB:Collider) => boolean) | null}
|
|
509
|
+
*/
|
|
510
|
+
getContactFilter() {
|
|
511
|
+
return this.__contact_filter;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* @private
|
|
516
|
+
* @param {RigidBody} rb
|
|
517
|
+
* @param {Collider} collider
|
|
518
|
+
* @param {Transform} transform
|
|
519
|
+
* @returns {number} BVH node id
|
|
520
|
+
*/
|
|
521
|
+
__insert_into_broadphase(rb, collider, transform) {
|
|
522
|
+
const shape = collider.shape;
|
|
523
|
+
|
|
524
|
+
assert.notNull(shape, 'Collider.shape must be set before attaching');
|
|
525
|
+
|
|
526
|
+
shape.compute_bounding_box(scratch_local_aabb);
|
|
527
|
+
|
|
528
|
+
const p = transform.position;
|
|
529
|
+
const q = transform.rotation;
|
|
530
|
+
|
|
531
|
+
aabb3_transform_oriented(
|
|
532
|
+
scratch_world_aabb, 0,
|
|
533
|
+
scratch_local_aabb[0], scratch_local_aabb[1], scratch_local_aabb[2],
|
|
534
|
+
scratch_local_aabb[3], scratch_local_aabb[4], scratch_local_aabb[5],
|
|
535
|
+
p.x, p.y, p.z,
|
|
536
|
+
q.x, q.y, q.z, q.w
|
|
537
|
+
);
|
|
538
|
+
|
|
539
|
+
const bvh = rb.kind === BodyKind.Static ? this.staticBvh : this.dynamicBvh;
|
|
540
|
+
const node = bvh.allocate_node();
|
|
541
|
+
|
|
542
|
+
bvh.node_set_aabb_primitive(
|
|
543
|
+
node,
|
|
544
|
+
scratch_world_aabb[0], scratch_world_aabb[1], scratch_world_aabb[2],
|
|
545
|
+
scratch_world_aabb[3], scratch_world_aabb[4], scratch_world_aabb[5]
|
|
546
|
+
);
|
|
547
|
+
bvh.node_set_user_data(node, rb._bodyId);
|
|
548
|
+
bvh.insert_leaf(node);
|
|
549
|
+
|
|
550
|
+
return node;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* @private
|
|
555
|
+
* @param {RigidBody} rb
|
|
556
|
+
* @param {number} node
|
|
557
|
+
*/
|
|
558
|
+
__remove_from_broadphase(rb, node) {
|
|
559
|
+
const bvh = rb.kind === BodyKind.Static ? this.staticBvh : this.dynamicBvh;
|
|
560
|
+
bvh.remove_leaf(node);
|
|
561
|
+
bvh.release_node(node);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Wake every sleeping dynamic body whose broadphase leaf overlaps the
|
|
566
|
+
* given leaf's AABB. Called BEFORE removing a NON-Dynamic body's leaf
|
|
567
|
+
* (unlink / collider detach): statics and kinematics join no sleep group,
|
|
568
|
+
* their sleepers' manifolds are dormant-frozen, and the broadphase never
|
|
569
|
+
* revisits sleeping bodies — so without this, a pile resting on the
|
|
570
|
+
* removed support would sleep in mid-air forever.
|
|
571
|
+
*
|
|
572
|
+
* Dynamic removals don't need it: a sleeping pile and its dynamic support
|
|
573
|
+
* slept as one island and share a sleep group, which unlink already
|
|
574
|
+
* dissolves by waking the group.
|
|
575
|
+
*
|
|
576
|
+
* @private
|
|
577
|
+
* @param {BVH} bvh tree currently holding `node`
|
|
578
|
+
* @param {number} node leaf about to be removed
|
|
579
|
+
*/
|
|
580
|
+
__wake_sleepers_overlapping_leaf(bvh, node) {
|
|
581
|
+
bvh.node_get_aabb(node, scratch_world_aabb);
|
|
582
|
+
|
|
583
|
+
let n;
|
|
584
|
+
for (;;) {
|
|
585
|
+
n = bvh_query_user_data_overlaps_aabb(scratch_wake_candidates, 0, this.dynamicBvh, scratch_world_aabb);
|
|
586
|
+
if (n <= scratch_wake_candidates.length) break;
|
|
587
|
+
// TRUE count returned, overflow writes dropped — grow and re-query.
|
|
588
|
+
scratch_wake_candidates = new Uint32Array(Math.max(n, scratch_wake_candidates.length * 2));
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
for (let i = 0; i < n; i++) {
|
|
592
|
+
const body_id = scratch_wake_candidates[i];
|
|
593
|
+
if (!this.storage.is_valid(body_id)) continue;
|
|
594
|
+
const rb = this.__bodies[body_id_index(body_id)];
|
|
595
|
+
if (rb === undefined) continue;
|
|
596
|
+
if (rb.sleepState !== SleepState.Sleeping) continue;
|
|
597
|
+
this.__wake_body(rb);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Lifecycle entry: invoked when an entity gains the (RigidBody, Transform)
|
|
603
|
+
* tuple. Allocates the body's slot in storage and seeds an empty collider
|
|
604
|
+
* list. Colliders are attached separately via {@link attach_collider} (the
|
|
605
|
+
* paired {@link ColliderObserverSystem} drives this from the dataset; in
|
|
606
|
+
* tests, call manually).
|
|
607
|
+
*
|
|
608
|
+
* @param {RigidBody} rigidBody
|
|
609
|
+
* @param {Transform} transform
|
|
610
|
+
* @param {number} entity
|
|
611
|
+
*/
|
|
612
|
+
link(rigidBody, transform, entity) {
|
|
613
|
+
const packed = this.storage.allocate(entity);
|
|
614
|
+
rigidBody._bodyId = packed;
|
|
615
|
+
|
|
616
|
+
const index = body_id_index(packed);
|
|
617
|
+
this.storage.set_kind(index, rigidBody.kind);
|
|
618
|
+
this.storage.set_flags(index, rigidBody.flags);
|
|
619
|
+
|
|
620
|
+
this.__bodies[index] = rigidBody;
|
|
621
|
+
this.__transforms[index] = transform;
|
|
622
|
+
this.__body_collider_lists[index] = [];
|
|
623
|
+
|
|
624
|
+
// The component's sleep fields are AUTHORITATIVE persistent state
|
|
625
|
+
// (see RigidBody.sleepState): a body restored from a snapshot — or
|
|
626
|
+
// re-linked after an unlink — resumes exactly as drowsy or asleep
|
|
627
|
+
// as it was, instead of being forced awake to re-settle. That keeps
|
|
628
|
+
// a reconstructed world on the original's wake/sleep schedule (the
|
|
629
|
+
// reconstruction-determinism contract). A freshly-constructed
|
|
630
|
+
// component defaults to Awake, so plain spawns are unchanged.
|
|
631
|
+
//
|
|
632
|
+
// A restored sleeper arrives as a sleep-group SINGLETON (the group
|
|
633
|
+
// links are world-instance-tied body indices, reset here); group
|
|
634
|
+
// membership is re-established by the contact-state import or, for
|
|
635
|
+
// a body slept in isolation, is already correct.
|
|
636
|
+
rigidBody.sleep_group_next = -1;
|
|
637
|
+
rigidBody.sleep_group_prev = -1;
|
|
638
|
+
|
|
639
|
+
// Static bodies do not need to live in the active list — they never move.
|
|
640
|
+
if (rigidBody.kind === BodyKind.Static
|
|
641
|
+
|| (rigidBody.kind === BodyKind.Dynamic && rigidBody.sleepState === SleepState.Sleeping)) {
|
|
642
|
+
this.storage.mark_sleeping(index);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Detach every collider attached to this body, free its slot, and clear
|
|
648
|
+
* the side-tables.
|
|
649
|
+
*
|
|
650
|
+
* @param {RigidBody} rigidBody
|
|
651
|
+
* @param {Transform} transform
|
|
652
|
+
* @param {number} entity
|
|
653
|
+
*/
|
|
654
|
+
unlink(rigidBody, transform, entity) {
|
|
655
|
+
const packed = rigidBody._bodyId;
|
|
656
|
+
|
|
657
|
+
assert.equal(this.storage.is_valid(packed), true, 'unlink: stale or absent body id');
|
|
658
|
+
|
|
659
|
+
// If the body is sleeping inside a multi-member sleep group, dissolve
|
|
660
|
+
// the group by waking every member first. Otherwise the surviving
|
|
661
|
+
// members would hold dangling indices in their sleep-group chain
|
|
662
|
+
// pointing at a slot that has just been freed.
|
|
663
|
+
if (rigidBody.sleep_group_next !== -1) {
|
|
664
|
+
this.__wake_body(rigidBody);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const index = body_id_index(packed);
|
|
668
|
+
const list = this.__body_collider_lists[index];
|
|
669
|
+
if (list !== undefined) {
|
|
670
|
+
// A removed static / kinematic body may have been the support
|
|
671
|
+
// under sleeping bodies — wake them before the leaves disappear
|
|
672
|
+
// (their AABBs are the query keys).
|
|
673
|
+
const wake_neighbours = rigidBody.kind !== BodyKind.Dynamic;
|
|
674
|
+
const bvh = rigidBody.kind === BodyKind.Static ? this.staticBvh : this.dynamicBvh;
|
|
675
|
+
for (let i = 0; i < list.length; i++) {
|
|
676
|
+
const entry = list[i];
|
|
677
|
+
if (entry.bvhNode !== COLLIDER_UNBOUND) {
|
|
678
|
+
if (wake_neighbours) {
|
|
679
|
+
this.__wake_sleepers_overlapping_leaf(bvh, entry.bvhNode);
|
|
680
|
+
}
|
|
681
|
+
this.__remove_from_broadphase(rigidBody, entry.bvhNode);
|
|
682
|
+
}
|
|
683
|
+
entry.collider._bvhNode = COLLIDER_UNBOUND;
|
|
684
|
+
entry.collider._bodyId = -1;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
this.__bodies[index] = undefined;
|
|
689
|
+
this.__transforms[index] = undefined;
|
|
690
|
+
this.__body_collider_lists[index] = undefined;
|
|
691
|
+
|
|
692
|
+
// Purge joints referencing the freed body. The solver already skips
|
|
693
|
+
// them via the generation-checked is_valid, but the 8-bit generation
|
|
694
|
+
// wraps after 256 reuse cycles of one slot (~seconds under a pooled
|
|
695
|
+
// spawner) — at which point a stale joint handle ALIASES an unrelated
|
|
696
|
+
// new body and silently reactivates against it. Removing the joint at
|
|
697
|
+
// the source closes the ABA window outright.
|
|
698
|
+
const joints = this.__joints;
|
|
699
|
+
for (let i = 0; i < joints.length; i++) {
|
|
700
|
+
const joint = joints[i];
|
|
701
|
+
if (joint === undefined || joint === null) continue;
|
|
702
|
+
if (joint._bodyIdA === packed || joint._bodyIdB === packed) {
|
|
703
|
+
this.unlink_joint(joint);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
this.storage.free(packed);
|
|
708
|
+
rigidBody._bodyId = RIGID_BODY_UNALLOCATED;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Attach a collider to an existing body. The collider can live on the
|
|
713
|
+
* same entity as the body (single-collider body) or on a child entity
|
|
714
|
+
* (compound body). The world transform passed here is the collider's
|
|
715
|
+
* own — for a same-entity collider it is the body's Transform; for a
|
|
716
|
+
* child collider it is the child entity's Transform.
|
|
717
|
+
*
|
|
718
|
+
* Idempotent — re-attaching the same collider is a no-op.
|
|
719
|
+
*
|
|
720
|
+
* @param {number} body_entity entity that owns the body
|
|
721
|
+
* @param {Collider} collider
|
|
722
|
+
* @param {Transform} transform world transform of the collider
|
|
723
|
+
* @param {number} [collider_entity] entity owning the collider (defaults to body_entity)
|
|
724
|
+
*/
|
|
725
|
+
attach_collider(body_entity, collider, transform, collider_entity = body_entity) {
|
|
726
|
+
// Find the body by walking the storage entity table. The body must
|
|
727
|
+
// have been allocated via `link` before any colliders are attached.
|
|
728
|
+
const body_index = this.__find_body_index_by_entity(body_entity);
|
|
729
|
+
assert.notEqual(body_index, -1, `attach_collider: no body found for entity ${body_entity}`);
|
|
730
|
+
|
|
731
|
+
const rb = this.__bodies[body_index];
|
|
732
|
+
// Idempotent: skip if collider already attached.
|
|
733
|
+
if (collider._bvhNode !== COLLIDER_UNBOUND) return;
|
|
734
|
+
|
|
735
|
+
const node = this.__insert_into_broadphase(rb, collider, transform);
|
|
736
|
+
|
|
737
|
+
collider._bvhNode = node;
|
|
738
|
+
collider._bodyId = rb._bodyId;
|
|
739
|
+
this.__body_collider_lists[body_index].push({
|
|
740
|
+
collider, transform, entity: collider_entity, bvhNode: node,
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Reverse of {@link attach_collider}. Idempotent.
|
|
746
|
+
*
|
|
747
|
+
* @param {number} body_entity
|
|
748
|
+
* @param {Collider} collider
|
|
749
|
+
*/
|
|
750
|
+
detach_collider(body_entity, collider) {
|
|
751
|
+
if (collider._bvhNode === COLLIDER_UNBOUND) return;
|
|
752
|
+
|
|
753
|
+
const body_index = this.__find_body_index_by_entity(body_entity);
|
|
754
|
+
if (body_index === -1) return;
|
|
755
|
+
|
|
756
|
+
const rb = this.__bodies[body_index];
|
|
757
|
+
// Same rule as unlink: removing a static / kinematic leaf may pull
|
|
758
|
+
// the support from under sleeping bodies — wake them first.
|
|
759
|
+
if (rb.kind !== BodyKind.Dynamic) {
|
|
760
|
+
const bvh = rb.kind === BodyKind.Static ? this.staticBvh : this.dynamicBvh;
|
|
761
|
+
this.__wake_sleepers_overlapping_leaf(bvh, collider._bvhNode);
|
|
762
|
+
}
|
|
763
|
+
this.__remove_from_broadphase(rb, collider._bvhNode);
|
|
764
|
+
|
|
765
|
+
const list = this.__body_collider_lists[body_index];
|
|
766
|
+
for (let i = 0; i < list.length; i++) {
|
|
767
|
+
if (list[i].collider === collider) {
|
|
768
|
+
list.splice(i, 1);
|
|
769
|
+
break;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
collider._bvhNode = COLLIDER_UNBOUND;
|
|
774
|
+
collider._bodyId = -1;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* Resolve an entity to its body index, or -1 if no live body owns it.
|
|
779
|
+
* O(1) via {@link BodyStorage#index_of_entity}'s entity → index map — used
|
|
780
|
+
* on the collider attach / detach and joint link paths.
|
|
781
|
+
*
|
|
782
|
+
* @private
|
|
783
|
+
* @param {number} entity
|
|
784
|
+
* @returns {number} body index or -1
|
|
785
|
+
*/
|
|
786
|
+
__find_body_index_by_entity(entity) {
|
|
787
|
+
return this.storage.index_of_entity(entity);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* Register a {@link Joint} (6-DOF constraint). Resolves the joint's
|
|
792
|
+
* entities to packed body ids and adds it to the active set, where it is
|
|
793
|
+
* solved alongside contacts in the TGS substep loop. Body A must be a
|
|
794
|
+
* linked body; body B is either a linked body or {@link JOINT_WORLD}
|
|
795
|
+
* (anchoring A to a fixed world point — `localAnchorB` is then a world
|
|
796
|
+
* coordinate).
|
|
797
|
+
*
|
|
798
|
+
* @param {Joint} joint
|
|
799
|
+
*/
|
|
800
|
+
link_joint(joint) {
|
|
801
|
+
const idxA = this.__find_body_index_by_entity(joint.entityA);
|
|
802
|
+
assert.notEqual(idxA, -1, `link_joint: no body for entityA ${joint.entityA}`);
|
|
803
|
+
joint._bodyIdA = this.__bodies[idxA]._bodyId;
|
|
804
|
+
|
|
805
|
+
if (joint.entityB === JOINT_WORLD) {
|
|
806
|
+
joint._bodyIdB = JOINT_WORLD;
|
|
807
|
+
} else {
|
|
808
|
+
const idxB = this.__find_body_index_by_entity(joint.entityB);
|
|
809
|
+
assert.notEqual(idxB, -1, `link_joint: no body for entityB ${joint.entityB}`);
|
|
810
|
+
joint._bodyIdB = this.__bodies[idxB]._bodyId;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// A (re-)linked joint starts cold: the accumulated warm-start impulse
|
|
814
|
+
// belongs to whatever configuration the joint solved BEFORE it was
|
|
815
|
+
// unlinked — replaying it against the new bodies is a phantom kick.
|
|
816
|
+
joint.dofImpulse.fill(0);
|
|
817
|
+
|
|
818
|
+
// Reuse a freed slot if available so joint ids stay dense-ish.
|
|
819
|
+
let id;
|
|
820
|
+
if (this.__joint_free.length > 0) {
|
|
821
|
+
id = this.__joint_free.pop();
|
|
822
|
+
} else {
|
|
823
|
+
id = this.__joints.length;
|
|
824
|
+
}
|
|
825
|
+
joint._jointId = id;
|
|
826
|
+
this.__joints[id] = joint;
|
|
827
|
+
|
|
828
|
+
// Insert at the upper bound of the joint's (entityA, entityB) key in
|
|
829
|
+
// the canonical solve-order list — equal keys keep link order.
|
|
830
|
+
const sorted = this.__joints_sorted;
|
|
831
|
+
let pos = sorted.length;
|
|
832
|
+
while (pos > 0) {
|
|
833
|
+
const prev = sorted[pos - 1];
|
|
834
|
+
if (prev.entityA < joint.entityA
|
|
835
|
+
|| (prev.entityA === joint.entityA && prev.entityB <= joint.entityB)) {
|
|
836
|
+
break;
|
|
837
|
+
}
|
|
838
|
+
pos--;
|
|
839
|
+
}
|
|
840
|
+
sorted.splice(pos, 0, joint);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Remove a previously {@link link_joint}'d joint from the active set.
|
|
845
|
+
* Idempotent.
|
|
846
|
+
* @param {Joint} joint
|
|
847
|
+
*/
|
|
848
|
+
unlink_joint(joint) {
|
|
849
|
+
const id = joint._jointId;
|
|
850
|
+
if (id === JOINT_UNALLOCATED || this.__joints[id] !== joint) return;
|
|
851
|
+
this.__joints[id] = undefined;
|
|
852
|
+
this.__joint_free.push(id);
|
|
853
|
+
joint._jointId = JOINT_UNALLOCATED;
|
|
854
|
+
|
|
855
|
+
const sorted = this.__joints_sorted;
|
|
856
|
+
const pos = sorted.indexOf(joint);
|
|
857
|
+
if (pos !== -1) sorted.splice(pos, 1);
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* Resolve a packed body id to its entity, or `-1` if the id is stale.
|
|
862
|
+
* @param {number} packed_body_id
|
|
863
|
+
* @returns {number}
|
|
864
|
+
*/
|
|
865
|
+
entityOf(packed_body_id) {
|
|
866
|
+
if (!this.storage.is_valid(packed_body_id)) return -1;
|
|
867
|
+
return this.storage.entity_at(body_id_index(packed_body_id));
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* Number of live bodies (regardless of awake/sleeping state).
|
|
872
|
+
* @returns {number}
|
|
873
|
+
*/
|
|
874
|
+
get bodyCount() {
|
|
875
|
+
return this.storage.size;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Apply an instantaneous change of momentum at the body's centre of mass.
|
|
880
|
+
* Linear-only — see {@link applyImpulseAt} for an off-centre impulse that
|
|
881
|
+
* also produces angular response.
|
|
882
|
+
*
|
|
883
|
+
* Wakes the body if it is asleep.
|
|
884
|
+
*
|
|
885
|
+
* @param {RigidBody} rigidBody
|
|
886
|
+
* @param {Vector3|{x:number,y:number,z:number}} impulse
|
|
887
|
+
*/
|
|
888
|
+
applyImpulse(rigidBody, impulse) {
|
|
889
|
+
if (rigidBody.kind !== BodyKind.Dynamic) {
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
const inv_m = rigidBody.mass > 0 ? 1 / rigidBody.mass : 0;
|
|
893
|
+
rigidBody.linearVelocity.addScaled(impulse, inv_m);
|
|
894
|
+
|
|
895
|
+
this.__wake_body(rigidBody);
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* Apply an instantaneous change of momentum at a specific world-space point.
|
|
900
|
+
* Off-centre impulses produce both linear (Δv = P/m) and angular
|
|
901
|
+
* (Δω = I_w⁻¹·(r × P)) response.
|
|
902
|
+
*
|
|
903
|
+
* Wakes the body if it is asleep.
|
|
904
|
+
*
|
|
905
|
+
* @param {RigidBody} rigidBody
|
|
906
|
+
* @param {Transform} transform body's current world Transform (used for r and I_w)
|
|
907
|
+
* @param {Vector3|{x:number,y:number,z:number}} impulse
|
|
908
|
+
* @param {Vector3|{x:number,y:number,z:number}} worldPoint
|
|
909
|
+
*/
|
|
910
|
+
applyImpulseAt(rigidBody, transform, impulse, worldPoint) {
|
|
911
|
+
if (rigidBody.kind !== BodyKind.Dynamic) {
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
const inv_m = rigidBody.mass > 0 ? 1 / rigidBody.mass : 0;
|
|
915
|
+
|
|
916
|
+
rigidBody.linearVelocity.set(
|
|
917
|
+
rigidBody.linearVelocity.x + impulse.x * inv_m,
|
|
918
|
+
rigidBody.linearVelocity.y + impulse.y * inv_m,
|
|
919
|
+
rigidBody.linearVelocity.z + impulse.z * inv_m
|
|
920
|
+
);
|
|
921
|
+
|
|
922
|
+
const rx = worldPoint.x - transform.position.x;
|
|
923
|
+
const ry = worldPoint.y - transform.position.y;
|
|
924
|
+
const rz = worldPoint.z - transform.position.z;
|
|
925
|
+
|
|
926
|
+
// Δω = I_w⁻¹ · (r × P)
|
|
927
|
+
const tx = ry * impulse.z - rz * impulse.y;
|
|
928
|
+
const ty = rz * impulse.x - rx * impulse.z;
|
|
929
|
+
const tz = rx * impulse.y - ry * impulse.x;
|
|
930
|
+
|
|
931
|
+
// LockRot* masks the BODY-LOCAL inverse-inertia diagonal here exactly
|
|
932
|
+
// as the solver gather does, so a user impulse cannot spin a locked
|
|
933
|
+
// DOF either.
|
|
934
|
+
const flags = rigidBody.flags;
|
|
935
|
+
const ii = rigidBody.inverseInertiaLocal;
|
|
936
|
+
scratch_locked_inertia.x = (flags & RigidBodyFlags.LockRotX) !== 0 ? 0 : ii.x;
|
|
937
|
+
scratch_locked_inertia.y = (flags & RigidBodyFlags.LockRotY) !== 0 ? 0 : ii.y;
|
|
938
|
+
scratch_locked_inertia.z = (flags & RigidBodyFlags.LockRotZ) !== 0 ? 0 : ii.z;
|
|
939
|
+
world_inverse_inertia_apply(scratch_angular_delta, 0, scratch_locked_inertia, transform.rotation, tx, ty, tz);
|
|
940
|
+
|
|
941
|
+
rigidBody.angularVelocity.set(
|
|
942
|
+
rigidBody.angularVelocity.x + scratch_angular_delta[0],
|
|
943
|
+
rigidBody.angularVelocity.y + scratch_angular_delta[1],
|
|
944
|
+
rigidBody.angularVelocity.z + scratch_angular_delta[2]
|
|
945
|
+
);
|
|
946
|
+
|
|
947
|
+
this.__wake_body(rigidBody);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
/**
|
|
951
|
+
* Accumulate a continuous torque (world-space) for integration on the
|
|
952
|
+
* next fixedUpdate. Pairs with {@link applyForce} for the rotational case.
|
|
953
|
+
*
|
|
954
|
+
* Wakes the body if asleep.
|
|
955
|
+
*
|
|
956
|
+
* @param {RigidBody} rigidBody
|
|
957
|
+
* @param {Vector3|{x:number,y:number,z:number}} torque
|
|
958
|
+
*/
|
|
959
|
+
applyTorque(rigidBody, torque) {
|
|
960
|
+
if (rigidBody.kind !== BodyKind.Dynamic) {
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
rigidBody.accumulatedTorque.set(
|
|
964
|
+
rigidBody.accumulatedTorque.x + torque.x,
|
|
965
|
+
rigidBody.accumulatedTorque.y + torque.y,
|
|
966
|
+
rigidBody.accumulatedTorque.z + torque.z
|
|
967
|
+
);
|
|
968
|
+
this.__wake_body(rigidBody);
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* Apply a continuous force at a specific world-space point. The force
|
|
973
|
+
* generates both a linear acceleration (F/m) and a torque (r × F) about
|
|
974
|
+
* the body's centre of mass.
|
|
975
|
+
*
|
|
976
|
+
* Wakes the body if asleep.
|
|
977
|
+
*
|
|
978
|
+
* @param {RigidBody} rigidBody
|
|
979
|
+
* @param {Transform} transform body's current world Transform
|
|
980
|
+
* @param {Vector3|{x:number,y:number,z:number}} force
|
|
981
|
+
* @param {Vector3|{x:number,y:number,z:number}} worldPoint
|
|
982
|
+
*/
|
|
983
|
+
applyForceAt(rigidBody, transform, force, worldPoint) {
|
|
984
|
+
if (rigidBody.kind !== BodyKind.Dynamic) {
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
rigidBody.accumulatedForce.set(
|
|
988
|
+
rigidBody.accumulatedForce.x + force.x,
|
|
989
|
+
rigidBody.accumulatedForce.y + force.y,
|
|
990
|
+
rigidBody.accumulatedForce.z + force.z
|
|
991
|
+
);
|
|
992
|
+
|
|
993
|
+
const rx = worldPoint.x - transform.position.x;
|
|
994
|
+
const ry = worldPoint.y - transform.position.y;
|
|
995
|
+
const rz = worldPoint.z - transform.position.z;
|
|
996
|
+
|
|
997
|
+
rigidBody.accumulatedTorque.set(
|
|
998
|
+
rigidBody.accumulatedTorque.x + (ry * force.z - rz * force.y),
|
|
999
|
+
rigidBody.accumulatedTorque.y + (rz * force.x - rx * force.z),
|
|
1000
|
+
rigidBody.accumulatedTorque.z + (rx * force.y - ry * force.x)
|
|
1001
|
+
);
|
|
1002
|
+
|
|
1003
|
+
this.__wake_body(rigidBody);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
/**
|
|
1007
|
+
* Accumulate a continuous force to be integrated next fixedUpdate step.
|
|
1008
|
+
* Wakes the body if asleep.
|
|
1009
|
+
*
|
|
1010
|
+
* @param {RigidBody} rigidBody
|
|
1011
|
+
* @param {Vector3|{x:number,y:number,z:number}} force
|
|
1012
|
+
*/
|
|
1013
|
+
applyForce(rigidBody, force) {
|
|
1014
|
+
if (rigidBody.kind !== BodyKind.Dynamic) {
|
|
1015
|
+
return;
|
|
1016
|
+
}
|
|
1017
|
+
rigidBody.accumulatedForce.add(force);
|
|
1018
|
+
this.__wake_body(rigidBody);
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
/**
|
|
1022
|
+
* Replace the linear velocity. Wakes the body if asleep.
|
|
1023
|
+
*
|
|
1024
|
+
* @param {RigidBody} rigidBody
|
|
1025
|
+
* @param {Vector3|{x:number,y:number,z:number}} v
|
|
1026
|
+
*/
|
|
1027
|
+
setLinearVelocity(rigidBody, v) {
|
|
1028
|
+
rigidBody.linearVelocity.copy(v);
|
|
1029
|
+
if (rigidBody.kind === BodyKind.Dynamic) {
|
|
1030
|
+
this.__wake_body(rigidBody);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
/**
|
|
1035
|
+
* Teleport a body to a new pose, bypassing integration: writes the body's
|
|
1036
|
+
* Transform directly and wakes it. For an interpolated body this also flags a
|
|
1037
|
+
* render `snap` on its {@link Interpolated} component, so the producer keeps
|
|
1038
|
+
* this pose (rather than restoring the previous tick over it) and the
|
|
1039
|
+
* renderer shows the new pose without sliding across the jump.
|
|
1040
|
+
*
|
|
1041
|
+
* This is the authoritative way to reposition an interpolated body — a raw
|
|
1042
|
+
* `Transform` write would be undone by the per-step restore. Velocity is left
|
|
1043
|
+
* as-is; zero it via {@link setLinearVelocity} if the teleport should also
|
|
1044
|
+
* stop the body.
|
|
1045
|
+
*
|
|
1046
|
+
* Works for STATIC bodies too: their broadphase leaves (which the step
|
|
1047
|
+
* never refits) are re-homed to the new pose, and sleeping bodies at both
|
|
1048
|
+
* the old and the new location are woken — a moved support drops what
|
|
1049
|
+
* rested on it, and whatever the static moved into must react.
|
|
1050
|
+
*
|
|
1051
|
+
* @param {RigidBody} rigidBody
|
|
1052
|
+
* @param {Vector3|{x:number,y:number,z:number}} position world position
|
|
1053
|
+
* @param {Quaternion|{x:number,y:number,z:number,w:number}} rotation world unit-quaternion rotation
|
|
1054
|
+
*/
|
|
1055
|
+
setPose(rigidBody, position, rotation) {
|
|
1056
|
+
const idx = body_id_index(rigidBody._bodyId);
|
|
1057
|
+
const transform = this.__transforms[idx];
|
|
1058
|
+
if (transform === undefined) {
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
transform.position.set(position.x, position.y, position.z);
|
|
1063
|
+
transform.rotation.set(rotation.x, rotation.y, rotation.z, rotation.w);
|
|
1064
|
+
|
|
1065
|
+
if (rigidBody.kind === BodyKind.Static) {
|
|
1066
|
+
// The step never refits a static's leaves (stage 2 covers awake
|
|
1067
|
+
// bodies only), so a moved static would keep its stale broadphase
|
|
1068
|
+
// AABB forever: nothing collides at the new location, ghost pairs
|
|
1069
|
+
// at the old one. Re-home each leaf now, and wake the sleepers at
|
|
1070
|
+
// BOTH locations — anything resting on the support that just
|
|
1071
|
+
// moved away, and anything the support just moved into.
|
|
1072
|
+
const list = this.__body_collider_lists[idx];
|
|
1073
|
+
if (list !== undefined) {
|
|
1074
|
+
for (let i = 0; i < list.length; i++) {
|
|
1075
|
+
const entry = list[i];
|
|
1076
|
+
if (entry.bvhNode === COLLIDER_UNBOUND) continue;
|
|
1077
|
+
this.__wake_sleepers_overlapping_leaf(this.staticBvh, entry.bvhNode);
|
|
1078
|
+
this.__remove_from_broadphase(rigidBody, entry.bvhNode);
|
|
1079
|
+
const node = this.__insert_into_broadphase(rigidBody, entry.collider, entry.transform);
|
|
1080
|
+
entry.bvhNode = node;
|
|
1081
|
+
entry.collider._bvhNode = node;
|
|
1082
|
+
this.__wake_sleepers_overlapping_leaf(this.staticBvh, node);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
} else {
|
|
1086
|
+
this.__wake_body(rigidBody);
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
// Flag a snap on the body's Interpolated component, if any, so the
|
|
1090
|
+
// interpolation producer (restore) and consumer (blend) treat this pose
|
|
1091
|
+
// as authoritative this frame instead of interpolating across the jump.
|
|
1092
|
+
const em = this.entityManager;
|
|
1093
|
+
if (em !== null && em !== undefined) {
|
|
1094
|
+
const dataset = em.dataset;
|
|
1095
|
+
if (dataset !== null && dataset !== undefined) {
|
|
1096
|
+
const entity = this.storage.entity_at(idx);
|
|
1097
|
+
const interpolated = dataset.getComponent(entity, Interpolated);
|
|
1098
|
+
if (interpolated !== undefined && interpolated !== null) {
|
|
1099
|
+
interpolated.snap = true;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
/**
|
|
1106
|
+
* Force the body awake. Static bodies are ignored.
|
|
1107
|
+
* @param {RigidBody} rigidBody
|
|
1108
|
+
*/
|
|
1109
|
+
wake(rigidBody) {
|
|
1110
|
+
this.__wake_body(rigidBody);
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
/**
|
|
1114
|
+
* Force the body asleep. Dynamic bodies will not re-enter the active list
|
|
1115
|
+
* until a wake event occurs.
|
|
1116
|
+
* @param {RigidBody} rigidBody
|
|
1117
|
+
*/
|
|
1118
|
+
sleep(rigidBody) {
|
|
1119
|
+
if (rigidBody.kind !== BodyKind.Dynamic) {
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1122
|
+
if (rigidBody.sleepState === SleepState.Sleeping) {
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
// An unlinked (or stale) body has no storage slot — indexing with its
|
|
1126
|
+
// dead id would corrupt the awake-list bookkeeping of whatever body
|
|
1127
|
+
// now owns that index.
|
|
1128
|
+
if (!this.storage.is_valid(rigidBody._bodyId)) {
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1131
|
+
rigidBody.sleepState = SleepState.Sleeping;
|
|
1132
|
+
const index = body_id_index(rigidBody._bodyId);
|
|
1133
|
+
this.storage.mark_sleeping(index);
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
/**
|
|
1137
|
+
* Wake a body and atomically wake every other body it was last sleeping
|
|
1138
|
+
* with (its "sleep group"). Sleep groups are circular doubly-linked lists
|
|
1139
|
+
* threaded through every member of an island when it sleeps atomically;
|
|
1140
|
+
* waking any one member walks the chain and wakes the rest in the same
|
|
1141
|
+
* call.
|
|
1142
|
+
*
|
|
1143
|
+
* Without this, a 100-block stack hit at the base would wake one block
|
|
1144
|
+
* per frame as the broadphase propagated awareness up the stack — a
|
|
1145
|
+
* visible ~1.6 s wave at 60 fps. Atomic wake eliminates the wave.
|
|
1146
|
+
*
|
|
1147
|
+
* No-op for non-dynamic bodies. Idempotent for already-awake bodies.
|
|
1148
|
+
* @private
|
|
1149
|
+
* @param {RigidBody} rb
|
|
1150
|
+
*/
|
|
1151
|
+
__wake_body(rb) {
|
|
1152
|
+
if (rb.kind !== BodyKind.Dynamic) return;
|
|
1153
|
+
if (rb.sleepState === SleepState.Awake) return;
|
|
1154
|
+
// Same stale-id guard as sleep(): an unlinked body's dead id must not
|
|
1155
|
+
// index into (and corrupt) another body's awake-list slot.
|
|
1156
|
+
if (!this.storage.is_valid(rb._bodyId)) return;
|
|
1157
|
+
const index = body_id_index(rb._bodyId);
|
|
1158
|
+
|
|
1159
|
+
// Remember the next-in-chain before clearing the body's own pointers;
|
|
1160
|
+
// the rest of the group is reached by walking forward from there.
|
|
1161
|
+
const start_next = rb.sleep_group_next;
|
|
1162
|
+
|
|
1163
|
+
rb.sleepState = SleepState.Awake;
|
|
1164
|
+
rb.sleep_timer = 0;
|
|
1165
|
+
rb.sleep_group_next = -1;
|
|
1166
|
+
rb.sleep_group_prev = -1;
|
|
1167
|
+
this.storage.mark_awake(index);
|
|
1168
|
+
|
|
1169
|
+
if (start_next === -1 || start_next === index) return;
|
|
1170
|
+
|
|
1171
|
+
// Walk the (now-broken) chain forward until we loop back. The chain
|
|
1172
|
+
// is circular so we know when to stop; defensive `-1` guards against
|
|
1173
|
+
// corruption from a body being unlinked mid-sleep-group.
|
|
1174
|
+
let cur = start_next;
|
|
1175
|
+
while (cur !== -1 && cur !== index) {
|
|
1176
|
+
const cur_rb = this.__bodies[cur];
|
|
1177
|
+
if (cur_rb === undefined) break;
|
|
1178
|
+
const nxt = cur_rb.sleep_group_next;
|
|
1179
|
+
cur_rb.sleepState = SleepState.Awake;
|
|
1180
|
+
cur_rb.sleep_timer = 0;
|
|
1181
|
+
cur_rb.sleep_group_next = -1;
|
|
1182
|
+
cur_rb.sleep_group_prev = -1;
|
|
1183
|
+
this.storage.mark_awake(cur);
|
|
1184
|
+
cur = nxt;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
/**
|
|
1189
|
+
* Atomically put every body in a contiguous range of island members to
|
|
1190
|
+
* sleep. Members are threaded into a circular doubly-linked list so any
|
|
1191
|
+
* future `wake` on any member walks the chain and revives them all.
|
|
1192
|
+
*
|
|
1193
|
+
* Velocities are zeroed because the body is by definition at rest at
|
|
1194
|
+
* this point — the alternative (storing residual velocities for "softer"
|
|
1195
|
+
* wake) is what Bullet does, but for a deterministic game-physics target
|
|
1196
|
+
* fully resetting is simpler and avoids drift while sleeping.
|
|
1197
|
+
*
|
|
1198
|
+
* @private
|
|
1199
|
+
* @param {Uint32Array} member_array view (or full array) of body indices
|
|
1200
|
+
* @param {number} start
|
|
1201
|
+
* @param {number} end
|
|
1202
|
+
*/
|
|
1203
|
+
__atomic_sleep_island_range(member_array, start, end) {
|
|
1204
|
+
const count = end - start;
|
|
1205
|
+
if (count === 0) return;
|
|
1206
|
+
const bodies = this.__bodies;
|
|
1207
|
+
const storage = this.storage;
|
|
1208
|
+
|
|
1209
|
+
if (count === 1) {
|
|
1210
|
+
const idx = member_array[start];
|
|
1211
|
+
const rb = bodies[idx];
|
|
1212
|
+
if (rb === undefined) return;
|
|
1213
|
+
rb.sleep_group_next = -1;
|
|
1214
|
+
rb.sleep_group_prev = -1;
|
|
1215
|
+
rb.sleepState = SleepState.Sleeping;
|
|
1216
|
+
rb.linearVelocity[0] = 0;
|
|
1217
|
+
rb.linearVelocity[1] = 0;
|
|
1218
|
+
rb.linearVelocity[2] = 0;
|
|
1219
|
+
rb.angularVelocity[0] = 0;
|
|
1220
|
+
rb.angularVelocity[1] = 0;
|
|
1221
|
+
rb.angularVelocity[2] = 0;
|
|
1222
|
+
storage.mark_sleeping(idx);
|
|
1223
|
+
return;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
for (let i = 0; i < count; i++) {
|
|
1227
|
+
const idx = member_array[start + i];
|
|
1228
|
+
const rb = bodies[idx];
|
|
1229
|
+
if (rb === undefined) continue;
|
|
1230
|
+
const next_idx = member_array[start + ((i + 1) % count)];
|
|
1231
|
+
const prev_idx = member_array[start + ((i - 1 + count) % count)];
|
|
1232
|
+
rb.sleep_group_next = next_idx;
|
|
1233
|
+
rb.sleep_group_prev = prev_idx;
|
|
1234
|
+
rb.sleepState = SleepState.Sleeping;
|
|
1235
|
+
rb.linearVelocity[0] = 0;
|
|
1236
|
+
rb.linearVelocity[1] = 0;
|
|
1237
|
+
rb.linearVelocity[2] = 0;
|
|
1238
|
+
rb.angularVelocity[0] = 0;
|
|
1239
|
+
rb.angularVelocity[1] = 0;
|
|
1240
|
+
rb.angularVelocity[2] = 0;
|
|
1241
|
+
storage.mark_sleeping(idx);
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
/**
|
|
1246
|
+
* Broadphase raycast against both BVHs. Fills `result` with the nearest
|
|
1247
|
+
* hit and returns `true` on hit, `false` on miss.
|
|
1248
|
+
*
|
|
1249
|
+
* Narrowphase refinement against the actual shape geometry is a
|
|
1250
|
+
* follow-up — for now `result.t` is the distance to the leaf's
|
|
1251
|
+
* inflated AABB and `result.normal` is the AABB face normal. Both are
|
|
1252
|
+
* exact for AABB-shaped colliders.
|
|
1253
|
+
*
|
|
1254
|
+
* @param {Ray3} ray origin + unit direction + `tMax`
|
|
1255
|
+
* @param {PhysicsSurfacePoint} result populated on hit; untouched on miss
|
|
1256
|
+
* @param {(entity:number, collider:Collider)=>boolean} [filter] defaults
|
|
1257
|
+
* to {@link returnTrue} (accept every candidate)
|
|
1258
|
+
* @returns {boolean}
|
|
1259
|
+
*/
|
|
1260
|
+
raycast(ray, result, filter = returnTrue) {
|
|
1261
|
+
return raycast_query(this, ray, result, filter);
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
/**
|
|
1265
|
+
* Sweep a convex shape along a ray and find the first body it
|
|
1266
|
+
* would hit. The shape starts at `ray.origin` oriented by
|
|
1267
|
+
* `rotation` and translates along `ray.direction` for up to
|
|
1268
|
+
* `ray.tMax` units. Returns the nearest impact within that
|
|
1269
|
+
* interval.
|
|
1270
|
+
*
|
|
1271
|
+
* The "swept AABB" broadphase finds candidate bodies whose BVH
|
|
1272
|
+
* leaves overlap the shape's swept volume; the narrowphase then
|
|
1273
|
+
* bisects [0, t] on GJK overlap to find the time-of-impact for
|
|
1274
|
+
* each candidate. Best-t early termination skips candidates that
|
|
1275
|
+
* can't tighten the answer.
|
|
1276
|
+
*
|
|
1277
|
+
* @param {Ray3} ray origin + unit direction + `tMax`
|
|
1278
|
+
* @param {AbstractShape3D} shape
|
|
1279
|
+
* @param {{x:number,y:number,z:number,w:number}} rotation
|
|
1280
|
+
* @param {PhysicsSurfacePoint} result populated on hit; untouched on miss
|
|
1281
|
+
* @param {(entity:number, collider:Collider)=>boolean} [filter]
|
|
1282
|
+
* @returns {boolean}
|
|
1283
|
+
*/
|
|
1284
|
+
shapeCast(ray, shape, rotation, result, filter = returnTrue) {
|
|
1285
|
+
return shape_cast_query(this, ray, shape, rotation, result, filter);
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
/**
|
|
1289
|
+
* Speculative overlap query: find all bodies whose collider would
|
|
1290
|
+
* overlap the given convex shape placed at the given world pose,
|
|
1291
|
+
* without mutating the simulation. Intended for kinematic /
|
|
1292
|
+
* character controllers that need to test "would I collide if I
|
|
1293
|
+
* moved here?" before committing the move.
|
|
1294
|
+
*
|
|
1295
|
+
* Pipeline:
|
|
1296
|
+
* 1. The shape's world AABB is computed from `position` + `rotation`.
|
|
1297
|
+
* 2. Both broadphase trees (static + dynamic) are queried for
|
|
1298
|
+
* bodies whose leaf AABB overlaps that envelope.
|
|
1299
|
+
* 3. Each candidate is GJK-tested in world frame. Convex
|
|
1300
|
+
* candidates run one GJK call; concave candidates (heightmap,
|
|
1301
|
+
* mesh) run per-triangle GJK via the decomposition path.
|
|
1302
|
+
* 4. The optional `filter` is consulted before the GJK test —
|
|
1303
|
+
* useful for skipping the caller's own body, allies, sensors,
|
|
1304
|
+
* etc.
|
|
1305
|
+
*
|
|
1306
|
+
* The output buffer is filled with overlapping bodies' `body_id`
|
|
1307
|
+
* values (uint32 with packed generation), starting at
|
|
1308
|
+
* `output_offset`. The caller is responsible for sizing the buffer;
|
|
1309
|
+
* IDs past its end are dropped silently and the count caps at the
|
|
1310
|
+
* available space.
|
|
1311
|
+
*
|
|
1312
|
+
* The query shape must be convex. Concave query shapes throw —
|
|
1313
|
+
* they're typically static terrain and not used as kinematic
|
|
1314
|
+
* probes; the M×N triangle-pair cost wouldn't be worth the rare
|
|
1315
|
+
* use case.
|
|
1316
|
+
*
|
|
1317
|
+
* @param {AbstractShape3D} shape convex query shape, in its local frame
|
|
1318
|
+
* @param {{x:number,y:number,z:number}} position world position of
|
|
1319
|
+
* the query shape
|
|
1320
|
+
* @param {{x:number,y:number,z:number,w:number}} rotation world
|
|
1321
|
+
* rotation (unit quaternion)
|
|
1322
|
+
* @param {Uint32Array|number[]} output buffer to receive body_ids
|
|
1323
|
+
* @param {number} output_offset starting index in output
|
|
1324
|
+
* @param {(entity:number, collider:Collider)=>boolean} [filter]
|
|
1325
|
+
* defaults to {@link returnTrue}
|
|
1326
|
+
* @returns {number} number of overlapping bodies written
|
|
1327
|
+
*/
|
|
1328
|
+
overlap(shape, position, rotation, output, output_offset, filter = returnTrue) {
|
|
1329
|
+
return overlap_shape_query(this, shape, position, rotation, output, output_offset, filter);
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
/**
|
|
1333
|
+
* Wake propagation through contact pairs. Runs BEFORE broadphase so a
|
|
1334
|
+
* body woken here participates in THIS frame's broadphase / narrowphase
|
|
1335
|
+
* / islands end to end — it never simulates a step without its support
|
|
1336
|
+
* contacts (free-fall penetration pop).
|
|
1337
|
+
*
|
|
1338
|
+
* Reads ONLY persistent manifold state (the slots whose pair the
|
|
1339
|
+
* broadphase touched last frame — `prev_touched`), never the transient
|
|
1340
|
+
* pair list: manifold state is part of the engine's exportable contact
|
|
1341
|
+
* state, so a reconstructed engine wakes on exactly the original's
|
|
1342
|
+
* schedule.
|
|
1343
|
+
*
|
|
1344
|
+
* A sleeper wakes when:
|
|
1345
|
+
* - its pair holds REAL contacts (`contact_count > 0`), unless the
|
|
1346
|
+
* awake side is a PARKED non-Dynamic (a stationary kinematic platform
|
|
1347
|
+
* or a static — sleepState of either is never updated — transmits no
|
|
1348
|
+
* motion; the moment it gets velocity, the riders wake); or
|
|
1349
|
+
* - the pair has no contacts yet but the awake side's velocity-swept
|
|
1350
|
+
* tight AABB just REACHED the sleeper's tight AABB (false→true edge
|
|
1351
|
+
* of {@link __swept_proximity}) — one precautionary wake so an
|
|
1352
|
+
* incoming body never spends its first touching frame against a
|
|
1353
|
+
* non-integrating sleeper, over-embedding by v·dt. Edge-triggered on
|
|
1354
|
+
* a pure function of body state: pair CREATION time (the old
|
|
1355
|
+
* trigger) depends on broadphase fat-box history, which a
|
|
1356
|
+
* reconstructed engine does not share; and level-triggered proximity
|
|
1357
|
+
* would re-wake a pile next to a hovering body every frame. Slot
|
|
1358
|
+
* existence alone wakes nothing.
|
|
1359
|
+
* @private
|
|
1360
|
+
* @param {number} dt step size — extent of the predicate's velocity sweep
|
|
1361
|
+
*/
|
|
1362
|
+
__wake_pairs(dt) {
|
|
1363
|
+
const bodies = this.__bodies;
|
|
1364
|
+
const storage = this.storage;
|
|
1365
|
+
const manifolds = this.manifolds;
|
|
1366
|
+
const live_count = manifolds.count;
|
|
1367
|
+
for (let i = 0; i < live_count; i++) {
|
|
1368
|
+
const slot = manifolds.live_at(i);
|
|
1369
|
+
// "Was in last frame's broadphase": acquire set touched, the
|
|
1370
|
+
// end-of-step advance rolled it to prev_touched. (A dormant
|
|
1371
|
+
// slot can carry a stale prev_touched from its sleep frame —
|
|
1372
|
+
// the both-asleep guard below skips it.)
|
|
1373
|
+
if (!manifolds.was_touched_prev(slot)) continue;
|
|
1374
|
+
|
|
1375
|
+
const idA = manifolds.bodyA(slot);
|
|
1376
|
+
const idB = manifolds.bodyB(slot);
|
|
1377
|
+
// Stale-slot guards: a body may have been unlinked since (and
|
|
1378
|
+
// its index reused by an unrelated body).
|
|
1379
|
+
if (!storage.is_valid(idA) || !storage.is_valid(idB)) continue;
|
|
1380
|
+
const a = bodies[body_id_index(idA)];
|
|
1381
|
+
const b = bodies[body_id_index(idB)];
|
|
1382
|
+
if (a === undefined || b === undefined) continue;
|
|
1383
|
+
|
|
1384
|
+
const aSleep = a.sleepState === SleepState.Sleeping;
|
|
1385
|
+
const bSleep = b.sleepState === SleepState.Sleeping;
|
|
1386
|
+
if (aSleep === bSleep) continue; // both awake, or a dormant pair
|
|
1387
|
+
|
|
1388
|
+
if (manifolds.contact_count(slot) > 0) {
|
|
1389
|
+
const mover = aSleep ? b : a;
|
|
1390
|
+
if (mover.kind !== BodyKind.Dynamic) {
|
|
1391
|
+
const lv = mover.linearVelocity;
|
|
1392
|
+
const av = mover.angularVelocity;
|
|
1393
|
+
if (lv[0] === 0 && lv[1] === 0 && lv[2] === 0
|
|
1394
|
+
&& av[0] === 0 && av[1] === 0 && av[2] === 0) {
|
|
1395
|
+
continue; // parked platform / static — transmits no motion
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
this.__wake_body(aSleep ? a : b);
|
|
1399
|
+
} else {
|
|
1400
|
+
// No contacts: pre-contact precautionary wake on the
|
|
1401
|
+
// proximity EDGE. The predicate needs no parked exemption —
|
|
1402
|
+
// a zero-velocity mover's swept box is its tight box, so it
|
|
1403
|
+
// only fires on actual tight-box overlap, once.
|
|
1404
|
+
const mover_idx = body_id_index(aSleep ? idB : idA);
|
|
1405
|
+
const sleeper_idx = body_id_index(aSleep ? idA : idB);
|
|
1406
|
+
const prox = this.__swept_proximity(mover_idx, sleeper_idx, dt);
|
|
1407
|
+
const had_prox = manifolds.is_prox(slot);
|
|
1408
|
+
manifolds.set_prox(slot, prox);
|
|
1409
|
+
if (prox && !had_prox) {
|
|
1410
|
+
this.__wake_body(aSleep ? a : b);
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
/**
|
|
1417
|
+
* Stage-0 pre-contact wake predicate: does any of `mover`'s collider
|
|
1418
|
+
* tight AABBs, swept directionally by the mover's linear velocity over
|
|
1419
|
+
* `dt`, overlap any of `sleeper`'s collider tight AABBs?
|
|
1420
|
+
*
|
|
1421
|
+
* A pure function of CURRENT body state (poses, shapes, velocity) — no
|
|
1422
|
+
* broadphase or pad history — so every engine holding the same bodies
|
|
1423
|
+
* evaluates it identically. Conservative containment: the swept box is
|
|
1424
|
+
* inside the mover's stage-2 fat box (pad = 2·|v|·dt + slack ⊇ v·dt)
|
|
1425
|
+
* and the sleeper's tight box is inside its stored leaf, so whenever
|
|
1426
|
+
* the predicate is true the broadphase has the pair THIS frame in any
|
|
1427
|
+
* engine — the manifold slot the wake stage needs is guaranteed to
|
|
1428
|
+
* exist on the frame the edge fires.
|
|
1429
|
+
*
|
|
1430
|
+
* Linear sweep only (matching the broadphase pad): a purely angular
|
|
1431
|
+
* approach is woken one frame later by its first actual contact.
|
|
1432
|
+
*
|
|
1433
|
+
* @private
|
|
1434
|
+
* @param {number} mover_idx body index of the awake side
|
|
1435
|
+
* @param {number} sleeper_idx body index of the sleeping side
|
|
1436
|
+
* @param {number} dt
|
|
1437
|
+
* @returns {boolean}
|
|
1438
|
+
*/
|
|
1439
|
+
__swept_proximity(mover_idx, sleeper_idx, dt) {
|
|
1440
|
+
const mover_list = this.__body_collider_lists[mover_idx];
|
|
1441
|
+
const sleeper_list = this.__body_collider_lists[sleeper_idx];
|
|
1442
|
+
if (mover_list === undefined || sleeper_list === undefined) return false;
|
|
1443
|
+
|
|
1444
|
+
const lv = this.__bodies[mover_idx].linearVelocity;
|
|
1445
|
+
const px = lv[0] * dt;
|
|
1446
|
+
const py = lv[1] * dt;
|
|
1447
|
+
const pz = lv[2] * dt;
|
|
1448
|
+
|
|
1449
|
+
for (let i = 0; i < mover_list.length; i++) {
|
|
1450
|
+
const m = mover_list[i];
|
|
1451
|
+
if (m.bvhNode === COLLIDER_UNBOUND) continue;
|
|
1452
|
+
compute_world_aabb(scratch_prox_mover, 0, m.collider.shape, m.transform);
|
|
1453
|
+
if (px < 0) scratch_prox_mover[0] += px; else scratch_prox_mover[3] += px;
|
|
1454
|
+
if (py < 0) scratch_prox_mover[1] += py; else scratch_prox_mover[4] += py;
|
|
1455
|
+
if (pz < 0) scratch_prox_mover[2] += pz; else scratch_prox_mover[5] += pz;
|
|
1456
|
+
|
|
1457
|
+
for (let k = 0; k < sleeper_list.length; k++) {
|
|
1458
|
+
const s = sleeper_list[k];
|
|
1459
|
+
if (s.bvhNode === COLLIDER_UNBOUND) continue;
|
|
1460
|
+
compute_world_aabb(scratch_prox_sleeper, 0, s.collider.shape, s.transform);
|
|
1461
|
+
if (scratch_prox_mover[0] <= scratch_prox_sleeper[3]
|
|
1462
|
+
&& scratch_prox_mover[3] >= scratch_prox_sleeper[0]
|
|
1463
|
+
&& scratch_prox_mover[1] <= scratch_prox_sleeper[4]
|
|
1464
|
+
&& scratch_prox_mover[4] >= scratch_prox_sleeper[1]
|
|
1465
|
+
&& scratch_prox_mover[2] <= scratch_prox_sleeper[5]
|
|
1466
|
+
&& scratch_prox_mover[5] >= scratch_prox_sleeper[2]) {
|
|
1467
|
+
return true;
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
return false;
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
/**
|
|
1475
|
+
* Wake propagation across joints: if a joint connects an awake body to a
|
|
1476
|
+
* sleeping one, wake the sleeper so the constraint stays coupled (a joint
|
|
1477
|
+
* with one body asleep and one awake would otherwise be skipped by the
|
|
1478
|
+
* solver, letting the awake side drift). A common trigger is a
|
|
1479
|
+
* kinematic/motor-driven body pulling on a sleeping chain.
|
|
1480
|
+
*
|
|
1481
|
+
* Bodies that slept together as one island share a sleep group, so the
|
|
1482
|
+
* usual atomic wake already revives the whole chain when any member is
|
|
1483
|
+
* hit; this catches the cases that atomic wake doesn't (joint spanning
|
|
1484
|
+
* separate groups, kinematic driver).
|
|
1485
|
+
* @private
|
|
1486
|
+
*/
|
|
1487
|
+
__wake_joints() {
|
|
1488
|
+
const joints = this.__joints;
|
|
1489
|
+
const n = joints.length;
|
|
1490
|
+
if (n === 0) return;
|
|
1491
|
+
const bodies = this.__bodies;
|
|
1492
|
+
const storage = this.storage;
|
|
1493
|
+
for (let i = 0; i < n; i++) {
|
|
1494
|
+
const joint = joints[i];
|
|
1495
|
+
if (joint === undefined || joint === null) continue;
|
|
1496
|
+
if (joint._bodyIdB === JOINT_WORLD) continue;
|
|
1497
|
+
if (!storage.is_valid(joint._bodyIdA) || !storage.is_valid(joint._bodyIdB)) continue;
|
|
1498
|
+
const a = bodies[body_id_index(joint._bodyIdA)];
|
|
1499
|
+
const b = bodies[body_id_index(joint._bodyIdB)];
|
|
1500
|
+
if (a === undefined || b === undefined) continue;
|
|
1501
|
+
const aSleep = a.sleepState === SleepState.Sleeping;
|
|
1502
|
+
const bSleep = b.sleepState === SleepState.Sleeping;
|
|
1503
|
+
if (aSleep === bSleep) continue; // both awake or both asleep — leave as is
|
|
1504
|
+
|
|
1505
|
+
// The "awake" side must be capable of pulling the sleeper. A
|
|
1506
|
+
// static anchor's sleepState is never updated (it reads Awake
|
|
1507
|
+
// forever), so without this rule a body jointed to a static could
|
|
1508
|
+
// never sleep — perpetual mismatch wake. A kinematic driver
|
|
1509
|
+
// counts only while it is actually moving: a parked motor leaves
|
|
1510
|
+
// its chain asleep, and starting it wakes the chain (same motion
|
|
1511
|
+
// rule as __wake_pairs).
|
|
1512
|
+
const mover = aSleep ? b : a;
|
|
1513
|
+
if (mover.kind !== BodyKind.Dynamic) {
|
|
1514
|
+
const lv = mover.linearVelocity;
|
|
1515
|
+
const av = mover.angularVelocity;
|
|
1516
|
+
if (lv[0] === 0 && lv[1] === 0 && lv[2] === 0
|
|
1517
|
+
&& av[0] === 0 && av[1] === 0 && av[2] === 0) {
|
|
1518
|
+
continue;
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
if (aSleep) this.__wake_body(a); else this.__wake_body(b);
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
/**
|
|
1526
|
+
* Per-island atomic sleep test. Walks each island once and applies the
|
|
1527
|
+
* decision uniformly across all members:
|
|
1528
|
+
*
|
|
1529
|
+
* - If any member carries {@link RigidBodyFlags.DisableSleep}, the
|
|
1530
|
+
* entire island is exempt; every member's sleep_timer is reset.
|
|
1531
|
+
* - If `max(|v|² + |ω|²)` across all members is below
|
|
1532
|
+
* {@link sleepVelocitySqrThreshold}, every member's sleep_timer is
|
|
1533
|
+
* incremented by `dt`. When the smallest member's timer crosses
|
|
1534
|
+
* {@link sleepTimeThreshold}, the whole island sleeps atomically in
|
|
1535
|
+
* the same step (members get threaded into a sleep-group chain so
|
|
1536
|
+
* {@link __wake_body} can wake them all in one call).
|
|
1537
|
+
* - Otherwise the island has at least one active member, so every
|
|
1538
|
+
* member's timer is reset.
|
|
1539
|
+
*
|
|
1540
|
+
* This is the design-plan atomic-island sleep — replaces the per-body
|
|
1541
|
+
* approximation that lived in this slot during the previous slice.
|
|
1542
|
+
* Weakly-connected piles no longer chatter awake when a single member
|
|
1543
|
+
* blips above threshold; piles fall asleep and wake up as one.
|
|
1544
|
+
*
|
|
1545
|
+
* @private
|
|
1546
|
+
* @param {number} dt
|
|
1547
|
+
*/
|
|
1548
|
+
__sleep_test(dt) {
|
|
1549
|
+
const threshold_sqr = this.sleepVelocitySqrThreshold;
|
|
1550
|
+
const time_threshold = this.sleepTimeThreshold;
|
|
1551
|
+
const bodies = this.__bodies;
|
|
1552
|
+
const islands = this.islands;
|
|
1553
|
+
const island_count = islands.island_count;
|
|
1554
|
+
const body_offsets = islands.body_offsets;
|
|
1555
|
+
const body_data = islands.body_data;
|
|
1556
|
+
|
|
1557
|
+
for (let isl = 0; isl < island_count; isl++) {
|
|
1558
|
+
const start = body_offsets[isl];
|
|
1559
|
+
const end = body_offsets[isl + 1];
|
|
1560
|
+
if (end === start) continue;
|
|
1561
|
+
|
|
1562
|
+
// Pass 1: find max v² + check DisableSleep across the island.
|
|
1563
|
+
let max_v_sqr = 0;
|
|
1564
|
+
let any_disable_sleep = false;
|
|
1565
|
+
for (let i = start; i < end; i++) {
|
|
1566
|
+
const idx = body_data[i];
|
|
1567
|
+
const rb = bodies[idx];
|
|
1568
|
+
if (rb === undefined) continue;
|
|
1569
|
+
if ((rb.flags & RigidBodyFlags.DisableSleep) !== 0) {
|
|
1570
|
+
any_disable_sleep = true;
|
|
1571
|
+
break;
|
|
1572
|
+
}
|
|
1573
|
+
const lv = rb.linearVelocity;
|
|
1574
|
+
const av = rb.angularVelocity;
|
|
1575
|
+
const v_sqr = lv[0] * lv[0] + lv[1] * lv[1] + lv[2] * lv[2]
|
|
1576
|
+
+ av[0] * av[0] + av[1] * av[1] + av[2] * av[2];
|
|
1577
|
+
if (v_sqr > max_v_sqr) max_v_sqr = v_sqr;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
if (any_disable_sleep) {
|
|
1581
|
+
// Whole island is exempt — reset every member's timer.
|
|
1582
|
+
for (let i = start; i < end; i++) {
|
|
1583
|
+
const rb = bodies[body_data[i]];
|
|
1584
|
+
if (rb !== undefined) rb.sleep_timer = 0;
|
|
1585
|
+
}
|
|
1586
|
+
continue;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
if (max_v_sqr < threshold_sqr) {
|
|
1590
|
+
// Island is at rest — increment every member's timer; if the
|
|
1591
|
+
// slowest-stabilising member has crossed the time threshold,
|
|
1592
|
+
// every member has (they were incremented together this step),
|
|
1593
|
+
// so atomic-sleep the island.
|
|
1594
|
+
let min_timer = Infinity;
|
|
1595
|
+
for (let i = start; i < end; i++) {
|
|
1596
|
+
const rb = bodies[body_data[i]];
|
|
1597
|
+
if (rb === undefined) continue;
|
|
1598
|
+
rb.sleep_timer += dt;
|
|
1599
|
+
if (rb.sleep_timer < min_timer) min_timer = rb.sleep_timer;
|
|
1600
|
+
}
|
|
1601
|
+
if (min_timer >= time_threshold) {
|
|
1602
|
+
this.__atomic_sleep_island_range(body_data, start, end);
|
|
1603
|
+
}
|
|
1604
|
+
} else {
|
|
1605
|
+
// At least one member is active — reset every timer.
|
|
1606
|
+
for (let i = start; i < end; i++) {
|
|
1607
|
+
const rb = bodies[body_data[i]];
|
|
1608
|
+
if (rb !== undefined) rb.sleep_timer = 0;
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
/**
|
|
1615
|
+
* Dispatch every buffered contact event to the entities involved, via the
|
|
1616
|
+
* dataset's per-entity event channel — `dataset.sendEvent(entity, name,
|
|
1617
|
+
* payload)`, once for each of the pair's entities. This is the only
|
|
1618
|
+
* contact-event path: a system with no dataset attached has nowhere to
|
|
1619
|
+
* deliver and emits nothing.
|
|
1620
|
+
*
|
|
1621
|
+
* Payload is a reused scratch object; listeners must copy anything they
|
|
1622
|
+
* intend to retain past the listener body.
|
|
1623
|
+
* @private
|
|
1624
|
+
*/
|
|
1625
|
+
__dispatch_contact_events() {
|
|
1626
|
+
const events = this.contactEvents;
|
|
1627
|
+
const n = events.count;
|
|
1628
|
+
if (n === 0) return;
|
|
1629
|
+
|
|
1630
|
+
const ecd = (this.entityManager !== null && this.entityManager !== undefined)
|
|
1631
|
+
? this.entityManager.dataset
|
|
1632
|
+
: null;
|
|
1633
|
+
// No dataset → nowhere to deliver. The buffer is cleared by
|
|
1634
|
+
// diff_manifolds each step regardless, so nothing leaks.
|
|
1635
|
+
if (ecd === null || ecd === undefined) return;
|
|
1636
|
+
|
|
1637
|
+
const manifolds = this.manifolds;
|
|
1638
|
+
const data = manifolds.data_buffer;
|
|
1639
|
+
|
|
1640
|
+
const payload = this.__contact_payload;
|
|
1641
|
+
|
|
1642
|
+
for (let i = 0; i < n; i++) {
|
|
1643
|
+
const kind = events.kind_at(i);
|
|
1644
|
+
const entA = events.entityA_at(i);
|
|
1645
|
+
const entB = events.entityB_at(i);
|
|
1646
|
+
const slot = events.slot_at(i);
|
|
1647
|
+
|
|
1648
|
+
// Use the deepest contact of the manifold as the representative
|
|
1649
|
+
// point/normal/depth for the event. v1: contact 0 only.
|
|
1650
|
+
const slot_off = manifolds.slot_data_offset(slot);
|
|
1651
|
+
const has_contact = manifolds.contact_count(slot) > 0;
|
|
1652
|
+
|
|
1653
|
+
// Scratch payload — write the point/normal components by index to
|
|
1654
|
+
// skip the Vector3 change-signal dispatch (nothing observes them).
|
|
1655
|
+
const pt = payload.point;
|
|
1656
|
+
const nm = payload.normal;
|
|
1657
|
+
if (has_contact) {
|
|
1658
|
+
const wax = data[slot_off], way = data[slot_off + 1], waz = data[slot_off + 2];
|
|
1659
|
+
const wbx = data[slot_off + 3], wby = data[slot_off + 4], wbz = data[slot_off + 5];
|
|
1660
|
+
pt[0] = (wax + wbx) * 0.5;
|
|
1661
|
+
pt[1] = (way + wby) * 0.5;
|
|
1662
|
+
pt[2] = (waz + wbz) * 0.5;
|
|
1663
|
+
nm[0] = data[slot_off + 6];
|
|
1664
|
+
nm[1] = data[slot_off + 7];
|
|
1665
|
+
nm[2] = data[slot_off + 8];
|
|
1666
|
+
payload.depth = data[slot_off + 9];
|
|
1667
|
+
|
|
1668
|
+
// The event pair is entity-canonical (min, max); the slot's
|
|
1669
|
+
// stored normal points from the slot's OWN body B toward its
|
|
1670
|
+
// body A — an assignment that follows packed-id order, i.e.
|
|
1671
|
+
// slot allocation history. Mirror the normal when the
|
|
1672
|
+
// canonicalization swapped the pair, so the payload contract
|
|
1673
|
+
// ("normal points from entityB toward entityA") holds
|
|
1674
|
+
// identically in every engine regardless of slot history.
|
|
1675
|
+
const slot_idA = manifolds.bodyA(slot);
|
|
1676
|
+
const slot_entA = this.storage.is_valid(slot_idA)
|
|
1677
|
+
? this.storage.entity_at(body_id_index(slot_idA))
|
|
1678
|
+
: -1;
|
|
1679
|
+
if (slot_entA !== entA) {
|
|
1680
|
+
nm[0] = -nm[0];
|
|
1681
|
+
nm[1] = -nm[1];
|
|
1682
|
+
nm[2] = -nm[2];
|
|
1683
|
+
}
|
|
1684
|
+
} else {
|
|
1685
|
+
pt[0] = 0;
|
|
1686
|
+
pt[1] = 0;
|
|
1687
|
+
pt[2] = 0;
|
|
1688
|
+
nm[0] = 0;
|
|
1689
|
+
nm[1] = 0;
|
|
1690
|
+
nm[2] = 0;
|
|
1691
|
+
payload.depth = 0;
|
|
1692
|
+
}
|
|
1693
|
+
payload.entityA = entA;
|
|
1694
|
+
payload.entityB = entB;
|
|
1695
|
+
|
|
1696
|
+
let event_name;
|
|
1697
|
+
if (kind === ContactEventKind.Begin) {
|
|
1698
|
+
event_name = PhysicsEvents.ContactBegin;
|
|
1699
|
+
} else if (kind === ContactEventKind.Stay) {
|
|
1700
|
+
event_name = PhysicsEvents.ContactStay;
|
|
1701
|
+
} else {
|
|
1702
|
+
event_name = PhysicsEvents.ContactEnd;
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
if (entA >= 0) ecd.sendEvent(entA, event_name, payload);
|
|
1706
|
+
if (entB >= 0) ecd.sendEvent(entB, event_name, payload);
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
/**
|
|
1711
|
+
* Producer — restore pass. At the top of a fixed step, reset every awake
|
|
1712
|
+
* {@link Interpolated} body's live components to their authoritative state
|
|
1713
|
+
* from the previous tick's snapshot, undoing any render-time interpolation
|
|
1714
|
+
* the {@link InterpolationSystem} wrote between frames so the sim integrates
|
|
1715
|
+
* from truth, not an interpolated pose. A body with no previous snapshot
|
|
1716
|
+
* (first step ever, or just woken) is left as-is — its live state is already
|
|
1717
|
+
* authoritative. No-op unless {@link interpolationLog} is wired.
|
|
1718
|
+
* @private
|
|
1719
|
+
*/
|
|
1720
|
+
__interp_restore() {
|
|
1721
|
+
const log = this.interpolationLog;
|
|
1722
|
+
const em = this.entityManager;
|
|
1723
|
+
if (log === null || em === null || em === undefined) return;
|
|
1724
|
+
const dataset = em.dataset;
|
|
1725
|
+
if (dataset === null || dataset === undefined) return;
|
|
1726
|
+
|
|
1727
|
+
const prev_tick = em.fixedStepTick - 1;
|
|
1728
|
+
if (prev_tick < 0) return;
|
|
1729
|
+
|
|
1730
|
+
const storage = this.storage;
|
|
1731
|
+
const count = storage.awake_count;
|
|
1732
|
+
const scratch = this.__interp_scratch;
|
|
1733
|
+
|
|
1734
|
+
for (let i = 0; i < count; i++) {
|
|
1735
|
+
const idx = storage.awake_at(i);
|
|
1736
|
+
const entity = storage.entity_at(idx);
|
|
1737
|
+
const interpolated = dataset.getComponent(entity, Interpolated);
|
|
1738
|
+
if (interpolated === undefined || interpolated === null) continue;
|
|
1739
|
+
// A teleported body (snap set, e.g. via setPose) keeps its live pose
|
|
1740
|
+
// this step — restoring the previous tick would undo the teleport.
|
|
1741
|
+
if (interpolated.snap) continue;
|
|
1742
|
+
const key = interpolated.key;
|
|
1743
|
+
if (key < 0) continue;
|
|
1744
|
+
|
|
1745
|
+
const interpolands = interpolated.interpolands;
|
|
1746
|
+
for (let k = 0; k < interpolands.length; k++) {
|
|
1747
|
+
const ip = interpolands[k];
|
|
1748
|
+
scratch.position = 0;
|
|
1749
|
+
// Snap to the previous tick's snapshot (both offsets equal → t irrelevant).
|
|
1750
|
+
const ok = log.interpolate(scratch, key, ip.type_id, prev_tick, prev_tick, 0, ip.interpolation_adapter);
|
|
1751
|
+
if (!ok) continue;
|
|
1752
|
+
const target = dataset.getComponent(entity, ip.component_class);
|
|
1753
|
+
if (target === undefined || target === null) continue;
|
|
1754
|
+
scratch.position = 0;
|
|
1755
|
+
ip.serialization_adapter.deserialize(scratch, target);
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
/**
|
|
1761
|
+
* Producer — record pass. At the end of a fixed step, snapshot every awake
|
|
1762
|
+
* {@link Interpolated} body's live components into the shared log under the
|
|
1763
|
+
* current `entityManager.fixedStepTick`. The render-time
|
|
1764
|
+
* {@link InterpolationSystem} blends consecutive ticks from these snapshots.
|
|
1765
|
+
* Only awake (moving) bodies are recorded, so the log stays sparse. No-op
|
|
1766
|
+
* unless {@link interpolationLog} is wired.
|
|
1767
|
+
* @private
|
|
1768
|
+
*/
|
|
1769
|
+
__interp_record() {
|
|
1770
|
+
const log = this.interpolationLog;
|
|
1771
|
+
const em = this.entityManager;
|
|
1772
|
+
if (log === null || em === null || em === undefined) return;
|
|
1773
|
+
const dataset = em.dataset;
|
|
1774
|
+
if (dataset === null || dataset === undefined) return;
|
|
1775
|
+
|
|
1776
|
+
const tick = em.fixedStepTick;
|
|
1777
|
+
const storage = this.storage;
|
|
1778
|
+
const count = storage.awake_count;
|
|
1779
|
+
|
|
1780
|
+
log.begin_tick(tick);
|
|
1781
|
+
for (let i = 0; i < count; i++) {
|
|
1782
|
+
const idx = storage.awake_at(i);
|
|
1783
|
+
const entity = storage.entity_at(idx);
|
|
1784
|
+
const interpolated = dataset.getComponent(entity, Interpolated);
|
|
1785
|
+
if (interpolated === undefined || interpolated === null) continue;
|
|
1786
|
+
const key = interpolated.key;
|
|
1787
|
+
if (key < 0) continue;
|
|
1788
|
+
|
|
1789
|
+
const interpolands = interpolated.interpolands;
|
|
1790
|
+
for (let k = 0; k < interpolands.length; k++) {
|
|
1791
|
+
const ip = interpolands[k];
|
|
1792
|
+
const target = dataset.getComponent(entity, ip.component_class);
|
|
1793
|
+
if (target === undefined || target === null) continue;
|
|
1794
|
+
const buf = log.begin_record(key, ip.type_id);
|
|
1795
|
+
ip.serialization_adapter.serialize(buf, target);
|
|
1796
|
+
log.end_record();
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
log.end_tick();
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
fixedUpdate(dt) {
|
|
1803
|
+
// Producer: restore authoritative pose (undo render interpolation)
|
|
1804
|
+
// before the sim reads any Transform this step.
|
|
1805
|
+
this.__interp_restore();
|
|
1806
|
+
|
|
1807
|
+
const gx = this.gravity.x;
|
|
1808
|
+
const gy = this.gravity.y;
|
|
1809
|
+
const gz = this.gravity.z;
|
|
1810
|
+
|
|
1811
|
+
const storage = this.storage;
|
|
1812
|
+
const bodies = this.__bodies;
|
|
1813
|
+
const transforms = this.__transforms;
|
|
1814
|
+
const joints = this.__joints;
|
|
1815
|
+
const manifolds = this.manifolds;
|
|
1816
|
+
|
|
1817
|
+
// Stage 0: wake propagation — through the persistent manifolds
|
|
1818
|
+
// (last frame's broadphase-touched pairs), then through joints.
|
|
1819
|
+
// Runs before everything else so a just-woken body is part of this
|
|
1820
|
+
// frame's awake set end to end (forces, refit, broadphase,
|
|
1821
|
+
// narrowphase, islands, solve): waking later would give it one
|
|
1822
|
+
// unsupported step (gravity with no contacts → penetration pop).
|
|
1823
|
+
// Reads only manifold + body state — both part of the exportable
|
|
1824
|
+
// world state — never the transient pair list, so a reconstructed
|
|
1825
|
+
// engine wakes on the original's schedule.
|
|
1826
|
+
this.__wake_pairs(dt);
|
|
1827
|
+
this.__wake_joints();
|
|
1828
|
+
|
|
1829
|
+
const count = storage.awake_count;
|
|
1830
|
+
|
|
1831
|
+
// Stage 1: consume the per-frame force / torque accumulators into
|
|
1832
|
+
// velocity at the full `dt`, exactly once (a user force is a per-frame
|
|
1833
|
+
// budget that must land in full regardless of substep count). Gravity
|
|
1834
|
+
// is applied per substep below, so the trajectory integrates at the
|
|
1835
|
+
// substep rate and — crucially — each substep's gravity is balanced by
|
|
1836
|
+
// that substep's contact warm-start, keeping resting stacks at zero
|
|
1837
|
+
// velocity.
|
|
1838
|
+
for (let i = 0; i < count; i++) {
|
|
1839
|
+
const idx = storage.awake_at(i);
|
|
1840
|
+
|
|
1841
|
+
const rb = bodies[idx];
|
|
1842
|
+
const tr = transforms[idx];
|
|
1843
|
+
|
|
1844
|
+
integrate_velocity_forces(rb, tr, dt);
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
// Stage 2: refit each awake body's collider leaves at the current
|
|
1848
|
+
// pose, padded by the swept extent for the body's velocity. The fat
|
|
1849
|
+
// margin uses the post-force velocity; this frame's gravity increment
|
|
1850
|
+
// is a sub-millimetre slack difference, safely inside the margin.
|
|
1851
|
+
const lists = this.__body_collider_lists;
|
|
1852
|
+
for (let i = 0; i < count; i++) {
|
|
1853
|
+
|
|
1854
|
+
const idx = storage.awake_at(i);
|
|
1855
|
+
const rb = bodies[idx];
|
|
1856
|
+
const list = lists[idx];
|
|
1857
|
+
|
|
1858
|
+
if (list === undefined) {
|
|
1859
|
+
continue;
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
const lv = rb.linearVelocity;
|
|
1863
|
+
|
|
1864
|
+
const list_length = list.length;
|
|
1865
|
+
|
|
1866
|
+
for (let k = 0; k < list_length; k++) {
|
|
1867
|
+
|
|
1868
|
+
const entry = list[k];
|
|
1869
|
+
|
|
1870
|
+
// Refit skip — the fat margin's whole purpose: while the
|
|
1871
|
+
// body's FATTENED box (tight + velocity pad) stays inside the
|
|
1872
|
+
// leaf's stored AABB, the stored box still covers everything
|
|
1873
|
+
// the body can reach this step, so the set + refit-to-root is
|
|
1874
|
+
// pure waste. A resting field pays only this containment test
|
|
1875
|
+
// per leaf per frame (at v ≈ 0 the fat box is the tight box
|
|
1876
|
+
// plus the constant slack, which the stored box includes).
|
|
1877
|
+
//
|
|
1878
|
+
// The containment probe MUST be the fat box, not the tight
|
|
1879
|
+
// one: the leaf is how the broadphase and every swept query
|
|
1880
|
+
// discover this body. A body whose velocity grew while its
|
|
1881
|
+
// tight box still sat inside the stored leaf (freshly linked
|
|
1882
|
+
// with a launch velocity, or accelerated by an impulse) would
|
|
1883
|
+
// otherwise keep a leaf covering none of the path it travels
|
|
1884
|
+
// this step — invisible to pair generation and to other
|
|
1885
|
+
// bodies' CCD sweeps for the whole step.
|
|
1886
|
+
compute_world_aabb(scratch_world_aabb, 0, entry.collider.shape, entry.transform);
|
|
1887
|
+
fatten_world_aabb(scratch_world_aabb, 0, lv[0], lv[1], lv[2], dt);
|
|
1888
|
+
const node = entry.bvhNode;
|
|
1889
|
+
this.dynamicBvh.node_get_aabb(node, scratch_stored_aabb);
|
|
1890
|
+
if (scratch_world_aabb[0] >= scratch_stored_aabb[0]
|
|
1891
|
+
&& scratch_world_aabb[1] >= scratch_stored_aabb[1]
|
|
1892
|
+
&& scratch_world_aabb[2] >= scratch_stored_aabb[2]
|
|
1893
|
+
&& scratch_world_aabb[3] <= scratch_stored_aabb[3]
|
|
1894
|
+
&& scratch_world_aabb[4] <= scratch_stored_aabb[4]
|
|
1895
|
+
&& scratch_world_aabb[5] <= scratch_stored_aabb[5]) {
|
|
1896
|
+
continue;
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
this.dynamicBvh.node_move_aabb(node, scratch_world_aabb);
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
// Stage 3: broadphase pair generation. The fat AABBs cover the full
|
|
1904
|
+
// outer-step motion, so the pair set stays valid across all substeps
|
|
1905
|
+
// — broadphase runs once.
|
|
1906
|
+
generate_pairs(
|
|
1907
|
+
storage,
|
|
1908
|
+
this.dynamicBvh,
|
|
1909
|
+
this.staticBvh,
|
|
1910
|
+
manifolds,
|
|
1911
|
+
lists,
|
|
1912
|
+
this.pairs,
|
|
1913
|
+
this.__pair_filter,
|
|
1914
|
+
this,
|
|
1915
|
+
);
|
|
1916
|
+
|
|
1917
|
+
// Stage 5: narrowphase — once per outer step. The substep loop below
|
|
1918
|
+
// re-derives each contact's penetration analytically from the moved
|
|
1919
|
+
// poses rather than re-running geometry.
|
|
1920
|
+
narrowphase_step(this.pairs, manifolds, this.__body_collider_lists);
|
|
1921
|
+
|
|
1922
|
+
// Stage 6: partition awake bodies + touched contacts into islands.
|
|
1923
|
+
// Consumed by the solver (flattened contact list) and the sleep test.
|
|
1924
|
+
this.islands.build(storage, manifolds, bodies, this.__body_collider_lists, joints);
|
|
1925
|
+
|
|
1926
|
+
// Stage 7: TGS substep loop.
|
|
1927
|
+
//
|
|
1928
|
+
// prepare_contacts captures per-contact anchors / effective masses /
|
|
1929
|
+
// approach velocity (no warm-start — that's per-substep). Each substep
|
|
1930
|
+
// integrates gravity by `h`, re-derives contact geometry from the
|
|
1931
|
+
// current poses, replays warm-start, solves velocity (non-penetration
|
|
1932
|
+
// + friction) and position (pseudo-velocity), and integrates the pose
|
|
1933
|
+
// by `h`. Per-substep gravity + per-substep warm-start balance exactly
|
|
1934
|
+
// at a resting contact (each cancels `h` of the other), so stacks hold
|
|
1935
|
+
// at zero velocity and sleep; the position correction adapts as bodies
|
|
1936
|
+
// separate between substeps — the TGS stack-stability mechanism —
|
|
1937
|
+
// without re-running narrowphase. Restitution is applied once after
|
|
1938
|
+
// the loop.
|
|
1939
|
+
// Clamp the substep count: 0 (or a negative / fractional value) would
|
|
1940
|
+
// feed h = dt / N = Infinity into prepare_contacts and a broken loop
|
|
1941
|
+
// bound into the solver.
|
|
1942
|
+
const N = this.substeps > 1 ? this.substeps | 0 : 1;
|
|
1943
|
+
const h = dt / N;
|
|
1944
|
+
const count_after_wake = storage.awake_count;
|
|
1945
|
+
|
|
1946
|
+
// CCD: capture start-of-step positions for flagged bodies over the
|
|
1947
|
+
// post-wake awake set (poses are unchanged until the substep loop below
|
|
1948
|
+
// integrates them). The CCD pass after the solver sweeps from here to
|
|
1949
|
+
// each body's final pose. Reads the primary collider's transform so the
|
|
1950
|
+
// start matches the end the resolve pass reads. Zero-cost when no body
|
|
1951
|
+
// is flagged.
|
|
1952
|
+
const ccd_on = this.ccdEnabled;
|
|
1953
|
+
|
|
1954
|
+
if (ccd_on) {
|
|
1955
|
+
|
|
1956
|
+
const ccd_need = storage.high_water_mark * 3;
|
|
1957
|
+
|
|
1958
|
+
if (this.__ccd_start_pos.length < ccd_need) {
|
|
1959
|
+
this.__ccd_start_pos = new Float64Array(ccd_need);
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
const ccd_start = this.__ccd_start_pos;
|
|
1963
|
+
|
|
1964
|
+
for (let i = 0; i < count_after_wake; i++) {
|
|
1965
|
+
const idx = storage.awake_at(i);
|
|
1966
|
+
const rb = bodies[idx];
|
|
1967
|
+
|
|
1968
|
+
if (rb.kind !== BodyKind.Dynamic) {
|
|
1969
|
+
continue;
|
|
1970
|
+
}
|
|
1971
|
+
if ((rb.flags & RigidBodyFlags.CCD) === 0) {
|
|
1972
|
+
continue;
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
const list = this.__body_collider_lists[idx];
|
|
1976
|
+
|
|
1977
|
+
if (list === undefined || list.length === 0) {
|
|
1978
|
+
continue;
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
const cp = list[0].transform.position;
|
|
1982
|
+
const cb = idx * 3;
|
|
1983
|
+
|
|
1984
|
+
ccd_start[cb] = cp[0];
|
|
1985
|
+
ccd_start[cb + 1] = cp[1];
|
|
1986
|
+
ccd_start[cb + 2] = cp[2];
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
// Size the pseudo-velocity buffer ONCE (it may reallocate on growth),
|
|
1991
|
+
// then capture the reference. Inside the loop we only zero its live
|
|
1992
|
+
// region per substep — re-capturing is unnecessary since it won't
|
|
1993
|
+
// reallocate again this step.
|
|
1994
|
+
this.__reset_pseudo_velocity();
|
|
1995
|
+
const pseudoVel = this.__pseudo_velocity;
|
|
1996
|
+
const pseudo_len = storage.high_water_mark * 6;
|
|
1997
|
+
|
|
1998
|
+
// Gather the data-oriented solver state for every body the substep loop
|
|
1999
|
+
// will touch: the post-wake awake set (all dynamics, at their post-force
|
|
2000
|
+
// velocity) plus the static / kinematic anchors and jointed partners
|
|
2001
|
+
// referenced by this step's contacts and joints. From here the substep
|
|
2002
|
+
// loop reads / writes velocity + orientation through `ss_data` with no
|
|
2003
|
+
// component-object dereference; persistent velocity is scattered back
|
|
2004
|
+
// onto the RigidBodies after the solve.
|
|
2005
|
+
const solver_state = this.__solver_state;
|
|
2006
|
+
solver_state.begin(storage.high_water_mark);
|
|
2007
|
+
|
|
2008
|
+
for (let i = 0; i < count_after_wake; i++) {
|
|
2009
|
+
const idx = storage.awake_at(i);
|
|
2010
|
+
solver_state.gather(idx, bodies[idx], transforms[idx]);
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
const island_contacts = this.islands.contact_data;
|
|
2014
|
+
const island_contact_total = this.islands.contact_offsets[this.islands.island_count];
|
|
2015
|
+
|
|
2016
|
+
for (let i = 0; i < island_contact_total; i++) {
|
|
2017
|
+
const slot = island_contacts[i];
|
|
2018
|
+
|
|
2019
|
+
const ia = body_id_index(manifolds.bodyA(slot));
|
|
2020
|
+
const ib = body_id_index(manifolds.bodyB(slot));
|
|
2021
|
+
|
|
2022
|
+
solver_state.gather(ia, bodies[ia], transforms[ia]);
|
|
2023
|
+
solver_state.gather(ib, bodies[ib], transforms[ib]);
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
const joint_count = joints.length;
|
|
2027
|
+
for (let i = 0; i < joint_count; i++) {
|
|
2028
|
+
const joint = joints[i];
|
|
2029
|
+
|
|
2030
|
+
if (joint === undefined || joint === null) {
|
|
2031
|
+
continue;
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
if (!storage.is_valid(joint._bodyIdA)) {
|
|
2035
|
+
continue;
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
const ia = body_id_index(joint._bodyIdA);
|
|
2039
|
+
|
|
2040
|
+
solver_state.gather(ia, bodies[ia], transforms[ia]);
|
|
2041
|
+
|
|
2042
|
+
if (joint._bodyIdB !== JOINT_WORLD && storage.is_valid(joint._bodyIdB)) {
|
|
2043
|
+
|
|
2044
|
+
const ib = body_id_index(joint._bodyIdB);
|
|
2045
|
+
|
|
2046
|
+
solver_state.gather(ib, bodies[ib], transforms[ib]);
|
|
2047
|
+
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
const ss_data = solver_state.data;
|
|
2052
|
+
|
|
2053
|
+
prepare_contacts(manifolds, this, h);
|
|
2054
|
+
|
|
2055
|
+
for (let s = 0; s < N; s++) {
|
|
2056
|
+
|
|
2057
|
+
// Gravity (+ damping) for this substep.
|
|
2058
|
+
for (let i = 0; i < count_after_wake; i++) {
|
|
2059
|
+
const idx = storage.awake_at(i);
|
|
2060
|
+
integrate_velocity_gravity(ss_data, idx * SBS_STRIDE, bodies[idx], gx, gy, gz, h);
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2063
|
+
// Re-derive contact geometry at the current poses: concave pairs
|
|
2064
|
+
// re-run narrowphase (fresh feature/normal as the body rocks),
|
|
2065
|
+
// convex pairs rotate frozen anchors analytically. Then replay
|
|
2066
|
+
// the per-substep warm-start and solve velocity.
|
|
2067
|
+
redetect_concave_contacts(manifolds, this);
|
|
2068
|
+
refresh_contacts(manifolds, this.__transforms);
|
|
2069
|
+
warm_start_contacts(manifolds, this);
|
|
2070
|
+
solve_velocity(manifolds, this, this.velocityIterations);
|
|
2071
|
+
|
|
2072
|
+
// Joints share the substep: warm-start + velocity-solve the 6-DOF
|
|
2073
|
+
// constraints on real velocity, coupled with the contacts above
|
|
2074
|
+
// (a body touched by both sees one substep of Gauss-Seidel across
|
|
2075
|
+
// contacts then joints). Position correction for locked DOFs is a
|
|
2076
|
+
// SPOOK bias inside this solve, so no separate joint position pass.
|
|
2077
|
+
// Solved in the entity-canonical order (NOT joint-id order, which
|
|
2078
|
+
// encodes link/unlink history) — see __joints_sorted.
|
|
2079
|
+
if (this.__joints_sorted.length > 0) {
|
|
2080
|
+
// Alternate the joint sweep direction on odd substeps so the chain
|
|
2081
|
+
// is solved root→tip and tip→root across the step (symmetric
|
|
2082
|
+
// Gauss-Seidel), cancelling the one-direction propagation bias.
|
|
2083
|
+
solve_joints(this.__joints_sorted, this, h, this.jointIterations, (s & 1) === 1);
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
// Position correction writes pseudo-velocity (zeroed first so it
|
|
2087
|
+
// is a fresh per-substep correction), folded into the pose by the
|
|
2088
|
+
// position integrate and then discarded. SOFT contacts skip it:
|
|
2089
|
+
// their penetration recovery is the velocity-bias term, and the
|
|
2090
|
+
// relax pass below strips the momentum that bias injected
|
|
2091
|
+
// (Box2D-v3 substep order).
|
|
2092
|
+
const contacts_soft = this.contactHertz > 0;
|
|
2093
|
+
pseudoVel.fill(0, 0, pseudo_len);
|
|
2094
|
+
if (!contacts_soft) {
|
|
2095
|
+
solve_position(manifolds, this, this.positionIterations);
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
for (let i = 0; i < count_after_wake; i++) {
|
|
2099
|
+
const idx = storage.awake_at(i);
|
|
2100
|
+
const rb = bodies[idx];
|
|
2101
|
+
const tr = transforms[idx];
|
|
2102
|
+
const base = idx * 6;
|
|
2103
|
+
integrate_position(ss_data, idx * SBS_STRIDE, rb, tr, h,
|
|
2104
|
+
pseudoVel[base], pseudoVel[base + 1], pseudoVel[base + 2],
|
|
2105
|
+
pseudoVel[base + 3], pseudoVel[base + 4], pseudoVel[base + 5]);
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
// Relax pass (soft contacts only): one biasless sweep over the
|
|
2109
|
+
// contact rows AFTER position integration, removing the real
|
|
2110
|
+
// momentum the velocity-bias push injected this substep
|
|
2111
|
+
// (Box2D-v3 substep order: solve -> integrate -> relax).
|
|
2112
|
+
if (contacts_soft) {
|
|
2113
|
+
solve_velocity(manifolds, this, 1, false);
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
// Stage 8: one-shot restitution, after the substep loop, keyed off
|
|
2118
|
+
// the approach velocity captured at prepare time.
|
|
2119
|
+
apply_restitution(manifolds, this);
|
|
2120
|
+
|
|
2121
|
+
// Scatter the solved persistent linear / angular velocity back onto the
|
|
2122
|
+
// RigidBody components (pose was written through to the Transforms each
|
|
2123
|
+
// substep). After this the bodies are authoritative again for CCD,
|
|
2124
|
+
// interpolation recording, and the sleep test below.
|
|
2125
|
+
solver_state.scatter(bodies);
|
|
2126
|
+
|
|
2127
|
+
// Stage 8.5: continuous collision — sweep CCD-flagged fast movers along
|
|
2128
|
+
// their net step translation and stop them at the first blocker, so they
|
|
2129
|
+
// can't tunnel through thin geometry between discrete steps. Runs on the
|
|
2130
|
+
// final post-solve poses, before the sleep test sees the clamped
|
|
2131
|
+
// velocities. No-op when no awake body is flagged.
|
|
2132
|
+
if (ccd_on) {
|
|
2133
|
+
ccd_resolve(this);
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
// Producer: record the post-step authoritative pose of every awake
|
|
2137
|
+
// interpolated body under this step's tick. Before the sleep test, so a
|
|
2138
|
+
// body that settles this step still records its final pose for the last
|
|
2139
|
+
// interpolation interval.
|
|
2140
|
+
this.__interp_record();
|
|
2141
|
+
|
|
2142
|
+
// Stage 9: sleep test.
|
|
2143
|
+
this.__sleep_test(dt);
|
|
2144
|
+
|
|
2145
|
+
// Stage 10: diff manifolds against the previous frame and dispatch
|
|
2146
|
+
// Begin / Stay / End events. MUST run before advance_frame, which
|
|
2147
|
+
// rolls the touched flags.
|
|
2148
|
+
diff_manifolds(manifolds, storage, this.contactEvents);
|
|
2149
|
+
this.__dispatch_contact_events();
|
|
2150
|
+
|
|
2151
|
+
// Stage 11 (end-of-step): roll touched → prev_touched and the
|
|
2152
|
+
// had-contacts flag, evict slots whose pair has not been touched
|
|
2153
|
+
// within the grace window. Dormant pairs (both bodies asleep) are
|
|
2154
|
+
// frozen — contacts and warm-start impulses survive the nap.
|
|
2155
|
+
manifolds.advance_frame(storage);
|
|
2156
|
+
|
|
2157
|
+
// Dev tripwire (assert.* is compiled out of prod): no NaN / Infinity
|
|
2158
|
+
// may survive a step in body state or contact manifolds. NaN is
|
|
2159
|
+
// self-concealing downstream — it fails every depth comparison and
|
|
2160
|
+
// sleep threshold — so it must fail loudly here, at the step boundary.
|
|
2161
|
+
assert.equal(find_non_finite_physics_state(this), "", "non-finite physics state after fixedUpdate");
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
/**
|
|
2166
|
+
* @readonly
|
|
2167
|
+
* @type {boolean}
|
|
2168
|
+
*/
|
|
2169
|
+
PhysicsSystem.prototype.isPhysicsSystem = true;
|
|
2170
|
+
|
|
2171
|
+
// Re-export for convenience.
|
|
2172
|
+
export { BodyKind, RigidBodyFlags };
|