Pārlūkot izejas kodu

Merge pull request #37626 from aaronfranke/rect2-warnings

Print warnings when using a Rect2 or AABB with a negative size
Max Hilbrunner 3 gadi atpakaļ
vecāks
revīzija
837e6bdf18

+ 20 - 0
core/math/aabb.cpp

@@ -46,6 +46,11 @@ bool AABB::operator!=(const AABB &p_rval) const {
 }
 
 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 end_1, end_2;
 	Vector3 min, max;
@@ -72,6 +77,11 @@ bool AABB::is_equal_approx(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_max = position + size;
 	Vector3 dst_min = p_aabb.position;
@@ -104,6 +114,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 {
+#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 end = position + size;
 	real_t near = -1e20;
@@ -147,6 +162,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 {
+#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;
 	int axis = 0;
 	real_t sign = 0;

+ 30 - 0
core/math/aabb.h

@@ -132,6 +132,11 @@ public:
 };
 
 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)) {
 		return false;
 	}
@@ -155,6 +160,11 @@ inline bool AABB::intersects(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)) {
 		return false;
 	}
@@ -178,6 +188,11 @@ inline bool AABB::intersects_inclusive(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_max = position + size;
 	Vector3 dst_min = p_aabb.position;
@@ -288,6 +303,11 @@ bool AABB::inside_convex_shape(const Plane *p_planes, int p_plane_count) 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) {
 		return false;
 	}
@@ -311,6 +331,11 @@ bool AABB::has_point(const Vector3 &p_point) const {
 }
 
 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 end = position + size;
 
@@ -377,6 +402,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 {
+#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 divy = 1.0 / p_dir.y;
 	real_t divz = 1.0 / p_dir.z;

+ 10 - 0
core/math/rect2.cpp

@@ -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 {
+#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;
 	int axis = 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 {
+#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
 
 	Vector2 xf_points[4] = {

+ 77 - 5
core/math/rect2.h

@@ -49,6 +49,11 @@ struct Rect2 {
 	_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 {
+#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 (position.x > (p_rect.position.x + p_rect.size.width)) {
 				return false;
@@ -81,6 +86,11 @@ struct Rect2 {
 	}
 
 	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;
 		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;
 
 	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) &&
 				((p_rect.position.x + p_rect.size.x) <= (position.x + size.x)) &&
 				((p_rect.position.y + p_rect.size.y) <= (position.y + size.y));
@@ -147,7 +162,11 @@ struct Rect2 {
 	}
 
 	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;
 
 		new_rect.position.x = MIN(p_rect.position.x, position.x);
@@ -161,6 +180,11 @@ struct Rect2 {
 		return new_rect;
 	}
 	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) {
 			return false;
 		}
@@ -183,6 +207,11 @@ struct Rect2 {
 	bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
 
 	inline Rect2 grow(real_t p_amount) 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;
 		g.grow_by(p_amount);
 		return g;
@@ -209,6 +238,11 @@ struct Rect2 {
 	}
 
 	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;
 		g.position.x -= p_left;
 		g.position.y -= p_top;
@@ -225,7 +259,11 @@ struct Rect2 {
 	}
 
 	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 end = position + size;
 
@@ -349,6 +387,11 @@ struct Rect2i {
 	_FORCE_INLINE_ Vector2i get_center() const { return position + (size / 2); }
 
 	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)) {
 			return false;
 		}
@@ -366,6 +409,11 @@ struct Rect2i {
 	}
 
 	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) &&
 				((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) &&
 				((p_rect.position.y + p_rect.size.y) < (position.y + size.y));
@@ -389,14 +437,18 @@ struct Rect2i {
 		Point2i p_rect_end = p_rect.position + p_rect.size;
 		Point2i end = position + size;
 
-		new_rect.size.x = (int)(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.x = MIN(p_rect_end.x, end.x) - new_rect.position.x;
+		new_rect.size.y = MIN(p_rect_end.y, end.y) - new_rect.position.y;
 
 		return new_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;
 
 		new_rect.position.x = MIN(p_rect.position.x, position.x);
@@ -410,6 +462,11 @@ struct Rect2i {
 		return new_rect;
 	}
 	bool has_point(const Point2i &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) {
 			return false;
 		}
@@ -431,6 +488,11 @@ struct Rect2i {
 	bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; }
 
 	Rect2i grow(int p_amount) 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;
 		g.position.x -= p_amount;
 		g.position.y -= p_amount;
@@ -453,6 +515,11 @@ struct Rect2i {
 	}
 
 	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;
 		g.position.x -= p_left;
 		g.position.y -= p_top;
@@ -469,6 +536,11 @@ struct Rect2i {
 	}
 
 	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 end = position + size;
 

+ 1 - 0
doc/classes/AABB.xml

@@ -6,6 +6,7 @@
 	<description>
 		[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].
+		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.
 	</description>
 	<tutorials>

+ 1 - 0
doc/classes/Rect2.xml

@@ -7,6 +7,7 @@
 		[Rect2] consists of a position, a size, and several utility functions. It is typically used for fast overlap tests.
 		It uses floating-point coordinates. If you need integer coordinates, use [Rect2i] instead.
 		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>
 	<tutorials>
 		<link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link>

+ 1 - 0
doc/classes/Rect2i.xml

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