@ifc-lite/clash 1.1.4 → 1.3.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/dist/analysis.d.ts +43 -0
- package/dist/analysis.d.ts.map +1 -0
- package/dist/analysis.js +62 -0
- package/dist/analysis.js.map +1 -0
- package/dist/contact/aabb.d.ts +20 -0
- package/dist/contact/aabb.d.ts.map +1 -0
- package/dist/contact/aabb.js +88 -0
- package/dist/contact/aabb.js.map +1 -0
- package/dist/contact/bvh.d.ts +39 -0
- package/dist/contact/bvh.d.ts.map +1 -0
- package/dist/contact/bvh.js +173 -0
- package/dist/contact/bvh.js.map +1 -0
- package/dist/contact/index.d.ts +31 -0
- package/dist/contact/index.d.ts.map +1 -0
- package/dist/contact/index.js +33 -0
- package/dist/contact/index.js.map +1 -0
- package/dist/contact/mesh-bvh.d.ts +21 -0
- package/dist/contact/mesh-bvh.d.ts.map +1 -0
- package/dist/contact/mesh-bvh.js +96 -0
- package/dist/contact/mesh-bvh.js.map +1 -0
- package/dist/contact/narrow-phase.d.ts +37 -0
- package/dist/contact/narrow-phase.d.ts.map +1 -0
- package/dist/contact/narrow-phase.js +49 -0
- package/dist/contact/narrow-phase.js.map +1 -0
- package/dist/contact/plane.d.ts +38 -0
- package/dist/contact/plane.d.ts.map +1 -0
- package/dist/contact/plane.js +83 -0
- package/dist/contact/plane.js.map +1 -0
- package/dist/contact/polygon-clip.d.ts +27 -0
- package/dist/contact/polygon-clip.d.ts.map +1 -0
- package/dist/contact/polygon-clip.js +162 -0
- package/dist/contact/polygon-clip.js.map +1 -0
- package/dist/contact/shared-faces.d.ts +61 -0
- package/dist/contact/shared-faces.d.ts.map +1 -0
- package/dist/contact/shared-faces.js +251 -0
- package/dist/contact/shared-faces.js.map +1 -0
- package/dist/contact/tri-tri.d.ts +34 -0
- package/dist/contact/tri-tri.d.ts.map +1 -0
- package/dist/contact/tri-tri.js +195 -0
- package/dist/contact/tri-tri.js.map +1 -0
- package/dist/contact/triangle.d.ts +22 -0
- package/dist/contact/triangle.d.ts.map +1 -0
- package/dist/contact/triangle.js +60 -0
- package/dist/contact/triangle.js.map +1 -0
- package/dist/contact/types.d.ts +33 -0
- package/dist/contact/types.d.ts.map +1 -0
- package/dist/contact/types.js +5 -0
- package/dist/contact/types.js.map +1 -0
- package/dist/contact/vec3.d.ts +19 -0
- package/dist/contact/vec3.d.ts.map +1 -0
- package/dist/contact/vec3.js +50 -0
- package/dist/contact/vec3.js.map +1 -0
- package/dist/duplicates.d.ts +26 -0
- package/dist/duplicates.d.ts.map +1 -0
- package/dist/duplicates.js +178 -0
- package/dist/duplicates.js.map +1 -0
- package/dist/engine-ts/narrow.d.ts.map +1 -1
- package/dist/engine-ts/narrow.js +102 -6
- package/dist/engine-ts/narrow.js.map +1 -1
- package/dist/engine-ts/tri-mesh.d.ts +10 -0
- package/dist/engine-ts/tri-mesh.d.ts.map +1 -1
- package/dist/engine-ts/tri-mesh.js +24 -0
- package/dist/engine-ts/tri-mesh.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +9 -5
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers for reading and ordering a clash result the way a reviewer
|
|
3
|
+
* thinks about it: how deep the overlap is, whether a "clash" is really just a
|
|
4
|
+
* face/edge contact, and which conflicts to look at first.
|
|
5
|
+
*
|
|
6
|
+
* Severity itself is a property of the *element-type pair* (see
|
|
7
|
+
* {@link inferClashSeverity}), NOT of the overlap geometry — so a deep pipe-vs-
|
|
8
|
+
* beam interpenetration and a shallow one share a severity. These helpers add
|
|
9
|
+
* the geometric dimension (depth) so the two can be combined when prioritising.
|
|
10
|
+
*/
|
|
11
|
+
import type { Clash, ClashSeverity } from './types.js';
|
|
12
|
+
/** Severity ordering, most-severe first (lower rank = more severe). */
|
|
13
|
+
export declare const SEVERITY_RANK: Record<ClashSeverity, number>;
|
|
14
|
+
/**
|
|
15
|
+
* Overlap (penetration) depth of a clash in metres, always `>= 0`.
|
|
16
|
+
*
|
|
17
|
+
* A `hard` clash carries a *signed* `distance` (`< 0` = interpenetration), so
|
|
18
|
+
* its depth is `-distance`. `clearance`/`touch` clashes are separated (no
|
|
19
|
+
* penetration) and report depth `0`. This is the right key for "sort by how
|
|
20
|
+
* badly things overlap" (#1274).
|
|
21
|
+
*/
|
|
22
|
+
export declare function penetrationDepth(c: Clash): number;
|
|
23
|
+
/** Default band (m) under which a `hard` clash is really a face/edge *contact*
|
|
24
|
+
* rather than a genuine interpenetration — see {@link isTouching}. */
|
|
25
|
+
export declare const TOUCHING_EPSILON = 0.0001;
|
|
26
|
+
/**
|
|
27
|
+
* Whether a clash is effectively a zero-distance *contact* rather than a real
|
|
28
|
+
* overlap (#1273). True for `touch`-status clashes and for `hard` clashes whose
|
|
29
|
+
* penetration is within `eps` — typically coincident faces (a wall meeting a
|
|
30
|
+
* slab, a column sitting on a footing) reported with a ~0 m depth, which users
|
|
31
|
+
* reasonably distrust when they appear in the clash list.
|
|
32
|
+
*/
|
|
33
|
+
export declare function isTouching(c: Clash, eps?: number): boolean;
|
|
34
|
+
export type ClashSortBy = 'severity' | 'depth' | 'distance';
|
|
35
|
+
/**
|
|
36
|
+
* Return a NEW array of clashes ordered by the chosen key. Ties fall back to the
|
|
37
|
+
* stable clash id so the order is deterministic across runs.
|
|
38
|
+
* - `severity`: most severe first, then deepest overlap (the panel default).
|
|
39
|
+
* - `depth`: deepest interpenetration first (#1274 — prioritise real problems).
|
|
40
|
+
* - `distance`: smallest signed distance first (deepest penetration → widest gap).
|
|
41
|
+
*/
|
|
42
|
+
export declare function sortClashes(clashes: readonly Clash[], by: ClashSortBy): Clash[];
|
|
43
|
+
//# sourceMappingURL=analysis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analysis.d.ts","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEvD,uEAAuE;AACvE,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAKvD,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAEjD;AAED;uEACuE;AACvE,eAAO,MAAM,gBAAgB,SAAO,CAAC;AAErC;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,GAAE,MAAyB,GAAG,OAAO,CAE5E;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAM5D;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,KAAK,EAAE,EAAE,EAAE,EAAE,WAAW,GAAG,KAAK,EAAE,CAmB/E"}
|
package/dist/analysis.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/** Severity ordering, most-severe first (lower rank = more severe). */
|
|
5
|
+
export const SEVERITY_RANK = {
|
|
6
|
+
critical: 0,
|
|
7
|
+
major: 1,
|
|
8
|
+
minor: 2,
|
|
9
|
+
info: 3,
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Overlap (penetration) depth of a clash in metres, always `>= 0`.
|
|
13
|
+
*
|
|
14
|
+
* A `hard` clash carries a *signed* `distance` (`< 0` = interpenetration), so
|
|
15
|
+
* its depth is `-distance`. `clearance`/`touch` clashes are separated (no
|
|
16
|
+
* penetration) and report depth `0`. This is the right key for "sort by how
|
|
17
|
+
* badly things overlap" (#1274).
|
|
18
|
+
*/
|
|
19
|
+
export function penetrationDepth(c) {
|
|
20
|
+
return c.distance < 0 ? -c.distance : 0;
|
|
21
|
+
}
|
|
22
|
+
/** Default band (m) under which a `hard` clash is really a face/edge *contact*
|
|
23
|
+
* rather than a genuine interpenetration — see {@link isTouching}. */
|
|
24
|
+
export const TOUCHING_EPSILON = 1e-4;
|
|
25
|
+
/**
|
|
26
|
+
* Whether a clash is effectively a zero-distance *contact* rather than a real
|
|
27
|
+
* overlap (#1273). True for `touch`-status clashes and for `hard` clashes whose
|
|
28
|
+
* penetration is within `eps` — typically coincident faces (a wall meeting a
|
|
29
|
+
* slab, a column sitting on a footing) reported with a ~0 m depth, which users
|
|
30
|
+
* reasonably distrust when they appear in the clash list.
|
|
31
|
+
*/
|
|
32
|
+
export function isTouching(c, eps = TOUCHING_EPSILON) {
|
|
33
|
+
return c.status === 'touch' || (c.status === 'hard' && penetrationDepth(c) <= eps);
|
|
34
|
+
}
|
|
35
|
+
function cmpId(a, b) {
|
|
36
|
+
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Return a NEW array of clashes ordered by the chosen key. Ties fall back to the
|
|
40
|
+
* stable clash id so the order is deterministic across runs.
|
|
41
|
+
* - `severity`: most severe first, then deepest overlap (the panel default).
|
|
42
|
+
* - `depth`: deepest interpenetration first (#1274 — prioritise real problems).
|
|
43
|
+
* - `distance`: smallest signed distance first (deepest penetration → widest gap).
|
|
44
|
+
*/
|
|
45
|
+
export function sortClashes(clashes, by) {
|
|
46
|
+
const out = clashes.slice();
|
|
47
|
+
switch (by) {
|
|
48
|
+
case 'severity':
|
|
49
|
+
out.sort((a, b) => SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity] ||
|
|
50
|
+
penetrationDepth(b) - penetrationDepth(a) ||
|
|
51
|
+
cmpId(a, b));
|
|
52
|
+
break;
|
|
53
|
+
case 'depth':
|
|
54
|
+
out.sort((a, b) => penetrationDepth(b) - penetrationDepth(a) || cmpId(a, b));
|
|
55
|
+
break;
|
|
56
|
+
case 'distance':
|
|
57
|
+
out.sort((a, b) => a.distance - b.distance || cmpId(a, b));
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=analysis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analysis.js","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAe/D,uEAAuE;AACvE,MAAM,CAAC,MAAM,aAAa,GAAkC;IAC1D,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;CACR,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAQ;IACvC,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED;uEACuE;AACvE,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAErC;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,CAAQ,EAAE,MAAc,gBAAgB;IACjE,OAAO,CAAC,CAAC,MAAM,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;AACrF,CAAC;AAID,SAAS,KAAK,CAAC,CAAQ,EAAE,CAAQ;IAC/B,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,OAAyB,EAAE,EAAe;IACpE,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAC5B,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,UAAU;YACb,GAAG,CAAC,IAAI,CACN,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC;gBACrD,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC;gBACzC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CACd,CAAC;YACF,MAAM;QACR,KAAK,OAAO;YACV,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7E,MAAM;QACR,KAAK,UAAU;YACb,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC3D,MAAM;IACV,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AABB, Vec3 } from "./types.js";
|
|
2
|
+
/** An empty AABB (inverted bounds); union with any AABB yields that AABB. */
|
|
3
|
+
export declare const EMPTY_AABB: AABB;
|
|
4
|
+
/** True when two AABBs overlap (closed intervals). */
|
|
5
|
+
export declare function intersects(a: AABB, b: AABB): boolean;
|
|
6
|
+
/** Smallest AABB containing both inputs. */
|
|
7
|
+
export declare function unionAabb(a: AABB, b: AABB): AABB;
|
|
8
|
+
/** Geometric centre of an AABB. */
|
|
9
|
+
export declare function center(a: AABB): Vec3;
|
|
10
|
+
/** Size (extent) of an AABB along each axis. */
|
|
11
|
+
export declare function size(a: AABB): Vec3;
|
|
12
|
+
/** True when the AABB contains the point (closed intervals). */
|
|
13
|
+
export declare function contains(a: AABB, p: Vec3): boolean;
|
|
14
|
+
/** Inflate the AABB by `eps` on every face. Negative values deflate. */
|
|
15
|
+
export declare function inflate(a: AABB, eps: number): AABB;
|
|
16
|
+
/** Build an AABB from a flat positions buffer (xyz, xyz, …). */
|
|
17
|
+
export declare function aabbFromPositions(positions: ArrayLike<number>): AABB;
|
|
18
|
+
/** Longest axis of the AABB: 0=x, 1=y, 2=z. */
|
|
19
|
+
export declare function longestAxis(a: AABB): 0 | 1 | 2;
|
|
20
|
+
//# sourceMappingURL=aabb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aabb.d.ts","sourceRoot":"","sources":["../../src/contact/aabb.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAE7C,6EAA6E;AAC7E,eAAO,MAAM,UAAU,EAAE,IAGxB,CAAC;AAEF,sDAAsD;AACtD,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CASpD;AAED,4CAA4C;AAC5C,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,IAAI,CAKhD;AAED,mCAAmC;AACnC,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,CAEpC;AAED,gDAAgD;AAChD,wBAAgB,IAAI,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,CAElC;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CASlD;AAED,wEAAwE;AACxE,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAKlD;AAED,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAsBpE;AAED,+CAA+C;AAC/C,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAK9C"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/** An empty AABB (inverted bounds); union with any AABB yields that AABB. */
|
|
5
|
+
export const EMPTY_AABB = {
|
|
6
|
+
min: [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
|
|
7
|
+
max: [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
|
|
8
|
+
};
|
|
9
|
+
/** True when two AABBs overlap (closed intervals). */
|
|
10
|
+
export function intersects(a, b) {
|
|
11
|
+
return (a.min[0] <= b.max[0] &&
|
|
12
|
+
a.max[0] >= b.min[0] &&
|
|
13
|
+
a.min[1] <= b.max[1] &&
|
|
14
|
+
a.max[1] >= b.min[1] &&
|
|
15
|
+
a.min[2] <= b.max[2] &&
|
|
16
|
+
a.max[2] >= b.min[2]);
|
|
17
|
+
}
|
|
18
|
+
/** Smallest AABB containing both inputs. */
|
|
19
|
+
export function unionAabb(a, b) {
|
|
20
|
+
return {
|
|
21
|
+
min: [Math.min(a.min[0], b.min[0]), Math.min(a.min[1], b.min[1]), Math.min(a.min[2], b.min[2])],
|
|
22
|
+
max: [Math.max(a.max[0], b.max[0]), Math.max(a.max[1], b.max[1]), Math.max(a.max[2], b.max[2])],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Geometric centre of an AABB. */
|
|
26
|
+
export function center(a) {
|
|
27
|
+
return [(a.min[0] + a.max[0]) / 2, (a.min[1] + a.max[1]) / 2, (a.min[2] + a.max[2]) / 2];
|
|
28
|
+
}
|
|
29
|
+
/** Size (extent) of an AABB along each axis. */
|
|
30
|
+
export function size(a) {
|
|
31
|
+
return [a.max[0] - a.min[0], a.max[1] - a.min[1], a.max[2] - a.min[2]];
|
|
32
|
+
}
|
|
33
|
+
/** True when the AABB contains the point (closed intervals). */
|
|
34
|
+
export function contains(a, p) {
|
|
35
|
+
return (p[0] >= a.min[0] &&
|
|
36
|
+
p[0] <= a.max[0] &&
|
|
37
|
+
p[1] >= a.min[1] &&
|
|
38
|
+
p[1] <= a.max[1] &&
|
|
39
|
+
p[2] >= a.min[2] &&
|
|
40
|
+
p[2] <= a.max[2]);
|
|
41
|
+
}
|
|
42
|
+
/** Inflate the AABB by `eps` on every face. Negative values deflate. */
|
|
43
|
+
export function inflate(a, eps) {
|
|
44
|
+
return {
|
|
45
|
+
min: [a.min[0] - eps, a.min[1] - eps, a.min[2] - eps],
|
|
46
|
+
max: [a.max[0] + eps, a.max[1] + eps, a.max[2] + eps],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** Build an AABB from a flat positions buffer (xyz, xyz, …). */
|
|
50
|
+
export function aabbFromPositions(positions) {
|
|
51
|
+
if (positions.length === 0 || positions.length % 3 !== 0) {
|
|
52
|
+
return EMPTY_AABB;
|
|
53
|
+
}
|
|
54
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
55
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
56
|
+
let minZ = Number.POSITIVE_INFINITY;
|
|
57
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
58
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
59
|
+
let maxZ = Number.NEGATIVE_INFINITY;
|
|
60
|
+
for (let i = 0; i < positions.length; i += 3) {
|
|
61
|
+
const x = positions[i];
|
|
62
|
+
const y = positions[i + 1];
|
|
63
|
+
const z = positions[i + 2];
|
|
64
|
+
if (x < minX)
|
|
65
|
+
minX = x;
|
|
66
|
+
if (y < minY)
|
|
67
|
+
minY = y;
|
|
68
|
+
if (z < minZ)
|
|
69
|
+
minZ = z;
|
|
70
|
+
if (x > maxX)
|
|
71
|
+
maxX = x;
|
|
72
|
+
if (y > maxY)
|
|
73
|
+
maxY = y;
|
|
74
|
+
if (z > maxZ)
|
|
75
|
+
maxZ = z;
|
|
76
|
+
}
|
|
77
|
+
return { min: [minX, minY, minZ], max: [maxX, maxY, maxZ] };
|
|
78
|
+
}
|
|
79
|
+
/** Longest axis of the AABB: 0=x, 1=y, 2=z. */
|
|
80
|
+
export function longestAxis(a) {
|
|
81
|
+
const [dx, dy, dz] = size(a);
|
|
82
|
+
if (dx >= dy && dx >= dz)
|
|
83
|
+
return 0;
|
|
84
|
+
if (dy >= dz)
|
|
85
|
+
return 1;
|
|
86
|
+
return 2;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=aabb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aabb.js","sourceRoot":"","sources":["../../src/contact/aabb.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAI/D,6EAA6E;AAC7E,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,GAAG,EAAE,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,CAAC;IACnF,GAAG,EAAE,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,CAAC;CACpF,CAAC;AAEF,sDAAsD;AACtD,MAAM,UAAU,UAAU,CAAC,CAAO,EAAE,CAAO;IACzC,OAAO,CACL,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CACrB,CAAC;AACJ,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,SAAS,CAAC,CAAO,EAAE,CAAO;IACxC,OAAO;QACL,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/F,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;KAChG,CAAC;AACJ,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,MAAM,CAAC,CAAO;IAC5B,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3F,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,IAAI,CAAC,CAAO;IAC1B,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,QAAQ,CAAC,CAAO,EAAE,CAAO;IACvC,OAAO,CACL,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CACjB,CAAC;AACJ,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,OAAO,CAAC,CAAO,EAAE,GAAW;IAC1C,OAAO;QACL,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;QACrD,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;KACtD,CAAC;AACJ,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,iBAAiB,CAAC,SAA4B;IAC5D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACpC,IAAI,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACpC,IAAI,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACpC,IAAI,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACpC,IAAI,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACpC,IAAI,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAW,CAAC;QACjC,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAW,CAAC;QACrC,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAW,CAAC;QACrC,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,WAAW,CAAC,CAAO;IACjC,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7B,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;QAAE,OAAO,CAAC,CAAC;IACnC,IAAI,EAAE,IAAI,EAAE;QAAE,OAAO,CAAC,CAAC;IACvB,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AABB, MeshBounds } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Median-split BVH with two query primitives:
|
|
4
|
+
* - queryAABB(q): items overlapping `q`
|
|
5
|
+
* - queryPairs(eps?): all unordered pairs whose (optionally inflated) AABBs overlap
|
|
6
|
+
*
|
|
7
|
+
* Build cost: O(n log n). queryPairs descends both subtrees simultaneously,
|
|
8
|
+
* pruning on AABB intersection — true O(n log n) self-pair enumeration rather
|
|
9
|
+
* than O(n^2) per-element queries.
|
|
10
|
+
*/
|
|
11
|
+
export interface BvhNode {
|
|
12
|
+
readonly bounds: AABB;
|
|
13
|
+
readonly left?: BvhNode;
|
|
14
|
+
readonly right?: BvhNode;
|
|
15
|
+
/** Indices into the original `items` array; present only on leaves. */
|
|
16
|
+
readonly items?: readonly number[];
|
|
17
|
+
}
|
|
18
|
+
export interface BvhOptions {
|
|
19
|
+
/** Maximum items per leaf; lower = deeper tree, higher = faster build. */
|
|
20
|
+
readonly leafSize?: number;
|
|
21
|
+
}
|
|
22
|
+
export declare class Bvh {
|
|
23
|
+
readonly root: BvhNode | null;
|
|
24
|
+
readonly items: readonly MeshBounds[];
|
|
25
|
+
private constructor();
|
|
26
|
+
/** Build a BVH from a list of bounded items. Median-split along the longest axis. */
|
|
27
|
+
static build(items: readonly MeshBounds[], opts?: BvhOptions): Bvh;
|
|
28
|
+
/** Return ids of items whose AABB intersects `q`. Order is depth-first, stable. */
|
|
29
|
+
queryAABB(q: AABB): string[];
|
|
30
|
+
/**
|
|
31
|
+
* Return all unordered pairs `(idA, idB)` with idA < idB (lex) whose AABBs
|
|
32
|
+
* (optionally inflated by `epsilon` on all sides) overlap. Pair order is
|
|
33
|
+
* deterministic given input order.
|
|
34
|
+
*/
|
|
35
|
+
queryPairs(epsilon?: number): IdPair[];
|
|
36
|
+
}
|
|
37
|
+
type IdPair = readonly [string, string];
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=bvh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bvh.d.ts","sourceRoot":"","sources":["../../src/contact/bvh.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;;;;;GAQG;AAEH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,uEAAuE;IACvE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,qBAAa,GAAG;IACd,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IAEtC,OAAO;IAKP,qFAAqF;IACrF,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,EAAE,IAAI,GAAE,UAAe,GAAG,GAAG;IAQtE,mFAAmF;IACnF,SAAS,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,EAAE;IAO5B;;;;OAIG;IACH,UAAU,CAAC,OAAO,SAAI,GAAG,MAAM,EAAE;CAgBlC;AAED,KAAK,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { EMPTY_AABB, center, intersects, longestAxis, unionAabb } from "./aabb.js";
|
|
5
|
+
export class Bvh {
|
|
6
|
+
root;
|
|
7
|
+
items;
|
|
8
|
+
constructor(root, items) {
|
|
9
|
+
this.root = root;
|
|
10
|
+
this.items = items;
|
|
11
|
+
}
|
|
12
|
+
/** Build a BVH from a list of bounded items. Median-split along the longest axis. */
|
|
13
|
+
static build(items, opts = {}) {
|
|
14
|
+
if (items.length === 0)
|
|
15
|
+
return new Bvh(null, items);
|
|
16
|
+
const leafSize = Math.max(1, opts.leafSize ?? 4);
|
|
17
|
+
const indices = items.map((_, i) => i);
|
|
18
|
+
const root = buildNode(items, indices, leafSize);
|
|
19
|
+
return new Bvh(root, items);
|
|
20
|
+
}
|
|
21
|
+
/** Return ids of items whose AABB intersects `q`. Order is depth-first, stable. */
|
|
22
|
+
queryAABB(q) {
|
|
23
|
+
if (!this.root)
|
|
24
|
+
return [];
|
|
25
|
+
const out = [];
|
|
26
|
+
queryAabbNode(this.root, q, this.items, out);
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Return all unordered pairs `(idA, idB)` with idA < idB (lex) whose AABBs
|
|
31
|
+
* (optionally inflated by `epsilon` on all sides) overlap. Pair order is
|
|
32
|
+
* deterministic given input order.
|
|
33
|
+
*/
|
|
34
|
+
queryPairs(epsilon = 0) {
|
|
35
|
+
if (!this.root)
|
|
36
|
+
return [];
|
|
37
|
+
const out = [];
|
|
38
|
+
selfPair(this.root, this.items, epsilon, out);
|
|
39
|
+
// Stable canonicalisation — the emission loops already guarantee no dupes,
|
|
40
|
+
// but we sort both within each pair and across the pair array so the
|
|
41
|
+
// output is insensitive to tree construction order (just input order).
|
|
42
|
+
for (let i = 0; i < out.length; i++) {
|
|
43
|
+
const p = out[i];
|
|
44
|
+
if (p[0] > p[1])
|
|
45
|
+
out[i] = [p[1], p[0]];
|
|
46
|
+
}
|
|
47
|
+
out.sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0);
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function buildNode(items, indices, leafSize) {
|
|
52
|
+
if (indices.length === 0) {
|
|
53
|
+
return { bounds: EMPTY_AABB, items: [] };
|
|
54
|
+
}
|
|
55
|
+
const bounds = indices.reduce((acc, idx) => unionAabb(acc, items[idx].aabb), EMPTY_AABB);
|
|
56
|
+
if (indices.length <= leafSize) {
|
|
57
|
+
return { bounds, items: indices.slice() };
|
|
58
|
+
}
|
|
59
|
+
const axis = longestAxis(bounds);
|
|
60
|
+
// Sort indices by centre along longest axis, then split at median.
|
|
61
|
+
indices.sort((ia, ib) => {
|
|
62
|
+
const ca = center(items[ia].aabb)[axis];
|
|
63
|
+
const cb = center(items[ib].aabb)[axis];
|
|
64
|
+
return ca - cb;
|
|
65
|
+
});
|
|
66
|
+
const mid = indices.length >> 1;
|
|
67
|
+
const leftIdx = indices.slice(0, mid);
|
|
68
|
+
const rightIdx = indices.slice(mid);
|
|
69
|
+
return {
|
|
70
|
+
bounds,
|
|
71
|
+
left: buildNode(items, leftIdx, leafSize),
|
|
72
|
+
right: buildNode(items, rightIdx, leafSize),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function queryAabbNode(node, q, items, out) {
|
|
76
|
+
if (!intersects(node.bounds, q))
|
|
77
|
+
return;
|
|
78
|
+
if (node.items) {
|
|
79
|
+
for (const i of node.items) {
|
|
80
|
+
const it = items[i];
|
|
81
|
+
if (intersects(it.aabb, q))
|
|
82
|
+
out.push(it.id);
|
|
83
|
+
}
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (node.left)
|
|
87
|
+
queryAabbNode(node.left, q, items, out);
|
|
88
|
+
if (node.right)
|
|
89
|
+
queryAabbNode(node.right, q, items, out);
|
|
90
|
+
}
|
|
91
|
+
/** Dual-traversal self-pair emission. */
|
|
92
|
+
function selfPair(node, items, eps, out) {
|
|
93
|
+
if (node.items) {
|
|
94
|
+
emitLeafPairs(node.items, items, eps, out);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (node.left)
|
|
98
|
+
selfPair(node.left, items, eps, out);
|
|
99
|
+
if (node.right)
|
|
100
|
+
selfPair(node.right, items, eps, out);
|
|
101
|
+
if (node.left && node.right)
|
|
102
|
+
crossPair(node.left, node.right, items, eps, out);
|
|
103
|
+
}
|
|
104
|
+
function crossPair(a, b, items, eps, out) {
|
|
105
|
+
if (!boundsOverlapInflated(a.bounds, b.bounds, eps))
|
|
106
|
+
return;
|
|
107
|
+
if (a.items && b.items) {
|
|
108
|
+
emitLeafCross(a.items, b.items, items, eps, out);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// Descend the larger side first to keep recursion depth bounded.
|
|
112
|
+
if (a.items) {
|
|
113
|
+
if (b.left)
|
|
114
|
+
crossPair(a, b.left, items, eps, out);
|
|
115
|
+
if (b.right)
|
|
116
|
+
crossPair(a, b.right, items, eps, out);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (b.items) {
|
|
120
|
+
if (a.left)
|
|
121
|
+
crossPair(a.left, b, items, eps, out);
|
|
122
|
+
if (a.right)
|
|
123
|
+
crossPair(a.right, b, items, eps, out);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (a.left) {
|
|
127
|
+
if (b.left)
|
|
128
|
+
crossPair(a.left, b.left, items, eps, out);
|
|
129
|
+
if (b.right)
|
|
130
|
+
crossPair(a.left, b.right, items, eps, out);
|
|
131
|
+
}
|
|
132
|
+
if (a.right) {
|
|
133
|
+
if (b.left)
|
|
134
|
+
crossPair(a.right, b.left, items, eps, out);
|
|
135
|
+
if (b.right)
|
|
136
|
+
crossPair(a.right, b.right, items, eps, out);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function emitLeafPairs(leaf, items, eps, out) {
|
|
140
|
+
for (let i = 0; i < leaf.length; i++) {
|
|
141
|
+
const ia = leaf[i];
|
|
142
|
+
const a = items[ia];
|
|
143
|
+
for (let j = i + 1; j < leaf.length; j++) {
|
|
144
|
+
const ib = leaf[j];
|
|
145
|
+
const b = items[ib];
|
|
146
|
+
if (boundsOverlapInflated(a.aabb, b.aabb, eps))
|
|
147
|
+
out.push([a.id, b.id]);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function emitLeafCross(aLeaf, bLeaf, items, eps, out) {
|
|
152
|
+
for (const ia of aLeaf) {
|
|
153
|
+
const a = items[ia];
|
|
154
|
+
for (const ib of bLeaf) {
|
|
155
|
+
const b = items[ib];
|
|
156
|
+
if (a.id === b.id)
|
|
157
|
+
continue;
|
|
158
|
+
if (boundsOverlapInflated(a.aabb, b.aabb, eps))
|
|
159
|
+
out.push([a.id, b.id]);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function boundsOverlapInflated(a, b, eps) {
|
|
164
|
+
if (eps === 0)
|
|
165
|
+
return intersects(a, b);
|
|
166
|
+
return (a.min[0] - eps <= b.max[0] + eps &&
|
|
167
|
+
a.max[0] + eps >= b.min[0] - eps &&
|
|
168
|
+
a.min[1] - eps <= b.max[1] + eps &&
|
|
169
|
+
a.max[1] + eps >= b.min[1] - eps &&
|
|
170
|
+
a.min[2] - eps <= b.max[2] + eps &&
|
|
171
|
+
a.max[2] + eps >= b.min[2] - eps);
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=bvh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bvh.js","sourceRoot":"","sources":["../../src/contact/bvh.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contact-interface geometry for a single pair of meshes.
|
|
3
|
+
*
|
|
4
|
+
* Where the AABB clash box is a crude proxy, this returns the REAL contact
|
|
5
|
+
* patch: the shared-face polygon for coplanar/flush overlaps (surface), the
|
|
6
|
+
* intersection line for crossings (line), or a point — classified by area and
|
|
7
|
+
* length. It is built from a Moller triangle-triangle test (which reports the
|
|
8
|
+
* intersection segment for crossings and the coplanar case) followed by
|
|
9
|
+
* shared-face clustering: coplanar triangle pairs are Sutherland-Hodgman clipped
|
|
10
|
+
* on their common plane and unioned into a boundary polygon; cross pairs union
|
|
11
|
+
* their segments along the intersection line.
|
|
12
|
+
*
|
|
13
|
+
* Intended for on-demand use on the FOCUSED clash (one pair), not the bulk
|
|
14
|
+
* detection sweep — clustering every clash would be far too expensive.
|
|
15
|
+
*/
|
|
16
|
+
import { narrowPhase, type NarrowPhaseOptions } from './narrow-phase.js';
|
|
17
|
+
import { clusterSharedFaces, type SharedFaceCluster, type SharedFaceOptions } from './shared-faces.js';
|
|
18
|
+
import type { Mesh } from './types.js';
|
|
19
|
+
export type { Mesh, Vec3, AABB } from './types.js';
|
|
20
|
+
export type { SharedFaceCluster, SharedFaceOptions } from './shared-faces.js';
|
|
21
|
+
export type { TrianglePair, NarrowPhaseOptions } from './narrow-phase.js';
|
|
22
|
+
export { narrowPhase, clusterSharedFaces };
|
|
23
|
+
export interface ContactOptions extends NarrowPhaseOptions, SharedFaceOptions {
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Compute the contact interface(s) between two world-space meshes: the real
|
|
27
|
+
* shared-face polygon (surface), intersection line, or point — not an AABB.
|
|
28
|
+
* Returns an empty array when the triangles neither cross nor share a plane.
|
|
29
|
+
*/
|
|
30
|
+
export declare function contactClusters(a: Mesh, b: Mesh, opts?: ContactOptions): SharedFaceCluster[];
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contact/index.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EACL,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,IAAI,EAAQ,MAAM,YAAY,CAAC;AAE7C,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACnD,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;AAE3C,MAAM,WAAW,cAAe,SAAQ,kBAAkB,EAAE,iBAAiB;CAAG;AAEhF;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,GAAE,cAAmB,GAAG,iBAAiB,EAAE,CAIhG"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* Contact-interface geometry for a single pair of meshes.
|
|
6
|
+
*
|
|
7
|
+
* Where the AABB clash box is a crude proxy, this returns the REAL contact
|
|
8
|
+
* patch: the shared-face polygon for coplanar/flush overlaps (surface), the
|
|
9
|
+
* intersection line for crossings (line), or a point — classified by area and
|
|
10
|
+
* length. It is built from a Moller triangle-triangle test (which reports the
|
|
11
|
+
* intersection segment for crossings and the coplanar case) followed by
|
|
12
|
+
* shared-face clustering: coplanar triangle pairs are Sutherland-Hodgman clipped
|
|
13
|
+
* on their common plane and unioned into a boundary polygon; cross pairs union
|
|
14
|
+
* their segments along the intersection line.
|
|
15
|
+
*
|
|
16
|
+
* Intended for on-demand use on the FOCUSED clash (one pair), not the bulk
|
|
17
|
+
* detection sweep — clustering every clash would be far too expensive.
|
|
18
|
+
*/
|
|
19
|
+
import { narrowPhase } from './narrow-phase.js';
|
|
20
|
+
import { clusterSharedFaces, } from './shared-faces.js';
|
|
21
|
+
export { narrowPhase, clusterSharedFaces };
|
|
22
|
+
/**
|
|
23
|
+
* Compute the contact interface(s) between two world-space meshes: the real
|
|
24
|
+
* shared-face polygon (surface), intersection line, or point — not an AABB.
|
|
25
|
+
* Returns an empty array when the triangles neither cross nor share a plane.
|
|
26
|
+
*/
|
|
27
|
+
export function contactClusters(a, b, opts = {}) {
|
|
28
|
+
const pairs = narrowPhase(a, b, opts);
|
|
29
|
+
if (pairs.length === 0)
|
|
30
|
+
return [];
|
|
31
|
+
return clusterSharedFaces(pairs, opts);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/contact/index.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,WAAW,EAA2B,MAAM,mBAAmB,CAAC;AACzE,OAAO,EACL,kBAAkB,GAGnB,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;AAI3C;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,CAAO,EAAE,CAAO,EAAE,OAAuB,EAAE;IACzE,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,OAAO,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Bvh } from "./bvh.js";
|
|
2
|
+
import type { Mesh } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* A BVH over a mesh's triangles. Item ids are stringified triangle indices.
|
|
5
|
+
* Cross-traversal between two MeshBvh yields candidate triangle-pair indices.
|
|
6
|
+
*/
|
|
7
|
+
export interface MeshBvh {
|
|
8
|
+
readonly mesh: Mesh;
|
|
9
|
+
readonly bvh: Bvh;
|
|
10
|
+
}
|
|
11
|
+
export declare function buildMeshBvh(mesh: Mesh, leafSize?: number): MeshBvh;
|
|
12
|
+
/**
|
|
13
|
+
* Cross-query two MeshBvh instances. Returns candidate triangle-index pairs
|
|
14
|
+
* `(iA, iB)` where iA is in `a.mesh` and iB is in `b.mesh`, whose AABBs
|
|
15
|
+
* (inflated by `epsilon`) overlap.
|
|
16
|
+
*
|
|
17
|
+
* Pairs are not canonicalised — both meshes are distinct inputs, so order
|
|
18
|
+
* is preserved (A first, B second).
|
|
19
|
+
*/
|
|
20
|
+
export declare function queryMeshCross(a: MeshBvh, b: MeshBvh, epsilon?: number): Array<readonly [number, number]>;
|
|
21
|
+
//# sourceMappingURL=mesh-bvh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mesh-bvh.d.ts","sourceRoot":"","sources":["../../src/contact/mesh-bvh.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,YAAY,CAAC;AAEnD;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;CACnB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,SAAI,GAAG,OAAO,CAO9D;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,OAAO,EACV,CAAC,EAAE,OAAO,EACV,OAAO,SAAI,GACV,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAelC"}
|