@jgphilpott/polytree 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/polytree.js DELETED
@@ -1,2938 +0,0 @@
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("./app/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
- };