@ifc-lite/clash 1.2.0 → 1.4.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/adapters/step.d.ts.map +1 -1
- package/dist/adapters/step.js +27 -1
- package/dist/adapters/step.js.map +1 -1
- 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/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/package.json +9 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../../src/adapters/step.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEpE,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CACxD;
|
|
1
|
+
{"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../../src/adapters/step.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEpE,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CACxD;AAwBD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,+EAA+E;IAC/E,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,8DAA8D;IAC9D,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,UAAU,EAAE,YAAY,CAAC;CAC1B;AAiBD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,iBAAiB,CAgE/E;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EACnB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,GACrC,YAAY,CAiCd"}
|
package/dist/adapters/step.js
CHANGED
|
@@ -4,6 +4,27 @@
|
|
|
4
4
|
import { EntityNode } from '@ifc-lite/query';
|
|
5
5
|
import { makeExclusionSet, qualifiedKey } from '../exclude.js';
|
|
6
6
|
import { fromPositions } from '../math/aabb.js';
|
|
7
|
+
/**
|
|
8
|
+
* Types that are never physical clash candidates: spatial volumes, voids,
|
|
9
|
+
* virtual/reference geometry, and non-product material associations. Including
|
|
10
|
+
* them produced phantom clashes (IfcSpace, IfcVirtualElement, IfcOpeningElement,
|
|
11
|
+
* even IfcMaterialConstituent) that no clash rule referenced - they are dropped
|
|
12
|
+
* from the candidate set entirely, so "detect all" and per-rule runs only ever
|
|
13
|
+
* consider real building elements. (#1464)
|
|
14
|
+
*/
|
|
15
|
+
const NON_CLASHABLE_TAGS = new Set([
|
|
16
|
+
'IfcSpace',
|
|
17
|
+
'IfcSpatialZone',
|
|
18
|
+
'IfcOpeningElement',
|
|
19
|
+
'IfcOpeningStandardCase',
|
|
20
|
+
'IfcVirtualElement',
|
|
21
|
+
'IfcGrid',
|
|
22
|
+
'IfcGridAxis',
|
|
23
|
+
'IfcAnnotation',
|
|
24
|
+
'IfcMaterial',
|
|
25
|
+
'IfcMaterialConstituent',
|
|
26
|
+
'IfcMaterialLayer',
|
|
27
|
+
]);
|
|
7
28
|
/**
|
|
8
29
|
* Lift local-frame vertices into the model's world frame: `world = origin + local`
|
|
9
30
|
* (the inverse of the renderer's per-element local frame). Returns a fresh f32
|
|
@@ -27,6 +48,11 @@ export function elementsFromStep(options) {
|
|
|
27
48
|
continue;
|
|
28
49
|
const expressId = mesh.expressId;
|
|
29
50
|
const node = new EntityNode(store, expressId);
|
|
51
|
+
// Drop non-physical / non-product geometry up front so it never becomes a
|
|
52
|
+
// clash candidate (no rule should have to exclude IfcSpace by hand). (#1464)
|
|
53
|
+
const tag = node.type || mesh.ifcType || 'IfcProduct';
|
|
54
|
+
if (NON_CLASHABLE_TAGS.has(tag))
|
|
55
|
+
continue;
|
|
30
56
|
// The wasm geometry path stores positions in the element's LOCAL frame
|
|
31
57
|
// (world = origin + position; see `MeshData.origin`). Clash works in world
|
|
32
58
|
// space — the `ClashElement` contract is world-frame triangles, and the
|
|
@@ -54,7 +80,7 @@ export function elementsFromStep(options) {
|
|
|
54
80
|
key,
|
|
55
81
|
ref: federation ? federation.toGlobalId(modelId, expressId) : expressId,
|
|
56
82
|
model: modelId,
|
|
57
|
-
tag
|
|
83
|
+
tag,
|
|
58
84
|
name: storedName || undefined,
|
|
59
85
|
storey: node.storey()?.name || undefined,
|
|
60
86
|
bounds: fromPositions(positions, worldTransform),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"step.js","sourceRoot":"","sources":["../../src/adapters/step.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAa/D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"step.js","sourceRoot":"","sources":["../../src/adapters/step.ts"],"names":[],"mappings":"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"}
|
|
@@ -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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"}
|