@woosh/meep-engine 2.138.20 → 2.139.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/package.json +1 -1
- package/src/core/collection/PairUint32Map.d.ts +100 -0
- package/src/core/collection/PairUint32Map.d.ts.map +1 -0
- package/src/core/collection/PairUint32Map.js +321 -0
- package/src/core/collection/Uint32Map.d.ts +119 -0
- package/src/core/collection/Uint32Map.d.ts.map +1 -0
- package/src/core/collection/Uint32Map.js +345 -0
- package/src/core/collection/array/array_shuffle.d.ts +10 -3
- package/src/core/collection/array/array_shuffle.d.ts.map +1 -1
- package/src/core/collection/array/array_shuffle.js +27 -22
- package/src/core/collection/heap/FibonacciHeap.d.ts +195 -0
- package/src/core/collection/heap/FibonacciHeap.d.ts.map +1 -0
- package/src/core/collection/heap/FibonacciHeap.js +586 -0
- package/src/core/collection/heap/Uint32Heap.js +1 -1
- package/src/core/collection/heap/Uint32Heap4.d.ts +169 -0
- package/src/core/collection/heap/Uint32Heap4.d.ts.map +1 -0
- package/src/core/collection/heap/Uint32Heap4.js +490 -0
- package/src/core/geom/3d/line/line3_closest_points_segment_segment.d.ts +27 -0
- package/src/core/geom/3d/line/line3_closest_points_segment_segment.d.ts.map +1 -0
- package/src/core/geom/3d/line/line3_closest_points_segment_segment.js +88 -0
- package/src/core/geom/3d/shape/BoxShape3D.d.ts +61 -0
- package/src/core/geom/3d/shape/BoxShape3D.d.ts.map +1 -0
- package/src/core/geom/3d/shape/BoxShape3D.js +158 -0
- package/src/core/geom/3d/shape/CapsuleShape3D.d.ts +11 -0
- package/src/core/geom/3d/shape/CapsuleShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/CapsuleShape3D.js +12 -0
- package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts +37 -9
- package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/UnitCubeShape3D.js +45 -98
- package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts +10 -0
- package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/UnitSphereShape3D.js +11 -0
- package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.d.ts +61 -0
- package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.d.ts.map +1 -0
- package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +148 -0
- package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.d.ts +39 -0
- package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.js +147 -0
- package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.d.ts +15 -0
- package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.js +22 -0
- package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.d.ts +2 -0
- package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.js +673 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts +26 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +222 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.d.ts +34 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.js +146 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.d.ts +36 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.js +232 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.d.ts +33 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.js +255 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts +68 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +365 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts +31 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +112 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts +22 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +55 -0
- package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.d.ts +32 -0
- package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.js +66 -0
- package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts +22 -0
- package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +49 -0
- package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts +134 -0
- package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +276 -3
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts +17 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +135 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.d.ts +14 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.js +177 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.js +20 -4
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.js +5 -3
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +9 -0
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.js +21 -45
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill.js +7 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.d.ts +8 -6
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.js +8 -6
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.d.ts +22 -0
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.js +73 -0
- package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.js +51 -1
- package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.d.ts +10 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.js +42 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts +28 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +227 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.d.ts +13 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.js +108 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.d.ts +11 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.js +20 -0
- package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.d.ts +20 -0
- package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.d.ts.map +1 -0
- package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.js +38 -0
- package/src/core/graph/csr/CSRGraph.d.ts +168 -0
- package/src/core/graph/csr/CSRGraph.d.ts.map +1 -0
- package/src/core/graph/csr/CSRGraph.js +319 -0
- package/src/core/graph/metis/cluster_mesh_metis.d.ts +12 -0
- package/src/core/graph/metis/cluster_mesh_metis.d.ts.map +1 -1
- package/src/core/graph/metis/cluster_mesh_metis.js +12 -0
- package/src/core/graph/metis/metis.d.ts +19 -0
- package/src/core/graph/metis/metis.d.ts.map +1 -1
- package/src/core/graph/metis/metis.js +20 -0
- package/src/core/graph/metis/metis_cluster_bs.d.ts +11 -0
- package/src/core/graph/metis/metis_cluster_bs.d.ts.map +1 -1
- package/src/core/graph/metis/metis_cluster_bs.js +11 -0
- package/src/core/graph/metis/metis_options.d.ts +17 -2
- package/src/core/graph/metis/metis_options.d.ts.map +1 -1
- package/src/core/graph/metis/metis_options.js +17 -2
- package/src/core/graph/metis/native/MetisGraph.d.ts +144 -0
- package/src/core/graph/metis/native/MetisGraph.d.ts.map +1 -0
- package/src/core/graph/metis/native/MetisGraph.js +212 -0
- package/src/core/graph/metis/native/bisection/BisectionScratch.d.ts +72 -0
- package/src/core/graph/metis/native/bisection/BisectionScratch.d.ts.map +1 -0
- package/src/core/graph/metis/native/bisection/BisectionScratch.js +101 -0
- package/src/core/graph/metis/native/bisection/bisect_graph.d.ts +37 -0
- package/src/core/graph/metis/native/bisection/bisect_graph.d.ts.map +1 -0
- package/src/core/graph/metis/native/bisection/bisect_graph.js +100 -0
- package/src/core/graph/metis/native/bisection/compute_2way_params.d.ts +15 -0
- package/src/core/graph/metis/native/bisection/compute_2way_params.d.ts.map +1 -0
- package/src/core/graph/metis/native/bisection/compute_2way_params.js +84 -0
- package/src/core/graph/metis/native/bisection/fm_2way.d.ts +30 -0
- package/src/core/graph/metis/native/bisection/fm_2way.d.ts.map +1 -0
- package/src/core/graph/metis/native/bisection/fm_2way.js +290 -0
- package/src/core/graph/metis/native/bisection/grow_bisection.d.ts +23 -0
- package/src/core/graph/metis/native/bisection/grow_bisection.d.ts.map +1 -0
- package/src/core/graph/metis/native/bisection/grow_bisection.js +137 -0
- package/src/core/graph/metis/native/bisection/split_graph_two_way.d.ts +28 -0
- package/src/core/graph/metis/native/bisection/split_graph_two_way.d.ts.map +1 -0
- package/src/core/graph/metis/native/bisection/split_graph_two_way.js +119 -0
- package/src/core/graph/metis/native/coarsen/coarsen_graph.d.ts +20 -0
- package/src/core/graph/metis/native/coarsen/coarsen_graph.d.ts.map +1 -0
- package/src/core/graph/metis/native/coarsen/coarsen_graph.js +94 -0
- package/src/core/graph/metis/native/coarsen/create_coarse_graph.d.ts +24 -0
- package/src/core/graph/metis/native/coarsen/create_coarse_graph.d.ts.map +1 -0
- package/src/core/graph/metis/native/coarsen/create_coarse_graph.js +158 -0
- package/src/core/graph/metis/native/coarsen/match_shem.d.ts +41 -0
- package/src/core/graph/metis/native/coarsen/match_shem.d.ts.map +1 -0
- package/src/core/graph/metis/native/coarsen/match_shem.js +175 -0
- package/src/core/graph/metis/native/initial/initial_kway_bfs.d.ts +24 -0
- package/src/core/graph/metis/native/initial/initial_kway_bfs.d.ts.map +1 -0
- package/src/core/graph/metis/native/initial/initial_kway_bfs.js +122 -0
- package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.d.ts +29 -0
- package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.d.ts.map +1 -0
- package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.js +170 -0
- package/src/core/graph/metis/native/metis_partition_kway.d.ts +41 -0
- package/src/core/graph/metis/native/metis_partition_kway.d.ts.map +1 -0
- package/src/core/graph/metis/native/metis_partition_kway.js +126 -0
- package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.d.ts +62 -0
- package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.d.ts.map +1 -0
- package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.js +261 -0
- package/src/core/graph/metis/native/refine/RefinementScratch.d.ts +45 -0
- package/src/core/graph/metis/native/refine/RefinementScratch.d.ts.map +1 -0
- package/src/core/graph/metis/native/refine/RefinementScratch.js +53 -0
- package/src/core/graph/metis/native/refine/compute_kway_params.d.ts +18 -0
- package/src/core/graph/metis/native/refine/compute_kway_params.d.ts.map +1 -0
- package/src/core/graph/metis/native/refine/compute_kway_params.js +138 -0
- package/src/core/graph/metis/native/refine/fm_kway.d.ts +63 -0
- package/src/core/graph/metis/native/refine/fm_kway.d.ts.map +1 -0
- package/src/core/graph/metis/native/refine/fm_kway.js +462 -0
- package/src/core/graph/metis/native/refine/project_kway.d.ts +22 -0
- package/src/core/graph/metis/native/refine/project_kway.d.ts.map +1 -0
- package/src/core/graph/metis/native/refine/project_kway.js +43 -0
- package/src/core/graph/metis/native/refine/refine_kway.d.ts +34 -0
- package/src/core/graph/metis/native/refine/refine_kway.d.ts.map +1 -0
- package/src/core/graph/metis/native/refine/refine_kway.js +43 -0
- package/src/core/math/linalg/eigen/matrix_householder_in_place.d.ts +2 -2
- package/src/core/math/linalg/eigen/matrix_householder_in_place.js +2 -2
- package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts +6 -4
- package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts.map +1 -1
- package/src/core/math/linalg/eigen/matrix_qr_in_place.js +69 -23
- package/src/engine/EngineHarness.d.ts +3 -1
- package/src/engine/EngineHarness.d.ts.map +1 -1
- package/src/engine/EngineHarness.js +3 -0
- package/src/engine/control/first-person/DESIGN.md +30 -6
- package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +563 -0
- package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +102 -9
- package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerController.js +38 -3
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +533 -4
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +315 -6
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts +220 -22
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +858 -241
- package/src/engine/control/first-person/TODO.md +127 -0
- package/src/engine/control/first-person/abilities/Ability.d.ts +101 -0
- package/src/engine/control/first-person/abilities/Ability.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/Ability.js +119 -0
- package/src/engine/control/first-person/abilities/AbilitySet.d.ts +86 -0
- package/src/engine/control/first-person/abilities/AbilitySet.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/AbilitySet.js +185 -0
- package/src/engine/control/first-person/abilities/LedgeGrab.d.ts +62 -0
- package/src/engine/control/first-person/abilities/LedgeGrab.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/LedgeGrab.js +199 -0
- package/src/engine/control/first-person/abilities/Mantle.d.ts +45 -0
- package/src/engine/control/first-person/abilities/Mantle.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/Mantle.js +188 -0
- package/src/engine/control/first-person/abilities/Slide.d.ts +33 -0
- package/src/engine/control/first-person/abilities/Slide.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/Slide.js +158 -0
- package/src/engine/control/first-person/abilities/WallJump.d.ts +45 -0
- package/src/engine/control/first-person/abilities/WallJump.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/WallJump.js +131 -0
- package/src/engine/control/first-person/abilities/WallRun.d.ts +44 -0
- package/src/engine/control/first-person/abilities/WallRun.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/WallRun.js +180 -0
- package/src/engine/control/first-person/composer/EyeOffsetStack.d.ts +49 -0
- package/src/engine/control/first-person/composer/EyeOffsetStack.d.ts.map +1 -0
- package/src/engine/control/first-person/composer/EyeOffsetStack.js +60 -0
- package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.d.ts +100 -0
- package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.js +133 -0
- package/src/engine/control/first-person/mastery/DecisionPoint.d.ts +10 -0
- package/src/engine/control/first-person/mastery/DecisionPoint.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/DecisionPoint.js +30 -0
- package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.d.ts +61 -0
- package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.js +109 -0
- package/src/engine/control/first-person/mastery/MasteryEvaluator.d.ts +40 -0
- package/src/engine/control/first-person/mastery/MasteryEvaluator.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/MasteryEvaluator.js +45 -0
- package/src/engine/control/first-person/mastery/MasteryScore.d.ts +68 -0
- package/src/engine/control/first-person/mastery/MasteryScore.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/MasteryScore.js +100 -0
- package/src/engine/control/first-person/mastery/MasterySet.d.ts +60 -0
- package/src/engine/control/first-person/mastery/MasterySet.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/MasterySet.js +86 -0
- package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts +58 -0
- package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.js +83 -0
- package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts +69 -0
- package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.js +109 -0
- package/src/engine/control/first-person/math/Spring.d.ts +56 -0
- package/src/engine/control/first-person/math/Spring.d.ts.map +1 -0
- package/src/engine/control/first-person/math/Spring.js +71 -0
- package/src/engine/control/first-person/math/computeLRCBreathRate.d.ts +26 -0
- package/src/engine/control/first-person/math/computeLRCBreathRate.d.ts.map +1 -0
- package/src/engine/control/first-person/math/computeLRCBreathRate.js +41 -0
- package/src/engine/control/first-person/math/computeMassRatios.d.ts +35 -0
- package/src/engine/control/first-person/math/computeMassRatios.d.ts.map +1 -0
- package/src/engine/control/first-person/math/computeMassRatios.js +44 -0
- package/src/engine/control/first-person/pose/FirstPersonPose.d.ts +31 -1
- package/src/engine/control/first-person/pose/FirstPersonPose.d.ts.map +1 -1
- package/src/engine/control/first-person/pose/FirstPersonPose.js +49 -3
- package/src/engine/control/first-person/pose/FirstPersonPosture.d.ts +7 -0
- package/src/engine/control/first-person/pose/FirstPersonPosture.d.ts.map +1 -0
- package/src/engine/control/first-person/pose/FirstPersonPosture.js +27 -0
- package/src/engine/control/first-person/prototype_first_person_controller.js +550 -119
- package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts +58 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts.map +1 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensors.js +77 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts +80 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts.map +1 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.js +196 -0
- package/src/engine/control/first-person/test/buildTestPlayer.d.ts +20 -0
- package/src/engine/control/first-person/test/buildTestPlayer.d.ts.map +1 -0
- package/src/engine/control/first-person/test/buildTestPlayer.js +28 -0
- package/src/engine/graphics/camera/testClippingPlaneComputation.js +0 -2
- package/src/engine/graphics/ecs/light/Light.d.ts.map +1 -1
- package/src/engine/graphics/ecs/light/Light.js +27 -0
- package/src/engine/graphics/ecs/light/LightSystem.js +1 -1
- package/src/engine/graphics/ecs/path/PathDisplaySystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/path/testPathDisplaySystem.js +0 -2
- package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +0 -2
- package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +0 -2
- package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +0 -2
- package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +0 -2
- package/src/engine/navigation/grid/find_path_on_grid_astar.d.ts.map +1 -1
- package/src/engine/navigation/grid/find_path_on_grid_astar.js +11 -2
- package/src/engine/navigation/mesh/bt_mesh_face_find_path.d.ts.map +1 -1
- package/src/engine/navigation/mesh/bt_mesh_face_find_path.js +11 -1
- package/src/engine/physics/PLAN.md +236 -0
- package/src/engine/physics/body/BodyStorage.d.ts +187 -0
- package/src/engine/physics/body/BodyStorage.d.ts.map +1 -0
- package/src/engine/physics/body/BodyStorage.js +427 -0
- package/src/engine/physics/broadphase/PairList.d.ts +62 -0
- package/src/engine/physics/broadphase/PairList.d.ts.map +1 -0
- package/src/engine/physics/broadphase/PairList.js +97 -0
- package/src/engine/physics/broadphase/aabb_transform_oriented.d.ts +30 -0
- package/src/engine/physics/broadphase/aabb_transform_oriented.d.ts.map +1 -0
- package/src/engine/physics/broadphase/aabb_transform_oriented.js +93 -0
- package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +16 -0
- package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -0
- package/src/engine/physics/broadphase/compute_fat_world_aabb.js +61 -0
- package/src/engine/physics/broadphase/generate_pairs.d.ts +38 -0
- package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -0
- package/src/engine/physics/broadphase/generate_pairs.js +101 -0
- package/src/engine/physics/contact/ManifoldStore.d.ts +226 -0
- package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -0
- package/src/engine/physics/contact/ManifoldStore.js +499 -0
- package/src/engine/physics/ecs/BodyKind.d.ts +23 -0
- package/src/engine/physics/ecs/BodyKind.d.ts.map +1 -0
- package/src/engine/physics/ecs/BodyKind.js +24 -0
- package/src/engine/physics/ecs/Collider.d.ts +98 -0
- package/src/engine/physics/ecs/Collider.d.ts.map +1 -0
- package/src/engine/physics/ecs/Collider.js +136 -0
- package/src/engine/physics/ecs/ColliderFlags.d.ts +14 -0
- package/src/engine/physics/ecs/ColliderFlags.d.ts.map +1 -0
- package/src/engine/physics/ecs/ColliderFlags.js +15 -0
- package/src/engine/physics/ecs/ColliderObserverSystem.d.ts +58 -0
- package/src/engine/physics/ecs/ColliderObserverSystem.d.ts.map +1 -0
- package/src/engine/physics/ecs/ColliderObserverSystem.js +103 -0
- package/src/engine/physics/ecs/ColliderSerializationAdapter.d.ts +25 -0
- package/src/engine/physics/ecs/ColliderSerializationAdapter.d.ts.map +1 -0
- package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -0
- package/src/engine/physics/ecs/PhysicsEvents.d.ts +15 -0
- package/src/engine/physics/ecs/PhysicsEvents.d.ts.map +1 -0
- package/src/engine/physics/ecs/PhysicsEvents.js +16 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +520 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -0
- package/src/engine/physics/ecs/PhysicsSystem.js +1159 -0
- package/src/engine/physics/ecs/RigidBody.d.ts +197 -0
- package/src/engine/physics/ecs/RigidBody.d.ts.map +1 -0
- package/src/engine/physics/ecs/RigidBody.js +240 -0
- package/src/engine/physics/ecs/RigidBodyFlags.d.ts +21 -0
- package/src/engine/physics/ecs/RigidBodyFlags.d.ts.map +1 -0
- package/src/engine/physics/ecs/RigidBodyFlags.js +22 -0
- package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts +28 -0
- package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts.map +1 -0
- package/src/engine/physics/ecs/RigidBodySerializationAdapter.js +81 -0
- package/src/engine/physics/ecs/SleepState.d.ts +11 -0
- package/src/engine/physics/ecs/SleepState.d.ts.map +1 -0
- package/src/engine/physics/ecs/SleepState.js +12 -0
- package/src/engine/physics/events/ContactEventBuffer.d.ts +46 -0
- package/src/engine/physics/events/ContactEventBuffer.d.ts.map +1 -0
- package/src/engine/physics/events/ContactEventBuffer.js +83 -0
- package/src/engine/physics/events/diff_manifolds.d.ts +25 -0
- package/src/engine/physics/events/diff_manifolds.d.ts.map +1 -0
- package/src/engine/physics/events/diff_manifolds.js +50 -0
- package/src/engine/physics/fluid/FluidField.d.ts +294 -16
- package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
- package/src/engine/physics/fluid/FluidField.js +510 -66
- package/src/engine/physics/fluid/FluidSimulator.d.ts +188 -5
- package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
- package/src/engine/physics/fluid/FluidSimulator.js +455 -95
- package/src/engine/physics/fluid/SliceVisualiser.d.ts +29 -6
- package/src/engine/physics/fluid/SliceVisualiser.d.ts.map +1 -1
- package/src/engine/physics/fluid/SliceVisualiser.js +190 -165
- package/src/engine/physics/fluid/ecs/FluidComponent.d.ts +154 -0
- package/src/engine/physics/fluid/ecs/FluidComponent.d.ts.map +1 -0
- package/src/engine/physics/fluid/ecs/FluidComponent.js +238 -0
- package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.d.ts +45 -0
- package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.d.ts.map +1 -0
- package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -0
- package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +107 -0
- package/src/engine/physics/fluid/ecs/FluidSystem.d.ts.map +1 -0
- package/src/engine/physics/fluid/ecs/FluidSystem.js +278 -0
- package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts +62 -1
- package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts.map +1 -1
- package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -6
- package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts +17 -4
- package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts.map +1 -1
- package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +105 -12
- package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts +43 -0
- package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts.map +1 -0
- package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +210 -0
- package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts +62 -1
- package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts.map +1 -1
- package/src/engine/physics/fluid/effector/WakeFluidEffector.js +302 -8
- package/src/engine/physics/fluid/prototype.js +102 -91
- package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts +33 -0
- package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/optimal_sor_omega.js +41 -0
- package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts +20 -5
- 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 +60 -38
- package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts +25 -4
- 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 +93 -73
- package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.d.ts +23 -0
- package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.js +60 -0
- package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.d.ts +23 -0
- package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.js +68 -0
- package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts +30 -0
- package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +66 -0
- package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.d.ts +26 -0
- package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -0
- package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.d.ts +30 -0
- package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts +49 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +126 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts +93 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +424 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts +20 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.js +83 -0
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts +26 -0
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +70 -0
- package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts.map +1 -1
- package/src/engine/physics/gjk/expanding_polytope_algorithm.js +8 -10
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts +29 -0
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -0
- package/src/engine/physics/inertia/world_inverse_inertia.js +79 -0
- package/src/engine/physics/integration/integrate_position.d.ts +16 -0
- package/src/engine/physics/integration/integrate_position.d.ts.map +1 -0
- package/src/engine/physics/integration/integrate_position.js +48 -0
- package/src/engine/physics/integration/integrate_velocity.d.ts +25 -0
- package/src/engine/physics/integration/integrate_velocity.d.ts.map +1 -0
- package/src/engine/physics/integration/integrate_velocity.js +79 -0
- package/src/engine/physics/integration/quat_integrate.d.ts +27 -0
- package/src/engine/physics/integration/quat_integrate.d.ts.map +1 -0
- package/src/engine/physics/integration/quat_integrate.js +62 -0
- package/src/engine/physics/island/IslandBuilder.d.ts +167 -0
- package/src/engine/physics/island/IslandBuilder.d.ts.map +1 -0
- package/src/engine/physics/island/IslandBuilder.js +411 -0
- package/src/engine/physics/island/union_find.d.ts +51 -0
- package/src/engine/physics/island/union_find.d.ts.map +1 -0
- package/src/engine/physics/island/union_find.js +76 -0
- package/src/engine/physics/narrowphase/PosedShape.d.ts +59 -0
- package/src/engine/physics/narrowphase/PosedShape.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/PosedShape.js +110 -0
- package/src/engine/physics/narrowphase/box_box_manifold.d.ts +32 -0
- package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/box_box_manifold.js +543 -0
- package/src/engine/physics/narrowphase/capsule_contacts.d.ts +122 -0
- package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/capsule_contacts.js +508 -0
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts +11 -0
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/narrowphase_step.js +382 -0
- package/src/engine/physics/narrowphase/sphere_box_contact.d.ts +38 -0
- package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/sphere_box_contact.js +130 -0
- package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts +26 -0
- package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/sphere_sphere_contact.js +51 -0
- package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts +83 -0
- package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts.map +1 -0
- package/src/engine/physics/queries/PhysicsSurfacePoint.js +100 -0
- package/src/engine/physics/queries/raycast.d.ts +20 -0
- package/src/engine/physics/queries/raycast.d.ts.map +1 -0
- package/src/engine/physics/queries/raycast.js +249 -0
- package/src/engine/physics/solver/friction_cone.d.ts +16 -0
- package/src/engine/physics/solver/friction_cone.d.ts.map +1 -0
- package/src/engine/physics/solver/friction_cone.js +37 -0
- package/src/engine/physics/solver/solve_contacts.d.ts +36 -0
- package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -0
- package/src/engine/physics/solver/solve_contacts.js +598 -0
- package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.d.ts +0 -34
- package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.d.ts.map +0 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.js +0 -66
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.d.ts +0 -2
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.d.ts.map +0 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.js +0 -54
- package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.d.ts +0 -2
- package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.d.ts.map +0 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.js +0 -26
- package/src/engine/ecs/components/Motion.d.ts +0 -21
- package/src/engine/ecs/components/Motion.d.ts.map +0 -1
- package/src/engine/ecs/components/Motion.js +0 -27
- package/src/engine/ecs/components/MotionSerializationAdapter.d.ts +0 -20
- package/src/engine/ecs/components/MotionSerializationAdapter.d.ts.map +0 -1
- package/src/engine/ecs/components/MotionSerializationAdapter.js +0 -26
- package/src/engine/ecs/systems/MotionSystem.d.ts +0 -9
- package/src/engine/ecs/systems/MotionSystem.d.ts.map +0 -1
- package/src/engine/ecs/systems/MotionSystem.js +0 -29
- package/src/engine/physics/fluid/Fluid.d.ts +0 -26
- package/src/engine/physics/fluid/Fluid.d.ts.map +0 -1
- package/src/engine/physics/fluid/Fluid.js +0 -221
- package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.d.ts +0 -7
- package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.d.ts.map +0 -1
- package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.js +0 -8
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { BoxGeometry, MeshStandardMaterial } from "three";
|
|
2
|
+
import { Ray3 } from "../../../core/geom/3d/ray/Ray3.js";
|
|
3
|
+
import { BoxShape3D } from "../../../core/geom/3d/shape/BoxShape3D.js";
|
|
4
|
+
import { CapsuleShape3D } from "../../../core/geom/3d/shape/CapsuleShape3D.js";
|
|
2
5
|
import Vector2 from "../../../core/geom/Vector2.js";
|
|
3
6
|
import Vector3 from "../../../core/geom/Vector3.js";
|
|
4
7
|
import { SerializationMetadata } from "../../ecs/components/SerializationMetadata.js";
|
|
5
8
|
import { Tag } from "../../ecs/components/Tag.js";
|
|
6
9
|
import Entity from "../../ecs/Entity.js";
|
|
10
|
+
import { obtainTerrain } from "../../ecs/terrain/util/obtainTerrain.js";
|
|
7
11
|
import { Transform } from "../../ecs/transform/Transform.js";
|
|
8
12
|
import { EngineHarness } from "../../EngineHarness.js";
|
|
9
13
|
import { CameraSystem } from "../../graphics/ecs/camera/CameraSystem.js";
|
|
@@ -12,11 +16,29 @@ import { ShadedGeometryFlags } from "../../graphics/ecs/mesh-v2/ShadedGeometryFl
|
|
|
12
16
|
import { ShadedGeometrySystem } from "../../graphics/ecs/mesh-v2/ShadedGeometrySystem.js";
|
|
13
17
|
import InputController from "../../input/ecs/components/InputController.js";
|
|
14
18
|
import InputControllerSystem from "../../input/ecs/systems/InputControllerSystem.js";
|
|
19
|
+
import { BodyKind } from "../../physics/ecs/BodyKind.js";
|
|
20
|
+
import { Collider } from "../../physics/ecs/Collider.js";
|
|
21
|
+
import { ColliderObserverSystem } from "../../physics/ecs/ColliderObserverSystem.js";
|
|
22
|
+
import { PhysicsSystem } from "../../physics/ecs/PhysicsSystem.js";
|
|
23
|
+
import { RigidBody } from "../../physics/ecs/RigidBody.js";
|
|
24
|
+
import { PhysicsSurfacePoint } from "../../physics/queries/PhysicsSurfacePoint.js";
|
|
25
|
+
import { LedgeGrab } from "./abilities/LedgeGrab.js";
|
|
26
|
+
import { Mantle } from "./abilities/Mantle.js";
|
|
27
|
+
import { Slide } from "./abilities/Slide.js";
|
|
28
|
+
import { WallJump } from "./abilities/WallJump.js";
|
|
29
|
+
import { WallRun } from "./abilities/WallRun.js";
|
|
15
30
|
import { FirstPersonPlayerController } from "./FirstPersonPlayerController.js";
|
|
16
31
|
import { FirstPersonPlayerControllerSystem } from "./FirstPersonPlayerControllerSystem.js";
|
|
32
|
+
import { BreathRhythmEvaluator } from "./mastery/BreathRhythmEvaluator.js";
|
|
33
|
+
import { DecisionPoint } from "./mastery/DecisionPoint.js";
|
|
34
|
+
import { FootAsymmetryTurnEvaluator } from "./mastery/FootAsymmetryTurnEvaluator.js";
|
|
35
|
+
import { SlideInitiationTimingEvaluator } from "./mastery/SlideInitiationTimingEvaluator.js";
|
|
36
|
+
import { StrideTimingJumpEvaluator } from "./mastery/StrideTimingJumpEvaluator.js";
|
|
37
|
+
import { FirstPersonSensorsSystem } from "./sensors/FirstPersonSensorsSystem.js";
|
|
17
38
|
|
|
18
39
|
/**
|
|
19
|
-
* Prototype harness for {@link FirstPersonPlayerController}
|
|
40
|
+
* Prototype harness for {@link FirstPersonPlayerController} — a parkour
|
|
41
|
+
* "gym" laid out as discrete test stations around the spawn point.
|
|
20
42
|
*
|
|
21
43
|
* Controls:
|
|
22
44
|
* - Click to capture mouse (pointer lock); ESC to release
|
|
@@ -24,12 +46,38 @@ import { FirstPersonPlayerControllerSystem } from "./FirstPersonPlayerController
|
|
|
24
46
|
* - Mouse — look
|
|
25
47
|
* - Space — jump (tap; holding does not auto-repeat)
|
|
26
48
|
* - Shift — sprint (hold while moving forward)
|
|
27
|
-
* - C — crouch (hold)
|
|
49
|
+
* - C — crouch (hold; sprint+crouch press → slide)
|
|
28
50
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
51
|
+
* Stations (compass directions from spawn):
|
|
52
|
+
*
|
|
53
|
+
* N Mantle row four obstacles from too-low to too-tall
|
|
54
|
+
* NE Slide tunnel sprint run-up + low ceiling
|
|
55
|
+
* E Wall-run wall one long wall to run alongside
|
|
56
|
+
* SE Gap jump raised platforms with a gap to clear
|
|
57
|
+
* S Ledge-grab wall too tall to mantle; jump + catch the lip
|
|
58
|
+
* SW (open)
|
|
59
|
+
* W Wall-jump chimney two parallel walls for back-and-forth jumps
|
|
60
|
+
* NW (open)
|
|
61
|
+
*
|
|
62
|
+
* Each station is colour-coded at the entrance. Look around: the
|
|
63
|
+
* coloured pad on the ground tells you what's there.
|
|
64
|
+
*
|
|
65
|
+
* @author Alex Goldring
|
|
66
|
+
* @copyright Company Named Limited (c) 2026
|
|
31
67
|
*/
|
|
32
68
|
|
|
69
|
+
const SPAWN_X = 100;
|
|
70
|
+
const SPAWN_Z = 100;
|
|
71
|
+
|
|
72
|
+
// Station palette — used for entry pads + matching obstacle colour.
|
|
73
|
+
const COLOR_MANTLE = 0x55ff55;
|
|
74
|
+
const COLOR_WALLRUN = 0xff5555;
|
|
75
|
+
const COLOR_WALLJUMP = 0xaa55ff;
|
|
76
|
+
const COLOR_LEDGE = 0xffaa44;
|
|
77
|
+
const COLOR_SLIDE = 0x44ddee;
|
|
78
|
+
const COLOR_GAP = 0xff66cc;
|
|
79
|
+
const COLOR_NEUTRAL = 0xaaaaaa;
|
|
80
|
+
|
|
33
81
|
const eh = new EngineHarness();
|
|
34
82
|
|
|
35
83
|
async function main(engine) {
|
|
@@ -43,6 +91,8 @@ async function main(engine) {
|
|
|
43
91
|
engine,
|
|
44
92
|
sunIntensity: 1.0,
|
|
45
93
|
ambientIntensity: 0.25,
|
|
94
|
+
shadowmapResolution: 2048,
|
|
95
|
+
sunShadowDistance: 30,
|
|
46
96
|
});
|
|
47
97
|
|
|
48
98
|
if (em.getSystem(CameraSystem) === null) {
|
|
@@ -55,11 +105,30 @@ async function main(engine) {
|
|
|
55
105
|
await em.addSystem(new ShadedGeometrySystem(engine));
|
|
56
106
|
}
|
|
57
107
|
|
|
108
|
+
// Physics — owns RigidBody+Collider lifecycle, fires contact events,
|
|
109
|
+
// and serves spatial queries (raycast). Sensors and the ground
|
|
110
|
+
// resolver both go through it. Added BEFORE the controller so the
|
|
111
|
+
// sensors and ground resolver find it in their startup auto-acquire.
|
|
112
|
+
const physicsSystem = new PhysicsSystem();
|
|
113
|
+
await em.addSystem(physicsSystem);
|
|
114
|
+
// ColliderObserver wires Collider components into PhysicsSystem
|
|
115
|
+
// bodies as entities are built. Without it, every collider would
|
|
116
|
+
// need an explicit attach_collider call.
|
|
117
|
+
await em.addSystem(new ColliderObserverSystem(physicsSystem));
|
|
118
|
+
|
|
58
119
|
const fpsSystem = new FirstPersonPlayerControllerSystem();
|
|
59
|
-
|
|
60
|
-
|
|
120
|
+
// Built-in flat-ground OFF — the gym uses the physics-backed ground
|
|
121
|
+
// resolver below (which finds the highest static surface under the
|
|
122
|
+
// player from BVH raycasts). Leaving the flat baseline on would
|
|
123
|
+
// pin the player to y=0 even when standing on a 2 m platform.
|
|
124
|
+
fpsSystem.useBuiltInFlatGround = false;
|
|
61
125
|
await em.addSystem(fpsSystem);
|
|
62
126
|
|
|
127
|
+
// Sensors system — populates wall/obstacle/ledge probes via
|
|
128
|
+
// PhysicsSystem.raycast. Auto-acquires the physics system in startup.
|
|
129
|
+
const sensorsSystem = new FirstPersonSensorsSystem();
|
|
130
|
+
await em.addSystem(sensorsSystem);
|
|
131
|
+
|
|
63
132
|
if (!ecd.isComponentTypeRegistered(Tag)) {
|
|
64
133
|
ecd.registerComponentType(Tag);
|
|
65
134
|
}
|
|
@@ -76,11 +145,22 @@ async function main(engine) {
|
|
|
76
145
|
diffuse0: "data/textures/materials/terrain_township_set/512/Grass_3.png",
|
|
77
146
|
});
|
|
78
147
|
|
|
79
|
-
|
|
148
|
+
obtainTerrain(ecd); // no-op call to ensure terrain is built
|
|
149
|
+
|
|
150
|
+
buildGym(ecd);
|
|
80
151
|
|
|
81
152
|
// -- Player ----------------------------------------------------------
|
|
82
153
|
const player = buildPlayerEntity(ecd);
|
|
83
154
|
|
|
155
|
+
// Ground resolver: downward raycast through PhysicsSystem, filtered
|
|
156
|
+
// to exclude the player's own capsule. Wired AFTER the player is
|
|
157
|
+
// built so the filter has the right entity id. The controller's
|
|
158
|
+
// vertical integrator falls through when the resolver returns null
|
|
159
|
+
// (no platform below) — set up with `useBuiltInFlatGround = false`
|
|
160
|
+
// above so that means actual airborne / void, not a hidden y=0
|
|
161
|
+
// safety floor.
|
|
162
|
+
fpsSystem.groundResolver = makePhysicsGroundResolver(physicsSystem, player.entity);
|
|
163
|
+
|
|
84
164
|
// -- Inputs ----------------------------------------------------------
|
|
85
165
|
buildInputBindings(ecd, player);
|
|
86
166
|
|
|
@@ -89,26 +169,461 @@ async function main(engine) {
|
|
|
89
169
|
logHelp();
|
|
90
170
|
}
|
|
91
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Downward-raycast ground resolver, backed by {@link PhysicsSystem.raycast}.
|
|
174
|
+
* Each call: from just above the player's feet, cast straight down
|
|
175
|
+
* through static + dynamic broadphase; filter out the player's own
|
|
176
|
+
* body; return the hit y, or null if no surface below.
|
|
177
|
+
*
|
|
178
|
+
* The controller's vertical integrator picks max(useBuiltInFlatGround,
|
|
179
|
+
* resolver). In the gym we leave useBuiltInFlatGround off so the
|
|
180
|
+
* resolver is the sole source of truth — gaps in the floor are real
|
|
181
|
+
* gaps (the player falls into them).
|
|
182
|
+
*
|
|
183
|
+
* @param {PhysicsSystem} physicsSystem
|
|
184
|
+
* @param {number} playerEntity excluded from raycasts to skip the player capsule
|
|
185
|
+
* @returns {(x:number, y:number, z:number) => number|null}
|
|
186
|
+
*/
|
|
187
|
+
function makePhysicsGroundResolver(physicsSystem, playerEntity) {
|
|
188
|
+
// Probe starts slightly above the player feet so a grounded player
|
|
189
|
+
// standing right on a platform still raycasts cleanly. Length is
|
|
190
|
+
// longer than any reasonable gym platform.
|
|
191
|
+
const PROBE_LIFT = 0.1;
|
|
192
|
+
const PROBE_DOWN = 50;
|
|
193
|
+
const filter = (entity) => entity !== playerEntity;
|
|
194
|
+
// Reuse a single ray and surface-point across calls — the resolver
|
|
195
|
+
// can fire many times per frame as the controller hunts for foothold.
|
|
196
|
+
const ray = Ray3.from(0, 0, 0, 0, -1, 0, PROBE_DOWN);
|
|
197
|
+
const hit = new PhysicsSurfacePoint();
|
|
198
|
+
return function physicsGroundResolver(x, y, z) {
|
|
199
|
+
ray.setOrigin(x, y + PROBE_LIFT, z);
|
|
200
|
+
if (!physicsSystem.raycast(ray, hit, filter)) return null;
|
|
201
|
+
// Direction is unit (0,-1,0); t is the distance to the surface
|
|
202
|
+
// along that direction. Surface Y = origin Y minus t.
|
|
203
|
+
return (y + PROBE_LIFT) - hit.t;
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// =====================================================================
|
|
208
|
+
// Gym construction
|
|
209
|
+
// =====================================================================
|
|
210
|
+
|
|
211
|
+
function buildGym(ecd) {
|
|
212
|
+
buildGroundPlane(ecd);
|
|
213
|
+
buildSpawnPlaza(ecd);
|
|
214
|
+
buildMantleStation(ecd);
|
|
215
|
+
buildWallRunStation(ecd);
|
|
216
|
+
buildWallJumpChimney(ecd);
|
|
217
|
+
buildLedgeGrabStation(ecd);
|
|
218
|
+
buildSlideTunnel(ecd);
|
|
219
|
+
buildGapJumpStation(ecd);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Reference markers around spawn so motion is visually obvious — a ring
|
|
224
|
+
* of coloured cubes (circle-strafe targets) and a few tall pillars at
|
|
225
|
+
* radius 22 for parallax-at-distance.
|
|
226
|
+
*/
|
|
227
|
+
function buildSpawnPlaza(ecd) {
|
|
228
|
+
const unitCubeGeom = new BoxGeometry(1, 1, 1);
|
|
229
|
+
const palette = [
|
|
230
|
+
0xff5555, 0x55ff55, 0x5577ff, 0xffaa44,
|
|
231
|
+
0xaa55ff, 0x44ddee, 0xff66cc, 0x66ffcc,
|
|
232
|
+
];
|
|
233
|
+
|
|
234
|
+
// Inner ring at radius 6 — close enough to circle-strafe around.
|
|
235
|
+
const RING_N = 8;
|
|
236
|
+
for (let i = 0; i < RING_N; i++) {
|
|
237
|
+
const a = (i / RING_N) * Math.PI * 2;
|
|
238
|
+
spawnBox(ecd, {
|
|
239
|
+
center: new Vector3(SPAWN_X + Math.cos(a) * 6, 0.5, SPAWN_Z + Math.sin(a) * 6),
|
|
240
|
+
size: new Vector3(1, 1, 1),
|
|
241
|
+
geometry: unitCubeGeom,
|
|
242
|
+
color: palette[i % palette.length],
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Tall pillars further out — parallax depth perception when running.
|
|
247
|
+
const pillarGeom = new BoxGeometry(1, 6, 1);
|
|
248
|
+
const PILLAR_N = 6;
|
|
249
|
+
for (let i = 0; i < PILLAR_N; i++) {
|
|
250
|
+
const a = (i / PILLAR_N) * Math.PI * 2 + 0.3;
|
|
251
|
+
const r = 22;
|
|
252
|
+
spawnBox(ecd, {
|
|
253
|
+
center: new Vector3(SPAWN_X + Math.cos(a) * r, 3, SPAWN_Z + Math.sin(a) * r),
|
|
254
|
+
size: new Vector3(1, 6, 1),
|
|
255
|
+
geometry: pillarGeom,
|
|
256
|
+
color: 0x888888,
|
|
257
|
+
roughness: 0.9,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Mantle row — directly north of spawn. Four obstacles in line, heights
|
|
264
|
+
* stepping past the mantle range:
|
|
265
|
+
*
|
|
266
|
+
* - 0.6m: well within mantle range; lowest "step-up" test
|
|
267
|
+
* - 1.0m: mid mantle range
|
|
268
|
+
* - 1.3m: near top of mantle range
|
|
269
|
+
* - 2.0m: too tall to mantle from the ground (heightDiff > maxHeight)
|
|
270
|
+
*
|
|
271
|
+
* The 2.0m block is also the canonical "LedgeGrab if you jump at it"
|
|
272
|
+
* candidate, but the dedicated LedgeGrab station to the south has a
|
|
273
|
+
* cleaner approach path.
|
|
274
|
+
*/
|
|
275
|
+
function buildMantleStation(ecd) {
|
|
276
|
+
const baseZ = SPAWN_Z + 15;
|
|
277
|
+
spawnPad(ecd, SPAWN_X, baseZ - 3, COLOR_MANTLE);
|
|
278
|
+
|
|
279
|
+
const heights = [0.6, 1.0, 1.3, 2.0];
|
|
280
|
+
for (let i = 0; i < heights.length; i++) {
|
|
281
|
+
const h = heights[i];
|
|
282
|
+
spawnBox(ecd, {
|
|
283
|
+
center: new Vector3(SPAWN_X, h / 2, baseZ + i * 5),
|
|
284
|
+
size: new Vector3(3, h, 1),
|
|
285
|
+
color: COLOR_MANTLE,
|
|
286
|
+
roughness: 0.6,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Wall-run wall — a long wall on the east side. Player runs east past
|
|
293
|
+
* spawn, jumps near the wall, runs along it.
|
|
294
|
+
*
|
|
295
|
+
* Two walls actually — left and right — so the player can wall-run on
|
|
296
|
+
* either side without needing to circle back.
|
|
297
|
+
*/
|
|
298
|
+
function buildWallRunStation(ecd) {
|
|
299
|
+
const baseX = SPAWN_X + 15;
|
|
300
|
+
spawnPad(ecd, baseX - 3, SPAWN_Z, COLOR_WALLRUN);
|
|
301
|
+
|
|
302
|
+
// South wall (run along its north face).
|
|
303
|
+
spawnBox(ecd, {
|
|
304
|
+
center: new Vector3(baseX + 5, 2, SPAWN_Z - 2),
|
|
305
|
+
size: new Vector3(10, 4, 0.5),
|
|
306
|
+
color: COLOR_WALLRUN,
|
|
307
|
+
roughness: 0.6,
|
|
308
|
+
});
|
|
309
|
+
// North wall (run along its south face) — separated by 4m so the
|
|
310
|
+
// wall-runner picks one side, not both.
|
|
311
|
+
spawnBox(ecd, {
|
|
312
|
+
center: new Vector3(baseX + 5, 2, SPAWN_Z + 2),
|
|
313
|
+
size: new Vector3(10, 4, 0.5),
|
|
314
|
+
color: COLOR_WALLRUN,
|
|
315
|
+
roughness: 0.6,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Wall-jump chimney — two parallel walls on the west side, ~3m apart,
|
|
321
|
+
* 6m tall. Player walks into the gap, jumps, hits one wall, wall-jumps
|
|
322
|
+
* to the other side. Repeat to climb.
|
|
323
|
+
*
|
|
324
|
+
* The walls are wide enough that wall-jumping straight back to the
|
|
325
|
+
* other side stays inside the chimney.
|
|
326
|
+
*/
|
|
327
|
+
function buildWallJumpChimney(ecd) {
|
|
328
|
+
const baseX = SPAWN_X - 15;
|
|
329
|
+
spawnPad(ecd, baseX + 3, SPAWN_Z, COLOR_WALLJUMP);
|
|
330
|
+
|
|
331
|
+
// North wall of the chimney (pushes south).
|
|
332
|
+
spawnBox(ecd, {
|
|
333
|
+
center: new Vector3(baseX - 2, 3, SPAWN_Z + 2),
|
|
334
|
+
size: new Vector3(4, 6, 0.5),
|
|
335
|
+
color: COLOR_WALLJUMP,
|
|
336
|
+
roughness: 0.6,
|
|
337
|
+
});
|
|
338
|
+
// South wall of the chimney (pushes north). 3m gap to the north wall.
|
|
339
|
+
spawnBox(ecd, {
|
|
340
|
+
center: new Vector3(baseX - 2, 3, SPAWN_Z - 1.25),
|
|
341
|
+
size: new Vector3(4, 6, 0.5),
|
|
342
|
+
color: COLOR_WALLJUMP,
|
|
343
|
+
roughness: 0.6,
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Ledge-grab station — a single 2m-tall wall just south of spawn.
|
|
349
|
+
* Too tall to mantle from the ground (heightDiff = 2 > maxHeight 1.4),
|
|
350
|
+
* but the player can run-jump at it and catch the lip on descent:
|
|
351
|
+
*
|
|
352
|
+
* 1. sprint south
|
|
353
|
+
* 2. jump just before the wall
|
|
354
|
+
* 3. on the way down, chest probe hits the wall face;
|
|
355
|
+
* ledgeAhead probe finds the top → LedgeGrab fires
|
|
356
|
+
* 4. press jump to chain into Mantle (mantle-up release)
|
|
357
|
+
*
|
|
358
|
+
* The wall is 6m wide so the player doesn't have to aim perfectly.
|
|
359
|
+
*/
|
|
360
|
+
function buildLedgeGrabStation(ecd) {
|
|
361
|
+
const baseZ = SPAWN_Z - 15;
|
|
362
|
+
spawnPad(ecd, SPAWN_X, baseZ + 3, COLOR_LEDGE);
|
|
363
|
+
|
|
364
|
+
spawnBox(ecd, {
|
|
365
|
+
center: new Vector3(SPAWN_X, 1.0, baseZ - 1),
|
|
366
|
+
size: new Vector3(6, 2.0, 2),
|
|
367
|
+
color: COLOR_LEDGE,
|
|
368
|
+
roughness: 0.6,
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// A larger top-of-wall platform behind the lip, so once the player
|
|
372
|
+
// climbs up they have somewhere to stand and look around.
|
|
373
|
+
spawnBox(ecd, {
|
|
374
|
+
center: new Vector3(SPAWN_X, 1.0, baseZ - 4.5),
|
|
375
|
+
size: new Vector3(6, 2.0, 5),
|
|
376
|
+
color: COLOR_LEDGE,
|
|
377
|
+
roughness: 0.6,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Slide tunnel — a sprint run-up followed by a low ceiling that forces
|
|
383
|
+
* the player to slide under. NE of spawn.
|
|
384
|
+
*
|
|
385
|
+
* Layout: a long flat lane (just an entry pad / marker, ground is
|
|
386
|
+
* already flat), with an overhead box at 1m height. Approaching at
|
|
387
|
+
* sprint + crouch press → slide → fits under the gap.
|
|
388
|
+
*/
|
|
389
|
+
function buildSlideTunnel(ecd) {
|
|
390
|
+
const baseX = SPAWN_X + 11;
|
|
391
|
+
const baseZ = SPAWN_Z + 11;
|
|
392
|
+
spawnPad(ecd, baseX, baseZ, COLOR_SLIDE);
|
|
393
|
+
|
|
394
|
+
// The "ceiling" — a slab suspended 1.0m above the ground. Sliding
|
|
395
|
+
// brings the eye height down to ~0.4m; standing-eye-height would
|
|
396
|
+
// collide.
|
|
397
|
+
spawnBox(ecd, {
|
|
398
|
+
center: new Vector3(baseX + 4, 1.5, baseZ + 4),
|
|
399
|
+
size: new Vector3(4, 1.0, 4),
|
|
400
|
+
color: COLOR_SLIDE,
|
|
401
|
+
roughness: 0.6,
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
// Side pillars to make the tunnel feel like a tunnel.
|
|
405
|
+
spawnBox(ecd, {
|
|
406
|
+
center: new Vector3(baseX + 4, 1.0, baseZ + 2.0),
|
|
407
|
+
size: new Vector3(4, 2.0, 0.5),
|
|
408
|
+
color: COLOR_SLIDE,
|
|
409
|
+
roughness: 0.7,
|
|
410
|
+
});
|
|
411
|
+
spawnBox(ecd, {
|
|
412
|
+
center: new Vector3(baseX + 4, 1.0, baseZ + 6.0),
|
|
413
|
+
size: new Vector3(4, 2.0, 0.5),
|
|
414
|
+
color: COLOR_SLIDE,
|
|
415
|
+
roughness: 0.7,
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Gap jump — two elevated platforms with a 3m gap between them. Player
|
|
421
|
+
* approaches via a mantle stair, runs across the first platform,
|
|
422
|
+
* sprints + jumps the gap.
|
|
423
|
+
*
|
|
424
|
+
* The platforms sit 1.5m above the spawn ground (mantleable). The gap
|
|
425
|
+
* doesn't actually break the floor — landing flat would still catch
|
|
426
|
+
* the player on the y=0 floor below. That's fine for testing the
|
|
427
|
+
* mid-flight feel of a jump; survival of misses is a feature here.
|
|
428
|
+
*/
|
|
429
|
+
function buildGapJumpStation(ecd) {
|
|
430
|
+
const baseX = SPAWN_X + 11;
|
|
431
|
+
const baseZ = SPAWN_Z - 11;
|
|
432
|
+
spawnPad(ecd, baseX, baseZ, COLOR_GAP);
|
|
433
|
+
|
|
434
|
+
// Approach mantle (step up to the first platform).
|
|
435
|
+
spawnBox(ecd, {
|
|
436
|
+
center: new Vector3(baseX + 2, 0.5, baseZ - 2),
|
|
437
|
+
size: new Vector3(2, 1.0, 2),
|
|
438
|
+
color: COLOR_GAP,
|
|
439
|
+
roughness: 0.7,
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
// First platform — 4m long along Z.
|
|
443
|
+
spawnBox(ecd, {
|
|
444
|
+
center: new Vector3(baseX + 5, 0.75, baseZ - 4),
|
|
445
|
+
size: new Vector3(4, 1.5, 4),
|
|
446
|
+
color: COLOR_GAP,
|
|
447
|
+
roughness: 0.6,
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
// Second platform — same height, 3m gap.
|
|
451
|
+
spawnBox(ecd, {
|
|
452
|
+
center: new Vector3(baseX + 5, 0.75, baseZ - 11),
|
|
453
|
+
size: new Vector3(4, 1.5, 4),
|
|
454
|
+
color: COLOR_GAP,
|
|
455
|
+
roughness: 0.6,
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// =====================================================================
|
|
460
|
+
// Spawn helpers
|
|
461
|
+
// =====================================================================
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Add a box-shaped obstacle to the world. Position is the box centre.
|
|
465
|
+
*
|
|
466
|
+
* Single entity carrying both visual (ShadedGeometry) and physical
|
|
467
|
+
* (RigidBody + Collider) representations so the player can stand on it,
|
|
468
|
+
* sensors can raycast against it, and dynamic crates (when added) bump
|
|
469
|
+
* off it. Bodies are {@link BodyKind.Static} — gym geometry never moves.
|
|
470
|
+
*
|
|
471
|
+
* @param {EntityComponentDataset} ecd
|
|
472
|
+
* @param {object} p
|
|
473
|
+
* @param {Vector3} p.center
|
|
474
|
+
* @param {Vector3} p.size w, h, d (box dimensions)
|
|
475
|
+
* @param {number} p.color
|
|
476
|
+
* @param {number} [p.roughness]
|
|
477
|
+
* @param {THREE.BufferGeometry} [p.geometry] reuse to avoid new geometry per spawn
|
|
478
|
+
* @param {string} [p.tag]
|
|
479
|
+
* @param {boolean} [p.collide] default true; set false for decorative pads
|
|
480
|
+
*/
|
|
481
|
+
function spawnBox(ecd, { center, size, color, roughness = 0.7, geometry, tag = "GymObstacle", collide = true }) {
|
|
482
|
+
const geom = geometry !== undefined ? geometry : new BoxGeometry(size.x, size.y, size.z);
|
|
483
|
+
const material = new MeshStandardMaterial({ color, roughness });
|
|
484
|
+
const sg = ShadedGeometry.from(geom, material);
|
|
485
|
+
sg.setFlag(ShadedGeometryFlags.CastShadow);
|
|
486
|
+
sg.setFlag(ShadedGeometryFlags.ReceiveShadow);
|
|
487
|
+
sg.setFlag(ShadedGeometryFlags.Visible);
|
|
488
|
+
|
|
489
|
+
const transform = new Transform();
|
|
490
|
+
transform.position.copy(center);
|
|
491
|
+
|
|
492
|
+
const eb = new Entity()
|
|
493
|
+
.add(sg)
|
|
494
|
+
.add(Tag.fromJSON([tag]))
|
|
495
|
+
.add(SerializationMetadata.Transient);
|
|
496
|
+
|
|
497
|
+
if (collide) {
|
|
498
|
+
const rigidBody = new RigidBody();
|
|
499
|
+
rigidBody.kind = BodyKind.Static;
|
|
500
|
+
const collider = new Collider();
|
|
501
|
+
// BoxShape3D with explicit half-extents — routes through the
|
|
502
|
+
// closed-form sphere-box / box-box / capsule-box narrowphase paths
|
|
503
|
+
// instead of degenerating into GJK+EPA, which is unreliable on
|
|
504
|
+
// smooth-surface pairs like capsule-vs-box.
|
|
505
|
+
collider.shape = BoxShape3D.from_size(size.x, size.y, size.z);
|
|
506
|
+
// Transform is added LAST so the (RigidBody, Transform) tuple
|
|
507
|
+
// completes only after the body is present — PhysicsSystem.link
|
|
508
|
+
// is the trigger, not the rigidBody add.
|
|
509
|
+
eb.add(rigidBody).add(collider).add(transform).build(ecd);
|
|
510
|
+
} else {
|
|
511
|
+
eb.add(transform).build(ecd);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Lay a thin coloured "entry pad" on the ground at (x, z). Visual
|
|
517
|
+
* landmark only — flush with the floor, no collision (a 5 cm-thick
|
|
518
|
+
* static body in the player's walking path would bump the camera).
|
|
519
|
+
*/
|
|
520
|
+
function spawnPad(ecd, x, z, color) {
|
|
521
|
+
spawnBox(ecd, {
|
|
522
|
+
center: new Vector3(x, 0.025, z),
|
|
523
|
+
size: new Vector3(4, 0.05, 4),
|
|
524
|
+
color,
|
|
525
|
+
roughness: 0.95,
|
|
526
|
+
tag: "GymEntryPad",
|
|
527
|
+
collide: false,
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* Lay a physics-only ground body underneath the entire gym so the
|
|
533
|
+
* player has something to stand on. The terrain mesh provides the
|
|
534
|
+
* grass visual at y=0; this is its physics counterpart (the player
|
|
535
|
+
* controller's vertical integrator and sensors only look at physics
|
|
536
|
+
* bodies, not the terrain heightfield).
|
|
537
|
+
*
|
|
538
|
+
* Sized to comfortably encompass all stations (the gym spans ~30 m
|
|
539
|
+
* radius around spawn). The slab top sits at y=0 — same as the
|
|
540
|
+
* terrain visual — so standing on it puts the player's feet on the
|
|
541
|
+
* grass.
|
|
542
|
+
*/
|
|
543
|
+
function buildGroundPlane(ecd) {
|
|
544
|
+
const SIZE = 120;
|
|
545
|
+
const THICKNESS = 1.0;
|
|
546
|
+
|
|
547
|
+
const rigidBody = new RigidBody();
|
|
548
|
+
rigidBody.kind = BodyKind.Static;
|
|
549
|
+
const collider = new Collider();
|
|
550
|
+
collider.shape = BoxShape3D.from_size(SIZE, THICKNESS, SIZE);
|
|
551
|
+
|
|
552
|
+
const transform = new Transform();
|
|
553
|
+
// Top face at y=0 → centre at y = -thickness/2.
|
|
554
|
+
transform.position.set(SPAWN_X, -THICKNESS / 2, SPAWN_Z);
|
|
555
|
+
|
|
556
|
+
new Entity()
|
|
557
|
+
.add(rigidBody)
|
|
558
|
+
.add(collider)
|
|
559
|
+
.add(Tag.fromJSON(["GymGroundPlane"]))
|
|
560
|
+
.add(SerializationMetadata.Transient)
|
|
561
|
+
.add(transform)
|
|
562
|
+
.build(ecd);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// =====================================================================
|
|
566
|
+
// Player + input
|
|
567
|
+
// =====================================================================
|
|
568
|
+
|
|
92
569
|
/**
|
|
93
570
|
* @param {EntityComponentDataset} ecd
|
|
94
571
|
* @returns {{entity:number, controller:FirstPersonPlayerController}}
|
|
95
572
|
*/
|
|
96
573
|
function buildPlayerEntity(ecd) {
|
|
97
574
|
const transform = new Transform();
|
|
98
|
-
// Spawn standing on the ground
|
|
99
|
-
transform.position.set(
|
|
575
|
+
// Spawn standing on the ground at the centre of the plaza.
|
|
576
|
+
transform.position.set(SPAWN_X, 0, SPAWN_Z);
|
|
100
577
|
|
|
101
578
|
const controller = new FirstPersonPlayerController();
|
|
102
|
-
// Most tuning lives at config defaults; mass-tweak example shown for
|
|
103
|
-
// documentation. Comment out for the default soldier feel.
|
|
104
|
-
// controller.config.body.mass = 120;
|
|
105
|
-
// controller.config.bob.verticalAmpAtWalk = 0.08;
|
|
106
579
|
|
|
580
|
+
// Movement abilities (priority order — see DESIGN_EXTENSIONS §2.2):
|
|
581
|
+
// Slide(10) < Mantle(30) < LedgeGrab(40) < WallRun(50) < WallJump(60).
|
|
582
|
+
controller.abilities.add(new Slide());
|
|
583
|
+
controller.abilities.add(new Mantle());
|
|
584
|
+
controller.abilities.add(new LedgeGrab());
|
|
585
|
+
controller.abilities.add(new WallRun());
|
|
586
|
+
controller.abilities.add(new WallJump());
|
|
587
|
+
|
|
588
|
+
// Mastery evaluators — small bonuses/penalties tied to gait phase,
|
|
589
|
+
// foot asymmetry, and breath rhythm. Each fires on one (or a few)
|
|
590
|
+
// DecisionPoint(s); contributions compose multiplicatively.
|
|
591
|
+
controller.mastery.add(new StrideTimingJumpEvaluator());
|
|
592
|
+
controller.mastery.add(new SlideInitiationTimingEvaluator());
|
|
593
|
+
controller.mastery.add(new FootAsymmetryTurnEvaluator());
|
|
594
|
+
controller.mastery.add(new BreathRhythmEvaluator());
|
|
595
|
+
controller.mastery.add(new BreathRhythmEvaluator({
|
|
596
|
+
decisionPoints: [DecisionPoint.GroundAccel],
|
|
597
|
+
peakBonus: 0.015,
|
|
598
|
+
troughPenalty: 0.005,
|
|
599
|
+
requireExertionAbove: 0.3,
|
|
600
|
+
}));
|
|
601
|
+
|
|
602
|
+
// Kinematic capsule body: the controller writes Transform directly,
|
|
603
|
+
// physics derives velocity from the per-step delta. Capsule centred
|
|
604
|
+
// on the Transform — bottom hemisphere extends below the feet (this
|
|
605
|
+
// is fine for spatial queries since sensor probes start at chest
|
|
606
|
+
// height and the ground resolver filters out the player's own body).
|
|
607
|
+
const bodyCfg = controller.config.body;
|
|
608
|
+
const radius = bodyCfg.radius;
|
|
609
|
+
const totalHeight = bodyCfg.height; // standing eye height ≈ body extent
|
|
610
|
+
const cylinderHeight = Math.max(0, totalHeight - 2 * radius);
|
|
611
|
+
const rigidBody = new RigidBody();
|
|
612
|
+
rigidBody.kind = BodyKind.KinematicPosition;
|
|
613
|
+
rigidBody.mass = bodyCfg.mass;
|
|
614
|
+
const collider = new Collider();
|
|
615
|
+
collider.shape = CapsuleShape3D.from(radius, cylinderHeight);
|
|
616
|
+
|
|
617
|
+
// Build order matters: Transform is added LAST so the FirstPerson
|
|
618
|
+
// controller system's link() sees the RigidBody already attached.
|
|
619
|
+
// (Same pattern as the spec helpers.)
|
|
107
620
|
const eb = new Entity()
|
|
108
|
-
.add(transform)
|
|
109
621
|
.add(controller)
|
|
622
|
+
.add(rigidBody)
|
|
623
|
+
.add(collider)
|
|
110
624
|
.add(Tag.fromJSON(["Player"]))
|
|
111
|
-
.add(SerializationMetadata.Transient)
|
|
625
|
+
.add(SerializationMetadata.Transient)
|
|
626
|
+
.add(transform);
|
|
112
627
|
|
|
113
628
|
eb.build(ecd);
|
|
114
629
|
|
|
@@ -116,9 +631,7 @@ function buildPlayerEntity(ecd) {
|
|
|
116
631
|
}
|
|
117
632
|
|
|
118
633
|
/**
|
|
119
|
-
* Wire keyboard + mouse to the controller's intent surface.
|
|
120
|
-
* `InputController` plumbing as the orbital-camera controller, so the
|
|
121
|
-
* standard `InputControllerSystem` does the device subscription bookkeeping.
|
|
634
|
+
* Wire keyboard + mouse to the controller's intent surface.
|
|
122
635
|
*
|
|
123
636
|
* @param {EntityComponentDataset} ecd
|
|
124
637
|
* @param {{entity:number, controller:FirstPersonPlayerController}} player
|
|
@@ -128,14 +641,9 @@ function buildInputBindings(ecd, player) {
|
|
|
128
641
|
const intent = player.controller.intent;
|
|
129
642
|
|
|
130
643
|
// Mouse sensitivity — radians of view rotation per pixel of mouse delta.
|
|
131
|
-
// ~1200px sweep = one full 360° turn. Comparable to Source-engine
|
|
132
|
-
// "sensitivity 2" at 800 DPI; calmer than typical web demos.
|
|
133
644
|
const SENSITIVITY = (Math.PI * 2) / 1200;
|
|
134
645
|
|
|
135
646
|
// -- WASD movement --------------------------------------------------
|
|
136
|
-
// Keep a small "held" mirror so we can recompute intent.move whenever
|
|
137
|
-
// any of the four keys change. We can't read intent.move directly
|
|
138
|
-
// because both keys can be pressed simultaneously.
|
|
139
647
|
const held = { w: false, a: false, s: false, d: false };
|
|
140
648
|
|
|
141
649
|
function recomputeMove() {
|
|
@@ -148,15 +656,22 @@ function buildInputBindings(ecd, player) {
|
|
|
148
656
|
}
|
|
149
657
|
|
|
150
658
|
function bindMoveKey(key, prop) {
|
|
151
|
-
ic.bind(`keyboard/keys/${key}/down`, () => {
|
|
152
|
-
|
|
659
|
+
ic.bind(`keyboard/keys/${key}/down`, () => {
|
|
660
|
+
held[prop] = true;
|
|
661
|
+
recomputeMove();
|
|
662
|
+
});
|
|
663
|
+
ic.bind(`keyboard/keys/${key}/up`, () => {
|
|
664
|
+
held[prop] = false;
|
|
665
|
+
recomputeMove();
|
|
666
|
+
});
|
|
153
667
|
}
|
|
668
|
+
|
|
154
669
|
bindMoveKey("w", "w");
|
|
155
670
|
bindMoveKey("a", "a");
|
|
156
671
|
bindMoveKey("s", "s");
|
|
157
672
|
bindMoveKey("d", "d");
|
|
158
673
|
|
|
159
|
-
// -- Jump
|
|
674
|
+
// -- Jump ------------------------------------------------------------
|
|
160
675
|
ic.bind("keyboard/keys/space/down", () => { intent.jump = true; });
|
|
161
676
|
ic.bind("keyboard/keys/space/up", () => { intent.jump = false; });
|
|
162
677
|
|
|
@@ -169,16 +684,11 @@ function buildInputBindings(ecd, player) {
|
|
|
169
684
|
ic.bind("keyboard/keys/c/up", () => { intent.crouch = false; });
|
|
170
685
|
|
|
171
686
|
// -- Mouse look ------------------------------------------------------
|
|
172
|
-
// Only accumulate look delta while the pointer is captured — otherwise
|
|
173
|
-
// moving the cursor over the page would steer the camera, which is
|
|
174
|
-
// jarring before the user has "claimed" the input surface.
|
|
175
687
|
ic.bind("pointer/on/move", (position, event, delta) => {
|
|
176
688
|
if (document.pointerLockElement === null) return;
|
|
177
689
|
intent.look._add(delta.x * SENSITIVITY, delta.y * SENSITIVITY);
|
|
178
690
|
});
|
|
179
691
|
|
|
180
|
-
// When the InputController unlinks (e.g. system shutdown), zero
|
|
181
|
-
// everything so a held key doesn't get stuck.
|
|
182
692
|
ic.on.unlinked.add(() => {
|
|
183
693
|
intent.move.set(0, 0);
|
|
184
694
|
intent.look.set(0, 0);
|
|
@@ -200,10 +710,6 @@ function buildInputBindings(ecd, player) {
|
|
|
200
710
|
*/
|
|
201
711
|
function setupPointerLock(engine) {
|
|
202
712
|
const el = engine.graphics.domElement;
|
|
203
|
-
|
|
204
|
-
// The harness wires the engine into the page body via viewStack; the
|
|
205
|
-
// canvas is the actual pointer-lock target. Listen on the viewStack
|
|
206
|
-
// element so clicks anywhere inside the canvas trigger the request.
|
|
207
713
|
const captureEl = engine.viewStack.el;
|
|
208
714
|
|
|
209
715
|
captureEl.addEventListener("click", () => {
|
|
@@ -212,98 +718,23 @@ function setupPointerLock(engine) {
|
|
|
212
718
|
}
|
|
213
719
|
});
|
|
214
720
|
|
|
215
|
-
// Suppress the right-click context menu so the canvas stays usable.
|
|
216
721
|
captureEl.addEventListener("contextmenu", (e) => e.preventDefault());
|
|
217
722
|
}
|
|
218
723
|
|
|
219
|
-
/**
|
|
220
|
-
* Spawn a handful of marker entities around the player so motion is
|
|
221
|
-
* visually obvious. All markers go through the standard ECS pipeline
|
|
222
|
-
* (Transform + ShadedGeometry) — same path as gameplay geometry — so
|
|
223
|
-
* shadows and lighting work correctly.
|
|
224
|
-
*
|
|
225
|
-
* @param {EntityComponentDataset} ecd
|
|
226
|
-
*/
|
|
227
|
-
function addReferenceMarkers(ecd) {
|
|
228
|
-
const SPAWN_X = 100, SPAWN_Z = 100;
|
|
229
|
-
|
|
230
|
-
// Share one unit-cube geometry across the ring cubes — cheap and lets
|
|
231
|
-
// the renderer's instancing path kick in if it wants.
|
|
232
|
-
const unitCubeGeom = new BoxGeometry(1, 1, 1);
|
|
233
|
-
const palette = [0xff5555, 0x55ff55, 0x5577ff, 0xffaa44, 0xaa55ff, 0x44ddee, 0xff66cc, 0x66ffcc];
|
|
234
|
-
|
|
235
|
-
// Ring of coloured cubes at radius 6 — circle-strafe targets.
|
|
236
|
-
const RING_N = 8;
|
|
237
|
-
for (let i = 0; i < RING_N; i++) {
|
|
238
|
-
const a = (i / RING_N) * Math.PI * 2;
|
|
239
|
-
spawnMarker({
|
|
240
|
-
ecd,
|
|
241
|
-
geometry: unitCubeGeom,
|
|
242
|
-
color: palette[i % palette.length],
|
|
243
|
-
roughness: 0.8,
|
|
244
|
-
position: new Vector3(SPAWN_X + Math.cos(a) * 6, 0.5, SPAWN_Z + Math.sin(a) * 6),
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// Tall pillars further out — for parallax depth-perception while
|
|
249
|
-
// testing bob and breath at distance.
|
|
250
|
-
const pillarGeom = new BoxGeometry(1, 6, 1);
|
|
251
|
-
const PILLAR_N = 6;
|
|
252
|
-
for (let i = 0; i < PILLAR_N; i++) {
|
|
253
|
-
const a = (i / PILLAR_N) * Math.PI * 2 + 0.3;
|
|
254
|
-
const r = 22;
|
|
255
|
-
spawnMarker({
|
|
256
|
-
ecd,
|
|
257
|
-
geometry: pillarGeom,
|
|
258
|
-
color: 0x888888,
|
|
259
|
-
roughness: 0.9,
|
|
260
|
-
position: new Vector3(SPAWN_X + Math.cos(a) * r, 3, SPAWN_Z + Math.sin(a) * r),
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// A low platform next to spawn — easy hop target, plus a chance to see
|
|
265
|
-
// the landing dip when stepping back down.
|
|
266
|
-
spawnMarker({
|
|
267
|
-
ecd,
|
|
268
|
-
geometry: new BoxGeometry(2, 0.4, 2),
|
|
269
|
-
color: 0xddddee,
|
|
270
|
-
roughness: 0.7,
|
|
271
|
-
position: new Vector3(SPAWN_X + 3, 0.2, SPAWN_Z),
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* @param {object} p
|
|
277
|
-
* @param {EntityComponentDataset} p.ecd
|
|
278
|
-
* @param {THREE.BufferGeometry} p.geometry
|
|
279
|
-
* @param {number} p.color Hex color, e.g. 0xff5555
|
|
280
|
-
* @param {number} [p.roughness]
|
|
281
|
-
* @param {Vector3} p.position
|
|
282
|
-
*/
|
|
283
|
-
function spawnMarker({ ecd, geometry, color, roughness = 0.8, position }) {
|
|
284
|
-
const material = new MeshStandardMaterial({ color, roughness });
|
|
285
|
-
const sg = ShadedGeometry.from(geometry, material);
|
|
286
|
-
sg.setFlag(ShadedGeometryFlags.CastShadow);
|
|
287
|
-
sg.setFlag(ShadedGeometryFlags.ReceiveShadow);
|
|
288
|
-
sg.setFlag(ShadedGeometryFlags.Visible);
|
|
289
|
-
|
|
290
|
-
const transform = new Transform();
|
|
291
|
-
transform.position.copy(position);
|
|
292
|
-
|
|
293
|
-
new Entity()
|
|
294
|
-
.add(transform)
|
|
295
|
-
.add(sg)
|
|
296
|
-
.add(Tag.fromJSON(["ReferenceMarker"]))
|
|
297
|
-
.add(SerializationMetadata.Transient)
|
|
298
|
-
.build(ecd);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
724
|
function logHelp() {
|
|
302
725
|
/* eslint-disable no-console */
|
|
303
|
-
console.log("%cFirstPersonPlayerController
|
|
726
|
+
console.log("%cFirstPersonPlayerController — Parkour Gym",
|
|
304
727
|
"color:#88ddff;font-weight:bold;font-size:14px");
|
|
305
728
|
console.log("Click the canvas to capture mouse. ESC to release.");
|
|
306
729
|
console.log("WASD = move | Mouse = look | Space = jump | Shift = sprint | C = crouch");
|
|
730
|
+
console.log("");
|
|
731
|
+
console.log("%cStations:", "font-weight:bold");
|
|
732
|
+
console.log(" N Mantle row — four obstacles, last one is too tall");
|
|
733
|
+
console.log(" NE Slide tunnel — sprint + C to slide under the low ceiling");
|
|
734
|
+
console.log(" E Wall-run — sprint along, jump near the wall");
|
|
735
|
+
console.log(" SE Gap jump — mantle up the stair, sprint, jump the gap");
|
|
736
|
+
console.log(" S Ledge-grab — too tall to mantle; jump at it, catch the lip");
|
|
737
|
+
console.log(" W Wall-jump chimney — alternate walls to climb");
|
|
307
738
|
}
|
|
308
739
|
|
|
309
740
|
async function init() {
|