• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

google / vector_math.dart / 13087264509

01 Feb 2025 09:20AM UTC coverage: 26.372%. Remained the same
13087264509

Pull #339

github

web-flow
Merge 4cc64e59c into bd4b574b2
Pull Request #339: Bump the github-actions group with 2 updates

4325 of 16400 relevant lines covered (26.37%)

1.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/lib/src/vector_math_64/aabb3.dart
1
// Copyright (c) 2015, Google Inc. Please see the AUTHORS file for details.
2
// All rights reserved. Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4

5
part of '../../vector_math_64.dart';
6

7
/// Defines a 3-dimensional axis-aligned bounding box between a [min] and a
8
/// [max] position.
9
class Aabb3 {
10
  final Vector3 _min;
11
  final Vector3 _max;
12

13
  Vector3 get min => _min;
×
14
  Vector3 get max => _max;
×
15

16
  /// The center of the AABB.
17
  Vector3 get center => _min.clone()
×
18
    ..add(_max)
×
19
    ..scale(0.5);
×
20

21
  /// Create a new AABB with [min] and [max] set to the origin.
22
  Aabb3()
×
23
      : _min = Vector3.zero(),
×
24
        _max = Vector3.zero();
×
25

26
  /// Create a new AABB as a copy of [other].
27
  Aabb3.copy(Aabb3 other)
×
28
      : _min = Vector3.copy(other._min),
×
29
        _max = Vector3.copy(other._max);
×
30

31
  /// Create a new AABB with a [min] and [max].
32
  Aabb3.minMax(Vector3 min, Vector3 max)
×
33
      : _min = Vector3.copy(min),
×
34
        _max = Vector3.copy(max);
×
35

36
  /// Create a new AABB that encloses a [sphere].
37
  factory Aabb3.fromSphere(Sphere sphere) => Aabb3()..setSphere(sphere);
×
38

39
  /// Create a new AABB that encloses a [triangle].
40
  factory Aabb3.fromTriangle(Triangle triangle) =>
×
41
      Aabb3()..setTriangle(triangle);
×
42

43
  /// Create a new AABB that encloses a [quad].
44
  factory Aabb3.fromQuad(Quad quad) => Aabb3()..setQuad(quad);
×
45

46
  /// Create a new AABB that encloses a [obb].
47
  factory Aabb3.fromObb3(Obb3 obb) => Aabb3()..setObb3(obb);
×
48

49
  /// Create a new AABB that encloses a limited [ray] (or line segment) that has
50
  /// a minLimit and maxLimit.
51
  factory Aabb3.fromRay(Ray ray, double limitMin, double limitMax) =>
×
52
      Aabb3()..setRay(ray, limitMin, limitMax);
×
53

54
  /// Create a new AABB with a [center] and [halfExtents].
55
  factory Aabb3.centerAndHalfExtents(Vector3 center, Vector3 halfExtents) =>
×
56
      Aabb3()..setCenterAndHalfExtents(center, halfExtents);
×
57

58
  /// Constructs [Aabb3] with a min/max storage that views given [buffer]
59
  /// starting at [offset]. [offset] has to be multiple of
60
  /// [Float64List.bytesPerElement].
61
  Aabb3.fromBuffer(ByteBuffer buffer, int offset)
×
62
      : _min = Vector3.fromBuffer(buffer, offset),
×
63
        _max = Vector3.fromBuffer(
×
64
            buffer, offset + Float64List.bytesPerElement * 3);
×
65

66
  /// Set the AABB by a [center] and [halfExtents].
67
  void setCenterAndHalfExtents(Vector3 center, Vector3 halfExtents) {
×
68
    _min
×
69
      ..setFrom(center)
×
70
      ..sub(halfExtents);
×
71
    _max
×
72
      ..setFrom(center)
×
73
      ..add(halfExtents);
×
74
  }
75

76
  /// Set the AABB to enclose a [sphere].
77
  void setSphere(Sphere sphere) {
×
78
    _min
×
79
      ..splat(-sphere.radius)
×
80
      ..add(sphere._center);
×
81
    _max
×
82
      ..splat(sphere.radius)
×
83
      ..add(sphere._center);
×
84
  }
85

86
  /// Set the AABB to enclose a [triangle].
87
  void setTriangle(Triangle triangle) {
×
88
    _min.setValues(
×
89
        math.min(triangle._point0.x,
×
90
            math.min(triangle._point1.x, triangle._point2.x)),
×
91
        math.min(triangle._point0.y,
×
92
            math.min(triangle._point1.y, triangle._point2.y)),
×
93
        math.min(triangle._point0.z,
×
94
            math.min(triangle._point1.z, triangle._point2.z)));
×
95
    _max.setValues(
×
96
        math.max(triangle._point0.x,
×
97
            math.max(triangle._point1.x, triangle._point2.x)),
×
98
        math.max(triangle._point0.y,
×
99
            math.max(triangle._point1.y, triangle._point2.y)),
×
100
        math.max(triangle._point0.z,
×
101
            math.max(triangle._point1.z, triangle._point2.z)));
×
102
  }
103

104
  /// Set the AABB to enclose a [quad].
105
  void setQuad(Quad quad) {
×
106
    _min.setValues(
×
107
        math.min(quad._point0.x,
×
108
            math.min(quad._point1.x, math.min(quad._point2.x, quad._point3.x))),
×
109
        math.min(quad._point0.y,
×
110
            math.min(quad._point1.y, math.min(quad._point2.y, quad._point3.y))),
×
111
        math.min(
×
112
            quad._point0.z,
×
113
            math.min(
×
114
                quad._point1.z, math.min(quad._point2.z, quad._point3.z))));
×
115
    _max.setValues(
×
116
        math.max(quad._point0.x,
×
117
            math.max(quad._point1.x, math.max(quad._point2.x, quad._point3.x))),
×
118
        math.max(quad._point0.y,
×
119
            math.max(quad._point1.y, math.max(quad._point2.y, quad._point3.y))),
×
120
        math.max(
×
121
            quad._point0.z,
×
122
            math.max(
×
123
                quad._point1.z, math.max(quad._point2.z, quad._point3.z))));
×
124
  }
125

126
  /// Set the AABB to enclose a [obb].
127
  void setObb3(Obb3 obb) {
×
128
    final corner = Vector3.zero();
×
129

130
    obb.copyCorner(0, corner);
×
131
    _min.setFrom(corner);
×
132
    _max.setFrom(corner);
×
133

134
    obb.copyCorner(1, corner);
×
135
    hullPoint(corner);
×
136

137
    obb.copyCorner(2, corner);
×
138
    hullPoint(corner);
×
139

140
    obb.copyCorner(3, corner);
×
141
    hullPoint(corner);
×
142

143
    obb.copyCorner(4, corner);
×
144
    hullPoint(corner);
×
145

146
    obb.copyCorner(5, corner);
×
147
    hullPoint(corner);
×
148

149
    obb.copyCorner(6, corner);
×
150
    hullPoint(corner);
×
151

152
    obb.copyCorner(7, corner);
×
153
    hullPoint(corner);
×
154
  }
155

156
  /// Set the AABB to enclose a limited [ray] (or line segment) that is limited
157
  /// by [limitMin] and [limitMax].
158
  void setRay(Ray ray, double limitMin, double limitMax) {
×
159
    ray
160
      ..copyAt(_min, limitMin)
×
161
      ..copyAt(_max, limitMax);
×
162

163
    if (_max.x < _min.x) {
×
164
      final temp = _max.x;
×
165
      _max.x = _min.x;
×
166
      _min.x = temp;
×
167
    }
168

169
    if (_max.y < _min.y) {
×
170
      final temp = _max.y;
×
171
      _max.y = _min.y;
×
172
      _min.y = temp;
×
173
    }
174

175
    if (_max.z < _min.z) {
×
176
      final temp = _max.z;
×
177
      _max.z = _min.z;
×
178
      _min.z = temp;
×
179
    }
180
  }
181

182
  /// Copy the [center] and the [halfExtents] of this.
183
  void copyCenterAndHalfExtents(Vector3 center, Vector3 halfExtents) {
×
184
    center
185
      ..setFrom(_min)
×
186
      ..add(_max)
×
187
      ..scale(0.5);
×
188
    halfExtents
189
      ..setFrom(_max)
×
190
      ..sub(_min)
×
191
      ..scale(0.5);
×
192
  }
193

194
  /// Copy the [center] of this.
195
  void copyCenter(Vector3 center) {
×
196
    center
197
      ..setFrom(_min)
×
198
      ..add(_max)
×
199
      ..scale(0.5);
×
200
  }
201

202
  /// Copy the [min] and [max] from [other] into this.
203
  void copyFrom(Aabb3 other) {
×
204
    _min.setFrom(other._min);
×
205
    _max.setFrom(other._max);
×
206
  }
207

208
  static final _center = Vector3.zero();
×
209
  static final _halfExtents = Vector3.zero();
×
210
  void _updateCenterAndHalfExtents() =>
×
211
      copyCenterAndHalfExtents(_center, _halfExtents);
×
212

213
  /// Transform this by the transform [t].
214
  void transform(Matrix4 t) {
×
215
    _updateCenterAndHalfExtents();
×
216
    t
217
      ..transform3(_center)
×
218
      ..absoluteRotate(_halfExtents);
×
219
    _min
×
220
      ..setFrom(_center)
×
221
      ..sub(_halfExtents);
×
222
    _max
×
223
      ..setFrom(_center)
×
224
      ..add(_halfExtents);
×
225
  }
226

227
  /// Rotate this by the rotation matrix [t].
228
  void rotate(Matrix4 t) {
×
229
    _updateCenterAndHalfExtents();
×
230
    t.absoluteRotate(_halfExtents);
×
231
    _min
×
232
      ..setFrom(_center)
×
233
      ..sub(_halfExtents);
×
234
    _max
×
235
      ..setFrom(_center)
×
236
      ..add(_halfExtents);
×
237
  }
238

239
  /// Create a copy of this that is transformed by the transform [t] and store
240
  /// it in [out].
241
  Aabb3 transformed(Matrix4 t, Aabb3 out) => out
×
242
    ..copyFrom(this)
×
243
    ..transform(t);
×
244

245
  /// Create a copy of this that is rotated by the rotation matrix [t] and
246
  /// store it in [out].
247
  Aabb3 rotated(Matrix4 t, Aabb3 out) => out
×
248
    ..copyFrom(this)
×
249
    ..rotate(t);
×
250

251
  void getPN(Vector3 planeNormal, Vector3 outP, Vector3 outN) {
×
252
    if (planeNormal.x < 0.0) {
×
253
      outP.x = _min.x;
×
254
      outN.x = _max.x;
×
255
    } else {
256
      outP.x = _max.x;
×
257
      outN.x = _min.x;
×
258
    }
259

260
    if (planeNormal.y < 0.0) {
×
261
      outP.y = _min.y;
×
262
      outN.y = _max.y;
×
263
    } else {
264
      outP.y = _max.y;
×
265
      outN.y = _min.y;
×
266
    }
267

268
    if (planeNormal.z < 0.0) {
×
269
      outP.z = _min.z;
×
270
      outN.z = _max.z;
×
271
    } else {
272
      outP.z = _max.z;
×
273
      outN.z = _min.z;
×
274
    }
275
  }
276

277
  /// Set the min and max of this so that this is a hull of this and
278
  /// [other].
279
  void hull(Aabb3 other) {
×
280
    Vector3.min(_min, other._min, _min);
×
281
    Vector3.max(_max, other._max, _max);
×
282
  }
283

284
  /// Set the min and max of this so that this contains [point].
285
  void hullPoint(Vector3 point) {
×
286
    Vector3.min(_min, point, _min);
×
287
    Vector3.max(_max, point, _max);
×
288
  }
289

290
  /// Return if this contains [other].
291
  bool containsAabb3(Aabb3 other) {
×
292
    final otherMax = other._max;
×
293
    final otherMin = other._min;
×
294

295
    return (_min.x < otherMin.x) &&
×
296
        (_min.y < otherMin.y) &&
×
297
        (_min.z < otherMin.z) &&
×
298
        (_max.x > otherMax.x) &&
×
299
        (_max.y > otherMax.y) &&
×
300
        (_max.z > otherMax.z);
×
301
  }
302

303
  /// Return if this contains [other].
304
  bool containsSphere(Sphere other) {
×
305
    final boxExtends = Vector3.all(other.radius);
×
306
    final sphereBox = Aabb3.centerAndHalfExtents(other._center, boxExtends);
×
307

308
    return containsAabb3(sphereBox);
×
309
  }
310

311
  /// Return if this contains [other].
312
  bool containsVector3(Vector3 other) =>
×
313
      (_min.x < other.x) &&
×
314
      (_min.y < other.y) &&
×
315
      (_min.z < other.z) &&
×
316
      (_max.x > other.x) &&
×
317
      (_max.y > other.y) &&
×
318
      (_max.z > other.z);
×
319

320
  /// Return if this contains [other].
321
  bool containsTriangle(Triangle other) =>
×
322
      containsVector3(other._point0) &&
×
323
      containsVector3(other._point1) &&
×
324
      containsVector3(other._point2);
×
325

326
  /// Return if this intersects with [other].
327
  bool intersectsWithAabb3(Aabb3 other) {
×
328
    final otherMax = other._max;
×
329
    final otherMin = other._min;
×
330

331
    return (_min.x <= otherMax.x) &&
×
332
        (_min.y <= otherMax.y) &&
×
333
        (_min.z <= otherMax.z) &&
×
334
        (_max.x >= otherMin.x) &&
×
335
        (_max.y >= otherMin.y) &&
×
336
        (_max.z >= otherMin.z);
×
337
  }
338

339
  /// Return if this intersects with [other].
340
  bool intersectsWithSphere(Sphere other) {
×
341
    final center = other._center;
×
342
    final radius = other.radius;
×
343
    var d = 0.0;
344
    var e = 0.0;
345

346
    for (var i = 0; i < 3; ++i) {
×
347
      if ((e = center[i] - _min[i]) < 0.0) {
×
348
        if (e < -radius) {
×
349
          return false;
350
        }
351

352
        d = d + e * e;
×
353
      } else {
354
        if ((e = center[i] - _max[i]) > 0.0) {
×
355
          if (e > radius) {
×
356
            return false;
357
          }
358

359
          d = d + e * e;
×
360
        }
361
      }
362
    }
363

364
    return d <= radius * radius;
×
365
  }
366

367
  /// Return if this intersects with [other].
368
  bool intersectsWithVector3(Vector3 other) =>
×
369
      (_min.x <= other.x) &&
×
370
      (_min.y <= other.y) &&
×
371
      (_min.z <= other.z) &&
×
372
      (_max.x >= other.x) &&
×
373
      (_max.y >= other.y) &&
×
374
      (_max.z >= other.z);
×
375

376
  // Avoid allocating these instance on every call to intersectsWithTriangle
377
  static final _aabbCenter = Vector3.zero();
×
378
  static final _aabbHalfExtents = Vector3.zero();
×
379
  static final _v0 = Vector3.zero();
×
380
  static final _v1 = Vector3.zero();
×
381
  static final _v2 = Vector3.zero();
×
382
  static final _f0 = Vector3.zero();
×
383
  static final _f1 = Vector3.zero();
×
384
  static final _f2 = Vector3.zero();
×
385
  static final _trianglePlane = Plane();
×
386

387
  static final _u0 = Vector3(1.0, 0.0, 0.0);
×
388
  static final _u1 = Vector3(0.0, 1.0, 0.0);
×
389
  static final _u2 = Vector3(0.0, 0.0, 1.0);
×
390

391
  /// Return if this intersects with [other].
392
  /// [epsilon] allows the caller to specify a custum eplsilon value that should
393
  /// be used for the test. If [result] is specified and an intersection is
394
  /// found, result is modified to contain more details about the type of
395
  /// intersection.
396
  bool intersectsWithTriangle(Triangle other,
×
397
      {double epsilon = 1e-3, IntersectionResult? result}) {
398
    double p0, p1, p2, r, len;
399
    double a;
400

401
    // This line isn't required if we are using center and half extents to
402
    // define a aabb
403
    copyCenterAndHalfExtents(_aabbCenter, _aabbHalfExtents);
×
404

405
    // Translate triangle as conceptually moving AABB to origin
406
    _v0
×
407
      ..setFrom(other.point0)
×
408
      ..sub(_aabbCenter);
×
409
    _v1
×
410
      ..setFrom(other.point1)
×
411
      ..sub(_aabbCenter);
×
412
    _v2
×
413
      ..setFrom(other.point2)
×
414
      ..sub(_aabbCenter);
×
415

416
    // Translate triangle as conceptually moving AABB to origin
417
    _f0
×
418
      ..setFrom(_v1)
×
419
      ..sub(_v0);
×
420
    _f1
×
421
      ..setFrom(_v2)
×
422
      ..sub(_v1);
×
423
    _f2
×
424
      ..setFrom(_v0)
×
425
      ..sub(_v2);
×
426

427
    // Test axes a00..a22 (category 3)
428
    // Test axis a00
429
    len = _f0.y * _f0.y + _f0.z * _f0.z;
×
430
    if (len > epsilon) {
×
431
      // Ignore tests on degenerate axes.
432
      p0 = _v0.z * _f0.y - _v0.y * _f0.z;
×
433
      p2 = _v2.z * _f0.y - _v2.y * _f0.z;
×
434
      r = _aabbHalfExtents[1] * _f0.z.abs() + _aabbHalfExtents[2] * _f0.y.abs();
×
435
      if (math.max(-math.max(p0, p2), math.min(p0, p2)) > r + epsilon) {
×
436
        return false; // Axis is a separating axis
437
      }
438

439
      a = math.min(p0, p2) - r;
×
440
      if (result != null && (result._depth == null || (result._depth!) < a)) {
×
441
        result._depth = a;
×
442
        _u0.crossInto(_f0, result.axis);
×
443
      }
444
    }
445

446
    // Test axis a01
447
    len = _f1.y * _f1.y + _f1.z * _f1.z;
×
448
    if (len > epsilon) {
×
449
      // Ignore tests on degenerate axes.
450
      p0 = _v0.z * _f1.y - _v0.y * _f1.z;
×
451
      p1 = _v1.z * _f1.y - _v1.y * _f1.z;
×
452
      r = _aabbHalfExtents[1] * _f1.z.abs() + _aabbHalfExtents[2] * _f1.y.abs();
×
453
      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
×
454
        return false; // Axis is a separating axis
455
      }
456

457
      a = math.min(p0, p1) - r;
×
458
      if (result != null && (result._depth == null || (result._depth!) < a)) {
×
459
        result._depth = a;
×
460
        _u0.crossInto(_f1, result.axis);
×
461
      }
462
    }
463

464
    // Test axis a02
465
    len = _f2.y * _f2.y + _f2.z * _f2.z;
×
466
    if (len > epsilon) {
×
467
      // Ignore tests on degenerate axes.
468
      p0 = _v0.z * _f2.y - _v0.y * _f2.z;
×
469
      p1 = _v1.z * _f2.y - _v1.y * _f2.z;
×
470
      r = _aabbHalfExtents[1] * _f2.z.abs() + _aabbHalfExtents[2] * _f2.y.abs();
×
471
      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
×
472
        return false; // Axis is a separating axis
473
      }
474

475
      a = math.min(p0, p1) - r;
×
476
      if (result != null && (result._depth == null || (result._depth!) < a)) {
×
477
        result._depth = a;
×
478
        _u0.crossInto(_f2, result.axis);
×
479
      }
480
    }
481

482
    // Test axis a10
483
    len = _f0.x * _f0.x + _f0.z * _f0.z;
×
484
    if (len > epsilon) {
×
485
      // Ignore tests on degenerate axes.
486
      p0 = _v0.x * _f0.z - _v0.z * _f0.x;
×
487
      p2 = _v2.x * _f0.z - _v2.z * _f0.x;
×
488
      r = _aabbHalfExtents[0] * _f0.z.abs() + _aabbHalfExtents[2] * _f0.x.abs();
×
489
      if (math.max(-math.max(p0, p2), math.min(p0, p2)) > r + epsilon) {
×
490
        return false; // Axis is a separating axis
491
      }
492

493
      a = math.min(p0, p2) - r;
×
494
      if (result != null && (result._depth == null || (result._depth!) < a)) {
×
495
        result._depth = a;
×
496
        _u1.crossInto(_f0, result.axis);
×
497
      }
498
    }
499

500
    // Test axis a11
501
    len = _f1.x * _f1.x + _f1.z * _f1.z;
×
502
    if (len > epsilon) {
×
503
      // Ignore tests on degenerate axes.
504
      p0 = _v0.x * _f1.z - _v0.z * _f1.x;
×
505
      p1 = _v1.x * _f1.z - _v1.z * _f1.x;
×
506
      r = _aabbHalfExtents[0] * _f1.z.abs() + _aabbHalfExtents[2] * _f1.x.abs();
×
507
      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
×
508
        return false; // Axis is a separating axis
509
      }
510

511
      a = math.min(p0, p1) - r;
×
512
      if (result != null && (result._depth == null || (result._depth!) < a)) {
×
513
        result._depth = a;
×
514
        _u1.crossInto(_f1, result.axis);
×
515
      }
516
    }
517

518
    // Test axis a12
519
    len = _f2.x * _f2.x + _f2.z * _f2.z;
×
520
    if (len > epsilon) {
×
521
      // Ignore tests on degenerate axes.
522
      p0 = _v0.x * _f2.z - _v0.z * _f2.x;
×
523
      p1 = _v1.x * _f2.z - _v1.z * _f2.x;
×
524
      r = _aabbHalfExtents[0] * _f2.z.abs() + _aabbHalfExtents[2] * _f2.x.abs();
×
525
      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
×
526
        return false; // Axis is a separating axis
527
      }
528

529
      a = math.min(p0, p1) - r;
×
530
      if (result != null && (result._depth == null || (result._depth!) < a)) {
×
531
        result._depth = a;
×
532
        _u1.crossInto(_f2, result.axis);
×
533
      }
534
    }
535

536
    // Test axis a20
537
    len = _f0.x * _f0.x + _f0.y * _f0.y;
×
538
    if (len > epsilon) {
×
539
      // Ignore tests on degenerate axes.
540
      p0 = _v0.y * _f0.x - _v0.x * _f0.y;
×
541
      p2 = _v2.y * _f0.x - _v2.x * _f0.y;
×
542
      r = _aabbHalfExtents[0] * _f0.y.abs() + _aabbHalfExtents[1] * _f0.x.abs();
×
543
      if (math.max(-math.max(p0, p2), math.min(p0, p2)) > r + epsilon) {
×
544
        return false; // Axis is a separating axis
545
      }
546

547
      a = math.min(p0, p2) - r;
×
548
      if (result != null && (result._depth == null || (result._depth!) < a)) {
×
549
        result._depth = a;
×
550
        _u2.crossInto(_f0, result.axis);
×
551
      }
552
    }
553

554
    // Test axis a21
555
    len = _f1.x * _f1.x + _f1.y * _f1.y;
×
556
    if (len > epsilon) {
×
557
      // Ignore tests on degenerate axes.
558
      p0 = _v0.y * _f1.x - _v0.x * _f1.y;
×
559
      p1 = _v1.y * _f1.x - _v1.x * _f1.y;
×
560
      r = _aabbHalfExtents[0] * _f1.y.abs() + _aabbHalfExtents[1] * _f1.x.abs();
×
561
      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
×
562
        return false; // Axis is a separating axis
563
      }
564

565
      a = math.min(p0, p1) - r;
×
566
      if (result != null && (result._depth == null || (result._depth!) < a)) {
×
567
        result._depth = a;
×
568
        _u2.crossInto(_f1, result.axis);
×
569
      }
570
    }
571

572
    // Test axis a22
573
    len = _f2.x * _f2.x + _f2.y * _f2.y;
×
574
    if (len > epsilon) {
×
575
      // Ignore tests on degenerate axes.
576
      p0 = _v0.y * _f2.x - _v0.x * _f2.y;
×
577
      p1 = _v1.y * _f2.x - _v1.x * _f2.y;
×
578
      r = _aabbHalfExtents[0] * _f2.y.abs() + _aabbHalfExtents[1] * _f2.x.abs();
×
579
      if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
×
580
        return false; // Axis is a separating axis
581
      }
582

583
      a = math.min(p0, p1) - r;
×
584
      if (result != null && (result._depth == null || (result._depth!) < a)) {
×
585
        result._depth = a;
×
586
        _u2.crossInto(_f2, result.axis);
×
587
      }
588
    }
589

590
    // Test the three axes corresponding to the face normals of AABB b
591
    // (category 1).
592
    // Exit if [-e0, e0] and [min(v0.x,v1.x,v2.x), max(v0.x,v1.x,v2.x)] do not
593
    // overlap
594
    if (math.max(_v0.x, math.max(_v1.x, _v2.x)) < -_aabbHalfExtents[0] ||
×
595
        math.min(_v0.x, math.min(_v1.x, _v2.x)) > _aabbHalfExtents[0]) {
×
596
      return false;
597
    }
598
    a = math.min(_v0.x, math.min(_v1.x, _v2.x)) - _aabbHalfExtents[0];
×
599
    if (result != null && (result._depth == null || (result._depth!) < a)) {
×
600
      result._depth = a;
×
601
      result.axis.setFrom(_u0);
×
602
    }
603
    // ... [-e1, e1] and [min(v0.y,v1.y,v2.y), max(v0.y,v1.y,v2.y)] do not
604
    // overlap
605
    if (math.max(_v0.y, math.max(_v1.y, _v2.y)) < -_aabbHalfExtents[1] ||
×
606
        math.min(_v0.y, math.min(_v1.y, _v2.y)) > _aabbHalfExtents[1]) {
×
607
      return false;
608
    }
609
    a = math.min(_v0.y, math.min(_v1.y, _v2.y)) - _aabbHalfExtents[1];
×
610
    if (result != null && (result._depth == null || (result._depth!) < a)) {
×
611
      result._depth = a;
×
612
      result.axis.setFrom(_u1);
×
613
    }
614
    // ... [-e2, e2] and [min(v0.z,v1.z,v2.z), max(v0.z,v1.z,v2.z)] do not
615
    // overlap
616
    if (math.max(_v0.z, math.max(_v1.z, _v2.z)) < -_aabbHalfExtents[2] ||
×
617
        math.min(_v0.z, math.min(_v1.z, _v2.z)) > _aabbHalfExtents[2]) {
×
618
      return false;
619
    }
620
    a = math.min(_v0.z, math.min(_v1.z, _v2.z)) - _aabbHalfExtents[2];
×
621
    if (result != null && (result._depth == null || (result._depth!) < a)) {
×
622
      result._depth = a;
×
623
      result.axis.setFrom(_u2);
×
624
    }
625

626
    // It seems like that wee need to move the edges before creating the
627
    // plane
628
    _v0.add(_aabbCenter);
×
629

630
    // Test separating axis corresponding to triangle face normal (category 2)
631
    _f0.crossInto(_f1, _trianglePlane.normal);
×
632
    _trianglePlane.constant = _trianglePlane.normal.dot(_v0);
×
633
    return intersectsWithPlane(_trianglePlane, result: result);
×
634
  }
635

636
  /// Return if this intersects with [other]
637
  bool intersectsWithPlane(Plane other, {IntersectionResult? result}) {
×
638
    // This line is not necessary with a (center, extents) AABB representation
639
    copyCenterAndHalfExtents(_aabbCenter, _aabbHalfExtents);
×
640

641
    // Compute the projection interval radius of b onto L(t) = b.c + t * p.n
642
    final r = _aabbHalfExtents[0] * other.normal[0].abs() +
×
643
        _aabbHalfExtents[1] * other.normal[1].abs() +
×
644
        _aabbHalfExtents[2] * other.normal[2].abs();
×
645
    // Compute distance of box center from plane
646
    final s = other.normal.dot(_aabbCenter) - other.constant;
×
647
    // Intersection occurs when distance s falls within [-r,+r] interval
648
    if (s.abs() <= r) {
×
649
      final a = s - r;
×
650
      if (result != null && (result._depth == null || (result._depth!) < a)) {
×
651
        result._depth = a;
×
652
        result.axis.setFrom(other.normal);
×
653
      }
654
      return true;
655
    }
656

657
    return false;
658
  }
659

660
  // Avoid allocating these instance on every call to intersectsWithTriangle
661
  static final _quadTriangle0 = Triangle();
×
662
  static final _quadTriangle1 = Triangle();
×
663

664
  /// Return `true` if this intersects with [other].
665
  ///
666
  /// If [result] is specified and an intersection is
667
  /// found, result is modified to contain more details about the type of
668
  /// intersection.
669
  bool intersectsWithQuad(Quad other, {IntersectionResult? result}) {
×
670
    other.copyTriangles(_quadTriangle0, _quadTriangle1);
×
671

672
    return intersectsWithTriangle(_quadTriangle0, result: result) ||
×
673
        intersectsWithTriangle(_quadTriangle1, result: result);
×
674
  }
675
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc