@woosh/meep-engine 2.153.0 → 2.154.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/geom/3d/shape/ConvexHullShape3D.d.ts +112 -0
- package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -0
- package/src/core/geom/3d/shape/ConvexHullShape3D.js +325 -0
- package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts +4 -0
- package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts.map +1 -1
- package/src/engine/graphics/ecs/trail2d/Trail2D.js +21 -0
- package/src/engine/physics/PLAN.md +4 -4
- package/src/engine/physics/body/BodyStorage.d.ts +3 -1
- package/src/engine/physics/body/BodyStorage.d.ts.map +1 -1
- package/src/engine/physics/body/BodyStorage.js +452 -450
- package/src/engine/physics/body/SolverBodyState.d.ts.map +1 -1
- package/src/engine/physics/body/SolverBodyState.js +6 -5
- package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
- package/src/engine/physics/broadphase/generate_pairs.js +9 -1
- package/src/engine/physics/ccd/linear_sweep.d.ts.map +1 -1
- package/src/engine/physics/ccd/linear_sweep.js +237 -238
- package/src/engine/physics/computeInterceptPoint.d.ts.map +1 -1
- package/src/engine/physics/computeInterceptPoint.js +8 -3
- package/src/engine/physics/contact/ManifoldStore.d.ts +0 -16
- package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -1
- package/src/engine/physics/contact/ManifoldStore.js +1 -38
- package/src/engine/physics/ecs/BodyKind.d.ts +3 -2
- package/src/engine/physics/ecs/BodyKind.d.ts.map +1 -1
- package/src/engine/physics/ecs/BodyKind.js +25 -24
- package/src/engine/physics/ecs/PhysicsEvents.d.ts +4 -5
- package/src/engine/physics/ecs/PhysicsEvents.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsEvents.js +15 -16
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +5 -30
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +13 -45
- package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts.map +1 -1
- package/src/engine/physics/ecs/RigidBodySerializationAdapter.js +85 -81
- package/src/engine/physics/ecs/is_sensor.d.ts +18 -0
- package/src/engine/physics/ecs/is_sensor.d.ts.map +1 -0
- package/src/engine/physics/ecs/is_sensor.js +27 -0
- package/src/engine/physics/events/ContactEventBuffer.d.ts +2 -1
- package/src/engine/physics/events/ContactEventBuffer.d.ts.map +1 -1
- package/src/engine/physics/events/ContactEventBuffer.js +84 -83
- package/src/engine/physics/gjk/gjk.d.ts +0 -26
- package/src/engine/physics/gjk/gjk.d.ts.map +1 -1
- package/src/engine/physics/gjk/gjk.js +3 -52
- package/src/engine/physics/gjk/gjk_epa_penetration.d.ts +16 -0
- package/src/engine/physics/gjk/gjk_epa_penetration.d.ts.map +1 -0
- package/src/engine/physics/gjk/gjk_epa_penetration.js +255 -0
- package/src/engine/physics/gjk/minkowski_support.d.ts +4 -9
- package/src/engine/physics/gjk/minkowski_support.d.ts.map +1 -1
- package/src/engine/physics/gjk/minkowski_support.js +70 -75
- package/src/engine/physics/gjk/mpr.d.ts +1 -1
- package/src/engine/physics/gjk/mpr.d.ts.map +1 -1
- package/src/engine/physics/gjk/mpr.js +362 -344
- package/src/engine/physics/island/IslandBuilder.d.ts.map +1 -1
- package/src/engine/physics/island/IslandBuilder.js +431 -428
- package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/box_box_manifold.js +4 -81
- package/src/engine/physics/narrowphase/box_triangle_contact.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/box_triangle_contact.js +4 -39
- package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/capsule_contacts.js +459 -462
- package/src/engine/physics/narrowphase/clip_against_axis_uv.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/clip_against_axis_uv.js +4 -1
- package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts +83 -0
- package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/convex_convex_manifold.js +425 -0
- package/src/engine/physics/narrowphase/convex_decomposition.d.ts +32 -0
- package/src/engine/physics/narrowphase/convex_decomposition.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/convex_decomposition.js +293 -0
- package/src/engine/physics/narrowphase/mesh_convex_hull.d.ts +41 -0
- package/src/engine/physics/narrowphase/mesh_convex_hull.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/mesh_convex_hull.js +106 -0
- package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.d.ts +8 -0
- package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.js +117 -0
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/narrowphase_step.js +105 -102
- package/src/engine/physics/narrowphase/reduce_manifold_contacts.d.ts +29 -0
- package/src/engine/physics/narrowphase/reduce_manifold_contacts.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/reduce_manifold_contacts.js +69 -0
- package/src/engine/physics/narrowphase/refine_ray_concave.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/refine_ray_concave.js +152 -145
- package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/sphere_box_contact.js +132 -123
- package/src/engine/physics/queries/overlap_shape.d.ts.map +1 -1
- package/src/engine/physics/queries/overlap_shape.js +16 -17
- package/src/engine/physics/queries/raycast.d.ts +5 -0
- package/src/engine/physics/queries/raycast.d.ts.map +1 -1
- package/src/engine/physics/queries/raycast.js +16 -8
- package/src/engine/physics/queries/shape_cast.d.ts.map +1 -1
- package/src/engine/physics/queries/shape_cast.js +13 -7
- package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -1
- package/src/engine/physics/solver/solve_contacts.js +8 -11
- package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -1
- package/src/engine/physics/vehicle/RaycastVehicle.js +339 -333
- package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts +0 -13
- package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts.map +0 -1
- package/src/engine/physics/gjk/expanding_polytope_algorithm.js +0 -399
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"description": "Pure JavaScript game engine. Fully featured and production ready.",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"author": "Alexander Goldring",
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.154.0",
|
|
10
10
|
"main": "build/meep.module.js",
|
|
11
11
|
"module": "build/meep.module.js",
|
|
12
12
|
"exports": {
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convex polyhedron collider.
|
|
3
|
+
*
|
|
4
|
+
* Holds a convex triangle surface (`vertices` + outward-CCW `indices`) and the
|
|
5
|
+
* derived face half-spaces. Because it is convex (`is_convex === true`, the
|
|
6
|
+
* default), it routes straight through the narrowphase's GJK + EPA path via
|
|
7
|
+
* {@link support} — no tetrahedralisation, no per-triangle decomposition, no
|
|
8
|
+
* BVH. This is the right shape for authored convex geometry (props, crates,
|
|
9
|
+
* gems, low-poly rocks, an icosphere) and is far cheaper to construct than
|
|
10
|
+
* {@link MeshShape3D}, which tetrahedralises its interior.
|
|
11
|
+
*
|
|
12
|
+
* Contract:
|
|
13
|
+
* - `support` is exact for any convex point set (deepest vertex along the
|
|
14
|
+
* direction) — the precondition GJK relies on.
|
|
15
|
+
* - `contains_point` is the convex half-space test (behind every face plane).
|
|
16
|
+
* - `signed_distance` / `nearest_point_on_surface` scan the surface triangles
|
|
17
|
+
* (O(F)); these are query-path helpers, not on the collision hot path.
|
|
18
|
+
*
|
|
19
|
+
* The input is assumed convex with outward-facing CCW winding — build it via
|
|
20
|
+
* {@link ConvexHullShape3D.from}. A genuine non-convex mesh belongs in
|
|
21
|
+
* {@link MeshShape3D} (and, once decomposition lands, will be represented as a
|
|
22
|
+
* set of these pieces).
|
|
23
|
+
*
|
|
24
|
+
* @author Alex Goldring
|
|
25
|
+
* @copyright Company Named Limited (c) 2026
|
|
26
|
+
*/
|
|
27
|
+
export class ConvexHullShape3D extends AbstractShape3D {
|
|
28
|
+
/**
|
|
29
|
+
* Build from a convex triangle surface. Vertices must lie on the hull and
|
|
30
|
+
* faces must wind CCW when viewed from outside.
|
|
31
|
+
*
|
|
32
|
+
* @param {Float32Array} vertices flat `(x, y, z)` per vertex
|
|
33
|
+
* @param {Uint32Array} indices three uint32 per triangle, outward CCW
|
|
34
|
+
* @returns {ConvexHullShape3D}
|
|
35
|
+
*/
|
|
36
|
+
static from(vertices: Float32Array, indices: Uint32Array): ConvexHullShape3D;
|
|
37
|
+
/**
|
|
38
|
+
* Hull vertex positions, flat `(x, y, z)` per vertex, in the body's
|
|
39
|
+
* local frame. Fed to {@link support}.
|
|
40
|
+
* @type {Float32Array}
|
|
41
|
+
*/
|
|
42
|
+
vertices: Float32Array;
|
|
43
|
+
/**
|
|
44
|
+
* Surface triangle indices, three uint32 per face (outward CCW). Used by
|
|
45
|
+
* the surface-scan query helpers (signed distance / nearest point).
|
|
46
|
+
* @type {Uint32Array}
|
|
47
|
+
*/
|
|
48
|
+
indices: Uint32Array;
|
|
49
|
+
/**
|
|
50
|
+
* Polygon-face representation for the contact clipper (CSR): face `f`'s
|
|
51
|
+
* vertex loop is `face_loops[face_offsets[f] .. face_offsets[f+1]]`,
|
|
52
|
+
* ordered CCW (outward). Currently one triangle per face; a coplanar-merge
|
|
53
|
+
* pass will collapse coplanar triangles into larger polygon faces.
|
|
54
|
+
* @type {Uint32Array}
|
|
55
|
+
*/
|
|
56
|
+
face_offsets: Uint32Array;
|
|
57
|
+
/** @type {Uint32Array} */
|
|
58
|
+
face_loops: Uint32Array;
|
|
59
|
+
/**
|
|
60
|
+
* Face half-spaces, four doubles per face `(nx, ny, nz, d)` with unit
|
|
61
|
+
* outward normal and `d = n · v` — point is inside iff `n · p − d ≤ 0`
|
|
62
|
+
* for every face. Derived in {@link recompute}.
|
|
63
|
+
* @private
|
|
64
|
+
* @type {Float64Array}
|
|
65
|
+
*/
|
|
66
|
+
private __planes;
|
|
67
|
+
/** @private @type {Float64Array} */
|
|
68
|
+
private __bbox;
|
|
69
|
+
/** @private @type {number} */
|
|
70
|
+
private __volume;
|
|
71
|
+
/** @private @type {number} */
|
|
72
|
+
private __surface_area;
|
|
73
|
+
/**
|
|
74
|
+
* Refresh the cached bbox / face planes / volume / surface area from the
|
|
75
|
+
* current `vertices` / `indices`.
|
|
76
|
+
*/
|
|
77
|
+
recompute(): void;
|
|
78
|
+
compute_bounding_box(result: any): void;
|
|
79
|
+
/**
|
|
80
|
+
* GJK support: the hull vertex furthest along the direction. Exact for a
|
|
81
|
+
* convex point set. Linear scan over the vertices — fine for the modest
|
|
82
|
+
* vertex counts of authored hulls; a hill-climb over vertex adjacency is
|
|
83
|
+
* the acceleration for very large hulls.
|
|
84
|
+
*/
|
|
85
|
+
support(result: any, result_offset: any, direction_x: any, direction_y: any, direction_z: any): void;
|
|
86
|
+
/**
|
|
87
|
+
* Convex half-space test: inside iff the point is behind (or on) every face
|
|
88
|
+
* plane. Exact for a convex polytope.
|
|
89
|
+
*/
|
|
90
|
+
contains_point(point: any): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Unsigned nearest-surface distance via a per-triangle scan, signed by
|
|
93
|
+
* {@link contains_point}. Same approach as {@link MeshShape3D}; O(F).
|
|
94
|
+
*/
|
|
95
|
+
signed_distance_at_point(point: any): number;
|
|
96
|
+
signed_distance_gradient_at_point(result: any, point: any): number;
|
|
97
|
+
nearest_point_on_surface(result: any, reference: any): void;
|
|
98
|
+
sample_random_point_in_volume(result: any, result_offset: any, random: any): void;
|
|
99
|
+
/**
|
|
100
|
+
* @param {ConvexHullShape3D} other
|
|
101
|
+
* @returns {boolean}
|
|
102
|
+
*/
|
|
103
|
+
equals(other: ConvexHullShape3D): boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Fast type-check marker.
|
|
106
|
+
* @readonly
|
|
107
|
+
* @type {boolean}
|
|
108
|
+
*/
|
|
109
|
+
readonly isConvexHullShape3D: boolean;
|
|
110
|
+
}
|
|
111
|
+
import { AbstractShape3D } from "./AbstractShape3D.js";
|
|
112
|
+
//# sourceMappingURL=ConvexHullShape3D.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConvexHullShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/ConvexHullShape3D.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH;IA+CI;;;;;;;OAOG;IACH,sBAJW,YAAY,WACZ,WAAW,GACT,iBAAiB,CAQ7B;IAxDG;;;;OAIG;IACH,UAFU,YAAY,CAEa;IAEnC;;;;OAIG;IACH,SAFU,WAAW,CAEY;IAEjC;;;;;;OAMG;IACH,cAFU,WAAW,CAEiB;IACtC,0BAA0B;IAC1B,YADW,WAAW,CACc;IAEpC;;;;;;OAMG;IACH,iBAAmC;IAEnC,oCAAoC;IACpC,eAAiC;IACjC,8BAA8B;IAC9B,iBAAiB;IACjB,8BAA8B;IAC9B,uBAAuB;IAmB3B;;;OAGG;IACH,kBAmDC;IAKD,wCAIC;IAED;;;;;OAKG;IACH,qGAgBC;IAED;;;OAGG;IACH,oCAgBC;IAED;;;OAGG;IACH,6CAwBC;IAED,mEAEC;IAED,4DAwBC;IAED,kFAmBC;IAED;;;OAGG;IACH,cAHW,iBAAiB,GACf,OAAO,CAanB;IAcL;;;;OAIG;IACH,8BAFU,OAAO,CAE8B;CAP9C;gCAxT+B,sBAAsB"}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import { computeHashFloat } from "../../../primitives/numbers/computeHashFloat.js";
|
|
2
|
+
import { computeTriangleClosestPointToPointBarycentric } from "../triangle/computeTriangleClosestPointToPointBarycentric.js";
|
|
3
|
+
import { AbstractShape3D } from "./AbstractShape3D.js";
|
|
4
|
+
import { compute_signed_distance_gradient_by_sampling } from "./util/compute_signed_distance_gradient_by_sampling.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Convex polyhedron collider.
|
|
8
|
+
*
|
|
9
|
+
* Holds a convex triangle surface (`vertices` + outward-CCW `indices`) and the
|
|
10
|
+
* derived face half-spaces. Because it is convex (`is_convex === true`, the
|
|
11
|
+
* default), it routes straight through the narrowphase's GJK + EPA path via
|
|
12
|
+
* {@link support} — no tetrahedralisation, no per-triangle decomposition, no
|
|
13
|
+
* BVH. This is the right shape for authored convex geometry (props, crates,
|
|
14
|
+
* gems, low-poly rocks, an icosphere) and is far cheaper to construct than
|
|
15
|
+
* {@link MeshShape3D}, which tetrahedralises its interior.
|
|
16
|
+
*
|
|
17
|
+
* Contract:
|
|
18
|
+
* - `support` is exact for any convex point set (deepest vertex along the
|
|
19
|
+
* direction) — the precondition GJK relies on.
|
|
20
|
+
* - `contains_point` is the convex half-space test (behind every face plane).
|
|
21
|
+
* - `signed_distance` / `nearest_point_on_surface` scan the surface triangles
|
|
22
|
+
* (O(F)); these are query-path helpers, not on the collision hot path.
|
|
23
|
+
*
|
|
24
|
+
* The input is assumed convex with outward-facing CCW winding — build it via
|
|
25
|
+
* {@link ConvexHullShape3D.from}. A genuine non-convex mesh belongs in
|
|
26
|
+
* {@link MeshShape3D} (and, once decomposition lands, will be represented as a
|
|
27
|
+
* set of these pieces).
|
|
28
|
+
*
|
|
29
|
+
* @author Alex Goldring
|
|
30
|
+
* @copyright Company Named Limited (c) 2026
|
|
31
|
+
*/
|
|
32
|
+
export class ConvexHullShape3D extends AbstractShape3D {
|
|
33
|
+
|
|
34
|
+
constructor() {
|
|
35
|
+
super();
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Hull vertex positions, flat `(x, y, z)` per vertex, in the body's
|
|
39
|
+
* local frame. Fed to {@link support}.
|
|
40
|
+
* @type {Float32Array}
|
|
41
|
+
*/
|
|
42
|
+
this.vertices = new Float32Array(0);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Surface triangle indices, three uint32 per face (outward CCW). Used by
|
|
46
|
+
* the surface-scan query helpers (signed distance / nearest point).
|
|
47
|
+
* @type {Uint32Array}
|
|
48
|
+
*/
|
|
49
|
+
this.indices = new Uint32Array(0);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Polygon-face representation for the contact clipper (CSR): face `f`'s
|
|
53
|
+
* vertex loop is `face_loops[face_offsets[f] .. face_offsets[f+1]]`,
|
|
54
|
+
* ordered CCW (outward). Currently one triangle per face; a coplanar-merge
|
|
55
|
+
* pass will collapse coplanar triangles into larger polygon faces.
|
|
56
|
+
* @type {Uint32Array}
|
|
57
|
+
*/
|
|
58
|
+
this.face_offsets = new Uint32Array(0);
|
|
59
|
+
/** @type {Uint32Array} */
|
|
60
|
+
this.face_loops = new Uint32Array(0);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Face half-spaces, four doubles per face `(nx, ny, nz, d)` with unit
|
|
64
|
+
* outward normal and `d = n · v` — point is inside iff `n · p − d ≤ 0`
|
|
65
|
+
* for every face. Derived in {@link recompute}.
|
|
66
|
+
* @private
|
|
67
|
+
* @type {Float64Array}
|
|
68
|
+
*/
|
|
69
|
+
this.__planes = new Float64Array(0);
|
|
70
|
+
|
|
71
|
+
/** @private @type {Float64Array} */
|
|
72
|
+
this.__bbox = new Float64Array(6);
|
|
73
|
+
/** @private @type {number} */
|
|
74
|
+
this.__volume = 0;
|
|
75
|
+
/** @private @type {number} */
|
|
76
|
+
this.__surface_area = 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Build from a convex triangle surface. Vertices must lie on the hull and
|
|
81
|
+
* faces must wind CCW when viewed from outside.
|
|
82
|
+
*
|
|
83
|
+
* @param {Float32Array} vertices flat `(x, y, z)` per vertex
|
|
84
|
+
* @param {Uint32Array} indices three uint32 per triangle, outward CCW
|
|
85
|
+
* @returns {ConvexHullShape3D}
|
|
86
|
+
*/
|
|
87
|
+
static from(vertices, indices) {
|
|
88
|
+
const s = new ConvexHullShape3D();
|
|
89
|
+
s.vertices = vertices;
|
|
90
|
+
s.indices = indices;
|
|
91
|
+
s.recompute();
|
|
92
|
+
return s;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Refresh the cached bbox / face planes / volume / surface area from the
|
|
97
|
+
* current `vertices` / `indices`.
|
|
98
|
+
*/
|
|
99
|
+
recompute() {
|
|
100
|
+
const v = this.vertices;
|
|
101
|
+
const idx = this.indices;
|
|
102
|
+
|
|
103
|
+
let mnx = Infinity, mny = Infinity, mnz = Infinity;
|
|
104
|
+
let mxx = -Infinity, mxy = -Infinity, mxz = -Infinity;
|
|
105
|
+
const vc = v.length / 3;
|
|
106
|
+
for (let i = 0; i < vc; i++) {
|
|
107
|
+
const x = v[i * 3], y = v[i * 3 + 1], z = v[i * 3 + 2];
|
|
108
|
+
if (x < mnx) mnx = x; if (x > mxx) mxx = x;
|
|
109
|
+
if (y < mny) mny = y; if (y > mxy) mxy = y;
|
|
110
|
+
if (z < mnz) mnz = z; if (z > mxz) mxz = z;
|
|
111
|
+
}
|
|
112
|
+
if (vc === 0) { mnx = mny = mnz = mxx = mxy = mxz = 0; }
|
|
113
|
+
const b = this.__bbox;
|
|
114
|
+
b[0] = mnx; b[1] = mny; b[2] = mnz; b[3] = mxx; b[4] = mxy; b[5] = mxz;
|
|
115
|
+
|
|
116
|
+
const tri = idx.length / 3;
|
|
117
|
+
const planes = new Float64Array(tri * 4);
|
|
118
|
+
let area = 0;
|
|
119
|
+
let vol6 = 0; // 6× the signed volume (Σ a·(b×c) over outward faces)
|
|
120
|
+
for (let f = 0; f < tri; f++) {
|
|
121
|
+
const ia = idx[f * 3] * 3, ib = idx[f * 3 + 1] * 3, ic = idx[f * 3 + 2] * 3;
|
|
122
|
+
const ax = v[ia], ay = v[ia + 1], az = v[ia + 2];
|
|
123
|
+
const bx = v[ib], by = v[ib + 1], bz = v[ib + 2];
|
|
124
|
+
const cx = v[ic], cy = v[ic + 1], cz = v[ic + 2];
|
|
125
|
+
|
|
126
|
+
const e1x = bx - ax, e1y = by - ay, e1z = bz - az;
|
|
127
|
+
const e2x = cx - ax, e2y = cy - ay, e2z = cz - az;
|
|
128
|
+
let nx = e1y * e2z - e1z * e2y;
|
|
129
|
+
let ny = e1z * e2x - e1x * e2z;
|
|
130
|
+
let nz = e1x * e2y - e1y * e2x;
|
|
131
|
+
const len = Math.sqrt(nx * nx + ny * ny + nz * nz) || 1;
|
|
132
|
+
area += 0.5 * len;
|
|
133
|
+
vol6 += ax * (by * cz - bz * cy) + ay * (bz * cx - bx * cz) + az * (bx * cy - by * cx);
|
|
134
|
+
|
|
135
|
+
nx /= len; ny /= len; nz /= len;
|
|
136
|
+
const o = f * 4;
|
|
137
|
+
planes[o] = nx; planes[o + 1] = ny; planes[o + 2] = nz;
|
|
138
|
+
planes[o + 3] = nx * ax + ny * ay + nz * az;
|
|
139
|
+
}
|
|
140
|
+
this.__planes = planes;
|
|
141
|
+
this.__surface_area = area;
|
|
142
|
+
this.__volume = Math.abs(vol6) / 6;
|
|
143
|
+
|
|
144
|
+
// Polygon faces for the clipper. v1: one triangle per face (the contact
|
|
145
|
+
// clipper consumes polygon loops; a tetrahedral piece is exactly this).
|
|
146
|
+
const fo = new Uint32Array(tri + 1);
|
|
147
|
+
for (let f = 0; f <= tri; f++) fo[f] = f * 3;
|
|
148
|
+
this.face_offsets = fo;
|
|
149
|
+
this.face_loops = idx;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
get volume() { return this.__volume; }
|
|
153
|
+
get surface_area() { return this.__surface_area; }
|
|
154
|
+
|
|
155
|
+
compute_bounding_box(result) {
|
|
156
|
+
const b = this.__bbox;
|
|
157
|
+
result[0] = b[0]; result[1] = b[1]; result[2] = b[2];
|
|
158
|
+
result[3] = b[3]; result[4] = b[4]; result[5] = b[5];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* GJK support: the hull vertex furthest along the direction. Exact for a
|
|
163
|
+
* convex point set. Linear scan over the vertices — fine for the modest
|
|
164
|
+
* vertex counts of authored hulls; a hill-climb over vertex adjacency is
|
|
165
|
+
* the acceleration for very large hulls.
|
|
166
|
+
*/
|
|
167
|
+
support(result, result_offset, direction_x, direction_y, direction_z) {
|
|
168
|
+
const v = this.vertices;
|
|
169
|
+
const vc = v.length / 3;
|
|
170
|
+
if (vc === 0) {
|
|
171
|
+
result[result_offset] = 0; result[result_offset + 1] = 0; result[result_offset + 2] = 0;
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
let best = -Infinity;
|
|
175
|
+
let bi = 0;
|
|
176
|
+
for (let i = 0; i < vc; i++) {
|
|
177
|
+
const d = direction_x * v[i * 3] + direction_y * v[i * 3 + 1] + direction_z * v[i * 3 + 2];
|
|
178
|
+
if (d > best) { best = d; bi = i; }
|
|
179
|
+
}
|
|
180
|
+
result[result_offset] = v[bi * 3];
|
|
181
|
+
result[result_offset + 1] = v[bi * 3 + 1];
|
|
182
|
+
result[result_offset + 2] = v[bi * 3 + 2];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Convex half-space test: inside iff the point is behind (or on) every face
|
|
187
|
+
* plane. Exact for a convex polytope.
|
|
188
|
+
*/
|
|
189
|
+
contains_point(point) {
|
|
190
|
+
const px = point[0], py = point[1], pz = point[2];
|
|
191
|
+
const b = this.__bbox;
|
|
192
|
+
if (px < b[0] || py < b[1] || pz < b[2] || px > b[3] || py > b[4] || pz > b[5]) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
const planes = this.__planes;
|
|
196
|
+
const f = planes.length / 4;
|
|
197
|
+
const EPS = 1e-6;
|
|
198
|
+
for (let i = 0; i < f; i++) {
|
|
199
|
+
const o = i * 4;
|
|
200
|
+
if (planes[o] * px + planes[o + 1] * py + planes[o + 2] * pz - planes[o + 3] > EPS) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Unsigned nearest-surface distance via a per-triangle scan, signed by
|
|
209
|
+
* {@link contains_point}. Same approach as {@link MeshShape3D}; O(F).
|
|
210
|
+
*/
|
|
211
|
+
signed_distance_at_point(point) {
|
|
212
|
+
const v = this.vertices;
|
|
213
|
+
const idx = this.indices;
|
|
214
|
+
const tri = idx.length / 3;
|
|
215
|
+
const px = point[0], py = point[1], pz = point[2];
|
|
216
|
+
|
|
217
|
+
let best_d2 = Infinity;
|
|
218
|
+
const baryc = scratch_barycentric;
|
|
219
|
+
for (let i = 0; i < tri; i++) {
|
|
220
|
+
const ia = idx[i * 3] * 3, ib = idx[i * 3 + 1] * 3, ic = idx[i * 3 + 2] * 3;
|
|
221
|
+
const ax = v[ia], ay = v[ia + 1], az = v[ia + 2];
|
|
222
|
+
const bx = v[ib], by = v[ib + 1], bz = v[ib + 2];
|
|
223
|
+
const cx = v[ic], cy = v[ic + 1], cz = v[ic + 2];
|
|
224
|
+
computeTriangleClosestPointToPointBarycentric(baryc, 0, px, py, pz, ax, ay, az, bx, by, bz, cx, cy, cz);
|
|
225
|
+
const u = baryc[0], w = baryc[1], t = 1 - u - w;
|
|
226
|
+
const qx = u * ax + w * bx + t * cx;
|
|
227
|
+
const qy = u * ay + w * by + t * cy;
|
|
228
|
+
const qz = u * az + w * bz + t * cz;
|
|
229
|
+
const dx = qx - px, dy = qy - py, dz = qz - pz;
|
|
230
|
+
const d2 = dx * dx + dy * dy + dz * dz;
|
|
231
|
+
if (d2 < best_d2) best_d2 = d2;
|
|
232
|
+
}
|
|
233
|
+
const dist = Math.sqrt(best_d2);
|
|
234
|
+
return this.contains_point(point) ? -dist : dist;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
signed_distance_gradient_at_point(result, point) {
|
|
238
|
+
return compute_signed_distance_gradient_by_sampling(result, this, point);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
nearest_point_on_surface(result, reference) {
|
|
242
|
+
const v = this.vertices;
|
|
243
|
+
const idx = this.indices;
|
|
244
|
+
const tri = idx.length / 3;
|
|
245
|
+
const px = reference[0], py = reference[1], pz = reference[2];
|
|
246
|
+
|
|
247
|
+
let best_d2 = Infinity;
|
|
248
|
+
let bx_ = 0, by_ = 0, bz_ = 0;
|
|
249
|
+
const baryc = scratch_barycentric;
|
|
250
|
+
for (let i = 0; i < tri; i++) {
|
|
251
|
+
const ia = idx[i * 3] * 3, ib = idx[i * 3 + 1] * 3, ic = idx[i * 3 + 2] * 3;
|
|
252
|
+
const ax = v[ia], ay = v[ia + 1], az = v[ia + 2];
|
|
253
|
+
const bx = v[ib], by = v[ib + 1], bz = v[ib + 2];
|
|
254
|
+
const cx = v[ic], cy = v[ic + 1], cz = v[ic + 2];
|
|
255
|
+
computeTriangleClosestPointToPointBarycentric(baryc, 0, px, py, pz, ax, ay, az, bx, by, bz, cx, cy, cz);
|
|
256
|
+
const u = baryc[0], w = baryc[1], t = 1 - u - w;
|
|
257
|
+
const qx = u * ax + w * bx + t * cx;
|
|
258
|
+
const qy = u * ay + w * by + t * cy;
|
|
259
|
+
const qz = u * az + w * bz + t * cz;
|
|
260
|
+
const dx = qx - px, dy = qy - py, dz = qz - pz;
|
|
261
|
+
const d2 = dx * dx + dy * dy + dz * dz;
|
|
262
|
+
if (d2 < best_d2) { best_d2 = d2; bx_ = qx; by_ = qy; bz_ = qz; }
|
|
263
|
+
}
|
|
264
|
+
result[0] = bx_; result[1] = by_; result[2] = bz_;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
sample_random_point_in_volume(result, result_offset, random) {
|
|
268
|
+
const b = this.__bbox;
|
|
269
|
+
const lx = b[0], ly = b[1], lz = b[2];
|
|
270
|
+
const sx = b[3] - b[0], sy = b[4] - b[1], sz = b[5] - b[2];
|
|
271
|
+
const probe = scratch_point;
|
|
272
|
+
for (let attempt = 0; attempt < 256; attempt++) {
|
|
273
|
+
probe[0] = lx + random() * sx;
|
|
274
|
+
probe[1] = ly + random() * sy;
|
|
275
|
+
probe[2] = lz + random() * sz;
|
|
276
|
+
if (this.contains_point(probe)) {
|
|
277
|
+
result[result_offset] = probe[0];
|
|
278
|
+
result[result_offset + 1] = probe[1];
|
|
279
|
+
result[result_offset + 2] = probe[2];
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
result[result_offset] = lx + sx * 0.5;
|
|
284
|
+
result[result_offset + 1] = ly + sy * 0.5;
|
|
285
|
+
result[result_offset + 2] = lz + sz * 0.5;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* @param {ConvexHullShape3D} other
|
|
290
|
+
* @returns {boolean}
|
|
291
|
+
*/
|
|
292
|
+
equals(other) {
|
|
293
|
+
if (!super.equals(other)) return false;
|
|
294
|
+
if (this.vertices.length !== other.vertices.length) return false;
|
|
295
|
+
if (this.indices.length !== other.indices.length) return false;
|
|
296
|
+
for (let i = 0; i < this.vertices.length; i++) {
|
|
297
|
+
if (this.vertices[i] !== other.vertices[i]) return false;
|
|
298
|
+
}
|
|
299
|
+
for (let i = 0; i < this.indices.length; i++) {
|
|
300
|
+
if (this.indices[i] !== other.indices[i]) return false;
|
|
301
|
+
}
|
|
302
|
+
return true;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
hash() {
|
|
306
|
+
const v_count = this.vertices.length / 3 | 0;
|
|
307
|
+
const t_count = this.indices.length / 3 | 0;
|
|
308
|
+
let h = (v_count * 31 + t_count) | 0;
|
|
309
|
+
if (this.vertices.length >= 3) {
|
|
310
|
+
h = (h * 31 + (computeHashFloat(this.vertices[0]))) | 0;
|
|
311
|
+
h = (h * 31 + (computeHashFloat(this.vertices[this.vertices.length - 1]))) | 0;
|
|
312
|
+
}
|
|
313
|
+
return h | 0;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Fast type-check marker.
|
|
319
|
+
* @readonly
|
|
320
|
+
* @type {boolean}
|
|
321
|
+
*/
|
|
322
|
+
ConvexHullShape3D.prototype.isConvexHullShape3D = true;
|
|
323
|
+
|
|
324
|
+
const scratch_barycentric = new Float64Array(2);
|
|
325
|
+
const scratch_point = new Float64Array(3);
|
|
@@ -90,6 +90,10 @@ declare class Trail2D {
|
|
|
90
90
|
*/
|
|
91
91
|
build(segment_count: number): void;
|
|
92
92
|
mesh: import("three").Mesh<import("three").BufferGeometry, import("three").Material | import("three").Material[]>;
|
|
93
|
+
/**
|
|
94
|
+
* Clear the trail's geometry and reset its state.
|
|
95
|
+
*/
|
|
96
|
+
clear(): void;
|
|
93
97
|
fromJSON({ maxAge, width, textureURL, offset, color }: {
|
|
94
98
|
maxAge?: number;
|
|
95
99
|
width?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Trail2D.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/trail2d/Trail2D.js"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"Trail2D.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/trail2d/Trail2D.js"],"names":[],"mappings":";AAoBA;IAsKI,oCAMC;IA1KD;;;OAGG;IACH,QAFU,MAAM,CAES;IAEzB;;;OAGG;IACH,OAFU,MAAM,CAEM;IAEtB;;;OAGG;IACH,MAFU,MAAM,CAEP;IAET;;;OAGG;IACH,eAFU,MAAM,CAEE;IAElB;;;OAGG;IACH,qBAFU,MAAM,CAEQ;IAExB;;;OAGG;IACH,gBAFU,KAAK,CAEe;IAE9B;;;;OAIG;IACH,iBAFU,OAAO,CAEM;IAEvB;;;OAGG;IACH,QAFU,OAAO,GAAC,IAAI,CAER;IAEd;;;OAGG;IACH,UAFU,mBAAmB,CAEQ;IAErC;;;OAGG;IACH,cAFU,SAAS,CAEG;IAEtB;;;OAGG;IACH,cAAsB;IAEtB,gBAQC;IAMD,4BAEC;IAND,yBAEC;IAMD;;;;OAIG;IACH,cAHW,MAAM,GAAC,YAAY,GACjB,IAAI,CAIhB;IAED;;;;OAIG;IACH,gBAHW,MAAM,GAAC,YAAY,GACjB,IAAI,CAIhB;IAED;;;;OAIG;IACH,gBAHW,MAAM,GAAC,YAAY,SACnB,OAAO,QAQjB;IAED;;;;OAIG;IACH,cAHW,MAAM,GAAC,YAAY,GACjB,OAAO,CAInB;IAED;;;OAGG;IACH,qBAFW,MAAM,QAehB;IADG,kHAAgB;IAGpB;;OAEG;IACH,cAeC;IAUD;;;;;;;;;;;aAcC;IAGD;;;;;;;;;;;;;;;MAQC;IAED;;;OAGG;IACH,cAFW,OAAO,WASjB;IAED;;;;;;;OAOG;IACH,cANW,MAAM,KACN,MAAM,KACN,MAAM,YACN,MAAM,GACJ,OAAO,CA2CnB;CAEJ;;;;;;sBA3RqB,iCAAiC;oBACnC,kCAAkC;wBAI9B,0BAA0B;oCACd,sCAAsC;0BAPhD,yCAAyC;6BAStC,mBAAmB;kCADd,wBAAwB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FLOAT32_MAX } from "../../../../core/binary/FLOAT32_MAX.js";
|
|
1
2
|
import { BvhClient } from "../../../../core/bvh2/bvh3/BvhClient.js";
|
|
2
3
|
import { Color } from "../../../../core/color/Color.js";
|
|
3
4
|
import Vector3 from "../../../../core/geom/Vector3.js";
|
|
@@ -163,6 +164,26 @@ class Trail2D {
|
|
|
163
164
|
this.mesh = mesh;
|
|
164
165
|
}
|
|
165
166
|
|
|
167
|
+
/**
|
|
168
|
+
* Clear the trail's geometry and reset its state.
|
|
169
|
+
*/
|
|
170
|
+
clear() {
|
|
171
|
+
const ribbon = this.ribbon;
|
|
172
|
+
|
|
173
|
+
if (ribbon === null) {
|
|
174
|
+
// nothing to clear
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const n = ribbon.getCount();
|
|
179
|
+
|
|
180
|
+
for (let i = 0; i < n; i++) {
|
|
181
|
+
ribbon.setPointAttribute_Scalar(i, RIBBON_ATTRIBUTE_ADDRESS_AGE, FLOAT32_MAX);
|
|
182
|
+
ribbon.setPointAlpha(i, 0);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
}
|
|
186
|
+
|
|
166
187
|
static fromJSON(json) {
|
|
167
188
|
const r = new Trail2D();
|
|
168
189
|
|
|
@@ -117,10 +117,10 @@ Architectural references for design choices:
|
|
|
117
117
|
call. A 100-block stack hit at the base wakes top-down in one frame
|
|
118
118
|
rather than over 100 frames of broadphase propagation.
|
|
119
119
|
- `DisableSleep` on any island member exempts the whole island.
|
|
120
|
-
- ContactBegin / Stay / End buffer + dispatch through
|
|
121
|
-
`
|
|
122
|
-
|
|
123
|
-
dataset is attached
|
|
120
|
+
- ContactBegin / Stay / End buffer + dispatch through the per-entity
|
|
121
|
+
`dataset.sendEvent(entity, PhysicsEvents.ContactBegin, ...)` channel — the
|
|
122
|
+
sole contact-event path, delivered to each entity of the pair when a
|
|
123
|
+
dataset is attached.
|
|
124
124
|
|
|
125
125
|
### Islands
|
|
126
126
|
- **Union-find** with path halving + union by min-index over the awake-body
|
|
@@ -68,7 +68,9 @@ export class BodyStorage {
|
|
|
68
68
|
*/
|
|
69
69
|
get size(): number;
|
|
70
70
|
/**
|
|
71
|
-
* Total slot capacity.
|
|
71
|
+
* Total slot capacity. Starts at the (power-of-two) default and grows by
|
|
72
|
+
* doubling; a caller-supplied non-power-of-two initial capacity is honoured
|
|
73
|
+
* as-is, so this is not guaranteed to be a power of two.
|
|
72
74
|
* @returns {number}
|
|
73
75
|
*/
|
|
74
76
|
get capacity(): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BodyStorage.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/body/BodyStorage.js"],"names":[],"mappings":"AA2BA;;;;;;GAMG;AACH,oCAJW,MAAM,cACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,sCAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,2CAHW,MAAM,GACJ,MAAM,CAIlB;AAlCD;;;;GAIG;AACH,gCAFU,MAAM,CAEoB;AA+BpC;;;;;;;;;;;;;;;;;;GAkBG;AACH;IAEI;;;OAGG;IACH,+BAFW,MAAM,EAqChB;IA9BG,mBAAqB;IAGrB,gBAAgB;IAEhB,uBAAqC;IACrC,0BAAwC;IACxC,oBAAkC;IAClC,qBAAmC;IAGnC,oBAAkC;IAGlC,0BAAwC;IACxC,wBAAsC;IACtC,sBAAsB;IAGtB,yBAAuC;IACvC,qBAAqB;IAMrB,iCAAkC;IAMtC;;;OAGG;IACH,mBAEC;IAED
|
|
1
|
+
{"version":3,"file":"BodyStorage.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/body/BodyStorage.js"],"names":[],"mappings":"AA2BA;;;;;;GAMG;AACH,oCAJW,MAAM,cACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,sCAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,2CAHW,MAAM,GACJ,MAAM,CAIlB;AAlCD;;;;GAIG;AACH,gCAFU,MAAM,CAEoB;AA+BpC;;;;;;;;;;;;;;;;;;GAkBG;AACH;IAEI;;;OAGG;IACH,+BAFW,MAAM,EAqChB;IA9BG,mBAAqB;IAGrB,gBAAgB;IAEhB,uBAAqC;IACrC,0BAAwC;IACxC,oBAAkC;IAClC,qBAAmC;IAGnC,oBAAkC;IAGlC,0BAAwC;IACxC,wBAAsC;IACtC,sBAAsB;IAGtB,yBAAuC;IACvC,qBAAqB;IAMrB,iCAAkC;IAMtC;;;OAGG;IACH,mBAEC;IAED;;;;;OAKG;IACH,uBAEC;IAED;;;OAGG;IACH,0BAEC;IAED;;;;OAIG;IACH,8BAEC;IAED;;;;;;;OAOG;IACH,iBAHW,MAAM,GACJ,MAAM,CA0BlB;IAED;;;;;OAKG;IACH,qBAFW,MAAM,QAwBhB;IAED;;;;OAIG;IACH,yBAHW,MAAM,GACJ,OAAO,CAWnB;IAED;;;OAGG;IACH,iBAHW,MAAM,GACJ,MAAM,CAOlB;IAED;;;;;;OAMG;IACH,wBAHW,MAAM,GACJ,MAAM,CAKlB;IAED;;;OAGG;IACH,qBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,eAHW,MAAM,GACJ,QAAQ,GAAC,MAAM,CAI3B;IAED;;;OAGG;IACH,gBAHW,MAAM,QACN,QAAQ,GAAC,MAAM,QAIzB;IAED;;;OAGG;IACH,gBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,iBAHW,MAAM,SACN,MAAM,QAIhB;IAED;;;;OAIG;IACH,yBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;OAIG;IACH,gBAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;;OAIG;IACH,YAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,kBAFW,MAAM,QAShB;IAED;;;OAGG;IACH,qBAFW,MAAM,QAShB;IAED;;;;OAIG;IACH,0BAOC;IAED;;OAEG;IACH,eAiCC;IAID;;;OAGG;IACH,oBAgBC;IAED;;;OAGG;IACH,mBAqBC;CACJ;yBAlcwB,oBAAoB"}
|