Skip to content

Commit fc21954

Browse files
committed
Remove duplicate code between intersects_ray and intersects_segment
1 parent b9437c3 commit fc21954

11 files changed

+230
-330
lines changed

core/math/aabb.cpp

+4-69
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,15 @@ AABB AABB::intersection(const AABB &p_aabb) const {
122122
// The caller can therefore decide when INSIDE whether to use the
123123
// backtracked intersection, or use p_from as the intersection, and
124124
// carry on progressing without e.g. reflecting against the normal.
125-
bool AABB::find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool &r_inside, Vector3 *r_intersection_point, Vector3 *r_normal) const {
125+
bool AABB::find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool &r_inside, Vector3 *r_intersection_point, Vector3 *r_normal, real_t p_max_distance) const {
126126
#ifdef MATH_CHECKS
127127
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
128128
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
129129
}
130130
#endif
131131
Vector3 end = position + size;
132-
real_t tmin = -1e20;
133-
real_t tmax = 1e20;
132+
real_t tmin = -INFINITY;
133+
real_t tmax = INFINITY;
134134
int axis = 0;
135135

136136
// Make sure r_inside is always initialized,
@@ -159,7 +159,7 @@ bool AABB::find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool
159159
}
160160
tmax = t2;
161161
}
162-
if (tmin > tmax) {
162+
if (tmin > tmax || (p_max_distance > 0 && tmin > p_max_distance)) {
163163
return false;
164164
}
165165
}
@@ -185,71 +185,6 @@ bool AABB::find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool
185185
return true;
186186
}
187187

188-
bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_intersection_point, Vector3 *r_normal) const {
189-
#ifdef MATH_CHECKS
190-
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
191-
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
192-
}
193-
#endif
194-
real_t min = 0, max = 1;
195-
int axis = 0;
196-
real_t sign = 0;
197-
198-
for (int i = 0; i < 3; i++) {
199-
real_t seg_from = p_from[i];
200-
real_t seg_to = p_to[i];
201-
real_t box_begin = position[i];
202-
real_t box_end = box_begin + size[i];
203-
real_t cmin, cmax;
204-
real_t csign;
205-
206-
if (seg_from < seg_to) {
207-
if (seg_from > box_end || seg_to < box_begin) {
208-
return false;
209-
}
210-
real_t length = seg_to - seg_from;
211-
cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0;
212-
cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1;
213-
csign = -1.0;
214-
215-
} else {
216-
if (seg_to > box_end || seg_from < box_begin) {
217-
return false;
218-
}
219-
real_t length = seg_to - seg_from;
220-
cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0;
221-
cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1;
222-
csign = 1.0;
223-
}
224-
225-
if (cmin > min) {
226-
min = cmin;
227-
axis = i;
228-
sign = csign;
229-
}
230-
if (cmax < max) {
231-
max = cmax;
232-
}
233-
if (max < min) {
234-
return false;
235-
}
236-
}
237-
238-
Vector3 rel = p_to - p_from;
239-
240-
if (r_normal) {
241-
Vector3 normal;
242-
normal[axis] = sign;
243-
*r_normal = normal;
244-
}
245-
246-
if (r_intersection_point) {
247-
*r_intersection_point = p_from + rel * min;
248-
}
249-
250-
return true;
251-
}
252-
253188
bool AABB::intersects_plane(const Plane &p_plane) const {
254189
Vector3 points[8] = {
255190
Vector3(position.x, position.y, position.z),

core/math/aabb.h

+32-2
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,42 @@ struct [[nodiscard]] AABB {
7373
AABB intersection(const AABB &p_aabb) const; ///get box where two intersect, empty if no intersection occurs
7474
_FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t p_t0, real_t p_t1) const;
7575

76-
bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_intersection_point = nullptr, Vector3 *r_normal = nullptr) const;
76+
bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_intersection_point = nullptr, Vector3 *r_normal = nullptr) const {
77+
Vector3 segment = p_to - p_from;
78+
real_t length = segment.length();
79+
if (unlikely(length == 0)) { // p_from and p_to are strictly identical.
80+
if (!has_point(p_from)) {
81+
return false;
82+
}
83+
if (r_intersection_point != nullptr) {
84+
*r_intersection_point = p_from;
85+
}
86+
if (r_normal != nullptr) {
87+
*r_normal = Vector3();
88+
}
89+
return true;
90+
}
91+
92+
bool inside = false;
93+
bool inter = find_intersects_ray(p_from, segment / length, inside, r_intersection_point, r_normal, length);
94+
if (inter && inside) {
95+
// Revert intersection to p_from if the latter is located inside the box.
96+
// This is because find_intersects_ray() returns the ray's entry point in the box *before* the starting point in this case.
97+
// While this behavior may be relevant with infinite rays, it's not consistent with a segment intersection.
98+
if (r_intersection_point != nullptr) {
99+
*r_intersection_point = p_from;
100+
}
101+
if (r_normal != nullptr) {
102+
*r_normal = Vector3();
103+
}
104+
}
105+
return inter;
106+
}
77107
bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir) const {
78108
bool inside;
79109
return find_intersects_ray(p_from, p_dir, inside);
80110
}
81-
bool find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool &r_inside, Vector3 *r_intersection_point = nullptr, Vector3 *r_normal = nullptr) const;
111+
bool find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool &r_inside, Vector3 *r_intersection_point = nullptr, Vector3 *r_normal = nullptr, real_t p_max_distance = 0) const;
82112

83113
_FORCE_INLINE_ bool intersects_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const;
84114
_FORCE_INLINE_ bool inside_convex_shape(const Plane *p_planes, int p_plane_count) const;

core/math/face3.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ int Face3::split_by_plane(const Plane &p_plane, Face3 p_res[3], bool p_is_point_
107107
return polygons_created;
108108
}
109109

110-
bool Face3::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const {
111-
return Geometry3D::ray_intersects_triangle(p_from, p_dir, vertex[0], vertex[1], vertex[2], p_intersection);
110+
bool Face3::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection, real_t p_dist) const {
111+
return Geometry3D::ray_intersects_triangle(p_from, p_dir, vertex[0], vertex[1], vertex[2], p_intersection, p_dist);
112112
}
113113

114114
bool Face3::intersects_segment(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const {

core/math/face3.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ struct [[nodiscard]] Face3 {
6262

6363
Vector3 get_closest_point_to(const Vector3 &p_point) const;
6464

65-
bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection = nullptr) const;
65+
bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection = nullptr, real_t p_dist = 0.0) const;
6666
bool intersects_segment(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection = nullptr) const;
6767

6868
void get_support(const Vector3 &p_normal, const Transform3D &p_transform, Vector3 *p_vertices, int *p_count, int p_max) const;

0 commit comments

Comments
 (0)