build-dxf 0.0.19 → 0.0.20-1
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/README.md +30 -0
- package/package.json +1 -3
- package/src/build.d.ts +23 -1
- package/src/build.js +74 -29
- package/src/index.css +625 -1
- package/src/index.js +4 -2
- package/src/index2.js +7 -3667
- package/src/index3.js +748 -288
- package/src/pages/Editor.vue.d.ts +3 -1
- package/src/selectLocalFile.js +443 -21
- package/src/utils/ComponentManager/Component.d.ts +1 -0
- package/src/utils/ComponentManager/ComponentManager.d.ts +1 -1
- package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/CommandFlowComponent.d.ts +9 -2
- package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/Default.d.ts +7 -1
- package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/DrawLine.d.ts +2 -1
- package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/DrawWindow.d.ts +2 -1
- package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/PointDrag.d.ts +2 -1
- package/src/utils/DxfSystem/plugin/Editor/components/Editor.d.ts +7 -0
- package/src/utils/DxfSystem/plugin/Editor/index.d.ts +8 -1
- package/src/utils/DxfSystem/plugin/Editor/pages/EditorTool.vue.d.ts +5 -1
- package/src/utils/DxfSystem/plugin/RenderPlugin/components/DomEventRegister.d.ts +28 -6
- package/src/utils/DxfSystem/plugin/RenderPlugin/components/Renderer.d.ts +1 -1
- package/src/utils/DxfSystem/plugin/RenderPlugin/index.d.ts +2 -1
- package/src/utils/Quadtree/LineSegment.d.ts +1 -1
- package/src/components/Editor.vue.d.ts +0 -26
- package/src/pages/Editor02.vue.d.ts +0 -4
package/src/index2.js
CHANGED
|
@@ -1,3541 +1,10 @@
|
|
|
1
1
|
import { C as Component, P as Point, V as Variable, D as DxfSystem, M as ModelDataPlugin, a as DetailsPoint, W as WhiteModel } from "./build.js";
|
|
2
2
|
import * as THREE from "three";
|
|
3
|
-
import {
|
|
3
|
+
import { Group } from "three";
|
|
4
4
|
import "clipper-lib";
|
|
5
5
|
import "dxf-writer";
|
|
6
|
-
import {
|
|
7
|
-
import { CSS2DObject, CSS2DRenderer } from "three/addons/renderers/CSS2DRenderer.js";
|
|
8
|
-
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
|
|
9
|
-
import * as TWEEN from "@tweenjs/tween.js";
|
|
6
|
+
import { E as ElButton, R as Renderer, L as Lines, D as DomEventRegister, a as DomContainer, b as ElCheckbox, S as SelectLocalFile } from "./selectLocalFile.js";
|
|
10
7
|
import { defineComponent, createElementBlock, openBlock, createElementVNode, toDisplayString, createVNode, unref, withCtx, createTextVNode, createApp, ref, watch, onMounted, onUnmounted, createCommentVNode, createStaticVNode } from "vue";
|
|
11
|
-
import { E as ElButton, L as Lines, a as ElCheckbox, S as SelectLocalFile } from "./selectLocalFile.js";
|
|
12
|
-
const CENTER = 0;
|
|
13
|
-
const AVERAGE = 1;
|
|
14
|
-
const SAH = 2;
|
|
15
|
-
const CONTAINED = 2;
|
|
16
|
-
const TRIANGLE_INTERSECT_COST = 1.25;
|
|
17
|
-
const TRAVERSAL_COST = 1;
|
|
18
|
-
const BYTES_PER_NODE = 6 * 4 + 4 + 4;
|
|
19
|
-
const IS_LEAFNODE_FLAG = 65535;
|
|
20
|
-
const FLOAT32_EPSILON = Math.pow(2, -24);
|
|
21
|
-
const SKIP_GENERATION = Symbol("SKIP_GENERATION");
|
|
22
|
-
function getVertexCount(geo) {
|
|
23
|
-
return geo.index ? geo.index.count : geo.attributes.position.count;
|
|
24
|
-
}
|
|
25
|
-
function getTriCount(geo) {
|
|
26
|
-
return getVertexCount(geo) / 3;
|
|
27
|
-
}
|
|
28
|
-
function getIndexArray(vertexCount, BufferConstructor = ArrayBuffer) {
|
|
29
|
-
if (vertexCount > 65535) {
|
|
30
|
-
return new Uint32Array(new BufferConstructor(4 * vertexCount));
|
|
31
|
-
} else {
|
|
32
|
-
return new Uint16Array(new BufferConstructor(2 * vertexCount));
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
function ensureIndex(geo, options) {
|
|
36
|
-
if (!geo.index) {
|
|
37
|
-
const vertexCount = geo.attributes.position.count;
|
|
38
|
-
const BufferConstructor = options.useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer;
|
|
39
|
-
const index2 = getIndexArray(vertexCount, BufferConstructor);
|
|
40
|
-
geo.setIndex(new BufferAttribute(index2, 1));
|
|
41
|
-
for (let i = 0; i < vertexCount; i++) {
|
|
42
|
-
index2[i] = i;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
function getFullGeometryRange(geo, range) {
|
|
47
|
-
const triCount = getTriCount(geo);
|
|
48
|
-
const drawRange = range ? range : geo.drawRange;
|
|
49
|
-
const start = drawRange.start / 3;
|
|
50
|
-
const end = (drawRange.start + drawRange.count) / 3;
|
|
51
|
-
const offset = Math.max(0, start);
|
|
52
|
-
const count = Math.min(triCount, end) - offset;
|
|
53
|
-
return [{
|
|
54
|
-
offset: Math.floor(offset),
|
|
55
|
-
count: Math.floor(count)
|
|
56
|
-
}];
|
|
57
|
-
}
|
|
58
|
-
function getRootIndexRanges(geo, range) {
|
|
59
|
-
if (!geo.groups || !geo.groups.length) {
|
|
60
|
-
return getFullGeometryRange(geo, range);
|
|
61
|
-
}
|
|
62
|
-
const ranges = [];
|
|
63
|
-
const rangeBoundaries = /* @__PURE__ */ new Set();
|
|
64
|
-
const drawRange = range ? range : geo.drawRange;
|
|
65
|
-
const drawRangeStart = drawRange.start / 3;
|
|
66
|
-
const drawRangeEnd = (drawRange.start + drawRange.count) / 3;
|
|
67
|
-
for (const group of geo.groups) {
|
|
68
|
-
const groupStart = group.start / 3;
|
|
69
|
-
const groupEnd = (group.start + group.count) / 3;
|
|
70
|
-
rangeBoundaries.add(Math.max(drawRangeStart, groupStart));
|
|
71
|
-
rangeBoundaries.add(Math.min(drawRangeEnd, groupEnd));
|
|
72
|
-
}
|
|
73
|
-
const sortedBoundaries = Array.from(rangeBoundaries.values()).sort((a, b) => a - b);
|
|
74
|
-
for (let i = 0; i < sortedBoundaries.length - 1; i++) {
|
|
75
|
-
const start = sortedBoundaries[i];
|
|
76
|
-
const end = sortedBoundaries[i + 1];
|
|
77
|
-
ranges.push({
|
|
78
|
-
offset: Math.floor(start),
|
|
79
|
-
count: Math.floor(end - start)
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
return ranges;
|
|
83
|
-
}
|
|
84
|
-
function hasGroupGaps(geometry, range) {
|
|
85
|
-
const vertexCount = getTriCount(geometry);
|
|
86
|
-
const groups = getRootIndexRanges(geometry, range).sort((a, b) => a.offset - b.offset);
|
|
87
|
-
const finalGroup = groups[groups.length - 1];
|
|
88
|
-
finalGroup.count = Math.min(vertexCount - finalGroup.offset, finalGroup.count);
|
|
89
|
-
let total = 0;
|
|
90
|
-
groups.forEach(({ count }) => total += count);
|
|
91
|
-
return vertexCount !== total;
|
|
92
|
-
}
|
|
93
|
-
function getBounds(triangleBounds, offset, count, target, centroidTarget) {
|
|
94
|
-
let minx = Infinity;
|
|
95
|
-
let miny = Infinity;
|
|
96
|
-
let minz = Infinity;
|
|
97
|
-
let maxx = -Infinity;
|
|
98
|
-
let maxy = -Infinity;
|
|
99
|
-
let maxz = -Infinity;
|
|
100
|
-
let cminx = Infinity;
|
|
101
|
-
let cminy = Infinity;
|
|
102
|
-
let cminz = Infinity;
|
|
103
|
-
let cmaxx = -Infinity;
|
|
104
|
-
let cmaxy = -Infinity;
|
|
105
|
-
let cmaxz = -Infinity;
|
|
106
|
-
for (let i = offset * 6, end = (offset + count) * 6; i < end; i += 6) {
|
|
107
|
-
const cx = triangleBounds[i + 0];
|
|
108
|
-
const hx = triangleBounds[i + 1];
|
|
109
|
-
const lx = cx - hx;
|
|
110
|
-
const rx = cx + hx;
|
|
111
|
-
if (lx < minx) minx = lx;
|
|
112
|
-
if (rx > maxx) maxx = rx;
|
|
113
|
-
if (cx < cminx) cminx = cx;
|
|
114
|
-
if (cx > cmaxx) cmaxx = cx;
|
|
115
|
-
const cy = triangleBounds[i + 2];
|
|
116
|
-
const hy = triangleBounds[i + 3];
|
|
117
|
-
const ly = cy - hy;
|
|
118
|
-
const ry = cy + hy;
|
|
119
|
-
if (ly < miny) miny = ly;
|
|
120
|
-
if (ry > maxy) maxy = ry;
|
|
121
|
-
if (cy < cminy) cminy = cy;
|
|
122
|
-
if (cy > cmaxy) cmaxy = cy;
|
|
123
|
-
const cz = triangleBounds[i + 4];
|
|
124
|
-
const hz = triangleBounds[i + 5];
|
|
125
|
-
const lz = cz - hz;
|
|
126
|
-
const rz = cz + hz;
|
|
127
|
-
if (lz < minz) minz = lz;
|
|
128
|
-
if (rz > maxz) maxz = rz;
|
|
129
|
-
if (cz < cminz) cminz = cz;
|
|
130
|
-
if (cz > cmaxz) cmaxz = cz;
|
|
131
|
-
}
|
|
132
|
-
target[0] = minx;
|
|
133
|
-
target[1] = miny;
|
|
134
|
-
target[2] = minz;
|
|
135
|
-
target[3] = maxx;
|
|
136
|
-
target[4] = maxy;
|
|
137
|
-
target[5] = maxz;
|
|
138
|
-
centroidTarget[0] = cminx;
|
|
139
|
-
centroidTarget[1] = cminy;
|
|
140
|
-
centroidTarget[2] = cminz;
|
|
141
|
-
centroidTarget[3] = cmaxx;
|
|
142
|
-
centroidTarget[4] = cmaxy;
|
|
143
|
-
centroidTarget[5] = cmaxz;
|
|
144
|
-
}
|
|
145
|
-
function computeTriangleBounds(geo, target = null, offset = null, count = null) {
|
|
146
|
-
const posAttr = geo.attributes.position;
|
|
147
|
-
const index2 = geo.index ? geo.index.array : null;
|
|
148
|
-
const triCount = getTriCount(geo);
|
|
149
|
-
const normalized = posAttr.normalized;
|
|
150
|
-
let triangleBounds;
|
|
151
|
-
if (target === null) {
|
|
152
|
-
triangleBounds = new Float32Array(triCount * 6);
|
|
153
|
-
offset = 0;
|
|
154
|
-
count = triCount;
|
|
155
|
-
} else {
|
|
156
|
-
triangleBounds = target;
|
|
157
|
-
offset = offset || 0;
|
|
158
|
-
count = count || triCount;
|
|
159
|
-
}
|
|
160
|
-
const posArr = posAttr.array;
|
|
161
|
-
const bufferOffset = posAttr.offset || 0;
|
|
162
|
-
let stride = 3;
|
|
163
|
-
if (posAttr.isInterleavedBufferAttribute) {
|
|
164
|
-
stride = posAttr.data.stride;
|
|
165
|
-
}
|
|
166
|
-
const getters = ["getX", "getY", "getZ"];
|
|
167
|
-
for (let tri = offset; tri < offset + count; tri++) {
|
|
168
|
-
const tri3 = tri * 3;
|
|
169
|
-
const tri6 = tri * 6;
|
|
170
|
-
let ai = tri3 + 0;
|
|
171
|
-
let bi = tri3 + 1;
|
|
172
|
-
let ci = tri3 + 2;
|
|
173
|
-
if (index2) {
|
|
174
|
-
ai = index2[ai];
|
|
175
|
-
bi = index2[bi];
|
|
176
|
-
ci = index2[ci];
|
|
177
|
-
}
|
|
178
|
-
if (!normalized) {
|
|
179
|
-
ai = ai * stride + bufferOffset;
|
|
180
|
-
bi = bi * stride + bufferOffset;
|
|
181
|
-
ci = ci * stride + bufferOffset;
|
|
182
|
-
}
|
|
183
|
-
for (let el = 0; el < 3; el++) {
|
|
184
|
-
let a, b, c;
|
|
185
|
-
if (normalized) {
|
|
186
|
-
a = posAttr[getters[el]](ai);
|
|
187
|
-
b = posAttr[getters[el]](bi);
|
|
188
|
-
c = posAttr[getters[el]](ci);
|
|
189
|
-
} else {
|
|
190
|
-
a = posArr[ai + el];
|
|
191
|
-
b = posArr[bi + el];
|
|
192
|
-
c = posArr[ci + el];
|
|
193
|
-
}
|
|
194
|
-
let min = a;
|
|
195
|
-
if (b < min) min = b;
|
|
196
|
-
if (c < min) min = c;
|
|
197
|
-
let max = a;
|
|
198
|
-
if (b > max) max = b;
|
|
199
|
-
if (c > max) max = c;
|
|
200
|
-
const halfExtents = (max - min) / 2;
|
|
201
|
-
const el2 = el * 2;
|
|
202
|
-
triangleBounds[tri6 + el2 + 0] = min + halfExtents;
|
|
203
|
-
triangleBounds[tri6 + el2 + 1] = halfExtents + (Math.abs(min) + halfExtents) * FLOAT32_EPSILON;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
return triangleBounds;
|
|
207
|
-
}
|
|
208
|
-
function arrayToBox(nodeIndex32, array, target) {
|
|
209
|
-
target.min.x = array[nodeIndex32];
|
|
210
|
-
target.min.y = array[nodeIndex32 + 1];
|
|
211
|
-
target.min.z = array[nodeIndex32 + 2];
|
|
212
|
-
target.max.x = array[nodeIndex32 + 3];
|
|
213
|
-
target.max.y = array[nodeIndex32 + 4];
|
|
214
|
-
target.max.z = array[nodeIndex32 + 5];
|
|
215
|
-
return target;
|
|
216
|
-
}
|
|
217
|
-
function getLongestEdgeIndex(bounds) {
|
|
218
|
-
let splitDimIdx = -1;
|
|
219
|
-
let splitDist = -Infinity;
|
|
220
|
-
for (let i = 0; i < 3; i++) {
|
|
221
|
-
const dist = bounds[i + 3] - bounds[i];
|
|
222
|
-
if (dist > splitDist) {
|
|
223
|
-
splitDist = dist;
|
|
224
|
-
splitDimIdx = i;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
return splitDimIdx;
|
|
228
|
-
}
|
|
229
|
-
function copyBounds(source, target) {
|
|
230
|
-
target.set(source);
|
|
231
|
-
}
|
|
232
|
-
function unionBounds(a, b, target) {
|
|
233
|
-
let aVal, bVal;
|
|
234
|
-
for (let d = 0; d < 3; d++) {
|
|
235
|
-
const d3 = d + 3;
|
|
236
|
-
aVal = a[d];
|
|
237
|
-
bVal = b[d];
|
|
238
|
-
target[d] = aVal < bVal ? aVal : bVal;
|
|
239
|
-
aVal = a[d3];
|
|
240
|
-
bVal = b[d3];
|
|
241
|
-
target[d3] = aVal > bVal ? aVal : bVal;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
function expandByTriangleBounds(startIndex, triangleBounds, bounds) {
|
|
245
|
-
for (let d = 0; d < 3; d++) {
|
|
246
|
-
const tCenter = triangleBounds[startIndex + 2 * d];
|
|
247
|
-
const tHalf = triangleBounds[startIndex + 2 * d + 1];
|
|
248
|
-
const tMin = tCenter - tHalf;
|
|
249
|
-
const tMax = tCenter + tHalf;
|
|
250
|
-
if (tMin < bounds[d]) {
|
|
251
|
-
bounds[d] = tMin;
|
|
252
|
-
}
|
|
253
|
-
if (tMax > bounds[d + 3]) {
|
|
254
|
-
bounds[d + 3] = tMax;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
function computeSurfaceArea(bounds) {
|
|
259
|
-
const d0 = bounds[3] - bounds[0];
|
|
260
|
-
const d1 = bounds[4] - bounds[1];
|
|
261
|
-
const d2 = bounds[5] - bounds[2];
|
|
262
|
-
return 2 * (d0 * d1 + d1 * d2 + d2 * d0);
|
|
263
|
-
}
|
|
264
|
-
const BIN_COUNT = 32;
|
|
265
|
-
const binsSort = (a, b) => a.candidate - b.candidate;
|
|
266
|
-
const sahBins = new Array(BIN_COUNT).fill().map(() => {
|
|
267
|
-
return {
|
|
268
|
-
count: 0,
|
|
269
|
-
bounds: new Float32Array(6),
|
|
270
|
-
rightCacheBounds: new Float32Array(6),
|
|
271
|
-
leftCacheBounds: new Float32Array(6),
|
|
272
|
-
candidate: 0
|
|
273
|
-
};
|
|
274
|
-
});
|
|
275
|
-
const leftBounds = new Float32Array(6);
|
|
276
|
-
function getOptimalSplit(nodeBoundingData, centroidBoundingData, triangleBounds, offset, count, strategy) {
|
|
277
|
-
let axis = -1;
|
|
278
|
-
let pos = 0;
|
|
279
|
-
if (strategy === CENTER) {
|
|
280
|
-
axis = getLongestEdgeIndex(centroidBoundingData);
|
|
281
|
-
if (axis !== -1) {
|
|
282
|
-
pos = (centroidBoundingData[axis] + centroidBoundingData[axis + 3]) / 2;
|
|
283
|
-
}
|
|
284
|
-
} else if (strategy === AVERAGE) {
|
|
285
|
-
axis = getLongestEdgeIndex(nodeBoundingData);
|
|
286
|
-
if (axis !== -1) {
|
|
287
|
-
pos = getAverage(triangleBounds, offset, count, axis);
|
|
288
|
-
}
|
|
289
|
-
} else if (strategy === SAH) {
|
|
290
|
-
const rootSurfaceArea = computeSurfaceArea(nodeBoundingData);
|
|
291
|
-
let bestCost = TRIANGLE_INTERSECT_COST * count;
|
|
292
|
-
const cStart = offset * 6;
|
|
293
|
-
const cEnd = (offset + count) * 6;
|
|
294
|
-
for (let a = 0; a < 3; a++) {
|
|
295
|
-
const axisLeft = centroidBoundingData[a];
|
|
296
|
-
const axisRight = centroidBoundingData[a + 3];
|
|
297
|
-
const axisLength = axisRight - axisLeft;
|
|
298
|
-
const binWidth = axisLength / BIN_COUNT;
|
|
299
|
-
if (count < BIN_COUNT / 4) {
|
|
300
|
-
const truncatedBins = [...sahBins];
|
|
301
|
-
truncatedBins.length = count;
|
|
302
|
-
let b = 0;
|
|
303
|
-
for (let c = cStart; c < cEnd; c += 6, b++) {
|
|
304
|
-
const bin = truncatedBins[b];
|
|
305
|
-
bin.candidate = triangleBounds[c + 2 * a];
|
|
306
|
-
bin.count = 0;
|
|
307
|
-
const {
|
|
308
|
-
bounds,
|
|
309
|
-
leftCacheBounds,
|
|
310
|
-
rightCacheBounds
|
|
311
|
-
} = bin;
|
|
312
|
-
for (let d = 0; d < 3; d++) {
|
|
313
|
-
rightCacheBounds[d] = Infinity;
|
|
314
|
-
rightCacheBounds[d + 3] = -Infinity;
|
|
315
|
-
leftCacheBounds[d] = Infinity;
|
|
316
|
-
leftCacheBounds[d + 3] = -Infinity;
|
|
317
|
-
bounds[d] = Infinity;
|
|
318
|
-
bounds[d + 3] = -Infinity;
|
|
319
|
-
}
|
|
320
|
-
expandByTriangleBounds(c, triangleBounds, bounds);
|
|
321
|
-
}
|
|
322
|
-
truncatedBins.sort(binsSort);
|
|
323
|
-
let splitCount = count;
|
|
324
|
-
for (let bi = 0; bi < splitCount; bi++) {
|
|
325
|
-
const bin = truncatedBins[bi];
|
|
326
|
-
while (bi + 1 < splitCount && truncatedBins[bi + 1].candidate === bin.candidate) {
|
|
327
|
-
truncatedBins.splice(bi + 1, 1);
|
|
328
|
-
splitCount--;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
for (let c = cStart; c < cEnd; c += 6) {
|
|
332
|
-
const center = triangleBounds[c + 2 * a];
|
|
333
|
-
for (let bi = 0; bi < splitCount; bi++) {
|
|
334
|
-
const bin = truncatedBins[bi];
|
|
335
|
-
if (center >= bin.candidate) {
|
|
336
|
-
expandByTriangleBounds(c, triangleBounds, bin.rightCacheBounds);
|
|
337
|
-
} else {
|
|
338
|
-
expandByTriangleBounds(c, triangleBounds, bin.leftCacheBounds);
|
|
339
|
-
bin.count++;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
for (let bi = 0; bi < splitCount; bi++) {
|
|
344
|
-
const bin = truncatedBins[bi];
|
|
345
|
-
const leftCount = bin.count;
|
|
346
|
-
const rightCount = count - bin.count;
|
|
347
|
-
const leftBounds2 = bin.leftCacheBounds;
|
|
348
|
-
const rightBounds = bin.rightCacheBounds;
|
|
349
|
-
let leftProb = 0;
|
|
350
|
-
if (leftCount !== 0) {
|
|
351
|
-
leftProb = computeSurfaceArea(leftBounds2) / rootSurfaceArea;
|
|
352
|
-
}
|
|
353
|
-
let rightProb = 0;
|
|
354
|
-
if (rightCount !== 0) {
|
|
355
|
-
rightProb = computeSurfaceArea(rightBounds) / rootSurfaceArea;
|
|
356
|
-
}
|
|
357
|
-
const cost = TRAVERSAL_COST + TRIANGLE_INTERSECT_COST * (leftProb * leftCount + rightProb * rightCount);
|
|
358
|
-
if (cost < bestCost) {
|
|
359
|
-
axis = a;
|
|
360
|
-
bestCost = cost;
|
|
361
|
-
pos = bin.candidate;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
} else {
|
|
365
|
-
for (let i = 0; i < BIN_COUNT; i++) {
|
|
366
|
-
const bin = sahBins[i];
|
|
367
|
-
bin.count = 0;
|
|
368
|
-
bin.candidate = axisLeft + binWidth + i * binWidth;
|
|
369
|
-
const bounds = bin.bounds;
|
|
370
|
-
for (let d = 0; d < 3; d++) {
|
|
371
|
-
bounds[d] = Infinity;
|
|
372
|
-
bounds[d + 3] = -Infinity;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
for (let c = cStart; c < cEnd; c += 6) {
|
|
376
|
-
const triCenter = triangleBounds[c + 2 * a];
|
|
377
|
-
const relativeCenter = triCenter - axisLeft;
|
|
378
|
-
let binIndex = ~~(relativeCenter / binWidth);
|
|
379
|
-
if (binIndex >= BIN_COUNT) binIndex = BIN_COUNT - 1;
|
|
380
|
-
const bin = sahBins[binIndex];
|
|
381
|
-
bin.count++;
|
|
382
|
-
expandByTriangleBounds(c, triangleBounds, bin.bounds);
|
|
383
|
-
}
|
|
384
|
-
const lastBin = sahBins[BIN_COUNT - 1];
|
|
385
|
-
copyBounds(lastBin.bounds, lastBin.rightCacheBounds);
|
|
386
|
-
for (let i = BIN_COUNT - 2; i >= 0; i--) {
|
|
387
|
-
const bin = sahBins[i];
|
|
388
|
-
const nextBin = sahBins[i + 1];
|
|
389
|
-
unionBounds(bin.bounds, nextBin.rightCacheBounds, bin.rightCacheBounds);
|
|
390
|
-
}
|
|
391
|
-
let leftCount = 0;
|
|
392
|
-
for (let i = 0; i < BIN_COUNT - 1; i++) {
|
|
393
|
-
const bin = sahBins[i];
|
|
394
|
-
const binCount = bin.count;
|
|
395
|
-
const bounds = bin.bounds;
|
|
396
|
-
const nextBin = sahBins[i + 1];
|
|
397
|
-
const rightBounds = nextBin.rightCacheBounds;
|
|
398
|
-
if (binCount !== 0) {
|
|
399
|
-
if (leftCount === 0) {
|
|
400
|
-
copyBounds(bounds, leftBounds);
|
|
401
|
-
} else {
|
|
402
|
-
unionBounds(bounds, leftBounds, leftBounds);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
leftCount += binCount;
|
|
406
|
-
let leftProb = 0;
|
|
407
|
-
let rightProb = 0;
|
|
408
|
-
if (leftCount !== 0) {
|
|
409
|
-
leftProb = computeSurfaceArea(leftBounds) / rootSurfaceArea;
|
|
410
|
-
}
|
|
411
|
-
const rightCount = count - leftCount;
|
|
412
|
-
if (rightCount !== 0) {
|
|
413
|
-
rightProb = computeSurfaceArea(rightBounds) / rootSurfaceArea;
|
|
414
|
-
}
|
|
415
|
-
const cost = TRAVERSAL_COST + TRIANGLE_INTERSECT_COST * (leftProb * leftCount + rightProb * rightCount);
|
|
416
|
-
if (cost < bestCost) {
|
|
417
|
-
axis = a;
|
|
418
|
-
bestCost = cost;
|
|
419
|
-
pos = bin.candidate;
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
} else {
|
|
425
|
-
console.warn(`MeshBVH: Invalid build strategy value ${strategy} used.`);
|
|
426
|
-
}
|
|
427
|
-
return { axis, pos };
|
|
428
|
-
}
|
|
429
|
-
function getAverage(triangleBounds, offset, count, axis) {
|
|
430
|
-
let avg = 0;
|
|
431
|
-
for (let i = offset, end = offset + count; i < end; i++) {
|
|
432
|
-
avg += triangleBounds[i * 6 + axis * 2];
|
|
433
|
-
}
|
|
434
|
-
return avg / count;
|
|
435
|
-
}
|
|
436
|
-
class MeshBVHNode {
|
|
437
|
-
constructor() {
|
|
438
|
-
this.boundingData = new Float32Array(6);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
function partition(indirectBuffer, index2, triangleBounds, offset, count, split) {
|
|
442
|
-
let left = offset;
|
|
443
|
-
let right = offset + count - 1;
|
|
444
|
-
const pos = split.pos;
|
|
445
|
-
const axisOffset = split.axis * 2;
|
|
446
|
-
while (true) {
|
|
447
|
-
while (left <= right && triangleBounds[left * 6 + axisOffset] < pos) {
|
|
448
|
-
left++;
|
|
449
|
-
}
|
|
450
|
-
while (left <= right && triangleBounds[right * 6 + axisOffset] >= pos) {
|
|
451
|
-
right--;
|
|
452
|
-
}
|
|
453
|
-
if (left < right) {
|
|
454
|
-
for (let i = 0; i < 3; i++) {
|
|
455
|
-
let t0 = index2[left * 3 + i];
|
|
456
|
-
index2[left * 3 + i] = index2[right * 3 + i];
|
|
457
|
-
index2[right * 3 + i] = t0;
|
|
458
|
-
}
|
|
459
|
-
for (let i = 0; i < 6; i++) {
|
|
460
|
-
let tb = triangleBounds[left * 6 + i];
|
|
461
|
-
triangleBounds[left * 6 + i] = triangleBounds[right * 6 + i];
|
|
462
|
-
triangleBounds[right * 6 + i] = tb;
|
|
463
|
-
}
|
|
464
|
-
left++;
|
|
465
|
-
right--;
|
|
466
|
-
} else {
|
|
467
|
-
return left;
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
function partition_indirect(indirectBuffer, index2, triangleBounds, offset, count, split) {
|
|
472
|
-
let left = offset;
|
|
473
|
-
let right = offset + count - 1;
|
|
474
|
-
const pos = split.pos;
|
|
475
|
-
const axisOffset = split.axis * 2;
|
|
476
|
-
while (true) {
|
|
477
|
-
while (left <= right && triangleBounds[left * 6 + axisOffset] < pos) {
|
|
478
|
-
left++;
|
|
479
|
-
}
|
|
480
|
-
while (left <= right && triangleBounds[right * 6 + axisOffset] >= pos) {
|
|
481
|
-
right--;
|
|
482
|
-
}
|
|
483
|
-
if (left < right) {
|
|
484
|
-
let t = indirectBuffer[left];
|
|
485
|
-
indirectBuffer[left] = indirectBuffer[right];
|
|
486
|
-
indirectBuffer[right] = t;
|
|
487
|
-
for (let i = 0; i < 6; i++) {
|
|
488
|
-
let tb = triangleBounds[left * 6 + i];
|
|
489
|
-
triangleBounds[left * 6 + i] = triangleBounds[right * 6 + i];
|
|
490
|
-
triangleBounds[right * 6 + i] = tb;
|
|
491
|
-
}
|
|
492
|
-
left++;
|
|
493
|
-
right--;
|
|
494
|
-
} else {
|
|
495
|
-
return left;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
function IS_LEAF(n16, uint16Array2) {
|
|
500
|
-
return uint16Array2[n16 + 15] === 65535;
|
|
501
|
-
}
|
|
502
|
-
function OFFSET(n32, uint32Array2) {
|
|
503
|
-
return uint32Array2[n32 + 6];
|
|
504
|
-
}
|
|
505
|
-
function COUNT(n16, uint16Array2) {
|
|
506
|
-
return uint16Array2[n16 + 14];
|
|
507
|
-
}
|
|
508
|
-
function LEFT_NODE(n32) {
|
|
509
|
-
return n32 + 8;
|
|
510
|
-
}
|
|
511
|
-
function RIGHT_NODE(n32, uint32Array2) {
|
|
512
|
-
return uint32Array2[n32 + 6];
|
|
513
|
-
}
|
|
514
|
-
function SPLIT_AXIS(n32, uint32Array2) {
|
|
515
|
-
return uint32Array2[n32 + 7];
|
|
516
|
-
}
|
|
517
|
-
function BOUNDING_DATA_INDEX(n32) {
|
|
518
|
-
return n32;
|
|
519
|
-
}
|
|
520
|
-
let float32Array, uint32Array, uint16Array, uint8Array;
|
|
521
|
-
const MAX_POINTER = Math.pow(2, 32);
|
|
522
|
-
function countNodes(node) {
|
|
523
|
-
if ("count" in node) {
|
|
524
|
-
return 1;
|
|
525
|
-
} else {
|
|
526
|
-
return 1 + countNodes(node.left) + countNodes(node.right);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
function populateBuffer(byteOffset, node, buffer) {
|
|
530
|
-
float32Array = new Float32Array(buffer);
|
|
531
|
-
uint32Array = new Uint32Array(buffer);
|
|
532
|
-
uint16Array = new Uint16Array(buffer);
|
|
533
|
-
uint8Array = new Uint8Array(buffer);
|
|
534
|
-
return _populateBuffer(byteOffset, node);
|
|
535
|
-
}
|
|
536
|
-
function _populateBuffer(byteOffset, node) {
|
|
537
|
-
const stride4Offset = byteOffset / 4;
|
|
538
|
-
const stride2Offset = byteOffset / 2;
|
|
539
|
-
const isLeaf = "count" in node;
|
|
540
|
-
const boundingData = node.boundingData;
|
|
541
|
-
for (let i = 0; i < 6; i++) {
|
|
542
|
-
float32Array[stride4Offset + i] = boundingData[i];
|
|
543
|
-
}
|
|
544
|
-
if (isLeaf) {
|
|
545
|
-
if (node.buffer) {
|
|
546
|
-
const buffer = node.buffer;
|
|
547
|
-
uint8Array.set(new Uint8Array(buffer), byteOffset);
|
|
548
|
-
for (let offset = byteOffset, l = byteOffset + buffer.byteLength; offset < l; offset += BYTES_PER_NODE) {
|
|
549
|
-
const offset2 = offset / 2;
|
|
550
|
-
if (!IS_LEAF(offset2, uint16Array)) {
|
|
551
|
-
uint32Array[offset / 4 + 6] += stride4Offset;
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
return byteOffset + buffer.byteLength;
|
|
555
|
-
} else {
|
|
556
|
-
const offset = node.offset;
|
|
557
|
-
const count = node.count;
|
|
558
|
-
uint32Array[stride4Offset + 6] = offset;
|
|
559
|
-
uint16Array[stride2Offset + 14] = count;
|
|
560
|
-
uint16Array[stride2Offset + 15] = IS_LEAFNODE_FLAG;
|
|
561
|
-
return byteOffset + BYTES_PER_NODE;
|
|
562
|
-
}
|
|
563
|
-
} else {
|
|
564
|
-
const left = node.left;
|
|
565
|
-
const right = node.right;
|
|
566
|
-
const splitAxis = node.splitAxis;
|
|
567
|
-
let nextUnusedPointer;
|
|
568
|
-
nextUnusedPointer = _populateBuffer(byteOffset + BYTES_PER_NODE, left);
|
|
569
|
-
if (nextUnusedPointer / 4 > MAX_POINTER) {
|
|
570
|
-
throw new Error("MeshBVH: Cannot store child pointer greater than 32 bits.");
|
|
571
|
-
}
|
|
572
|
-
uint32Array[stride4Offset + 6] = nextUnusedPointer / 4;
|
|
573
|
-
nextUnusedPointer = _populateBuffer(nextUnusedPointer, right);
|
|
574
|
-
uint32Array[stride4Offset + 7] = splitAxis;
|
|
575
|
-
return nextUnusedPointer;
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
function generateIndirectBuffer(geometry, useSharedArrayBuffer) {
|
|
579
|
-
const triCount = (geometry.index ? geometry.index.count : geometry.attributes.position.count) / 3;
|
|
580
|
-
const useUint32 = triCount > 2 ** 16;
|
|
581
|
-
const byteCount = useUint32 ? 4 : 2;
|
|
582
|
-
const buffer = useSharedArrayBuffer ? new SharedArrayBuffer(triCount * byteCount) : new ArrayBuffer(triCount * byteCount);
|
|
583
|
-
const indirectBuffer = useUint32 ? new Uint32Array(buffer) : new Uint16Array(buffer);
|
|
584
|
-
for (let i = 0, l = indirectBuffer.length; i < l; i++) {
|
|
585
|
-
indirectBuffer[i] = i;
|
|
586
|
-
}
|
|
587
|
-
return indirectBuffer;
|
|
588
|
-
}
|
|
589
|
-
function buildTree(bvh, triangleBounds, offset, count, options) {
|
|
590
|
-
const {
|
|
591
|
-
maxDepth,
|
|
592
|
-
verbose,
|
|
593
|
-
maxLeafTris,
|
|
594
|
-
strategy,
|
|
595
|
-
onProgress,
|
|
596
|
-
indirect
|
|
597
|
-
} = options;
|
|
598
|
-
const indirectBuffer = bvh._indirectBuffer;
|
|
599
|
-
const geometry = bvh.geometry;
|
|
600
|
-
const indexArray = geometry.index ? geometry.index.array : null;
|
|
601
|
-
const partionFunc = indirect ? partition_indirect : partition;
|
|
602
|
-
const totalTriangles = getTriCount(geometry);
|
|
603
|
-
const cacheCentroidBoundingData = new Float32Array(6);
|
|
604
|
-
let reachedMaxDepth = false;
|
|
605
|
-
const root = new MeshBVHNode();
|
|
606
|
-
getBounds(triangleBounds, offset, count, root.boundingData, cacheCentroidBoundingData);
|
|
607
|
-
splitNode(root, offset, count, cacheCentroidBoundingData);
|
|
608
|
-
return root;
|
|
609
|
-
function triggerProgress(trianglesProcessed) {
|
|
610
|
-
if (onProgress) {
|
|
611
|
-
onProgress(trianglesProcessed / totalTriangles);
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
function splitNode(node, offset2, count2, centroidBoundingData = null, depth = 0) {
|
|
615
|
-
if (!reachedMaxDepth && depth >= maxDepth) {
|
|
616
|
-
reachedMaxDepth = true;
|
|
617
|
-
if (verbose) {
|
|
618
|
-
console.warn(`MeshBVH: Max depth of ${maxDepth} reached when generating BVH. Consider increasing maxDepth.`);
|
|
619
|
-
console.warn(geometry);
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
if (count2 <= maxLeafTris || depth >= maxDepth) {
|
|
623
|
-
triggerProgress(offset2 + count2);
|
|
624
|
-
node.offset = offset2;
|
|
625
|
-
node.count = count2;
|
|
626
|
-
return node;
|
|
627
|
-
}
|
|
628
|
-
const split = getOptimalSplit(node.boundingData, centroidBoundingData, triangleBounds, offset2, count2, strategy);
|
|
629
|
-
if (split.axis === -1) {
|
|
630
|
-
triggerProgress(offset2 + count2);
|
|
631
|
-
node.offset = offset2;
|
|
632
|
-
node.count = count2;
|
|
633
|
-
return node;
|
|
634
|
-
}
|
|
635
|
-
const splitOffset = partionFunc(indirectBuffer, indexArray, triangleBounds, offset2, count2, split);
|
|
636
|
-
if (splitOffset === offset2 || splitOffset === offset2 + count2) {
|
|
637
|
-
triggerProgress(offset2 + count2);
|
|
638
|
-
node.offset = offset2;
|
|
639
|
-
node.count = count2;
|
|
640
|
-
} else {
|
|
641
|
-
node.splitAxis = split.axis;
|
|
642
|
-
const left = new MeshBVHNode();
|
|
643
|
-
const lstart = offset2;
|
|
644
|
-
const lcount = splitOffset - offset2;
|
|
645
|
-
node.left = left;
|
|
646
|
-
getBounds(triangleBounds, lstart, lcount, left.boundingData, cacheCentroidBoundingData);
|
|
647
|
-
splitNode(left, lstart, lcount, cacheCentroidBoundingData, depth + 1);
|
|
648
|
-
const right = new MeshBVHNode();
|
|
649
|
-
const rstart = splitOffset;
|
|
650
|
-
const rcount = count2 - lcount;
|
|
651
|
-
node.right = right;
|
|
652
|
-
getBounds(triangleBounds, rstart, rcount, right.boundingData, cacheCentroidBoundingData);
|
|
653
|
-
splitNode(right, rstart, rcount, cacheCentroidBoundingData, depth + 1);
|
|
654
|
-
}
|
|
655
|
-
return node;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
function buildPackedTree(bvh, options) {
|
|
659
|
-
const geometry = bvh.geometry;
|
|
660
|
-
if (options.indirect) {
|
|
661
|
-
bvh._indirectBuffer = generateIndirectBuffer(geometry, options.useSharedArrayBuffer);
|
|
662
|
-
if (hasGroupGaps(geometry, options.range) && !options.verbose) {
|
|
663
|
-
console.warn(
|
|
664
|
-
'MeshBVH: Provided geometry contains groups or a range that do not fully span the vertex contents while using the "indirect" option. BVH may incorrectly report intersections on unrendered portions of the geometry.'
|
|
665
|
-
);
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
if (!bvh._indirectBuffer) {
|
|
669
|
-
ensureIndex(geometry, options);
|
|
670
|
-
}
|
|
671
|
-
const BufferConstructor = options.useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer;
|
|
672
|
-
const triangleBounds = computeTriangleBounds(geometry);
|
|
673
|
-
const geometryRanges = options.indirect ? getFullGeometryRange(geometry, options.range) : getRootIndexRanges(geometry, options.range);
|
|
674
|
-
bvh._roots = geometryRanges.map((range) => {
|
|
675
|
-
const root = buildTree(bvh, triangleBounds, range.offset, range.count, options);
|
|
676
|
-
const nodeCount = countNodes(root);
|
|
677
|
-
const buffer = new BufferConstructor(BYTES_PER_NODE * nodeCount);
|
|
678
|
-
populateBuffer(0, root, buffer);
|
|
679
|
-
return buffer;
|
|
680
|
-
});
|
|
681
|
-
}
|
|
682
|
-
class SeparatingAxisBounds {
|
|
683
|
-
constructor() {
|
|
684
|
-
this.min = Infinity;
|
|
685
|
-
this.max = -Infinity;
|
|
686
|
-
}
|
|
687
|
-
setFromPointsField(points, field) {
|
|
688
|
-
let min = Infinity;
|
|
689
|
-
let max = -Infinity;
|
|
690
|
-
for (let i = 0, l = points.length; i < l; i++) {
|
|
691
|
-
const p = points[i];
|
|
692
|
-
const val = p[field];
|
|
693
|
-
min = val < min ? val : min;
|
|
694
|
-
max = val > max ? val : max;
|
|
695
|
-
}
|
|
696
|
-
this.min = min;
|
|
697
|
-
this.max = max;
|
|
698
|
-
}
|
|
699
|
-
setFromPoints(axis, points) {
|
|
700
|
-
let min = Infinity;
|
|
701
|
-
let max = -Infinity;
|
|
702
|
-
for (let i = 0, l = points.length; i < l; i++) {
|
|
703
|
-
const p = points[i];
|
|
704
|
-
const val = axis.dot(p);
|
|
705
|
-
min = val < min ? val : min;
|
|
706
|
-
max = val > max ? val : max;
|
|
707
|
-
}
|
|
708
|
-
this.min = min;
|
|
709
|
-
this.max = max;
|
|
710
|
-
}
|
|
711
|
-
isSeparated(other) {
|
|
712
|
-
return this.min > other.max || other.min > this.max;
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
SeparatingAxisBounds.prototype.setFromBox = (function() {
|
|
716
|
-
const p = new Vector3();
|
|
717
|
-
return function setFromBox(axis, box) {
|
|
718
|
-
const boxMin = box.min;
|
|
719
|
-
const boxMax = box.max;
|
|
720
|
-
let min = Infinity;
|
|
721
|
-
let max = -Infinity;
|
|
722
|
-
for (let x = 0; x <= 1; x++) {
|
|
723
|
-
for (let y = 0; y <= 1; y++) {
|
|
724
|
-
for (let z = 0; z <= 1; z++) {
|
|
725
|
-
p.x = boxMin.x * x + boxMax.x * (1 - x);
|
|
726
|
-
p.y = boxMin.y * y + boxMax.y * (1 - y);
|
|
727
|
-
p.z = boxMin.z * z + boxMax.z * (1 - z);
|
|
728
|
-
const val = axis.dot(p);
|
|
729
|
-
min = Math.min(val, min);
|
|
730
|
-
max = Math.max(val, max);
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
this.min = min;
|
|
735
|
-
this.max = max;
|
|
736
|
-
};
|
|
737
|
-
})();
|
|
738
|
-
const closestPointLineToLine = (function() {
|
|
739
|
-
const dir1 = new Vector3();
|
|
740
|
-
const dir2 = new Vector3();
|
|
741
|
-
const v02 = new Vector3();
|
|
742
|
-
return function closestPointLineToLine2(l1, l2, result) {
|
|
743
|
-
const v0 = l1.start;
|
|
744
|
-
const v10 = dir1;
|
|
745
|
-
const v2 = l2.start;
|
|
746
|
-
const v32 = dir2;
|
|
747
|
-
v02.subVectors(v0, v2);
|
|
748
|
-
dir1.subVectors(l1.end, l1.start);
|
|
749
|
-
dir2.subVectors(l2.end, l2.start);
|
|
750
|
-
const d0232 = v02.dot(v32);
|
|
751
|
-
const d3210 = v32.dot(v10);
|
|
752
|
-
const d3232 = v32.dot(v32);
|
|
753
|
-
const d0210 = v02.dot(v10);
|
|
754
|
-
const d1010 = v10.dot(v10);
|
|
755
|
-
const denom = d1010 * d3232 - d3210 * d3210;
|
|
756
|
-
let d, d2;
|
|
757
|
-
if (denom !== 0) {
|
|
758
|
-
d = (d0232 * d3210 - d0210 * d3232) / denom;
|
|
759
|
-
} else {
|
|
760
|
-
d = 0;
|
|
761
|
-
}
|
|
762
|
-
d2 = (d0232 + d * d3210) / d3232;
|
|
763
|
-
result.x = d;
|
|
764
|
-
result.y = d2;
|
|
765
|
-
};
|
|
766
|
-
})();
|
|
767
|
-
const closestPointsSegmentToSegment = (function() {
|
|
768
|
-
const paramResult = new Vector2();
|
|
769
|
-
const temp12 = new Vector3();
|
|
770
|
-
const temp22 = new Vector3();
|
|
771
|
-
return function closestPointsSegmentToSegment2(l1, l2, target1, target2) {
|
|
772
|
-
closestPointLineToLine(l1, l2, paramResult);
|
|
773
|
-
let d = paramResult.x;
|
|
774
|
-
let d2 = paramResult.y;
|
|
775
|
-
if (d >= 0 && d <= 1 && d2 >= 0 && d2 <= 1) {
|
|
776
|
-
l1.at(d, target1);
|
|
777
|
-
l2.at(d2, target2);
|
|
778
|
-
return;
|
|
779
|
-
} else if (d >= 0 && d <= 1) {
|
|
780
|
-
if (d2 < 0) {
|
|
781
|
-
l2.at(0, target2);
|
|
782
|
-
} else {
|
|
783
|
-
l2.at(1, target2);
|
|
784
|
-
}
|
|
785
|
-
l1.closestPointToPoint(target2, true, target1);
|
|
786
|
-
return;
|
|
787
|
-
} else if (d2 >= 0 && d2 <= 1) {
|
|
788
|
-
if (d < 0) {
|
|
789
|
-
l1.at(0, target1);
|
|
790
|
-
} else {
|
|
791
|
-
l1.at(1, target1);
|
|
792
|
-
}
|
|
793
|
-
l2.closestPointToPoint(target1, true, target2);
|
|
794
|
-
return;
|
|
795
|
-
} else {
|
|
796
|
-
let p;
|
|
797
|
-
if (d < 0) {
|
|
798
|
-
p = l1.start;
|
|
799
|
-
} else {
|
|
800
|
-
p = l1.end;
|
|
801
|
-
}
|
|
802
|
-
let p2;
|
|
803
|
-
if (d2 < 0) {
|
|
804
|
-
p2 = l2.start;
|
|
805
|
-
} else {
|
|
806
|
-
p2 = l2.end;
|
|
807
|
-
}
|
|
808
|
-
const closestPoint = temp12;
|
|
809
|
-
const closestPoint2 = temp22;
|
|
810
|
-
l1.closestPointToPoint(p2, true, temp12);
|
|
811
|
-
l2.closestPointToPoint(p, true, temp22);
|
|
812
|
-
if (closestPoint.distanceToSquared(p2) <= closestPoint2.distanceToSquared(p)) {
|
|
813
|
-
target1.copy(closestPoint);
|
|
814
|
-
target2.copy(p2);
|
|
815
|
-
return;
|
|
816
|
-
} else {
|
|
817
|
-
target1.copy(p);
|
|
818
|
-
target2.copy(closestPoint2);
|
|
819
|
-
return;
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
};
|
|
823
|
-
})();
|
|
824
|
-
const sphereIntersectTriangle = (function() {
|
|
825
|
-
const closestPointTemp = new Vector3();
|
|
826
|
-
const projectedPointTemp = new Vector3();
|
|
827
|
-
const planeTemp = new Plane();
|
|
828
|
-
const lineTemp = new Line3();
|
|
829
|
-
return function sphereIntersectTriangle2(sphere, triangle3) {
|
|
830
|
-
const { radius, center } = sphere;
|
|
831
|
-
const { a, b, c } = triangle3;
|
|
832
|
-
lineTemp.start = a;
|
|
833
|
-
lineTemp.end = b;
|
|
834
|
-
const closestPoint1 = lineTemp.closestPointToPoint(center, true, closestPointTemp);
|
|
835
|
-
if (closestPoint1.distanceTo(center) <= radius) return true;
|
|
836
|
-
lineTemp.start = a;
|
|
837
|
-
lineTemp.end = c;
|
|
838
|
-
const closestPoint2 = lineTemp.closestPointToPoint(center, true, closestPointTemp);
|
|
839
|
-
if (closestPoint2.distanceTo(center) <= radius) return true;
|
|
840
|
-
lineTemp.start = b;
|
|
841
|
-
lineTemp.end = c;
|
|
842
|
-
const closestPoint3 = lineTemp.closestPointToPoint(center, true, closestPointTemp);
|
|
843
|
-
if (closestPoint3.distanceTo(center) <= radius) return true;
|
|
844
|
-
const plane = triangle3.getPlane(planeTemp);
|
|
845
|
-
const dp = Math.abs(plane.distanceToPoint(center));
|
|
846
|
-
if (dp <= radius) {
|
|
847
|
-
const pp = plane.projectPoint(center, projectedPointTemp);
|
|
848
|
-
const cp = triangle3.containsPoint(pp);
|
|
849
|
-
if (cp) return true;
|
|
850
|
-
}
|
|
851
|
-
return false;
|
|
852
|
-
};
|
|
853
|
-
})();
|
|
854
|
-
const ZERO_EPSILON = 1e-15;
|
|
855
|
-
function isNearZero(value) {
|
|
856
|
-
return Math.abs(value) < ZERO_EPSILON;
|
|
857
|
-
}
|
|
858
|
-
class ExtendedTriangle extends Triangle {
|
|
859
|
-
constructor(...args) {
|
|
860
|
-
super(...args);
|
|
861
|
-
this.isExtendedTriangle = true;
|
|
862
|
-
this.satAxes = new Array(4).fill().map(() => new Vector3());
|
|
863
|
-
this.satBounds = new Array(4).fill().map(() => new SeparatingAxisBounds());
|
|
864
|
-
this.points = [this.a, this.b, this.c];
|
|
865
|
-
this.sphere = new Sphere();
|
|
866
|
-
this.plane = new Plane();
|
|
867
|
-
this.needsUpdate = true;
|
|
868
|
-
}
|
|
869
|
-
intersectsSphere(sphere) {
|
|
870
|
-
return sphereIntersectTriangle(sphere, this);
|
|
871
|
-
}
|
|
872
|
-
update() {
|
|
873
|
-
const a = this.a;
|
|
874
|
-
const b = this.b;
|
|
875
|
-
const c = this.c;
|
|
876
|
-
const points = this.points;
|
|
877
|
-
const satAxes = this.satAxes;
|
|
878
|
-
const satBounds = this.satBounds;
|
|
879
|
-
const axis0 = satAxes[0];
|
|
880
|
-
const sab0 = satBounds[0];
|
|
881
|
-
this.getNormal(axis0);
|
|
882
|
-
sab0.setFromPoints(axis0, points);
|
|
883
|
-
const axis1 = satAxes[1];
|
|
884
|
-
const sab1 = satBounds[1];
|
|
885
|
-
axis1.subVectors(a, b);
|
|
886
|
-
sab1.setFromPoints(axis1, points);
|
|
887
|
-
const axis2 = satAxes[2];
|
|
888
|
-
const sab2 = satBounds[2];
|
|
889
|
-
axis2.subVectors(b, c);
|
|
890
|
-
sab2.setFromPoints(axis2, points);
|
|
891
|
-
const axis3 = satAxes[3];
|
|
892
|
-
const sab3 = satBounds[3];
|
|
893
|
-
axis3.subVectors(c, a);
|
|
894
|
-
sab3.setFromPoints(axis3, points);
|
|
895
|
-
this.sphere.setFromPoints(this.points);
|
|
896
|
-
this.plane.setFromNormalAndCoplanarPoint(axis0, a);
|
|
897
|
-
this.needsUpdate = false;
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
ExtendedTriangle.prototype.closestPointToSegment = (function() {
|
|
901
|
-
const point1 = new Vector3();
|
|
902
|
-
const point2 = new Vector3();
|
|
903
|
-
const edge = new Line3();
|
|
904
|
-
return function distanceToSegment(segment, target1 = null, target2 = null) {
|
|
905
|
-
const { start, end } = segment;
|
|
906
|
-
const points = this.points;
|
|
907
|
-
let distSq;
|
|
908
|
-
let closestDistanceSq = Infinity;
|
|
909
|
-
for (let i = 0; i < 3; i++) {
|
|
910
|
-
const nexti = (i + 1) % 3;
|
|
911
|
-
edge.start.copy(points[i]);
|
|
912
|
-
edge.end.copy(points[nexti]);
|
|
913
|
-
closestPointsSegmentToSegment(edge, segment, point1, point2);
|
|
914
|
-
distSq = point1.distanceToSquared(point2);
|
|
915
|
-
if (distSq < closestDistanceSq) {
|
|
916
|
-
closestDistanceSq = distSq;
|
|
917
|
-
if (target1) target1.copy(point1);
|
|
918
|
-
if (target2) target2.copy(point2);
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
this.closestPointToPoint(start, point1);
|
|
922
|
-
distSq = start.distanceToSquared(point1);
|
|
923
|
-
if (distSq < closestDistanceSq) {
|
|
924
|
-
closestDistanceSq = distSq;
|
|
925
|
-
if (target1) target1.copy(point1);
|
|
926
|
-
if (target2) target2.copy(start);
|
|
927
|
-
}
|
|
928
|
-
this.closestPointToPoint(end, point1);
|
|
929
|
-
distSq = end.distanceToSquared(point1);
|
|
930
|
-
if (distSq < closestDistanceSq) {
|
|
931
|
-
closestDistanceSq = distSq;
|
|
932
|
-
if (target1) target1.copy(point1);
|
|
933
|
-
if (target2) target2.copy(end);
|
|
934
|
-
}
|
|
935
|
-
return Math.sqrt(closestDistanceSq);
|
|
936
|
-
};
|
|
937
|
-
})();
|
|
938
|
-
ExtendedTriangle.prototype.intersectsTriangle = (function() {
|
|
939
|
-
const saTri2 = new ExtendedTriangle();
|
|
940
|
-
const arr1 = new Array(3);
|
|
941
|
-
const arr2 = new Array(3);
|
|
942
|
-
const cachedSatBounds = new SeparatingAxisBounds();
|
|
943
|
-
const cachedSatBounds2 = new SeparatingAxisBounds();
|
|
944
|
-
const cachedAxis = new Vector3();
|
|
945
|
-
const dir = new Vector3();
|
|
946
|
-
const dir1 = new Vector3();
|
|
947
|
-
const dir2 = new Vector3();
|
|
948
|
-
const tempDir = new Vector3();
|
|
949
|
-
const edge = new Line3();
|
|
950
|
-
const edge1 = new Line3();
|
|
951
|
-
const edge2 = new Line3();
|
|
952
|
-
const tempPoint = new Vector3();
|
|
953
|
-
function triIntersectPlane(tri, plane, targetEdge) {
|
|
954
|
-
const points = tri.points;
|
|
955
|
-
let count = 0;
|
|
956
|
-
let startPointIntersection = -1;
|
|
957
|
-
for (let i = 0; i < 3; i++) {
|
|
958
|
-
const { start, end } = edge;
|
|
959
|
-
start.copy(points[i]);
|
|
960
|
-
end.copy(points[(i + 1) % 3]);
|
|
961
|
-
edge.delta(dir);
|
|
962
|
-
const startIntersects = isNearZero(plane.distanceToPoint(start));
|
|
963
|
-
if (isNearZero(plane.normal.dot(dir)) && startIntersects) {
|
|
964
|
-
targetEdge.copy(edge);
|
|
965
|
-
count = 2;
|
|
966
|
-
break;
|
|
967
|
-
}
|
|
968
|
-
const doesIntersect = plane.intersectLine(edge, tempPoint);
|
|
969
|
-
if (!doesIntersect && startIntersects) {
|
|
970
|
-
tempPoint.copy(start);
|
|
971
|
-
}
|
|
972
|
-
if ((doesIntersect || startIntersects) && !isNearZero(tempPoint.distanceTo(end))) {
|
|
973
|
-
if (count <= 1) {
|
|
974
|
-
const point = count === 1 ? targetEdge.start : targetEdge.end;
|
|
975
|
-
point.copy(tempPoint);
|
|
976
|
-
if (startIntersects) {
|
|
977
|
-
startPointIntersection = count;
|
|
978
|
-
}
|
|
979
|
-
} else if (count >= 2) {
|
|
980
|
-
const point = startPointIntersection === 1 ? targetEdge.start : targetEdge.end;
|
|
981
|
-
point.copy(tempPoint);
|
|
982
|
-
count = 2;
|
|
983
|
-
break;
|
|
984
|
-
}
|
|
985
|
-
count++;
|
|
986
|
-
if (count === 2 && startPointIntersection === -1) {
|
|
987
|
-
break;
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
return count;
|
|
992
|
-
}
|
|
993
|
-
return function intersectsTriangle(other, target = null, suppressLog = false) {
|
|
994
|
-
if (this.needsUpdate) {
|
|
995
|
-
this.update();
|
|
996
|
-
}
|
|
997
|
-
if (!other.isExtendedTriangle) {
|
|
998
|
-
saTri2.copy(other);
|
|
999
|
-
saTri2.update();
|
|
1000
|
-
other = saTri2;
|
|
1001
|
-
} else if (other.needsUpdate) {
|
|
1002
|
-
other.update();
|
|
1003
|
-
}
|
|
1004
|
-
const plane1 = this.plane;
|
|
1005
|
-
const plane2 = other.plane;
|
|
1006
|
-
if (Math.abs(plane1.normal.dot(plane2.normal)) > 1 - 1e-10) {
|
|
1007
|
-
const satBounds1 = this.satBounds;
|
|
1008
|
-
const satAxes1 = this.satAxes;
|
|
1009
|
-
arr2[0] = other.a;
|
|
1010
|
-
arr2[1] = other.b;
|
|
1011
|
-
arr2[2] = other.c;
|
|
1012
|
-
for (let i = 0; i < 4; i++) {
|
|
1013
|
-
const sb = satBounds1[i];
|
|
1014
|
-
const sa = satAxes1[i];
|
|
1015
|
-
cachedSatBounds.setFromPoints(sa, arr2);
|
|
1016
|
-
if (sb.isSeparated(cachedSatBounds)) return false;
|
|
1017
|
-
}
|
|
1018
|
-
const satBounds2 = other.satBounds;
|
|
1019
|
-
const satAxes2 = other.satAxes;
|
|
1020
|
-
arr1[0] = this.a;
|
|
1021
|
-
arr1[1] = this.b;
|
|
1022
|
-
arr1[2] = this.c;
|
|
1023
|
-
for (let i = 0; i < 4; i++) {
|
|
1024
|
-
const sb = satBounds2[i];
|
|
1025
|
-
const sa = satAxes2[i];
|
|
1026
|
-
cachedSatBounds.setFromPoints(sa, arr1);
|
|
1027
|
-
if (sb.isSeparated(cachedSatBounds)) return false;
|
|
1028
|
-
}
|
|
1029
|
-
for (let i = 0; i < 4; i++) {
|
|
1030
|
-
const sa1 = satAxes1[i];
|
|
1031
|
-
for (let i2 = 0; i2 < 4; i2++) {
|
|
1032
|
-
const sa2 = satAxes2[i2];
|
|
1033
|
-
cachedAxis.crossVectors(sa1, sa2);
|
|
1034
|
-
cachedSatBounds.setFromPoints(cachedAxis, arr1);
|
|
1035
|
-
cachedSatBounds2.setFromPoints(cachedAxis, arr2);
|
|
1036
|
-
if (cachedSatBounds.isSeparated(cachedSatBounds2)) return false;
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
if (target) {
|
|
1040
|
-
if (!suppressLog) {
|
|
1041
|
-
console.warn("ExtendedTriangle.intersectsTriangle: Triangles are coplanar which does not support an output edge. Setting edge to 0, 0, 0.");
|
|
1042
|
-
}
|
|
1043
|
-
target.start.set(0, 0, 0);
|
|
1044
|
-
target.end.set(0, 0, 0);
|
|
1045
|
-
}
|
|
1046
|
-
return true;
|
|
1047
|
-
} else {
|
|
1048
|
-
const count1 = triIntersectPlane(this, plane2, edge1);
|
|
1049
|
-
if (count1 === 1 && other.containsPoint(edge1.end)) {
|
|
1050
|
-
if (target) {
|
|
1051
|
-
target.start.copy(edge1.end);
|
|
1052
|
-
target.end.copy(edge1.end);
|
|
1053
|
-
}
|
|
1054
|
-
return true;
|
|
1055
|
-
} else if (count1 !== 2) {
|
|
1056
|
-
return false;
|
|
1057
|
-
}
|
|
1058
|
-
const count2 = triIntersectPlane(other, plane1, edge2);
|
|
1059
|
-
if (count2 === 1 && this.containsPoint(edge2.end)) {
|
|
1060
|
-
if (target) {
|
|
1061
|
-
target.start.copy(edge2.end);
|
|
1062
|
-
target.end.copy(edge2.end);
|
|
1063
|
-
}
|
|
1064
|
-
return true;
|
|
1065
|
-
} else if (count2 !== 2) {
|
|
1066
|
-
return false;
|
|
1067
|
-
}
|
|
1068
|
-
edge1.delta(dir1);
|
|
1069
|
-
edge2.delta(dir2);
|
|
1070
|
-
if (dir1.dot(dir2) < 0) {
|
|
1071
|
-
let tmp = edge2.start;
|
|
1072
|
-
edge2.start = edge2.end;
|
|
1073
|
-
edge2.end = tmp;
|
|
1074
|
-
}
|
|
1075
|
-
const s1 = edge1.start.dot(dir1);
|
|
1076
|
-
const e1 = edge1.end.dot(dir1);
|
|
1077
|
-
const s2 = edge2.start.dot(dir1);
|
|
1078
|
-
const e2 = edge2.end.dot(dir1);
|
|
1079
|
-
const separated1 = e1 < s2;
|
|
1080
|
-
const separated2 = s1 < e2;
|
|
1081
|
-
if (s1 !== e2 && s2 !== e1 && separated1 === separated2) {
|
|
1082
|
-
return false;
|
|
1083
|
-
}
|
|
1084
|
-
if (target) {
|
|
1085
|
-
tempDir.subVectors(edge1.start, edge2.start);
|
|
1086
|
-
if (tempDir.dot(dir1) > 0) {
|
|
1087
|
-
target.start.copy(edge1.start);
|
|
1088
|
-
} else {
|
|
1089
|
-
target.start.copy(edge2.start);
|
|
1090
|
-
}
|
|
1091
|
-
tempDir.subVectors(edge1.end, edge2.end);
|
|
1092
|
-
if (tempDir.dot(dir1) < 0) {
|
|
1093
|
-
target.end.copy(edge1.end);
|
|
1094
|
-
} else {
|
|
1095
|
-
target.end.copy(edge2.end);
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
return true;
|
|
1099
|
-
}
|
|
1100
|
-
};
|
|
1101
|
-
})();
|
|
1102
|
-
ExtendedTriangle.prototype.distanceToPoint = (function() {
|
|
1103
|
-
const target = new Vector3();
|
|
1104
|
-
return function distanceToPoint(point) {
|
|
1105
|
-
this.closestPointToPoint(point, target);
|
|
1106
|
-
return point.distanceTo(target);
|
|
1107
|
-
};
|
|
1108
|
-
})();
|
|
1109
|
-
ExtendedTriangle.prototype.distanceToTriangle = (function() {
|
|
1110
|
-
const point = new Vector3();
|
|
1111
|
-
const point2 = new Vector3();
|
|
1112
|
-
const cornerFields = ["a", "b", "c"];
|
|
1113
|
-
const line1 = new Line3();
|
|
1114
|
-
const line2 = new Line3();
|
|
1115
|
-
return function distanceToTriangle(other, target1 = null, target2 = null) {
|
|
1116
|
-
const lineTarget = target1 || target2 ? line1 : null;
|
|
1117
|
-
if (this.intersectsTriangle(other, lineTarget)) {
|
|
1118
|
-
if (target1 || target2) {
|
|
1119
|
-
if (target1) lineTarget.getCenter(target1);
|
|
1120
|
-
if (target2) lineTarget.getCenter(target2);
|
|
1121
|
-
}
|
|
1122
|
-
return 0;
|
|
1123
|
-
}
|
|
1124
|
-
let closestDistanceSq = Infinity;
|
|
1125
|
-
for (let i = 0; i < 3; i++) {
|
|
1126
|
-
let dist;
|
|
1127
|
-
const field = cornerFields[i];
|
|
1128
|
-
const otherVec = other[field];
|
|
1129
|
-
this.closestPointToPoint(otherVec, point);
|
|
1130
|
-
dist = otherVec.distanceToSquared(point);
|
|
1131
|
-
if (dist < closestDistanceSq) {
|
|
1132
|
-
closestDistanceSq = dist;
|
|
1133
|
-
if (target1) target1.copy(point);
|
|
1134
|
-
if (target2) target2.copy(otherVec);
|
|
1135
|
-
}
|
|
1136
|
-
const thisVec = this[field];
|
|
1137
|
-
other.closestPointToPoint(thisVec, point);
|
|
1138
|
-
dist = thisVec.distanceToSquared(point);
|
|
1139
|
-
if (dist < closestDistanceSq) {
|
|
1140
|
-
closestDistanceSq = dist;
|
|
1141
|
-
if (target1) target1.copy(thisVec);
|
|
1142
|
-
if (target2) target2.copy(point);
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
for (let i = 0; i < 3; i++) {
|
|
1146
|
-
const f11 = cornerFields[i];
|
|
1147
|
-
const f12 = cornerFields[(i + 1) % 3];
|
|
1148
|
-
line1.set(this[f11], this[f12]);
|
|
1149
|
-
for (let i2 = 0; i2 < 3; i2++) {
|
|
1150
|
-
const f21 = cornerFields[i2];
|
|
1151
|
-
const f22 = cornerFields[(i2 + 1) % 3];
|
|
1152
|
-
line2.set(other[f21], other[f22]);
|
|
1153
|
-
closestPointsSegmentToSegment(line1, line2, point, point2);
|
|
1154
|
-
const dist = point.distanceToSquared(point2);
|
|
1155
|
-
if (dist < closestDistanceSq) {
|
|
1156
|
-
closestDistanceSq = dist;
|
|
1157
|
-
if (target1) target1.copy(point);
|
|
1158
|
-
if (target2) target2.copy(point2);
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
return Math.sqrt(closestDistanceSq);
|
|
1163
|
-
};
|
|
1164
|
-
})();
|
|
1165
|
-
class OrientedBox {
|
|
1166
|
-
constructor(min, max, matrix) {
|
|
1167
|
-
this.isOrientedBox = true;
|
|
1168
|
-
this.min = new Vector3();
|
|
1169
|
-
this.max = new Vector3();
|
|
1170
|
-
this.matrix = new Matrix4();
|
|
1171
|
-
this.invMatrix = new Matrix4();
|
|
1172
|
-
this.points = new Array(8).fill().map(() => new Vector3());
|
|
1173
|
-
this.satAxes = new Array(3).fill().map(() => new Vector3());
|
|
1174
|
-
this.satBounds = new Array(3).fill().map(() => new SeparatingAxisBounds());
|
|
1175
|
-
this.alignedSatBounds = new Array(3).fill().map(() => new SeparatingAxisBounds());
|
|
1176
|
-
this.needsUpdate = false;
|
|
1177
|
-
if (min) this.min.copy(min);
|
|
1178
|
-
if (max) this.max.copy(max);
|
|
1179
|
-
if (matrix) this.matrix.copy(matrix);
|
|
1180
|
-
}
|
|
1181
|
-
set(min, max, matrix) {
|
|
1182
|
-
this.min.copy(min);
|
|
1183
|
-
this.max.copy(max);
|
|
1184
|
-
this.matrix.copy(matrix);
|
|
1185
|
-
this.needsUpdate = true;
|
|
1186
|
-
}
|
|
1187
|
-
copy(other) {
|
|
1188
|
-
this.min.copy(other.min);
|
|
1189
|
-
this.max.copy(other.max);
|
|
1190
|
-
this.matrix.copy(other.matrix);
|
|
1191
|
-
this.needsUpdate = true;
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
OrientedBox.prototype.update = /* @__PURE__ */ (function() {
|
|
1195
|
-
return function update() {
|
|
1196
|
-
const matrix = this.matrix;
|
|
1197
|
-
const min = this.min;
|
|
1198
|
-
const max = this.max;
|
|
1199
|
-
const points = this.points;
|
|
1200
|
-
for (let x = 0; x <= 1; x++) {
|
|
1201
|
-
for (let y = 0; y <= 1; y++) {
|
|
1202
|
-
for (let z = 0; z <= 1; z++) {
|
|
1203
|
-
const i = (1 << 0) * x | (1 << 1) * y | (1 << 2) * z;
|
|
1204
|
-
const v = points[i];
|
|
1205
|
-
v.x = x ? max.x : min.x;
|
|
1206
|
-
v.y = y ? max.y : min.y;
|
|
1207
|
-
v.z = z ? max.z : min.z;
|
|
1208
|
-
v.applyMatrix4(matrix);
|
|
1209
|
-
}
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
const satBounds = this.satBounds;
|
|
1213
|
-
const satAxes = this.satAxes;
|
|
1214
|
-
const minVec = points[0];
|
|
1215
|
-
for (let i = 0; i < 3; i++) {
|
|
1216
|
-
const axis = satAxes[i];
|
|
1217
|
-
const sb = satBounds[i];
|
|
1218
|
-
const index2 = 1 << i;
|
|
1219
|
-
const pi = points[index2];
|
|
1220
|
-
axis.subVectors(minVec, pi);
|
|
1221
|
-
sb.setFromPoints(axis, points);
|
|
1222
|
-
}
|
|
1223
|
-
const alignedSatBounds = this.alignedSatBounds;
|
|
1224
|
-
alignedSatBounds[0].setFromPointsField(points, "x");
|
|
1225
|
-
alignedSatBounds[1].setFromPointsField(points, "y");
|
|
1226
|
-
alignedSatBounds[2].setFromPointsField(points, "z");
|
|
1227
|
-
this.invMatrix.copy(this.matrix).invert();
|
|
1228
|
-
this.needsUpdate = false;
|
|
1229
|
-
};
|
|
1230
|
-
})();
|
|
1231
|
-
OrientedBox.prototype.intersectsBox = (function() {
|
|
1232
|
-
const aabbBounds = new SeparatingAxisBounds();
|
|
1233
|
-
return function intersectsBox(box) {
|
|
1234
|
-
if (this.needsUpdate) {
|
|
1235
|
-
this.update();
|
|
1236
|
-
}
|
|
1237
|
-
const min = box.min;
|
|
1238
|
-
const max = box.max;
|
|
1239
|
-
const satBounds = this.satBounds;
|
|
1240
|
-
const satAxes = this.satAxes;
|
|
1241
|
-
const alignedSatBounds = this.alignedSatBounds;
|
|
1242
|
-
aabbBounds.min = min.x;
|
|
1243
|
-
aabbBounds.max = max.x;
|
|
1244
|
-
if (alignedSatBounds[0].isSeparated(aabbBounds)) return false;
|
|
1245
|
-
aabbBounds.min = min.y;
|
|
1246
|
-
aabbBounds.max = max.y;
|
|
1247
|
-
if (alignedSatBounds[1].isSeparated(aabbBounds)) return false;
|
|
1248
|
-
aabbBounds.min = min.z;
|
|
1249
|
-
aabbBounds.max = max.z;
|
|
1250
|
-
if (alignedSatBounds[2].isSeparated(aabbBounds)) return false;
|
|
1251
|
-
for (let i = 0; i < 3; i++) {
|
|
1252
|
-
const axis = satAxes[i];
|
|
1253
|
-
const sb = satBounds[i];
|
|
1254
|
-
aabbBounds.setFromBox(axis, box);
|
|
1255
|
-
if (sb.isSeparated(aabbBounds)) return false;
|
|
1256
|
-
}
|
|
1257
|
-
return true;
|
|
1258
|
-
};
|
|
1259
|
-
})();
|
|
1260
|
-
OrientedBox.prototype.intersectsTriangle = (function() {
|
|
1261
|
-
const saTri = new ExtendedTriangle();
|
|
1262
|
-
const pointsArr = new Array(3);
|
|
1263
|
-
const cachedSatBounds = new SeparatingAxisBounds();
|
|
1264
|
-
const cachedSatBounds2 = new SeparatingAxisBounds();
|
|
1265
|
-
const cachedAxis = new Vector3();
|
|
1266
|
-
return function intersectsTriangle(triangle3) {
|
|
1267
|
-
if (this.needsUpdate) {
|
|
1268
|
-
this.update();
|
|
1269
|
-
}
|
|
1270
|
-
if (!triangle3.isExtendedTriangle) {
|
|
1271
|
-
saTri.copy(triangle3);
|
|
1272
|
-
saTri.update();
|
|
1273
|
-
triangle3 = saTri;
|
|
1274
|
-
} else if (triangle3.needsUpdate) {
|
|
1275
|
-
triangle3.update();
|
|
1276
|
-
}
|
|
1277
|
-
const satBounds = this.satBounds;
|
|
1278
|
-
const satAxes = this.satAxes;
|
|
1279
|
-
pointsArr[0] = triangle3.a;
|
|
1280
|
-
pointsArr[1] = triangle3.b;
|
|
1281
|
-
pointsArr[2] = triangle3.c;
|
|
1282
|
-
for (let i = 0; i < 3; i++) {
|
|
1283
|
-
const sb = satBounds[i];
|
|
1284
|
-
const sa = satAxes[i];
|
|
1285
|
-
cachedSatBounds.setFromPoints(sa, pointsArr);
|
|
1286
|
-
if (sb.isSeparated(cachedSatBounds)) return false;
|
|
1287
|
-
}
|
|
1288
|
-
const triSatBounds = triangle3.satBounds;
|
|
1289
|
-
const triSatAxes = triangle3.satAxes;
|
|
1290
|
-
const points = this.points;
|
|
1291
|
-
for (let i = 0; i < 3; i++) {
|
|
1292
|
-
const sb = triSatBounds[i];
|
|
1293
|
-
const sa = triSatAxes[i];
|
|
1294
|
-
cachedSatBounds.setFromPoints(sa, points);
|
|
1295
|
-
if (sb.isSeparated(cachedSatBounds)) return false;
|
|
1296
|
-
}
|
|
1297
|
-
for (let i = 0; i < 3; i++) {
|
|
1298
|
-
const sa1 = satAxes[i];
|
|
1299
|
-
for (let i2 = 0; i2 < 4; i2++) {
|
|
1300
|
-
const sa2 = triSatAxes[i2];
|
|
1301
|
-
cachedAxis.crossVectors(sa1, sa2);
|
|
1302
|
-
cachedSatBounds.setFromPoints(cachedAxis, pointsArr);
|
|
1303
|
-
cachedSatBounds2.setFromPoints(cachedAxis, points);
|
|
1304
|
-
if (cachedSatBounds.isSeparated(cachedSatBounds2)) return false;
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
return true;
|
|
1308
|
-
};
|
|
1309
|
-
})();
|
|
1310
|
-
OrientedBox.prototype.closestPointToPoint = /* @__PURE__ */ (function() {
|
|
1311
|
-
return function closestPointToPoint2(point, target1) {
|
|
1312
|
-
if (this.needsUpdate) {
|
|
1313
|
-
this.update();
|
|
1314
|
-
}
|
|
1315
|
-
target1.copy(point).applyMatrix4(this.invMatrix).clamp(this.min, this.max).applyMatrix4(this.matrix);
|
|
1316
|
-
return target1;
|
|
1317
|
-
};
|
|
1318
|
-
})();
|
|
1319
|
-
OrientedBox.prototype.distanceToPoint = (function() {
|
|
1320
|
-
const target = new Vector3();
|
|
1321
|
-
return function distanceToPoint(point) {
|
|
1322
|
-
this.closestPointToPoint(point, target);
|
|
1323
|
-
return point.distanceTo(target);
|
|
1324
|
-
};
|
|
1325
|
-
})();
|
|
1326
|
-
OrientedBox.prototype.distanceToBox = (function() {
|
|
1327
|
-
const xyzFields = ["x", "y", "z"];
|
|
1328
|
-
const segments1 = new Array(12).fill().map(() => new Line3());
|
|
1329
|
-
const segments2 = new Array(12).fill().map(() => new Line3());
|
|
1330
|
-
const point1 = new Vector3();
|
|
1331
|
-
const point2 = new Vector3();
|
|
1332
|
-
return function distanceToBox(box, threshold = 0, target1 = null, target2 = null) {
|
|
1333
|
-
if (this.needsUpdate) {
|
|
1334
|
-
this.update();
|
|
1335
|
-
}
|
|
1336
|
-
if (this.intersectsBox(box)) {
|
|
1337
|
-
if (target1 || target2) {
|
|
1338
|
-
box.getCenter(point2);
|
|
1339
|
-
this.closestPointToPoint(point2, point1);
|
|
1340
|
-
box.closestPointToPoint(point1, point2);
|
|
1341
|
-
if (target1) target1.copy(point1);
|
|
1342
|
-
if (target2) target2.copy(point2);
|
|
1343
|
-
}
|
|
1344
|
-
return 0;
|
|
1345
|
-
}
|
|
1346
|
-
const threshold2 = threshold * threshold;
|
|
1347
|
-
const min = box.min;
|
|
1348
|
-
const max = box.max;
|
|
1349
|
-
const points = this.points;
|
|
1350
|
-
let closestDistanceSq = Infinity;
|
|
1351
|
-
for (let i = 0; i < 8; i++) {
|
|
1352
|
-
const p = points[i];
|
|
1353
|
-
point2.copy(p).clamp(min, max);
|
|
1354
|
-
const dist = p.distanceToSquared(point2);
|
|
1355
|
-
if (dist < closestDistanceSq) {
|
|
1356
|
-
closestDistanceSq = dist;
|
|
1357
|
-
if (target1) target1.copy(p);
|
|
1358
|
-
if (target2) target2.copy(point2);
|
|
1359
|
-
if (dist < threshold2) return Math.sqrt(dist);
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
let count = 0;
|
|
1363
|
-
for (let i = 0; i < 3; i++) {
|
|
1364
|
-
for (let i1 = 0; i1 <= 1; i1++) {
|
|
1365
|
-
for (let i2 = 0; i2 <= 1; i2++) {
|
|
1366
|
-
const nextIndex = (i + 1) % 3;
|
|
1367
|
-
const nextIndex2 = (i + 2) % 3;
|
|
1368
|
-
const index2 = i1 << nextIndex | i2 << nextIndex2;
|
|
1369
|
-
const index22 = 1 << i | i1 << nextIndex | i2 << nextIndex2;
|
|
1370
|
-
const p1 = points[index2];
|
|
1371
|
-
const p2 = points[index22];
|
|
1372
|
-
const line1 = segments1[count];
|
|
1373
|
-
line1.set(p1, p2);
|
|
1374
|
-
const f1 = xyzFields[i];
|
|
1375
|
-
const f2 = xyzFields[nextIndex];
|
|
1376
|
-
const f3 = xyzFields[nextIndex2];
|
|
1377
|
-
const line2 = segments2[count];
|
|
1378
|
-
const start = line2.start;
|
|
1379
|
-
const end = line2.end;
|
|
1380
|
-
start[f1] = min[f1];
|
|
1381
|
-
start[f2] = i1 ? min[f2] : max[f2];
|
|
1382
|
-
start[f3] = i2 ? min[f3] : max[f2];
|
|
1383
|
-
end[f1] = max[f1];
|
|
1384
|
-
end[f2] = i1 ? min[f2] : max[f2];
|
|
1385
|
-
end[f3] = i2 ? min[f3] : max[f2];
|
|
1386
|
-
count++;
|
|
1387
|
-
}
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
for (let x = 0; x <= 1; x++) {
|
|
1391
|
-
for (let y = 0; y <= 1; y++) {
|
|
1392
|
-
for (let z = 0; z <= 1; z++) {
|
|
1393
|
-
point2.x = x ? max.x : min.x;
|
|
1394
|
-
point2.y = y ? max.y : min.y;
|
|
1395
|
-
point2.z = z ? max.z : min.z;
|
|
1396
|
-
this.closestPointToPoint(point2, point1);
|
|
1397
|
-
const dist = point2.distanceToSquared(point1);
|
|
1398
|
-
if (dist < closestDistanceSq) {
|
|
1399
|
-
closestDistanceSq = dist;
|
|
1400
|
-
if (target1) target1.copy(point1);
|
|
1401
|
-
if (target2) target2.copy(point2);
|
|
1402
|
-
if (dist < threshold2) return Math.sqrt(dist);
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
|
-
}
|
|
1407
|
-
for (let i = 0; i < 12; i++) {
|
|
1408
|
-
const l1 = segments1[i];
|
|
1409
|
-
for (let i2 = 0; i2 < 12; i2++) {
|
|
1410
|
-
const l2 = segments2[i2];
|
|
1411
|
-
closestPointsSegmentToSegment(l1, l2, point1, point2);
|
|
1412
|
-
const dist = point1.distanceToSquared(point2);
|
|
1413
|
-
if (dist < closestDistanceSq) {
|
|
1414
|
-
closestDistanceSq = dist;
|
|
1415
|
-
if (target1) target1.copy(point1);
|
|
1416
|
-
if (target2) target2.copy(point2);
|
|
1417
|
-
if (dist < threshold2) return Math.sqrt(dist);
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
}
|
|
1421
|
-
return Math.sqrt(closestDistanceSq);
|
|
1422
|
-
};
|
|
1423
|
-
})();
|
|
1424
|
-
class PrimitivePool {
|
|
1425
|
-
constructor(getNewPrimitive) {
|
|
1426
|
-
this._getNewPrimitive = getNewPrimitive;
|
|
1427
|
-
this._primitives = [];
|
|
1428
|
-
}
|
|
1429
|
-
getPrimitive() {
|
|
1430
|
-
const primitives = this._primitives;
|
|
1431
|
-
if (primitives.length === 0) {
|
|
1432
|
-
return this._getNewPrimitive();
|
|
1433
|
-
} else {
|
|
1434
|
-
return primitives.pop();
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1437
|
-
releasePrimitive(primitive) {
|
|
1438
|
-
this._primitives.push(primitive);
|
|
1439
|
-
}
|
|
1440
|
-
}
|
|
1441
|
-
class ExtendedTrianglePoolBase extends PrimitivePool {
|
|
1442
|
-
constructor() {
|
|
1443
|
-
super(() => new ExtendedTriangle());
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1446
|
-
const ExtendedTrianglePool = /* @__PURE__ */ new ExtendedTrianglePoolBase();
|
|
1447
|
-
class _BufferStack {
|
|
1448
|
-
constructor() {
|
|
1449
|
-
this.float32Array = null;
|
|
1450
|
-
this.uint16Array = null;
|
|
1451
|
-
this.uint32Array = null;
|
|
1452
|
-
const stack = [];
|
|
1453
|
-
let prevBuffer = null;
|
|
1454
|
-
this.setBuffer = (buffer) => {
|
|
1455
|
-
if (prevBuffer) {
|
|
1456
|
-
stack.push(prevBuffer);
|
|
1457
|
-
}
|
|
1458
|
-
prevBuffer = buffer;
|
|
1459
|
-
this.float32Array = new Float32Array(buffer);
|
|
1460
|
-
this.uint16Array = new Uint16Array(buffer);
|
|
1461
|
-
this.uint32Array = new Uint32Array(buffer);
|
|
1462
|
-
};
|
|
1463
|
-
this.clearBuffer = () => {
|
|
1464
|
-
prevBuffer = null;
|
|
1465
|
-
this.float32Array = null;
|
|
1466
|
-
this.uint16Array = null;
|
|
1467
|
-
this.uint32Array = null;
|
|
1468
|
-
if (stack.length !== 0) {
|
|
1469
|
-
this.setBuffer(stack.pop());
|
|
1470
|
-
}
|
|
1471
|
-
};
|
|
1472
|
-
}
|
|
1473
|
-
}
|
|
1474
|
-
const BufferStack = new _BufferStack();
|
|
1475
|
-
let _box1, _box2;
|
|
1476
|
-
const boxStack = [];
|
|
1477
|
-
const boxPool = /* @__PURE__ */ new PrimitivePool(() => new Box3());
|
|
1478
|
-
function shapecast(bvh, root, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset) {
|
|
1479
|
-
_box1 = boxPool.getPrimitive();
|
|
1480
|
-
_box2 = boxPool.getPrimitive();
|
|
1481
|
-
boxStack.push(_box1, _box2);
|
|
1482
|
-
BufferStack.setBuffer(bvh._roots[root]);
|
|
1483
|
-
const result = shapecastTraverse(0, bvh.geometry, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset);
|
|
1484
|
-
BufferStack.clearBuffer();
|
|
1485
|
-
boxPool.releasePrimitive(_box1);
|
|
1486
|
-
boxPool.releasePrimitive(_box2);
|
|
1487
|
-
boxStack.pop();
|
|
1488
|
-
boxStack.pop();
|
|
1489
|
-
const length = boxStack.length;
|
|
1490
|
-
if (length > 0) {
|
|
1491
|
-
_box2 = boxStack[length - 1];
|
|
1492
|
-
_box1 = boxStack[length - 2];
|
|
1493
|
-
}
|
|
1494
|
-
return result;
|
|
1495
|
-
}
|
|
1496
|
-
function shapecastTraverse(nodeIndex32, geometry, intersectsBoundsFunc, intersectsRangeFunc, nodeScoreFunc = null, nodeIndexByteOffset = 0, depth = 0) {
|
|
1497
|
-
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
1498
|
-
let nodeIndex16 = nodeIndex32 * 2;
|
|
1499
|
-
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
1500
|
-
if (isLeaf) {
|
|
1501
|
-
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
1502
|
-
const count = COUNT(nodeIndex16, uint16Array2);
|
|
1503
|
-
arrayToBox(BOUNDING_DATA_INDEX(nodeIndex32), float32Array2, _box1);
|
|
1504
|
-
return intersectsRangeFunc(offset, count, false, depth, nodeIndexByteOffset + nodeIndex32, _box1);
|
|
1505
|
-
} else {
|
|
1506
|
-
let getLeftOffset = function(nodeIndex322) {
|
|
1507
|
-
const { uint16Array: uint16Array3, uint32Array: uint32Array3 } = BufferStack;
|
|
1508
|
-
let nodeIndex162 = nodeIndex322 * 2;
|
|
1509
|
-
while (!IS_LEAF(nodeIndex162, uint16Array3)) {
|
|
1510
|
-
nodeIndex322 = LEFT_NODE(nodeIndex322);
|
|
1511
|
-
nodeIndex162 = nodeIndex322 * 2;
|
|
1512
|
-
}
|
|
1513
|
-
return OFFSET(nodeIndex322, uint32Array3);
|
|
1514
|
-
}, getRightEndOffset = function(nodeIndex322) {
|
|
1515
|
-
const { uint16Array: uint16Array3, uint32Array: uint32Array3 } = BufferStack;
|
|
1516
|
-
let nodeIndex162 = nodeIndex322 * 2;
|
|
1517
|
-
while (!IS_LEAF(nodeIndex162, uint16Array3)) {
|
|
1518
|
-
nodeIndex322 = RIGHT_NODE(nodeIndex322, uint32Array3);
|
|
1519
|
-
nodeIndex162 = nodeIndex322 * 2;
|
|
1520
|
-
}
|
|
1521
|
-
return OFFSET(nodeIndex322, uint32Array3) + COUNT(nodeIndex162, uint16Array3);
|
|
1522
|
-
};
|
|
1523
|
-
const left = LEFT_NODE(nodeIndex32);
|
|
1524
|
-
const right = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
1525
|
-
let c1 = left;
|
|
1526
|
-
let c2 = right;
|
|
1527
|
-
let score1, score2;
|
|
1528
|
-
let box1, box2;
|
|
1529
|
-
if (nodeScoreFunc) {
|
|
1530
|
-
box1 = _box1;
|
|
1531
|
-
box2 = _box2;
|
|
1532
|
-
arrayToBox(BOUNDING_DATA_INDEX(c1), float32Array2, box1);
|
|
1533
|
-
arrayToBox(BOUNDING_DATA_INDEX(c2), float32Array2, box2);
|
|
1534
|
-
score1 = nodeScoreFunc(box1);
|
|
1535
|
-
score2 = nodeScoreFunc(box2);
|
|
1536
|
-
if (score2 < score1) {
|
|
1537
|
-
c1 = right;
|
|
1538
|
-
c2 = left;
|
|
1539
|
-
const temp5 = score1;
|
|
1540
|
-
score1 = score2;
|
|
1541
|
-
score2 = temp5;
|
|
1542
|
-
box1 = box2;
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
if (!box1) {
|
|
1546
|
-
box1 = _box1;
|
|
1547
|
-
arrayToBox(BOUNDING_DATA_INDEX(c1), float32Array2, box1);
|
|
1548
|
-
}
|
|
1549
|
-
const isC1Leaf = IS_LEAF(c1 * 2, uint16Array2);
|
|
1550
|
-
const c1Intersection = intersectsBoundsFunc(box1, isC1Leaf, score1, depth + 1, nodeIndexByteOffset + c1);
|
|
1551
|
-
let c1StopTraversal;
|
|
1552
|
-
if (c1Intersection === CONTAINED) {
|
|
1553
|
-
const offset = getLeftOffset(c1);
|
|
1554
|
-
const end = getRightEndOffset(c1);
|
|
1555
|
-
const count = end - offset;
|
|
1556
|
-
c1StopTraversal = intersectsRangeFunc(offset, count, true, depth + 1, nodeIndexByteOffset + c1, box1);
|
|
1557
|
-
} else {
|
|
1558
|
-
c1StopTraversal = c1Intersection && shapecastTraverse(
|
|
1559
|
-
c1,
|
|
1560
|
-
geometry,
|
|
1561
|
-
intersectsBoundsFunc,
|
|
1562
|
-
intersectsRangeFunc,
|
|
1563
|
-
nodeScoreFunc,
|
|
1564
|
-
nodeIndexByteOffset,
|
|
1565
|
-
depth + 1
|
|
1566
|
-
);
|
|
1567
|
-
}
|
|
1568
|
-
if (c1StopTraversal) return true;
|
|
1569
|
-
box2 = _box2;
|
|
1570
|
-
arrayToBox(BOUNDING_DATA_INDEX(c2), float32Array2, box2);
|
|
1571
|
-
const isC2Leaf = IS_LEAF(c2 * 2, uint16Array2);
|
|
1572
|
-
const c2Intersection = intersectsBoundsFunc(box2, isC2Leaf, score2, depth + 1, nodeIndexByteOffset + c2);
|
|
1573
|
-
let c2StopTraversal;
|
|
1574
|
-
if (c2Intersection === CONTAINED) {
|
|
1575
|
-
const offset = getLeftOffset(c2);
|
|
1576
|
-
const end = getRightEndOffset(c2);
|
|
1577
|
-
const count = end - offset;
|
|
1578
|
-
c2StopTraversal = intersectsRangeFunc(offset, count, true, depth + 1, nodeIndexByteOffset + c2, box2);
|
|
1579
|
-
} else {
|
|
1580
|
-
c2StopTraversal = c2Intersection && shapecastTraverse(
|
|
1581
|
-
c2,
|
|
1582
|
-
geometry,
|
|
1583
|
-
intersectsBoundsFunc,
|
|
1584
|
-
intersectsRangeFunc,
|
|
1585
|
-
nodeScoreFunc,
|
|
1586
|
-
nodeIndexByteOffset,
|
|
1587
|
-
depth + 1
|
|
1588
|
-
);
|
|
1589
|
-
}
|
|
1590
|
-
if (c2StopTraversal) return true;
|
|
1591
|
-
return false;
|
|
1592
|
-
}
|
|
1593
|
-
}
|
|
1594
|
-
const temp = /* @__PURE__ */ new Vector3();
|
|
1595
|
-
const temp1$2 = /* @__PURE__ */ new Vector3();
|
|
1596
|
-
function closestPointToPoint(bvh, point, target = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
1597
|
-
const minThresholdSq = minThreshold * minThreshold;
|
|
1598
|
-
const maxThresholdSq = maxThreshold * maxThreshold;
|
|
1599
|
-
let closestDistanceSq = Infinity;
|
|
1600
|
-
let closestDistanceTriIndex = null;
|
|
1601
|
-
bvh.shapecast(
|
|
1602
|
-
{
|
|
1603
|
-
boundsTraverseOrder: (box) => {
|
|
1604
|
-
temp.copy(point).clamp(box.min, box.max);
|
|
1605
|
-
return temp.distanceToSquared(point);
|
|
1606
|
-
},
|
|
1607
|
-
intersectsBounds: (box, isLeaf, score) => {
|
|
1608
|
-
return score < closestDistanceSq && score < maxThresholdSq;
|
|
1609
|
-
},
|
|
1610
|
-
intersectsTriangle: (tri, triIndex) => {
|
|
1611
|
-
tri.closestPointToPoint(point, temp);
|
|
1612
|
-
const distSq = point.distanceToSquared(temp);
|
|
1613
|
-
if (distSq < closestDistanceSq) {
|
|
1614
|
-
temp1$2.copy(temp);
|
|
1615
|
-
closestDistanceSq = distSq;
|
|
1616
|
-
closestDistanceTriIndex = triIndex;
|
|
1617
|
-
}
|
|
1618
|
-
if (distSq < minThresholdSq) {
|
|
1619
|
-
return true;
|
|
1620
|
-
} else {
|
|
1621
|
-
return false;
|
|
1622
|
-
}
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
);
|
|
1626
|
-
if (closestDistanceSq === Infinity) return null;
|
|
1627
|
-
const closestDistance = Math.sqrt(closestDistanceSq);
|
|
1628
|
-
if (!target.point) target.point = temp1$2.clone();
|
|
1629
|
-
else target.point.copy(temp1$2);
|
|
1630
|
-
target.distance = closestDistance, target.faceIndex = closestDistanceTriIndex;
|
|
1631
|
-
return target;
|
|
1632
|
-
}
|
|
1633
|
-
const IS_GT_REVISION_169 = parseInt(REVISION) >= 169;
|
|
1634
|
-
const _vA = /* @__PURE__ */ new Vector3();
|
|
1635
|
-
const _vB = /* @__PURE__ */ new Vector3();
|
|
1636
|
-
const _vC = /* @__PURE__ */ new Vector3();
|
|
1637
|
-
const _uvA = /* @__PURE__ */ new Vector2();
|
|
1638
|
-
const _uvB = /* @__PURE__ */ new Vector2();
|
|
1639
|
-
const _uvC = /* @__PURE__ */ new Vector2();
|
|
1640
|
-
const _normalA = /* @__PURE__ */ new Vector3();
|
|
1641
|
-
const _normalB = /* @__PURE__ */ new Vector3();
|
|
1642
|
-
const _normalC = /* @__PURE__ */ new Vector3();
|
|
1643
|
-
const _intersectionPoint = /* @__PURE__ */ new Vector3();
|
|
1644
|
-
function checkIntersection(ray2, pA, pB, pC, point, side, near, far) {
|
|
1645
|
-
let intersect;
|
|
1646
|
-
if (side === BackSide) {
|
|
1647
|
-
intersect = ray2.intersectTriangle(pC, pB, pA, true, point);
|
|
1648
|
-
} else {
|
|
1649
|
-
intersect = ray2.intersectTriangle(pA, pB, pC, side !== DoubleSide, point);
|
|
1650
|
-
}
|
|
1651
|
-
if (intersect === null) return null;
|
|
1652
|
-
const distance = ray2.origin.distanceTo(point);
|
|
1653
|
-
if (distance < near || distance > far) return null;
|
|
1654
|
-
return {
|
|
1655
|
-
distance,
|
|
1656
|
-
point: point.clone()
|
|
1657
|
-
};
|
|
1658
|
-
}
|
|
1659
|
-
function checkBufferGeometryIntersection(ray2, position, normal, uv, uv1, a, b, c, side, near, far) {
|
|
1660
|
-
_vA.fromBufferAttribute(position, a);
|
|
1661
|
-
_vB.fromBufferAttribute(position, b);
|
|
1662
|
-
_vC.fromBufferAttribute(position, c);
|
|
1663
|
-
const intersection = checkIntersection(ray2, _vA, _vB, _vC, _intersectionPoint, side, near, far);
|
|
1664
|
-
if (intersection) {
|
|
1665
|
-
const barycoord = new Vector3();
|
|
1666
|
-
Triangle.getBarycoord(_intersectionPoint, _vA, _vB, _vC, barycoord);
|
|
1667
|
-
if (uv) {
|
|
1668
|
-
_uvA.fromBufferAttribute(uv, a);
|
|
1669
|
-
_uvB.fromBufferAttribute(uv, b);
|
|
1670
|
-
_uvC.fromBufferAttribute(uv, c);
|
|
1671
|
-
intersection.uv = Triangle.getInterpolation(_intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2());
|
|
1672
|
-
}
|
|
1673
|
-
if (uv1) {
|
|
1674
|
-
_uvA.fromBufferAttribute(uv1, a);
|
|
1675
|
-
_uvB.fromBufferAttribute(uv1, b);
|
|
1676
|
-
_uvC.fromBufferAttribute(uv1, c);
|
|
1677
|
-
intersection.uv1 = Triangle.getInterpolation(_intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2());
|
|
1678
|
-
}
|
|
1679
|
-
if (normal) {
|
|
1680
|
-
_normalA.fromBufferAttribute(normal, a);
|
|
1681
|
-
_normalB.fromBufferAttribute(normal, b);
|
|
1682
|
-
_normalC.fromBufferAttribute(normal, c);
|
|
1683
|
-
intersection.normal = Triangle.getInterpolation(_intersectionPoint, _vA, _vB, _vC, _normalA, _normalB, _normalC, new Vector3());
|
|
1684
|
-
if (intersection.normal.dot(ray2.direction) > 0) {
|
|
1685
|
-
intersection.normal.multiplyScalar(-1);
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
const face = {
|
|
1689
|
-
a,
|
|
1690
|
-
b,
|
|
1691
|
-
c,
|
|
1692
|
-
normal: new Vector3(),
|
|
1693
|
-
materialIndex: 0
|
|
1694
|
-
};
|
|
1695
|
-
Triangle.getNormal(_vA, _vB, _vC, face.normal);
|
|
1696
|
-
intersection.face = face;
|
|
1697
|
-
intersection.faceIndex = a;
|
|
1698
|
-
if (IS_GT_REVISION_169) {
|
|
1699
|
-
intersection.barycoord = barycoord;
|
|
1700
|
-
}
|
|
1701
|
-
}
|
|
1702
|
-
return intersection;
|
|
1703
|
-
}
|
|
1704
|
-
function intersectTri(geo, side, ray2, tri, intersections, near, far) {
|
|
1705
|
-
const triOffset = tri * 3;
|
|
1706
|
-
let a = triOffset + 0;
|
|
1707
|
-
let b = triOffset + 1;
|
|
1708
|
-
let c = triOffset + 2;
|
|
1709
|
-
const index2 = geo.index;
|
|
1710
|
-
if (geo.index) {
|
|
1711
|
-
a = index2.getX(a);
|
|
1712
|
-
b = index2.getX(b);
|
|
1713
|
-
c = index2.getX(c);
|
|
1714
|
-
}
|
|
1715
|
-
const { position, normal, uv, uv1 } = geo.attributes;
|
|
1716
|
-
const intersection = checkBufferGeometryIntersection(ray2, position, normal, uv, uv1, a, b, c, side, near, far);
|
|
1717
|
-
if (intersection) {
|
|
1718
|
-
intersection.faceIndex = tri;
|
|
1719
|
-
if (intersections) intersections.push(intersection);
|
|
1720
|
-
return intersection;
|
|
1721
|
-
}
|
|
1722
|
-
return null;
|
|
1723
|
-
}
|
|
1724
|
-
function setTriangle(tri, i, index2, pos) {
|
|
1725
|
-
const ta = tri.a;
|
|
1726
|
-
const tb = tri.b;
|
|
1727
|
-
const tc = tri.c;
|
|
1728
|
-
let i0 = i;
|
|
1729
|
-
let i1 = i + 1;
|
|
1730
|
-
let i2 = i + 2;
|
|
1731
|
-
if (index2) {
|
|
1732
|
-
i0 = index2.getX(i0);
|
|
1733
|
-
i1 = index2.getX(i1);
|
|
1734
|
-
i2 = index2.getX(i2);
|
|
1735
|
-
}
|
|
1736
|
-
ta.x = pos.getX(i0);
|
|
1737
|
-
ta.y = pos.getY(i0);
|
|
1738
|
-
ta.z = pos.getZ(i0);
|
|
1739
|
-
tb.x = pos.getX(i1);
|
|
1740
|
-
tb.y = pos.getY(i1);
|
|
1741
|
-
tb.z = pos.getZ(i1);
|
|
1742
|
-
tc.x = pos.getX(i2);
|
|
1743
|
-
tc.y = pos.getY(i2);
|
|
1744
|
-
tc.z = pos.getZ(i2);
|
|
1745
|
-
}
|
|
1746
|
-
function intersectTris(bvh, side, ray2, offset, count, intersections, near, far) {
|
|
1747
|
-
const { geometry, _indirectBuffer } = bvh;
|
|
1748
|
-
for (let i = offset, end = offset + count; i < end; i++) {
|
|
1749
|
-
intersectTri(geometry, side, ray2, i, intersections, near, far);
|
|
1750
|
-
}
|
|
1751
|
-
}
|
|
1752
|
-
function intersectClosestTri(bvh, side, ray2, offset, count, near, far) {
|
|
1753
|
-
const { geometry, _indirectBuffer } = bvh;
|
|
1754
|
-
let dist = Infinity;
|
|
1755
|
-
let res = null;
|
|
1756
|
-
for (let i = offset, end = offset + count; i < end; i++) {
|
|
1757
|
-
let intersection;
|
|
1758
|
-
intersection = intersectTri(geometry, side, ray2, i, null, near, far);
|
|
1759
|
-
if (intersection && intersection.distance < dist) {
|
|
1760
|
-
res = intersection;
|
|
1761
|
-
dist = intersection.distance;
|
|
1762
|
-
}
|
|
1763
|
-
}
|
|
1764
|
-
return res;
|
|
1765
|
-
}
|
|
1766
|
-
function iterateOverTriangles(offset, count, bvh, intersectsTriangleFunc, contained, depth, triangle3) {
|
|
1767
|
-
const { geometry } = bvh;
|
|
1768
|
-
const { index: index2 } = geometry;
|
|
1769
|
-
const pos = geometry.attributes.position;
|
|
1770
|
-
for (let i = offset, l = count + offset; i < l; i++) {
|
|
1771
|
-
let tri;
|
|
1772
|
-
tri = i;
|
|
1773
|
-
setTriangle(triangle3, tri * 3, index2, pos);
|
|
1774
|
-
triangle3.needsUpdate = true;
|
|
1775
|
-
if (intersectsTriangleFunc(triangle3, tri, contained, depth)) {
|
|
1776
|
-
return true;
|
|
1777
|
-
}
|
|
1778
|
-
}
|
|
1779
|
-
return false;
|
|
1780
|
-
}
|
|
1781
|
-
function refit(bvh, nodeIndices = null) {
|
|
1782
|
-
if (nodeIndices && Array.isArray(nodeIndices)) {
|
|
1783
|
-
nodeIndices = new Set(nodeIndices);
|
|
1784
|
-
}
|
|
1785
|
-
const geometry = bvh.geometry;
|
|
1786
|
-
const indexArr = geometry.index ? geometry.index.array : null;
|
|
1787
|
-
const posAttr = geometry.attributes.position;
|
|
1788
|
-
let buffer, uint32Array2, uint16Array2, float32Array2;
|
|
1789
|
-
let byteOffset = 0;
|
|
1790
|
-
const roots = bvh._roots;
|
|
1791
|
-
for (let i = 0, l = roots.length; i < l; i++) {
|
|
1792
|
-
buffer = roots[i];
|
|
1793
|
-
uint32Array2 = new Uint32Array(buffer);
|
|
1794
|
-
uint16Array2 = new Uint16Array(buffer);
|
|
1795
|
-
float32Array2 = new Float32Array(buffer);
|
|
1796
|
-
_traverse2(0, byteOffset);
|
|
1797
|
-
byteOffset += buffer.byteLength;
|
|
1798
|
-
}
|
|
1799
|
-
function _traverse2(node32Index, byteOffset2, force = false) {
|
|
1800
|
-
const node16Index = node32Index * 2;
|
|
1801
|
-
const isLeaf = uint16Array2[node16Index + 15] === IS_LEAFNODE_FLAG;
|
|
1802
|
-
if (isLeaf) {
|
|
1803
|
-
const offset = uint32Array2[node32Index + 6];
|
|
1804
|
-
const count = uint16Array2[node16Index + 14];
|
|
1805
|
-
let minx = Infinity;
|
|
1806
|
-
let miny = Infinity;
|
|
1807
|
-
let minz = Infinity;
|
|
1808
|
-
let maxx = -Infinity;
|
|
1809
|
-
let maxy = -Infinity;
|
|
1810
|
-
let maxz = -Infinity;
|
|
1811
|
-
for (let i = 3 * offset, l = 3 * (offset + count); i < l; i++) {
|
|
1812
|
-
let index2 = indexArr[i];
|
|
1813
|
-
const x = posAttr.getX(index2);
|
|
1814
|
-
const y = posAttr.getY(index2);
|
|
1815
|
-
const z = posAttr.getZ(index2);
|
|
1816
|
-
if (x < minx) minx = x;
|
|
1817
|
-
if (x > maxx) maxx = x;
|
|
1818
|
-
if (y < miny) miny = y;
|
|
1819
|
-
if (y > maxy) maxy = y;
|
|
1820
|
-
if (z < minz) minz = z;
|
|
1821
|
-
if (z > maxz) maxz = z;
|
|
1822
|
-
}
|
|
1823
|
-
if (float32Array2[node32Index + 0] !== minx || float32Array2[node32Index + 1] !== miny || float32Array2[node32Index + 2] !== minz || float32Array2[node32Index + 3] !== maxx || float32Array2[node32Index + 4] !== maxy || float32Array2[node32Index + 5] !== maxz) {
|
|
1824
|
-
float32Array2[node32Index + 0] = minx;
|
|
1825
|
-
float32Array2[node32Index + 1] = miny;
|
|
1826
|
-
float32Array2[node32Index + 2] = minz;
|
|
1827
|
-
float32Array2[node32Index + 3] = maxx;
|
|
1828
|
-
float32Array2[node32Index + 4] = maxy;
|
|
1829
|
-
float32Array2[node32Index + 5] = maxz;
|
|
1830
|
-
return true;
|
|
1831
|
-
} else {
|
|
1832
|
-
return false;
|
|
1833
|
-
}
|
|
1834
|
-
} else {
|
|
1835
|
-
const left = node32Index + 8;
|
|
1836
|
-
const right = uint32Array2[node32Index + 6];
|
|
1837
|
-
const offsetLeft = left + byteOffset2;
|
|
1838
|
-
const offsetRight = right + byteOffset2;
|
|
1839
|
-
let forceChildren = force;
|
|
1840
|
-
let includesLeft = false;
|
|
1841
|
-
let includesRight = false;
|
|
1842
|
-
if (nodeIndices) {
|
|
1843
|
-
if (!forceChildren) {
|
|
1844
|
-
includesLeft = nodeIndices.has(offsetLeft);
|
|
1845
|
-
includesRight = nodeIndices.has(offsetRight);
|
|
1846
|
-
forceChildren = !includesLeft && !includesRight;
|
|
1847
|
-
}
|
|
1848
|
-
} else {
|
|
1849
|
-
includesLeft = true;
|
|
1850
|
-
includesRight = true;
|
|
1851
|
-
}
|
|
1852
|
-
const traverseLeft = forceChildren || includesLeft;
|
|
1853
|
-
const traverseRight = forceChildren || includesRight;
|
|
1854
|
-
let leftChange = false;
|
|
1855
|
-
if (traverseLeft) {
|
|
1856
|
-
leftChange = _traverse2(left, byteOffset2, forceChildren);
|
|
1857
|
-
}
|
|
1858
|
-
let rightChange = false;
|
|
1859
|
-
if (traverseRight) {
|
|
1860
|
-
rightChange = _traverse2(right, byteOffset2, forceChildren);
|
|
1861
|
-
}
|
|
1862
|
-
const didChange = leftChange || rightChange;
|
|
1863
|
-
if (didChange) {
|
|
1864
|
-
for (let i = 0; i < 3; i++) {
|
|
1865
|
-
const lefti = left + i;
|
|
1866
|
-
const righti = right + i;
|
|
1867
|
-
const minLeftValue = float32Array2[lefti];
|
|
1868
|
-
const maxLeftValue = float32Array2[lefti + 3];
|
|
1869
|
-
const minRightValue = float32Array2[righti];
|
|
1870
|
-
const maxRightValue = float32Array2[righti + 3];
|
|
1871
|
-
float32Array2[node32Index + i] = minLeftValue < minRightValue ? minLeftValue : minRightValue;
|
|
1872
|
-
float32Array2[node32Index + i + 3] = maxLeftValue > maxRightValue ? maxLeftValue : maxRightValue;
|
|
1873
|
-
}
|
|
1874
|
-
}
|
|
1875
|
-
return didChange;
|
|
1876
|
-
}
|
|
1877
|
-
}
|
|
1878
|
-
}
|
|
1879
|
-
function intersectRay(nodeIndex32, array, ray2, near, far) {
|
|
1880
|
-
let tmin, tmax, tymin, tymax, tzmin, tzmax;
|
|
1881
|
-
const invdirx = 1 / ray2.direction.x, invdiry = 1 / ray2.direction.y, invdirz = 1 / ray2.direction.z;
|
|
1882
|
-
const ox = ray2.origin.x;
|
|
1883
|
-
const oy = ray2.origin.y;
|
|
1884
|
-
const oz = ray2.origin.z;
|
|
1885
|
-
let minx = array[nodeIndex32];
|
|
1886
|
-
let maxx = array[nodeIndex32 + 3];
|
|
1887
|
-
let miny = array[nodeIndex32 + 1];
|
|
1888
|
-
let maxy = array[nodeIndex32 + 3 + 1];
|
|
1889
|
-
let minz = array[nodeIndex32 + 2];
|
|
1890
|
-
let maxz = array[nodeIndex32 + 3 + 2];
|
|
1891
|
-
if (invdirx >= 0) {
|
|
1892
|
-
tmin = (minx - ox) * invdirx;
|
|
1893
|
-
tmax = (maxx - ox) * invdirx;
|
|
1894
|
-
} else {
|
|
1895
|
-
tmin = (maxx - ox) * invdirx;
|
|
1896
|
-
tmax = (minx - ox) * invdirx;
|
|
1897
|
-
}
|
|
1898
|
-
if (invdiry >= 0) {
|
|
1899
|
-
tymin = (miny - oy) * invdiry;
|
|
1900
|
-
tymax = (maxy - oy) * invdiry;
|
|
1901
|
-
} else {
|
|
1902
|
-
tymin = (maxy - oy) * invdiry;
|
|
1903
|
-
tymax = (miny - oy) * invdiry;
|
|
1904
|
-
}
|
|
1905
|
-
if (tmin > tymax || tymin > tmax) return false;
|
|
1906
|
-
if (tymin > tmin || isNaN(tmin)) tmin = tymin;
|
|
1907
|
-
if (tymax < tmax || isNaN(tmax)) tmax = tymax;
|
|
1908
|
-
if (invdirz >= 0) {
|
|
1909
|
-
tzmin = (minz - oz) * invdirz;
|
|
1910
|
-
tzmax = (maxz - oz) * invdirz;
|
|
1911
|
-
} else {
|
|
1912
|
-
tzmin = (maxz - oz) * invdirz;
|
|
1913
|
-
tzmax = (minz - oz) * invdirz;
|
|
1914
|
-
}
|
|
1915
|
-
if (tmin > tzmax || tzmin > tmax) return false;
|
|
1916
|
-
if (tzmin > tmin || tmin !== tmin) tmin = tzmin;
|
|
1917
|
-
if (tzmax < tmax || tmax !== tmax) tmax = tzmax;
|
|
1918
|
-
return tmin <= far && tmax >= near;
|
|
1919
|
-
}
|
|
1920
|
-
function intersectTris_indirect(bvh, side, ray2, offset, count, intersections, near, far) {
|
|
1921
|
-
const { geometry, _indirectBuffer } = bvh;
|
|
1922
|
-
for (let i = offset, end = offset + count; i < end; i++) {
|
|
1923
|
-
let vi = _indirectBuffer ? _indirectBuffer[i] : i;
|
|
1924
|
-
intersectTri(geometry, side, ray2, vi, intersections, near, far);
|
|
1925
|
-
}
|
|
1926
|
-
}
|
|
1927
|
-
function intersectClosestTri_indirect(bvh, side, ray2, offset, count, near, far) {
|
|
1928
|
-
const { geometry, _indirectBuffer } = bvh;
|
|
1929
|
-
let dist = Infinity;
|
|
1930
|
-
let res = null;
|
|
1931
|
-
for (let i = offset, end = offset + count; i < end; i++) {
|
|
1932
|
-
let intersection;
|
|
1933
|
-
intersection = intersectTri(geometry, side, ray2, _indirectBuffer ? _indirectBuffer[i] : i, null, near, far);
|
|
1934
|
-
if (intersection && intersection.distance < dist) {
|
|
1935
|
-
res = intersection;
|
|
1936
|
-
dist = intersection.distance;
|
|
1937
|
-
}
|
|
1938
|
-
}
|
|
1939
|
-
return res;
|
|
1940
|
-
}
|
|
1941
|
-
function iterateOverTriangles_indirect(offset, count, bvh, intersectsTriangleFunc, contained, depth, triangle3) {
|
|
1942
|
-
const { geometry } = bvh;
|
|
1943
|
-
const { index: index2 } = geometry;
|
|
1944
|
-
const pos = geometry.attributes.position;
|
|
1945
|
-
for (let i = offset, l = count + offset; i < l; i++) {
|
|
1946
|
-
let tri;
|
|
1947
|
-
tri = bvh.resolveTriangleIndex(i);
|
|
1948
|
-
setTriangle(triangle3, tri * 3, index2, pos);
|
|
1949
|
-
triangle3.needsUpdate = true;
|
|
1950
|
-
if (intersectsTriangleFunc(triangle3, tri, contained, depth)) {
|
|
1951
|
-
return true;
|
|
1952
|
-
}
|
|
1953
|
-
}
|
|
1954
|
-
return false;
|
|
1955
|
-
}
|
|
1956
|
-
function raycast(bvh, root, side, ray2, intersects, near, far) {
|
|
1957
|
-
BufferStack.setBuffer(bvh._roots[root]);
|
|
1958
|
-
_raycast$1(0, bvh, side, ray2, intersects, near, far);
|
|
1959
|
-
BufferStack.clearBuffer();
|
|
1960
|
-
}
|
|
1961
|
-
function _raycast$1(nodeIndex32, bvh, side, ray2, intersects, near, far) {
|
|
1962
|
-
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
1963
|
-
const nodeIndex16 = nodeIndex32 * 2;
|
|
1964
|
-
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
1965
|
-
if (isLeaf) {
|
|
1966
|
-
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
1967
|
-
const count = COUNT(nodeIndex16, uint16Array2);
|
|
1968
|
-
intersectTris(bvh, side, ray2, offset, count, intersects, near, far);
|
|
1969
|
-
} else {
|
|
1970
|
-
const leftIndex = LEFT_NODE(nodeIndex32);
|
|
1971
|
-
if (intersectRay(leftIndex, float32Array2, ray2, near, far)) {
|
|
1972
|
-
_raycast$1(leftIndex, bvh, side, ray2, intersects, near, far);
|
|
1973
|
-
}
|
|
1974
|
-
const rightIndex = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
1975
|
-
if (intersectRay(rightIndex, float32Array2, ray2, near, far)) {
|
|
1976
|
-
_raycast$1(rightIndex, bvh, side, ray2, intersects, near, far);
|
|
1977
|
-
}
|
|
1978
|
-
}
|
|
1979
|
-
}
|
|
1980
|
-
const _xyzFields$1 = ["x", "y", "z"];
|
|
1981
|
-
function raycastFirst(bvh, root, side, ray2, near, far) {
|
|
1982
|
-
BufferStack.setBuffer(bvh._roots[root]);
|
|
1983
|
-
const result = _raycastFirst$1(0, bvh, side, ray2, near, far);
|
|
1984
|
-
BufferStack.clearBuffer();
|
|
1985
|
-
return result;
|
|
1986
|
-
}
|
|
1987
|
-
function _raycastFirst$1(nodeIndex32, bvh, side, ray2, near, far) {
|
|
1988
|
-
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
1989
|
-
let nodeIndex16 = nodeIndex32 * 2;
|
|
1990
|
-
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
1991
|
-
if (isLeaf) {
|
|
1992
|
-
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
1993
|
-
const count = COUNT(nodeIndex16, uint16Array2);
|
|
1994
|
-
return intersectClosestTri(bvh, side, ray2, offset, count, near, far);
|
|
1995
|
-
} else {
|
|
1996
|
-
const splitAxis = SPLIT_AXIS(nodeIndex32, uint32Array2);
|
|
1997
|
-
const xyzAxis = _xyzFields$1[splitAxis];
|
|
1998
|
-
const rayDir = ray2.direction[xyzAxis];
|
|
1999
|
-
const leftToRight = rayDir >= 0;
|
|
2000
|
-
let c1, c2;
|
|
2001
|
-
if (leftToRight) {
|
|
2002
|
-
c1 = LEFT_NODE(nodeIndex32);
|
|
2003
|
-
c2 = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
2004
|
-
} else {
|
|
2005
|
-
c1 = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
2006
|
-
c2 = LEFT_NODE(nodeIndex32);
|
|
2007
|
-
}
|
|
2008
|
-
const c1Intersection = intersectRay(c1, float32Array2, ray2, near, far);
|
|
2009
|
-
const c1Result = c1Intersection ? _raycastFirst$1(c1, bvh, side, ray2, near, far) : null;
|
|
2010
|
-
if (c1Result) {
|
|
2011
|
-
const point = c1Result.point[xyzAxis];
|
|
2012
|
-
const isOutside = leftToRight ? point <= float32Array2[c2 + splitAxis] : (
|
|
2013
|
-
// min bounding data
|
|
2014
|
-
point >= float32Array2[c2 + splitAxis + 3]
|
|
2015
|
-
);
|
|
2016
|
-
if (isOutside) {
|
|
2017
|
-
return c1Result;
|
|
2018
|
-
}
|
|
2019
|
-
}
|
|
2020
|
-
const c2Intersection = intersectRay(c2, float32Array2, ray2, near, far);
|
|
2021
|
-
const c2Result = c2Intersection ? _raycastFirst$1(c2, bvh, side, ray2, near, far) : null;
|
|
2022
|
-
if (c1Result && c2Result) {
|
|
2023
|
-
return c1Result.distance <= c2Result.distance ? c1Result : c2Result;
|
|
2024
|
-
} else {
|
|
2025
|
-
return c1Result || c2Result || null;
|
|
2026
|
-
}
|
|
2027
|
-
}
|
|
2028
|
-
}
|
|
2029
|
-
const boundingBox$1 = /* @__PURE__ */ new Box3();
|
|
2030
|
-
const triangle$1 = /* @__PURE__ */ new ExtendedTriangle();
|
|
2031
|
-
const triangle2$1 = /* @__PURE__ */ new ExtendedTriangle();
|
|
2032
|
-
const invertedMat$1 = /* @__PURE__ */ new Matrix4();
|
|
2033
|
-
const obb$4 = /* @__PURE__ */ new OrientedBox();
|
|
2034
|
-
const obb2$3 = /* @__PURE__ */ new OrientedBox();
|
|
2035
|
-
function intersectsGeometry(bvh, root, otherGeometry, geometryToBvh) {
|
|
2036
|
-
BufferStack.setBuffer(bvh._roots[root]);
|
|
2037
|
-
const result = _intersectsGeometry$1(0, bvh, otherGeometry, geometryToBvh);
|
|
2038
|
-
BufferStack.clearBuffer();
|
|
2039
|
-
return result;
|
|
2040
|
-
}
|
|
2041
|
-
function _intersectsGeometry$1(nodeIndex32, bvh, otherGeometry, geometryToBvh, cachedObb = null) {
|
|
2042
|
-
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
2043
|
-
let nodeIndex16 = nodeIndex32 * 2;
|
|
2044
|
-
if (cachedObb === null) {
|
|
2045
|
-
if (!otherGeometry.boundingBox) {
|
|
2046
|
-
otherGeometry.computeBoundingBox();
|
|
2047
|
-
}
|
|
2048
|
-
obb$4.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
|
|
2049
|
-
cachedObb = obb$4;
|
|
2050
|
-
}
|
|
2051
|
-
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
2052
|
-
if (isLeaf) {
|
|
2053
|
-
const thisGeometry = bvh.geometry;
|
|
2054
|
-
const thisIndex = thisGeometry.index;
|
|
2055
|
-
const thisPos = thisGeometry.attributes.position;
|
|
2056
|
-
const index2 = otherGeometry.index;
|
|
2057
|
-
const pos = otherGeometry.attributes.position;
|
|
2058
|
-
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
2059
|
-
const count = COUNT(nodeIndex16, uint16Array2);
|
|
2060
|
-
invertedMat$1.copy(geometryToBvh).invert();
|
|
2061
|
-
if (otherGeometry.boundsTree) {
|
|
2062
|
-
arrayToBox(BOUNDING_DATA_INDEX(nodeIndex32), float32Array2, obb2$3);
|
|
2063
|
-
obb2$3.matrix.copy(invertedMat$1);
|
|
2064
|
-
obb2$3.needsUpdate = true;
|
|
2065
|
-
const res = otherGeometry.boundsTree.shapecast({
|
|
2066
|
-
intersectsBounds: (box) => obb2$3.intersectsBox(box),
|
|
2067
|
-
intersectsTriangle: (tri) => {
|
|
2068
|
-
tri.a.applyMatrix4(geometryToBvh);
|
|
2069
|
-
tri.b.applyMatrix4(geometryToBvh);
|
|
2070
|
-
tri.c.applyMatrix4(geometryToBvh);
|
|
2071
|
-
tri.needsUpdate = true;
|
|
2072
|
-
for (let i = offset * 3, l = (count + offset) * 3; i < l; i += 3) {
|
|
2073
|
-
setTriangle(triangle2$1, i, thisIndex, thisPos);
|
|
2074
|
-
triangle2$1.needsUpdate = true;
|
|
2075
|
-
if (tri.intersectsTriangle(triangle2$1)) {
|
|
2076
|
-
return true;
|
|
2077
|
-
}
|
|
2078
|
-
}
|
|
2079
|
-
return false;
|
|
2080
|
-
}
|
|
2081
|
-
});
|
|
2082
|
-
return res;
|
|
2083
|
-
} else {
|
|
2084
|
-
for (let i = offset * 3, l = (count + offset) * 3; i < l; i += 3) {
|
|
2085
|
-
setTriangle(triangle$1, i, thisIndex, thisPos);
|
|
2086
|
-
triangle$1.a.applyMatrix4(invertedMat$1);
|
|
2087
|
-
triangle$1.b.applyMatrix4(invertedMat$1);
|
|
2088
|
-
triangle$1.c.applyMatrix4(invertedMat$1);
|
|
2089
|
-
triangle$1.needsUpdate = true;
|
|
2090
|
-
for (let i2 = 0, l2 = index2.count; i2 < l2; i2 += 3) {
|
|
2091
|
-
setTriangle(triangle2$1, i2, index2, pos);
|
|
2092
|
-
triangle2$1.needsUpdate = true;
|
|
2093
|
-
if (triangle$1.intersectsTriangle(triangle2$1)) {
|
|
2094
|
-
return true;
|
|
2095
|
-
}
|
|
2096
|
-
}
|
|
2097
|
-
}
|
|
2098
|
-
}
|
|
2099
|
-
} else {
|
|
2100
|
-
const left = nodeIndex32 + 8;
|
|
2101
|
-
const right = uint32Array2[nodeIndex32 + 6];
|
|
2102
|
-
arrayToBox(BOUNDING_DATA_INDEX(left), float32Array2, boundingBox$1);
|
|
2103
|
-
const leftIntersection = cachedObb.intersectsBox(boundingBox$1) && _intersectsGeometry$1(left, bvh, otherGeometry, geometryToBvh, cachedObb);
|
|
2104
|
-
if (leftIntersection) return true;
|
|
2105
|
-
arrayToBox(BOUNDING_DATA_INDEX(right), float32Array2, boundingBox$1);
|
|
2106
|
-
const rightIntersection = cachedObb.intersectsBox(boundingBox$1) && _intersectsGeometry$1(right, bvh, otherGeometry, geometryToBvh, cachedObb);
|
|
2107
|
-
if (rightIntersection) return true;
|
|
2108
|
-
return false;
|
|
2109
|
-
}
|
|
2110
|
-
}
|
|
2111
|
-
const tempMatrix$1 = /* @__PURE__ */ new Matrix4();
|
|
2112
|
-
const obb$3 = /* @__PURE__ */ new OrientedBox();
|
|
2113
|
-
const obb2$2 = /* @__PURE__ */ new OrientedBox();
|
|
2114
|
-
const temp1$1 = /* @__PURE__ */ new Vector3();
|
|
2115
|
-
const temp2$1 = /* @__PURE__ */ new Vector3();
|
|
2116
|
-
const temp3$1 = /* @__PURE__ */ new Vector3();
|
|
2117
|
-
const temp4$1 = /* @__PURE__ */ new Vector3();
|
|
2118
|
-
function closestPointToGeometry(bvh, otherGeometry, geometryToBvh, target1 = {}, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
2119
|
-
if (!otherGeometry.boundingBox) {
|
|
2120
|
-
otherGeometry.computeBoundingBox();
|
|
2121
|
-
}
|
|
2122
|
-
obb$3.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
|
|
2123
|
-
obb$3.needsUpdate = true;
|
|
2124
|
-
const geometry = bvh.geometry;
|
|
2125
|
-
const pos = geometry.attributes.position;
|
|
2126
|
-
const index2 = geometry.index;
|
|
2127
|
-
const otherPos = otherGeometry.attributes.position;
|
|
2128
|
-
const otherIndex = otherGeometry.index;
|
|
2129
|
-
const triangle3 = ExtendedTrianglePool.getPrimitive();
|
|
2130
|
-
const triangle22 = ExtendedTrianglePool.getPrimitive();
|
|
2131
|
-
let tempTarget1 = temp1$1;
|
|
2132
|
-
let tempTargetDest1 = temp2$1;
|
|
2133
|
-
let tempTarget2 = null;
|
|
2134
|
-
let tempTargetDest2 = null;
|
|
2135
|
-
if (target2) {
|
|
2136
|
-
tempTarget2 = temp3$1;
|
|
2137
|
-
tempTargetDest2 = temp4$1;
|
|
2138
|
-
}
|
|
2139
|
-
let closestDistance = Infinity;
|
|
2140
|
-
let closestDistanceTriIndex = null;
|
|
2141
|
-
let closestDistanceOtherTriIndex = null;
|
|
2142
|
-
tempMatrix$1.copy(geometryToBvh).invert();
|
|
2143
|
-
obb2$2.matrix.copy(tempMatrix$1);
|
|
2144
|
-
bvh.shapecast(
|
|
2145
|
-
{
|
|
2146
|
-
boundsTraverseOrder: (box) => {
|
|
2147
|
-
return obb$3.distanceToBox(box);
|
|
2148
|
-
},
|
|
2149
|
-
intersectsBounds: (box, isLeaf, score) => {
|
|
2150
|
-
if (score < closestDistance && score < maxThreshold) {
|
|
2151
|
-
if (isLeaf) {
|
|
2152
|
-
obb2$2.min.copy(box.min);
|
|
2153
|
-
obb2$2.max.copy(box.max);
|
|
2154
|
-
obb2$2.needsUpdate = true;
|
|
2155
|
-
}
|
|
2156
|
-
return true;
|
|
2157
|
-
}
|
|
2158
|
-
return false;
|
|
2159
|
-
},
|
|
2160
|
-
intersectsRange: (offset, count) => {
|
|
2161
|
-
if (otherGeometry.boundsTree) {
|
|
2162
|
-
const otherBvh = otherGeometry.boundsTree;
|
|
2163
|
-
return otherBvh.shapecast({
|
|
2164
|
-
boundsTraverseOrder: (box) => {
|
|
2165
|
-
return obb2$2.distanceToBox(box);
|
|
2166
|
-
},
|
|
2167
|
-
intersectsBounds: (box, isLeaf, score) => {
|
|
2168
|
-
return score < closestDistance && score < maxThreshold;
|
|
2169
|
-
},
|
|
2170
|
-
intersectsRange: (otherOffset, otherCount) => {
|
|
2171
|
-
for (let i2 = otherOffset, l2 = otherOffset + otherCount; i2 < l2; i2++) {
|
|
2172
|
-
setTriangle(triangle22, 3 * i2, otherIndex, otherPos);
|
|
2173
|
-
triangle22.a.applyMatrix4(geometryToBvh);
|
|
2174
|
-
triangle22.b.applyMatrix4(geometryToBvh);
|
|
2175
|
-
triangle22.c.applyMatrix4(geometryToBvh);
|
|
2176
|
-
triangle22.needsUpdate = true;
|
|
2177
|
-
for (let i = offset, l = offset + count; i < l; i++) {
|
|
2178
|
-
setTriangle(triangle3, 3 * i, index2, pos);
|
|
2179
|
-
triangle3.needsUpdate = true;
|
|
2180
|
-
const dist = triangle3.distanceToTriangle(triangle22, tempTarget1, tempTarget2);
|
|
2181
|
-
if (dist < closestDistance) {
|
|
2182
|
-
tempTargetDest1.copy(tempTarget1);
|
|
2183
|
-
if (tempTargetDest2) {
|
|
2184
|
-
tempTargetDest2.copy(tempTarget2);
|
|
2185
|
-
}
|
|
2186
|
-
closestDistance = dist;
|
|
2187
|
-
closestDistanceTriIndex = i;
|
|
2188
|
-
closestDistanceOtherTriIndex = i2;
|
|
2189
|
-
}
|
|
2190
|
-
if (dist < minThreshold) {
|
|
2191
|
-
return true;
|
|
2192
|
-
}
|
|
2193
|
-
}
|
|
2194
|
-
}
|
|
2195
|
-
}
|
|
2196
|
-
});
|
|
2197
|
-
} else {
|
|
2198
|
-
const triCount = getTriCount(otherGeometry);
|
|
2199
|
-
for (let i2 = 0, l2 = triCount; i2 < l2; i2++) {
|
|
2200
|
-
setTriangle(triangle22, 3 * i2, otherIndex, otherPos);
|
|
2201
|
-
triangle22.a.applyMatrix4(geometryToBvh);
|
|
2202
|
-
triangle22.b.applyMatrix4(geometryToBvh);
|
|
2203
|
-
triangle22.c.applyMatrix4(geometryToBvh);
|
|
2204
|
-
triangle22.needsUpdate = true;
|
|
2205
|
-
for (let i = offset, l = offset + count; i < l; i++) {
|
|
2206
|
-
setTriangle(triangle3, 3 * i, index2, pos);
|
|
2207
|
-
triangle3.needsUpdate = true;
|
|
2208
|
-
const dist = triangle3.distanceToTriangle(triangle22, tempTarget1, tempTarget2);
|
|
2209
|
-
if (dist < closestDistance) {
|
|
2210
|
-
tempTargetDest1.copy(tempTarget1);
|
|
2211
|
-
if (tempTargetDest2) {
|
|
2212
|
-
tempTargetDest2.copy(tempTarget2);
|
|
2213
|
-
}
|
|
2214
|
-
closestDistance = dist;
|
|
2215
|
-
closestDistanceTriIndex = i;
|
|
2216
|
-
closestDistanceOtherTriIndex = i2;
|
|
2217
|
-
}
|
|
2218
|
-
if (dist < minThreshold) {
|
|
2219
|
-
return true;
|
|
2220
|
-
}
|
|
2221
|
-
}
|
|
2222
|
-
}
|
|
2223
|
-
}
|
|
2224
|
-
}
|
|
2225
|
-
}
|
|
2226
|
-
);
|
|
2227
|
-
ExtendedTrianglePool.releasePrimitive(triangle3);
|
|
2228
|
-
ExtendedTrianglePool.releasePrimitive(triangle22);
|
|
2229
|
-
if (closestDistance === Infinity) {
|
|
2230
|
-
return null;
|
|
2231
|
-
}
|
|
2232
|
-
if (!target1.point) {
|
|
2233
|
-
target1.point = tempTargetDest1.clone();
|
|
2234
|
-
} else {
|
|
2235
|
-
target1.point.copy(tempTargetDest1);
|
|
2236
|
-
}
|
|
2237
|
-
target1.distance = closestDistance, target1.faceIndex = closestDistanceTriIndex;
|
|
2238
|
-
if (target2) {
|
|
2239
|
-
if (!target2.point) target2.point = tempTargetDest2.clone();
|
|
2240
|
-
else target2.point.copy(tempTargetDest2);
|
|
2241
|
-
target2.point.applyMatrix4(tempMatrix$1);
|
|
2242
|
-
tempTargetDest1.applyMatrix4(tempMatrix$1);
|
|
2243
|
-
target2.distance = tempTargetDest1.sub(target2.point).length();
|
|
2244
|
-
target2.faceIndex = closestDistanceOtherTriIndex;
|
|
2245
|
-
}
|
|
2246
|
-
return target1;
|
|
2247
|
-
}
|
|
2248
|
-
function refit_indirect(bvh, nodeIndices = null) {
|
|
2249
|
-
if (nodeIndices && Array.isArray(nodeIndices)) {
|
|
2250
|
-
nodeIndices = new Set(nodeIndices);
|
|
2251
|
-
}
|
|
2252
|
-
const geometry = bvh.geometry;
|
|
2253
|
-
const indexArr = geometry.index ? geometry.index.array : null;
|
|
2254
|
-
const posAttr = geometry.attributes.position;
|
|
2255
|
-
let buffer, uint32Array2, uint16Array2, float32Array2;
|
|
2256
|
-
let byteOffset = 0;
|
|
2257
|
-
const roots = bvh._roots;
|
|
2258
|
-
for (let i = 0, l = roots.length; i < l; i++) {
|
|
2259
|
-
buffer = roots[i];
|
|
2260
|
-
uint32Array2 = new Uint32Array(buffer);
|
|
2261
|
-
uint16Array2 = new Uint16Array(buffer);
|
|
2262
|
-
float32Array2 = new Float32Array(buffer);
|
|
2263
|
-
_traverse2(0, byteOffset);
|
|
2264
|
-
byteOffset += buffer.byteLength;
|
|
2265
|
-
}
|
|
2266
|
-
function _traverse2(node32Index, byteOffset2, force = false) {
|
|
2267
|
-
const node16Index = node32Index * 2;
|
|
2268
|
-
const isLeaf = uint16Array2[node16Index + 15] === IS_LEAFNODE_FLAG;
|
|
2269
|
-
if (isLeaf) {
|
|
2270
|
-
const offset = uint32Array2[node32Index + 6];
|
|
2271
|
-
const count = uint16Array2[node16Index + 14];
|
|
2272
|
-
let minx = Infinity;
|
|
2273
|
-
let miny = Infinity;
|
|
2274
|
-
let minz = Infinity;
|
|
2275
|
-
let maxx = -Infinity;
|
|
2276
|
-
let maxy = -Infinity;
|
|
2277
|
-
let maxz = -Infinity;
|
|
2278
|
-
for (let i = offset, l = offset + count; i < l; i++) {
|
|
2279
|
-
const t = 3 * bvh.resolveTriangleIndex(i);
|
|
2280
|
-
for (let j = 0; j < 3; j++) {
|
|
2281
|
-
let index2 = t + j;
|
|
2282
|
-
index2 = indexArr ? indexArr[index2] : index2;
|
|
2283
|
-
const x = posAttr.getX(index2);
|
|
2284
|
-
const y = posAttr.getY(index2);
|
|
2285
|
-
const z = posAttr.getZ(index2);
|
|
2286
|
-
if (x < minx) minx = x;
|
|
2287
|
-
if (x > maxx) maxx = x;
|
|
2288
|
-
if (y < miny) miny = y;
|
|
2289
|
-
if (y > maxy) maxy = y;
|
|
2290
|
-
if (z < minz) minz = z;
|
|
2291
|
-
if (z > maxz) maxz = z;
|
|
2292
|
-
}
|
|
2293
|
-
}
|
|
2294
|
-
if (float32Array2[node32Index + 0] !== minx || float32Array2[node32Index + 1] !== miny || float32Array2[node32Index + 2] !== minz || float32Array2[node32Index + 3] !== maxx || float32Array2[node32Index + 4] !== maxy || float32Array2[node32Index + 5] !== maxz) {
|
|
2295
|
-
float32Array2[node32Index + 0] = minx;
|
|
2296
|
-
float32Array2[node32Index + 1] = miny;
|
|
2297
|
-
float32Array2[node32Index + 2] = minz;
|
|
2298
|
-
float32Array2[node32Index + 3] = maxx;
|
|
2299
|
-
float32Array2[node32Index + 4] = maxy;
|
|
2300
|
-
float32Array2[node32Index + 5] = maxz;
|
|
2301
|
-
return true;
|
|
2302
|
-
} else {
|
|
2303
|
-
return false;
|
|
2304
|
-
}
|
|
2305
|
-
} else {
|
|
2306
|
-
const left = node32Index + 8;
|
|
2307
|
-
const right = uint32Array2[node32Index + 6];
|
|
2308
|
-
const offsetLeft = left + byteOffset2;
|
|
2309
|
-
const offsetRight = right + byteOffset2;
|
|
2310
|
-
let forceChildren = force;
|
|
2311
|
-
let includesLeft = false;
|
|
2312
|
-
let includesRight = false;
|
|
2313
|
-
if (nodeIndices) {
|
|
2314
|
-
if (!forceChildren) {
|
|
2315
|
-
includesLeft = nodeIndices.has(offsetLeft);
|
|
2316
|
-
includesRight = nodeIndices.has(offsetRight);
|
|
2317
|
-
forceChildren = !includesLeft && !includesRight;
|
|
2318
|
-
}
|
|
2319
|
-
} else {
|
|
2320
|
-
includesLeft = true;
|
|
2321
|
-
includesRight = true;
|
|
2322
|
-
}
|
|
2323
|
-
const traverseLeft = forceChildren || includesLeft;
|
|
2324
|
-
const traverseRight = forceChildren || includesRight;
|
|
2325
|
-
let leftChange = false;
|
|
2326
|
-
if (traverseLeft) {
|
|
2327
|
-
leftChange = _traverse2(left, byteOffset2, forceChildren);
|
|
2328
|
-
}
|
|
2329
|
-
let rightChange = false;
|
|
2330
|
-
if (traverseRight) {
|
|
2331
|
-
rightChange = _traverse2(right, byteOffset2, forceChildren);
|
|
2332
|
-
}
|
|
2333
|
-
const didChange = leftChange || rightChange;
|
|
2334
|
-
if (didChange) {
|
|
2335
|
-
for (let i = 0; i < 3; i++) {
|
|
2336
|
-
const lefti = left + i;
|
|
2337
|
-
const righti = right + i;
|
|
2338
|
-
const minLeftValue = float32Array2[lefti];
|
|
2339
|
-
const maxLeftValue = float32Array2[lefti + 3];
|
|
2340
|
-
const minRightValue = float32Array2[righti];
|
|
2341
|
-
const maxRightValue = float32Array2[righti + 3];
|
|
2342
|
-
float32Array2[node32Index + i] = minLeftValue < minRightValue ? minLeftValue : minRightValue;
|
|
2343
|
-
float32Array2[node32Index + i + 3] = maxLeftValue > maxRightValue ? maxLeftValue : maxRightValue;
|
|
2344
|
-
}
|
|
2345
|
-
}
|
|
2346
|
-
return didChange;
|
|
2347
|
-
}
|
|
2348
|
-
}
|
|
2349
|
-
}
|
|
2350
|
-
function raycast_indirect(bvh, root, side, ray2, intersects, near, far) {
|
|
2351
|
-
BufferStack.setBuffer(bvh._roots[root]);
|
|
2352
|
-
_raycast(0, bvh, side, ray2, intersects, near, far);
|
|
2353
|
-
BufferStack.clearBuffer();
|
|
2354
|
-
}
|
|
2355
|
-
function _raycast(nodeIndex32, bvh, side, ray2, intersects, near, far) {
|
|
2356
|
-
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
2357
|
-
const nodeIndex16 = nodeIndex32 * 2;
|
|
2358
|
-
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
2359
|
-
if (isLeaf) {
|
|
2360
|
-
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
2361
|
-
const count = COUNT(nodeIndex16, uint16Array2);
|
|
2362
|
-
intersectTris_indirect(bvh, side, ray2, offset, count, intersects, near, far);
|
|
2363
|
-
} else {
|
|
2364
|
-
const leftIndex = LEFT_NODE(nodeIndex32);
|
|
2365
|
-
if (intersectRay(leftIndex, float32Array2, ray2, near, far)) {
|
|
2366
|
-
_raycast(leftIndex, bvh, side, ray2, intersects, near, far);
|
|
2367
|
-
}
|
|
2368
|
-
const rightIndex = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
2369
|
-
if (intersectRay(rightIndex, float32Array2, ray2, near, far)) {
|
|
2370
|
-
_raycast(rightIndex, bvh, side, ray2, intersects, near, far);
|
|
2371
|
-
}
|
|
2372
|
-
}
|
|
2373
|
-
}
|
|
2374
|
-
const _xyzFields = ["x", "y", "z"];
|
|
2375
|
-
function raycastFirst_indirect(bvh, root, side, ray2, near, far) {
|
|
2376
|
-
BufferStack.setBuffer(bvh._roots[root]);
|
|
2377
|
-
const result = _raycastFirst(0, bvh, side, ray2, near, far);
|
|
2378
|
-
BufferStack.clearBuffer();
|
|
2379
|
-
return result;
|
|
2380
|
-
}
|
|
2381
|
-
function _raycastFirst(nodeIndex32, bvh, side, ray2, near, far) {
|
|
2382
|
-
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
2383
|
-
let nodeIndex16 = nodeIndex32 * 2;
|
|
2384
|
-
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
2385
|
-
if (isLeaf) {
|
|
2386
|
-
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
2387
|
-
const count = COUNT(nodeIndex16, uint16Array2);
|
|
2388
|
-
return intersectClosestTri_indirect(bvh, side, ray2, offset, count, near, far);
|
|
2389
|
-
} else {
|
|
2390
|
-
const splitAxis = SPLIT_AXIS(nodeIndex32, uint32Array2);
|
|
2391
|
-
const xyzAxis = _xyzFields[splitAxis];
|
|
2392
|
-
const rayDir = ray2.direction[xyzAxis];
|
|
2393
|
-
const leftToRight = rayDir >= 0;
|
|
2394
|
-
let c1, c2;
|
|
2395
|
-
if (leftToRight) {
|
|
2396
|
-
c1 = LEFT_NODE(nodeIndex32);
|
|
2397
|
-
c2 = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
2398
|
-
} else {
|
|
2399
|
-
c1 = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
2400
|
-
c2 = LEFT_NODE(nodeIndex32);
|
|
2401
|
-
}
|
|
2402
|
-
const c1Intersection = intersectRay(c1, float32Array2, ray2, near, far);
|
|
2403
|
-
const c1Result = c1Intersection ? _raycastFirst(c1, bvh, side, ray2, near, far) : null;
|
|
2404
|
-
if (c1Result) {
|
|
2405
|
-
const point = c1Result.point[xyzAxis];
|
|
2406
|
-
const isOutside = leftToRight ? point <= float32Array2[c2 + splitAxis] : (
|
|
2407
|
-
// min bounding data
|
|
2408
|
-
point >= float32Array2[c2 + splitAxis + 3]
|
|
2409
|
-
);
|
|
2410
|
-
if (isOutside) {
|
|
2411
|
-
return c1Result;
|
|
2412
|
-
}
|
|
2413
|
-
}
|
|
2414
|
-
const c2Intersection = intersectRay(c2, float32Array2, ray2, near, far);
|
|
2415
|
-
const c2Result = c2Intersection ? _raycastFirst(c2, bvh, side, ray2, near, far) : null;
|
|
2416
|
-
if (c1Result && c2Result) {
|
|
2417
|
-
return c1Result.distance <= c2Result.distance ? c1Result : c2Result;
|
|
2418
|
-
} else {
|
|
2419
|
-
return c1Result || c2Result || null;
|
|
2420
|
-
}
|
|
2421
|
-
}
|
|
2422
|
-
}
|
|
2423
|
-
const boundingBox = /* @__PURE__ */ new Box3();
|
|
2424
|
-
const triangle = /* @__PURE__ */ new ExtendedTriangle();
|
|
2425
|
-
const triangle2 = /* @__PURE__ */ new ExtendedTriangle();
|
|
2426
|
-
const invertedMat = /* @__PURE__ */ new Matrix4();
|
|
2427
|
-
const obb$2 = /* @__PURE__ */ new OrientedBox();
|
|
2428
|
-
const obb2$1 = /* @__PURE__ */ new OrientedBox();
|
|
2429
|
-
function intersectsGeometry_indirect(bvh, root, otherGeometry, geometryToBvh) {
|
|
2430
|
-
BufferStack.setBuffer(bvh._roots[root]);
|
|
2431
|
-
const result = _intersectsGeometry(0, bvh, otherGeometry, geometryToBvh);
|
|
2432
|
-
BufferStack.clearBuffer();
|
|
2433
|
-
return result;
|
|
2434
|
-
}
|
|
2435
|
-
function _intersectsGeometry(nodeIndex32, bvh, otherGeometry, geometryToBvh, cachedObb = null) {
|
|
2436
|
-
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
2437
|
-
let nodeIndex16 = nodeIndex32 * 2;
|
|
2438
|
-
if (cachedObb === null) {
|
|
2439
|
-
if (!otherGeometry.boundingBox) {
|
|
2440
|
-
otherGeometry.computeBoundingBox();
|
|
2441
|
-
}
|
|
2442
|
-
obb$2.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
|
|
2443
|
-
cachedObb = obb$2;
|
|
2444
|
-
}
|
|
2445
|
-
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
2446
|
-
if (isLeaf) {
|
|
2447
|
-
const thisGeometry = bvh.geometry;
|
|
2448
|
-
const thisIndex = thisGeometry.index;
|
|
2449
|
-
const thisPos = thisGeometry.attributes.position;
|
|
2450
|
-
const index2 = otherGeometry.index;
|
|
2451
|
-
const pos = otherGeometry.attributes.position;
|
|
2452
|
-
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
2453
|
-
const count = COUNT(nodeIndex16, uint16Array2);
|
|
2454
|
-
invertedMat.copy(geometryToBvh).invert();
|
|
2455
|
-
if (otherGeometry.boundsTree) {
|
|
2456
|
-
arrayToBox(BOUNDING_DATA_INDEX(nodeIndex32), float32Array2, obb2$1);
|
|
2457
|
-
obb2$1.matrix.copy(invertedMat);
|
|
2458
|
-
obb2$1.needsUpdate = true;
|
|
2459
|
-
const res = otherGeometry.boundsTree.shapecast({
|
|
2460
|
-
intersectsBounds: (box) => obb2$1.intersectsBox(box),
|
|
2461
|
-
intersectsTriangle: (tri) => {
|
|
2462
|
-
tri.a.applyMatrix4(geometryToBvh);
|
|
2463
|
-
tri.b.applyMatrix4(geometryToBvh);
|
|
2464
|
-
tri.c.applyMatrix4(geometryToBvh);
|
|
2465
|
-
tri.needsUpdate = true;
|
|
2466
|
-
for (let i = offset, l = count + offset; i < l; i++) {
|
|
2467
|
-
setTriangle(triangle2, 3 * bvh.resolveTriangleIndex(i), thisIndex, thisPos);
|
|
2468
|
-
triangle2.needsUpdate = true;
|
|
2469
|
-
if (tri.intersectsTriangle(triangle2)) {
|
|
2470
|
-
return true;
|
|
2471
|
-
}
|
|
2472
|
-
}
|
|
2473
|
-
return false;
|
|
2474
|
-
}
|
|
2475
|
-
});
|
|
2476
|
-
return res;
|
|
2477
|
-
} else {
|
|
2478
|
-
for (let i = offset, l = count + offset; i < l; i++) {
|
|
2479
|
-
const ti = bvh.resolveTriangleIndex(i);
|
|
2480
|
-
setTriangle(triangle, 3 * ti, thisIndex, thisPos);
|
|
2481
|
-
triangle.a.applyMatrix4(invertedMat);
|
|
2482
|
-
triangle.b.applyMatrix4(invertedMat);
|
|
2483
|
-
triangle.c.applyMatrix4(invertedMat);
|
|
2484
|
-
triangle.needsUpdate = true;
|
|
2485
|
-
for (let i2 = 0, l2 = index2.count; i2 < l2; i2 += 3) {
|
|
2486
|
-
setTriangle(triangle2, i2, index2, pos);
|
|
2487
|
-
triangle2.needsUpdate = true;
|
|
2488
|
-
if (triangle.intersectsTriangle(triangle2)) {
|
|
2489
|
-
return true;
|
|
2490
|
-
}
|
|
2491
|
-
}
|
|
2492
|
-
}
|
|
2493
|
-
}
|
|
2494
|
-
} else {
|
|
2495
|
-
const left = nodeIndex32 + 8;
|
|
2496
|
-
const right = uint32Array2[nodeIndex32 + 6];
|
|
2497
|
-
arrayToBox(BOUNDING_DATA_INDEX(left), float32Array2, boundingBox);
|
|
2498
|
-
const leftIntersection = cachedObb.intersectsBox(boundingBox) && _intersectsGeometry(left, bvh, otherGeometry, geometryToBvh, cachedObb);
|
|
2499
|
-
if (leftIntersection) return true;
|
|
2500
|
-
arrayToBox(BOUNDING_DATA_INDEX(right), float32Array2, boundingBox);
|
|
2501
|
-
const rightIntersection = cachedObb.intersectsBox(boundingBox) && _intersectsGeometry(right, bvh, otherGeometry, geometryToBvh, cachedObb);
|
|
2502
|
-
if (rightIntersection) return true;
|
|
2503
|
-
return false;
|
|
2504
|
-
}
|
|
2505
|
-
}
|
|
2506
|
-
const tempMatrix = /* @__PURE__ */ new Matrix4();
|
|
2507
|
-
const obb$1 = /* @__PURE__ */ new OrientedBox();
|
|
2508
|
-
const obb2 = /* @__PURE__ */ new OrientedBox();
|
|
2509
|
-
const temp1 = /* @__PURE__ */ new Vector3();
|
|
2510
|
-
const temp2 = /* @__PURE__ */ new Vector3();
|
|
2511
|
-
const temp3 = /* @__PURE__ */ new Vector3();
|
|
2512
|
-
const temp4 = /* @__PURE__ */ new Vector3();
|
|
2513
|
-
function closestPointToGeometry_indirect(bvh, otherGeometry, geometryToBvh, target1 = {}, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
2514
|
-
if (!otherGeometry.boundingBox) {
|
|
2515
|
-
otherGeometry.computeBoundingBox();
|
|
2516
|
-
}
|
|
2517
|
-
obb$1.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
|
|
2518
|
-
obb$1.needsUpdate = true;
|
|
2519
|
-
const geometry = bvh.geometry;
|
|
2520
|
-
const pos = geometry.attributes.position;
|
|
2521
|
-
const index2 = geometry.index;
|
|
2522
|
-
const otherPos = otherGeometry.attributes.position;
|
|
2523
|
-
const otherIndex = otherGeometry.index;
|
|
2524
|
-
const triangle3 = ExtendedTrianglePool.getPrimitive();
|
|
2525
|
-
const triangle22 = ExtendedTrianglePool.getPrimitive();
|
|
2526
|
-
let tempTarget1 = temp1;
|
|
2527
|
-
let tempTargetDest1 = temp2;
|
|
2528
|
-
let tempTarget2 = null;
|
|
2529
|
-
let tempTargetDest2 = null;
|
|
2530
|
-
if (target2) {
|
|
2531
|
-
tempTarget2 = temp3;
|
|
2532
|
-
tempTargetDest2 = temp4;
|
|
2533
|
-
}
|
|
2534
|
-
let closestDistance = Infinity;
|
|
2535
|
-
let closestDistanceTriIndex = null;
|
|
2536
|
-
let closestDistanceOtherTriIndex = null;
|
|
2537
|
-
tempMatrix.copy(geometryToBvh).invert();
|
|
2538
|
-
obb2.matrix.copy(tempMatrix);
|
|
2539
|
-
bvh.shapecast(
|
|
2540
|
-
{
|
|
2541
|
-
boundsTraverseOrder: (box) => {
|
|
2542
|
-
return obb$1.distanceToBox(box);
|
|
2543
|
-
},
|
|
2544
|
-
intersectsBounds: (box, isLeaf, score) => {
|
|
2545
|
-
if (score < closestDistance && score < maxThreshold) {
|
|
2546
|
-
if (isLeaf) {
|
|
2547
|
-
obb2.min.copy(box.min);
|
|
2548
|
-
obb2.max.copy(box.max);
|
|
2549
|
-
obb2.needsUpdate = true;
|
|
2550
|
-
}
|
|
2551
|
-
return true;
|
|
2552
|
-
}
|
|
2553
|
-
return false;
|
|
2554
|
-
},
|
|
2555
|
-
intersectsRange: (offset, count) => {
|
|
2556
|
-
if (otherGeometry.boundsTree) {
|
|
2557
|
-
const otherBvh = otherGeometry.boundsTree;
|
|
2558
|
-
return otherBvh.shapecast({
|
|
2559
|
-
boundsTraverseOrder: (box) => {
|
|
2560
|
-
return obb2.distanceToBox(box);
|
|
2561
|
-
},
|
|
2562
|
-
intersectsBounds: (box, isLeaf, score) => {
|
|
2563
|
-
return score < closestDistance && score < maxThreshold;
|
|
2564
|
-
},
|
|
2565
|
-
intersectsRange: (otherOffset, otherCount) => {
|
|
2566
|
-
for (let i2 = otherOffset, l2 = otherOffset + otherCount; i2 < l2; i2++) {
|
|
2567
|
-
const ti2 = otherBvh.resolveTriangleIndex(i2);
|
|
2568
|
-
setTriangle(triangle22, 3 * ti2, otherIndex, otherPos);
|
|
2569
|
-
triangle22.a.applyMatrix4(geometryToBvh);
|
|
2570
|
-
triangle22.b.applyMatrix4(geometryToBvh);
|
|
2571
|
-
triangle22.c.applyMatrix4(geometryToBvh);
|
|
2572
|
-
triangle22.needsUpdate = true;
|
|
2573
|
-
for (let i = offset, l = offset + count; i < l; i++) {
|
|
2574
|
-
const ti = bvh.resolveTriangleIndex(i);
|
|
2575
|
-
setTriangle(triangle3, 3 * ti, index2, pos);
|
|
2576
|
-
triangle3.needsUpdate = true;
|
|
2577
|
-
const dist = triangle3.distanceToTriangle(triangle22, tempTarget1, tempTarget2);
|
|
2578
|
-
if (dist < closestDistance) {
|
|
2579
|
-
tempTargetDest1.copy(tempTarget1);
|
|
2580
|
-
if (tempTargetDest2) {
|
|
2581
|
-
tempTargetDest2.copy(tempTarget2);
|
|
2582
|
-
}
|
|
2583
|
-
closestDistance = dist;
|
|
2584
|
-
closestDistanceTriIndex = i;
|
|
2585
|
-
closestDistanceOtherTriIndex = i2;
|
|
2586
|
-
}
|
|
2587
|
-
if (dist < minThreshold) {
|
|
2588
|
-
return true;
|
|
2589
|
-
}
|
|
2590
|
-
}
|
|
2591
|
-
}
|
|
2592
|
-
}
|
|
2593
|
-
});
|
|
2594
|
-
} else {
|
|
2595
|
-
const triCount = getTriCount(otherGeometry);
|
|
2596
|
-
for (let i2 = 0, l2 = triCount; i2 < l2; i2++) {
|
|
2597
|
-
setTriangle(triangle22, 3 * i2, otherIndex, otherPos);
|
|
2598
|
-
triangle22.a.applyMatrix4(geometryToBvh);
|
|
2599
|
-
triangle22.b.applyMatrix4(geometryToBvh);
|
|
2600
|
-
triangle22.c.applyMatrix4(geometryToBvh);
|
|
2601
|
-
triangle22.needsUpdate = true;
|
|
2602
|
-
for (let i = offset, l = offset + count; i < l; i++) {
|
|
2603
|
-
const ti = bvh.resolveTriangleIndex(i);
|
|
2604
|
-
setTriangle(triangle3, 3 * ti, index2, pos);
|
|
2605
|
-
triangle3.needsUpdate = true;
|
|
2606
|
-
const dist = triangle3.distanceToTriangle(triangle22, tempTarget1, tempTarget2);
|
|
2607
|
-
if (dist < closestDistance) {
|
|
2608
|
-
tempTargetDest1.copy(tempTarget1);
|
|
2609
|
-
if (tempTargetDest2) {
|
|
2610
|
-
tempTargetDest2.copy(tempTarget2);
|
|
2611
|
-
}
|
|
2612
|
-
closestDistance = dist;
|
|
2613
|
-
closestDistanceTriIndex = i;
|
|
2614
|
-
closestDistanceOtherTriIndex = i2;
|
|
2615
|
-
}
|
|
2616
|
-
if (dist < minThreshold) {
|
|
2617
|
-
return true;
|
|
2618
|
-
}
|
|
2619
|
-
}
|
|
2620
|
-
}
|
|
2621
|
-
}
|
|
2622
|
-
}
|
|
2623
|
-
}
|
|
2624
|
-
);
|
|
2625
|
-
ExtendedTrianglePool.releasePrimitive(triangle3);
|
|
2626
|
-
ExtendedTrianglePool.releasePrimitive(triangle22);
|
|
2627
|
-
if (closestDistance === Infinity) {
|
|
2628
|
-
return null;
|
|
2629
|
-
}
|
|
2630
|
-
if (!target1.point) {
|
|
2631
|
-
target1.point = tempTargetDest1.clone();
|
|
2632
|
-
} else {
|
|
2633
|
-
target1.point.copy(tempTargetDest1);
|
|
2634
|
-
}
|
|
2635
|
-
target1.distance = closestDistance, target1.faceIndex = closestDistanceTriIndex;
|
|
2636
|
-
if (target2) {
|
|
2637
|
-
if (!target2.point) target2.point = tempTargetDest2.clone();
|
|
2638
|
-
else target2.point.copy(tempTargetDest2);
|
|
2639
|
-
target2.point.applyMatrix4(tempMatrix);
|
|
2640
|
-
tempTargetDest1.applyMatrix4(tempMatrix);
|
|
2641
|
-
target2.distance = tempTargetDest1.sub(target2.point).length();
|
|
2642
|
-
target2.faceIndex = closestDistanceOtherTriIndex;
|
|
2643
|
-
}
|
|
2644
|
-
return target1;
|
|
2645
|
-
}
|
|
2646
|
-
function isSharedArrayBufferSupported() {
|
|
2647
|
-
return typeof SharedArrayBuffer !== "undefined";
|
|
2648
|
-
}
|
|
2649
|
-
const _bufferStack1 = new BufferStack.constructor();
|
|
2650
|
-
const _bufferStack2 = new BufferStack.constructor();
|
|
2651
|
-
const _boxPool = new PrimitivePool(() => new Box3());
|
|
2652
|
-
const _leftBox1 = new Box3();
|
|
2653
|
-
const _rightBox1 = new Box3();
|
|
2654
|
-
const _leftBox2 = new Box3();
|
|
2655
|
-
const _rightBox2 = new Box3();
|
|
2656
|
-
let _active = false;
|
|
2657
|
-
function bvhcast(bvh, otherBvh, matrixToLocal, intersectsRanges) {
|
|
2658
|
-
if (_active) {
|
|
2659
|
-
throw new Error("MeshBVH: Recursive calls to bvhcast not supported.");
|
|
2660
|
-
}
|
|
2661
|
-
_active = true;
|
|
2662
|
-
const roots = bvh._roots;
|
|
2663
|
-
const otherRoots = otherBvh._roots;
|
|
2664
|
-
let result;
|
|
2665
|
-
let offset1 = 0;
|
|
2666
|
-
let offset2 = 0;
|
|
2667
|
-
const invMat = new Matrix4().copy(matrixToLocal).invert();
|
|
2668
|
-
for (let i = 0, il = roots.length; i < il; i++) {
|
|
2669
|
-
_bufferStack1.setBuffer(roots[i]);
|
|
2670
|
-
offset2 = 0;
|
|
2671
|
-
const localBox = _boxPool.getPrimitive();
|
|
2672
|
-
arrayToBox(BOUNDING_DATA_INDEX(0), _bufferStack1.float32Array, localBox);
|
|
2673
|
-
localBox.applyMatrix4(invMat);
|
|
2674
|
-
for (let j = 0, jl = otherRoots.length; j < jl; j++) {
|
|
2675
|
-
_bufferStack2.setBuffer(otherRoots[j]);
|
|
2676
|
-
result = _traverse(
|
|
2677
|
-
0,
|
|
2678
|
-
0,
|
|
2679
|
-
matrixToLocal,
|
|
2680
|
-
invMat,
|
|
2681
|
-
intersectsRanges,
|
|
2682
|
-
offset1,
|
|
2683
|
-
offset2,
|
|
2684
|
-
0,
|
|
2685
|
-
0,
|
|
2686
|
-
localBox
|
|
2687
|
-
);
|
|
2688
|
-
_bufferStack2.clearBuffer();
|
|
2689
|
-
offset2 += otherRoots[j].length;
|
|
2690
|
-
if (result) {
|
|
2691
|
-
break;
|
|
2692
|
-
}
|
|
2693
|
-
}
|
|
2694
|
-
_boxPool.releasePrimitive(localBox);
|
|
2695
|
-
_bufferStack1.clearBuffer();
|
|
2696
|
-
offset1 += roots[i].length;
|
|
2697
|
-
if (result) {
|
|
2698
|
-
break;
|
|
2699
|
-
}
|
|
2700
|
-
}
|
|
2701
|
-
_active = false;
|
|
2702
|
-
return result;
|
|
2703
|
-
}
|
|
2704
|
-
function _traverse(node1Index32, node2Index32, matrix2to1, matrix1to2, intersectsRangesFunc, node1IndexByteOffset = 0, node2IndexByteOffset = 0, depth1 = 0, depth2 = 0, currBox = null, reversed = false) {
|
|
2705
|
-
let bufferStack1, bufferStack2;
|
|
2706
|
-
if (reversed) {
|
|
2707
|
-
bufferStack1 = _bufferStack2;
|
|
2708
|
-
bufferStack2 = _bufferStack1;
|
|
2709
|
-
} else {
|
|
2710
|
-
bufferStack1 = _bufferStack1;
|
|
2711
|
-
bufferStack2 = _bufferStack2;
|
|
2712
|
-
}
|
|
2713
|
-
const float32Array1 = bufferStack1.float32Array, uint32Array1 = bufferStack1.uint32Array, uint16Array1 = bufferStack1.uint16Array, float32Array2 = bufferStack2.float32Array, uint32Array2 = bufferStack2.uint32Array, uint16Array2 = bufferStack2.uint16Array;
|
|
2714
|
-
const node1Index16 = node1Index32 * 2;
|
|
2715
|
-
const node2Index16 = node2Index32 * 2;
|
|
2716
|
-
const isLeaf1 = IS_LEAF(node1Index16, uint16Array1);
|
|
2717
|
-
const isLeaf2 = IS_LEAF(node2Index16, uint16Array2);
|
|
2718
|
-
let result = false;
|
|
2719
|
-
if (isLeaf2 && isLeaf1) {
|
|
2720
|
-
if (reversed) {
|
|
2721
|
-
result = intersectsRangesFunc(
|
|
2722
|
-
OFFSET(node2Index32, uint32Array2),
|
|
2723
|
-
COUNT(node2Index32 * 2, uint16Array2),
|
|
2724
|
-
OFFSET(node1Index32, uint32Array1),
|
|
2725
|
-
COUNT(node1Index32 * 2, uint16Array1),
|
|
2726
|
-
depth2,
|
|
2727
|
-
node2IndexByteOffset + node2Index32,
|
|
2728
|
-
depth1,
|
|
2729
|
-
node1IndexByteOffset + node1Index32
|
|
2730
|
-
);
|
|
2731
|
-
} else {
|
|
2732
|
-
result = intersectsRangesFunc(
|
|
2733
|
-
OFFSET(node1Index32, uint32Array1),
|
|
2734
|
-
COUNT(node1Index32 * 2, uint16Array1),
|
|
2735
|
-
OFFSET(node2Index32, uint32Array2),
|
|
2736
|
-
COUNT(node2Index32 * 2, uint16Array2),
|
|
2737
|
-
depth1,
|
|
2738
|
-
node1IndexByteOffset + node1Index32,
|
|
2739
|
-
depth2,
|
|
2740
|
-
node2IndexByteOffset + node2Index32
|
|
2741
|
-
);
|
|
2742
|
-
}
|
|
2743
|
-
} else if (isLeaf2) {
|
|
2744
|
-
const newBox = _boxPool.getPrimitive();
|
|
2745
|
-
arrayToBox(BOUNDING_DATA_INDEX(node2Index32), float32Array2, newBox);
|
|
2746
|
-
newBox.applyMatrix4(matrix2to1);
|
|
2747
|
-
const cl1 = LEFT_NODE(node1Index32);
|
|
2748
|
-
const cr1 = RIGHT_NODE(node1Index32, uint32Array1);
|
|
2749
|
-
arrayToBox(BOUNDING_DATA_INDEX(cl1), float32Array1, _leftBox1);
|
|
2750
|
-
arrayToBox(BOUNDING_DATA_INDEX(cr1), float32Array1, _rightBox1);
|
|
2751
|
-
const intersectCl1 = newBox.intersectsBox(_leftBox1);
|
|
2752
|
-
const intersectCr1 = newBox.intersectsBox(_rightBox1);
|
|
2753
|
-
result = intersectCl1 && _traverse(
|
|
2754
|
-
node2Index32,
|
|
2755
|
-
cl1,
|
|
2756
|
-
matrix1to2,
|
|
2757
|
-
matrix2to1,
|
|
2758
|
-
intersectsRangesFunc,
|
|
2759
|
-
node2IndexByteOffset,
|
|
2760
|
-
node1IndexByteOffset,
|
|
2761
|
-
depth2,
|
|
2762
|
-
depth1 + 1,
|
|
2763
|
-
newBox,
|
|
2764
|
-
!reversed
|
|
2765
|
-
) || intersectCr1 && _traverse(
|
|
2766
|
-
node2Index32,
|
|
2767
|
-
cr1,
|
|
2768
|
-
matrix1to2,
|
|
2769
|
-
matrix2to1,
|
|
2770
|
-
intersectsRangesFunc,
|
|
2771
|
-
node2IndexByteOffset,
|
|
2772
|
-
node1IndexByteOffset,
|
|
2773
|
-
depth2,
|
|
2774
|
-
depth1 + 1,
|
|
2775
|
-
newBox,
|
|
2776
|
-
!reversed
|
|
2777
|
-
);
|
|
2778
|
-
_boxPool.releasePrimitive(newBox);
|
|
2779
|
-
} else {
|
|
2780
|
-
const cl2 = LEFT_NODE(node2Index32);
|
|
2781
|
-
const cr2 = RIGHT_NODE(node2Index32, uint32Array2);
|
|
2782
|
-
arrayToBox(BOUNDING_DATA_INDEX(cl2), float32Array2, _leftBox2);
|
|
2783
|
-
arrayToBox(BOUNDING_DATA_INDEX(cr2), float32Array2, _rightBox2);
|
|
2784
|
-
const leftIntersects = currBox.intersectsBox(_leftBox2);
|
|
2785
|
-
const rightIntersects = currBox.intersectsBox(_rightBox2);
|
|
2786
|
-
if (leftIntersects && rightIntersects) {
|
|
2787
|
-
result = _traverse(
|
|
2788
|
-
node1Index32,
|
|
2789
|
-
cl2,
|
|
2790
|
-
matrix2to1,
|
|
2791
|
-
matrix1to2,
|
|
2792
|
-
intersectsRangesFunc,
|
|
2793
|
-
node1IndexByteOffset,
|
|
2794
|
-
node2IndexByteOffset,
|
|
2795
|
-
depth1,
|
|
2796
|
-
depth2 + 1,
|
|
2797
|
-
currBox,
|
|
2798
|
-
reversed
|
|
2799
|
-
) || _traverse(
|
|
2800
|
-
node1Index32,
|
|
2801
|
-
cr2,
|
|
2802
|
-
matrix2to1,
|
|
2803
|
-
matrix1to2,
|
|
2804
|
-
intersectsRangesFunc,
|
|
2805
|
-
node1IndexByteOffset,
|
|
2806
|
-
node2IndexByteOffset,
|
|
2807
|
-
depth1,
|
|
2808
|
-
depth2 + 1,
|
|
2809
|
-
currBox,
|
|
2810
|
-
reversed
|
|
2811
|
-
);
|
|
2812
|
-
} else if (leftIntersects) {
|
|
2813
|
-
if (isLeaf1) {
|
|
2814
|
-
result = _traverse(
|
|
2815
|
-
node1Index32,
|
|
2816
|
-
cl2,
|
|
2817
|
-
matrix2to1,
|
|
2818
|
-
matrix1to2,
|
|
2819
|
-
intersectsRangesFunc,
|
|
2820
|
-
node1IndexByteOffset,
|
|
2821
|
-
node2IndexByteOffset,
|
|
2822
|
-
depth1,
|
|
2823
|
-
depth2 + 1,
|
|
2824
|
-
currBox,
|
|
2825
|
-
reversed
|
|
2826
|
-
);
|
|
2827
|
-
} else {
|
|
2828
|
-
const newBox = _boxPool.getPrimitive();
|
|
2829
|
-
newBox.copy(_leftBox2).applyMatrix4(matrix2to1);
|
|
2830
|
-
const cl1 = LEFT_NODE(node1Index32);
|
|
2831
|
-
const cr1 = RIGHT_NODE(node1Index32, uint32Array1);
|
|
2832
|
-
arrayToBox(BOUNDING_DATA_INDEX(cl1), float32Array1, _leftBox1);
|
|
2833
|
-
arrayToBox(BOUNDING_DATA_INDEX(cr1), float32Array1, _rightBox1);
|
|
2834
|
-
const intersectCl1 = newBox.intersectsBox(_leftBox1);
|
|
2835
|
-
const intersectCr1 = newBox.intersectsBox(_rightBox1);
|
|
2836
|
-
result = intersectCl1 && _traverse(
|
|
2837
|
-
cl2,
|
|
2838
|
-
cl1,
|
|
2839
|
-
matrix1to2,
|
|
2840
|
-
matrix2to1,
|
|
2841
|
-
intersectsRangesFunc,
|
|
2842
|
-
node2IndexByteOffset,
|
|
2843
|
-
node1IndexByteOffset,
|
|
2844
|
-
depth2,
|
|
2845
|
-
depth1 + 1,
|
|
2846
|
-
newBox,
|
|
2847
|
-
!reversed
|
|
2848
|
-
) || intersectCr1 && _traverse(
|
|
2849
|
-
cl2,
|
|
2850
|
-
cr1,
|
|
2851
|
-
matrix1to2,
|
|
2852
|
-
matrix2to1,
|
|
2853
|
-
intersectsRangesFunc,
|
|
2854
|
-
node2IndexByteOffset,
|
|
2855
|
-
node1IndexByteOffset,
|
|
2856
|
-
depth2,
|
|
2857
|
-
depth1 + 1,
|
|
2858
|
-
newBox,
|
|
2859
|
-
!reversed
|
|
2860
|
-
);
|
|
2861
|
-
_boxPool.releasePrimitive(newBox);
|
|
2862
|
-
}
|
|
2863
|
-
} else if (rightIntersects) {
|
|
2864
|
-
if (isLeaf1) {
|
|
2865
|
-
result = _traverse(
|
|
2866
|
-
node1Index32,
|
|
2867
|
-
cr2,
|
|
2868
|
-
matrix2to1,
|
|
2869
|
-
matrix1to2,
|
|
2870
|
-
intersectsRangesFunc,
|
|
2871
|
-
node1IndexByteOffset,
|
|
2872
|
-
node2IndexByteOffset,
|
|
2873
|
-
depth1,
|
|
2874
|
-
depth2 + 1,
|
|
2875
|
-
currBox,
|
|
2876
|
-
reversed
|
|
2877
|
-
);
|
|
2878
|
-
} else {
|
|
2879
|
-
const newBox = _boxPool.getPrimitive();
|
|
2880
|
-
newBox.copy(_rightBox2).applyMatrix4(matrix2to1);
|
|
2881
|
-
const cl1 = LEFT_NODE(node1Index32);
|
|
2882
|
-
const cr1 = RIGHT_NODE(node1Index32, uint32Array1);
|
|
2883
|
-
arrayToBox(BOUNDING_DATA_INDEX(cl1), float32Array1, _leftBox1);
|
|
2884
|
-
arrayToBox(BOUNDING_DATA_INDEX(cr1), float32Array1, _rightBox1);
|
|
2885
|
-
const intersectCl1 = newBox.intersectsBox(_leftBox1);
|
|
2886
|
-
const intersectCr1 = newBox.intersectsBox(_rightBox1);
|
|
2887
|
-
result = intersectCl1 && _traverse(
|
|
2888
|
-
cr2,
|
|
2889
|
-
cl1,
|
|
2890
|
-
matrix1to2,
|
|
2891
|
-
matrix2to1,
|
|
2892
|
-
intersectsRangesFunc,
|
|
2893
|
-
node2IndexByteOffset,
|
|
2894
|
-
node1IndexByteOffset,
|
|
2895
|
-
depth2,
|
|
2896
|
-
depth1 + 1,
|
|
2897
|
-
newBox,
|
|
2898
|
-
!reversed
|
|
2899
|
-
) || intersectCr1 && _traverse(
|
|
2900
|
-
cr2,
|
|
2901
|
-
cr1,
|
|
2902
|
-
matrix1to2,
|
|
2903
|
-
matrix2to1,
|
|
2904
|
-
intersectsRangesFunc,
|
|
2905
|
-
node2IndexByteOffset,
|
|
2906
|
-
node1IndexByteOffset,
|
|
2907
|
-
depth2,
|
|
2908
|
-
depth1 + 1,
|
|
2909
|
-
newBox,
|
|
2910
|
-
!reversed
|
|
2911
|
-
);
|
|
2912
|
-
_boxPool.releasePrimitive(newBox);
|
|
2913
|
-
}
|
|
2914
|
-
}
|
|
2915
|
-
}
|
|
2916
|
-
return result;
|
|
2917
|
-
}
|
|
2918
|
-
const obb = /* @__PURE__ */ new OrientedBox();
|
|
2919
|
-
const tempBox = /* @__PURE__ */ new Box3();
|
|
2920
|
-
const DEFAULT_OPTIONS = {
|
|
2921
|
-
strategy: CENTER,
|
|
2922
|
-
maxDepth: 40,
|
|
2923
|
-
maxLeafTris: 10,
|
|
2924
|
-
useSharedArrayBuffer: false,
|
|
2925
|
-
setBoundingBox: true,
|
|
2926
|
-
onProgress: null,
|
|
2927
|
-
indirect: false,
|
|
2928
|
-
verbose: true,
|
|
2929
|
-
range: null
|
|
2930
|
-
};
|
|
2931
|
-
class MeshBVH {
|
|
2932
|
-
static serialize(bvh, options = {}) {
|
|
2933
|
-
options = {
|
|
2934
|
-
cloneBuffers: true,
|
|
2935
|
-
...options
|
|
2936
|
-
};
|
|
2937
|
-
const geometry = bvh.geometry;
|
|
2938
|
-
const rootData = bvh._roots;
|
|
2939
|
-
const indirectBuffer = bvh._indirectBuffer;
|
|
2940
|
-
const indexAttribute = geometry.getIndex();
|
|
2941
|
-
let result;
|
|
2942
|
-
if (options.cloneBuffers) {
|
|
2943
|
-
result = {
|
|
2944
|
-
roots: rootData.map((root) => root.slice()),
|
|
2945
|
-
index: indexAttribute ? indexAttribute.array.slice() : null,
|
|
2946
|
-
indirectBuffer: indirectBuffer ? indirectBuffer.slice() : null
|
|
2947
|
-
};
|
|
2948
|
-
} else {
|
|
2949
|
-
result = {
|
|
2950
|
-
roots: rootData,
|
|
2951
|
-
index: indexAttribute ? indexAttribute.array : null,
|
|
2952
|
-
indirectBuffer
|
|
2953
|
-
};
|
|
2954
|
-
}
|
|
2955
|
-
return result;
|
|
2956
|
-
}
|
|
2957
|
-
static deserialize(data, geometry, options = {}) {
|
|
2958
|
-
options = {
|
|
2959
|
-
setIndex: true,
|
|
2960
|
-
indirect: Boolean(data.indirectBuffer),
|
|
2961
|
-
...options
|
|
2962
|
-
};
|
|
2963
|
-
const { index: index2, roots, indirectBuffer } = data;
|
|
2964
|
-
const bvh = new MeshBVH(geometry, { ...options, [SKIP_GENERATION]: true });
|
|
2965
|
-
bvh._roots = roots;
|
|
2966
|
-
bvh._indirectBuffer = indirectBuffer || null;
|
|
2967
|
-
if (options.setIndex) {
|
|
2968
|
-
const indexAttribute = geometry.getIndex();
|
|
2969
|
-
if (indexAttribute === null) {
|
|
2970
|
-
const newIndex = new BufferAttribute(data.index, 1, false);
|
|
2971
|
-
geometry.setIndex(newIndex);
|
|
2972
|
-
} else if (indexAttribute.array !== index2) {
|
|
2973
|
-
indexAttribute.array.set(index2);
|
|
2974
|
-
indexAttribute.needsUpdate = true;
|
|
2975
|
-
}
|
|
2976
|
-
}
|
|
2977
|
-
return bvh;
|
|
2978
|
-
}
|
|
2979
|
-
get indirect() {
|
|
2980
|
-
return !!this._indirectBuffer;
|
|
2981
|
-
}
|
|
2982
|
-
constructor(geometry, options = {}) {
|
|
2983
|
-
if (!geometry.isBufferGeometry) {
|
|
2984
|
-
throw new Error("MeshBVH: Only BufferGeometries are supported.");
|
|
2985
|
-
} else if (geometry.index && geometry.index.isInterleavedBufferAttribute) {
|
|
2986
|
-
throw new Error("MeshBVH: InterleavedBufferAttribute is not supported for the index attribute.");
|
|
2987
|
-
}
|
|
2988
|
-
options = Object.assign({
|
|
2989
|
-
...DEFAULT_OPTIONS,
|
|
2990
|
-
// undocumented options
|
|
2991
|
-
// Whether to skip generating the tree. Used for deserialization.
|
|
2992
|
-
[SKIP_GENERATION]: false
|
|
2993
|
-
}, options);
|
|
2994
|
-
if (options.useSharedArrayBuffer && !isSharedArrayBufferSupported()) {
|
|
2995
|
-
throw new Error("MeshBVH: SharedArrayBuffer is not available.");
|
|
2996
|
-
}
|
|
2997
|
-
this.geometry = geometry;
|
|
2998
|
-
this._roots = null;
|
|
2999
|
-
this._indirectBuffer = null;
|
|
3000
|
-
if (!options[SKIP_GENERATION]) {
|
|
3001
|
-
buildPackedTree(this, options);
|
|
3002
|
-
if (!geometry.boundingBox && options.setBoundingBox) {
|
|
3003
|
-
geometry.boundingBox = this.getBoundingBox(new Box3());
|
|
3004
|
-
}
|
|
3005
|
-
}
|
|
3006
|
-
this.resolveTriangleIndex = options.indirect ? (i) => this._indirectBuffer[i] : (i) => i;
|
|
3007
|
-
}
|
|
3008
|
-
refit(nodeIndices = null) {
|
|
3009
|
-
const refitFunc = this.indirect ? refit_indirect : refit;
|
|
3010
|
-
return refitFunc(this, nodeIndices);
|
|
3011
|
-
}
|
|
3012
|
-
traverse(callback, rootIndex = 0) {
|
|
3013
|
-
const buffer = this._roots[rootIndex];
|
|
3014
|
-
const uint32Array2 = new Uint32Array(buffer);
|
|
3015
|
-
const uint16Array2 = new Uint16Array(buffer);
|
|
3016
|
-
_traverse2(0);
|
|
3017
|
-
function _traverse2(node32Index, depth = 0) {
|
|
3018
|
-
const node16Index = node32Index * 2;
|
|
3019
|
-
const isLeaf = uint16Array2[node16Index + 15] === IS_LEAFNODE_FLAG;
|
|
3020
|
-
if (isLeaf) {
|
|
3021
|
-
const offset = uint32Array2[node32Index + 6];
|
|
3022
|
-
const count = uint16Array2[node16Index + 14];
|
|
3023
|
-
callback(depth, isLeaf, new Float32Array(buffer, node32Index * 4, 6), offset, count);
|
|
3024
|
-
} else {
|
|
3025
|
-
const left = node32Index + BYTES_PER_NODE / 4;
|
|
3026
|
-
const right = uint32Array2[node32Index + 6];
|
|
3027
|
-
const splitAxis = uint32Array2[node32Index + 7];
|
|
3028
|
-
const stopTraversal = callback(depth, isLeaf, new Float32Array(buffer, node32Index * 4, 6), splitAxis);
|
|
3029
|
-
if (!stopTraversal) {
|
|
3030
|
-
_traverse2(left, depth + 1);
|
|
3031
|
-
_traverse2(right, depth + 1);
|
|
3032
|
-
}
|
|
3033
|
-
}
|
|
3034
|
-
}
|
|
3035
|
-
}
|
|
3036
|
-
/* Core Cast Functions */
|
|
3037
|
-
raycast(ray2, materialOrSide = FrontSide, near = 0, far = Infinity) {
|
|
3038
|
-
const roots = this._roots;
|
|
3039
|
-
const geometry = this.geometry;
|
|
3040
|
-
const intersects = [];
|
|
3041
|
-
const isMaterial = materialOrSide.isMaterial;
|
|
3042
|
-
const isArrayMaterial = Array.isArray(materialOrSide);
|
|
3043
|
-
const groups = geometry.groups;
|
|
3044
|
-
const side = isMaterial ? materialOrSide.side : materialOrSide;
|
|
3045
|
-
const raycastFunc = this.indirect ? raycast_indirect : raycast;
|
|
3046
|
-
for (let i = 0, l = roots.length; i < l; i++) {
|
|
3047
|
-
const materialSide = isArrayMaterial ? materialOrSide[groups[i].materialIndex].side : side;
|
|
3048
|
-
const startCount = intersects.length;
|
|
3049
|
-
raycastFunc(this, i, materialSide, ray2, intersects, near, far);
|
|
3050
|
-
if (isArrayMaterial) {
|
|
3051
|
-
const materialIndex = groups[i].materialIndex;
|
|
3052
|
-
for (let j = startCount, jl = intersects.length; j < jl; j++) {
|
|
3053
|
-
intersects[j].face.materialIndex = materialIndex;
|
|
3054
|
-
}
|
|
3055
|
-
}
|
|
3056
|
-
}
|
|
3057
|
-
return intersects;
|
|
3058
|
-
}
|
|
3059
|
-
raycastFirst(ray2, materialOrSide = FrontSide, near = 0, far = Infinity) {
|
|
3060
|
-
const roots = this._roots;
|
|
3061
|
-
const geometry = this.geometry;
|
|
3062
|
-
const isMaterial = materialOrSide.isMaterial;
|
|
3063
|
-
const isArrayMaterial = Array.isArray(materialOrSide);
|
|
3064
|
-
let closestResult = null;
|
|
3065
|
-
const groups = geometry.groups;
|
|
3066
|
-
const side = isMaterial ? materialOrSide.side : materialOrSide;
|
|
3067
|
-
const raycastFirstFunc = this.indirect ? raycastFirst_indirect : raycastFirst;
|
|
3068
|
-
for (let i = 0, l = roots.length; i < l; i++) {
|
|
3069
|
-
const materialSide = isArrayMaterial ? materialOrSide[groups[i].materialIndex].side : side;
|
|
3070
|
-
const result = raycastFirstFunc(this, i, materialSide, ray2, near, far);
|
|
3071
|
-
if (result != null && (closestResult == null || result.distance < closestResult.distance)) {
|
|
3072
|
-
closestResult = result;
|
|
3073
|
-
if (isArrayMaterial) {
|
|
3074
|
-
result.face.materialIndex = groups[i].materialIndex;
|
|
3075
|
-
}
|
|
3076
|
-
}
|
|
3077
|
-
}
|
|
3078
|
-
return closestResult;
|
|
3079
|
-
}
|
|
3080
|
-
intersectsGeometry(otherGeometry, geomToMesh) {
|
|
3081
|
-
let result = false;
|
|
3082
|
-
const roots = this._roots;
|
|
3083
|
-
const intersectsGeometryFunc = this.indirect ? intersectsGeometry_indirect : intersectsGeometry;
|
|
3084
|
-
for (let i = 0, l = roots.length; i < l; i++) {
|
|
3085
|
-
result = intersectsGeometryFunc(this, i, otherGeometry, geomToMesh);
|
|
3086
|
-
if (result) {
|
|
3087
|
-
break;
|
|
3088
|
-
}
|
|
3089
|
-
}
|
|
3090
|
-
return result;
|
|
3091
|
-
}
|
|
3092
|
-
shapecast(callbacks) {
|
|
3093
|
-
const triangle3 = ExtendedTrianglePool.getPrimitive();
|
|
3094
|
-
const iterateFunc = this.indirect ? iterateOverTriangles_indirect : iterateOverTriangles;
|
|
3095
|
-
let {
|
|
3096
|
-
boundsTraverseOrder,
|
|
3097
|
-
intersectsBounds,
|
|
3098
|
-
intersectsRange,
|
|
3099
|
-
intersectsTriangle
|
|
3100
|
-
} = callbacks;
|
|
3101
|
-
if (intersectsRange && intersectsTriangle) {
|
|
3102
|
-
const originalIntersectsRange = intersectsRange;
|
|
3103
|
-
intersectsRange = (offset, count, contained, depth, nodeIndex) => {
|
|
3104
|
-
if (!originalIntersectsRange(offset, count, contained, depth, nodeIndex)) {
|
|
3105
|
-
return iterateFunc(offset, count, this, intersectsTriangle, contained, depth, triangle3);
|
|
3106
|
-
}
|
|
3107
|
-
return true;
|
|
3108
|
-
};
|
|
3109
|
-
} else if (!intersectsRange) {
|
|
3110
|
-
if (intersectsTriangle) {
|
|
3111
|
-
intersectsRange = (offset, count, contained, depth) => {
|
|
3112
|
-
return iterateFunc(offset, count, this, intersectsTriangle, contained, depth, triangle3);
|
|
3113
|
-
};
|
|
3114
|
-
} else {
|
|
3115
|
-
intersectsRange = (offset, count, contained) => {
|
|
3116
|
-
return contained;
|
|
3117
|
-
};
|
|
3118
|
-
}
|
|
3119
|
-
}
|
|
3120
|
-
let result = false;
|
|
3121
|
-
let byteOffset = 0;
|
|
3122
|
-
const roots = this._roots;
|
|
3123
|
-
for (let i = 0, l = roots.length; i < l; i++) {
|
|
3124
|
-
const root = roots[i];
|
|
3125
|
-
result = shapecast(this, i, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset);
|
|
3126
|
-
if (result) {
|
|
3127
|
-
break;
|
|
3128
|
-
}
|
|
3129
|
-
byteOffset += root.byteLength;
|
|
3130
|
-
}
|
|
3131
|
-
ExtendedTrianglePool.releasePrimitive(triangle3);
|
|
3132
|
-
return result;
|
|
3133
|
-
}
|
|
3134
|
-
bvhcast(otherBvh, matrixToLocal, callbacks) {
|
|
3135
|
-
let {
|
|
3136
|
-
intersectsRanges,
|
|
3137
|
-
intersectsTriangles
|
|
3138
|
-
} = callbacks;
|
|
3139
|
-
const triangle1 = ExtendedTrianglePool.getPrimitive();
|
|
3140
|
-
const indexAttr1 = this.geometry.index;
|
|
3141
|
-
const positionAttr1 = this.geometry.attributes.position;
|
|
3142
|
-
const assignTriangle1 = this.indirect ? (i1) => {
|
|
3143
|
-
const ti = this.resolveTriangleIndex(i1);
|
|
3144
|
-
setTriangle(triangle1, ti * 3, indexAttr1, positionAttr1);
|
|
3145
|
-
} : (i1) => {
|
|
3146
|
-
setTriangle(triangle1, i1 * 3, indexAttr1, positionAttr1);
|
|
3147
|
-
};
|
|
3148
|
-
const triangle22 = ExtendedTrianglePool.getPrimitive();
|
|
3149
|
-
const indexAttr2 = otherBvh.geometry.index;
|
|
3150
|
-
const positionAttr2 = otherBvh.geometry.attributes.position;
|
|
3151
|
-
const assignTriangle2 = otherBvh.indirect ? (i2) => {
|
|
3152
|
-
const ti2 = otherBvh.resolveTriangleIndex(i2);
|
|
3153
|
-
setTriangle(triangle22, ti2 * 3, indexAttr2, positionAttr2);
|
|
3154
|
-
} : (i2) => {
|
|
3155
|
-
setTriangle(triangle22, i2 * 3, indexAttr2, positionAttr2);
|
|
3156
|
-
};
|
|
3157
|
-
if (intersectsTriangles) {
|
|
3158
|
-
const iterateOverDoubleTriangles = (offset1, count1, offset2, count2, depth1, index1, depth2, index2) => {
|
|
3159
|
-
for (let i2 = offset2, l2 = offset2 + count2; i2 < l2; i2++) {
|
|
3160
|
-
assignTriangle2(i2);
|
|
3161
|
-
triangle22.a.applyMatrix4(matrixToLocal);
|
|
3162
|
-
triangle22.b.applyMatrix4(matrixToLocal);
|
|
3163
|
-
triangle22.c.applyMatrix4(matrixToLocal);
|
|
3164
|
-
triangle22.needsUpdate = true;
|
|
3165
|
-
for (let i1 = offset1, l1 = offset1 + count1; i1 < l1; i1++) {
|
|
3166
|
-
assignTriangle1(i1);
|
|
3167
|
-
triangle1.needsUpdate = true;
|
|
3168
|
-
if (intersectsTriangles(triangle1, triangle22, i1, i2, depth1, index1, depth2, index2)) {
|
|
3169
|
-
return true;
|
|
3170
|
-
}
|
|
3171
|
-
}
|
|
3172
|
-
}
|
|
3173
|
-
return false;
|
|
3174
|
-
};
|
|
3175
|
-
if (intersectsRanges) {
|
|
3176
|
-
const originalIntersectsRanges = intersectsRanges;
|
|
3177
|
-
intersectsRanges = function(offset1, count1, offset2, count2, depth1, index1, depth2, index2) {
|
|
3178
|
-
if (!originalIntersectsRanges(offset1, count1, offset2, count2, depth1, index1, depth2, index2)) {
|
|
3179
|
-
return iterateOverDoubleTriangles(offset1, count1, offset2, count2, depth1, index1, depth2, index2);
|
|
3180
|
-
}
|
|
3181
|
-
return true;
|
|
3182
|
-
};
|
|
3183
|
-
} else {
|
|
3184
|
-
intersectsRanges = iterateOverDoubleTriangles;
|
|
3185
|
-
}
|
|
3186
|
-
}
|
|
3187
|
-
return bvhcast(this, otherBvh, matrixToLocal, intersectsRanges);
|
|
3188
|
-
}
|
|
3189
|
-
/* Derived Cast Functions */
|
|
3190
|
-
intersectsBox(box, boxToMesh) {
|
|
3191
|
-
obb.set(box.min, box.max, boxToMesh);
|
|
3192
|
-
obb.needsUpdate = true;
|
|
3193
|
-
return this.shapecast(
|
|
3194
|
-
{
|
|
3195
|
-
intersectsBounds: (box2) => obb.intersectsBox(box2),
|
|
3196
|
-
intersectsTriangle: (tri) => obb.intersectsTriangle(tri)
|
|
3197
|
-
}
|
|
3198
|
-
);
|
|
3199
|
-
}
|
|
3200
|
-
intersectsSphere(sphere) {
|
|
3201
|
-
return this.shapecast(
|
|
3202
|
-
{
|
|
3203
|
-
intersectsBounds: (box) => sphere.intersectsBox(box),
|
|
3204
|
-
intersectsTriangle: (tri) => tri.intersectsSphere(sphere)
|
|
3205
|
-
}
|
|
3206
|
-
);
|
|
3207
|
-
}
|
|
3208
|
-
closestPointToGeometry(otherGeometry, geometryToBvh, target1 = {}, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
3209
|
-
const closestPointToGeometryFunc = this.indirect ? closestPointToGeometry_indirect : closestPointToGeometry;
|
|
3210
|
-
return closestPointToGeometryFunc(
|
|
3211
|
-
this,
|
|
3212
|
-
otherGeometry,
|
|
3213
|
-
geometryToBvh,
|
|
3214
|
-
target1,
|
|
3215
|
-
target2,
|
|
3216
|
-
minThreshold,
|
|
3217
|
-
maxThreshold
|
|
3218
|
-
);
|
|
3219
|
-
}
|
|
3220
|
-
closestPointToPoint(point, target = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
3221
|
-
return closestPointToPoint(
|
|
3222
|
-
this,
|
|
3223
|
-
point,
|
|
3224
|
-
target,
|
|
3225
|
-
minThreshold,
|
|
3226
|
-
maxThreshold
|
|
3227
|
-
);
|
|
3228
|
-
}
|
|
3229
|
-
getBoundingBox(target) {
|
|
3230
|
-
target.makeEmpty();
|
|
3231
|
-
const roots = this._roots;
|
|
3232
|
-
roots.forEach((buffer) => {
|
|
3233
|
-
arrayToBox(0, new Float32Array(buffer), tempBox);
|
|
3234
|
-
target.union(tempBox);
|
|
3235
|
-
});
|
|
3236
|
-
return target;
|
|
3237
|
-
}
|
|
3238
|
-
}
|
|
3239
|
-
function convertRaycastIntersect(hit, object, raycaster) {
|
|
3240
|
-
if (hit === null) {
|
|
3241
|
-
return null;
|
|
3242
|
-
}
|
|
3243
|
-
hit.point.applyMatrix4(object.matrixWorld);
|
|
3244
|
-
hit.distance = hit.point.distanceTo(raycaster.ray.origin);
|
|
3245
|
-
hit.object = object;
|
|
3246
|
-
return hit;
|
|
3247
|
-
}
|
|
3248
|
-
const ray = /* @__PURE__ */ new Ray();
|
|
3249
|
-
const direction = /* @__PURE__ */ new Vector3();
|
|
3250
|
-
const tmpInverseMatrix = /* @__PURE__ */ new Matrix4();
|
|
3251
|
-
const origMeshRaycastFunc = Mesh.prototype.raycast;
|
|
3252
|
-
const origBatchedRaycastFunc = BatchedMesh.prototype.raycast;
|
|
3253
|
-
const _worldScale = /* @__PURE__ */ new Vector3();
|
|
3254
|
-
const _mesh = /* @__PURE__ */ new Mesh();
|
|
3255
|
-
const _batchIntersects = [];
|
|
3256
|
-
function acceleratedRaycast(raycaster, intersects) {
|
|
3257
|
-
if (this.isBatchedMesh) {
|
|
3258
|
-
acceleratedBatchedMeshRaycast.call(this, raycaster, intersects);
|
|
3259
|
-
} else {
|
|
3260
|
-
acceleratedMeshRaycast.call(this, raycaster, intersects);
|
|
3261
|
-
}
|
|
3262
|
-
}
|
|
3263
|
-
function acceleratedBatchedMeshRaycast(raycaster, intersects) {
|
|
3264
|
-
if (this.boundsTrees) {
|
|
3265
|
-
const boundsTrees = this.boundsTrees;
|
|
3266
|
-
const drawInfo = this._drawInfo || this._instanceInfo;
|
|
3267
|
-
const drawRanges = this._drawRanges || this._geometryInfo;
|
|
3268
|
-
const matrixWorld = this.matrixWorld;
|
|
3269
|
-
_mesh.material = this.material;
|
|
3270
|
-
_mesh.geometry = this.geometry;
|
|
3271
|
-
const oldBoundsTree = _mesh.geometry.boundsTree;
|
|
3272
|
-
const oldDrawRange = _mesh.geometry.drawRange;
|
|
3273
|
-
if (_mesh.geometry.boundingSphere === null) {
|
|
3274
|
-
_mesh.geometry.boundingSphere = new Sphere();
|
|
3275
|
-
}
|
|
3276
|
-
for (let i = 0, l = drawInfo.length; i < l; i++) {
|
|
3277
|
-
if (!this.getVisibleAt(i)) {
|
|
3278
|
-
continue;
|
|
3279
|
-
}
|
|
3280
|
-
const geometryId = drawInfo[i].geometryIndex;
|
|
3281
|
-
_mesh.geometry.boundsTree = boundsTrees[geometryId];
|
|
3282
|
-
this.getMatrixAt(i, _mesh.matrixWorld).premultiply(matrixWorld);
|
|
3283
|
-
if (!_mesh.geometry.boundsTree) {
|
|
3284
|
-
this.getBoundingBoxAt(geometryId, _mesh.geometry.boundingBox);
|
|
3285
|
-
this.getBoundingSphereAt(geometryId, _mesh.geometry.boundingSphere);
|
|
3286
|
-
const drawRange = drawRanges[geometryId];
|
|
3287
|
-
_mesh.geometry.setDrawRange(drawRange.start, drawRange.count);
|
|
3288
|
-
}
|
|
3289
|
-
_mesh.raycast(raycaster, _batchIntersects);
|
|
3290
|
-
for (let j = 0, l2 = _batchIntersects.length; j < l2; j++) {
|
|
3291
|
-
const intersect = _batchIntersects[j];
|
|
3292
|
-
intersect.object = this;
|
|
3293
|
-
intersect.batchId = i;
|
|
3294
|
-
intersects.push(intersect);
|
|
3295
|
-
}
|
|
3296
|
-
_batchIntersects.length = 0;
|
|
3297
|
-
}
|
|
3298
|
-
_mesh.geometry.boundsTree = oldBoundsTree;
|
|
3299
|
-
_mesh.geometry.drawRange = oldDrawRange;
|
|
3300
|
-
_mesh.material = null;
|
|
3301
|
-
_mesh.geometry = null;
|
|
3302
|
-
} else {
|
|
3303
|
-
origBatchedRaycastFunc.call(this, raycaster, intersects);
|
|
3304
|
-
}
|
|
3305
|
-
}
|
|
3306
|
-
function acceleratedMeshRaycast(raycaster, intersects) {
|
|
3307
|
-
if (this.geometry.boundsTree) {
|
|
3308
|
-
if (this.material === void 0) return;
|
|
3309
|
-
tmpInverseMatrix.copy(this.matrixWorld).invert();
|
|
3310
|
-
ray.copy(raycaster.ray).applyMatrix4(tmpInverseMatrix);
|
|
3311
|
-
_worldScale.setFromMatrixScale(this.matrixWorld);
|
|
3312
|
-
direction.copy(ray.direction).multiply(_worldScale);
|
|
3313
|
-
const scaleFactor = direction.length();
|
|
3314
|
-
const near = raycaster.near / scaleFactor;
|
|
3315
|
-
const far = raycaster.far / scaleFactor;
|
|
3316
|
-
const bvh = this.geometry.boundsTree;
|
|
3317
|
-
if (raycaster.firstHitOnly === true) {
|
|
3318
|
-
const hit = convertRaycastIntersect(bvh.raycastFirst(ray, this.material, near, far), this, raycaster);
|
|
3319
|
-
if (hit) {
|
|
3320
|
-
intersects.push(hit);
|
|
3321
|
-
}
|
|
3322
|
-
} else {
|
|
3323
|
-
const hits = bvh.raycast(ray, this.material, near, far);
|
|
3324
|
-
for (let i = 0, l = hits.length; i < l; i++) {
|
|
3325
|
-
const hit = convertRaycastIntersect(hits[i], this, raycaster);
|
|
3326
|
-
if (hit) {
|
|
3327
|
-
intersects.push(hit);
|
|
3328
|
-
}
|
|
3329
|
-
}
|
|
3330
|
-
}
|
|
3331
|
-
} else {
|
|
3332
|
-
origMeshRaycastFunc.call(this, raycaster, intersects);
|
|
3333
|
-
}
|
|
3334
|
-
}
|
|
3335
|
-
function computeBoundsTree(options = {}) {
|
|
3336
|
-
this.boundsTree = new MeshBVH(this, options);
|
|
3337
|
-
return this.boundsTree;
|
|
3338
|
-
}
|
|
3339
|
-
function disposeBoundsTree() {
|
|
3340
|
-
this.boundsTree = null;
|
|
3341
|
-
}
|
|
3342
|
-
THREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree;
|
|
3343
|
-
THREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree;
|
|
3344
|
-
THREE.Mesh.prototype.raycast = acceleratedRaycast;
|
|
3345
|
-
THREE.Object3D.DEFAULT_UP = new THREE.Vector3(0, 0, 1);
|
|
3346
|
-
class Renderer extends Component {
|
|
3347
|
-
static name = "Renderer";
|
|
3348
|
-
static CSS2DObject = CSS2DObject;
|
|
3349
|
-
static CSS3DObject = CSS3DObject;
|
|
3350
|
-
static CSS3DSprite = CSS3DSprite;
|
|
3351
|
-
static Group = THREE.Group;
|
|
3352
|
-
static Object3D = THREE.Object3D;
|
|
3353
|
-
static Mesh = THREE.Mesh;
|
|
3354
|
-
static Line = THREE.Line;
|
|
3355
|
-
static LineSegments = THREE.LineSegments;
|
|
3356
|
-
static Points = THREE.Points;
|
|
3357
|
-
scene;
|
|
3358
|
-
camera;
|
|
3359
|
-
renderer;
|
|
3360
|
-
orbitControls;
|
|
3361
|
-
resizeObserver;
|
|
3362
|
-
description;
|
|
3363
|
-
html2DRenderer;
|
|
3364
|
-
html3DRenderer;
|
|
3365
|
-
container = new THREE.Group();
|
|
3366
|
-
onUpdate;
|
|
3367
|
-
onResize;
|
|
3368
|
-
tweenTaskList = [];
|
|
3369
|
-
constructor(description) {
|
|
3370
|
-
super();
|
|
3371
|
-
this.description = description;
|
|
3372
|
-
const {
|
|
3373
|
-
scene = new THREE.Scene(),
|
|
3374
|
-
camera = new THREE.PerspectiveCamera(45, 1, 0.01, 1e3)
|
|
3375
|
-
} = description;
|
|
3376
|
-
this.camera = camera;
|
|
3377
|
-
this.scene = scene;
|
|
3378
|
-
scene.add(this.container);
|
|
3379
|
-
this.renderer = new THREE.WebGLRenderer({
|
|
3380
|
-
canvas: this.description.canvas,
|
|
3381
|
-
antialias: true
|
|
3382
|
-
});
|
|
3383
|
-
this.renderer.setPixelRatio(window.devicePixelRatio);
|
|
3384
|
-
if (description.htmlRenderer) {
|
|
3385
|
-
if (description.htmlRenderer["2d"]) {
|
|
3386
|
-
this.html2DRenderer = new CSS2DRenderer();
|
|
3387
|
-
Object.assign(this.html2DRenderer.domElement.style, { position: "absolute", left: "0px", top: "0px" });
|
|
3388
|
-
description.htmlRenderer["2d"].appendChild(this.html2DRenderer.domElement);
|
|
3389
|
-
}
|
|
3390
|
-
if (description.htmlRenderer["3d"]) {
|
|
3391
|
-
this.html3DRenderer = new CSS3DRenderer();
|
|
3392
|
-
Object.assign(this.html3DRenderer.domElement.style, { position: "absolute", left: "0px", top: "0px" });
|
|
3393
|
-
description.htmlRenderer["3d"].appendChild(this.html3DRenderer.domElement);
|
|
3394
|
-
}
|
|
3395
|
-
}
|
|
3396
|
-
if (description.orbitControls) {
|
|
3397
|
-
this.orbitControls = new OrbitControls(this.camera, description.orbitControls.domElement);
|
|
3398
|
-
Object.assign(this.orbitControls, description.orbitControls);
|
|
3399
|
-
}
|
|
3400
|
-
if (this.description.resizeObserver) {
|
|
3401
|
-
const dom = this.description.resizeObserver;
|
|
3402
|
-
this.resizeObserver = new ResizeObserver(() => {
|
|
3403
|
-
const camera2 = this.camera;
|
|
3404
|
-
const { width, height } = dom.getBoundingClientRect();
|
|
3405
|
-
this.renderer.setSize(width, height);
|
|
3406
|
-
if (this.html2DRenderer) this.html2DRenderer.setSize(width, height);
|
|
3407
|
-
if (this.html3DRenderer) this.html3DRenderer.setSize(width, height);
|
|
3408
|
-
if (camera2 instanceof THREE.PerspectiveCamera) {
|
|
3409
|
-
camera2.aspect = width / height;
|
|
3410
|
-
} else if (camera2 instanceof THREE.OrthographicCamera) {
|
|
3411
|
-
camera2.left = -width * 0.5;
|
|
3412
|
-
camera2.right = width * 0.5;
|
|
3413
|
-
camera2.top = height * 0.5;
|
|
3414
|
-
camera2.bottom = -height * 0.5;
|
|
3415
|
-
}
|
|
3416
|
-
camera2.updateProjectionMatrix();
|
|
3417
|
-
this.onResize && this.onResize(width, height);
|
|
3418
|
-
this.dispatchEvent({ type: "resize", width, height });
|
|
3419
|
-
});
|
|
3420
|
-
this.resizeObserver.observe(dom);
|
|
3421
|
-
}
|
|
3422
|
-
this.renderer.setAnimationLoop(() => {
|
|
3423
|
-
if (this.html2DRenderer) this.html2DRenderer.render(this.scene, this.camera);
|
|
3424
|
-
if (this.html3DRenderer) this.html3DRenderer.render(this.scene, this.camera);
|
|
3425
|
-
this.renderer.render(this.scene, this.camera);
|
|
3426
|
-
if (this.orbitControls && this.orbitControls.enabled) this.orbitControls.update();
|
|
3427
|
-
this.tweenTaskList.forEach((tween) => tween.update());
|
|
3428
|
-
this.onUpdate && this.onUpdate();
|
|
3429
|
-
this.parent?.components.forEach((c) => c.dispatchEvent({ type: "update" }));
|
|
3430
|
-
});
|
|
3431
|
-
this.scene.add(new THREE.AmbientLight(16777215, 0.5));
|
|
3432
|
-
this.scene.background = new THREE.Color(3355443);
|
|
3433
|
-
const directLight = new THREE.DirectionalLight(16777215, 4);
|
|
3434
|
-
directLight.position.set(100, -100, 100);
|
|
3435
|
-
this.scene.add(directLight);
|
|
3436
|
-
camera.position.set(10, 10, 10);
|
|
3437
|
-
}
|
|
3438
|
-
/**
|
|
3439
|
-
* 世界坐标转屏幕坐标
|
|
3440
|
-
* @param worldPosition
|
|
3441
|
-
* @param camera
|
|
3442
|
-
* @param renderer
|
|
3443
|
-
* @returns
|
|
3444
|
-
*/
|
|
3445
|
-
worldToScreenPosition(worldPosition) {
|
|
3446
|
-
const vector = new THREE.Vector3();
|
|
3447
|
-
vector.copy(worldPosition);
|
|
3448
|
-
vector.project(this.camera);
|
|
3449
|
-
const x = (vector.x * 0.5 + 0.5) * this.renderer.domElement.clientWidth;
|
|
3450
|
-
const z = (-vector.z * 0.5 + 0.5) * this.renderer.domElement.clientHeight;
|
|
3451
|
-
return new THREE.Vector2(x, z);
|
|
3452
|
-
}
|
|
3453
|
-
cameraPositionRecord = [];
|
|
3454
|
-
/**
|
|
3455
|
-
* 相机
|
|
3456
|
-
* @param position
|
|
3457
|
-
* @param lookAt
|
|
3458
|
-
* @param onEnd
|
|
3459
|
-
*/
|
|
3460
|
-
cameraTo(position, lookAt, onEnd) {
|
|
3461
|
-
this.cameraPositionRecord.push([
|
|
3462
|
-
this.camera.position.clone(),
|
|
3463
|
-
this.camera.quaternion.clone()
|
|
3464
|
-
]);
|
|
3465
|
-
const tween = new TWEEN.Tween(this.camera.position);
|
|
3466
|
-
tween.to(position, 600);
|
|
3467
|
-
tween.start();
|
|
3468
|
-
tween.onUpdate(() => {
|
|
3469
|
-
this.camera.lookAt(lookAt);
|
|
3470
|
-
});
|
|
3471
|
-
tween.onComplete(() => {
|
|
3472
|
-
const i = this.tweenTaskList.indexOf(tween);
|
|
3473
|
-
this.tweenTaskList.splice(i, 1);
|
|
3474
|
-
onEnd && onEnd();
|
|
3475
|
-
});
|
|
3476
|
-
this.tweenTaskList.push(tween);
|
|
3477
|
-
}
|
|
3478
|
-
cameraBack() {
|
|
3479
|
-
if (this.cameraPositionRecord.length) {
|
|
3480
|
-
const [pos, quat] = this.cameraPositionRecord.pop();
|
|
3481
|
-
this.camera.position.copy(pos);
|
|
3482
|
-
this.camera.quaternion.copy(quat);
|
|
3483
|
-
}
|
|
3484
|
-
}
|
|
3485
|
-
/**
|
|
3486
|
-
* 创建点
|
|
3487
|
-
* @param pos
|
|
3488
|
-
*/
|
|
3489
|
-
createPointMesh(pos, size = 0.02, parameters, parent = this.container) {
|
|
3490
|
-
const box = new THREE.Mesh(
|
|
3491
|
-
new THREE.SphereGeometry(size),
|
|
3492
|
-
new THREE.MeshBasicMaterial(parameters)
|
|
3493
|
-
);
|
|
3494
|
-
if (pos instanceof Point) box.position.set(pos.x, pos.y, 0);
|
|
3495
|
-
else if (pos instanceof THREE.Vector3) box.position.copy(pos);
|
|
3496
|
-
parent.add(box);
|
|
3497
|
-
return box;
|
|
3498
|
-
}
|
|
3499
|
-
/**
|
|
3500
|
-
* 创建文本
|
|
3501
|
-
* @param text
|
|
3502
|
-
* @param pos
|
|
3503
|
-
* @param style
|
|
3504
|
-
*/
|
|
3505
|
-
createText(text, pos, style, parent = this.container) {
|
|
3506
|
-
const div = document.createElement("div");
|
|
3507
|
-
div.innerHTML = text;
|
|
3508
|
-
div.style.pointerEvents = "none";
|
|
3509
|
-
Object.assign(div.style, { fontSize: "10px", color: "#ffffff", ...style });
|
|
3510
|
-
const css2DObject = new Renderer.CSS2DObject(div);
|
|
3511
|
-
if (pos instanceof Point) css2DObject.position.set(pos.x, pos.y, 0);
|
|
3512
|
-
else if (pos instanceof THREE.Vector3) css2DObject.position.copy(pos);
|
|
3513
|
-
parent.add(css2DObject);
|
|
3514
|
-
return css2DObject;
|
|
3515
|
-
}
|
|
3516
|
-
/**
|
|
3517
|
-
* 创建几何缓冲区
|
|
3518
|
-
* @param map
|
|
3519
|
-
* @param count
|
|
3520
|
-
*/
|
|
3521
|
-
createLineSegments(map, count, parameters, parent = this.container) {
|
|
3522
|
-
const geometry = new THREE.BufferGeometry();
|
|
3523
|
-
Object.keys(map).forEach((key) => {
|
|
3524
|
-
const value = map[key];
|
|
3525
|
-
geometry.setAttribute(key, new THREE.BufferAttribute(new Float32Array(value), value.length / count));
|
|
3526
|
-
});
|
|
3527
|
-
const lineSegmentList = new THREE.LineSegments(geometry, new THREE.LineBasicMaterial({ ...parameters }));
|
|
3528
|
-
parent.add(lineSegmentList);
|
|
3529
|
-
return lineSegmentList;
|
|
3530
|
-
}
|
|
3531
|
-
destroy() {
|
|
3532
|
-
if (this.resizeObserver) {
|
|
3533
|
-
this.renderer.dispose();
|
|
3534
|
-
this.resizeObserver.disconnect();
|
|
3535
|
-
this.resizeObserver = void 0;
|
|
3536
|
-
}
|
|
3537
|
-
}
|
|
3538
|
-
}
|
|
3539
8
|
function drawLinePathToPng(points, width, height, color = "#fff", lineWidth = 2) {
|
|
3540
9
|
const can = document.createElement("canvas"), ctx = can.getContext("2d");
|
|
3541
10
|
can.width = width;
|
|
@@ -3789,41 +258,6 @@ class DetailsPointRender extends Component {
|
|
|
3789
258
|
renderer.camera.updateProjectionMatrix();
|
|
3790
259
|
}
|
|
3791
260
|
}
|
|
3792
|
-
class DomContainer extends Component {
|
|
3793
|
-
static name = "DomContainer";
|
|
3794
|
-
domElement = document.createElement("div");
|
|
3795
|
-
canvas = document.createElement("canvas");
|
|
3796
|
-
html2DRenderer = document.createElement("div");
|
|
3797
|
-
html3DRenderer = document.createElement("div");
|
|
3798
|
-
constructor() {
|
|
3799
|
-
super();
|
|
3800
|
-
this.domElement.appendChild(this.canvas);
|
|
3801
|
-
this.domElement.appendChild(this.html3DRenderer);
|
|
3802
|
-
this.domElement.appendChild(this.html2DRenderer);
|
|
3803
|
-
Object.assign(this.domElement.style, {
|
|
3804
|
-
width: "100%",
|
|
3805
|
-
height: "100%",
|
|
3806
|
-
position: "relative",
|
|
3807
|
-
userSelect: "none"
|
|
3808
|
-
});
|
|
3809
|
-
Object.assign(this.html3DRenderer.style, {
|
|
3810
|
-
position: "absolute",
|
|
3811
|
-
left: 0,
|
|
3812
|
-
top: 0,
|
|
3813
|
-
zIndex: 9,
|
|
3814
|
-
width: "100%",
|
|
3815
|
-
height: "100%"
|
|
3816
|
-
});
|
|
3817
|
-
Object.assign(this.html2DRenderer.style, {
|
|
3818
|
-
position: "absolute",
|
|
3819
|
-
left: 0,
|
|
3820
|
-
top: 0,
|
|
3821
|
-
zIndex: 10,
|
|
3822
|
-
width: "100%",
|
|
3823
|
-
height: "100%"
|
|
3824
|
-
});
|
|
3825
|
-
}
|
|
3826
|
-
}
|
|
3827
261
|
class OriginalLineRender extends Component {
|
|
3828
262
|
static name = "OriginalLineRender";
|
|
3829
263
|
Dxf = null;
|
|
@@ -3950,103 +384,6 @@ class ModelDataRender extends Component {
|
|
|
3950
384
|
variable?.addEventListener("currentKeyUp", (e) => e.value === "e" && variable.set("whiteModelVisible", !variable.whiteModelVisible));
|
|
3951
385
|
}
|
|
3952
386
|
}
|
|
3953
|
-
class DomEventRegister extends Component {
|
|
3954
|
-
static name = "DomEventRegister";
|
|
3955
|
-
cancelDefaultBehaviorList = [];
|
|
3956
|
-
pointer = new Vector2();
|
|
3957
|
-
/**
|
|
3958
|
-
*
|
|
3959
|
-
* @param parent
|
|
3960
|
-
*/
|
|
3961
|
-
onAddFromParent(parent) {
|
|
3962
|
-
const domContainer = parent.findComponentByType(DomContainer);
|
|
3963
|
-
const variable = parent.findComponentByType(Variable);
|
|
3964
|
-
const domElement = domContainer.domElement;
|
|
3965
|
-
domElement.tabIndex = 1;
|
|
3966
|
-
domElement.addEventListener("keyup", (e) => {
|
|
3967
|
-
const key = e.key.toLocaleLowerCase();
|
|
3968
|
-
variable.set("currentKeyUp", key);
|
|
3969
|
-
for (let i = 0; i < this.cancelDefaultBehaviorList.length; i++) {
|
|
3970
|
-
const element = this.cancelDefaultBehaviorList[i];
|
|
3971
|
-
if (element(e)) e.preventDefault();
|
|
3972
|
-
}
|
|
3973
|
-
});
|
|
3974
|
-
domElement.addEventListener("keydown", (e) => {
|
|
3975
|
-
const key = e.key.toLocaleLowerCase();
|
|
3976
|
-
variable.set("currentKeyDown", key);
|
|
3977
|
-
for (let i = 0; i < this.cancelDefaultBehaviorList.length; i++) {
|
|
3978
|
-
const element = this.cancelDefaultBehaviorList[i];
|
|
3979
|
-
if (element(e)) e.preventDefault();
|
|
3980
|
-
}
|
|
3981
|
-
});
|
|
3982
|
-
domElement.addEventListener("mousedown", (e) => {
|
|
3983
|
-
variable.set("currentMouseDown", "mouse_" + e.button);
|
|
3984
|
-
});
|
|
3985
|
-
domElement.addEventListener("mouseup", (e) => {
|
|
3986
|
-
variable.set("currentMouseUp", "mouse_" + e.button);
|
|
3987
|
-
});
|
|
3988
|
-
domElement.addEventListener("wheel", (e) => {
|
|
3989
|
-
variable.set("currentWheel", e.wheelDelta);
|
|
3990
|
-
});
|
|
3991
|
-
domElement.addEventListener("focus", () => {
|
|
3992
|
-
variable.set("focus", true);
|
|
3993
|
-
});
|
|
3994
|
-
domElement.addEventListener("blur", () => {
|
|
3995
|
-
variable.set("focus", false);
|
|
3996
|
-
});
|
|
3997
|
-
this.dragMoveHelper(domElement, (_0, x, y) => variable.set("pointerMove", { x, y }), { x: 0, y: 0 });
|
|
3998
|
-
domElement.addEventListener("mousemove", (e) => {
|
|
3999
|
-
this.pointer.set(e.offsetX, e.offsetY);
|
|
4000
|
-
this.dispatchEvent({
|
|
4001
|
-
type: "mousemove",
|
|
4002
|
-
x: e.offsetX,
|
|
4003
|
-
y: e.offsetY,
|
|
4004
|
-
moveX: e.movementX,
|
|
4005
|
-
moveY: e.movementY
|
|
4006
|
-
});
|
|
4007
|
-
});
|
|
4008
|
-
domElement.addEventListener("mousedown", (e) => {
|
|
4009
|
-
this.pointer.set(e.offsetX, e.offsetY);
|
|
4010
|
-
this.dispatchEvent({
|
|
4011
|
-
type: "mousedown",
|
|
4012
|
-
x: e.offsetX,
|
|
4013
|
-
y: e.offsetY
|
|
4014
|
-
});
|
|
4015
|
-
});
|
|
4016
|
-
}
|
|
4017
|
-
/**
|
|
4018
|
-
*
|
|
4019
|
-
* @param callBack
|
|
4020
|
-
*/
|
|
4021
|
-
addCancelDefaultBehavior(callBack) {
|
|
4022
|
-
this.cancelDefaultBehaviorList.push(callBack);
|
|
4023
|
-
return this;
|
|
4024
|
-
}
|
|
4025
|
-
/**
|
|
4026
|
-
*
|
|
4027
|
-
* @param el
|
|
4028
|
-
* @param callBack
|
|
4029
|
-
* @param offset
|
|
4030
|
-
* @param condition
|
|
4031
|
-
*/
|
|
4032
|
-
dragMoveHelper(el, callBack, offset = { x: 0, y: 0 }, condition = () => true) {
|
|
4033
|
-
el.addEventListener("mousedown", () => {
|
|
4034
|
-
if (!condition()) return;
|
|
4035
|
-
const move = (e) => {
|
|
4036
|
-
offset.x += e.movementX;
|
|
4037
|
-
offset.y += e.movementY;
|
|
4038
|
-
callBack({ ...offset }, e.movementX, e.movementY);
|
|
4039
|
-
};
|
|
4040
|
-
const end = () => {
|
|
4041
|
-
document.removeEventListener("mousemove", move);
|
|
4042
|
-
document.removeEventListener("mouseup", end);
|
|
4043
|
-
};
|
|
4044
|
-
document.addEventListener("mousemove", move);
|
|
4045
|
-
document.addEventListener("mouseup", end);
|
|
4046
|
-
});
|
|
4047
|
-
callBack({ ...offset }, 0, 0);
|
|
4048
|
-
}
|
|
4049
|
-
}
|
|
4050
387
|
class EventInput extends Component {
|
|
4051
388
|
static name = "EventInput";
|
|
4052
389
|
keyList = /* @__PURE__ */ new Set();
|
|
@@ -4085,6 +422,8 @@ class EventInput extends Component {
|
|
|
4085
422
|
this.mouseList.clear();
|
|
4086
423
|
});
|
|
4087
424
|
this.addEventListener("codeChange", this._computedkeyCombination.bind(this));
|
|
425
|
+
this.addKeyCombination("save", ["control", "s"]);
|
|
426
|
+
this.addCancelDefaultBehavior((input) => input.isOnlyKeyDowns(["control", "s"]));
|
|
4088
427
|
}
|
|
4089
428
|
/** 添加取消浏览器默认行为规则
|
|
4090
429
|
* @param callBack
|
|
@@ -4353,6 +692,7 @@ function RenderPlugin_(dxfSystem, option = {}) {
|
|
|
4353
692
|
originalLine = true,
|
|
4354
693
|
modelData = true,
|
|
4355
694
|
detailsPoint = true,
|
|
695
|
+
orbitControls = true,
|
|
4356
696
|
camera = new THREE.PerspectiveCamera(45, 1, 0.01, 1e3)
|
|
4357
697
|
} = option;
|
|
4358
698
|
const domContainer = new DomContainer();
|
|
@@ -4365,11 +705,11 @@ function RenderPlugin_(dxfSystem, option = {}) {
|
|
|
4365
705
|
"3d": domContainer.html3DRenderer
|
|
4366
706
|
},
|
|
4367
707
|
resizeObserver: domContainer.domElement,
|
|
4368
|
-
orbitControls: {
|
|
708
|
+
orbitControls: orbitControls ? {
|
|
4369
709
|
domElement: domContainer.domElement,
|
|
4370
710
|
enableDamping: true,
|
|
4371
711
|
dampingFactor: 0.15
|
|
4372
|
-
}
|
|
712
|
+
} : void 0
|
|
4373
713
|
}));
|
|
4374
714
|
originalLine && dxfSystem.addComponent(new OriginalLineRender());
|
|
4375
715
|
modelData && dxfSystem.addComponent(new ModelDataRender());
|