intersectsWithTriangle method Null safety
- Triangle other,
- {double epsilon = 1e-3,
- IntersectionResult? result}
Return if this intersects with other
.
epsilon
allows the caller to specify a custum eplsilon value that should
be used for the test. If result
is specified and an intersection is
found, result is modified to contain more details about the type of
intersection.
Implementation
bool intersectsWithTriangle(Triangle other,
{double epsilon = 1e-3, IntersectionResult? result}) {
double p0, p1, p2, r, len;
double a;
// This line isn't required if we are using center and half extents to
// define a aabb
copyCenterAndHalfExtents(_aabbCenter, _aabbHalfExtents);
// Translate triangle as conceptually moving AABB to origin
_v0
..setFrom(other.point0)
..sub(_aabbCenter);
_v1
..setFrom(other.point1)
..sub(_aabbCenter);
_v2
..setFrom(other.point2)
..sub(_aabbCenter);
// Translate triangle as conceptually moving AABB to origin
_f0
..setFrom(_v1)
..sub(_v0);
_f1
..setFrom(_v2)
..sub(_v1);
_f2
..setFrom(_v0)
..sub(_v2);
// Test axes a00..a22 (category 3)
// Test axis a00
len = _f0.y * _f0.y + _f0.z * _f0.z;
if (len > epsilon) {
// Ignore tests on degenerate axes.
p0 = _v0.z * _f0.y - _v0.y * _f0.z;
p2 = _v2.z * _f0.y - _v2.y * _f0.z;
r = _aabbHalfExtents[1] * _f0.z.abs() + _aabbHalfExtents[2] * _f0.y.abs();
if (math.max(-math.max(p0, p2), math.min(p0, p2)) > r + epsilon) {
return false; // Axis is a separating axis
}
a = math.min(p0, p2) - r;
if (result != null && (result._depth == null || (result._depth!) < a)) {
result._depth = a;
_u0.crossInto(_f0, result.axis);
}
}
// Test axis a01
len = _f1.y * _f1.y + _f1.z * _f1.z;
if (len > epsilon) {
// Ignore tests on degenerate axes.
p0 = _v0.z * _f1.y - _v0.y * _f1.z;
p1 = _v1.z * _f1.y - _v1.y * _f1.z;
r = _aabbHalfExtents[1] * _f1.z.abs() + _aabbHalfExtents[2] * _f1.y.abs();
if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
return false; // Axis is a separating axis
}
a = math.min(p0, p1) - r;
if (result != null && (result._depth == null || (result._depth!) < a)) {
result._depth = a;
_u0.crossInto(_f1, result.axis);
}
}
// Test axis a02
len = _f2.y * _f2.y + _f2.z * _f2.z;
if (len > epsilon) {
// Ignore tests on degenerate axes.
p0 = _v0.z * _f2.y - _v0.y * _f2.z;
p1 = _v1.z * _f2.y - _v1.y * _f2.z;
r = _aabbHalfExtents[1] * _f2.z.abs() + _aabbHalfExtents[2] * _f2.y.abs();
if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
return false; // Axis is a separating axis
}
a = math.min(p0, p1) - r;
if (result != null && (result._depth == null || (result._depth!) < a)) {
result._depth = a;
_u0.crossInto(_f2, result.axis);
}
}
// Test axis a10
len = _f0.x * _f0.x + _f0.z * _f0.z;
if (len > epsilon) {
// Ignore tests on degenerate axes.
p0 = _v0.x * _f0.z - _v0.z * _f0.x;
p2 = _v2.x * _f0.z - _v2.z * _f0.x;
r = _aabbHalfExtents[0] * _f0.z.abs() + _aabbHalfExtents[2] * _f0.x.abs();
if (math.max(-math.max(p0, p2), math.min(p0, p2)) > r + epsilon) {
return false; // Axis is a separating axis
}
a = math.min(p0, p2) - r;
if (result != null && (result._depth == null || (result._depth!) < a)) {
result._depth = a;
_u1.crossInto(_f0, result.axis);
}
}
// Test axis a11
len = _f1.x * _f1.x + _f1.z * _f1.z;
if (len > epsilon) {
// Ignore tests on degenerate axes.
p0 = _v0.x * _f1.z - _v0.z * _f1.x;
p1 = _v1.x * _f1.z - _v1.z * _f1.x;
r = _aabbHalfExtents[0] * _f1.z.abs() + _aabbHalfExtents[2] * _f1.x.abs();
if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
return false; // Axis is a separating axis
}
a = math.min(p0, p1) - r;
if (result != null && (result._depth == null || (result._depth!) < a)) {
result._depth = a;
_u1.crossInto(_f1, result.axis);
}
}
// Test axis a12
len = _f2.x * _f2.x + _f2.z * _f2.z;
if (len > epsilon) {
// Ignore tests on degenerate axes.
p0 = _v0.x * _f2.z - _v0.z * _f2.x;
p1 = _v1.x * _f2.z - _v1.z * _f2.x;
r = _aabbHalfExtents[0] * _f2.z.abs() + _aabbHalfExtents[2] * _f2.x.abs();
if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
return false; // Axis is a separating axis
}
a = math.min(p0, p1) - r;
if (result != null && (result._depth == null || (result._depth!) < a)) {
result._depth = a;
_u1.crossInto(_f2, result.axis);
}
}
// Test axis a20
len = _f0.x * _f0.x + _f0.y * _f0.y;
if (len > epsilon) {
// Ignore tests on degenerate axes.
p0 = _v0.y * _f0.x - _v0.x * _f0.y;
p2 = _v2.y * _f0.x - _v2.x * _f0.y;
r = _aabbHalfExtents[0] * _f0.y.abs() + _aabbHalfExtents[1] * _f0.x.abs();
if (math.max(-math.max(p0, p2), math.min(p0, p2)) > r + epsilon) {
return false; // Axis is a separating axis
}
a = math.min(p0, p2) - r;
if (result != null && (result._depth == null || (result._depth!) < a)) {
result._depth = a;
_u2.crossInto(_f0, result.axis);
}
}
// Test axis a21
len = _f1.x * _f1.x + _f1.y * _f1.y;
if (len > epsilon) {
// Ignore tests on degenerate axes.
p0 = _v0.y * _f1.x - _v0.x * _f1.y;
p1 = _v1.y * _f1.x - _v1.x * _f1.y;
r = _aabbHalfExtents[0] * _f1.y.abs() + _aabbHalfExtents[1] * _f1.x.abs();
if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
return false; // Axis is a separating axis
}
a = math.min(p0, p1) - r;
if (result != null && (result._depth == null || (result._depth!) < a)) {
result._depth = a;
_u2.crossInto(_f1, result.axis);
}
}
// Test axis a22
len = _f2.x * _f2.x + _f2.y * _f2.y;
if (len > epsilon) {
// Ignore tests on degenerate axes.
p0 = _v0.y * _f2.x - _v0.x * _f2.y;
p1 = _v1.y * _f2.x - _v1.x * _f2.y;
r = _aabbHalfExtents[0] * _f2.y.abs() + _aabbHalfExtents[1] * _f2.x.abs();
if (math.max(-math.max(p0, p1), math.min(p0, p1)) > r + epsilon) {
return false; // Axis is a separating axis
}
a = math.min(p0, p1) - r;
if (result != null && (result._depth == null || (result._depth!) < a)) {
result._depth = a;
_u2.crossInto(_f2, result.axis);
}
}
// Test the three axes corresponding to the face normals of AABB b (category 1). // Exit if...
// ... [-e0, e0] and [min(v0.x,v1.x,v2.x), max(v0.x,v1.x,v2.x)] do not overlap
if (math.max(_v0.x, math.max(_v1.x, _v2.x)) < -_aabbHalfExtents[0] ||
math.min(_v0.x, math.min(_v1.x, _v2.x)) > _aabbHalfExtents[0]) {
return false;
}
a = math.min(_v0.x, math.min(_v1.x, _v2.x)) - _aabbHalfExtents[0];
if (result != null && (result._depth == null || (result._depth!) < a)) {
result._depth = a;
result.axis.setFrom(_u0);
}
// ... [-e1, e1] and [min(v0.y,v1.y,v2.y), max(v0.y,v1.y,v2.y)] do not overlap
if (math.max(_v0.y, math.max(_v1.y, _v2.y)) < -_aabbHalfExtents[1] ||
math.min(_v0.y, math.min(_v1.y, _v2.y)) > _aabbHalfExtents[1]) {
return false;
}
a = math.min(_v0.y, math.min(_v1.y, _v2.y)) - _aabbHalfExtents[1];
if (result != null && (result._depth == null || (result._depth!) < a)) {
result._depth = a;
result.axis.setFrom(_u1);
}
// ... [-e2, e2] and [min(v0.z,v1.z,v2.z), max(v0.z,v1.z,v2.z)] do not overlap
if (math.max(_v0.z, math.max(_v1.z, _v2.z)) < -_aabbHalfExtents[2] ||
math.min(_v0.z, math.min(_v1.z, _v2.z)) > _aabbHalfExtents[2]) {
return false;
}
a = math.min(_v0.z, math.min(_v1.z, _v2.z)) - _aabbHalfExtents[2];
if (result != null && (result._depth == null || (result._depth!) < a)) {
result._depth = a;
result.axis.setFrom(_u2);
}
// It seems like that wee need to move the edges before creating the
// plane
_v0.add(_aabbCenter);
// Test separating axis corresponding to triangle face normal (category 2)
_f0.crossInto(_f1, _trianglePlane.normal);
_trianglePlane.constant = _trianglePlane.normal.dot(_v0);
return intersectsWithPlane(_trianglePlane, result: result);
}