@carbonenginejs/core-math 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/box3.js ADDED
@@ -0,0 +1,1329 @@
1
+ import { num } from "./num.js";
2
+ import { vec3 } from "./vec3.js";
3
+ import { sph3 } from "./sph3.js";
4
+ import { pool } from "./pool.js";
5
+
6
+
7
+ /**
8
+ * 3D Box
9
+ * @typedef {Float32Array} box3
10
+ */
11
+
12
+ export const box3 = { bounds: {} };
13
+
14
+ /**
15
+ * Allocates a pooled box3
16
+ * @returns {box3|Float32Array}
17
+ */
18
+ box3.alloc = function()
19
+ {
20
+ return pool.allocF32(6);
21
+ };
22
+
23
+ /**
24
+ * Frees a pooled box3
25
+ * @param {box3|Float32Array} b
26
+ */
27
+ box3.unalloc = function(b)
28
+ {
29
+ pool.freeType(b);
30
+ };
31
+
32
+ /**
33
+ * Gets a subarray of a box3's min vector
34
+ * @property {box3} a
35
+ * @returns {TypedArray}
36
+ */
37
+ box3.$min = function (a)
38
+ {
39
+ return a.subarray(0, 3);
40
+ };
41
+
42
+ /**
43
+ * Gets a subarray of a box3's max vector
44
+ * @property {box3} a
45
+ * @returns {TypedArray}
46
+ */
47
+ box3.$max = function (a)
48
+ {
49
+ return a.subarray(3, 6);
50
+ };
51
+
52
+ /**
53
+ * Adds a point to a box3
54
+ *
55
+ * @param {box3} out - receiving box3
56
+ * @param {box3} a - source box3
57
+ * @param {vec3} p - point to add
58
+ * @returns {box3} out - receiving box3
59
+ */
60
+ box3.addPoint = function (out, a, p)
61
+ {
62
+ out[0] = Math.min(a[0], p[0]);
63
+ out[1] = Math.min(a[1], p[1]);
64
+ out[2] = Math.min(a[2], p[2]);
65
+ out[3] = Math.max(a[3], p[0]);
66
+ out[4] = Math.max(a[4], p[1]);
67
+ out[5] = Math.max(a[5], p[2]);
68
+ return out;
69
+ };
70
+
71
+ /**
72
+ * Sets a box3 from a box3 with added points
73
+ *
74
+ * @param {box3} out - receiving box3
75
+ * @param {box3} a - source box3
76
+ * @param {Array.<number>} points - points to add
77
+ * @returns {box3} out - receiving box3
78
+ */
79
+ box3.addPoints = function (out, a, points)
80
+ {
81
+ let minX = a[0],
82
+ minY = a[1],
83
+ minZ = a[2],
84
+ maxX = a[3],
85
+ maxY = a[4],
86
+ maxZ = a[5];
87
+
88
+ for (let i = 0; i < points.length; i++)
89
+ {
90
+ minX = Math.min(minX, points[i][0]);
91
+ minY = Math.min(minY, points[i][1]);
92
+ minZ = Math.min(minZ, points[i][2]);
93
+ maxX = Math.max(maxX, points[i][0]);
94
+ maxY = Math.max(maxY, points[i][1]);
95
+ maxZ = Math.max(maxZ, points[i][2]);
96
+ }
97
+
98
+ out[0] = minX;
99
+ out[1] = minY;
100
+ out[2] = minZ;
101
+ out[3] = maxX;
102
+ out[4] = maxY;
103
+ out[5] = maxZ;
104
+ return out;
105
+ };
106
+
107
+ /**
108
+ * Clones a box3
109
+ *
110
+ * @param {box3} a - source box3
111
+ * @returns {box3} - a new box3
112
+ */
113
+ box3.clone = function (a)
114
+ {
115
+ let out = new Float32Array(6);
116
+ out[0] = a[0];
117
+ out[1] = a[1];
118
+ out[2] = a[2];
119
+ out[3] = a[3];
120
+ out[4] = a[4];
121
+ out[5] = a[5];
122
+ return out;
123
+ };
124
+
125
+ /**
126
+ * Checks if a box3 contains another box3
127
+ *
128
+ * @param {box3} a - source box3
129
+ * @param {box3} b - box3 to compare
130
+ * @returns {boolean} - true if the source box3 contains the second
131
+ */
132
+ box3.contains = function (a, b)
133
+ {
134
+ return (
135
+ (a[0] <= b[0]) && (b[3] <= a[3]) &&
136
+ (a[1] <= b[1]) && (b[4] <= a[4]) &&
137
+ (a[2] <= b[2]) && (b[5] <= a[5])
138
+ );
139
+ };
140
+
141
+ /**
142
+ * Checks if the box3 contains min and max bounds
143
+ *
144
+ * @param {box3} a - source box3
145
+ * @param {vec3} min - min bounds
146
+ * @param {vec3} max - max bounds
147
+ * @returns {boolean} - true if the source box3 contains the bounds
148
+ */
149
+ box3.containsBounds = function (a, min, max)
150
+ {
151
+ return (
152
+ (a[0] <= min[0]) && (max[0] <= a[3]) &&
153
+ (a[1] <= min[1]) && (max[1] <= a[4]) &&
154
+ (a[2] <= min[2]) && (max[2] <= a[5])
155
+ );
156
+ };
157
+
158
+ /**
159
+ * Checks if a box3 contains a point
160
+ *
161
+ * @param {box3} a - source box3
162
+ * @param {vec3} p - point to compare
163
+ * @returns {boolean} - true if the source box contains the point
164
+ */
165
+ box3.containsPoint = function (a, p)
166
+ {
167
+ return !(
168
+ p[0] < a[0] || p[0] > a[3] ||
169
+ p[1] < a[1] || p[1] > a[4] ||
170
+ p[2] < a[2] || p[2] > a[5]
171
+ );
172
+ };
173
+
174
+ /**
175
+ * Checks if a box3 contains a point's values
176
+ *
177
+ * @param {box3} a - source box3
178
+ * @param {Number} px - point X
179
+ * @param {Number} py - point Y
180
+ * @param {Number} pz - point Z
181
+ * @returns {boolean} - true if the source box3 contains the point
182
+ */
183
+ box3.containsValue = function (a, px, py, pz)
184
+ {
185
+ return !(
186
+ px < a[0] || px > a[3] ||
187
+ py < a[1] || py > a[4] ||
188
+ pz < a[2] || pz > a[5]
189
+ );
190
+ };
191
+
192
+ /**
193
+ * Copies the values from one box3 into another
194
+ *
195
+ * @param {box3} out - receiving box3
196
+ * @param {box3} a - source box3
197
+ * @returns {box3} out - receiving box3
198
+ */
199
+ box3.copy = function (out, a)
200
+ {
201
+ out[0] = a[0];
202
+ out[1] = a[1];
203
+ out[2] = a[2];
204
+ out[3] = a[3];
205
+ out[4] = a[4];
206
+ out[5] = a[5];
207
+ return out;
208
+ };
209
+
210
+ /**
211
+ * Copies the min vector of one box3 to another
212
+ *
213
+ * @param {box3} out
214
+ * @param {box3} a
215
+ * @returns {box3}
216
+ */
217
+ box3.copyMin = vec3.copy;
218
+
219
+ /**
220
+ * Copies the max vector of one box3 to another
221
+ *
222
+ * @param {box3} out
223
+ * @param {box3} a
224
+ * @returns {box3}
225
+ */
226
+ box3.copyMax = function (out, a)
227
+ {
228
+ out[3] = a[3];
229
+ out[4] = a[4];
230
+ out[5] = a[5];
231
+ return out;
232
+ };
233
+
234
+ /**
235
+ * Creates a box3
236
+ *
237
+ * @returns {box3} - The new box3
238
+ */
239
+ box3.create = function ()
240
+ {
241
+ return box3.empty(new Float32Array(6));
242
+ };
243
+
244
+ /**
245
+ * Gets the distance from a box3 to a point
246
+ *
247
+ * @param {box3} a - source box3
248
+ * @param {vec3} p - point
249
+ * @returns {number} - distance between the source box3 and point
250
+ */
251
+ box3.distanceToPoint = function (a, p)
252
+ {
253
+ let x = Math.max(a[0], Math.min(a[3], p[0])) - p[0],
254
+ y = Math.max(a[1], Math.min(a[4], p[1])) - p[1],
255
+ z = Math.max(a[2], Math.min(a[5], p[2])) - p[2];
256
+
257
+ return Math.sqrt(x * x + y * y + z * z);
258
+ };
259
+
260
+ /**
261
+ * Gets the distance from a box3 to a point's values
262
+ *
263
+ * @param {box3} a - source box3
264
+ * @param {Number} px - point x
265
+ * @param {Number} py - point y
266
+ * @param {Number} pz - point z
267
+ * @returns {number} - distance between the source box3 and point
268
+ */
269
+ box3.distanceToValues = function (a, px, py, pz)
270
+ {
271
+ let x = Math.max(a[0], Math.min(a[3], px)) - px,
272
+ y = Math.max(a[1], Math.min(a[4], py)) - py,
273
+ z = Math.max(a[2], Math.min(a[5], pz)) - pz;
274
+
275
+ return Math.sqrt(x * x + y * y + z * z);
276
+ };
277
+
278
+ /**
279
+ * Empties a box3
280
+ *
281
+ * @param {box3} a - box3 to empty
282
+ * @returns {box3} - the empty box3
283
+ */
284
+ box3.empty = function (a)
285
+ {
286
+ a[0] = 0;
287
+ a[1] = 0;
288
+ a[2] = 0;
289
+ a[3] = 0;
290
+ a[4] = 0;
291
+ a[5] = 0;
292
+ return a;
293
+ };
294
+
295
+ /**
296
+ * Empties bounds
297
+ *
298
+ * @param {vec3} min - min bounds
299
+ * @param {vec3} max - max bounds
300
+ */
301
+ box3.bounds.empty = function (min, max)
302
+ {
303
+ min[0] = 0;
304
+ min[1] = 0;
305
+ min[2] = 0;
306
+ max[0] = 0;
307
+ max[1] = 0;
308
+ max[2] = 0;
309
+ };
310
+
311
+ /**
312
+ * Checks two box3's for equality
313
+ *
314
+ * @param {box3} a - box3 to compare
315
+ * @param {box3} b - box3 to compare
316
+ * @returns {boolean} - true if box3s are equal
317
+ */
318
+ box3.equals = function (a, b)
319
+ {
320
+ let a0 = a[0],
321
+ a1 = a[1],
322
+ a2 = a[2],
323
+ a3 = a[3],
324
+ a4 = a[4],
325
+ a5 = a[5];
326
+
327
+ let b0 = b[0],
328
+ b1 = b[1],
329
+ b2 = b[2],
330
+ b3 = b[3],
331
+ b4 = b[4],
332
+ b5 = b[5];
333
+
334
+ return (
335
+ Math.abs(a0 - b0) <= num.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
336
+ Math.abs(a1 - b1) <= num.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
337
+ Math.abs(a2 - b2) <= num.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
338
+ Math.abs(a3 - b3) <= num.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) &&
339
+ Math.abs(a4 - b4) <= num.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) &&
340
+ Math.abs(a5 - b5) <= num.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5))
341
+ );
342
+ };
343
+
344
+ /**
345
+ * Checks a box3 and box3 components for equality
346
+ *
347
+ * @param {box3} a - box3 to compare
348
+ * @param {vec3} min - min bounds to compare
349
+ * @param {vec3} max - max bounds to compare
350
+ * @returns {boolean} - true if the box3 and bounds are equal
351
+ */
352
+ box3.equalsBounds = function (a, min, max)
353
+ {
354
+ let a0 = a[0],
355
+ a1 = a[1],
356
+ a2 = a[2],
357
+ a3 = a[3],
358
+ a4 = a[4],
359
+ a5 = a[5];
360
+
361
+ let b0 = min[0],
362
+ b1 = min[1],
363
+ b2 = min[2],
364
+ b3 = max[0],
365
+ b4 = max[1],
366
+ b5 = max[2];
367
+
368
+ return (
369
+ Math.abs(a0 - b0) <= num.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
370
+ Math.abs(a1 - b1) <= num.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
371
+ Math.abs(a2 - b2) <= num.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
372
+ Math.abs(a3 - b3) <= num.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) &&
373
+ Math.abs(a4 - b4) <= num.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) &&
374
+ Math.abs(a5 - b5) <= num.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5))
375
+ );
376
+ };
377
+
378
+ /**
379
+ * Checks for vec6 exact equality
380
+ *
381
+ * @param {box3} a - box3 to compare
382
+ * @param {box3} b - box3 to compare
383
+ * @returns {boolean} - true if both box3s are exactly equal
384
+ */
385
+ box3.exactEquals = function (a, b)
386
+ {
387
+ return (
388
+ a[0] === b[0] && a[1] === b[1] && a[2] === b[2] &&
389
+ a[3] === b[3] && a[4] === b[4] && a[5] === b[5]
390
+ );
391
+ };
392
+
393
+ /**
394
+ * Checks for exact equality between a box3 and components
395
+ *
396
+ * @param {box3} a - box3 to compare
397
+ * @param {vec3} min - min bounds to compare
398
+ * @param {vec3} max - max bounds to compare
399
+ * @returns {boolean} - true if the box3 and bounds are exactly equal
400
+ */
401
+ box3.exactEqualsBounds = function (a, min, max)
402
+ {
403
+ return (
404
+ a[0] === min[0] && a[1] === min[1] && a[2] === min[2] &&
405
+ a[3] === max[0] && a[4] === max[1] && a[5] === max[2]
406
+ );
407
+ };
408
+
409
+ /**
410
+ * Sets a box3 from the expansion of a box3 and a given scalar
411
+ *
412
+ * @param {box3} out - receiving box3
413
+ * @param {box3} a - source box3
414
+ * @param {number} s - scalar to expand by
415
+ * @returns {box3} out - receiving box3
416
+ */
417
+ box3.expandScalar = function (out, a, s)
418
+ {
419
+ out[0] = a[0] - s;
420
+ out[1] = a[1] - s;
421
+ out[2] = a[2] - s;
422
+ out[3] = a[3] + s;
423
+ out[4] = a[4] + s;
424
+ out[5] = a[5] + s;
425
+ return out;
426
+ };
427
+
428
+ /**
429
+ * Sets a box3 from the expansion of a box3 and a vector's values
430
+ *
431
+ * @param {box3} out - receiving box3
432
+ * @param {box3} a - source box3
433
+ * @param {number} vx - vector x
434
+ * @param {number} vy - vector y
435
+ * @param {number} vz - vector z
436
+ * @returns {box3} out - receiving box3
437
+ */
438
+ box3.expandValues = function (out, a, vx, vy, vz)
439
+ {
440
+ out[0] = a[0] - vx;
441
+ out[1] = a[1] - vy;
442
+ out[2] = a[2] - vz;
443
+ out[3] = a[3] + vx;
444
+ out[4] = a[4] + vy;
445
+ out[5] = a[5] + vz;
446
+ return out;
447
+ };
448
+
449
+ /**
450
+ * Expands a box3 by a vec3
451
+ *
452
+ * @param {box3} out - receiving box3
453
+ * @param {box3} a - source box3
454
+ * @param {vec3} v - vector to expand by
455
+ * @returns {box3} out - receiving box3
456
+ */
457
+ box3.expandVec3 = function (out, a, v)
458
+ {
459
+ out[0] = a[0] - v[0];
460
+ out[1] = a[1] - v[1];
461
+ out[2] = a[2] - v[2];
462
+ out[3] = a[3] + v[0];
463
+ out[4] = a[4] + v[1];
464
+ out[5] = a[5] + v[2];
465
+ return out;
466
+ };
467
+
468
+ /**
469
+ * Sets a box3 from an array at an optional offset
470
+ *
471
+ * @param {box3} out - receiving box3
472
+ * @param {Array} arr - source array
473
+ * @param {number} [index=0] - optional array index
474
+ * @returns {box3} - receiving box3
475
+ */
476
+ box3.fromArray = function (out, arr, index = 0)
477
+ {
478
+ out[0] = arr[index];
479
+ out[1] = arr[index + 1];
480
+ out[2] = arr[index + 2];
481
+ out[3] = arr[index + 3];
482
+ out[4] = arr[index + 4];
483
+ out[5] = arr[index + 5];
484
+ return out;
485
+ };
486
+
487
+ /**
488
+ * Sets a box3 from bounds
489
+ *
490
+ * @param {box3} out - receiving box3
491
+ * @param {vec3} min - source min bounds
492
+ * @param {vec3} max - source max bounds
493
+ * @returns {box3} out - receiving box3
494
+ */
495
+ box3.fromBounds = function (out, min, max)
496
+ {
497
+ out[0] = min[0];
498
+ out[1] = min[1];
499
+ out[2] = min[2];
500
+ out[3] = max[0];
501
+ out[4] = max[1];
502
+ out[5] = max[2];
503
+ return out;
504
+ };
505
+
506
+ box3.from = box3.fromBounds;
507
+
508
+
509
+ /**
510
+ * Sets a box3 from position and size
511
+ *
512
+ * @param {box3} out - receiving box3
513
+ * @param {vec3} position - source position
514
+ * @param {vec3} size - source size
515
+ * @returns {box3} out - receiving box3
516
+ */
517
+ box3.fromPositionSize = function (out, position, size)
518
+ {
519
+ out[0] = position[0] - size[0] * 0.5;
520
+ out[1] = position[1] - size[1] * 0.5;
521
+ out[2] = position[2] - size[2] * 0.5;
522
+ out[3] = position[0] + size[0] * 0.5;
523
+ out[4] = position[1] + size[1] * 0.5;
524
+ out[5] = position[2] + size[2] * 0.5;
525
+ return out;
526
+ };
527
+
528
+ /**
529
+ * Sets a box3 from an array of points
530
+ *
531
+ * @param {box3} out - receiving box3
532
+ * @param {Array.<vec3>} points - array of points
533
+ * @returns {box3} out - receiving box3
534
+ */
535
+ box3.fromPoints = function (out, points)
536
+ {
537
+ if (!points.length) return box3.empty(out);
538
+
539
+ out[0] = out[3] = points[0][0];
540
+ out[1] = out[4] = points[0][1];
541
+ out[2] = out[5] = points[0][2];
542
+
543
+ for (let i = 1; i < points.length; i++)
544
+ {
545
+ out[0] = Math.min(out[0], points[i][0]);
546
+ out[1] = Math.min(out[1], points[i][1]);
547
+ out[2] = Math.min(out[2], points[i][2]);
548
+ out[3] = Math.max(out[3], points[i][0]);
549
+ out[4] = Math.max(out[4], points[i][1]);
550
+ out[5] = Math.max(out[5], points[i][2]);
551
+ }
552
+
553
+ return out;
554
+ };
555
+
556
+ box3.setPoints = box3.fromPoints;
557
+
558
+ /**
559
+ * Sets a box3 from a sphere's components
560
+ *
561
+ * @param {box3} out - receiving box3
562
+ * @param {vec3} position - position
563
+ * @param {number} radius - radius
564
+ * @returns {box3} - receiving box3
565
+ */
566
+ box3.fromPositionRadius = function (out, position, radius)
567
+ {
568
+ out[0] = position[0] - radius;
569
+ out[1] = position[1] - radius;
570
+ out[2] = position[2] - radius;
571
+ out[3] = position[0] + radius;
572
+ out[4] = position[1] + radius;
573
+ out[5] = position[2] + radius;
574
+ return out;
575
+ };
576
+
577
+ /**
578
+ * Sets a box3 from a Float32Array(4) sphere
579
+ *
580
+ * @param {box3} out - receiving box3
581
+ * @param {sph3} sphere - source sphere
582
+ * @returns {box3} out - receiving box3
583
+ */
584
+ box3.fromSph3 = function (out, sphere)
585
+ {
586
+ out[0] = sphere[0] - sphere[3];
587
+ out[1] = sphere[1] - sphere[3];
588
+ out[2] = sphere[2] - sphere[3];
589
+ out[3] = sphere[0] + sphere[3];
590
+ out[4] = sphere[1] + sphere[3];
591
+ out[5] = sphere[2] + sphere[3];
592
+ return out;
593
+ };
594
+
595
+ /**
596
+ * Creates a box3 from a transform
597
+ * @param {box3} out
598
+ * @param {mat4} m
599
+ * @param {Number} [initialScale=1]
600
+ * @returns {box3} out
601
+ */
602
+ box3.fromTransform = function(out, m, initialScale=1)
603
+ {
604
+ out[0] = out[1] = out[2] = -initialScale / 2;
605
+ out[3] = out[4] = out[5] = initialScale / 2;
606
+ return box3.transformMat4(out, out, m);
607
+ };
608
+
609
+ /**
610
+ * Creates a box3 from values
611
+ * @param {Number} minx
612
+ * @param {Number} miny
613
+ * @param {Number} minz
614
+ * @param {Number} maxx
615
+ * @param {Number} maxy
616
+ * @param {Number} maxz
617
+ * @returns {box3}
618
+ */
619
+ box3.fromValues = function (minx, miny, minz, maxx, maxy, maxz)
620
+ {
621
+ const out = box3.create();
622
+ out[0] = minx;
623
+ out[1] = miny;
624
+ out[2] = minz;
625
+ out[3] = maxx;
626
+ out[4] = maxy;
627
+ out[5] = maxz;
628
+ return out;
629
+ };
630
+
631
+ /**
632
+ * Gets a box3's center
633
+ *
634
+ * @param {vec3} out
635
+ * @param {box3} a
636
+ * @return {vec3} out
637
+ */
638
+ box3.getCenter = function (out, a)
639
+ {
640
+ if (box3.isEmpty(a))
641
+ {
642
+ out[0] = 0;
643
+ out[1] = 0;
644
+ out[2] = 0;
645
+ return out;
646
+ }
647
+
648
+ out[0] = (a[0] + a[3]) * 0.5;
649
+ out[1] = (a[1] + a[4]) * 0.5;
650
+ out[2] = (a[2] + a[5]) * 0.5;
651
+ return out;
652
+ };
653
+
654
+ /**
655
+ * Sets a vec3 from a point clamped to a box3
656
+ *
657
+ * @param {vec3} out - receiving vec3
658
+ * @param {box3} a - source box
659
+ * @param {vec3} p - the point to clamp
660
+ * @returns {vec3} [out] - receiving vec3
661
+ */
662
+ box3.getClampedPoint = function (out, a, p)
663
+ {
664
+ out[0] = Math.max(a[0], Math.min(a[3], p[0]));
665
+ out[1] = Math.max(a[1], Math.min(a[4], p[1]));
666
+ out[2] = Math.max(a[2], Math.min(a[5], p[2]));
667
+ return out;
668
+ };
669
+
670
+ /**
671
+ * Sets a vec3 with the box3's max bounds
672
+ *
673
+ * @param {vec3} out - receiving vec3
674
+ * @param {box3} a - source box
675
+ * @returns {vec3} [out] - receiving vec3
676
+ */
677
+ box3.getMax = function (out, a)
678
+ {
679
+ out[0] = a[3];
680
+ out[1] = a[4];
681
+ out[2] = a[5];
682
+ return out;
683
+ };
684
+
685
+ /**
686
+ * Sets a vec3 with the box3's min bounds
687
+ *
688
+ * @param {vec3} out - receiving vec3
689
+ * @param {box3} a - source box
690
+ * @returns {vec3} [out] - receiving vec3
691
+ */
692
+ box3.getMin = function (out, a)
693
+ {
694
+ out[0] = a[0];
695
+ out[1] = a[1];
696
+ out[2] = a[2];
697
+ return out;
698
+ };
699
+
700
+ /**
701
+ * Sets a vec3 with a box3's size
702
+ *
703
+ * @param {vec3} out - receiving vec3
704
+ * @param {box3} a - source box
705
+ * @returns {vec3} [out] - receiving vec3
706
+ */
707
+ box3.getSize = function (out, a)
708
+ {
709
+ out[0] = a[3] - a[0];
710
+ out[1] = a[4] - a[1];
711
+ out[2] = a[5] - a[2];
712
+ return out;
713
+ };
714
+
715
+ /**
716
+ * Sets a vec3 with the box3's position
717
+ *
718
+ * @param {vec3} out - receiving vec3
719
+ * @param {box3} a - source box
720
+ * @returns {vec3} [out] - receiving vec3
721
+ */
722
+ box3.getPosition = function (out, a)
723
+ {
724
+ out[0] = (a[0] + a[3]) * 0.5;
725
+ out[1] = (a[1] + a[4]) * 0.5;
726
+ out[2] = (a[2] + a[5]) * 0.5;
727
+ return out;
728
+ };
729
+
730
+ /**
731
+ * Gets the effective radius of a bounding box
732
+ * @param {box3} a
733
+ * @returns {number}
734
+ */
735
+ box3.radius = function (a)
736
+ {
737
+ let sX = a[3] - a[0],
738
+ sY = a[4] - a[1],
739
+ sZ = a[5] - a[2];
740
+
741
+ return Math.sqrt(sX * sX + sY * sY + sZ * sZ) * 0.5;
742
+ };
743
+
744
+ /**
745
+ * Sets a box3 from the intersect of two box3s
746
+ *
747
+ * @param {box3} out - receiving box3
748
+ * @param {box3} a - first box3
749
+ * @param {box3} b - second box3
750
+ * @returns {box3} out - receiving box3
751
+ */
752
+ box3.intersect = function (out, a, b)
753
+ {
754
+ out[0] = Math.max(a[0], b[0]);
755
+ out[1] = Math.max(a[1], b[1]);
756
+ out[2] = Math.max(a[2], b[2]);
757
+ out[3] = Math.min(a[3], b[3]);
758
+ out[4] = Math.min(a[4], b[4]);
759
+ out[5] = Math.min(a[5], b[5]);
760
+ return out;
761
+ };
762
+
763
+ /**
764
+ * Sets a box3 from the intersect of a box3 and min and max bounds
765
+ *
766
+ * @param {box3} out - receiving box3
767
+ * @param {box3} a - box3
768
+ * @param {vec3} min - min bounds
769
+ * @param {vec3} max - max bounds
770
+ * @returns {box3} out - receiving box3
771
+ */
772
+ box3.intersectBounds = function (out, a, min, max)
773
+ {
774
+ out[0] = Math.max(a[0], min[0]);
775
+ out[1] = Math.max(a[1], min[1]);
776
+ out[2] = Math.max(a[2], min[2]);
777
+ out[3] = Math.min(a[3], max[0]);
778
+ out[4] = Math.min(a[4], max[1]);
779
+ out[5] = Math.min(a[5], max[2]);
780
+ return out;
781
+ };
782
+
783
+ /**
784
+ * Checks for box3 intersection with another box3
785
+ *
786
+ * @param a - first box3 to compare
787
+ * @param b - second box3 to compare
788
+ * @returns {boolean} - true if intersection occurred
789
+ */
790
+ box3.intersects = function (a, b)
791
+ {
792
+ return !(
793
+ b[3] < a[0] || b[0] > a[3] ||
794
+ b[4] < a[1] || b[1] > a[4] ||
795
+ b[5] < a[2] || b[2] > a[5]
796
+ );
797
+ };
798
+
799
+ /**
800
+ * Checks for box3 intersection with min and max bounds
801
+ *
802
+ * @param {box3} a - box3 to compare
803
+ * @param {vec3} min - min bounds to compare
804
+ * @param {vec3} max - max bounds to compare
805
+ * @returns {boolean} - true if intersection occurred
806
+ */
807
+ box3.intersectsBounds = function (a, min, max)
808
+ {
809
+ return !(
810
+ max[0] < a[0] || min[0] > a[3] ||
811
+ max[1] < a[1] || min[1] > a[4] ||
812
+ max[2] < a[2] || min[2] > a[5]
813
+ );
814
+ };
815
+
816
+ /**
817
+ * Checks for box3 intersection with a plane normal and constant
818
+ *
819
+ * @param {box3} a - source box3
820
+ * @param {vec3} normal - plane normal vec3
821
+ * @param {number} constant - plane constant
822
+ * @returns {boolean} - true if intersection occurs
823
+ */
824
+ box3.intersectsNormalConstant = function (a, normal, constant)
825
+ {
826
+ let tMin = 0,
827
+ tMax = 0;
828
+
829
+ if (normal[0] > 0)
830
+ {
831
+ tMin += normal[0] * a[0];
832
+ tMax += normal[0] * a[3];
833
+ }
834
+ else
835
+ {
836
+ tMin += normal[0] * a[3];
837
+ tMax += normal[0] * a[0];
838
+ }
839
+
840
+ if (normal[1] > 0)
841
+ {
842
+ tMin += normal[1] * a[1];
843
+ tMax += normal[1] * a[4];
844
+ }
845
+ else
846
+ {
847
+ tMin += normal[1] * a[4];
848
+ tMax += normal[1] * a[1];
849
+ }
850
+
851
+ if (normal[2] > 0)
852
+ {
853
+ tMin += normal[2] * a[2];
854
+ tMax += normal[2] * a[5];
855
+ }
856
+ else
857
+ {
858
+ tMin += normal[2] * a[5];
859
+ tMax += normal[2] * a[2];
860
+ }
861
+
862
+ return (tMin <= constant && tMax >= constant);
863
+ };
864
+
865
+ /**
866
+ * Checks for box3 intersection with a Float32Array(4) plane
867
+ *
868
+ * @param {box3} a - box3 to compare
869
+ * @param {(pln|Float32Array)} p - plane to compare
870
+ * @returns {boolean} - true if intersection occurs
871
+ */
872
+ box3.intersectsPln = function (a, p)
873
+ {
874
+ // const x = p.subarray(0, 3);
875
+ return box3.intersectsNormalConstant(a, p, p[3]);
876
+ };
877
+
878
+ /**
879
+ * Checks for box3 intersection with a point
880
+ *
881
+ * @param {box3} a - box3 to compare
882
+ * @param {vec3} p - point to compare
883
+ * @returns {boolean} - true if intersection occurs
884
+ */
885
+ box3.intersectsPoint = function (a, p)
886
+ {
887
+ return p[0] >= a[0] && p[0] <= a[3] && p[1] >= a[1] && p[1] <= a[4] && p[2] >= a[2] && p[2] <= a[5];
888
+ };
889
+
890
+ /**
891
+ * Checks for box3 intersection with a point's values
892
+ *
893
+ * @param {box3} a - box3 to compare
894
+ * @param {Number} px - point x to compare
895
+ * @param {Number} py - point y to compare
896
+ * @param {Number} pz - point z to compare
897
+ * @returns {boolean} - true if intersection occurs
898
+ */
899
+ box3.intersectsValues = function (a, px, py, pz)
900
+ {
901
+ return px >= a[0] && px <= a[3] && py >= a[1] && py <= a[4] && pz >= a[2] && pz <= a[5];
902
+ };
903
+
904
+ /**
905
+ * Checks for box3 intersection with a sphere's components
906
+ *
907
+ * @param {box3} a - box3 to compare
908
+ * @param {vec3} position - sphere position to compare
909
+ * @param {number} radius - sphere radius to compare
910
+ * @returns {boolean} - true if intersection occurs
911
+ */
912
+ box3.intersectsPositionRadius = function (a, position, radius)
913
+ {
914
+ let x = Math.max(a[0], Math.min(a[3], position[0])) - position[0],
915
+ y = Math.max(a[1], Math.min(a[4], position[1])) - position[1],
916
+ z = Math.max(a[2], Math.min(a[5], position[2])) - position[2];
917
+
918
+ return (x * x + y * y + z * z) <= radius * radius;
919
+ };
920
+
921
+ /**
922
+ * Checks for box3 intersection with a Float32Array(4) sphere
923
+ *
924
+ * @param {box3} a - box3 to compare
925
+ * @param {sph3} sphere - sph3 to compare
926
+ * @returns {boolean} - true if intersection occurs
927
+ */
928
+ box3.intersectsSph3 = function (a, sphere)
929
+ {
930
+ let x = Math.max(a[0], Math.min(a[3], sphere[0])) - sphere[0],
931
+ y = Math.max(a[1], Math.min(a[4], sphere[1])) - sphere[1],
932
+ z = Math.max(a[2], Math.min(a[5], sphere[2])) - sphere[2];
933
+
934
+ return (x * x + y * y + z * z) <= sphere[3] * sphere[3];
935
+ };
936
+
937
+ /**
938
+ * Checks if a box3 is empty
939
+ *
940
+ * @param {box3} a - source box3
941
+ * @returns {boolean} - true if empty
942
+ */
943
+ box3.isEmpty = function (a)
944
+ {
945
+ if (a[0] + a[1] + a[2] + a[3] + a[4] + a[5] === 0) return true;
946
+ return (a[3] < a[0]) || (a[4] < a[1]) || (a[5] < a[2]);
947
+ };
948
+
949
+ /**
950
+ * Checks if bounds are empty
951
+ *
952
+ * @param {vec3} min
953
+ * @param {vec3} max
954
+ * @returns {boolean}
955
+ */
956
+ box3.bounds.isEmpty = function (min, max)
957
+ {
958
+ if (min[0] + min[1] + min[2] + max[0] + max[1] + max[2] === 0) return true;
959
+ return (max[0] < min[0]) || (max[1] < min[1]) || (max[2] < min[2]);
960
+ };
961
+
962
+ /**
963
+ * Sets a box3 from values
964
+ *
965
+ * @param {box3} out - receiving box3
966
+ * @param {Number} aX
967
+ * @param {Number} aY
968
+ * @param {Number} aZ
969
+ * @param {Number} bX
970
+ * @param {Number} bY
971
+ * @param {Number} bZ
972
+ * @returns {box3}
973
+ */
974
+ box3.set = function (out, aX, aY, aZ, bX, bY, bZ)
975
+ {
976
+ out[0] = aX;
977
+ out[1] = aY;
978
+ out[2] = aZ;
979
+ out[3] = bX;
980
+ out[4] = bY;
981
+ out[5] = bZ;
982
+ return out;
983
+ };
984
+
985
+ /**
986
+ * Sets the box's min bounds
987
+ * @param {box3} out
988
+ * @param {vec3} v
989
+ * @returns {box3} out
990
+ */
991
+ box3.setMinBounds = vec3.copy;
992
+
993
+ /**
994
+ * Sets the box's max bounds
995
+ * @param {box3} out
996
+ * @param {vec3} v
997
+ * @returns {box3} out
998
+ */
999
+ box3.setMaxBounds = function (out, v)
1000
+ {
1001
+ out[3] = v[0];
1002
+ out[4] = v[1];
1003
+ out[5] = v[2];
1004
+ return out;
1005
+ };
1006
+
1007
+ /**
1008
+ * Gets the distance from a box3 to a point
1009
+ *
1010
+ * @param {box3} a - source box3
1011
+ * @param {vec3} p - point
1012
+ * @returns {number} - distance
1013
+ */
1014
+ box3.squaredDistanceToPoint = function (a, p)
1015
+ {
1016
+ let x = Math.max(a[0], Math.min(a[3], p[0])) - p[0],
1017
+ y = Math.max(a[1], Math.min(a[4], p[1])) - p[1],
1018
+ z = Math.max(a[2], Math.min(a[5], p[2])) - p[2];
1019
+
1020
+ return x * x + y * y + z * z;
1021
+ };
1022
+
1023
+ /**
1024
+ * Gets the surface area of a box3
1025
+ *
1026
+ * @param {box3} a - source box3
1027
+ * @returns {number} - surface area
1028
+ */
1029
+ box3.surfaceArea = function (a)
1030
+ {
1031
+ let aa = a[3] - a[0],
1032
+ h = a[4] - a[1],
1033
+ d = a[5] - a[2];
1034
+
1035
+ return 2 * (aa * (h + d) + h * d);
1036
+ };
1037
+
1038
+ /**
1039
+ * Converts the box3 into an array
1040
+ *
1041
+ * @param {box3} a - receiving box3
1042
+ * @param {Array} arr - source array
1043
+ * @param {number} [offset=0] - optional offset
1044
+ * @returns {box3} a - receiving box3
1045
+ */
1046
+ box3.toArray = function (a, arr, offset = 0)
1047
+ {
1048
+ arr[offset] = a[0];
1049
+ arr[offset + 1] = a[1];
1050
+ arr[offset + 2] = a[2];
1051
+ arr[offset + 3] = a[3];
1052
+ arr[offset + 4] = a[4];
1053
+ arr[offset + 5] = a[5];
1054
+ return a;
1055
+ };
1056
+
1057
+ /**
1058
+ * Converts a box3 to bounds
1059
+ *
1060
+ * @param {vec3} outMin - receiving vector for min bounds
1061
+ * @param {vec3} outMax - receiving vector for max bounds
1062
+ * @param {box3} a - source box3
1063
+ */
1064
+ box3.toBounds = function (a, outMin, outMax)
1065
+ {
1066
+ outMin[0] = a[0];
1067
+ outMin[1] = a[1];
1068
+ outMin[2] = a[2];
1069
+ outMax[0] = a[3];
1070
+ outMax[1] = a[4];
1071
+ outMax[2] = a[5];
1072
+ return a;
1073
+ };
1074
+
1075
+ /**
1076
+ * Converts a box3 to an array of points
1077
+ * @param {box3} a
1078
+ * @param {Array} [points]
1079
+ * @returns {Array<Array>} points
1080
+ */
1081
+ box3.toPoints = function (a, points = [])
1082
+ {
1083
+ const
1084
+ ax = a[0],
1085
+ ay = a[1],
1086
+ az = a[2],
1087
+ bx = a[3],
1088
+ by = a[4],
1089
+ bz = a[5],
1090
+ x = bx + Math.abs(ax),
1091
+ y = by + Math.abs(ay),
1092
+ z = bz + Math.abs(az);
1093
+
1094
+ points.push([ bx + 0, by + 0, bz + 0 ]);
1095
+ points.push([ bx - x, by + 0, bz + 0 ]);
1096
+ points.push([ bx + 0, by + 0, bz - z ]);
1097
+ points.push([ bx - x, by + 0, bz - z ]);
1098
+ points.push([ bx + 0, by - y, bz + 0 ]);
1099
+ points.push([ bx - x, by - y, bz + 0 ]);
1100
+ points.push([ bx + 0, by - y, bz - z ]);
1101
+ points.push([ bx - x, by - y, bz - z ]);
1102
+
1103
+ return points;
1104
+ };
1105
+
1106
+ /**
1107
+ * Converts a box3 to position radius
1108
+ * @param a
1109
+ * @param outCenter
1110
+ * @returns {number}
1111
+ */
1112
+ box3.toPositionRadius = function (a, outCenter)
1113
+ {
1114
+ let sX = a[3] - a[0],
1115
+ sY = a[4] - a[1],
1116
+ sZ = a[5] - a[2];
1117
+
1118
+ outCenter[0] = (a[0] + a[3]) * 0.5;
1119
+ outCenter[1] = (a[1] + a[4]) * 0.5;
1120
+ outCenter[2] = (a[2] + a[5]) * 0.5;
1121
+
1122
+ return Math.sqrt(sX * sX + sY * sY + sZ * sZ) * 0.5;
1123
+ };
1124
+
1125
+ /**
1126
+ * Converts bounds to position radius
1127
+ * @param {vec3} minBounds
1128
+ * @param {vec3} maxBounds
1129
+ * @param {vec3} outCenter
1130
+ * @returns {number}
1131
+ */
1132
+ box3.bounds.toPositionRadius = function (minBounds, maxBounds, outCenter)
1133
+ {
1134
+ let sX = maxBounds[0] - minBounds[0],
1135
+ sY = maxBounds[1] - minBounds[1],
1136
+ sZ = maxBounds[2] - minBounds[2];
1137
+
1138
+ outCenter[0] = (minBounds[0] + maxBounds[0]) * 0.5;
1139
+ outCenter[1] = (minBounds[1] + maxBounds[1]) * 0.5;
1140
+ outCenter[2] = (minBounds[2] + maxBounds[2]) * 0.5;
1141
+
1142
+ return Math.sqrt(sX * sX + sY * sY + sZ * sZ) * 0.5;
1143
+ };
1144
+
1145
+ /**
1146
+ * Sets a receiving box3 from the translation of a box3 and a vec3
1147
+ *
1148
+ * @param {box3} out - receiving box3
1149
+ * @param {box3} a - source box3
1150
+ * @param {vec3} v - vec3 to translate by
1151
+ * @returns {box3} out - receiving box3
1152
+ */
1153
+ box3.translate = function (out, a, v)
1154
+ {
1155
+ out[0] = a[0] + v[0];
1156
+ out[1] = a[1] + v[1];
1157
+ out[2] = a[2] + v[2];
1158
+ out[3] = a[3] + v[0];
1159
+ out[4] = a[4] + v[1];
1160
+ out[5] = a[5] + v[2];
1161
+ return out;
1162
+ };
1163
+
1164
+ /**
1165
+ * Sets a receiving box3 from the transformation of a box3 with a mat4
1166
+ *
1167
+ * @param {box3} out - receiving box3
1168
+ * @param {box3} a - source box3
1169
+ * @param {mat4} m - mat4 to transform with
1170
+ * @returns {box3} out - receiving box3
1171
+ */
1172
+ box3.transformMat4 = function (out, a, m)
1173
+ {
1174
+ if (box3.isEmpty(a)) return box3.empty(out);
1175
+
1176
+ const
1177
+ ax = a[0],
1178
+ ay = a[1],
1179
+ az = a[2],
1180
+ bx = a[3],
1181
+ by = a[4],
1182
+ bz = a[5],
1183
+ point = vec3.alloc();
1184
+
1185
+ out[0] = out[1] = out[2] = Infinity;
1186
+ out[3] = out[4] = out[5] = -Infinity;
1187
+
1188
+ for (let i = 0; i < 8; i++)
1189
+ {
1190
+ point[0] = i & 1 ? bx : ax;
1191
+ point[1] = i & 2 ? by : ay;
1192
+ point[2] = i & 4 ? bz : az;
1193
+ vec3.transformMat4(point, point, m);
1194
+ box3.addPoint(out, out, point);
1195
+ }
1196
+
1197
+ vec3.unalloc(point);
1198
+
1199
+ return out;
1200
+ };
1201
+
1202
+ /**
1203
+ * Sets a box3 from the union of two box3s
1204
+ *
1205
+ * @param {box3} out - receiving box3
1206
+ * @param {box3} a - first box3
1207
+ * @param {box3} b - second box3
1208
+ * @returns {box3} out - receiving box3
1209
+ */
1210
+ box3.union = function (out, a, b)
1211
+ {
1212
+ out[0] = Math.min(a[0], b[0]);
1213
+ out[1] = Math.min(a[1], b[1]);
1214
+ out[2] = Math.min(a[2], b[2]);
1215
+ out[3] = Math.max(a[3], b[3]);
1216
+ out[4] = Math.max(a[4], b[4]);
1217
+ out[5] = Math.max(a[5], b[5]);
1218
+ return out;
1219
+ };
1220
+
1221
+ /**
1222
+ * Sets a box3 from the union of a box3 and min and max bounds
1223
+ *
1224
+ * @param {box3} out - receiving box3
1225
+ * @param {box3} a - box3
1226
+ * @param {vec3} min - min bounds
1227
+ * @param {vec3} max - max bounds
1228
+ * @returns {box3} out - receiving box3
1229
+ */
1230
+ box3.unionBounds = function (out, a, min, max)
1231
+ {
1232
+ out[0] = Math.min(a[0], min[0]);
1233
+ out[1] = Math.min(a[1], min[1]);
1234
+ out[2] = Math.min(a[2], min[2]);
1235
+ out[3] = Math.max(a[3], max[0]);
1236
+ out[4] = Math.max(a[4], max[1]);
1237
+ out[5] = Math.max(a[5], max[2]);
1238
+ return out;
1239
+ };
1240
+
1241
+ /**
1242
+ * Sets bounds from the union of two sets of bounds
1243
+ *
1244
+ * @param {vec3} outMin
1245
+ * @param {vec3} outMax
1246
+ * @param {vec3} aMin
1247
+ * @param {vec3} aMax
1248
+ * @param {vec3} bMin
1249
+ * @param {vec3} bMax
1250
+ */
1251
+ box3.bounds.union = function (outMin, outMax, aMin, aMax, bMin, bMax)
1252
+ {
1253
+ outMin[0] = Math.min(aMin[0], bMin[0]);
1254
+ outMin[1] = Math.min(aMin[1], bMin[1]);
1255
+ outMin[2] = Math.min(aMin[2], bMin[2]);
1256
+ outMax[0] = Math.max(aMax[0], bMax[0]);
1257
+ outMax[1] = Math.max(aMax[1], bMax[1]);
1258
+ outMax[2] = Math.max(aMax[2], bMax[2]);
1259
+ };
1260
+
1261
+ export const {
1262
+ bounds,
1263
+ alloc,
1264
+ unalloc,
1265
+ $min,
1266
+ $max,
1267
+ addPoint,
1268
+ addPoints,
1269
+ clone,
1270
+ contains,
1271
+ containsBounds,
1272
+ containsPoint,
1273
+ containsValue,
1274
+ copy,
1275
+ copyMin,
1276
+ copyMax,
1277
+ create,
1278
+ distanceToPoint,
1279
+ distanceToValues,
1280
+ empty,
1281
+ equals,
1282
+ equalsBounds,
1283
+ exactEquals,
1284
+ exactEqualsBounds,
1285
+ expandScalar,
1286
+ expandValues,
1287
+ expandVec3,
1288
+ fromArray,
1289
+ fromBounds,
1290
+ from,
1291
+ fromPositionSize,
1292
+ fromPoints,
1293
+ setPoints,
1294
+ fromPositionRadius,
1295
+ fromSph3,
1296
+ fromTransform,
1297
+ fromValues,
1298
+ getCenter,
1299
+ getClampedPoint,
1300
+ getMax,
1301
+ getMin,
1302
+ getSize,
1303
+ getPosition,
1304
+ radius,
1305
+ intersect,
1306
+ intersectBounds,
1307
+ intersects,
1308
+ intersectsBounds,
1309
+ intersectsNormalConstant,
1310
+ intersectsPln,
1311
+ intersectsPoint,
1312
+ intersectsValues,
1313
+ intersectsPositionRadius,
1314
+ intersectsSph3,
1315
+ isEmpty,
1316
+ set,
1317
+ setMinBounds,
1318
+ setMaxBounds,
1319
+ squaredDistanceToPoint,
1320
+ surfaceArea,
1321
+ toArray,
1322
+ toBounds,
1323
+ toPoints,
1324
+ toPositionRadius,
1325
+ translate,
1326
+ transformMat4,
1327
+ union,
1328
+ unionBounds
1329
+ } = box3;