Warn when using an AABB or Rect2 with a negative size

(cherry picked from commit 9687f6fca3)
This commit is contained in:
Aaron Franke 2020-04-06 04:34:18 -04:00 committed by Rémi Verschelde
parent d0569255f2
commit d75e580765
No known key found for this signature in database
GPG key ID: C3336907360768E1
6 changed files with 140 additions and 6 deletions

View file

@ -82,6 +82,11 @@ bool AABB::create_from_points(const Vector<Vector3> &p_points) {
} }
void AABB::merge_with(const AABB &p_aabb) { void AABB::merge_with(const AABB &p_aabb) {
#ifdef MATH_CHECKS
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)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
Vector3 beg_1, beg_2; Vector3 beg_1, beg_2;
Vector3 end_1, end_2; Vector3 end_1, end_2;
Vector3 min, max; Vector3 min, max;
@ -108,6 +113,11 @@ bool AABB::is_equal_approx(const AABB &p_aabb) const {
} }
AABB AABB::intersection(const AABB &p_aabb) const { AABB AABB::intersection(const AABB &p_aabb) const {
#ifdef MATH_CHECKS
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)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
Vector3 src_min = position; Vector3 src_min = position;
Vector3 src_max = position + size; Vector3 src_max = position + size;
Vector3 dst_min = p_aabb.position; Vector3 dst_min = p_aabb.position;
@ -140,6 +150,11 @@ AABB AABB::intersection(const AABB &p_aabb) const {
} }
bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const { bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
Vector3 c1, c2; Vector3 c1, c2;
Vector3 end = position + size; Vector3 end = position + size;
real_t near = -1e20; real_t near = -1e20;
@ -183,6 +198,11 @@ bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *
} }
bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const { bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
real_t min = 0, max = 1; real_t min = 0, max = 1;
int axis = 0; int axis = 0;
real_t sign = 0; real_t sign = 0;

View file

@ -115,6 +115,11 @@ public:
}; };
inline bool AABB::intersects(const AABB &p_aabb) const { inline bool AABB::intersects(const AABB &p_aabb) const {
#ifdef MATH_CHECKS
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)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
if (position.x >= (p_aabb.position.x + p_aabb.size.x)) { if (position.x >= (p_aabb.position.x + p_aabb.size.x)) {
return false; return false;
} }
@ -138,6 +143,11 @@ inline bool AABB::intersects(const AABB &p_aabb) const {
} }
inline bool AABB::intersects_inclusive(const AABB &p_aabb) const { inline bool AABB::intersects_inclusive(const AABB &p_aabb) const {
#ifdef MATH_CHECKS
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)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
if (position.x > (p_aabb.position.x + p_aabb.size.x)) { if (position.x > (p_aabb.position.x + p_aabb.size.x)) {
return false; return false;
} }
@ -161,6 +171,11 @@ inline bool AABB::intersects_inclusive(const AABB &p_aabb) const {
} }
inline bool AABB::encloses(const AABB &p_aabb) const { inline bool AABB::encloses(const AABB &p_aabb) const {
#ifdef MATH_CHECKS
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)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
Vector3 src_min = position; Vector3 src_min = position;
Vector3 src_max = position + size; Vector3 src_max = position + size;
Vector3 dst_min = p_aabb.position; Vector3 dst_min = p_aabb.position;
@ -271,6 +286,11 @@ bool AABB::inside_convex_shape(const Plane *p_planes, int p_plane_count) const {
} }
bool AABB::has_point(const Vector3 &p_point) const { bool AABB::has_point(const Vector3 &p_point) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
if (p_point.x < position.x) { if (p_point.x < position.x) {
return false; return false;
} }
@ -294,6 +314,11 @@ bool AABB::has_point(const Vector3 &p_point) const {
} }
inline void AABB::expand_to(const Vector3 &p_vector) { inline void AABB::expand_to(const Vector3 &p_vector) {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
Vector3 begin = position; Vector3 begin = position;
Vector3 end = position + size; Vector3 end = position + size;
@ -360,6 +385,11 @@ inline real_t AABB::get_shortest_axis_size() const {
} }
bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const { bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
real_t divx = 1.0 / p_dir.x; real_t divx = 1.0 / p_dir.x;
real_t divy = 1.0 / p_dir.y; real_t divy = 1.0 / p_dir.y;
real_t divz = 1.0 / p_dir.z; real_t divz = 1.0 / p_dir.z;

View file

@ -35,6 +35,11 @@ bool Rect2::is_equal_approx(const Rect2 &p_rect) const {
} }
bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const { bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
real_t min = 0, max = 1; real_t min = 0, max = 1;
int axis = 0; int axis = 0;
real_t sign = 0; real_t sign = 0;
@ -95,6 +100,11 @@ bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2
} }
bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const { bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
//SAT intersection between local and transformed rect2 //SAT intersection between local and transformed rect2
Vector2 xf_points[4] = { Vector2 xf_points[4] = {

View file

@ -49,6 +49,11 @@ struct Rect2 {
_FORCE_INLINE_ Vector2 get_center() const { return position + (size * 0.5); } _FORCE_INLINE_ Vector2 get_center() const { return position + (size * 0.5); }
inline bool intersects(const Rect2 &p_rect, const bool p_include_borders = false) const { inline bool intersects(const Rect2 &p_rect, const bool p_include_borders = false) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
if (p_include_borders) { if (p_include_borders) {
if (position.x > (p_rect.position.x + p_rect.size.width)) { if (position.x > (p_rect.position.x + p_rect.size.width)) {
return false; return false;
@ -81,6 +86,11 @@ struct Rect2 {
} }
inline real_t distance_to(const Vector2 &p_point) const { inline real_t distance_to(const Vector2 &p_point) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
real_t dist = 0.0; real_t dist = 0.0;
bool inside = true; bool inside = true;
@ -117,6 +127,11 @@ struct Rect2 {
bool intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos = nullptr, Point2 *r_normal = nullptr) const; bool intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos = nullptr, Point2 *r_normal = nullptr) const;
inline bool encloses(const Rect2 &p_rect) const { inline bool encloses(const Rect2 &p_rect) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) && return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) &&
((p_rect.position.x + p_rect.size.x) <= (position.x + size.x)) && ((p_rect.position.x + p_rect.size.x) <= (position.x + size.x)) &&
((p_rect.position.y + p_rect.size.y) <= (position.y + size.y)); ((p_rect.position.y + p_rect.size.y) <= (position.y + size.y));
@ -146,7 +161,11 @@ struct Rect2 {
} }
inline Rect2 merge(const Rect2 &p_rect) const { ///< return a merged rect inline Rect2 merge(const Rect2 &p_rect) const { ///< return a merged rect
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
Rect2 new_rect; Rect2 new_rect;
new_rect.position.x = MIN(p_rect.position.x, position.x); new_rect.position.x = MIN(p_rect.position.x, position.x);
@ -160,6 +179,11 @@ struct Rect2 {
return new_rect; return new_rect;
}; };
inline bool has_point(const Point2 &p_point) const { inline bool has_point(const Point2 &p_point) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
if (p_point.x < position.x) { if (p_point.x < position.x) {
return false; return false;
} }
@ -182,6 +206,11 @@ struct Rect2 {
bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; } bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
inline Rect2 grow(real_t p_by) const { inline Rect2 grow(real_t p_by) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
Rect2 g = *this; Rect2 g = *this;
g.grow_by(p_by); g.grow_by(p_by);
return g; return g;
@ -204,6 +233,11 @@ struct Rect2 {
} }
inline Rect2 grow_individual(real_t p_left, real_t p_top, real_t p_right, real_t p_bottom) const { inline Rect2 grow_individual(real_t p_left, real_t p_top, real_t p_right, real_t p_bottom) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
Rect2 g = *this; Rect2 g = *this;
g.position.x -= p_left; g.position.x -= p_left;
g.position.y -= p_top; g.position.y -= p_top;
@ -220,7 +254,11 @@ struct Rect2 {
} }
inline void expand_to(const Vector2 &p_vector) { //in place function for speed inline void expand_to(const Vector2 &p_vector) { //in place function for speed
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
Vector2 begin = position; Vector2 begin = position;
Vector2 end = position + size; Vector2 end = position + size;
@ -273,6 +311,11 @@ struct Rect2i {
_FORCE_INLINE_ Vector2i get_center() const { return position + (size / 2); } _FORCE_INLINE_ Vector2i get_center() const { return position + (size / 2); }
inline bool intersects(const Rect2i &p_rect) const { inline bool intersects(const Rect2i &p_rect) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
if (position.x > (p_rect.position.x + p_rect.size.width)) { if (position.x > (p_rect.position.x + p_rect.size.width)) {
return false; return false;
} }
@ -290,6 +333,11 @@ struct Rect2i {
} }
inline bool encloses(const Rect2i &p_rect) const { inline bool encloses(const Rect2i &p_rect) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) && return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) &&
((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) && ((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) &&
((p_rect.position.y + p_rect.size.y) < (position.y + size.y)); ((p_rect.position.y + p_rect.size.y) < (position.y + size.y));
@ -312,14 +360,18 @@ struct Rect2i {
Point2 p_rect_end = p_rect.position + p_rect.size; Point2 p_rect_end = p_rect.position + p_rect.size;
Point2 end = position + size; Point2 end = position + size;
new_rect.size.x = (int)(MIN(p_rect_end.x, end.x) - new_rect.position.x); new_rect.size.x = MIN(p_rect_end.x, end.x) - new_rect.position.x;
new_rect.size.y = (int)(MIN(p_rect_end.y, end.y) - new_rect.position.y); new_rect.size.y = MIN(p_rect_end.y, end.y) - new_rect.position.y;
return new_rect; return new_rect;
} }
inline Rect2i merge(const Rect2i &p_rect) const { ///< return a merged rect inline Rect2i merge(const Rect2i &p_rect) const { ///< return a merged rect
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
Rect2i new_rect; Rect2i new_rect;
new_rect.position.x = MIN(p_rect.position.x, position.x); new_rect.position.x = MIN(p_rect.position.x, position.x);
@ -331,8 +383,13 @@ struct Rect2i {
new_rect.size = new_rect.size - new_rect.position; //make relative again new_rect.size = new_rect.size - new_rect.position; //make relative again
return new_rect; return new_rect;
}; }
bool has_point(const Point2 &p_point) const { bool has_point(const Point2 &p_point) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
if (p_point.x < position.x) { if (p_point.x < position.x) {
return false; return false;
} }
@ -354,6 +411,11 @@ struct Rect2i {
bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; } bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; }
Rect2i grow(int p_by) const { Rect2i grow(int p_by) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
Rect2i g = *this; Rect2i g = *this;
g.position.x -= p_by; g.position.x -= p_by;
g.position.y -= p_by; g.position.y -= p_by;
@ -372,6 +434,11 @@ struct Rect2i {
} }
inline Rect2i grow_individual(int p_left, int p_top, int p_right, int p_bottom) const { inline Rect2i grow_individual(int p_left, int p_top, int p_right, int p_bottom) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
Rect2i g = *this; Rect2i g = *this;
g.position.x -= p_left; g.position.x -= p_left;
g.position.y -= p_top; g.position.y -= p_top;
@ -388,6 +455,11 @@ struct Rect2i {
} }
inline void expand_to(const Point2i &p_vector) { inline void expand_to(const Point2i &p_vector) {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
Point2i begin = position; Point2i begin = position;
Point2i end = position + size; Point2i end = position + size;

View file

@ -6,6 +6,7 @@
<description> <description>
[AABB] consists of a position, a size, and several utility functions. It is typically used for fast overlap tests. [AABB] consists of a position, a size, and several utility functions. It is typically used for fast overlap tests.
It uses floating-point coordinates. The 2D counterpart to [AABB] is [Rect2]. It uses floating-point coordinates. The 2D counterpart to [AABB] is [Rect2].
Negative values for [member size] are not supported and will not work for most methods. Use [method abs] to get an AABB with a positive size.
[b]Note:[/b] Unlike [Rect2], [AABB] does not have a variant that uses integer coordinates. [b]Note:[/b] Unlike [Rect2], [AABB] does not have a variant that uses integer coordinates.
</description> </description>
<tutorials> <tutorials>

View file

@ -7,6 +7,7 @@
[Rect2] consists of a position, a size, and several utility functions. It is typically used for fast overlap tests. [Rect2] consists of a position, a size, and several utility functions. It is typically used for fast overlap tests.
It uses floating-point coordinates. It uses floating-point coordinates.
The 3D counterpart to [Rect2] is [AABB]. The 3D counterpart to [Rect2] is [AABB].
Negative values for [member size] are not supported and will not work for most methods. Use [method abs] to get a Rect2 with a positive size.
</description> </description>
<tutorials> <tutorials>
<link title="Math tutorial index">$DOCS_URL/tutorials/math/index.html</link> <link title="Math tutorial index">$DOCS_URL/tutorials/math/index.html</link>