@woosh/meep-engine 2.155.0 → 2.156.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 +1 -1
- 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/package.json +1 -1
- package/src/core/binary/32BitEncoder.js +1 -1
- package/src/core/binary/to_half_float_uint16.js +3 -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/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/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/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/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/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/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/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/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/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/core/geom/3d/shape/MeshShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/MeshShape3D.js +7 -0
- 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/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 +3 -3
- 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 +3 -3
- 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 +3 -3
- 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 +3 -3
- 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/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/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/random/randomIntegerBetween.d.ts.map +1 -1
- package/src/core/math/random/randomIntegerBetween.js +4 -1
- 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/visual/NodeGraphVisualData.d.ts +1 -0
- package/src/core/model/node-graph/visual/NodeGraphVisualData.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/NodeGraphVisualData.js +2 -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/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/action/AsynchronousDelayAction.d.ts.map +1 -1
- package/src/core/process/action/AsynchronousDelayAction.js +3 -0
- 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 +3 -3
- package/src/engine/animation/curve/AnimationCurve.d.ts.map +1 -1
- package/src/engine/animation/curve/AnimationCurve.js +4 -2
- 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/graphics/camera/testClippingPlaneComputation.js +1 -1
- package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +1 -1
- package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +1 -1
- 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/visibility/hiz/prototypeHiZ.js +1 -1
- package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +1 -1
- package/src/engine/graphics/shadows/testShadowMapRendering.js +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/PLAN.md +6 -5
- 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 +147 -33
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +1750 -1747
- package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
- package/src/engine/physics/gjk/gjk_epa_penetration.d.ts.map +1 -1
- package/src/engine/physics/gjk/gjk_epa_penetration.js +5 -9
- package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/convex_convex_manifold.js +22 -25
- 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/mesh_convex_hull.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/mesh_convex_hull.js +13 -8
- 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/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/graphics/sh3/path_tracer/sampling/v3_orthonormal_matrix_from_normal.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/{engine/graphics/sh3/path_tracer/sampling → core/geom/vec3}/v3_orthonormal_matrix_from_normal.d.ts +0 -0
|
@@ -1,213 +1,405 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* - `
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* -
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* -
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
this.
|
|
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
|
-
|
|
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
|
-
controller.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if
|
|
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
|
-
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
import { clamp } from "../../../../core/math/clamp.js";
|
|
3
|
+
import { DEG_TO_RAD } from "../../../../core/math/DEG_TO_RAD.js";
|
|
4
|
+
import { Ray3 } from "../../../../core/geom/3d/ray/Ray3.js";
|
|
5
|
+
import { PhysicsSurfacePoint } from "../../../physics/queries/PhysicsSurfacePoint.js";
|
|
6
|
+
import { FirstPersonPosture } from "../pose/FirstPersonPosture.js";
|
|
7
|
+
import { Ability } from "./Ability.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Ledge-grab ability — catch a forward ledge while descending, then HANG
|
|
11
|
+
* from it and traverse it: shimmy along the edge, pull up / vault over it,
|
|
12
|
+
* or dismount.
|
|
13
|
+
*
|
|
14
|
+
* Activation (AUTO-CATCH):
|
|
15
|
+
* - `sensors.ledgeAhead.hit` — a forward+up obstacle probe found a
|
|
16
|
+
* grabbable edge (the same probe mantle uses). This already implies the
|
|
17
|
+
* body is facing a wall with a top, so even neutral input catches it.
|
|
18
|
+
* - `runtime.velocityY <= 0` — descending or static. We don't auto-catch
|
|
19
|
+
* on the way UP (that would feel like the world grabbed you mid-jump).
|
|
20
|
+
* - `state.airborneTime >= minAirborneTime` — a small post-takeoff window
|
|
21
|
+
* where ledge-grab can't fire even if instantly at apex.
|
|
22
|
+
* - NOT moving away — the move intent, taken to world space and projected
|
|
23
|
+
* onto the wall's outward normal, must not exceed `moveAwayThreshold`.
|
|
24
|
+
* You won't catch a ledge you're deliberately leaving (this also blocks
|
|
25
|
+
* a same-tick re-grab right after an away-dismount).
|
|
26
|
+
*
|
|
27
|
+
* The hanging input model (evaluated every tick): the move intent is taken
|
|
28
|
+
* to WORLD space and decomposed against the wall frame captured at grab —
|
|
29
|
+
* the outward normal `n` and the horizontal edge tangent `t = (-nz, nx)`.
|
|
30
|
+
* This makes toward / away / lateral facing-INDEPENDENT, which is exactly
|
|
31
|
+
* what makes "turn the camera to look away ≠ dismount" fall out for free.
|
|
32
|
+
*
|
|
33
|
+
* - `away = worldMove · n` (>0 = off the wall, <0 = into it)
|
|
34
|
+
* - `lateral = worldMove · t` (signed, along the edge)
|
|
35
|
+
* - `facing = forward · (-n)` (how squarely the camera faces the wall)
|
|
36
|
+
*
|
|
37
|
+
* Per-tick decision (mutually exclusive — opposite axes can't both be high):
|
|
38
|
+
* 1. PULL-UP / VAULT — moving toward the wall, OR jump pressed while
|
|
39
|
+
* facing within `pullUpFacingConeDeg` of it. Hands off to Mantle
|
|
40
|
+
* (`runtime.ledgePullUpRequest`): onto a standable top, or a vault
|
|
41
|
+
* over a too-thin one.
|
|
42
|
+
* 2. DISMOUNT (drop) — crouch, or an away-DOMINANT world-move past
|
|
43
|
+
* `moveAwayThreshold` (conservative: a strafe that merely bleeds into
|
|
44
|
+
* `away` shimmies instead — leaving the hang is more consequential).
|
|
45
|
+
* 3. SHIMMY — lateral intent dominant: step along the edge if it stays
|
|
46
|
+
* clear and continuous; otherwise clamp (hold) — a shimmy NEVER drops.
|
|
47
|
+
* 4. HOLD — snap to the hang pose, accrue fatigue.
|
|
48
|
+
* 5. SLIP — exertion saturates (forced release).
|
|
49
|
+
* A jump pressed while facing AWAY is consumed (no back-hop in v1) and
|
|
50
|
+
* you keep hanging.
|
|
51
|
+
*
|
|
52
|
+
* Priority 40 — above mantle (30), below wall-run (50). Mantle CAN'T
|
|
53
|
+
* preempt an active ledge-grab — that's the point of placing ledge higher.
|
|
54
|
+
*
|
|
55
|
+
* @author Alex Goldring
|
|
56
|
+
* @copyright Company Named Limited (c) 2026
|
|
57
|
+
*/
|
|
58
|
+
export class LedgeGrab extends Ability {
|
|
59
|
+
constructor() {
|
|
60
|
+
super();
|
|
61
|
+
this.name = "LedgeGrab";
|
|
62
|
+
this.priority = 40;
|
|
63
|
+
|
|
64
|
+
/** @private Wall-face anchor (x,z), the face's outward normal (x,z),
|
|
65
|
+
* and the top-edge height (y) — captured at onActivate and advanced
|
|
66
|
+
* while shimmying. The hang pose is built from the WALL, not the
|
|
67
|
+
* (possibly oblique) body facing, so it stays just outside the wall
|
|
68
|
+
* at any approach angle. */
|
|
69
|
+
this._anchorX = 0;
|
|
70
|
+
this._anchorZ = 0;
|
|
71
|
+
this._nx = 0;
|
|
72
|
+
this._nz = 0;
|
|
73
|
+
this._edgeY = 0;
|
|
74
|
+
|
|
75
|
+
/** @private Scratch query primitives for the shimmy probes — refilled
|
|
76
|
+
* in place so a hanging player doesn't allocate each tick. */
|
|
77
|
+
this._ray = new Ray3();
|
|
78
|
+
this._hit = new PhysicsSurfacePoint();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
canActivate(controller, runtime, sensors) {
|
|
82
|
+
const cfg = controller.config.ledgeGrab;
|
|
83
|
+
if (!cfg) return false;
|
|
84
|
+
if (sensors === undefined || sensors === null) return false;
|
|
85
|
+
|
|
86
|
+
// Refractory window after a release — don't immediately re-grab the
|
|
87
|
+
// lip we just dismounted from (the auto-catch is otherwise eager
|
|
88
|
+
// enough to snap us straight back onto it while we're still falling
|
|
89
|
+
// clear of it).
|
|
90
|
+
if (runtime.ledgeRegrabCooldown > 0) return false;
|
|
91
|
+
|
|
92
|
+
if (!sensors.ledgeAhead.hit) return false;
|
|
93
|
+
if (runtime.velocityY > 0) return false; // not on the way up
|
|
94
|
+
if (controller.state.grounded) return false;
|
|
95
|
+
if (controller.state.airborneTime < cfg.minAirborneTime) return false;
|
|
96
|
+
// Crouch or exhausted: don't re-grab. These are the same exit
|
|
97
|
+
// conditions that would IMMEDIATELY release after activation, so
|
|
98
|
+
// gating them here prevents a same-tick re-activation flicker.
|
|
99
|
+
if (controller.intent.crouch) return false;
|
|
100
|
+
if (controller.state.exertion >= 1.0) return false;
|
|
101
|
+
|
|
102
|
+
// Auto-catch, but not a ledge we're deliberately LEAVING: decompose
|
|
103
|
+
// the world move against the obstacle face normal (ledgeAhead.hit
|
|
104
|
+
// implies obstacleAhead.hit, so the face data is present). Moving away
|
|
105
|
+
// past the threshold refuses the grab — which also prevents a same-tick
|
|
106
|
+
// re-grab right after an away-dismount.
|
|
107
|
+
const face = sensors.obstacleAhead;
|
|
108
|
+
if (face.hit) {
|
|
109
|
+
const away = this._worldMoveDot(controller, runtime, face.normal.x, face.normal.z);
|
|
110
|
+
if (away > cfg.moveAwayThreshold) return false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
onActivate(controller, runtime) {
|
|
117
|
+
const sensors = runtime.sensors;
|
|
118
|
+
|
|
119
|
+
// Clear any stale pull-up request — a fresh grab starts neutral.
|
|
120
|
+
runtime.ledgePullUpRequest = false;
|
|
121
|
+
|
|
122
|
+
// Anchor on the wall face + its outward normal (ledgeAhead is only
|
|
123
|
+
// probed when obstacleAhead hits, so the face data is always present
|
|
124
|
+
// here). The top-edge height comes from the ledge probe.
|
|
125
|
+
this._anchorX = sensors.obstacleAhead.point.x;
|
|
126
|
+
this._anchorZ = sensors.obstacleAhead.point.z;
|
|
127
|
+
this._nx = sensors.obstacleAhead.normal.x;
|
|
128
|
+
this._nz = sensors.obstacleAhead.normal.z;
|
|
129
|
+
this._edgeY = sensors.ledgeAhead.point.y;
|
|
130
|
+
|
|
131
|
+
// -- Preconditions (dev-only; compiled out of prod). The hang frame is
|
|
132
|
+
// built entirely from these — a bad capture here is the kind of
|
|
133
|
+
// thing that silently produces a degenerate pose now and an
|
|
134
|
+
// inexplicable camera jump later.
|
|
135
|
+
assert.ok(sensors.obstacleAhead.hit,
|
|
136
|
+
"LedgeGrab: activated without an obstacleAhead hit (no wall to anchor the hang)");
|
|
137
|
+
assert.ok(sensors.ledgeAhead.hit,
|
|
138
|
+
"LedgeGrab: activated without a ledgeAhead hit (no edge to grab)");
|
|
139
|
+
// The wall normal must be roughly horizontal + unit — the whole
|
|
140
|
+
// wall-frame model (toward/away/lateral, shimmy tangent, hang standoff)
|
|
141
|
+
// assumes it. A near-zero horizontal normal (e.g. a floor/slope hit)
|
|
142
|
+
// would collapse the frame.
|
|
143
|
+
assert.greaterThan(Math.hypot(this._nx, this._nz), 0.5,
|
|
144
|
+
"LedgeGrab: wall normal is not horizontal — degenerate hang/shimmy frame");
|
|
145
|
+
assert.ok(
|
|
146
|
+
Number.isFinite(this._anchorX) && Number.isFinite(this._anchorZ) && Number.isFinite(this._edgeY),
|
|
147
|
+
"LedgeGrab: captured a non-finite hang anchor/edge",
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
// Zero velocity — the body is now parked on the ledge.
|
|
151
|
+
runtime.velocityX = 0;
|
|
152
|
+
runtime.velocityY = 0;
|
|
153
|
+
runtime.velocityZ = 0;
|
|
154
|
+
|
|
155
|
+
// Clear any in-progress jump state — hanging supersedes them.
|
|
156
|
+
runtime.midJump = false;
|
|
157
|
+
runtime.apexFired = false;
|
|
158
|
+
controller.state.isVariableJumpCut = false;
|
|
159
|
+
controller.state.isAscending = false;
|
|
160
|
+
|
|
161
|
+
// The body is hanging — not on the ground.
|
|
162
|
+
controller.state.grounded = false;
|
|
163
|
+
|
|
164
|
+
// Body is suspended by the hands; L2 reads posture to gate gait and
|
|
165
|
+
// set eye height.
|
|
166
|
+
controller.state.posture = FirstPersonPosture.Hang;
|
|
167
|
+
|
|
168
|
+
controller.signals.onLedgeGrab.send1({
|
|
169
|
+
ledgeHeight: this._edgeY - controller.pose.rootPosition.y,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
canInterrupt() {
|
|
174
|
+
// Wall-run / wall-jump can preempt if their conditions somehow hold
|
|
175
|
+
// (unusual mid-hang). Higher-priority abilities shouldn't be blocked.
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
onDeactivate(controller, runtime) {
|
|
180
|
+
// Open the re-grab refractory window on EVERY release (drop, slip,
|
|
181
|
+
// pull-up, shuffle-off). Covers the case where the dismount input
|
|
182
|
+
// returns to neutral while the body is still inside the grab window —
|
|
183
|
+
// without this the auto-catch re-fires next tick and snaps us back
|
|
184
|
+
// onto the lip.
|
|
185
|
+
runtime.ledgeRegrabCooldown = controller.config.ledgeGrab.regrabCooldown;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
tick(controller, runtime, bodyTransform, dt, _system) {
|
|
189
|
+
const cfg = controller.config.ledgeGrab;
|
|
190
|
+
const intent = controller.intent;
|
|
191
|
+
|
|
192
|
+
// Re-assert posture each tick (defence against any layer resetting it
|
|
193
|
+
// before L2 reads). Body parked against the wall — no lean.
|
|
194
|
+
controller.state.posture = FirstPersonPosture.Hang;
|
|
195
|
+
runtime.leanTargetRad = 0;
|
|
196
|
+
|
|
197
|
+
// -- Exit: lost the ledge. Probe the CAPTURED anchor (not the
|
|
198
|
+
// facing-relative sensor) so turning to look away from the wall
|
|
199
|
+
// never reads as "ledge lost" — that's the whole point of the
|
|
200
|
+
// wall-frame model. Releases only when the lip genuinely isn't
|
|
201
|
+
// under us any more (e.g. the wall was removed).
|
|
202
|
+
if (!this._ledgeStillThere(runtime, cfg, _system)) {
|
|
203
|
+
controller.signals.onLedgeRelease.send1({ reason: "shuffle-off" });
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// -- Decompose the move intent against the captured wall frame. These
|
|
208
|
+
// are facing-INDEPENDENT (built from n/t, not the camera) — looking
|
|
209
|
+
// away changes `facing` but not away/lateral, so it can't dismount.
|
|
210
|
+
const away = this._worldMoveDot(controller, runtime, this._nx, this._nz);
|
|
211
|
+
const lateral = this._worldMoveDot(controller, runtime, -this._nz, this._nx);
|
|
212
|
+
const { sinYaw, cosYaw } = runtime;
|
|
213
|
+
const facing = sinYaw * (-this._nx) + cosYaw * (-this._nz);
|
|
214
|
+
const jumpEdge = intent.jump && !runtime.prevJumpHeld;
|
|
215
|
+
const coneCos = Math.cos(cfg.pullUpFacingConeDeg * DEG_TO_RAD);
|
|
216
|
+
|
|
217
|
+
// -- (1) Pull-up / vault: moving toward the wall, OR a jump press while
|
|
218
|
+
// facing into it. Request the climb; Mantle (next tick) resolves it
|
|
219
|
+
// onto a standable top, or vaults over a too-thin one. The small
|
|
220
|
+
// upward kick keeps mantle's ledgeAhead probe resolving correctly.
|
|
221
|
+
if (away < -cfg.moveTowardThreshold || (jumpEdge && facing > coneCos)) {
|
|
222
|
+
runtime.ledgePullUpRequest = true;
|
|
223
|
+
runtime.velocityY = runtime.jumpInitialVy * cfg.mantleUpUpFactor;
|
|
224
|
+
if (jumpEdge) runtime.prevJumpHeld = true;
|
|
225
|
+
runtime.midJump = true;
|
|
226
|
+
controller.state.isAscending = true;
|
|
227
|
+
controller.signals.onLedgeRelease.send1({ reason: "mantle-up" });
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
// Consume a jump press that DIDN'T pull up (facing away) so it doesn't
|
|
231
|
+
// fire later; stay hanging — looking away never auto-acts.
|
|
232
|
+
if (jumpEdge) runtime.prevJumpHeld = true;
|
|
233
|
+
|
|
234
|
+
// -- (2) Dismount. Crouch is an explicit, unconditional dismount.
|
|
235
|
+
// Movement-away is CONSERVATIVE: leaving the hang (you fall) is more
|
|
236
|
+
// consequential than shimmying, so a strafe taken while looking
|
|
237
|
+
// somewhat off the wall — which bleeds a little into `away` — reads
|
|
238
|
+
// as a SHIMMY (handled below), not an ejection. Only a stick that
|
|
239
|
+
// clearly points OFF the edge (away-DOMINANT, past the threshold)
|
|
240
|
+
// drops you.
|
|
241
|
+
if (intent.crouch) {
|
|
242
|
+
controller.signals.onLedgeRelease.send1({ reason: "drop" });
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
if (away > cfg.moveAwayThreshold && away > Math.abs(lateral)) {
|
|
246
|
+
controller.signals.onLedgeRelease.send1({ reason: "drop" });
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// -- (5) Slip: exertion saturated → forced release.
|
|
251
|
+
if (controller.state.exertion >= 1.0) {
|
|
252
|
+
controller.signals.onLedgeRelease.send1({ reason: "slip" });
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// -- (3) Shimmy: lateral intent dominant → try one step along the edge.
|
|
257
|
+
// A blocked or discontinuous edge clamps (we stay hanging here),
|
|
258
|
+
// never drops.
|
|
259
|
+
let shimmying = false;
|
|
260
|
+
if (Math.abs(lateral) > cfg.shimmyLateralMin && Math.abs(lateral) >= Math.abs(away)) {
|
|
261
|
+
shimmying = this._tryShimmy(controller, runtime, cfg, Math.sign(lateral), dt, _system);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// -- (4) Hold (or post-shimmy advance): snap to the hang pose just
|
|
265
|
+
// OUTSIDE the wall face, gripping the top edge. The body centre sits
|
|
266
|
+
// a capsule radius (+ a small gap) out from the face along its
|
|
267
|
+
// outward normal — anchoring on the WALL keeps the body clear even
|
|
268
|
+
// when the ledge was reached obliquely (a facing-relative offset
|
|
269
|
+
// would sink it into a thin wall).
|
|
270
|
+
const standoff = controller.config.body.radius + cfg.hangOffsetForward;
|
|
271
|
+
bodyTransform.position.set(
|
|
272
|
+
this._anchorX + this._nx * standoff,
|
|
273
|
+
this._edgeY + cfg.hangOffsetY,
|
|
274
|
+
this._anchorZ + this._nz * standoff,
|
|
275
|
+
);
|
|
276
|
+
runtime.velocityX = 0;
|
|
277
|
+
runtime.velocityY = 0;
|
|
278
|
+
runtime.velocityZ = 0;
|
|
279
|
+
controller.state.grounded = false;
|
|
280
|
+
|
|
281
|
+
// Teleport-snap the camera on a parked (non-shimmying) hang: the body
|
|
282
|
+
// was just snapped onto the wall from wherever it was falling, so the
|
|
283
|
+
// render interpolation must JUMP to the hang pose, not glide into it.
|
|
284
|
+
// During a shimmy the body moves smoothly, so we let it interpolate.
|
|
285
|
+
if (!shimmying) runtime.renderSnap = true;
|
|
286
|
+
|
|
287
|
+
// Exertion rises while hanging — fatigue. Faster while actively
|
|
288
|
+
// shimmying. Mass-scaled like the rest of the exertion system.
|
|
289
|
+
const exertRate = cfg.exertionRiseRate * (shimmying ? cfg.shimmyExertionFactor : 1);
|
|
290
|
+
controller.state.exertion = clamp(
|
|
291
|
+
controller.state.exertion + exertRate * dt
|
|
292
|
+
* runtime.massRatios.exertionRiseScale,
|
|
293
|
+
0, 1,
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* World-space move intent (clamped to the unit disk) dotted with a
|
|
301
|
+
* horizontal axis (ax, az). Uses the controller's own move→world
|
|
302
|
+
* convention (screen_fwd = (sinYaw, cosYaw)). Facing-independent by
|
|
303
|
+
* construction — it's the intent in WORLD space, not camera space.
|
|
304
|
+
* @private
|
|
305
|
+
*/
|
|
306
|
+
_worldMoveDot(controller, runtime, ax, az) {
|
|
307
|
+
const { sinYaw, cosYaw } = runtime;
|
|
308
|
+
let mx = controller.intent.move.x;
|
|
309
|
+
let my = controller.intent.move.y;
|
|
310
|
+
const len = Math.hypot(mx, my);
|
|
311
|
+
if (len > 1) { mx /= len; my /= len; }
|
|
312
|
+
const wmx = sinYaw * my - cosYaw * mx;
|
|
313
|
+
const wmz = cosYaw * my + sinYaw * mx;
|
|
314
|
+
return wmx * ax + wmz * az;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Is the grabbed lip still under us? Probes the CAPTURED anchor (a down-ray
|
|
319
|
+
* just past the face, into the wall along −n), independent of where the
|
|
320
|
+
* camera looks — so turning to look away never reads as "ledge lost". Falls
|
|
321
|
+
* back to the facing-relative sensor only when no physics backend is present
|
|
322
|
+
* (the flat-ground unit harness, which simulates loss via that sensor).
|
|
323
|
+
* @private
|
|
324
|
+
*/
|
|
325
|
+
_ledgeStillThere(runtime, cfg, system) {
|
|
326
|
+
const physics = system && system.physicsSystem;
|
|
327
|
+
if (!physics) return runtime.sensors.ledgeAhead.hit;
|
|
328
|
+
|
|
329
|
+
const ray = this._ray;
|
|
330
|
+
const hit = this._hit;
|
|
331
|
+
ray.setOrigin(
|
|
332
|
+
this._anchorX - this._nx * cfg.shimmyEdgeProbeForward,
|
|
333
|
+
this._edgeY + cfg.shimmyContinuityProbeUp,
|
|
334
|
+
this._anchorZ - this._nz * cfg.shimmyEdgeProbeForward,
|
|
335
|
+
);
|
|
336
|
+
ray.setDirection(0, -1, 0);
|
|
337
|
+
ray.tMax = cfg.shimmyContinuityProbeUp + cfg.shimmyContinuityProbeDown;
|
|
338
|
+
const filter = (_e, c) => c !== runtime.collider;
|
|
339
|
+
if (!physics.raycast(ray, hit, filter)) return false;
|
|
340
|
+
return Math.abs(hit.position.y - this._edgeY) <= cfg.shimmyContinuityTol;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Attempt one shimmy step of `dir` (±1) along the edge tangent. Returns
|
|
345
|
+
* true if it stepped (clear AND continuous), false if it CLAMPED — a clamp
|
|
346
|
+
* holds in place, it never drops. On success it advances the anchor and
|
|
347
|
+
* re-captures the edge height so an undulating top is tracked.
|
|
348
|
+
*
|
|
349
|
+
* Two probes, both must pass:
|
|
350
|
+
* (A) lateral CLEARANCE — a ray along the tangent from the body centre
|
|
351
|
+
* must be free for the step (a perpendicular/concave wall blocks it).
|
|
352
|
+
* (B) edge CONTINUITY — a down-ray just past the shifted edge must find
|
|
353
|
+
* the lip still at ~edge height (else the edge ended).
|
|
354
|
+
* Needs the physics backend; without it (flat-ground unit harness) it
|
|
355
|
+
* can't verify geometry, so it clamps.
|
|
356
|
+
* @private
|
|
357
|
+
*/
|
|
358
|
+
_tryShimmy(controller, runtime, cfg, dir, dt, system) {
|
|
359
|
+
const physics = system && system.physicsSystem;
|
|
360
|
+
if (!physics) return false; // no spatial backend → can't verify → clamp
|
|
361
|
+
|
|
362
|
+
const r = controller.config.body.radius;
|
|
363
|
+
const standoff = r + cfg.hangOffsetForward;
|
|
364
|
+
// Edge tangent (n is unit, so t is unit). dir picks the direction.
|
|
365
|
+
const tx = dir * (-this._nz);
|
|
366
|
+
const tz = dir * this._nx;
|
|
367
|
+
const step = cfg.shimmySpeed * dt;
|
|
368
|
+
const filter = (_e, c) => c !== runtime.collider; // exclude own body
|
|
369
|
+
const ray = this._ray;
|
|
370
|
+
const hit = this._hit;
|
|
371
|
+
|
|
372
|
+
// Body centre at the current hang pose.
|
|
373
|
+
const bx = this._anchorX + this._nx * standoff;
|
|
374
|
+
const bz = this._anchorZ + this._nz * standoff;
|
|
375
|
+
|
|
376
|
+
// (A) Lateral clearance along the tangent.
|
|
377
|
+
ray.setOrigin(bx, this._edgeY + cfg.shimmyClearanceProbeY, bz);
|
|
378
|
+
ray.setDirection(tx, 0, tz);
|
|
379
|
+
ray.tMax = step + r + cfg.shimmyClearanceGap;
|
|
380
|
+
if (physics.raycast(ray, hit, filter)) return false; // blocked → clamp
|
|
381
|
+
|
|
382
|
+
// (B) Edge continuity: down-probe just past the SHIFTED edge. The top
|
|
383
|
+
// surface sits INTO the wall from the face (along -n), so offset the
|
|
384
|
+
// probe that way before dropping it.
|
|
385
|
+
const nex = this._anchorX + tx * step;
|
|
386
|
+
const nez = this._anchorZ + tz * step;
|
|
387
|
+
ray.setOrigin(
|
|
388
|
+
nex - this._nx * cfg.shimmyEdgeProbeForward,
|
|
389
|
+
this._edgeY + cfg.shimmyContinuityProbeUp,
|
|
390
|
+
nez - this._nz * cfg.shimmyEdgeProbeForward,
|
|
391
|
+
);
|
|
392
|
+
ray.setDirection(0, -1, 0);
|
|
393
|
+
ray.tMax = cfg.shimmyContinuityProbeUp + cfg.shimmyContinuityProbeDown;
|
|
394
|
+
if (!physics.raycast(ray, hit, filter)) return false; // edge ended → clamp
|
|
395
|
+
if (Math.abs(hit.position.y - this._edgeY) > cfg.shimmyContinuityTol) return false;
|
|
396
|
+
|
|
397
|
+
// Commit: advance along the face and track the (possibly undulating)
|
|
398
|
+
// lip. The wall normal is kept constant — a straight face is the common
|
|
399
|
+
// case; wrapping a curving/convex wall is a v2 refinement.
|
|
400
|
+
this._anchorX = nex;
|
|
401
|
+
this._anchorZ = nez;
|
|
402
|
+
this._edgeY = hit.position.y;
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
}
|