| // Copyright (c) 2015, Google Inc. Please see the AUTHORS file for details. |
| // All rights reserved. Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| part of vector_math_64; |
| |
| /// Defines a [Ray] by an [origin] and a [direction]. |
| class Ray { |
| final Vector3 _origin; |
| final Vector3 _direction; |
| |
| /// The [origin] of the ray. |
| Vector3 get origin => _origin; |
| |
| /// The [direction] of the ray. |
| Vector3 get direction => _direction; |
| |
| /// Create a new, uninitialized ray. |
| Ray() |
| : _origin = Vector3.zero(), |
| _direction = Vector3.zero(); |
| |
| /// Create a ray as a copy of [other]. |
| Ray.copy(Ray other) |
| : _origin = Vector3.copy(other._origin), |
| _direction = Vector3.copy(other._direction); |
| |
| /// Create a ray with an [origin] and a [direction]. |
| Ray.originDirection(Vector3 origin, Vector3 direction) |
| : _origin = Vector3.copy(origin), |
| _direction = Vector3.copy(direction); |
| |
| /// Copy the [origin] and [direction] from [other] into this. |
| void copyFrom(Ray other) { |
| _origin.setFrom(other._origin); |
| _direction.setFrom(other._direction); |
| } |
| |
| /// Returns the position on this with a distance of [t] from [origin]. |
| Vector3 at(double t) => _direction.scaled(t)..add(_origin); |
| |
| /// Copy the position on this with a distance of [t] from [origin] into |
| /// [other]. |
| void copyAt(Vector3 other, double t) { |
| other |
| ..setFrom(_direction) |
| ..scale(t) |
| ..add(_origin); |
| } |
| |
| /// Return the distance from the origin of this to the intersection with |
| /// [other] if this intersects with [other], or null if the don't intersect. |
| double? intersectsWithSphere(Sphere other) { |
| final r = other.radius; |
| final r2 = r * r; |
| final l = other._center.clone()..sub(_origin); |
| final s = l.dot(_direction); |
| final l2 = l.dot(l); |
| if (s < 0 && l2 > r2) { |
| return null; |
| } |
| final m2 = l2 - s * s; |
| if (m2 > r2) { |
| return null; |
| } |
| final q = math.sqrt(r2 - m2); |
| |
| return (l2 > r2) ? s - q : s + q; |
| } |
| |
| // Some varaibles that are used for intersectsWithTriangle and |
| // intersectsWithQuad. The performance is better in Dart and JS if we avoid |
| // to create temporary instance over and over. Also reduce GC. |
| static final _e1 = Vector3.zero(); |
| static final _e2 = Vector3.zero(); |
| static final _q = Vector3.zero(); |
| static final _s = Vector3.zero(); |
| static final _r = Vector3.zero(); |
| |
| /// Return the distance from the origin of this to the intersection with |
| /// [other] if this intersects with [other], or null if the don't intersect. |
| double? intersectsWithTriangle(Triangle other) { |
| const epsilon = 10e-6; |
| |
| final point0 = other._point0; |
| final point1 = other._point1; |
| final point2 = other._point2; |
| |
| _e1 |
| ..setFrom(point1) |
| ..sub(point0); |
| _e2 |
| ..setFrom(point2) |
| ..sub(point0); |
| |
| _direction.crossInto(_e2, _q); |
| final a = _e1.dot(_q); |
| |
| if (a > -epsilon && a < epsilon) { |
| return null; |
| } |
| |
| final f = 1 / a; |
| _s |
| ..setFrom(_origin) |
| ..sub(point0); |
| final u = f * (_s.dot(_q)); |
| |
| if (u < 0.0) { |
| return null; |
| } |
| |
| _s.crossInto(_e1, _r); |
| final v = f * (_direction.dot(_r)); |
| |
| if (v < -epsilon || u + v > 1.0 + epsilon) { |
| return null; |
| } |
| |
| final t = f * (_e2.dot(_r)); |
| |
| return t; |
| } |
| |
| /// Return the distance from the origin of this to the intersection with |
| /// [other] if this intersects with [other], or null if the don't intersect. |
| double? intersectsWithQuad(Quad other) { |
| const epsilon = 10e-6; |
| |
| // First triangle |
| var point0 = other._point0; |
| var point1 = other._point1; |
| var point2 = other._point2; |
| |
| _e1 |
| ..setFrom(point1) |
| ..sub(point0); |
| _e2 |
| ..setFrom(point2) |
| ..sub(point0); |
| |
| _direction.crossInto(_e2, _q); |
| final a0 = _e1.dot(_q); |
| |
| if (!(a0 > -epsilon && a0 < epsilon)) { |
| final f = 1 / a0; |
| _s |
| ..setFrom(_origin) |
| ..sub(point0); |
| final u = f * (_s.dot(_q)); |
| |
| if (u >= 0.0) { |
| _s.crossInto(_e1, _r); |
| final v = f * (_direction.dot(_r)); |
| |
| if (!(v < -epsilon || u + v > 1.0 + epsilon)) { |
| final t = f * (_e2.dot(_r)); |
| |
| return t; |
| } |
| } |
| } |
| |
| // Second triangle |
| point0 = other._point3; |
| point1 = other._point0; |
| point2 = other._point2; |
| |
| _e1 |
| ..setFrom(point1) |
| ..sub(point0); |
| _e2 |
| ..setFrom(point2) |
| ..sub(point0); |
| |
| _direction.crossInto(_e2, _q); |
| final a1 = _e1.dot(_q); |
| |
| if (!(a1 > -epsilon && a1 < epsilon)) { |
| final f = 1 / a1; |
| _s |
| ..setFrom(_origin) |
| ..sub(point0); |
| final u = f * (_s.dot(_q)); |
| |
| if (u >= 0.0) { |
| _s.crossInto(_e1, _r); |
| final v = f * (_direction.dot(_r)); |
| |
| if (!(v < -epsilon || u + v > 1.0 + epsilon)) { |
| final t = f * (_e2.dot(_r)); |
| |
| return t; |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| /// Return the distance from the origin of this to the intersection with |
| /// [other] if this intersects with [other], or null if the don't intersect. |
| double? intersectsWithAabb3(Aabb3 other) { |
| final otherMin = other.min; |
| final otherMax = other.max; |
| |
| var tNear = -double.maxFinite; |
| var tFar = double.maxFinite; |
| |
| for (var i = 0; i < 3; ++i) { |
| if (_direction[i] == 0.0) { |
| if (_origin[i] < otherMin[i] || _origin[i] > otherMax[i]) { |
| return null; |
| } |
| } else { |
| var t1 = (otherMin[i] - _origin[i]) / _direction[i]; |
| var t2 = (otherMax[i] - _origin[i]) / _direction[i]; |
| |
| if (t1 > t2) { |
| final temp = t1; |
| t1 = t2; |
| t2 = temp; |
| } |
| |
| if (t1 > tNear) { |
| tNear = t1; |
| } |
| |
| if (t2 < tFar) { |
| tFar = t2; |
| } |
| |
| if (tNear > tFar || tFar < 0) { |
| return null; |
| } |
| } |
| } |
| |
| return tNear; |
| } |
| } |