|
33 | 33 | #include "core/string/ustring.h"
|
34 | 34 | #include "core/variant/variant.h"
|
35 | 35 |
|
36 |
| -real_t AABB::get_volume() const { |
37 |
| - return size.x * size.y * size.z; |
38 |
| -} |
39 |
| - |
40 |
| -void AABB::merge_with(const AABB &p_aabb) { |
41 |
| -#ifdef MATH_CHECKS |
42 |
| - if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) { |
43 |
| - ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size."); |
44 |
| - } |
45 |
| -#endif |
46 |
| - Vector3 beg_1, beg_2; |
47 |
| - Vector3 end_1, end_2; |
48 |
| - Vector3 min, max; |
49 |
| - |
50 |
| - beg_1 = position; |
51 |
| - beg_2 = p_aabb.position; |
52 |
| - end_1 = size + beg_1; |
53 |
| - end_2 = p_aabb.size + beg_2; |
54 |
| - |
55 |
| - min.x = (beg_1.x < beg_2.x) ? beg_1.x : beg_2.x; |
56 |
| - min.y = (beg_1.y < beg_2.y) ? beg_1.y : beg_2.y; |
57 |
| - min.z = (beg_1.z < beg_2.z) ? beg_1.z : beg_2.z; |
58 |
| - |
59 |
| - max.x = (end_1.x > end_2.x) ? end_1.x : end_2.x; |
60 |
| - max.y = (end_1.y > end_2.y) ? end_1.y : end_2.y; |
61 |
| - max.z = (end_1.z > end_2.z) ? end_1.z : end_2.z; |
62 |
| - |
63 |
| - position = min; |
64 |
| - size = max - min; |
65 |
| -} |
66 |
| - |
67 |
| -bool AABB::is_equal_approx(const AABB &p_aabb) const { |
68 |
| - return position.is_equal_approx(p_aabb.position) && size.is_equal_approx(p_aabb.size); |
69 |
| -} |
70 |
| - |
71 |
| -bool AABB::is_same(const AABB &p_aabb) const { |
72 |
| - return position.is_same(p_aabb.position) && size.is_same(p_aabb.size); |
73 |
| -} |
74 |
| - |
75 |
| -bool AABB::is_finite() const { |
76 |
| - return position.is_finite() && size.is_finite(); |
77 |
| -} |
78 |
| - |
79 |
| -AABB AABB::intersection(const AABB &p_aabb) const { |
80 |
| -#ifdef MATH_CHECKS |
81 |
| - if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) { |
82 |
| - ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size."); |
83 |
| - } |
84 |
| -#endif |
85 |
| - Vector3 src_min = position; |
86 |
| - Vector3 src_max = position + size; |
87 |
| - Vector3 dst_min = p_aabb.position; |
88 |
| - Vector3 dst_max = p_aabb.position + p_aabb.size; |
89 |
| - |
90 |
| - Vector3 min, max; |
91 |
| - |
92 |
| - if (src_min.x > dst_max.x || src_max.x < dst_min.x) { |
93 |
| - return AABB(); |
94 |
| - } else { |
95 |
| - min.x = (src_min.x > dst_min.x) ? src_min.x : dst_min.x; |
96 |
| - max.x = (src_max.x < dst_max.x) ? src_max.x : dst_max.x; |
97 |
| - } |
98 |
| - |
99 |
| - if (src_min.y > dst_max.y || src_max.y < dst_min.y) { |
100 |
| - return AABB(); |
101 |
| - } else { |
102 |
| - min.y = (src_min.y > dst_min.y) ? src_min.y : dst_min.y; |
103 |
| - max.y = (src_max.y < dst_max.y) ? src_max.y : dst_max.y; |
104 |
| - } |
105 |
| - |
106 |
| - if (src_min.z > dst_max.z || src_max.z < dst_min.z) { |
107 |
| - return AABB(); |
108 |
| - } else { |
109 |
| - min.z = (src_min.z > dst_min.z) ? src_min.z : dst_min.z; |
110 |
| - max.z = (src_max.z < dst_max.z) ? src_max.z : dst_max.z; |
111 |
| - } |
112 |
| - |
113 |
| - return AABB(min, max - min); |
114 |
| -} |
115 |
| - |
116 |
| -// Note that this routine returns the BACKTRACKED (i.e. behind the ray origin) |
117 |
| -// intersection point + normal if INSIDE the AABB. |
118 |
| -// The caller can therefore decide when INSIDE whether to use the |
119 |
| -// backtracked intersection, or use p_from as the intersection, and |
120 |
| -// carry on progressing without e.g. reflecting against the normal. |
121 |
| -bool AABB::find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool &r_inside, Vector3 *r_intersection_point, Vector3 *r_normal) const { |
122 |
| -#ifdef MATH_CHECKS |
123 |
| - if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) { |
124 |
| - ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size."); |
125 |
| - } |
126 |
| -#endif |
127 |
| - Vector3 end = position + size; |
128 |
| - real_t tmin = -1e20; |
129 |
| - real_t tmax = 1e20; |
130 |
| - int axis = 0; |
131 |
| - |
132 |
| - // Make sure r_inside is always initialized, |
133 |
| - // to prevent reading uninitialized data in the client code. |
134 |
| - r_inside = false; |
135 |
| - |
136 |
| - for (int i = 0; i < 3; i++) { |
137 |
| - if (p_dir[i] == 0) { |
138 |
| - if ((p_from[i] < position[i]) || (p_from[i] > end[i])) { |
139 |
| - return false; |
140 |
| - } |
141 |
| - } else { // ray not parallel to planes in this direction |
142 |
| - real_t t1 = (position[i] - p_from[i]) / p_dir[i]; |
143 |
| - real_t t2 = (end[i] - p_from[i]) / p_dir[i]; |
144 |
| - |
145 |
| - if (t1 > t2) { |
146 |
| - SWAP(t1, t2); |
147 |
| - } |
148 |
| - if (t1 >= tmin) { |
149 |
| - tmin = t1; |
150 |
| - axis = i; |
151 |
| - } |
152 |
| - if (t2 < tmax) { |
153 |
| - if (t2 < 0) { |
154 |
| - return false; |
155 |
| - } |
156 |
| - tmax = t2; |
157 |
| - } |
158 |
| - if (tmin > tmax) { |
159 |
| - return false; |
160 |
| - } |
161 |
| - } |
162 |
| - } |
163 |
| - |
164 |
| - // Did the ray start from inside the box? |
165 |
| - // In which case the intersection returned is the point of entry |
166 |
| - // (behind the ray start) or the calling routine can use the ray origin as intersection point. |
167 |
| - r_inside = tmin < 0; |
168 |
| - |
169 |
| - if (r_intersection_point) { |
170 |
| - *r_intersection_point = p_from + p_dir * tmin; |
171 |
| - |
172 |
| - // Prevent float error by making sure the point is exactly |
173 |
| - // on the AABB border on the relevant axis. |
174 |
| - r_intersection_point->coord[axis] = (p_dir[axis] >= 0) ? position.coord[axis] : end.coord[axis]; |
175 |
| - } |
176 |
| - if (r_normal) { |
177 |
| - *r_normal = Vector3(); |
178 |
| - (*r_normal)[axis] = (p_dir[axis] >= 0) ? -1 : 1; |
179 |
| - } |
180 |
| - |
181 |
| - return true; |
182 |
| -} |
183 |
| - |
184 |
| -bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_intersection_point, Vector3 *r_normal) const { |
185 |
| -#ifdef MATH_CHECKS |
186 |
| - if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) { |
187 |
| - ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size."); |
188 |
| - } |
189 |
| -#endif |
190 |
| - real_t min = 0, max = 1; |
191 |
| - int axis = 0; |
192 |
| - real_t sign = 0; |
193 |
| - |
194 |
| - for (int i = 0; i < 3; i++) { |
195 |
| - real_t seg_from = p_from[i]; |
196 |
| - real_t seg_to = p_to[i]; |
197 |
| - real_t box_begin = position[i]; |
198 |
| - real_t box_end = box_begin + size[i]; |
199 |
| - real_t cmin, cmax; |
200 |
| - real_t csign; |
201 |
| - |
202 |
| - if (seg_from < seg_to) { |
203 |
| - if (seg_from > box_end || seg_to < box_begin) { |
204 |
| - return false; |
205 |
| - } |
206 |
| - real_t length = seg_to - seg_from; |
207 |
| - cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0; |
208 |
| - cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1; |
209 |
| - csign = -1.0; |
210 |
| - |
211 |
| - } else { |
212 |
| - if (seg_to > box_end || seg_from < box_begin) { |
213 |
| - return false; |
214 |
| - } |
215 |
| - real_t length = seg_to - seg_from; |
216 |
| - cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0; |
217 |
| - cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1; |
218 |
| - csign = 1.0; |
219 |
| - } |
220 |
| - |
221 |
| - if (cmin > min) { |
222 |
| - min = cmin; |
223 |
| - axis = i; |
224 |
| - sign = csign; |
225 |
| - } |
226 |
| - if (cmax < max) { |
227 |
| - max = cmax; |
228 |
| - } |
229 |
| - if (max < min) { |
230 |
| - return false; |
231 |
| - } |
232 |
| - } |
233 |
| - |
234 |
| - Vector3 rel = p_to - p_from; |
235 |
| - |
236 |
| - if (r_normal) { |
237 |
| - Vector3 normal; |
238 |
| - normal[axis] = sign; |
239 |
| - *r_normal = normal; |
240 |
| - } |
241 |
| - |
242 |
| - if (r_intersection_point) { |
243 |
| - *r_intersection_point = p_from + rel * min; |
244 |
| - } |
245 |
| - |
246 |
| - return true; |
247 |
| -} |
248 |
| - |
249 |
| -bool AABB::intersects_plane(const Plane &p_plane) const { |
250 |
| - Vector3 points[8] = { |
251 |
| - Vector3(position.x, position.y, position.z), |
252 |
| - Vector3(position.x, position.y, position.z + size.z), |
253 |
| - Vector3(position.x, position.y + size.y, position.z), |
254 |
| - Vector3(position.x, position.y + size.y, position.z + size.z), |
255 |
| - Vector3(position.x + size.x, position.y, position.z), |
256 |
| - Vector3(position.x + size.x, position.y, position.z + size.z), |
257 |
| - Vector3(position.x + size.x, position.y + size.y, position.z), |
258 |
| - Vector3(position.x + size.x, position.y + size.y, position.z + size.z), |
259 |
| - }; |
260 |
| - |
261 |
| - bool over = false; |
262 |
| - bool under = false; |
263 |
| - |
264 |
| - for (int i = 0; i < 8; i++) { |
265 |
| - if (p_plane.distance_to(points[i]) > 0) { |
266 |
| - over = true; |
267 |
| - } else { |
268 |
| - under = true; |
269 |
| - } |
270 |
| - } |
271 |
| - |
272 |
| - return under && over; |
273 |
| -} |
274 |
| - |
275 |
| -Vector3 AABB::get_longest_axis() const { |
276 |
| - Vector3 axis(1, 0, 0); |
277 |
| - real_t max_size = size.x; |
278 |
| - |
279 |
| - if (size.y > max_size) { |
280 |
| - axis = Vector3(0, 1, 0); |
281 |
| - max_size = size.y; |
282 |
| - } |
283 |
| - |
284 |
| - if (size.z > max_size) { |
285 |
| - axis = Vector3(0, 0, 1); |
286 |
| - } |
287 |
| - |
288 |
| - return axis; |
289 |
| -} |
290 |
| - |
291 |
| -int AABB::get_longest_axis_index() const { |
292 |
| - int axis = 0; |
293 |
| - real_t max_size = size.x; |
294 |
| - |
295 |
| - if (size.y > max_size) { |
296 |
| - axis = 1; |
297 |
| - max_size = size.y; |
298 |
| - } |
299 |
| - |
300 |
| - if (size.z > max_size) { |
301 |
| - axis = 2; |
302 |
| - } |
303 |
| - |
304 |
| - return axis; |
305 |
| -} |
306 |
| - |
307 |
| -Vector3 AABB::get_shortest_axis() const { |
308 |
| - Vector3 axis(1, 0, 0); |
309 |
| - real_t min_size = size.x; |
310 |
| - |
311 |
| - if (size.y < min_size) { |
312 |
| - axis = Vector3(0, 1, 0); |
313 |
| - min_size = size.y; |
314 |
| - } |
315 |
| - |
316 |
| - if (size.z < min_size) { |
317 |
| - axis = Vector3(0, 0, 1); |
318 |
| - } |
319 |
| - |
320 |
| - return axis; |
321 |
| -} |
322 |
| - |
323 |
| -int AABB::get_shortest_axis_index() const { |
324 |
| - int axis = 0; |
325 |
| - real_t min_size = size.x; |
326 |
| - |
327 |
| - if (size.y < min_size) { |
328 |
| - axis = 1; |
329 |
| - min_size = size.y; |
330 |
| - } |
331 |
| - |
332 |
| - if (size.z < min_size) { |
333 |
| - axis = 2; |
334 |
| - } |
335 |
| - |
336 |
| - return axis; |
337 |
| -} |
338 |
| - |
339 |
| -AABB AABB::merge(const AABB &p_with) const { |
340 |
| - AABB aabb = *this; |
341 |
| - aabb.merge_with(p_with); |
342 |
| - return aabb; |
343 |
| -} |
344 |
| - |
345 |
| -AABB AABB::expand(const Vector3 &p_vector) const { |
346 |
| - AABB aabb = *this; |
347 |
| - aabb.expand_to(p_vector); |
348 |
| - return aabb; |
349 |
| -} |
350 |
| - |
351 |
| -AABB AABB::grow(real_t p_by) const { |
352 |
| - AABB aabb = *this; |
353 |
| - aabb.grow_by(p_by); |
354 |
| - return aabb; |
355 |
| -} |
356 |
| - |
357 |
| -void AABB::get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const { |
358 |
| - ERR_FAIL_INDEX(p_edge, 12); |
359 |
| - switch (p_edge) { |
360 |
| - case 0: { |
361 |
| - r_from = Vector3(position.x + size.x, position.y, position.z); |
362 |
| - r_to = Vector3(position.x, position.y, position.z); |
363 |
| - } break; |
364 |
| - case 1: { |
365 |
| - r_from = Vector3(position.x + size.x, position.y, position.z + size.z); |
366 |
| - r_to = Vector3(position.x + size.x, position.y, position.z); |
367 |
| - } break; |
368 |
| - case 2: { |
369 |
| - r_from = Vector3(position.x, position.y, position.z + size.z); |
370 |
| - r_to = Vector3(position.x + size.x, position.y, position.z + size.z); |
371 |
| - |
372 |
| - } break; |
373 |
| - case 3: { |
374 |
| - r_from = Vector3(position.x, position.y, position.z); |
375 |
| - r_to = Vector3(position.x, position.y, position.z + size.z); |
376 |
| - |
377 |
| - } break; |
378 |
| - case 4: { |
379 |
| - r_from = Vector3(position.x, position.y + size.y, position.z); |
380 |
| - r_to = Vector3(position.x + size.x, position.y + size.y, position.z); |
381 |
| - } break; |
382 |
| - case 5: { |
383 |
| - r_from = Vector3(position.x + size.x, position.y + size.y, position.z); |
384 |
| - r_to = Vector3(position.x + size.x, position.y + size.y, position.z + size.z); |
385 |
| - } break; |
386 |
| - case 6: { |
387 |
| - r_from = Vector3(position.x + size.x, position.y + size.y, position.z + size.z); |
388 |
| - r_to = Vector3(position.x, position.y + size.y, position.z + size.z); |
389 |
| - |
390 |
| - } break; |
391 |
| - case 7: { |
392 |
| - r_from = Vector3(position.x, position.y + size.y, position.z + size.z); |
393 |
| - r_to = Vector3(position.x, position.y + size.y, position.z); |
394 |
| - |
395 |
| - } break; |
396 |
| - case 8: { |
397 |
| - r_from = Vector3(position.x, position.y, position.z + size.z); |
398 |
| - r_to = Vector3(position.x, position.y + size.y, position.z + size.z); |
399 |
| - |
400 |
| - } break; |
401 |
| - case 9: { |
402 |
| - r_from = Vector3(position.x, position.y, position.z); |
403 |
| - r_to = Vector3(position.x, position.y + size.y, position.z); |
404 |
| - |
405 |
| - } break; |
406 |
| - case 10: { |
407 |
| - r_from = Vector3(position.x + size.x, position.y, position.z); |
408 |
| - r_to = Vector3(position.x + size.x, position.y + size.y, position.z); |
409 |
| - |
410 |
| - } break; |
411 |
| - case 11: { |
412 |
| - r_from = Vector3(position.x + size.x, position.y, position.z + size.z); |
413 |
| - r_to = Vector3(position.x + size.x, position.y + size.y, position.z + size.z); |
414 |
| - |
415 |
| - } break; |
416 |
| - } |
417 |
| -} |
418 |
| - |
419 | 36 | Variant AABB::intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const {
|
420 | 37 | Vector3 inters;
|
421 | 38 | if (intersects_segment(p_from, p_to, &inters)) {
|
|
0 commit comments