@ifc-lite/clash 1.2.0 → 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.
Files changed (56) hide show
  1. package/dist/contact/aabb.d.ts +20 -0
  2. package/dist/contact/aabb.d.ts.map +1 -0
  3. package/dist/contact/aabb.js +88 -0
  4. package/dist/contact/aabb.js.map +1 -0
  5. package/dist/contact/bvh.d.ts +39 -0
  6. package/dist/contact/bvh.d.ts.map +1 -0
  7. package/dist/contact/bvh.js +173 -0
  8. package/dist/contact/bvh.js.map +1 -0
  9. package/dist/contact/index.d.ts +31 -0
  10. package/dist/contact/index.d.ts.map +1 -0
  11. package/dist/contact/index.js +33 -0
  12. package/dist/contact/index.js.map +1 -0
  13. package/dist/contact/mesh-bvh.d.ts +21 -0
  14. package/dist/contact/mesh-bvh.d.ts.map +1 -0
  15. package/dist/contact/mesh-bvh.js +96 -0
  16. package/dist/contact/mesh-bvh.js.map +1 -0
  17. package/dist/contact/narrow-phase.d.ts +37 -0
  18. package/dist/contact/narrow-phase.d.ts.map +1 -0
  19. package/dist/contact/narrow-phase.js +49 -0
  20. package/dist/contact/narrow-phase.js.map +1 -0
  21. package/dist/contact/plane.d.ts +38 -0
  22. package/dist/contact/plane.d.ts.map +1 -0
  23. package/dist/contact/plane.js +83 -0
  24. package/dist/contact/plane.js.map +1 -0
  25. package/dist/contact/polygon-clip.d.ts +27 -0
  26. package/dist/contact/polygon-clip.d.ts.map +1 -0
  27. package/dist/contact/polygon-clip.js +162 -0
  28. package/dist/contact/polygon-clip.js.map +1 -0
  29. package/dist/contact/shared-faces.d.ts +61 -0
  30. package/dist/contact/shared-faces.d.ts.map +1 -0
  31. package/dist/contact/shared-faces.js +251 -0
  32. package/dist/contact/shared-faces.js.map +1 -0
  33. package/dist/contact/tri-tri.d.ts +34 -0
  34. package/dist/contact/tri-tri.d.ts.map +1 -0
  35. package/dist/contact/tri-tri.js +195 -0
  36. package/dist/contact/tri-tri.js.map +1 -0
  37. package/dist/contact/triangle.d.ts +22 -0
  38. package/dist/contact/triangle.d.ts.map +1 -0
  39. package/dist/contact/triangle.js +60 -0
  40. package/dist/contact/triangle.js.map +1 -0
  41. package/dist/contact/types.d.ts +33 -0
  42. package/dist/contact/types.d.ts.map +1 -0
  43. package/dist/contact/types.js +5 -0
  44. package/dist/contact/types.js.map +1 -0
  45. package/dist/contact/vec3.d.ts +19 -0
  46. package/dist/contact/vec3.d.ts.map +1 -0
  47. package/dist/contact/vec3.js +50 -0
  48. package/dist/contact/vec3.js.map +1 -0
  49. package/dist/engine-ts/narrow.d.ts.map +1 -1
  50. package/dist/engine-ts/narrow.js +102 -6
  51. package/dist/engine-ts/narrow.js.map +1 -1
  52. package/dist/engine-ts/tri-mesh.d.ts +10 -0
  53. package/dist/engine-ts/tri-mesh.d.ts.map +1 -1
  54. package/dist/engine-ts/tri-mesh.js +24 -0
  55. package/dist/engine-ts/tri-mesh.js.map +1 -1
  56. package/package.json +9 -5
@@ -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":"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"}
@@ -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"}
@@ -0,0 +1,96 @@
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 { Bvh } from "./bvh.js";
5
+ import { triangleAabb, triangleAt, triangleCount } from "./triangle.js";
6
+ export function buildMeshBvh(mesh, leafSize = 8) {
7
+ const n = triangleCount(mesh);
8
+ const items = new Array(n);
9
+ for (let i = 0; i < n; i++) {
10
+ items[i] = { id: String(i), aabb: triangleAabb(triangleAt(mesh, i)) };
11
+ }
12
+ return { mesh, bvh: Bvh.build(items, { leafSize }) };
13
+ }
14
+ /**
15
+ * Cross-query two MeshBvh instances. Returns candidate triangle-index pairs
16
+ * `(iA, iB)` where iA is in `a.mesh` and iB is in `b.mesh`, whose AABBs
17
+ * (inflated by `epsilon`) overlap.
18
+ *
19
+ * Pairs are not canonicalised — both meshes are distinct inputs, so order
20
+ * is preserved (A first, B second).
21
+ */
22
+ export function queryMeshCross(a, b, epsilon = 0) {
23
+ if (!a.bvh.root || !b.bvh.root)
24
+ return [];
25
+ const out = [];
26
+ crossNode(a.bvh, b.bvh, a.bvh.root, b.bvh.root, epsilon, out);
27
+ // Dedup — BVHs partition the triangle set, so no true duplicates, but
28
+ // belt-and-braces:
29
+ const seen = new Set();
30
+ const deduped = [];
31
+ for (const p of out) {
32
+ const key = `${p[0]}|${p[1]}`;
33
+ if (seen.has(key))
34
+ continue;
35
+ seen.add(key);
36
+ deduped.push(p);
37
+ }
38
+ return deduped;
39
+ }
40
+ function crossNode(aTree, bTree, aNode, bNode, eps, out) {
41
+ if (!boundsOverlap(aNode.bounds, bNode.bounds, eps))
42
+ return;
43
+ const aLeaf = aNode.items;
44
+ const bLeaf = bNode.items;
45
+ if (aLeaf && bLeaf) {
46
+ for (const ia of aLeaf) {
47
+ const aItem = aTree.items[ia];
48
+ if (!aItem)
49
+ continue;
50
+ for (const ib of bLeaf) {
51
+ const bItem = bTree.items[ib];
52
+ if (!bItem)
53
+ continue;
54
+ if (boundsOverlap(aItem.aabb, bItem.aabb, eps)) {
55
+ out.push([Number(aItem.id), Number(bItem.id)]);
56
+ }
57
+ }
58
+ }
59
+ return;
60
+ }
61
+ if (aLeaf) {
62
+ if (bNode.left)
63
+ crossNode(aTree, bTree, aNode, bNode.left, eps, out);
64
+ if (bNode.right)
65
+ crossNode(aTree, bTree, aNode, bNode.right, eps, out);
66
+ return;
67
+ }
68
+ if (bLeaf) {
69
+ if (aNode.left)
70
+ crossNode(aTree, bTree, aNode.left, bNode, eps, out);
71
+ if (aNode.right)
72
+ crossNode(aTree, bTree, aNode.right, bNode, eps, out);
73
+ return;
74
+ }
75
+ if (aNode.left) {
76
+ if (bNode.left)
77
+ crossNode(aTree, bTree, aNode.left, bNode.left, eps, out);
78
+ if (bNode.right)
79
+ crossNode(aTree, bTree, aNode.left, bNode.right, eps, out);
80
+ }
81
+ if (aNode.right) {
82
+ if (bNode.left)
83
+ crossNode(aTree, bTree, aNode.right, bNode.left, eps, out);
84
+ if (bNode.right)
85
+ crossNode(aTree, bTree, aNode.right, bNode.right, eps, out);
86
+ }
87
+ }
88
+ function boundsOverlap(a, b, eps) {
89
+ return (a.min[0] - eps <= b.max[0] + eps &&
90
+ a.max[0] + eps >= b.min[0] - eps &&
91
+ a.min[1] - eps <= b.max[1] + eps &&
92
+ a.max[1] + eps >= b.min[1] - eps &&
93
+ a.min[2] - eps <= b.max[2] + eps &&
94
+ a.max[2] + eps >= b.min[2] - eps);
95
+ }
96
+ //# sourceMappingURL=mesh-bvh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mesh-bvh.js","sourceRoot":"","sources":["../../src/contact/mesh-bvh.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { Triangle } from "./triangle.js";
2
+ import type { Mesh, Vec3 } from "./types.js";
3
+ export type TrianglePair = {
4
+ readonly triA: number;
5
+ readonly triB: number;
6
+ readonly a: Triangle;
7
+ readonly b: Triangle;
8
+ readonly kind: "coplanar";
9
+ } | {
10
+ readonly triA: number;
11
+ readonly triB: number;
12
+ readonly a: Triangle;
13
+ readonly b: Triangle;
14
+ readonly kind: "cross";
15
+ /** 3D endpoints of the intersection segment on the common line. */
16
+ readonly p0: Vec3;
17
+ readonly p1: Vec3;
18
+ };
19
+ export interface NarrowPhaseOptions {
20
+ /** AABB inflation (world units). Default 0.002 (2 mm). */
21
+ readonly epsilon?: number;
22
+ /** Plane-distance tolerance for coplanarity and Möller sign tests. */
23
+ readonly planeEps?: number;
24
+ /** BVH leaf size for per-mesh triangle BVHs. Default 8. */
25
+ readonly leafSize?: number;
26
+ }
27
+ /**
28
+ * For two meshes A and B, return every triangle pair whose triangles
29
+ * either strictly cross or are coplanar (and whose AABBs are within
30
+ * `epsilon` of each other).
31
+ *
32
+ * Coplanar pairs are emitted without further 2D-overlap testing —
33
+ * shared-face clustering (downstream) does that more robustly across
34
+ * a whole cluster of coplanar hits.
35
+ */
36
+ export declare function narrowPhase(a: Mesh, b: Mesh, opts?: NarrowPhaseOptions): TrianglePair[];
37
+ //# sourceMappingURL=narrow-phase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"narrow-phase.d.ts","sourceRoot":"","sources":["../../src/contact/narrow-phase.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,MAAM,YAAY,GACpB;IACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC;IACrB,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;CAC3B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC;IACrB,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;CACnB,CAAC;AAEN,MAAM,WAAW,kBAAkB;IACjC,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,GAAE,kBAAuB,GAAG,YAAY,EAAE,CAiC3F"}
@@ -0,0 +1,49 @@
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 { buildMeshBvh, queryMeshCross } from "./mesh-bvh.js";
5
+ import { triTriIntersect } from "./tri-tri.js";
6
+ import { triangleAt, triangleCount } from "./triangle.js";
7
+ /**
8
+ * For two meshes A and B, return every triangle pair whose triangles
9
+ * either strictly cross or are coplanar (and whose AABBs are within
10
+ * `epsilon` of each other).
11
+ *
12
+ * Coplanar pairs are emitted without further 2D-overlap testing —
13
+ * shared-face clustering (downstream) does that more robustly across
14
+ * a whole cluster of coplanar hits.
15
+ */
16
+ export function narrowPhase(a, b, opts = {}) {
17
+ const epsilon = opts.epsilon ?? 0.002;
18
+ const planeEps = opts.planeEps ?? 1e-6;
19
+ const leafSize = opts.leafSize ?? 8;
20
+ if (triangleCount(a) === 0 || triangleCount(b) === 0)
21
+ return [];
22
+ const bvhA = buildMeshBvh(a, leafSize);
23
+ const bvhB = buildMeshBvh(b, leafSize);
24
+ const candidates = queryMeshCross(bvhA, bvhB, epsilon);
25
+ const out = [];
26
+ for (const [iA, iB] of candidates) {
27
+ const triA = triangleAt(a, iA);
28
+ const triB = triangleAt(b, iB);
29
+ const res = triTriIntersect(triA, triB, planeEps);
30
+ if (res.kind === "none")
31
+ continue;
32
+ if (res.kind === "coplanar") {
33
+ out.push({ triA: iA, triB: iB, a: triA, b: triB, kind: "coplanar" });
34
+ }
35
+ else {
36
+ out.push({
37
+ triA: iA,
38
+ triB: iB,
39
+ a: triA,
40
+ b: triB,
41
+ kind: "cross",
42
+ p0: res.p0,
43
+ p1: res.p1,
44
+ });
45
+ }
46
+ }
47
+ return out;
48
+ }
49
+ //# sourceMappingURL=narrow-phase.js.map