@jgphilpott/polytree 0.0.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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +34 -0
  3. package/package.json +56 -0
  4. package/polytree.js +2938 -0
package/polytree.js ADDED
@@ -0,0 +1,2938 @@
1
+ // Generated by CoffeeScript 2.7.0
2
+ var BACK, Box3, BufferAttribute, BufferGeometry, COPLANAR, CSG_Rules, DoubleSide, EPSILON, FRONT, Matrix3, Mesh, OctreeCSG, Plane, Polygon, RAY_EPSILON, Ray, Raycaster, SPANNING, Triangle, Vector2, Vector3, Vertex, _asyncUnionArrayID, _asyncUnionID, _box3$1, _matrix3, _normal1, _polygonID, _ray, _rayDirection, _raycaster1, _v1, _v2, _wP, _wP_EPS_ARR, _wP_EPS_ARR_COUNT, _wV1, _wV2, _wV3, calcWindingNumber_buffer, disposeOctree, edge1, edge2, h, handleIntersectingOctrees, handleObjectForOp, handleObjectForOp_async, isUniqueTriangle, isValidTriangle, nbuf2, nbuf3, pointRounding, polyInside_WindingNumber_buffer, prepareTriangleBuffer, q, rayIntersectsTriangle, raycastIntersectAscSort, returnXYZ, s, splitPolygonArr, splitPolygonByPlane, tmpm3, triangleIntersectsTriangle, ttvv0, tv0, tv1, wNPI;
3
+
4
+ ({Vector2, Vector3, Box3, DoubleSide, Matrix3, Ray, Triangle, BufferGeometry, BufferAttribute, Mesh, Raycaster} = require("three"));
5
+
6
+ ({triangleIntersectsTriangle} = require("./src/triangle.intersection.js"));
7
+
8
+ _v1 = new Vector3();
9
+
10
+ _v2 = new Vector3();
11
+
12
+ _box3$1 = new Box3();
13
+
14
+ tv0 = new Vector3();
15
+
16
+ tv1 = new Vector3();
17
+
18
+ _raycaster1 = new Raycaster();
19
+
20
+ _ray = new Ray();
21
+
22
+ _rayDirection = new Vector3(0, 0, 1);
23
+
24
+ EPSILON = 1e-5;
25
+
26
+ COPLANAR = 0;
27
+
28
+ FRONT = 1;
29
+
30
+ BACK = 2;
31
+
32
+ SPANNING = 3;
33
+
34
+ _polygonID = 0;
35
+
36
+ OctreeCSG = class OctreeCSG {
37
+ constructor(box, parent) {
38
+ this.polygons = [];
39
+ this.replacedPolygons = [];
40
+ this.mesh;
41
+ this.originalMatrixWorld;
42
+ this.box = box;
43
+ this.subTrees = [];
44
+ this.parent = parent;
45
+ this.level = 0;
46
+ this.polygonArrays = void 0;
47
+ // @isOctree = true
48
+ this.addPolygonsArrayToRoot(this.polygons);
49
+ }
50
+
51
+ clone() {
52
+ return (new this.constructor()).copy(this);
53
+ }
54
+
55
+ copy(source) {
56
+ var i, k, ref, subTree;
57
+ this.deletePolygonsArrayFromRoot(this.polygons);
58
+ this.polygons = source.polygons.map(function(p) {
59
+ return p.clone();
60
+ });
61
+ this.addPolygonsArrayToRoot(this.polygons);
62
+ this.replacedPolygons = source.replacedPolygons.map(function(p) {
63
+ return p.clone();
64
+ });
65
+ if (source.mesh) {
66
+ this.mesh = source.mesh;
67
+ }
68
+ if (source.originalMatrixWorld) {
69
+ this.originalMatrixWorld = source.originalMatrixWorld.clone();
70
+ }
71
+ this.box = source.box.clone();
72
+ this.level = source.level;
73
+ for (i = k = 0, ref = source.subTrees.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
74
+ subTree = new this.constructor(void 0, this).copy(source.subTrees[i]);
75
+ this.subTrees.push(subTree);
76
+ }
77
+ return this;
78
+ }
79
+
80
+ addPolygonsArrayToRoot(array) {
81
+ if (this.parent) {
82
+ return this.parent.addPolygonsArrayToRoot(array);
83
+ } else {
84
+ if (this.polygonArrays === void 0) {
85
+ this.polygonArrays = [];
86
+ }
87
+ return this.polygonArrays.push(array);
88
+ }
89
+ }
90
+
91
+ deletePolygonsArrayFromRoot(array) {
92
+ var index;
93
+ if (this.parent) {
94
+ return this.parent.deletePolygonsArrayFromRoot(array);
95
+ } else {
96
+ index = this.polygonArrays.indexOf(array);
97
+ if (index > -1) {
98
+ return this.polygonArrays.splice(index, 1);
99
+ }
100
+ }
101
+ }
102
+
103
+ isEmpty() {
104
+ return this.polygons.length === 0;
105
+ }
106
+
107
+ addPolygon(polygon, trianglesSet) {
108
+ var triangle;
109
+ if (!this.bounds) {
110
+ this.bounds = new Box3();
111
+ }
112
+ triangle = polygon.triangle;
113
+ if (trianglesSet && !isUniqueTriangle(triangle, trianglesSet)) {
114
+ return this;
115
+ }
116
+ this.bounds.min.x = Math.min(this.bounds.min.x, triangle.a.x, triangle.b.x, triangle.c.x);
117
+ this.bounds.min.y = Math.min(this.bounds.min.y, triangle.a.y, triangle.b.y, triangle.c.y);
118
+ this.bounds.min.z = Math.min(this.bounds.min.z, triangle.a.z, triangle.b.z, triangle.c.z);
119
+ this.bounds.max.x = Math.max(this.bounds.max.x, triangle.a.x, triangle.b.x, triangle.c.x);
120
+ this.bounds.max.y = Math.max(this.bounds.max.y, triangle.a.y, triangle.b.y, triangle.c.y);
121
+ this.bounds.max.z = Math.max(this.bounds.max.z, triangle.a.z, triangle.b.z, triangle.c.z);
122
+ this.polygons.push(polygon);
123
+ return this;
124
+ }
125
+
126
+ calcBox() {
127
+ if (!this.bounds) {
128
+ this.bounds = new Box3();
129
+ }
130
+ this.box = this.bounds.clone();
131
+ // offset small ammount to account for regular grid
132
+ this.box.min.x -= 0.01;
133
+ this.box.min.y -= 0.01;
134
+ this.box.min.z -= 0.01;
135
+ return this;
136
+ }
137
+
138
+ newOctree(box, parent) {
139
+ return new this.constructor(box, parent);
140
+ }
141
+
142
+ split(level) {
143
+ var box, found, halfsize, i, i1, k, l, len, m, o, polygon, ref, ref1, subTrees, v, x, y, z;
144
+ if (!this.box) {
145
+ return;
146
+ }
147
+ subTrees = [];
148
+ halfsize = _v2.copy(this.box.max).sub(this.box.min).multiplyScalar(0.5);
149
+ for (x = k = 0; k <= 1; x = ++k) {
150
+ for (y = l = 0; l <= 1; y = ++l) {
151
+ for (z = m = 0; m <= 1; z = ++m) {
152
+ box = new Box3();
153
+ v = _v1.set(x, y, z);
154
+ box.min.copy(this.box.min).add(v.multiply(halfsize));
155
+ box.max.copy(box.min).add(halfsize);
156
+ box.expandByScalar(EPSILON);
157
+ subTrees.push(this.newOctree(box, this));
158
+ }
159
+ }
160
+ }
161
+ polygon = void 0;
162
+ while (polygon = this.polygons.pop()) {
163
+ found = false;
164
+ for (i = o = 0, ref = subTrees.length; (0 <= ref ? o < ref : o > ref); i = 0 <= ref ? ++o : --o) {
165
+ if (subTrees[i].box.containsPoint(polygon.getMidpoint())) {
166
+ subTrees[i].polygons.push(polygon);
167
+ found = true;
168
+ }
169
+ }
170
+ if (!found) {
171
+ console.error("ERROR: unable to find subtree for:", polygon.triangle);
172
+ throw new Error(`Unable to find subtree for triangle at level ${level}`);
173
+ }
174
+ }
175
+ for (i = i1 = 0, ref1 = subTrees.length; (0 <= ref1 ? i1 < ref1 : i1 > ref1); i = 0 <= ref1 ? ++i1 : --i1) {
176
+ subTrees[i].level = level + 1;
177
+ len = subTrees[i].polygons.length;
178
+ // if (len !== 0) {
179
+ if (len > OctreeCSG.polygonsPerTree && level < OctreeCSG.maxLevel) {
180
+ subTrees[i].split(level + 1);
181
+ }
182
+ this.subTrees.push(subTrees[i]);
183
+ }
184
+ return this;
185
+ }
186
+
187
+ buildTree() {
188
+ this.calcBox();
189
+ this.split(0);
190
+ this.processTree();
191
+ return this;
192
+ }
193
+
194
+ processTree() {
195
+ var i, k, l, ref, ref1, results1;
196
+ if (!this.isEmpty()) {
197
+ _box3$1.copy(this.box);
198
+ for (i = k = 0, ref = this.polygons.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
199
+ this.box.expandByPoint(this.polygons[i].triangle.a);
200
+ this.box.expandByPoint(this.polygons[i].triangle.b);
201
+ this.box.expandByPoint(this.polygons[i].triangle.c);
202
+ }
203
+ this.expandParentBox();
204
+ }
205
+ results1 = [];
206
+ for (i = l = 0, ref1 = this.subTrees.length; (0 <= ref1 ? l < ref1 : l > ref1); i = 0 <= ref1 ? ++l : --l) {
207
+ results1.push(this.subTrees[i].processTree());
208
+ }
209
+ return results1;
210
+ }
211
+
212
+ expandParentBox() {
213
+ if (this.parent) {
214
+ this.parent.box.expandByPoint(this.box.min);
215
+ this.parent.box.expandByPoint(this.box.max);
216
+ return this.parent.expandParentBox();
217
+ }
218
+ }
219
+
220
+ getPolygonsIntersectingPolygon(targetPolygon, polygons = []) {
221
+ var allPolygons, i, k, l, m, polygon, ref, ref1, ref2;
222
+ if (this.box.intersectsTriangle(targetPolygon.triangle)) {
223
+ if (this.polygons.length > 0) {
224
+ allPolygons = this.polygons.slice();
225
+ if (this.replacedPolygons.length > 0) {
226
+ for (i = k = 0, ref = this.replacedPolygons.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
227
+ allPolygons.push(this.replacedPolygons[i]);
228
+ }
229
+ }
230
+ for (i = l = 0, ref1 = allPolygons.length; (0 <= ref1 ? l < ref1 : l > ref1); i = 0 <= ref1 ? ++l : --l) {
231
+ polygon = allPolygons[i];
232
+ if (!(polygon.originalValid && polygon.valid && polygon.intersects)) {
233
+ continue;
234
+ }
235
+ if (triangleIntersectsTriangle(targetPolygon.triangle, polygon.triangle)) {
236
+ polygons.push(polygon);
237
+ }
238
+ }
239
+ }
240
+ }
241
+ for (i = m = 0, ref2 = this.subTrees.length; (0 <= ref2 ? m < ref2 : m > ref2); i = 0 <= ref2 ? ++m : --m) {
242
+ this.subTrees[i].getPolygonsIntersectingPolygon(targetPolygon, polygons);
243
+ }
244
+ return polygons;
245
+ }
246
+
247
+ getRayPolygons(ray, polygons = []) {
248
+ var i, k, l, ref, ref1;
249
+ if (this.polygons.length > 0) {
250
+ for (i = k = 0, ref = this.polygons.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
251
+ if (this.polygons[i].valid && this.polygons[i].originalValid) {
252
+ if (polygons.indexOf(this.polygons[i]) === -1) {
253
+ polygons.push(this.polygons[i]);
254
+ }
255
+ }
256
+ }
257
+ }
258
+ if (this.replacedPolygons.length > 0) {
259
+ polygons.push(...this.replacedPolygons);
260
+ }
261
+ for (i = l = 0, ref1 = this.subTrees.length; (0 <= ref1 ? l < ref1 : l > ref1); i = 0 <= ref1 ? ++l : --l) {
262
+ if (ray.intersectsBox(this.subTrees[i].box)) {
263
+ this.subTrees[i].getRayPolygons(ray, polygons);
264
+ }
265
+ }
266
+ return polygons;
267
+ }
268
+
269
+ rayIntersect(ray, matrixWorld, intersects = []) {
270
+ var distance, i, k, newdistance, polygons, ref, result;
271
+ if (ray.direction.length() === 0) {
272
+ return [];
273
+ }
274
+ distance = 1e100;
275
+ polygons = this.getRayPolygons(ray);
276
+ for (i = k = 0, ref = polygons.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
277
+ result = void 0;
278
+ if (OctreeCSG.rayIntersectTriangleType === "regular") {
279
+ result = ray.intersectTriangle(polygons[i].triangle.a, polygons[i].triangle.b, polygons[i].triangle.c, false, _v1);
280
+ if (result) {
281
+ _v1.applyMatrix4(matrixWorld);
282
+ distance = _v1.distanceTo(ray.origin);
283
+ if (distance < 0 || distance > 2e308) {
284
+ console.warn("[rayIntersect] Failed ray distance check", ray);
285
+ } else {
286
+ intersects.push({
287
+ distance: distance,
288
+ polygon: polygons[i],
289
+ position: _v1.clone()
290
+ });
291
+ }
292
+ }
293
+ } else {
294
+ result = rayIntersectsTriangle(ray, polygons[i].triangle, _v1);
295
+ if (result) {
296
+ newdistance = result.clone().sub(ray.origin).length();
297
+ if (distance > newdistance) {
298
+ distance = newdistance;
299
+ }
300
+ if (distance < 1e100) {
301
+ intersects.push({
302
+ distance: distance,
303
+ polygon: polygons[i],
304
+ position: result.clone().add(ray.origin)
305
+ });
306
+ }
307
+ }
308
+ }
309
+ }
310
+ intersects.length && intersects.sort(raycastIntersectAscSort);
311
+ return intersects;
312
+ }
313
+
314
+ getIntersectingPolygons(polygons = []) {
315
+ this.polygonArrays.forEach(function(polygonsArray) {
316
+ var i, k, ref, results1;
317
+ if (polygonsArray.length) {
318
+ results1 = [];
319
+ for (i = k = 0, ref = polygonsArray.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
320
+ if (polygonsArray[i].valid && polygonsArray[i].intersects) {
321
+ results1.push(polygons.push(polygonsArray[i]));
322
+ } else {
323
+ results1.push(void 0);
324
+ }
325
+ }
326
+ return results1;
327
+ }
328
+ });
329
+ // if (@polygons.length)
330
+ // for i in [0...@polygons.length]
331
+ // if @polygons[i].valid and @polygons[i].intersects
332
+ // polygons.push(@polygons[i])
333
+ // for i in [0...@subTrees.length]
334
+ // @subTrees[i].getIntersectingPolygons(polygons)
335
+ return polygons;
336
+ }
337
+
338
+ getPolygons(polygons = []) {
339
+ this.polygonArrays.forEach(function(polygonsArray) {
340
+ var i, k, ref, results1;
341
+ if (polygonsArray.length) {
342
+ results1 = [];
343
+ for (i = k = 0, ref = polygonsArray.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
344
+ if (polygonsArray[i].valid) {
345
+ if (polygons.indexOf(polygonsArray[i]) === -1) {
346
+ results1.push(polygons.push(polygonsArray[i]));
347
+ } else {
348
+ results1.push(void 0);
349
+ }
350
+ } else {
351
+ results1.push(void 0);
352
+ }
353
+ }
354
+ return results1;
355
+ }
356
+ });
357
+ // if @polygons.length > 0
358
+ // for i in [0...@polygons.length]
359
+ // if @polygons[i].valid
360
+ // if polygons.indexOf(@polygons[i]) is -1
361
+ // polygons.push(@polygons[i])
362
+ // for i in [0...@subTrees.length]
363
+ // @subTrees[i].getPolygons(polygons)
364
+ return polygons;
365
+ }
366
+
367
+ invert() {
368
+ return this.polygonArrays.forEach(function(polygonsArray) {
369
+ if (polygonsArray.length) {
370
+ return polygonsArray.forEach(function(p) {
371
+ return p.flip();
372
+ });
373
+ }
374
+ });
375
+ }
376
+
377
+ // if @polygons.length > 0
378
+ // @polygons.forEach (p) -> p.flip()
379
+ // for i in [0...@subTrees.length]
380
+ // @subTrees[i].invert()
381
+ getMesh() {
382
+ if (this.parent) {
383
+ return this.parent.getMesh();
384
+ } else {
385
+ return this.mesh;
386
+ }
387
+ }
388
+
389
+ replacePolygon(polygon, newPolygons) {
390
+ var i, k, polygonIndex, ref, results1;
391
+ if (!Array.isArray(newPolygons)) {
392
+ newPolygons = [newPolygons];
393
+ }
394
+ // if @polygons.length > 0
395
+ // polygonIndex = @polygons.indexOf(polygon)
396
+ // if polygonIndex > -1
397
+ // if polygon.originalValid is true
398
+ // @replacedPolygons.push(polygon)
399
+ // else
400
+ // polygon.setInvalid()
401
+ // @polygons.splice(polygonIndex, 1, ...newPolygons)
402
+ // for i in [0...@subTrees.length]
403
+ // @subTrees[i].replacePolygon(polygon, newPolygons)
404
+ if (this.polygons.length > 0) {
405
+ polygonIndex = this.polygons.indexOf(polygon);
406
+ if (polygonIndex > -1) {
407
+ if (polygon.originalValid === true) {
408
+ this.replacedPolygons.push(polygon);
409
+ } else {
410
+ polygon.setInvalid();
411
+ }
412
+ this.polygons.splice(polygonIndex, 1, ...newPolygons);
413
+ }
414
+ }
415
+ results1 = [];
416
+ for (i = k = 0, ref = this.subTrees.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
417
+ results1.push(this.subTrees[i].replacePolygon(polygon, newPolygons));
418
+ }
419
+ return results1;
420
+ }
421
+
422
+ deletePolygonsByStateRules(rulesArr, firstRun = true) {
423
+ return this.polygonArrays.forEach(function(polygonsArray) {
424
+ var polygonArr;
425
+ if (polygonsArray.length) {
426
+ polygonArr = polygonsArray.filter(function(polygon) {
427
+ return (polygon.valid === true) && (polygon.intersects === true);
428
+ });
429
+ return polygonArr.forEach(function(polygon) {
430
+ var found, i, j, k, l, mainStatesObj, polygonIndex, ref, ref1, state, states, statesObj;
431
+ found = false;
432
+ for (j = k = 0, ref = rulesArr.length; (0 <= ref ? k < ref : k > ref); j = 0 <= ref ? ++k : --k) {
433
+ if (rulesArr[j].array) {
434
+ states = rulesArr[j].rule;
435
+ if ((states.includes(polygon.state)) && (((polygon.previousState !== "undecided") && (states.includes(polygon.previousState))) || (polygon.previousState === "undecided"))) {
436
+ found = true;
437
+ statesObj = {};
438
+ mainStatesObj = {};
439
+ states.forEach(function(state) {
440
+ return statesObj[state] = false;
441
+ });
442
+ states.forEach(function(state) {
443
+ return mainStatesObj[state] = false;
444
+ });
445
+ statesObj[polygon.state] = true;
446
+ for (i = l = 0, ref1 = polygon.previousStates.length; (0 <= ref1 ? l < ref1 : l > ref1); i = 0 <= ref1 ? ++l : --l) {
447
+ if (!states.includes(polygon.previousStates[i])) {
448
+ found = false;
449
+ break;
450
+ } else {
451
+ statesObj[polygon.previousStates[i]] = true;
452
+ }
453
+ }
454
+ if (found) {
455
+ for (state in statesObj) {
456
+ if (statesObj[state] === false) {
457
+ found = false;
458
+ break;
459
+ }
460
+ }
461
+ if (found) {
462
+ break;
463
+ }
464
+ }
465
+ }
466
+ } else {
467
+ if (polygon.checkAllStates(rulesArr[j].rule)) {
468
+ found = true;
469
+ break;
470
+ }
471
+ }
472
+ }
473
+ if (found) {
474
+ polygonIndex = polygonsArray.indexOf(polygon);
475
+ if (polygonIndex > -1) {
476
+ polygon.setInvalid();
477
+ polygonsArray.splice(polygonIndex, 1);
478
+ }
479
+ if (firstRun) {
480
+ return polygon.delete();
481
+ }
482
+ }
483
+ });
484
+ }
485
+ });
486
+ }
487
+
488
+ // if @polygons.length > 0
489
+ // polygonArr = @polygons.filter (polygon) -> (polygon.valid == true) and (polygon.intersects == true)
490
+ // polygonArr.forEach (polygon) ->
491
+ // found = false
492
+ // for j in [0...rulesArr.length]
493
+ // if rulesArr[j].array
494
+ // states = rulesArr[j].rule
495
+ // if (states.includes(polygon.state)) and (((polygon.previousState isnt "undecided") and (states.includes(polygon.previousState))) or (polygon.previousState is "undecided"))
496
+ // found = true
497
+ // statesObj = {}
498
+ // mainStatesObj = {}
499
+ // states.forEach (state) -> statesObj[state] = false
500
+ // states.forEach (state) -> mainStatesObj[state] = false
501
+ // statesObj[polygon.state] = true
502
+ // for i in [0...polygon.previousStates.length]
503
+ // unless states.includes(polygon.previousStates[i])
504
+ // found = false
505
+ // break
506
+ // else
507
+ // statesObj[polygon.previousStates[i]] = true
508
+ // if found
509
+ // for state of statesObj
510
+ // if statesObj[state] is false
511
+ // found = false
512
+ // break
513
+ // if found
514
+ // break
515
+ // else
516
+ // if polygon.checkAllStates(rulesArr[j].rule)
517
+ // found = true
518
+ // break
519
+ // if found
520
+ // polygonIndex = @polygons.indexOf(polygon)
521
+ // if polygonIndex > -1
522
+ // polygon.setInvalid()
523
+ // @polygons.splice(polygonIndex, 1)
524
+ // if firstRun
525
+ // polygon.delete()
526
+ // for i in [0...@subTrees.length]
527
+ // @subTrees[i].deletePolygonsByStateRules(rulesArr, false)
528
+ deletePolygonsByIntersection(intersects, firstRun = true) {
529
+ if (intersects === void 0) {
530
+ return;
531
+ }
532
+ return this.polygonArrays.forEach(function(polygonsArray) {
533
+ var polygonArr;
534
+ if (polygonsArray.length) {
535
+ polygonArr = polygonsArray.slice();
536
+ return polygonArr.forEach(function(polygon) {
537
+ var polygonIndex;
538
+ if (polygon.valid) {
539
+ if (polygon.intersects === intersects) {
540
+ polygonIndex = polygonsArray.indexOf(polygon);
541
+ if (polygonIndex > -1) {
542
+ polygon.setInvalid();
543
+ polygonsArray.splice(polygonIndex, 1);
544
+ }
545
+ if (firstRun) {
546
+ return polygon.delete();
547
+ }
548
+ }
549
+ }
550
+ });
551
+ }
552
+ });
553
+ }
554
+
555
+ // if @polygons.length > 0
556
+ // polygonArr = @polygons.slice()
557
+ // polygonArr.forEach (polygon) ->
558
+ // if polygon.valid
559
+ // if polygon.intersects == intersects
560
+ // polygonIndex = @polygons.indexOf(polygon)
561
+ // if polygonIndex > -1
562
+ // polygon.setInvalid()
563
+ // @polygons.splice(polygonIndex, 1)
564
+ // if firstRun
565
+ // polygon.delete()
566
+ // for i in [0...@subTrees.length]
567
+ // @subTrees[i].deletePolygonsByIntersection(intersects, false)
568
+ isPolygonIntersecting(polygon) {
569
+ if (!this.box.intersectsTriangle(polygon.triangle)) {
570
+ return false;
571
+ }
572
+ return true;
573
+ }
574
+
575
+ markIntesectingPolygons(targetOctree) {
576
+ return this.polygonArrays.forEach(function(polygonsArray) {
577
+ if (polygonsArray.length) {
578
+ return polygonsArray.forEach(function(polygon) {
579
+ return polygon.intersects = targetOctree.isPolygonIntersecting(polygon);
580
+ });
581
+ }
582
+ });
583
+ }
584
+
585
+ // if @polygons.length > 0
586
+ // @polygons.forEach (polygon) ->
587
+ // polygon.intersects = targetOctree.isPolygonIntersecting(polygon)
588
+ // for i in [0...@subTrees.length]
589
+ // @subTrees[i].markIntesectingPolygons(targetOctree)
590
+ resetPolygons(resetOriginal = true) {
591
+ return this.polygonArrays.forEach(function(polygonsArray) {
592
+ if (polygonsArray.length) {
593
+ return polygonsArray.forEach(function(polygon) {
594
+ return polygon.reset(resetOriginal);
595
+ });
596
+ }
597
+ });
598
+ }
599
+
600
+ // if @polygons.length > 0
601
+ // @polygons.forEach (polygon) ->
602
+ // polygon.reset(resetOriginal)
603
+ // for i in [0...@subTrees.length]
604
+ // @subTrees[i].resetPolygons(resetOriginal)
605
+ handleIntersectingPolygons(targetOctree, targetOctreeBuffer) {
606
+ var currentPolygon, i, i1, inside, intersects, j, k, l, m, o, point, polygon, polygonStack, ref, ref1, ref2, ref3, ref4, results1, splitResults, target, targetPolygons;
607
+ // if @polygons.length > 0
608
+ // polygonStack = @polygons.filter (polygon) -> (polygon.valid == true) and (polygon.intersects == true) and (polygon.state == "undecided")
609
+ // currentPolygon = polygonStack.pop()
610
+ // while currentPolygon
611
+ // if currentPolygon.state isnt "undecided"
612
+ // continue
613
+ // unless currentPolygon.valid
614
+ // continue
615
+ // targetPolygons = targetOctree.getPolygonsIntersectingPolygon(currentPolygon)
616
+ // if targetPolygons.length > 0
617
+ // for j in [0...targetPolygons.length]
618
+ // target = targetPolygons[j]
619
+ // splitResults = splitPolygonByPlane(currentPolygon, target.plane)
620
+ // if splitResults.length > 1
621
+ // for i in [0...splitResults.length]
622
+ // polygon = splitResults[i].polygon
623
+ // polygon.intersects = currentPolygon.intersects
624
+ // polygon.newPolygon = true
625
+ // polygonStack.push(polygon)
626
+ // @replacePolygon(currentPolygon, splitResults.map((result) -> result.polygon))
627
+ // break
628
+ // else
629
+ // if currentPolygon.id isnt splitResults[0].polygon.id
630
+ // splitResults[0].polygon.intersects = currentPolygon.intersects
631
+ // splitResults[0].polygon.newPolygon = true
632
+ // polygonStack.push(splitResults[0].polygon)
633
+ // @replacePolygon(currentPolygon, splitResults[0].polygon)
634
+ // break
635
+ // else
636
+ // if (splitResults[0].type == "coplanar-front") or (splitResults[0].type == "coplanar-back")
637
+ // currentPolygon.setState(splitResults[0].type)
638
+ // currentPolygon.coplanar = true
639
+ // currentPolygon = polygonStack.pop()
640
+ // polygonStack = @polygons.filter (polygon) -> (polygon.valid == true) and (polygon.intersects == true)
641
+ // currentPolygon = polygonStack.pop()
642
+ // inside = false
643
+ // while currentPolygon
644
+ // unless currentPolygon.valid
645
+ // continue
646
+ // inside = false
647
+ // if targetOctree.box.containsPoint(currentPolygon.getMidpoint())
648
+ // if OctreeCSG.useWindingNumber is true
649
+ // inside = polyInside_WindingNumber_buffer(targetOctreeBuffer, currentPolygon.getMidpoint(), currentPolygon.coplanar)
650
+ // else
651
+ // point = pointRounding(_v2.copy(currentPolygon.getMidpoint()))
652
+ // if OctreeCSG.useOctreeRay isnt true and targetOctree.mesh
653
+ // _rayDirection.copy(currentPolygon.plane.normal)
654
+ // _raycaster1.set(point, _rayDirection)
655
+ // intersects = _raycaster1.intersectObject(targetOctree.mesh)
656
+ // if intersects.length
657
+ // if _rayDirection.dot(intersects[0].face.normal) > 0
658
+ // inside = true
659
+ // unless inside or not currentPolygon.coplanar
660
+ // for j in [0..._wP_EPS_ARR_COUNT]
661
+ // _raycaster1.ray.origin.copy(point).add(_wP_EPS_ARR[j])
662
+ // intersects = _raycaster1.intersectObject(targetOctree.mesh)
663
+ // if intersects.length
664
+ // if _rayDirection.dot(intersects[0].face.normal) > 0
665
+ // inside = true
666
+ // break
667
+ // else
668
+ // _ray.origin.copy(point)
669
+ // _rayDirection.copy(currentPolygon.plane.normal)
670
+ // _ray.direction.copy(currentPolygon.plane.normal)
671
+ // intersects = targetOctree.rayIntersect(_ray, targetOctree.originalMatrixWorld)
672
+ // if intersects.length
673
+ // if _rayDirection.dot(intersects[0].polygon.plane.normal) > 0
674
+ // inside = true
675
+ // unless inside or not currentPolygon.coplanar
676
+ // for j in [0..._wP_EPS_ARR_COUNT]
677
+ // _ray.origin.copy(point).add(_wP_EPS_ARR[j])
678
+ // _rayDirection.copy(currentPolygon.plane.normal)
679
+ // _ray.direction.copy(currentPolygon.plane.normal)
680
+ // intersects = targetOctree.rayIntersect(_ray, targetOctree.originalMatrixWorld)
681
+ // if intersects.length
682
+ // if _rayDirection.dot(intersects[0].polygon.plane.normal) > 0
683
+ // inside = true
684
+ // break
685
+ // if inside is true
686
+ // currentPolygon.setState("inside")
687
+ // else
688
+ // currentPolygon.setState("outside")
689
+ // currentPolygon = polygonStack.pop()
690
+ // for i in [0...@subTrees.length]
691
+ // @subTrees[i].handleIntersectingPolygons(targetOctree, targetOctreeBuffer)
692
+ if (this.polygons.length > 0) {
693
+ polygonStack = this.polygons.filter(function(polygon) {
694
+ return (polygon.valid === true) && (polygon.intersects === true) && (polygon.state === "undecided");
695
+ });
696
+ currentPolygon = polygonStack.pop();
697
+ while (currentPolygon) {
698
+ if (currentPolygon.state !== "undecided") {
699
+ continue;
700
+ }
701
+ if (!currentPolygon.valid) {
702
+ continue;
703
+ }
704
+ targetPolygons = targetOctree.getPolygonsIntersectingPolygon(currentPolygon);
705
+ if (targetPolygons.length > 0) {
706
+ for (j = k = 0, ref = targetPolygons.length; (0 <= ref ? k < ref : k > ref); j = 0 <= ref ? ++k : --k) {
707
+ target = targetPolygons[j];
708
+ splitResults = splitPolygonByPlane(currentPolygon, target.plane);
709
+ if (splitResults.length > 1) {
710
+ for (i = l = 0, ref1 = splitResults.length; (0 <= ref1 ? l < ref1 : l > ref1); i = 0 <= ref1 ? ++l : --l) {
711
+ polygon = splitResults[i].polygon;
712
+ polygon.intersects = currentPolygon.intersects;
713
+ polygon.newPolygon = true;
714
+ polygonStack.push(polygon);
715
+ }
716
+ this.replacePolygon(currentPolygon, splitResults.map(function(result) {
717
+ return result.polygon;
718
+ }));
719
+ break;
720
+ } else {
721
+ if (currentPolygon.id !== splitResults[0].polygon.id) {
722
+ splitResults[0].polygon.intersects = currentPolygon.intersects;
723
+ splitResults[0].polygon.newPolygon = true;
724
+ polygonStack.push(splitResults[0].polygon);
725
+ this.replacePolygon(currentPolygon, splitResults[0].polygon);
726
+ break;
727
+ } else {
728
+ if ((splitResults[0].type === "coplanar-front") || (splitResults[0].type === "coplanar-back")) {
729
+ currentPolygon.setState(splitResults[0].type);
730
+ currentPolygon.coplanar = true;
731
+ }
732
+ }
733
+ }
734
+ }
735
+ }
736
+ currentPolygon = polygonStack.pop();
737
+ }
738
+ polygonStack = this.polygons.filter(function(polygon) {
739
+ return (polygon.valid === true) && (polygon.intersects === true);
740
+ });
741
+ currentPolygon = polygonStack.pop();
742
+ inside = false;
743
+ while (currentPolygon) {
744
+ if (!currentPolygon.valid) {
745
+ continue;
746
+ }
747
+ inside = false;
748
+ if (targetOctree.box.containsPoint(currentPolygon.getMidpoint())) {
749
+ if (OctreeCSG.useWindingNumber === true) {
750
+ inside = polyInside_WindingNumber_buffer(targetOctreeBuffer, currentPolygon.getMidpoint(), currentPolygon.coplanar);
751
+ } else {
752
+ point = pointRounding(_v2.copy(currentPolygon.getMidpoint()));
753
+ if (OctreeCSG.useOctreeRay !== true && targetOctree.mesh) {
754
+ _rayDirection.copy(currentPolygon.plane.normal);
755
+ _raycaster1.set(point, _rayDirection);
756
+ intersects = _raycaster1.intersectObject(targetOctree.mesh);
757
+ if (intersects.length) {
758
+ if (_rayDirection.dot(intersects[0].face.normal) > 0) {
759
+ inside = true;
760
+ }
761
+ }
762
+ if (!(inside || !currentPolygon.coplanar)) {
763
+ for (j = m = 0, ref2 = _wP_EPS_ARR_COUNT; (0 <= ref2 ? m < ref2 : m > ref2); j = 0 <= ref2 ? ++m : --m) {
764
+ _raycaster1.ray.origin.copy(point).add(_wP_EPS_ARR[j]);
765
+ intersects = _raycaster1.intersectObject(targetOctree.mesh);
766
+ if (intersects.length) {
767
+ if (_rayDirection.dot(intersects[0].face.normal) > 0) {
768
+ inside = true;
769
+ break;
770
+ }
771
+ }
772
+ }
773
+ }
774
+ } else {
775
+ _ray.origin.copy(point);
776
+ _rayDirection.copy(currentPolygon.plane.normal);
777
+ _ray.direction.copy(currentPolygon.plane.normal);
778
+ intersects = targetOctree.rayIntersect(_ray, targetOctree.originalMatrixWorld);
779
+ if (intersects.length) {
780
+ if (_rayDirection.dot(intersects[0].polygon.plane.normal) > 0) {
781
+ inside = true;
782
+ }
783
+ }
784
+ if (!(inside || !currentPolygon.coplanar)) {
785
+ for (j = o = 0, ref3 = _wP_EPS_ARR_COUNT; (0 <= ref3 ? o < ref3 : o > ref3); j = 0 <= ref3 ? ++o : --o) {
786
+ _ray.origin.copy(point).add(_wP_EPS_ARR[j]);
787
+ _rayDirection.copy(currentPolygon.plane.normal);
788
+ _ray.direction.copy(currentPolygon.plane.normal);
789
+ intersects = targetOctree.rayIntersect(_ray, targetOctree.originalMatrixWorld);
790
+ if (intersects.length) {
791
+ if (_rayDirection.dot(intersects[0].polygon.plane.normal) > 0) {
792
+ inside = true;
793
+ break;
794
+ }
795
+ }
796
+ }
797
+ }
798
+ }
799
+ }
800
+ }
801
+ if (inside === true) {
802
+ currentPolygon.setState("inside");
803
+ } else {
804
+ currentPolygon.setState("outside");
805
+ }
806
+ currentPolygon = polygonStack.pop();
807
+ }
808
+ }
809
+ results1 = [];
810
+ for (i = i1 = 0, ref4 = this.subTrees.length; (0 <= ref4 ? i1 < ref4 : i1 > ref4); i = 0 <= ref4 ? ++i1 : --i1) {
811
+ results1.push(this.subTrees[i].handleIntersectingPolygons(targetOctree, targetOctreeBuffer));
812
+ }
813
+ return results1;
814
+ }
815
+
816
+ delete(deletePolygons = true) {
817
+ var i, k, ref;
818
+ if (this.polygons.length > 0 && deletePolygons) {
819
+ this.polygons.forEach(function(p) {
820
+ return p.delete();
821
+ });
822
+ this.polygons.length = 0;
823
+ }
824
+ if (this.replacedPolygons.length > 0 && deletePolygons) {
825
+ this.replacedPolygons.forEach(function(p) {
826
+ return p.delete();
827
+ });
828
+ this.replacedPolygons.length = 0;
829
+ }
830
+ if (this.polygonArrays) {
831
+ this.polygonArrays.length = 0;
832
+ }
833
+ if (this.subTrees.length) {
834
+ for (i = k = 0, ref = this.subTrees.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
835
+ this.subTrees[i].delete(deletePolygons);
836
+ }
837
+ this.subTrees.length = 0;
838
+ }
839
+ this.mesh = void 0;
840
+ this.originalMatrixWorld = void 0;
841
+ this.box = void 0;
842
+ this.parent = void 0;
843
+ return this.level = void 0;
844
+ }
845
+
846
+ dispose(deletePolygons = true) {
847
+ return this.delete(deletePolygons);
848
+ }
849
+
850
+ getPolygonCloneCallback(cbFunc, trianglesSet) {
851
+ return this.polygonArrays.forEach(function(polygonsArray) {
852
+ var i, k, ref, results1;
853
+ if (polygonsArray.length) {
854
+ results1 = [];
855
+ for (i = k = 0, ref = polygonsArray.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
856
+ if (polygonsArray[i].valid) {
857
+ results1.push(cbFunc(polygonsArray[i].clone(), trianglesSet));
858
+ } else {
859
+ results1.push(void 0);
860
+ }
861
+ }
862
+ return results1;
863
+ }
864
+ });
865
+ }
866
+
867
+ // if @polygons.length > 0
868
+ // for i in [0...@polygons.length]
869
+ // if @polygons[i].valid
870
+ // cbFunc(@polygons[i].clone(), trianglesSet)
871
+ // for i in [0...@subTrees.length]
872
+ // @subTrees[i].getPolygonCloneCallback(cbFunc, trianglesSet)
873
+ deleteReplacedPolygons() {
874
+ var i, k, ref, results1;
875
+ if (this.replacedPolygons.length > 0) {
876
+ this.replacedPolygons.forEach(function(p) {
877
+ return p.delete();
878
+ });
879
+ this.replacedPolygons.length = 0;
880
+ }
881
+ results1 = [];
882
+ for (i = k = 0, ref = this.subTrees.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
883
+ results1.push(this.subTrees[i].deleteReplacedPolygons());
884
+ }
885
+ return results1;
886
+ }
887
+
888
+ markPolygonsAsOriginal() {
889
+ return this.polygonArrays.forEach(function(polygonsArray) {
890
+ if (polygonsArray.length) {
891
+ return polygonsArray.forEach(function(p) {
892
+ return p.originalValid = true;
893
+ });
894
+ }
895
+ });
896
+ }
897
+
898
+ // if @polygons.length > 0
899
+ // @polygons.forEach (p) -> p.originalValid = true
900
+ // for i in [0...@subTrees.length]
901
+ // @subTrees[i].markPolygonsAsOriginal()
902
+ applyMatrix(matrix, normalMatrix, firstRun = true) {
903
+ var i, k, l, ref, ref1;
904
+ if (matrix.isMesh) {
905
+ matrix.updateMatrix();
906
+ matrix = matrix.matrix;
907
+ }
908
+ this.box.makeEmpty();
909
+ normalMatrix = normalMatrix || tmpm3.getNormalMatrix(matrix);
910
+ if (this.polygons.length > 0) {
911
+ for (i = k = 0, ref = this.polygons.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
912
+ if (this.polygons[i].valid) {
913
+ this.polygons[i].applyMatrix(matrix, normalMatrix);
914
+ }
915
+ }
916
+ }
917
+ for (i = l = 0, ref1 = this.subTrees.length; (0 <= ref1 ? l < ref1 : l > ref1); i = 0 <= ref1 ? ++l : --l) {
918
+ this.subTrees[i].applyMatrix(matrix, normalMatrix, false);
919
+ }
920
+ if (firstRun) {
921
+ return this.processTree();
922
+ }
923
+ }
924
+
925
+ setPolygonIndex(index) {
926
+ if (index === void 0) {
927
+ return;
928
+ }
929
+ return this.polygonArrays.forEach(function(polygonsArray) {
930
+ if (polygonsArray.length) {
931
+ return polygonsArray.forEach(function(p) {
932
+ return p.shared = index;
933
+ });
934
+ }
935
+ });
936
+ }
937
+
938
+ };
939
+
940
+ // if @polygons.length > 0
941
+ // @polygons.forEach (p) -> p.shared = index
942
+ // for i in [0...@subTrees.length]
943
+ // @subTrees[i].setPolygonIndex(index)
944
+ OctreeCSG.prototype.isOctree = true;
945
+
946
+ raycastIntersectAscSort = function(a, b) {
947
+ return a.distance - b.distance;
948
+ };
949
+
950
+ pointRounding = function(point, num = 15) {
951
+ point.x = +point.x.toFixed(num);
952
+ point.y = +point.y.toFixed(num);
953
+ point.z = +point.z.toFixed(num);
954
+ return point;
955
+ };
956
+
957
+ splitPolygonByPlane = function(polygon, plane, result = []) {
958
+ var b, f, i, j, k, l, m, newPolys, npI, o, polygonType, ref, ref1, ref2, ref3, returnPolygon, t, ti, tj, type, types, v, vi, vj;
959
+ returnPolygon = {
960
+ polygon: polygon,
961
+ type: "undecided"
962
+ };
963
+ polygonType = 0;
964
+ types = [];
965
+ for (i = k = 0, ref = polygon.vertices.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
966
+ t = plane.normal.dot(polygon.vertices[i].pos) - plane.w;
967
+ type = t < -EPSILON ? BACK : t > EPSILON ? FRONT : COPLANAR;
968
+ polygonType |= type;
969
+ types.push(type);
970
+ }
971
+ switch (polygonType) {
972
+ case COPLANAR:
973
+ returnPolygon.type = plane.normal.dot(polygon.plane.normal) > 0 ? "coplanar-front" : "coplanar-back";
974
+ result.push(returnPolygon);
975
+ break;
976
+ case FRONT:
977
+ returnPolygon.type = "front";
978
+ result.push(returnPolygon);
979
+ break;
980
+ case BACK:
981
+ returnPolygon.type = "back";
982
+ result.push(returnPolygon);
983
+ break;
984
+ case SPANNING:
985
+ f = [];
986
+ b = [];
987
+ for (i = l = 0, ref1 = polygon.vertices.length; (0 <= ref1 ? l < ref1 : l > ref1); i = 0 <= ref1 ? ++l : --l) {
988
+ j = (i + 1) % polygon.vertices.length;
989
+ ti = types[i];
990
+ tj = types[j];
991
+ vi = polygon.vertices[i];
992
+ vj = polygon.vertices[j];
993
+ if (ti !== BACK) {
994
+ f.push(vi);
995
+ }
996
+ if (ti !== FRONT) {
997
+ b.push(ti !== BACK ? vi.clone() : vi);
998
+ }
999
+ if ((ti | tj) === SPANNING) {
1000
+ t = (plane.w - plane.normal.dot(vi.pos)) / plane.normal.dot(tv0.copy(vj.pos).sub(vi.pos));
1001
+ v = vi.interpolate(vj, t);
1002
+ f.push(v);
1003
+ b.push(v.clone());
1004
+ }
1005
+ }
1006
+ if (f.length >= 3) {
1007
+ if (f.length > 3) {
1008
+ newPolys = splitPolygonArr(f);
1009
+ for (npI = m = 0, ref2 = newPolys.length; (0 <= ref2 ? m < ref2 : m > ref2); npI = 0 <= ref2 ? ++m : --m) {
1010
+ result.push({
1011
+ polygon: new Polygon(newPolys[npI], polygon.shared),
1012
+ type: "front"
1013
+ });
1014
+ }
1015
+ } else {
1016
+ result.push({
1017
+ polygon: new Polygon(f, polygon.shared),
1018
+ type: "front"
1019
+ });
1020
+ }
1021
+ }
1022
+ if (b.length >= 3) {
1023
+ if (b.length > 3) {
1024
+ newPolys = splitPolygonArr(b);
1025
+ for (npI = o = 0, ref3 = newPolys.length; (0 <= ref3 ? o < ref3 : o > ref3); npI = 0 <= ref3 ? ++o : --o) {
1026
+ result.push({
1027
+ polygon: new Polygon(newPolys[npI], polygon.shared),
1028
+ type: "back"
1029
+ });
1030
+ }
1031
+ } else {
1032
+ result.push({
1033
+ polygon: new Polygon(b, polygon.shared),
1034
+ type: "back"
1035
+ });
1036
+ }
1037
+ }
1038
+ }
1039
+ if (result.length === 0) {
1040
+ result.push(returnPolygon);
1041
+ }
1042
+ return result;
1043
+ };
1044
+
1045
+ splitPolygonArr = function(arr) {
1046
+ var j, k, ref, result, resultArr;
1047
+ resultArr = [];
1048
+ if (arr.length > 4) {
1049
+ console.warn("[splitPolygonArr] arr.length > 4", arr.length);
1050
+ for (j = k = 3, ref = arr.length; (3 <= ref ? k <= ref : k >= ref); j = 3 <= ref ? ++k : --k) {
1051
+ result = [];
1052
+ result.push(arr[0].clone());
1053
+ result.push(arr[j - 2].clone());
1054
+ result.push(arr[j - 1].clone());
1055
+ resultArr.push(result);
1056
+ }
1057
+ } else {
1058
+ if (arr[0].pos.distanceTo(arr[2].pos) <= arr[1].pos.distanceTo(arr[3].pos)) {
1059
+ resultArr.push([arr[0].clone(), arr[1].clone(), arr[2].clone()], [arr[0].clone(), arr[2].clone(), arr[3].clone()]);
1060
+ } else {
1061
+ resultArr.push([arr[0].clone(), arr[1].clone(), arr[3].clone()], [arr[1].clone(), arr[2].clone(), arr[3].clone()]);
1062
+ }
1063
+ return resultArr;
1064
+ }
1065
+ return resultArr;
1066
+ };
1067
+
1068
+ CSG_Rules = {
1069
+ union: {
1070
+ a: [
1071
+ {
1072
+ array: true,
1073
+ rule: ["inside",
1074
+ "coplanar-back"]
1075
+ },
1076
+ {
1077
+ array: false,
1078
+ rule: "inside"
1079
+ }
1080
+ ],
1081
+ b: [
1082
+ {
1083
+ array: true,
1084
+ rule: ["inside",
1085
+ "coplanar-back"]
1086
+ },
1087
+ {
1088
+ array: true,
1089
+ rule: ["inside",
1090
+ "coplanar-front"]
1091
+ },
1092
+ {
1093
+ array: false,
1094
+ rule: "inside"
1095
+ }
1096
+ ]
1097
+ },
1098
+ subtract: {
1099
+ a: [
1100
+ {
1101
+ array: true,
1102
+ rule: ["inside",
1103
+ "coplanar-back"]
1104
+ },
1105
+ {
1106
+ array: true,
1107
+ rule: ["inside",
1108
+ "coplanar-front"]
1109
+ },
1110
+ {
1111
+ array: false,
1112
+ rule: "inside"
1113
+ }
1114
+ ],
1115
+ b: [
1116
+ {
1117
+ array: true,
1118
+ rule: ["outside",
1119
+ "coplanar-back"]
1120
+ },
1121
+ {
1122
+ array: true,
1123
+ rule: ["outside",
1124
+ "coplanar-front"]
1125
+ },
1126
+ {
1127
+ array: true,
1128
+ rule: ["inside",
1129
+ "coplanar-front"]
1130
+ },
1131
+ {
1132
+ array: false,
1133
+ rule: "outside"
1134
+ }
1135
+ ]
1136
+ },
1137
+ intersect: {
1138
+ a: [
1139
+ {
1140
+ array: true,
1141
+ rule: ["inside",
1142
+ "coplanar-back"]
1143
+ },
1144
+ {
1145
+ array: true,
1146
+ rule: ["outside",
1147
+ "coplanar-front"]
1148
+ },
1149
+ {
1150
+ array: true,
1151
+ rule: ["outside",
1152
+ "coplanar-back"]
1153
+ },
1154
+ {
1155
+ array: false,
1156
+ rule: "outside"
1157
+ }
1158
+ ],
1159
+ b: [
1160
+ {
1161
+ array: true,
1162
+ rule: ["inside",
1163
+ "coplanar-front"]
1164
+ },
1165
+ {
1166
+ array: true,
1167
+ rule: ["inside",
1168
+ "coplanar-back"]
1169
+ },
1170
+ {
1171
+ array: true,
1172
+ rule: ["outside",
1173
+ "coplanar-front"]
1174
+ },
1175
+ {
1176
+ array: true,
1177
+ rule: ["outside",
1178
+ "coplanar-back"]
1179
+ },
1180
+ {
1181
+ array: false,
1182
+ rule: "outside"
1183
+ }
1184
+ ]
1185
+ }
1186
+ };
1187
+
1188
+ // class OctreeCSG { };
1189
+ /*
1190
+ Union:
1191
+ - Combine all polygons from A and B, except:
1192
+ - Polygons in A that are inside B or coplanar-back with B
1193
+ - Polygons in B that are inside A or coplanar-back/front with A
1194
+ */
1195
+ /*
1196
+ Subtract:
1197
+ - Keep polygons from A that are outside B or coplanar-front with B
1198
+ - Keep polygons from B that are inside A and coplanar-front with A
1199
+ */
1200
+ /*
1201
+ Intersect:
1202
+ 1. Delete all polygons in A that are:
1203
+ a. inside and coplanar-back
1204
+ b. outside and coplanar-front
1205
+ c. outside and coplanar-back
1206
+ d. outside
1207
+ 2. Delete all polygons in B that are:
1208
+ a. inside and coplanar-front
1209
+ b. inside and coplanar-back
1210
+ c. outside and coplanar-front
1211
+ d. outside and coplanar-back
1212
+ e. outside
1213
+ */
1214
+ OctreeCSG.union = function(octreeA, octreeB, buildTargetOctree = true) {
1215
+ var currentMeshSideA, currentMeshSideB, octree, trianglesSet;
1216
+ octree = new OctreeCSG();
1217
+ trianglesSet = new Set();
1218
+ if (octreeA.box.intersectsBox(octreeB.box)) {
1219
+ currentMeshSideA = void 0;
1220
+ currentMeshSideB = void 0;
1221
+ if (octreeA.mesh) {
1222
+ currentMeshSideA = octreeA.mesh.material.side;
1223
+ octreeA.mesh.material.side = DoubleSide;
1224
+ }
1225
+ if (octreeB.mesh) {
1226
+ currentMeshSideB = octreeB.mesh.material.side;
1227
+ octreeB.mesh.material.side = DoubleSide;
1228
+ }
1229
+ octreeA.resetPolygons(false);
1230
+ octreeB.resetPolygons(false);
1231
+ octreeA.markIntesectingPolygons(octreeB);
1232
+ octreeB.markIntesectingPolygons(octreeA);
1233
+ handleIntersectingOctrees(octreeA, octreeB);
1234
+ octreeA.deleteReplacedPolygons();
1235
+ octreeB.deleteReplacedPolygons();
1236
+ octreeA.deletePolygonsByStateRules(CSG_Rules.union.a);
1237
+ octreeB.deletePolygonsByStateRules(CSG_Rules.union.b);
1238
+ octreeA.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1239
+ octreeB.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1240
+ if (octreeA.mesh && octreeA.mesh.material.side !== currentMeshSideA) {
1241
+ octreeA.mesh.material.side = currentMeshSideA;
1242
+ }
1243
+ if (octreeB.mesh && octreeB.mesh.material.side !== currentMeshSideB) {
1244
+ octreeB.mesh.material.side = currentMeshSideB;
1245
+ }
1246
+ } else {
1247
+ octreeA.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1248
+ octreeB.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1249
+ }
1250
+ trianglesSet.clear();
1251
+ trianglesSet = void 0;
1252
+ octree.markPolygonsAsOriginal();
1253
+ buildTargetOctree && octree.buildTree();
1254
+ return octree;
1255
+ };
1256
+
1257
+ OctreeCSG.subtract = function(octreeA, octreeB, buildTargetOctree = true) {
1258
+ var currentMeshSideA, currentMeshSideB, octree, trianglesSet;
1259
+ octree = new OctreeCSG();
1260
+ trianglesSet = new Set();
1261
+ if (octreeA.box.intersectsBox(octreeB.box)) {
1262
+ currentMeshSideA = void 0;
1263
+ currentMeshSideB = void 0;
1264
+ if (octreeA.mesh) {
1265
+ currentMeshSideA = octreeA.mesh.material.side;
1266
+ octreeA.mesh.material.side = DoubleSide;
1267
+ }
1268
+ if (octreeB.mesh) {
1269
+ currentMeshSideB = octreeB.mesh.material.side;
1270
+ octreeB.mesh.material.side = DoubleSide;
1271
+ }
1272
+ octreeA.resetPolygons(false);
1273
+ octreeB.resetPolygons(false);
1274
+ octreeA.markIntesectingPolygons(octreeB);
1275
+ octreeB.markIntesectingPolygons(octreeA);
1276
+ handleIntersectingOctrees(octreeA, octreeB);
1277
+ octreeA.deleteReplacedPolygons();
1278
+ octreeB.deleteReplacedPolygons();
1279
+ octreeA.deletePolygonsByStateRules(CSG_Rules.subtract.a);
1280
+ octreeB.deletePolygonsByStateRules(CSG_Rules.subtract.b);
1281
+ octreeB.deletePolygonsByIntersection(false);
1282
+ octreeB.invert();
1283
+ octreeA.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1284
+ octreeB.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1285
+ if (octreeA.mesh && octreeA.mesh.material.side !== currentMeshSideA) {
1286
+ octreeA.mesh.material.side = currentMeshSideA;
1287
+ }
1288
+ if (octreeB.mesh && octreeB.mesh.material.side !== currentMeshSideB) {
1289
+ octreeB.mesh.material.side = currentMeshSideB;
1290
+ }
1291
+ } else {
1292
+ octreeA.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1293
+ }
1294
+ trianglesSet.clear();
1295
+ trianglesSet = void 0;
1296
+ octree.markPolygonsAsOriginal();
1297
+ buildTargetOctree && octree.buildTree();
1298
+ // octree.invert()
1299
+ return octree;
1300
+ };
1301
+
1302
+ OctreeCSG.intersect = function(octreeA, octreeB, buildTargetOctree = true) {
1303
+ var currentMeshSideA, currentMeshSideB, octree, trianglesSet;
1304
+ octree = new OctreeCSG();
1305
+ trianglesSet = new Set();
1306
+ if (octreeA.box.intersectsBox(octreeB.box)) {
1307
+ currentMeshSideA = void 0;
1308
+ currentMeshSideB = void 0;
1309
+ if (octreeA.mesh) {
1310
+ currentMeshSideA = octreeA.mesh.material.side;
1311
+ octreeA.mesh.material.side = DoubleSide;
1312
+ }
1313
+ if (octreeB.mesh) {
1314
+ currentMeshSideB = octreeB.mesh.material.side;
1315
+ octreeB.mesh.material.side = DoubleSide;
1316
+ }
1317
+ octreeA.resetPolygons(false);
1318
+ octreeB.resetPolygons(false);
1319
+ octreeA.markIntesectingPolygons(octreeB);
1320
+ octreeB.markIntesectingPolygons(octreeA);
1321
+ handleIntersectingOctrees(octreeA, octreeB);
1322
+ octreeA.deleteReplacedPolygons();
1323
+ octreeB.deleteReplacedPolygons();
1324
+ octreeA.deletePolygonsByStateRules(CSG_Rules.intersect.a);
1325
+ octreeB.deletePolygonsByStateRules(CSG_Rules.intersect.b);
1326
+ octreeA.deletePolygonsByIntersection(false);
1327
+ octreeB.deletePolygonsByIntersection(false);
1328
+ octreeA.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1329
+ octreeB.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1330
+ if (octreeA.mesh && octreeA.mesh.material.side !== currentMeshSideA) {
1331
+ octreeA.mesh.material.side = currentMeshSideA;
1332
+ }
1333
+ if (octreeB.mesh && octreeB.mesh.material.side !== currentMeshSideB) {
1334
+ octreeB.mesh.material.side = currentMeshSideB;
1335
+ }
1336
+ }
1337
+ trianglesSet.clear();
1338
+ trianglesSet = void 0;
1339
+ return octree.markPolygons;
1340
+ };
1341
+
1342
+ CSG_Rules = {
1343
+ union: {
1344
+ a: [
1345
+ {
1346
+ array: true,
1347
+ rule: ["inside",
1348
+ "coplanar-back"]
1349
+ },
1350
+ {
1351
+ array: false,
1352
+ rule: "inside"
1353
+ }
1354
+ ],
1355
+ b: [
1356
+ {
1357
+ array: true,
1358
+ rule: ["inside",
1359
+ "coplanar-back"]
1360
+ },
1361
+ {
1362
+ array: true,
1363
+ rule: ["inside",
1364
+ "coplanar-front"]
1365
+ },
1366
+ {
1367
+ array: false,
1368
+ rule: "inside"
1369
+ }
1370
+ ]
1371
+ },
1372
+ subtract: {
1373
+ a: [
1374
+ {
1375
+ array: true,
1376
+ rule: ["inside",
1377
+ "coplanar-back"]
1378
+ },
1379
+ {
1380
+ array: true,
1381
+ rule: ["inside",
1382
+ "coplanar-front"]
1383
+ },
1384
+ {
1385
+ array: false,
1386
+ rule: "inside"
1387
+ }
1388
+ ],
1389
+ b: [
1390
+ {
1391
+ array: true,
1392
+ rule: ["outside",
1393
+ "coplanar-back"]
1394
+ },
1395
+ {
1396
+ array: true,
1397
+ rule: ["outside",
1398
+ "coplanar-front"]
1399
+ },
1400
+ {
1401
+ array: true,
1402
+ rule: ["inside",
1403
+ "coplanar-front"]
1404
+ },
1405
+ {
1406
+ array: false,
1407
+ rule: "outside"
1408
+ }
1409
+ ]
1410
+ },
1411
+ intersect: {
1412
+ a: [
1413
+ {
1414
+ array: true,
1415
+ rule: ["inside",
1416
+ "coplanar-back"]
1417
+ },
1418
+ {
1419
+ array: true,
1420
+ rule: ["outside",
1421
+ "coplanar-front"]
1422
+ },
1423
+ {
1424
+ array: true,
1425
+ rule: ["outside",
1426
+ "coplanar-back"]
1427
+ },
1428
+ {
1429
+ array: false,
1430
+ rule: "outside"
1431
+ }
1432
+ ],
1433
+ b: [
1434
+ {
1435
+ array: true,
1436
+ rule: ["inside",
1437
+ "coplanar-front"]
1438
+ },
1439
+ {
1440
+ array: true,
1441
+ rule: ["inside",
1442
+ "coplanar-back"]
1443
+ },
1444
+ {
1445
+ array: true,
1446
+ rule: ["outside",
1447
+ "coplanar-front"]
1448
+ },
1449
+ {
1450
+ array: true,
1451
+ rule: ["outside",
1452
+ "coplanar-back"]
1453
+ },
1454
+ {
1455
+ array: false,
1456
+ rule: "outside"
1457
+ }
1458
+ ]
1459
+ }
1460
+ };
1461
+
1462
+ // class OctreeCSG { };
1463
+ /*
1464
+ Union:
1465
+ - Combine all polygons from A and B, except:
1466
+ - Polygons in A that are inside B or coplanar-back with B
1467
+ - Polygons in B that are inside A or coplanar-back/front with A
1468
+ */
1469
+ /*
1470
+ Subtract:
1471
+ - Keep polygons from A that are outside B or coplanar-front with B
1472
+ - Keep polygons from B that are inside A and coplanar-front with A
1473
+ */
1474
+ /*
1475
+ Intersect:
1476
+ 1. Delete all polygons in A that are:
1477
+ a. inside and coplanar-back
1478
+ b. outside and coplanar-front
1479
+ c. outside and coplanar-back
1480
+ d. outside
1481
+ 2. Delete all polygons in B that are:
1482
+ a. inside and coplanar-front
1483
+ b. inside and coplanar-back
1484
+ c. outside and coplanar-front
1485
+ d. outside and coplanar-back
1486
+ e. outside
1487
+ */
1488
+ OctreeCSG.union = function(octreeA, octreeB, buildTargetOctree = true) {
1489
+ var currentMeshSideA, currentMeshSideB, octree, trianglesSet;
1490
+ octree = new OctreeCSG();
1491
+ trianglesSet = new Set();
1492
+ if (octreeA.box.intersectsBox(octreeB.box)) {
1493
+ currentMeshSideA = void 0;
1494
+ currentMeshSideB = void 0;
1495
+ if (octreeA.mesh) {
1496
+ currentMeshSideA = octreeA.mesh.material.side;
1497
+ octreeA.mesh.material.side = DoubleSide;
1498
+ }
1499
+ if (octreeB.mesh) {
1500
+ currentMeshSideB = octreeB.mesh.material.side;
1501
+ octreeB.mesh.material.side = DoubleSide;
1502
+ }
1503
+ octreeA.resetPolygons(false);
1504
+ octreeB.resetPolygons(false);
1505
+ octreeA.markIntesectingPolygons(octreeB);
1506
+ octreeB.markIntesectingPolygons(octreeA);
1507
+ handleIntersectingOctrees(octreeA, octreeB);
1508
+ octreeA.deleteReplacedPolygons();
1509
+ octreeB.deleteReplacedPolygons();
1510
+ octreeA.deletePolygonsByStateRules(CSG_Rules.union.a);
1511
+ octreeB.deletePolygonsByStateRules(CSG_Rules.union.b);
1512
+ octreeA.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1513
+ octreeB.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1514
+ if (octreeA.mesh && octreeA.mesh.material.side !== currentMeshSideA) {
1515
+ octreeA.mesh.material.side = currentMeshSideA;
1516
+ }
1517
+ if (octreeB.mesh && octreeB.mesh.material.side !== currentMeshSideB) {
1518
+ octreeB.mesh.material.side = currentMeshSideB;
1519
+ }
1520
+ } else {
1521
+ octreeA.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1522
+ octreeB.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1523
+ }
1524
+ trianglesSet.clear();
1525
+ trianglesSet = void 0;
1526
+ octree.markPolygonsAsOriginal();
1527
+ buildTargetOctree && octree.buildTree();
1528
+ return octree;
1529
+ };
1530
+
1531
+ OctreeCSG.subtract = function(octreeA, octreeB, buildTargetOctree = true) {
1532
+ var currentMeshSideA, currentMeshSideB, octree, trianglesSet;
1533
+ octree = new OctreeCSG();
1534
+ trianglesSet = new Set();
1535
+ if (octreeA.box.intersectsBox(octreeB.box)) {
1536
+ currentMeshSideA = void 0;
1537
+ currentMeshSideB = void 0;
1538
+ if (octreeA.mesh) {
1539
+ currentMeshSideA = octreeA.mesh.material.side;
1540
+ octreeA.mesh.material.side = DoubleSide;
1541
+ }
1542
+ if (octreeB.mesh) {
1543
+ currentMeshSideB = octreeB.mesh.material.side;
1544
+ octreeB.mesh.material.side = DoubleSide;
1545
+ }
1546
+ octreeA.resetPolygons(false);
1547
+ octreeB.resetPolygons(false);
1548
+ octreeA.markIntesectingPolygons(octreeB);
1549
+ octreeB.markIntesectingPolygons(octreeA);
1550
+ handleIntersectingOctrees(octreeA, octreeB);
1551
+ octreeA.deleteReplacedPolygons();
1552
+ octreeB.deleteReplacedPolygons();
1553
+ octreeA.deletePolygonsByStateRules(CSG_Rules.subtract.a);
1554
+ octreeB.deletePolygonsByStateRules(CSG_Rules.subtract.b);
1555
+ octreeB.deletePolygonsByIntersection(false);
1556
+ octreeB.invert();
1557
+ octreeA.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1558
+ octreeB.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1559
+ if (octreeA.mesh && octreeA.mesh.material.side !== currentMeshSideA) {
1560
+ octreeA.mesh.material.side = currentMeshSideA;
1561
+ }
1562
+ if (octreeB.mesh && octreeB.mesh.material.side !== currentMeshSideB) {
1563
+ octreeB.mesh.material.side = currentMeshSideB;
1564
+ }
1565
+ } else {
1566
+ octreeA.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1567
+ }
1568
+ trianglesSet.clear();
1569
+ trianglesSet = void 0;
1570
+ octree.markPolygonsAsOriginal();
1571
+ buildTargetOctree && octree.buildTree();
1572
+ // octree.invert()
1573
+ return octree;
1574
+ };
1575
+
1576
+ /*
1577
+ Intersect:
1578
+ 1. Delete all polygons in A that are:
1579
+ a. inside and coplanar-back
1580
+ b. outside and coplanar-front
1581
+ c. outside and coplanar-back
1582
+ d. outside
1583
+ 2. Delete all polygons in B that are:
1584
+ a. inside and coplanar-front
1585
+ b. inside and coplanar-back
1586
+ c. outside and coplanar-front
1587
+ d. outside and coplanar-back
1588
+ e. outside
1589
+ */
1590
+ OctreeCSG.intersect = function(octreeA, octreeB, buildTargetOctree = true) {
1591
+ var currentMeshSideA, currentMeshSideB, octree, trianglesSet;
1592
+ octree = new OctreeCSG();
1593
+ trianglesSet = new Set();
1594
+ if (octreeA.box.intersectsBox(octreeB.box)) {
1595
+ currentMeshSideA = void 0;
1596
+ currentMeshSideB = void 0;
1597
+ if (octreeA.mesh) {
1598
+ currentMeshSideA = octreeA.mesh.material.side;
1599
+ octreeA.mesh.material.side = DoubleSide;
1600
+ }
1601
+ if (octreeB.mesh) {
1602
+ currentMeshSideB = octreeB.mesh.material.side;
1603
+ octreeB.mesh.material.side = DoubleSide;
1604
+ }
1605
+ octreeA.resetPolygons(false);
1606
+ octreeB.resetPolygons(false);
1607
+ octreeA.markIntesectingPolygons(octreeB);
1608
+ octreeB.markIntesectingPolygons(octreeA);
1609
+ handleIntersectingOctrees(octreeA, octreeB);
1610
+ octreeA.deleteReplacedPolygons();
1611
+ octreeB.deleteReplacedPolygons();
1612
+ octreeA.deletePolygonsByStateRules(CSG_Rules.intersect.a);
1613
+ octreeB.deletePolygonsByStateRules(CSG_Rules.intersect.b);
1614
+ octreeA.deletePolygonsByIntersection(false);
1615
+ octreeB.deletePolygonsByIntersection(false);
1616
+ octreeA.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1617
+ octreeB.getPolygonCloneCallback(octree.addPolygon.bind(octree), trianglesSet);
1618
+ if (octreeA.mesh) {
1619
+ if (octreeA.mesh.material.side !== currentMeshSideA) {
1620
+ octreeA.mesh.material.side = currentMeshSideA;
1621
+ }
1622
+ }
1623
+ if (octreeB.mesh) {
1624
+ if (octreeB.mesh.material.side !== currentMeshSideB) {
1625
+ octreeB.mesh.material.side = currentMeshSideB;
1626
+ }
1627
+ }
1628
+ }
1629
+ trianglesSet.clear();
1630
+ trianglesSet = void 0;
1631
+ octree.markPolygonsAsOriginal();
1632
+ buildTargetOctree && octree.buildTree();
1633
+ return octree;
1634
+ };
1635
+
1636
+ OctreeCSG.meshUnion = function(mesh1, mesh2, targetMaterial) {
1637
+ var octreeA, octreeB, resultMesh, resultOctree;
1638
+ octreeA = void 0;
1639
+ octreeB = void 0;
1640
+ if (targetMaterial && Array.isArray(targetMaterial)) {
1641
+ octreeA = OctreeCSG.fromMesh(mesh1, 0);
1642
+ octreeB = OctreeCSG.fromMesh(mesh2, 1);
1643
+ } else {
1644
+ octreeA = OctreeCSG.fromMesh(mesh1);
1645
+ octreeB = OctreeCSG.fromMesh(mesh2);
1646
+ targetMaterial = targetMaterial !== void 0 ? targetMaterial : (Array.isArray(mesh1.material) ? mesh1.material[0] : mesh1.material).clone();
1647
+ }
1648
+ resultOctree = OctreeCSG.union(octreeA, octreeB, false);
1649
+ resultMesh = OctreeCSG.toMesh(resultOctree, targetMaterial);
1650
+ disposeOctree(octreeA, octreeB, resultOctree);
1651
+ return resultMesh;
1652
+ };
1653
+
1654
+ OctreeCSG.meshSubtract = function(mesh1, mesh2, targetMaterial) {
1655
+ var octreeA, octreeB, resultMesh, resultOctree;
1656
+ octreeA = void 0;
1657
+ octreeB = void 0;
1658
+ if (targetMaterial && Array.isArray(targetMaterial)) {
1659
+ octreeA = OctreeCSG.fromMesh(mesh1, 0);
1660
+ octreeB = OctreeCSG.fromMesh(mesh2, 1);
1661
+ } else {
1662
+ octreeA = OctreeCSG.fromMesh(mesh1);
1663
+ octreeB = OctreeCSG.fromMesh(mesh2);
1664
+ targetMaterial = targetMaterial !== void 0 ? targetMaterial : (Array.isArray(mesh1.material) ? mesh1.material[0] : mesh1.material).clone();
1665
+ }
1666
+ resultOctree = OctreeCSG.subtract(octreeA, octreeB, false);
1667
+ resultMesh = OctreeCSG.toMesh(resultOctree, targetMaterial);
1668
+ disposeOctree(octreeA, octreeB, resultOctree);
1669
+ return resultMesh;
1670
+ };
1671
+
1672
+ OctreeCSG.meshIntersect = function(mesh1, mesh2, targetMaterial) {
1673
+ var octreeA, octreeB, resultMesh, resultOctree;
1674
+ octreeA = void 0;
1675
+ octreeB = void 0;
1676
+ if (targetMaterial && Array.isArray(targetMaterial)) {
1677
+ octreeA = OctreeCSG.fromMesh(mesh1, 0);
1678
+ octreeB = OctreeCSG.fromMesh(mesh2, 1);
1679
+ } else {
1680
+ octreeA = OctreeCSG.fromMesh(mesh1);
1681
+ octreeB = OctreeCSG.fromMesh(mesh2);
1682
+ targetMaterial = targetMaterial !== void 0 ? targetMaterial : (Array.isArray(mesh1.material) ? mesh1.material[0] : mesh1.material).clone();
1683
+ }
1684
+ resultOctree = OctreeCSG.intersect(octreeA, octreeB, false);
1685
+ resultMesh = OctreeCSG.toMesh(resultOctree, targetMaterial);
1686
+ disposeOctree(octreeA, octreeB, resultOctree);
1687
+ return resultMesh;
1688
+ };
1689
+
1690
+ _asyncUnionID = 0;
1691
+
1692
+ _asyncUnionArrayID = 0;
1693
+
1694
+ OctreeCSG.disposeOctree = true;
1695
+
1696
+ OctreeCSG.async = {
1697
+ batchSize: 100,
1698
+ union: function(octreeA, octreeB, buildTargetOctree = true) {
1699
+ return new Promise(function(resolve, reject) {
1700
+ var e, result;
1701
+ try {
1702
+ // const id = _asyncUnionID++
1703
+ // console.log("Promise Union ##{id} started")
1704
+ result = OctreeCSG.union(octreeA, octreeB, buildTargetOctree);
1705
+ resolve(result);
1706
+ return disposeOctree(octreeA, octreeB);
1707
+ } catch (error) {
1708
+ e = error;
1709
+ return reject(e);
1710
+ }
1711
+ });
1712
+ },
1713
+ subtract: function(octreeA, octreeB, buildTargetOctree = true) {
1714
+ return new Promise(function(resolve, reject) {
1715
+ var e, result;
1716
+ try {
1717
+ result = OctreeCSG.subtract(octreeA, octreeB, buildTargetOctree);
1718
+ resolve(result);
1719
+ return disposeOctree(octreeA, octreeB);
1720
+ } catch (error) {
1721
+ e = error;
1722
+ return reject(e);
1723
+ }
1724
+ });
1725
+ },
1726
+ intersect: function(octreeA, octreeB, buildTargetOctree = true) {
1727
+ return new Promise(function(resolve, reject) {
1728
+ var e, result;
1729
+ try {
1730
+ result = OctreeCSG.intersect(octreeA, octreeB, buildTargetOctree);
1731
+ resolve(result);
1732
+ return disposeOctree(octreeA, octreeB);
1733
+ } catch (error) {
1734
+ e = error;
1735
+ return reject(e);
1736
+ }
1737
+ });
1738
+ },
1739
+ unionArray: function(objArr, materialIndexMax = 2e308) {
1740
+ return new Promise(function(resolve, reject) {
1741
+ var batch, batches, currentIndex, e, hasLeftOver, i, k, l, leftOverOctree, mainOctree, mainOctreeUsed, materialIndex, octreesArray, promise, promises, ref, ref1, result, tempOctree, usingBatches;
1742
+ try {
1743
+ usingBatches = OctreeCSG.async.batchSize > 4 && OctreeCSG.async.batchSize < objArr.length;
1744
+ // const id = _asyncUnionArrayID++
1745
+ // console.log("Promise Union Array ##{id}", usingBatches)
1746
+ mainOctree = void 0;
1747
+ mainOctreeUsed = false;
1748
+ promises = [];
1749
+ if (usingBatches) {
1750
+ batches = [];
1751
+ currentIndex = 0;
1752
+ while (currentIndex < objArr.length) {
1753
+ batches.push(objArr.slice(currentIndex, currentIndex + OctreeCSG.async.batchSize));
1754
+ currentIndex += OctreeCSG.async.batchSize;
1755
+ }
1756
+ batch = batches.shift();
1757
+ while (batch) {
1758
+ promise = OctreeCSG.async.unionArray(batch, 0);
1759
+ promises.push(promise);
1760
+ batch = batches.shift();
1761
+ }
1762
+ usingBatches = true;
1763
+ mainOctreeUsed = true;
1764
+ objArr.length = 0;
1765
+ } else {
1766
+ octreesArray = [];
1767
+ for (i = k = 0, ref = objArr.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
1768
+ materialIndex = i > materialIndexMax ? materialIndexMax : i;
1769
+ tempOctree = void 0;
1770
+ if (objArr[i].isMesh) {
1771
+ tempOctree = OctreeCSG.fromMesh(objArr[i], materialIndexMax > -1 ? materialIndex : void 0);
1772
+ } else {
1773
+ tempOctree = objArr[i];
1774
+ if (materialIndexMax > -1) {
1775
+ tempOctree.setPolygonIndex(materialIndex);
1776
+ }
1777
+ }
1778
+ tempOctree.octreeIndex = i;
1779
+ octreesArray.push(tempOctree);
1780
+ }
1781
+ mainOctree = octreesArray.shift();
1782
+ result = void 0;
1783
+ hasLeftOver = false;
1784
+ leftOverOctree = void 0;
1785
+ for (i = l = 0, ref1 = octreesArray.length; l < ref1; i = l += 2) {
1786
+ if (i + 1 >= octreesArray.length) {
1787
+ leftOverOctree = octreesArray[i];
1788
+ hasLeftOver = true;
1789
+ break;
1790
+ }
1791
+ promise = OctreeCSG.async.union(octreesArray[i], octreesArray[i + 1]);
1792
+ promises.push(promise);
1793
+ }
1794
+ if (leftOverOctree) {
1795
+ promise = OctreeCSG.async.union(mainOctree, leftOverOctree);
1796
+ promises.push(promise);
1797
+ mainOctreeUsed = true;
1798
+ }
1799
+ }
1800
+ return Promise.allSettled(promises).then(function(results) {
1801
+ var octrees;
1802
+ octrees = [];
1803
+ results.forEach(function(r) {
1804
+ if (r.status === "fulfilled") {
1805
+ return octrees.push(r.value);
1806
+ }
1807
+ });
1808
+ if (!mainOctreeUsed) {
1809
+ octrees.unshift(mainOctree);
1810
+ }
1811
+ if (octrees.length > 0) {
1812
+ if (octrees.length === 1) {
1813
+ return resolve(octrees[0]);
1814
+ } else if (octrees.length > 3) {
1815
+ return OctreeCSG.async.unionArray(octrees, usingBatches ? 0 : -1).then(function(result) {
1816
+ return resolve(result);
1817
+ }).catch(function(e) {
1818
+ return reject(e);
1819
+ });
1820
+ } else {
1821
+ return OctreeCSG.async.union(octrees[0], octrees[1]).then(function(result) {
1822
+ if (octrees.length === 3) {
1823
+ return OctreeCSG.async.union(result, octrees[2]).then(function(result) {
1824
+ return resolve(result);
1825
+ }).catch(function(e) {
1826
+ return reject(e);
1827
+ });
1828
+ } else {
1829
+ return resolve(result);
1830
+ }
1831
+ }).catch(function(e) {
1832
+ return reject(e);
1833
+ });
1834
+ }
1835
+ } else {
1836
+ return reject('Unable to find any result octree');
1837
+ }
1838
+ });
1839
+ } catch (error) {
1840
+ e = error;
1841
+ return reject(e);
1842
+ }
1843
+ });
1844
+ },
1845
+ subtractArray: function(objArr, materialIndexMax = 2e308) {
1846
+ return new Promise(function(resolve, reject) {
1847
+ var batch, batches, currentIndex, e, hasLeftOver, i, k, l, leftOverOctree, mainOctree, mainOctreeUsed, materialIndex, octreesArray, promise, promises, ref, ref1, result, tempOctree, usingBatches;
1848
+ try {
1849
+ usingBatches = OctreeCSG.async.batchSize > 4 && OctreeCSG.async.batchSize < objArr.length;
1850
+ mainOctree = void 0;
1851
+ mainOctreeUsed = false;
1852
+ promises = [];
1853
+ if (usingBatches) {
1854
+ batches = [];
1855
+ currentIndex = 0;
1856
+ while (currentIndex < objArr.length) {
1857
+ batches.push(objArr.slice(currentIndex, currentIndex + OctreeCSG.async.batchSize));
1858
+ currentIndex += OctreeCSG.async.batchSize;
1859
+ }
1860
+ batch = batches.shift();
1861
+ while (batch) {
1862
+ promise = OctreeCSG.async.subtractArray(batch, 0);
1863
+ promises.push(promise);
1864
+ batch = batches.shift();
1865
+ }
1866
+ usingBatches = true;
1867
+ mainOctreeUsed = true;
1868
+ objArr.length = 0;
1869
+ } else {
1870
+ octreesArray = [];
1871
+ for (i = k = 0, ref = objArr.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
1872
+ materialIndex = i > materialIndexMax ? materialIndexMax : i;
1873
+ tempOctree = void 0;
1874
+ if (objArr[i].isMesh) {
1875
+ tempOctree = OctreeCSG.fromMesh(objArr[i], materialIndexMax > -1 ? materialIndex : void 0);
1876
+ } else {
1877
+ tempOctree = objArr[i];
1878
+ if (materialIndexMax > -1) {
1879
+ tempOctree.setPolygonIndex(materialIndex);
1880
+ }
1881
+ }
1882
+ tempOctree.octreeIndex = i;
1883
+ octreesArray.push(tempOctree);
1884
+ }
1885
+ mainOctree = octreesArray.shift();
1886
+ result = void 0;
1887
+ hasLeftOver = false;
1888
+ leftOverOctree = void 0;
1889
+ for (i = l = 0, ref1 = octreesArray.length; l < ref1; i = l += 2) {
1890
+ if (i + 1 >= octreesArray.length) {
1891
+ leftOverOctree = octreesArray[i];
1892
+ hasLeftOver = true;
1893
+ break;
1894
+ }
1895
+ promise = OctreeCSG.async.subtract(octreesArray[i], octreesArray[i + 1]);
1896
+ promises.push(promise);
1897
+ }
1898
+ if (leftOverOctree) {
1899
+ promise = OctreeCSG.async.subtract(mainOctree, leftOverOctree);
1900
+ promises.push(promise);
1901
+ mainOctreeUsed = true;
1902
+ }
1903
+ }
1904
+ return Promise.allSettled(promises).then(function(results) {
1905
+ var octrees;
1906
+ octrees = [];
1907
+ results.forEach(function(r) {
1908
+ if (r.status === "fulfilled") {
1909
+ return octrees.push(r.value);
1910
+ }
1911
+ });
1912
+ if (!mainOctreeUsed) {
1913
+ octrees.unshift(mainOctree);
1914
+ }
1915
+ if (octrees.length > 0) {
1916
+ if (octrees.length === 1) {
1917
+ return resolve(octrees[0]);
1918
+ } else if (octrees.length > 3) {
1919
+ return OctreeCSG.async.subtractArray(octrees, usingBatches ? 0 : -1).then(function(result) {
1920
+ return resolve(result);
1921
+ }).catch(function(e) {
1922
+ return reject(e);
1923
+ });
1924
+ } else {
1925
+ return OctreeCSG.async.subtract(octrees[0], octrees[1]).then(function(result) {
1926
+ if (octrees.length === 3) {
1927
+ return OctreeCSG.async.subtract(result, octrees[2]).then(function(result) {
1928
+ return resolve(result);
1929
+ }).catch(function(e) {
1930
+ return reject(e);
1931
+ });
1932
+ } else {
1933
+ return resolve(result);
1934
+ }
1935
+ }).catch(function(e) {
1936
+ return reject(e);
1937
+ });
1938
+ }
1939
+ } else {
1940
+ return reject('Unable to find any result octree');
1941
+ }
1942
+ });
1943
+ } catch (error) {
1944
+ e = error;
1945
+ return reject(e);
1946
+ }
1947
+ });
1948
+ },
1949
+ intersectArray: function(objArr, materialIndexMax = 2e308) {
1950
+ return new Promise(function(resolve, reject) {
1951
+ var batch, batches, currentIndex, e, hasLeftOver, i, k, l, leftOverOctree, mainOctree, mainOctreeUsed, materialIndex, octreesArray, promise, promises, ref, ref1, result, tempOctree, usingBatches;
1952
+ try {
1953
+ usingBatches = OctreeCSG.async.batchSize > 4 && OctreeCSG.async.batchSize < objArr.length;
1954
+ mainOctree = void 0;
1955
+ mainOctreeUsed = false;
1956
+ promises = [];
1957
+ if (usingBatches) {
1958
+ batches = [];
1959
+ currentIndex = 0;
1960
+ while (currentIndex < objArr.length) {
1961
+ batches.push(objArr.slice(currentIndex, currentIndex + OctreeCSG.async.batchSize));
1962
+ currentIndex += OctreeCSG.async.batchSize;
1963
+ }
1964
+ batch = batches.shift();
1965
+ while (batch) {
1966
+ promise = OctreeCSG.async.intersectArray(batch, 0);
1967
+ promises.push(promise);
1968
+ batch = batches.shift();
1969
+ }
1970
+ usingBatches = true;
1971
+ mainOctreeUsed = true;
1972
+ objArr.length = 0;
1973
+ } else {
1974
+ octreesArray = [];
1975
+ for (i = k = 0, ref = objArr.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
1976
+ materialIndex = i > materialIndexMax ? materialIndexMax : i;
1977
+ tempOctree = void 0;
1978
+ if (objArr[i].isMesh) {
1979
+ tempOctree = OctreeCSG.fromMesh(objArr[i], materialIndexMax > -1 ? materialIndex : void 0);
1980
+ } else {
1981
+ tempOctree = objArr[i];
1982
+ if (materialIndexMax > -1) {
1983
+ tempOctree.setPolygonIndex(materialIndex);
1984
+ }
1985
+ }
1986
+ tempOctree.octreeIndex = i;
1987
+ octreesArray.push(tempOctree);
1988
+ }
1989
+ mainOctree = octreesArray.shift();
1990
+ result = void 0;
1991
+ hasLeftOver = false;
1992
+ leftOverOctree = void 0;
1993
+ for (i = l = 0, ref1 = octreesArray.length; l < ref1; i = l += 2) {
1994
+ if (i + 1 >= octreesArray.length) {
1995
+ leftOverOctree = octreesArray[i];
1996
+ hasLeftOver = true;
1997
+ break;
1998
+ }
1999
+ promise = OctreeCSG.async.intersect(octreesArray[i], octreesArray[i + 1]);
2000
+ promises.push(promise);
2001
+ }
2002
+ if (leftOverOctree) {
2003
+ promise = OctreeCSG.async.intersect(mainOctree, leftOverOctree);
2004
+ promises.push(promise);
2005
+ mainOctreeUsed = true;
2006
+ }
2007
+ }
2008
+ return Promise.allSettled(promises).then(function(results) {
2009
+ var octrees;
2010
+ octrees = [];
2011
+ results.forEach(function(r) {
2012
+ if (r.status === "fulfilled") {
2013
+ return octrees.push(r.value);
2014
+ }
2015
+ });
2016
+ if (!mainOctreeUsed) {
2017
+ octrees.unshift(mainOctree);
2018
+ }
2019
+ if (octrees.length > 0) {
2020
+ if (octrees.length === 1) {
2021
+ return resolve(octrees[0]);
2022
+ } else if (octrees.length > 3) {
2023
+ return OctreeCSG.async.intersectArray(octrees, usingBatches ? 0 : -1).then(function(result) {
2024
+ return resolve(result);
2025
+ }).catch(function(e) {
2026
+ return reject(e);
2027
+ });
2028
+ } else {
2029
+ return OctreeCSG.async.intersect(octrees[0], octrees[1]).then(function(result) {
2030
+ if (octrees.length === 3) {
2031
+ return OctreeCSG.async.intersect(result, octrees[2]).then(function(result) {
2032
+ return resolve(result);
2033
+ }).catch(function(e) {
2034
+ return reject(e);
2035
+ });
2036
+ } else {
2037
+ return resolve(result);
2038
+ }
2039
+ }).catch(function(e) {
2040
+ return reject(e);
2041
+ });
2042
+ }
2043
+ } else {
2044
+ return reject('Unable to find any result octree');
2045
+ }
2046
+ });
2047
+ } catch (error) {
2048
+ e = error;
2049
+ return reject(e);
2050
+ }
2051
+ });
2052
+ },
2053
+ operation: function(obj, returnOctrees = false, buildTargetOctree = true, options = {
2054
+ objCounter: 0
2055
+ }, firstRun = true) {
2056
+ return new Promise(function(resolve, reject) {
2057
+ var e, material, octreeA, octreeB, promise, promises, resultOctree;
2058
+ try {
2059
+ octreeA = void 0;
2060
+ octreeB = void 0;
2061
+ resultOctree = void 0;
2062
+ material = void 0;
2063
+ if (obj.material) {
2064
+ material = obj.material;
2065
+ }
2066
+ promises = [];
2067
+ if (obj.objA) {
2068
+ promise = handleObjectForOp_async(obj.objA, returnOctrees, buildTargetOctree, options, 0);
2069
+ promises.push(promise);
2070
+ }
2071
+ if (obj.objB) {
2072
+ promise = handleObjectForOp_async(obj.objB, returnOctrees, buildTargetOctree, options, 1);
2073
+ promises.push(promise);
2074
+ }
2075
+ return Promise.allSettled(promises).then(function(results) {
2076
+ var octrees, resultPromise;
2077
+ octrees = [];
2078
+ results.forEach(function(r) {
2079
+ if (r.status === "fulfilled") {
2080
+ if (r.value.objIndex === 0) {
2081
+ return octreeA = r.value;
2082
+ } else if (r.value.objIndex === 1) {
2083
+ return octreeB = r.value;
2084
+ }
2085
+ }
2086
+ });
2087
+ if (returnOctrees === true) {
2088
+ obj.objA = octreeA.original;
2089
+ octreeA = octreeA.result;
2090
+ obj.objB = octreeB.original;
2091
+ octreeB = octreeB.result;
2092
+ }
2093
+ resultPromise = void 0;
2094
+ switch (obj.op) {
2095
+ case 'union':
2096
+ resultPromise = OctreeCSG.async.union(octreeA, octreeB, buildTargetOctree);
2097
+ break;
2098
+ case 'subtract':
2099
+ resultPromise = OctreeCSG.async.subtract(octreeA, octreeB, buildTargetOctree);
2100
+ break;
2101
+ case 'intersect':
2102
+ resultPromise = OctreeCSG.async.intersect(octreeA, octreeB, buildTargetOctree);
2103
+ }
2104
+ return resultPromise.then(function(resultOctree) {
2105
+ var mesh;
2106
+ if (firstRun && material) {
2107
+ mesh = OctreeCSG.toMesh(resultOctree, material);
2108
+ if (!returnOctrees) {
2109
+ disposeOctree(resultOctree);
2110
+ }
2111
+ resolve(returnOctrees ? {
2112
+ result: mesh,
2113
+ operationTree: obj
2114
+ } : mesh);
2115
+ } else if (firstRun && returnOctrees) {
2116
+ resolve({
2117
+ result: resultOctree,
2118
+ operationTree: obj
2119
+ });
2120
+ } else {
2121
+ resolve(resultOctree);
2122
+ }
2123
+ if (!returnOctrees) {
2124
+ return disposeOctree(octreeA, octreeB);
2125
+ }
2126
+ }).catch(function(e) {
2127
+ return reject(e);
2128
+ });
2129
+ });
2130
+ } catch (error) {
2131
+ e = error;
2132
+ return reject(e);
2133
+ }
2134
+ });
2135
+ }
2136
+ };
2137
+
2138
+ OctreeCSG.unionArray = function(objArr, materialIndexMax = 2e308) {
2139
+ var i, k, materialIndex, octreeA, octreeB, octreesArray, ref, resultOctree, tempOctree;
2140
+ octreesArray = [];
2141
+ for (i = k = 0, ref = objArr.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
2142
+ materialIndex = i > materialIndexMax ? materialIndexMax : i;
2143
+ tempOctree = void 0;
2144
+ if (objArr[i].isMesh) {
2145
+ tempOctree = OctreeCSG.fromMesh(objArr[i], materialIndex);
2146
+ } else {
2147
+ tempOctree = objArr[i];
2148
+ tempOctree.setPolygonIndex(materialIndex);
2149
+ }
2150
+ tempOctree.octreeIndex = i;
2151
+ octreesArray.push(tempOctree);
2152
+ }
2153
+ octreeA = octreesArray.shift();
2154
+ octreeB = octreesArray.shift();
2155
+ while (octreeA && octreeB) {
2156
+ resultOctree = OctreeCSG.union(octreeA, octreeB);
2157
+ disposeOctree(octreeA, octreeB);
2158
+ octreeA = resultOctree;
2159
+ octreeB = octreesArray.shift();
2160
+ }
2161
+ return octreeA;
2162
+ };
2163
+
2164
+ OctreeCSG.subtractArray = function(objArr, materialIndexMax = 2e308) {
2165
+ var i, k, materialIndex, octreeA, octreeB, octreesArray, ref, resultOctree, tempOctree;
2166
+ octreesArray = [];
2167
+ for (i = k = 0, ref = objArr.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
2168
+ materialIndex = i > materialIndexMax ? materialIndexMax : i;
2169
+ tempOctree = void 0;
2170
+ if (objArr[i].isMesh) {
2171
+ tempOctree = OctreeCSG.fromMesh(objArr[i], materialIndex);
2172
+ } else {
2173
+ tempOctree = objArr[i];
2174
+ tempOctree.setPolygonIndex(materialIndex);
2175
+ }
2176
+ tempOctree.octreeIndex = i;
2177
+ octreesArray.push(tempOctree);
2178
+ }
2179
+ octreeA = octreesArray.shift();
2180
+ octreeB = octreesArray.shift();
2181
+ while (octreeA && octreeB) {
2182
+ resultOctree = OctreeCSG.subtract(octreeA, octreeB);
2183
+ disposeOctree(octreeA, octreeB);
2184
+ octreeA = resultOctree;
2185
+ octreeB = octreesArray.shift();
2186
+ }
2187
+ return octreeA;
2188
+ };
2189
+
2190
+ OctreeCSG.intersectArray = function(objArr, materialIndexMax = 2e308) {
2191
+ var i, k, materialIndex, octreeA, octreeB, octreesArray, ref, resultOctree, tempOctree;
2192
+ octreesArray = [];
2193
+ for (i = k = 0, ref = objArr.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
2194
+ materialIndex = i > materialIndexMax ? materialIndexMax : i;
2195
+ tempOctree = void 0;
2196
+ if (objArr[i].isMesh) {
2197
+ tempOctree = OctreeCSG.fromMesh(objArr[i], materialIndex);
2198
+ } else {
2199
+ tempOctree = objArr[i];
2200
+ tempOctree.setPolygonIndex(materialIndex);
2201
+ }
2202
+ tempOctree.octreeIndex = i;
2203
+ octreesArray.push(tempOctree);
2204
+ }
2205
+ octreeA = octreesArray.shift();
2206
+ octreeB = octreesArray.shift();
2207
+ while (octreeA && octreeB) {
2208
+ resultOctree = OctreeCSG.intersect(octreeA, octreeB);
2209
+ disposeOctree(octreeA, octreeB);
2210
+ octreeA = resultOctree;
2211
+ octreeB = octreesArray.shift();
2212
+ }
2213
+ return octreeA;
2214
+ };
2215
+
2216
+ OctreeCSG.operation = function(obj, returnOctrees = false, buildTargetOctree = true, options = {
2217
+ objCounter: 0
2218
+ }, firstRun = true) {
2219
+ var material, mesh, octreeA, octreeB, resultOctree;
2220
+ octreeA = void 0;
2221
+ octreeB = void 0;
2222
+ resultOctree = void 0;
2223
+ material = void 0;
2224
+ if (obj.material) {
2225
+ material = obj.material;
2226
+ }
2227
+ if (obj.objA) {
2228
+ octreeA = handleObjectForOp(obj.objA, returnOctrees, buildTargetOctree, options);
2229
+ if (returnOctrees === true) {
2230
+ obj.objA = octreeA.original;
2231
+ octreeA = octreeA.result;
2232
+ }
2233
+ }
2234
+ if (obj.objB) {
2235
+ octreeB = handleObjectForOp(obj.objB, returnOctrees, buildTargetOctree, options);
2236
+ if (returnOctrees === true) {
2237
+ obj.objB = octreeB.original;
2238
+ octreeB = octreeB.result;
2239
+ }
2240
+ }
2241
+ switch (obj.op) {
2242
+ case 'union':
2243
+ resultOctree = OctreeCSG.union(octreeA, octreeB, buildTargetOctree);
2244
+ break;
2245
+ case 'subtract':
2246
+ resultOctree = OctreeCSG.subtract(octreeA, octreeB, buildTargetOctree);
2247
+ break;
2248
+ case 'intersect':
2249
+ resultOctree = OctreeCSG.intersect(octreeA, octreeB, buildTargetOctree);
2250
+ }
2251
+ if (!returnOctrees) {
2252
+ disposeOctree(octreeA, octreeB);
2253
+ }
2254
+ if (firstRun && material) {
2255
+ mesh = OctreeCSG.toMesh(resultOctree, material);
2256
+ disposeOctree(resultOctree);
2257
+ if (returnOctrees) {
2258
+ return {
2259
+ result: mesh,
2260
+ operationTree: obj
2261
+ };
2262
+ } else {
2263
+ return mesh;
2264
+ }
2265
+ }
2266
+ if (firstRun && returnOctrees) {
2267
+ return {
2268
+ result: resultOctree,
2269
+ operationTree: obj
2270
+ };
2271
+ }
2272
+ return resultOctree;
2273
+ };
2274
+
2275
+ handleObjectForOp = function(obj, returnOctrees, buildTargetOctree, options) {
2276
+ var returnObj;
2277
+ returnObj = void 0;
2278
+ if (obj.isMesh) {
2279
+ returnObj = OctreeCSG.fromMesh(obj, options.objCounter++);
2280
+ if (returnOctrees) {
2281
+ returnObj = {
2282
+ result: returnObj,
2283
+ original: returnObj.clone()
2284
+ };
2285
+ }
2286
+ } else if (obj.isOctree) {
2287
+ returnObj = obj;
2288
+ if (returnOctrees) {
2289
+ returnObj = {
2290
+ result: obj,
2291
+ original: obj.clone()
2292
+ };
2293
+ }
2294
+ } else if (obj.op) {
2295
+ returnObj = OctreeCSG.operation(obj, returnOctrees, buildTargetOctree, options, false);
2296
+ if (returnOctrees) {
2297
+ returnObj = {
2298
+ result: returnObj,
2299
+ original: obj
2300
+ };
2301
+ }
2302
+ }
2303
+ return returnObj;
2304
+ };
2305
+
2306
+ handleObjectForOp_async = function(obj, returnOctrees, buildTargetOctree, options, objIndex) {
2307
+ return new Promise(function(resolve, reject) {
2308
+ var e, returnObj;
2309
+ try {
2310
+ returnObj = void 0;
2311
+ if (obj.isMesh) {
2312
+ returnObj = OctreeCSG.fromMesh(obj, options.objCounter++);
2313
+ if (returnOctrees) {
2314
+ returnObj = {
2315
+ result: returnObj,
2316
+ original: returnObj.clone()
2317
+ };
2318
+ }
2319
+ returnObj.objIndex = objIndex;
2320
+ return resolve(returnObj);
2321
+ } else if (obj.isOctree) {
2322
+ returnObj = obj;
2323
+ if (returnOctrees) {
2324
+ returnObj = {
2325
+ result: obj,
2326
+ original: obj.clone()
2327
+ };
2328
+ }
2329
+ returnObj.objIndex = objIndex;
2330
+ return resolve(returnObj);
2331
+ } else if (obj.op) {
2332
+ return OctreeCSG.async.operation(obj, returnOctrees, buildTargetOctree, options, false).then(function(returnObj) {
2333
+ if (returnOctrees) {
2334
+ returnObj = {
2335
+ result: returnObj,
2336
+ original: obj
2337
+ };
2338
+ }
2339
+ returnObj.objIndex = objIndex;
2340
+ return resolve(returnObj);
2341
+ });
2342
+ }
2343
+ } catch (error) {
2344
+ e = error;
2345
+ return reject(e);
2346
+ }
2347
+ });
2348
+ };
2349
+
2350
+ isUniqueTriangle = function(triangle, set, map) {
2351
+ var hash1;
2352
+ hash1 = `{${triangle.a.x},${triangle.a.y},${triangle.a.z}}-{${triangle.b.x},${triangle.b.y},${triangle.b.z}}-{${triangle.c.x},${triangle.c.y},${triangle.c.z}}`;
2353
+ if (set.has(hash1) === true) {
2354
+ return false;
2355
+ } else {
2356
+ set.add(hash1);
2357
+ if (map) {
2358
+ map.set(triangle, triangle);
2359
+ }
2360
+ return true;
2361
+ }
2362
+ };
2363
+
2364
+ nbuf3 = function(ct) {
2365
+ return {
2366
+ top: 0,
2367
+ array: new Float32Array(ct),
2368
+ write: function(v) {
2369
+ this.array[this.top++] = v.x;
2370
+ this.array[this.top++] = v.y;
2371
+ return this.array[this.top++] = v.z;
2372
+ }
2373
+ };
2374
+ };
2375
+
2376
+ nbuf2 = function(ct) {
2377
+ return {
2378
+ top: 0,
2379
+ array: new Float32Array(ct),
2380
+ write: function(v) {
2381
+ this.array[this.top++] = v.x;
2382
+ return this.array[this.top++] = v.y;
2383
+ }
2384
+ };
2385
+ };
2386
+
2387
+ _normal1 = new Vector3();
2388
+
2389
+ tmpm3 = new Matrix3();
2390
+
2391
+ ttvv0 = new Vector3();
2392
+
2393
+ OctreeCSG.toGeometry = function(octree) {
2394
+ var colors, defaultGroup, geometry, groupBase, groups, i, index, k, l, len1, m, normals, polygon, polygons, positions, ref, ref1, triangleCount, uvs, vertices, verticesLen;
2395
+ polygons = octree.getPolygons();
2396
+ triangleCount = polygons.length;
2397
+ // let validPolygons = [];
2398
+ // let trianglesSet = new Set();
2399
+ // let duplicateCount = 0;
2400
+
2401
+ // let triangleCount = 0;
2402
+ // polygons.forEach(polygon => {
2403
+ // if (isUniqueTriangle(polygon.triangle, trianglesSet)) {
2404
+ // triangleCount += (polygon.vertices.length - 2);
2405
+ // validPolygons.push(polygon);
2406
+ // }
2407
+ // });
2408
+
2409
+ // trianglesSet.clear();
2410
+ // trianglesSet = undefined;
2411
+ positions = nbuf3(triangleCount * 3 * 3);
2412
+ normals = nbuf3(triangleCount * 3 * 3);
2413
+ uvs = void 0;
2414
+ colors = void 0;
2415
+ groups = [];
2416
+ defaultGroup = [];
2417
+ for (k = 0, len1 = polygons.length; k < len1; k++) {
2418
+ polygon = polygons[k];
2419
+ vertices = polygon.vertices;
2420
+ verticesLen = vertices.length;
2421
+ if (polygon.shared !== void 0) {
2422
+ if (!groups[polygon.shared]) {
2423
+ groups[polygon.shared] = [];
2424
+ }
2425
+ }
2426
+ if (verticesLen > 0) {
2427
+ if (vertices[0].uv !== void 0) {
2428
+ uvs || (uvs = nbuf2(triangleCount * 2 * 3));
2429
+ }
2430
+ if (vertices[0].color !== void 0) {
2431
+ colors || (colors = nbuf3(triangleCount * 3 * 3));
2432
+ }
2433
+ }
2434
+ for (i = l = 3, ref = verticesLen; (3 <= ref ? l <= ref : l >= ref); i = 3 <= ref ? ++l : --l) {
2435
+ (polygon.shared === void 0 ? defaultGroup : groups[polygon.shared]).push(positions.top / 3, (positions.top / 3) + 1, (positions.top / 3) + 2);
2436
+ positions.write(vertices[0].pos);
2437
+ positions.write(vertices[i - 2].pos);
2438
+ positions.write(vertices[i - 1].pos);
2439
+ normals.write(vertices[0].normal);
2440
+ normals.write(vertices[i - 2].normal);
2441
+ normals.write(vertices[i - 1].normal);
2442
+ if (uvs != null) {
2443
+ uvs.write(vertices[0].uv);
2444
+ uvs.write(vertices[i - 2].uv);
2445
+ uvs.write(vertices[i - 1].uv);
2446
+ }
2447
+ if (colors != null) {
2448
+ colors.write(vertices[0].color);
2449
+ colors.write(vertices[i - 2].color);
2450
+ colors.write(vertices[i - 1].color);
2451
+ }
2452
+ }
2453
+ }
2454
+ geometry = new BufferGeometry();
2455
+ geometry.setAttribute('position', new BufferAttribute(positions.array, 3));
2456
+ geometry.setAttribute('normal', new BufferAttribute(normals.array, 3));
2457
+ uvs && geometry.setAttribute('uv', new BufferAttribute(uvs.array, 2));
2458
+ colors && geometry.setAttribute('color', new BufferAttribute(colors.array, 3));
2459
+ if (groups.length > 0) {
2460
+ index = [];
2461
+ groupBase = 0;
2462
+ for (i = m = 0, ref1 = groups.length; (0 <= ref1 ? m < ref1 : m > ref1); i = 0 <= ref1 ? ++m : --m) {
2463
+ groups[i] = groups[i] || [];
2464
+ geometry.addGroup(groupBase, groups[i].length, i);
2465
+ groupBase += groups[i].length;
2466
+ index = index.concat(groups[i]);
2467
+ }
2468
+ if (defaultGroup.length) {
2469
+ geometry.addGroup(groupBase, defaultGroup.length, groups.length);
2470
+ index = index.concat(defaultGroup);
2471
+ }
2472
+ geometry.setIndex(index);
2473
+ }
2474
+ return geometry;
2475
+ };
2476
+
2477
+ OctreeCSG.toMesh = function(octree, toMaterial) {
2478
+ var geometry;
2479
+ geometry = OctreeCSG.toGeometry(octree);
2480
+ return new Mesh(geometry, toMaterial);
2481
+ };
2482
+
2483
+ OctreeCSG.fromMesh = function(obj, objectIndex, octree = new OctreeCSG(), buildTargetOctree = true) {
2484
+ var color, colorattr, geometry, group, groups, i, index, j, k, l, len1, m, normal, normalattr, o, polygon, polys, pos, posattr, ref, ref1, uv, uvattr, vertices, vi, vp, vt;
2485
+ if (obj.isOctree) {
2486
+ return obj;
2487
+ }
2488
+ if (OctreeCSG.rayIntersectTriangleType === "regular") {
2489
+ octree.originalMatrixWorld = obj.matrixWorld.clone();
2490
+ }
2491
+ obj.updateWorldMatrix(true, true);
2492
+ geometry = obj.geometry;
2493
+ tmpm3.getNormalMatrix(obj.matrix);
2494
+ posattr = geometry.attributes.position;
2495
+ normalattr = geometry.attributes.normal;
2496
+ uvattr = geometry.attributes.uv;
2497
+ colorattr = geometry.attributes.color;
2498
+ groups = geometry.groups;
2499
+ index = geometry.index ? geometry.index.array : Array((posattr.array.length / posattr.itemSize) | 0).fill().map(function(_, i) {
2500
+ return i;
2501
+ });
2502
+ polys = [];
2503
+ for (i = k = 0, ref = index.length; k < ref; i = k += 3) {
2504
+ vertices = [];
2505
+ for (j = l = 0; l < 3; j = ++l) {
2506
+ vi = index[i + j];
2507
+ vp = vi * 3;
2508
+ vt = vi * 2;
2509
+ pos = new Vector3(posattr.array[vp], posattr.array[vp + 1], posattr.array[vp + 2]);
2510
+ normal = new Vector3(normalattr.array[vp], normalattr.array[vp + 1], normalattr.array[vp + 2]);
2511
+ pos.applyMatrix4(obj.matrix);
2512
+ normal.applyMatrix3(tmpm3);
2513
+ uv = uvattr ? {
2514
+ x: uvattr.array[vt],
2515
+ y: uvattr.array[vt + 1]
2516
+ } : void 0;
2517
+ color = colorattr ? {
2518
+ x: colorattr.array[vt],
2519
+ y: colorattr.array[vt + 1],
2520
+ z: colorattr.array[vt + 2]
2521
+ } : void 0;
2522
+ vertices.push(new Vertex(pos, normal, uv, color));
2523
+ }
2524
+ if ((objectIndex === void 0) && groups && groups.length > 0) {
2525
+ polygon = void 0;
2526
+ for (m = 0, len1 = groups.length; m < len1; m++) {
2527
+ group = groups[m];
2528
+ if ((index[i] >= group.start) && (index[i] < (group.start + group.count))) {
2529
+ polygon = new Polygon(vertices, group.materialIndex);
2530
+ polygon.originalValid = true;
2531
+ }
2532
+ }
2533
+ if (polygon) {
2534
+ polys.push(polygon);
2535
+ }
2536
+ } else {
2537
+ polygon = new Polygon(vertices, objectIndex);
2538
+ polygon.originalValid = true;
2539
+ polys.push(polygon);
2540
+ }
2541
+ }
2542
+ for (i = o = 0, ref1 = polys.length; (0 <= ref1 ? o < ref1 : o > ref1); i = 0 <= ref1 ? ++o : --o) {
2543
+ if (isValidTriangle(polys[i].triangle)) {
2544
+ octree.addPolygon(polys[i]);
2545
+ } else {
2546
+ polys[i].delete();
2547
+ }
2548
+ }
2549
+ buildTargetOctree && octree.buildTree();
2550
+ if (OctreeCSG.useOctreeRay !== true) {
2551
+ octree.mesh = obj;
2552
+ }
2553
+ return octree;
2554
+ };
2555
+
2556
+ isValidTriangle = function(triangle) {
2557
+ if (triangle.a.equals(triangle.b)) {
2558
+ return false;
2559
+ }
2560
+ if (triangle.a.equals(triangle.c)) {
2561
+ return false;
2562
+ }
2563
+ if (triangle.b.equals(triangle.c)) {
2564
+ return false;
2565
+ }
2566
+ return true;
2567
+ };
2568
+
2569
+ // class Vertex
2570
+ Vertex = class Vertex {
2571
+ constructor(pos, normal, uv, color) {
2572
+ this.pos = new Vector3().copy(pos);
2573
+ this.normal = new Vector3().copy(normal);
2574
+ uv && (this.uv = new Vector2().copy(uv));
2575
+ color && (this.color = new Vector3().copy(color));
2576
+ }
2577
+
2578
+ clone() {
2579
+ return new Vertex(this.pos.clone(), this.normal.clone(), this.uv && this.uv.clone(), this.color && this.color.clone());
2580
+ }
2581
+
2582
+ flip() {
2583
+ return this.normal.negate();
2584
+ }
2585
+
2586
+ delete() {
2587
+ this.pos = void 0;
2588
+ this.normal = void 0;
2589
+ this.uv && (this.uv = void 0);
2590
+ return this.color && (this.color = void 0);
2591
+ }
2592
+
2593
+ interpolate(other, t) {
2594
+ return new Vertex(this.pos.clone().lerp(other.pos, t), this.normal.clone().lerp(other.normal, t), this.uv && other.uv && this.uv.clone().lerp(other.uv, t), this.color && other.color && this.color.clone().lerp(other.color, t));
2595
+ }
2596
+
2597
+ };
2598
+
2599
+ // class Plane
2600
+ Plane = class Plane {
2601
+ constructor(normal, w) {
2602
+ this.normal = normal;
2603
+ this.w = w;
2604
+ }
2605
+
2606
+ clone() {
2607
+ return new Plane(this.normal.clone(), this.w);
2608
+ }
2609
+
2610
+ flip() {
2611
+ this.normal.negate();
2612
+ return this.w = -this.w;
2613
+ }
2614
+
2615
+ delete() {
2616
+ this.normal = void 0;
2617
+ return this.w = void 0;
2618
+ }
2619
+
2620
+ equals(p) {
2621
+ return this.normal.equals(p.normal) && this.w === p.w;
2622
+ }
2623
+
2624
+ };
2625
+
2626
+ Plane.fromPoints = function(a, b, c) {
2627
+ var n;
2628
+ n = tv0.copy(b).sub(a).cross(tv1.copy(c).sub(a)).normalize().clone();
2629
+ return new Plane(n, n.dot(a));
2630
+ };
2631
+
2632
+ // class Polygon
2633
+ Polygon = class Polygon {
2634
+ constructor(vertices, shared) {
2635
+ this.id = _polygonID++;
2636
+ this.vertices = vertices.map(function(v) {
2637
+ return v.clone();
2638
+ });
2639
+ this.shared = shared;
2640
+ this.plane = Plane.fromPoints(this.vertices[0].pos, this.vertices[1].pos, this.vertices[2].pos);
2641
+ this.triangle = new Triangle(this.vertices[0].pos, this.vertices[1].pos, this.vertices[2].pos);
2642
+ this.intersects = false;
2643
+ this.state = "undecided";
2644
+ this.previousState = "undecided";
2645
+ this.previousStates = [];
2646
+ this.valid = true;
2647
+ this.coplanar = false;
2648
+ this.originalValid = false;
2649
+ this.newPolygon = false;
2650
+ }
2651
+
2652
+ getMidpoint() {
2653
+ if (this.triangle.midPoint) {
2654
+ return this.triangle.midPoint;
2655
+ } else {
2656
+ return this.triangle.midPoint = this.triangle.getMidpoint(new Vector3());
2657
+ }
2658
+ }
2659
+
2660
+ applyMatrix(matrix, normalMatrix) {
2661
+ normalMatrix = normalMatrix || tmpm3.getNormalMatrix(matrix);
2662
+ this.vertices.forEach(function(v) {
2663
+ v.pos.applyMatrix4(matrix);
2664
+ return v.normal.applyMatrix3(normalMatrix);
2665
+ });
2666
+ this.plane.delete();
2667
+ this.plane = Plane.fromPoints(this.vertices[0].pos, this.vertices[1].pos, this.vertices[2].pos);
2668
+ this.triangle.set(this.vertices[0].pos, this.vertices[1].pos, this.vertices[2].pos);
2669
+ if (this.triangle.midPoint) {
2670
+ return this.triangle.getMidpoint(this.triangle.midPoint);
2671
+ }
2672
+ }
2673
+
2674
+ reset(resetOriginal = true) {
2675
+ this.intersects = false;
2676
+ this.state = "undecided";
2677
+ this.previousState = "undecided";
2678
+ this.previousStates.length = 0;
2679
+ this.valid = true;
2680
+ this.coplanar = false;
2681
+ resetOriginal && (this.originalValid = false);
2682
+ return this.newPolygon = false;
2683
+ }
2684
+
2685
+ setState(state, keepState) {
2686
+ if (this.state === keepState) {
2687
+ return;
2688
+ }
2689
+ this.previousState = this.state;
2690
+ this.state !== "undecided" && this.previousStates.push(this.state);
2691
+ return this.state = state;
2692
+ }
2693
+
2694
+ checkAllStates(state) {
2695
+ var k, len1, ref, s;
2696
+ if ((this.state !== state) || ((this.previousState !== state) && (this.previousState !== "undecided"))) {
2697
+ return false;
2698
+ }
2699
+ ref = this.previousStates;
2700
+ for (k = 0, len1 = ref.length; k < len1; k++) {
2701
+ s = ref[k];
2702
+ if (s !== state) {
2703
+ return false;
2704
+ }
2705
+ }
2706
+ return true;
2707
+ }
2708
+
2709
+ setInvalid() {
2710
+ return this.valid = false;
2711
+ }
2712
+
2713
+ setValid() {
2714
+ return this.valid = true;
2715
+ }
2716
+
2717
+ clone() {
2718
+ var polygon;
2719
+ polygon = new Polygon(this.vertices.map(function(v) {
2720
+ return v.clone();
2721
+ }), this.shared);
2722
+ polygon.intersects = this.intersects;
2723
+ polygon.valid = this.valid;
2724
+ polygon.coplanar = this.coplanar;
2725
+ polygon.state = this.state;
2726
+ polygon.originalValid = this.originalValid;
2727
+ polygon.newPolygon = this.newPolygon;
2728
+ polygon.previousState = this.previousState;
2729
+ polygon.previousStates = this.previousStates.slice();
2730
+ if (this.triangle.midPoint) {
2731
+ polygon.triangle.midPoint = this.triangle.midPoint.clone();
2732
+ }
2733
+ return polygon;
2734
+ }
2735
+
2736
+ flip() {
2737
+ var tmp;
2738
+ this.vertices.reverse().forEach(function(v) {
2739
+ return v.flip();
2740
+ });
2741
+ tmp = this.triangle.a;
2742
+ this.triangle.a = this.triangle.c;
2743
+ this.triangle.c = tmp;
2744
+ return this.plane.flip();
2745
+ }
2746
+
2747
+ delete() {
2748
+ this.vertices.forEach(function(v) {
2749
+ return v.delete();
2750
+ });
2751
+ this.vertices.length = 0;
2752
+ if (this.plane) {
2753
+ this.plane.delete();
2754
+ this.plane = void 0;
2755
+ }
2756
+ this.triangle = void 0;
2757
+ this.shared = void 0;
2758
+ return this.setInvalid();
2759
+ }
2760
+
2761
+ };
2762
+
2763
+ disposeOctree = function(...octrees) {
2764
+ if (OctreeCSG.disposeOctree) {
2765
+ return octrees.forEach(function(octree) {
2766
+ return octree.delete();
2767
+ });
2768
+ }
2769
+ };
2770
+
2771
+ // Winding Number algorithm adapted from https://github.com/grame-cncm/faust/blob/master-dev/tools/physicalModeling/mesh2faust/vega/libraries/windingNumber/windingNumber.cpp
2772
+ _wV1 = new Vector3();
2773
+
2774
+ _wV2 = new Vector3();
2775
+
2776
+ _wV3 = new Vector3();
2777
+
2778
+ _wP = new Vector3();
2779
+
2780
+ _wP_EPS_ARR = [new Vector3(EPSILON, 0, 0), new Vector3(0, EPSILON, 0), new Vector3(0, 0, EPSILON), new Vector3(-EPSILON, 0, 0), new Vector3(0, -EPSILON, 0), new Vector3(0, 0, -EPSILON)];
2781
+
2782
+ _wP_EPS_ARR_COUNT = _wP_EPS_ARR.length;
2783
+
2784
+ _matrix3 = new Matrix3();
2785
+
2786
+ wNPI = 4 * Math.PI;
2787
+
2788
+ returnXYZ = function(arr, index) {
2789
+ return {
2790
+ x: arr[index],
2791
+ y: arr[index + 1],
2792
+ z: arr[index + 2]
2793
+ };
2794
+ };
2795
+
2796
+ calcWindingNumber_buffer = function(trianglesArr, point) {
2797
+ var i, k, lenA, lenB, lenC, omega, ref, wN;
2798
+ wN = 0;
2799
+ for (i = k = 0, ref = trianglesArr.length; k < ref; i = k += 9) {
2800
+ _wV1.subVectors(returnXYZ(trianglesArr, i), point);
2801
+ _wV2.subVectors(returnXYZ(trianglesArr, i + 3), point);
2802
+ _wV3.subVectors(returnXYZ(trianglesArr, i + 6), point);
2803
+ lenA = _wV1.length();
2804
+ lenB = _wV2.length();
2805
+ lenC = _wV3.length();
2806
+ _matrix3.set(_wV1.x, _wV1.y, _wV1.z, _wV2.x, _wV2.y, _wV2.z, _wV3.x, _wV3.y, _wV3.z);
2807
+ omega = 2 * Math.atan2(_matrix3.determinant(), lenA * lenB * lenC + _wV1.dot(_wV2) * lenC + _wV2.dot(_wV3) * lenA + _wV3.dot(_wV1) * lenB);
2808
+ wN += omega;
2809
+ }
2810
+ wN = Math.round(wN / wNPI);
2811
+ return wN;
2812
+ };
2813
+
2814
+ polyInside_WindingNumber_buffer = function(trianglesArr, point, coplanar) {
2815
+ var j, k, ref, result, wN;
2816
+ result = false;
2817
+ _wP.copy(point);
2818
+ wN = calcWindingNumber_buffer(trianglesArr, _wP);
2819
+ if (wN === 0) {
2820
+ if (coplanar) {
2821
+ for (j = k = 0, ref = _wP_EPS_ARR_COUNT; (0 <= ref ? k < ref : k > ref); j = 0 <= ref ? ++k : --k) {
2822
+ _wP.copy(point).add(_wP_EPS_ARR[j]);
2823
+ wN = calcWindingNumber_buffer(trianglesArr, _wP);
2824
+ if (wN !== 0) {
2825
+ result = true;
2826
+ break;
2827
+ }
2828
+ }
2829
+ }
2830
+ } else {
2831
+ result = true;
2832
+ }
2833
+ return result;
2834
+ };
2835
+
2836
+ // -----
2837
+ handleIntersectingOctrees = function(octreeA, octreeB, bothOctrees = true) {
2838
+ var octreeA_buffer, octreeB_buffer;
2839
+ octreeA_buffer = void 0;
2840
+ octreeB_buffer = void 0;
2841
+ if (OctreeCSG.useWindingNumber === true) {
2842
+ if (bothOctrees) {
2843
+ octreeA_buffer = prepareTriangleBuffer(octreeA.getPolygons());
2844
+ }
2845
+ octreeB_buffer = prepareTriangleBuffer(octreeB.getPolygons());
2846
+ }
2847
+ octreeA.handleIntersectingPolygons(octreeB, octreeB_buffer);
2848
+ if (bothOctrees) {
2849
+ octreeB.handleIntersectingPolygons(octreeA, octreeA_buffer);
2850
+ }
2851
+ if (octreeA_buffer !== void 0) {
2852
+ octreeA_buffer = void 0;
2853
+ return octreeB_buffer = void 0;
2854
+ }
2855
+ };
2856
+
2857
+ prepareTriangleBuffer = function(polygons) {
2858
+ var array, bufferIndex, i, k, numOfTriangles, ref, triangle;
2859
+ numOfTriangles = polygons.length;
2860
+ array = new Float32Array(numOfTriangles * 3 * 3);
2861
+ bufferIndex = 0;
2862
+ for (i = k = 0, ref = numOfTriangles; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
2863
+ triangle = polygons[i].triangle;
2864
+ array[bufferIndex++] = triangle.a.x;
2865
+ array[bufferIndex++] = triangle.a.y;
2866
+ array[bufferIndex++] = triangle.a.z;
2867
+ array[bufferIndex++] = triangle.b.x;
2868
+ array[bufferIndex++] = triangle.b.y;
2869
+ array[bufferIndex++] = triangle.b.z;
2870
+ array[bufferIndex++] = triangle.c.x;
2871
+ array[bufferIndex++] = triangle.c.y;
2872
+ array[bufferIndex++] = triangle.c.z;
2873
+ }
2874
+ return array;
2875
+ };
2876
+
2877
+ // https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
2878
+ edge1 = new Vector3();
2879
+
2880
+ edge2 = new Vector3();
2881
+
2882
+ h = new Vector3();
2883
+
2884
+ s = new Vector3();
2885
+
2886
+ q = new Vector3();
2887
+
2888
+ RAY_EPSILON = 0.0000001;
2889
+
2890
+ rayIntersectsTriangle = function(ray, triangle, target = new Vector3()) {
2891
+ var a, f, t, u, v;
2892
+ edge1.subVectors(triangle.b, triangle.a);
2893
+ edge2.subVectors(triangle.c, triangle.a);
2894
+ h.crossVectors(ray.direction, edge2);
2895
+ a = edge1.dot(h);
2896
+ if (a > -RAY_EPSILON && a < RAY_EPSILON) {
2897
+ return null; // Ray is parallel to the triangle
2898
+ }
2899
+ f = 1 / a;
2900
+ s.subVectors(ray.origin, triangle.a);
2901
+ u = f * s.dot(h);
2902
+ if (u < 0 || u > 1) {
2903
+ return null;
2904
+ }
2905
+ q.crossVectors(s, edge1);
2906
+ v = f * ray.direction.dot(q);
2907
+ if (v < 0 || u + v > 1) {
2908
+ return null;
2909
+ }
2910
+ t = f * edge2.dot(q);
2911
+ if (t > RAY_EPSILON) {
2912
+ return target.copy(ray.direction).multiplyScalar(t).add(ray.origin);
2913
+ }
2914
+ return null;
2915
+ };
2916
+
2917
+ OctreeCSG.rayIntersectsTriangle = rayIntersectsTriangle;
2918
+
2919
+ OctreeCSG.useOctreeRay = true;
2920
+
2921
+ OctreeCSG.useWindingNumber = false;
2922
+
2923
+ OctreeCSG.rayIntersectTriangleType = "MollerTrumbore"; // "regular" (three.js' ray.intersectTriangle; "MollerTrumbore" (Moller Trumbore algorithm);
2924
+
2925
+ OctreeCSG.maxLevel = 16;
2926
+
2927
+ OctreeCSG.polygonsPerTree = 100;
2928
+
2929
+ // OctreeCSG.Octree = Octree
2930
+ module.exports = {
2931
+ default: OctreeCSG,
2932
+ CSG: OctreeCSG,
2933
+ OctreeCSG: OctreeCSG,
2934
+ Polygon: Polygon,
2935
+ Plane: Plane,
2936
+ Vertex: Vertex,
2937
+ rayIntersectsTriangle: rayIntersectsTriangle
2938
+ };