Ver Fonte

Core: Add `constexpr` constructors/operators to math structs

• Begin integrating `constexpr` on math tests; use `static_assert` where appropriate
Thaddeus Crews há 9 meses atrás
pai
commit
ea62170dac
56 ficheiros alterados com 1119 adições e 1169 exclusões
  1. 0 8
      core/math/aabb.cpp
  2. 8 4
      core/math/aabb.h
  3. 35 34
      core/math/audio_frame.h
  4. 0 16
      core/math/basis.cpp
  5. 49 27
      core/math/basis.h
  6. 0 2
      core/math/bvh.h
  7. 0 98
      core/math/color.cpp
  8. 128 37
      core/math/color.h
  9. 3 6
      core/math/face3.h
  10. 9 9
      core/math/plane.h
  11. 0 37
      core/math/projection.cpp
  12. 37 10
      core/math/projection.h
  13. 0 16
      core/math/quaternion.cpp
  14. 52 41
      core/math/quaternion.h
  15. 5 5
      core/math/rect2.h
  16. 5 5
      core/math/rect2i.h
  17. 0 44
      core/math/transform_2d.cpp
  18. 66 26
      core/math/transform_2d.h
  19. 0 47
      core/math/transform_3d.cpp
  20. 46 10
      core/math/transform_3d.h
  21. 51 49
      core/math/vector2.h
  22. 0 69
      core/math/vector2i.cpp
  23. 108 37
      core/math/vector2i.h
  24. 51 51
      core/math/vector3.h
  25. 59 59
      core/math/vector3i.h
  26. 51 52
      core/math/vector4.h
  27. 59 60
      core/math/vector4i.h
  28. 0 1
      editor/import/3d/collada.cpp
  29. 0 1
      editor/plugins/canvas_item_editor_plugin.cpp
  30. 0 1
      editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp
  31. 1 1
      editor/plugins/polygon_3d_editor_plugin.cpp
  32. 1 1
      modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.cpp
  33. 0 1
      modules/mobile_vr/mobile_vr_interface.cpp
  34. 0 2
      modules/openxr/openxr_api.cpp
  35. 0 1
      platform/android/java_godot_lib_jni.cpp
  36. 0 1
      scene/gui/label.cpp
  37. 0 1
      scene/resources/bit_map.cpp
  38. 15 15
      tests/core/math/test_aabb.h
  39. 1 1
      tests/core/math/test_astar.h
  40. 1 1
      tests/core/math/test_basis.h
  41. 12 12
      tests/core/math/test_color.h
  42. 8 8
      tests/core/math/test_geometry_2d.h
  43. 4 4
      tests/core/math/test_geometry_3d.h
  44. 22 22
      tests/core/math/test_plane.h
  45. 0 6
      tests/core/math/test_projection.h
  46. 27 27
      tests/core/math/test_quaternion.h
  47. 7 7
      tests/core/math/test_rect2.h
  48. 7 7
      tests/core/math/test_rect2i.h
  49. 15 15
      tests/core/math/test_transform_2d.h
  50. 6 6
      tests/core/math/test_transform_3d.h
  51. 40 40
      tests/core/math/test_vector2.h
  52. 17 17
      tests/core/math/test_vector2i.h
  53. 41 41
      tests/core/math/test_vector3.h
  54. 19 17
      tests/core/math/test_vector3i.h
  55. 35 35
      tests/core/math/test_vector4.h
  56. 18 18
      tests/core/math/test_vector4i.h

+ 0 - 8
core/math/aabb.cpp

@@ -37,14 +37,6 @@ real_t AABB::get_volume() const {
 	return size.x * size.y * size.z;
 }
 
-bool AABB::operator==(const AABB &p_rval) const {
-	return ((position == p_rval.position) && (size == p_rval.size));
-}
-
-bool AABB::operator!=(const AABB &p_rval) const {
-	return ((position != p_rval.position) || (size != p_rval.size));
-}
-
 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)) {

+ 8 - 4
core/math/aabb.h

@@ -58,8 +58,12 @@ struct [[nodiscard]] AABB {
 	const Vector3 &get_size() const { return size; }
 	void set_size(const Vector3 &p_size) { size = p_size; }
 
-	bool operator==(const AABB &p_rval) const;
-	bool operator!=(const AABB &p_rval) const;
+	constexpr bool operator==(const AABB &p_rval) const {
+		return position == p_rval.position && size == p_rval.size;
+	}
+	constexpr bool operator!=(const AABB &p_rval) const {
+		return position != p_rval.position || size != p_rval.size;
+	}
 
 	bool is_equal_approx(const AABB &p_aabb) const;
 	bool is_same(const AABB &p_aabb) const;
@@ -129,8 +133,8 @@ struct [[nodiscard]] AABB {
 
 	operator String() const;
 
-	_FORCE_INLINE_ AABB() {}
-	inline AABB(const Vector3 &p_pos, const Vector3 &p_size) :
+	AABB() = default;
+	constexpr AABB(const Vector3 &p_pos, const Vector3 &p_size) :
 			position(p_pos),
 			size(p_size) {
 	}

+ 35 - 34
core/math/audio_frame.h

@@ -52,6 +52,7 @@ static const float AUDIO_MIN_PEAK_DB = -200.0f; // linear_to_db(AUDIO_PEAK_OFFSE
 struct AudioFrame {
 	// Left and right samples.
 	union {
+		// NOLINTBEGIN(modernize-use-default-member-init)
 		struct {
 			float left;
 			float right;
@@ -63,6 +64,7 @@ struct AudioFrame {
 		};
 #endif
 		float levels[2] = { 0.0 };
+		// NOLINTEND(modernize-use-default-member-init)
 	};
 
 	_ALWAYS_INLINE_ const float &operator[](int p_idx) const {
@@ -74,46 +76,46 @@ struct AudioFrame {
 		return levels[p_idx];
 	}
 
-	_ALWAYS_INLINE_ AudioFrame operator+(const AudioFrame &p_frame) const { return AudioFrame(left + p_frame.left, right + p_frame.right); }
-	_ALWAYS_INLINE_ AudioFrame operator-(const AudioFrame &p_frame) const { return AudioFrame(left - p_frame.left, right - p_frame.right); }
-	_ALWAYS_INLINE_ AudioFrame operator*(const AudioFrame &p_frame) const { return AudioFrame(left * p_frame.left, right * p_frame.right); }
-	_ALWAYS_INLINE_ AudioFrame operator/(const AudioFrame &p_frame) const { return AudioFrame(left / p_frame.left, right / p_frame.right); }
+	constexpr AudioFrame operator+(const AudioFrame &p_frame) const { return AudioFrame(left + p_frame.left, right + p_frame.right); }
+	constexpr AudioFrame operator-(const AudioFrame &p_frame) const { return AudioFrame(left - p_frame.left, right - p_frame.right); }
+	constexpr AudioFrame operator*(const AudioFrame &p_frame) const { return AudioFrame(left * p_frame.left, right * p_frame.right); }
+	constexpr AudioFrame operator/(const AudioFrame &p_frame) const { return AudioFrame(left / p_frame.left, right / p_frame.right); }
 
-	_ALWAYS_INLINE_ AudioFrame operator+(float p_sample) const { return AudioFrame(left + p_sample, right + p_sample); }
-	_ALWAYS_INLINE_ AudioFrame operator-(float p_sample) const { return AudioFrame(left - p_sample, right - p_sample); }
-	_ALWAYS_INLINE_ AudioFrame operator*(float p_sample) const { return AudioFrame(left * p_sample, right * p_sample); }
-	_ALWAYS_INLINE_ AudioFrame operator/(float p_sample) const { return AudioFrame(left / p_sample, right / p_sample); }
+	constexpr AudioFrame operator+(float p_sample) const { return AudioFrame(left + p_sample, right + p_sample); }
+	constexpr AudioFrame operator-(float p_sample) const { return AudioFrame(left - p_sample, right - p_sample); }
+	constexpr AudioFrame operator*(float p_sample) const { return AudioFrame(left * p_sample, right * p_sample); }
+	constexpr AudioFrame operator/(float p_sample) const { return AudioFrame(left / p_sample, right / p_sample); }
 
-	_ALWAYS_INLINE_ void operator+=(const AudioFrame &p_frame) {
+	constexpr void operator+=(const AudioFrame &p_frame) {
 		left += p_frame.left;
 		right += p_frame.right;
 	}
-	_ALWAYS_INLINE_ void operator-=(const AudioFrame &p_frame) {
+	constexpr void operator-=(const AudioFrame &p_frame) {
 		left -= p_frame.left;
 		right -= p_frame.right;
 	}
-	_ALWAYS_INLINE_ void operator*=(const AudioFrame &p_frame) {
+	constexpr void operator*=(const AudioFrame &p_frame) {
 		left *= p_frame.left;
 		right *= p_frame.right;
 	}
-	_ALWAYS_INLINE_ void operator/=(const AudioFrame &p_frame) {
+	constexpr void operator/=(const AudioFrame &p_frame) {
 		left /= p_frame.left;
 		right /= p_frame.right;
 	}
 
-	_ALWAYS_INLINE_ void operator+=(float p_sample) {
+	constexpr void operator+=(float p_sample) {
 		left += p_sample;
 		right += p_sample;
 	}
-	_ALWAYS_INLINE_ void operator-=(float p_sample) {
+	constexpr void operator-=(float p_sample) {
 		left -= p_sample;
 		right -= p_sample;
 	}
-	_ALWAYS_INLINE_ void operator*=(float p_sample) {
+	constexpr void operator*=(float p_sample) {
 		left *= p_sample;
 		right *= p_sample;
 	}
-	_ALWAYS_INLINE_ void operator/=(float p_sample) {
+	constexpr void operator/=(float p_sample) {
 		left /= p_sample;
 		right /= p_sample;
 	}
@@ -132,40 +134,39 @@ struct AudioFrame {
 		return res;
 	}
 
-	_ALWAYS_INLINE_ AudioFrame(float p_left, float p_right) {
-		left = p_left;
-		right = p_right;
-	}
-	_ALWAYS_INLINE_ AudioFrame(const AudioFrame &p_frame) {
-		left = p_frame.left;
-		right = p_frame.right;
-	}
+	// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
+	constexpr AudioFrame(float p_left, float p_right) :
+			left(p_left), right(p_right) {}
+	constexpr AudioFrame(const AudioFrame &p_frame) :
+			left(p_frame.left), right(p_frame.right) {}
+	// NOLINTEND(cppcoreguidelines-pro-type-member-init)
 
-	_ALWAYS_INLINE_ void operator=(const AudioFrame &p_frame) {
+	constexpr void operator=(const AudioFrame &p_frame) {
 		left = p_frame.left;
 		right = p_frame.right;
 	}
 
-	_ALWAYS_INLINE_ operator Vector2() const {
+	constexpr operator Vector2() const {
 		return Vector2(left, right);
 	}
 
-	_ALWAYS_INLINE_ AudioFrame(const Vector2 &p_v2) {
-		left = p_v2.x;
-		right = p_v2.y;
-	}
-	_ALWAYS_INLINE_ AudioFrame() {}
+	// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
+	constexpr AudioFrame(const Vector2 &p_v2) :
+			left(p_v2.x), right(p_v2.y) {}
+	constexpr AudioFrame() :
+			left(0), right(0) {}
+	// NOLINTEND(cppcoreguidelines-pro-type-member-init)
 };
 
-_ALWAYS_INLINE_ AudioFrame operator*(float p_scalar, const AudioFrame &p_frame) {
+constexpr AudioFrame operator*(float p_scalar, const AudioFrame &p_frame) {
 	return AudioFrame(p_frame.left * p_scalar, p_frame.right * p_scalar);
 }
 
-_ALWAYS_INLINE_ AudioFrame operator*(int32_t p_scalar, const AudioFrame &p_frame) {
+constexpr AudioFrame operator*(int32_t p_scalar, const AudioFrame &p_frame) {
 	return AudioFrame(p_frame.left * p_scalar, p_frame.right * p_scalar);
 }
 
-_ALWAYS_INLINE_ AudioFrame operator*(int64_t p_scalar, const AudioFrame &p_frame) {
+constexpr AudioFrame operator*(int64_t p_scalar, const AudioFrame &p_frame) {
 	return AudioFrame(p_frame.left * p_scalar, p_frame.right * p_scalar);
 }
 

+ 0 - 16
core/math/basis.cpp

@@ -707,22 +707,6 @@ bool Basis::is_finite() const {
 	return rows[0].is_finite() && rows[1].is_finite() && rows[2].is_finite();
 }
 
-bool Basis::operator==(const Basis &p_matrix) const {
-	for (int i = 0; i < 3; i++) {
-		for (int j = 0; j < 3; j++) {
-			if (rows[i][j] != p_matrix.rows[i][j]) {
-				return false;
-			}
-		}
-	}
-
-	return true;
-}
-
-bool Basis::operator!=(const Basis &p_matrix) const {
-	return (!(*this == p_matrix));
-}
-
 Basis::operator String() const {
 	return "[X: " + get_column(0).operator String() +
 			", Y: " + get_column(1).operator String() +

+ 49 - 27
core/math/basis.h

@@ -40,10 +40,10 @@ struct [[nodiscard]] Basis {
 		Vector3(0, 0, 1)
 	};
 
-	_FORCE_INLINE_ const Vector3 &operator[](int p_row) const {
+	constexpr const Vector3 &operator[](int p_row) const {
 		return rows[p_row];
 	}
-	_FORCE_INLINE_ Vector3 &operator[](int p_row) {
+	constexpr Vector3 &operator[](int p_row) {
 		return rows[p_row];
 	}
 
@@ -123,21 +123,21 @@ struct [[nodiscard]] Basis {
 	bool is_same(const Basis &p_basis) const;
 	bool is_finite() const;
 
-	bool operator==(const Basis &p_matrix) const;
-	bool operator!=(const Basis &p_matrix) const;
+	constexpr bool operator==(const Basis &p_matrix) const;
+	constexpr bool operator!=(const Basis &p_matrix) const;
 
 	_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vector) const;
 	_FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_vector) const;
 	_FORCE_INLINE_ void operator*=(const Basis &p_matrix);
 	_FORCE_INLINE_ Basis operator*(const Basis &p_matrix) const;
-	_FORCE_INLINE_ void operator+=(const Basis &p_matrix);
-	_FORCE_INLINE_ Basis operator+(const Basis &p_matrix) const;
-	_FORCE_INLINE_ void operator-=(const Basis &p_matrix);
-	_FORCE_INLINE_ Basis operator-(const Basis &p_matrix) const;
-	_FORCE_INLINE_ void operator*=(real_t p_val);
-	_FORCE_INLINE_ Basis operator*(real_t p_val) const;
-	_FORCE_INLINE_ void operator/=(real_t p_val);
-	_FORCE_INLINE_ Basis operator/(real_t p_val) const;
+	constexpr void operator+=(const Basis &p_matrix);
+	constexpr Basis operator+(const Basis &p_matrix) const;
+	constexpr void operator-=(const Basis &p_matrix);
+	constexpr Basis operator-(const Basis &p_matrix) const;
+	constexpr void operator*=(real_t p_val);
+	constexpr Basis operator*(real_t p_val) const;
+	constexpr void operator/=(real_t p_val);
+	constexpr Basis operator/(real_t p_val) const;
 
 	bool is_orthogonal() const;
 	bool is_orthonormal() const;
@@ -204,9 +204,12 @@ struct [[nodiscard]] Basis {
 				rows[0].z * p_m[0].y + rows[1].z * p_m[1].y + rows[2].z * p_m[2].y,
 				rows[0].z * p_m[0].z + rows[1].z * p_m[1].z + rows[2].z * p_m[2].z);
 	}
-	Basis(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz) {
-		set(p_xx, p_xy, p_xz, p_yx, p_yy, p_yz, p_zx, p_zy, p_zz);
-	}
+	constexpr Basis(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz) :
+			rows{
+				{ p_xx, p_xy, p_xz },
+				{ p_yx, p_yy, p_yz },
+				{ p_zx, p_zy, p_zz },
+			} {}
 
 	void orthonormalize();
 	Basis orthonormalized() const;
@@ -230,17 +233,36 @@ struct [[nodiscard]] Basis {
 	Basis(const Vector3 &p_axis, real_t p_angle, const Vector3 &p_scale) { set_axis_angle_scale(p_axis, p_angle, p_scale); }
 	static Basis from_scale(const Vector3 &p_scale);
 
-	_FORCE_INLINE_ Basis(const Vector3 &p_x_axis, const Vector3 &p_y_axis, const Vector3 &p_z_axis) {
-		set_columns(p_x_axis, p_y_axis, p_z_axis);
-	}
+	constexpr Basis(const Vector3 &p_x_axis, const Vector3 &p_y_axis, const Vector3 &p_z_axis) :
+			rows{
+				{ p_x_axis.x, p_y_axis.x, p_z_axis.x },
+				{ p_x_axis.y, p_y_axis.y, p_z_axis.y },
+				{ p_x_axis.z, p_y_axis.z, p_z_axis.z },
+			} {}
 
-	_FORCE_INLINE_ Basis() {}
+	Basis() = default;
 
 private:
 	// Helper method.
 	void _set_diagonal(const Vector3 &p_diag);
 };
 
+constexpr bool Basis::operator==(const Basis &p_matrix) const {
+	for (int i = 0; i < 3; i++) {
+		for (int j = 0; j < 3; j++) {
+			if (rows[i][j] != p_matrix.rows[i][j]) {
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+constexpr bool Basis::operator!=(const Basis &p_matrix) const {
+	return (!(*this == p_matrix));
+}
+
 _FORCE_INLINE_ void Basis::operator*=(const Basis &p_matrix) {
 	set(
 			p_matrix.tdotx(rows[0]), p_matrix.tdoty(rows[0]), p_matrix.tdotz(rows[0]),
@@ -255,49 +277,49 @@ _FORCE_INLINE_ Basis Basis::operator*(const Basis &p_matrix) const {
 			p_matrix.tdotx(rows[2]), p_matrix.tdoty(rows[2]), p_matrix.tdotz(rows[2]));
 }
 
-_FORCE_INLINE_ void Basis::operator+=(const Basis &p_matrix) {
+constexpr void Basis::operator+=(const Basis &p_matrix) {
 	rows[0] += p_matrix.rows[0];
 	rows[1] += p_matrix.rows[1];
 	rows[2] += p_matrix.rows[2];
 }
 
-_FORCE_INLINE_ Basis Basis::operator+(const Basis &p_matrix) const {
+constexpr Basis Basis::operator+(const Basis &p_matrix) const {
 	Basis ret(*this);
 	ret += p_matrix;
 	return ret;
 }
 
-_FORCE_INLINE_ void Basis::operator-=(const Basis &p_matrix) {
+constexpr void Basis::operator-=(const Basis &p_matrix) {
 	rows[0] -= p_matrix.rows[0];
 	rows[1] -= p_matrix.rows[1];
 	rows[2] -= p_matrix.rows[2];
 }
 
-_FORCE_INLINE_ Basis Basis::operator-(const Basis &p_matrix) const {
+constexpr Basis Basis::operator-(const Basis &p_matrix) const {
 	Basis ret(*this);
 	ret -= p_matrix;
 	return ret;
 }
 
-_FORCE_INLINE_ void Basis::operator*=(real_t p_val) {
+constexpr void Basis::operator*=(real_t p_val) {
 	rows[0] *= p_val;
 	rows[1] *= p_val;
 	rows[2] *= p_val;
 }
 
-_FORCE_INLINE_ Basis Basis::operator*(real_t p_val) const {
+constexpr Basis Basis::operator*(real_t p_val) const {
 	Basis ret(*this);
 	ret *= p_val;
 	return ret;
 }
 
-_FORCE_INLINE_ void Basis::operator/=(real_t p_val) {
+constexpr void Basis::operator/=(real_t p_val) {
 	rows[0] /= p_val;
 	rows[1] /= p_val;
 	rows[2] /= p_val;
 }
 
-_FORCE_INLINE_ Basis Basis::operator/(real_t p_val) const {
+constexpr Basis Basis::operator/(real_t p_val) const {
 	Basis ret(*this);
 	ret /= p_val;
 	return ret;

+ 0 - 2
core/math/bvh.h

@@ -434,8 +434,6 @@ private:
 			return;
 		}
 
-		BOUNDS bb;
-
 		typename BVHTREE_CLASS::CullParams params;
 
 		params.result_count_overall = 0;

+ 0 - 98
core/math/color.cpp

@@ -490,104 +490,6 @@ Color::operator String() const {
 	return "(" + String::num(r, 4) + ", " + String::num(g, 4) + ", " + String::num(b, 4) + ", " + String::num(a, 4) + ")";
 }
 
-Color Color::operator+(const Color &p_color) const {
-	return Color(
-			r + p_color.r,
-			g + p_color.g,
-			b + p_color.b,
-			a + p_color.a);
-}
-
-void Color::operator+=(const Color &p_color) {
-	r = r + p_color.r;
-	g = g + p_color.g;
-	b = b + p_color.b;
-	a = a + p_color.a;
-}
-
-Color Color::operator-(const Color &p_color) const {
-	return Color(
-			r - p_color.r,
-			g - p_color.g,
-			b - p_color.b,
-			a - p_color.a);
-}
-
-void Color::operator-=(const Color &p_color) {
-	r = r - p_color.r;
-	g = g - p_color.g;
-	b = b - p_color.b;
-	a = a - p_color.a;
-}
-
-Color Color::operator*(const Color &p_color) const {
-	return Color(
-			r * p_color.r,
-			g * p_color.g,
-			b * p_color.b,
-			a * p_color.a);
-}
-
-Color Color::operator*(float p_scalar) const {
-	return Color(
-			r * p_scalar,
-			g * p_scalar,
-			b * p_scalar,
-			a * p_scalar);
-}
-
-void Color::operator*=(const Color &p_color) {
-	r = r * p_color.r;
-	g = g * p_color.g;
-	b = b * p_color.b;
-	a = a * p_color.a;
-}
-
-void Color::operator*=(float p_scalar) {
-	r = r * p_scalar;
-	g = g * p_scalar;
-	b = b * p_scalar;
-	a = a * p_scalar;
-}
-
-Color Color::operator/(const Color &p_color) const {
-	return Color(
-			r / p_color.r,
-			g / p_color.g,
-			b / p_color.b,
-			a / p_color.a);
-}
-
-Color Color::operator/(float p_scalar) const {
-	return Color(
-			r / p_scalar,
-			g / p_scalar,
-			b / p_scalar,
-			a / p_scalar);
-}
-
-void Color::operator/=(const Color &p_color) {
-	r = r / p_color.r;
-	g = g / p_color.g;
-	b = b / p_color.b;
-	a = a / p_color.a;
-}
-
-void Color::operator/=(float p_scalar) {
-	r = r / p_scalar;
-	g = g / p_scalar;
-	b = b / p_scalar;
-	a = a / p_scalar;
-}
-
-Color Color::operator-() const {
-	return Color(
-			1.0f - r,
-			1.0f - g,
-			1.0f - b,
-			1.0f - a);
-}
-
 Color Color::from_ok_hsl(float p_h, float p_s, float p_l, float p_alpha) {
 	Color c;
 	c.set_ok_hsl(p_h, p_s, p_l, p_alpha);

+ 128 - 37
core/math/color.h

@@ -36,6 +36,7 @@ class String;
 
 struct [[nodiscard]] Color {
 	union {
+		// NOLINTBEGIN(modernize-use-default-member-init)
 		struct {
 			float r;
 			float g;
@@ -43,6 +44,7 @@ struct [[nodiscard]] Color {
 			float a;
 		};
 		float components[4] = { 0, 0, 0, 1.0 };
+		// NOLINTEND(modernize-use-default-member-init)
 	};
 
 	uint32_t to_rgba32() const;
@@ -68,29 +70,29 @@ struct [[nodiscard]] Color {
 		return components[p_idx];
 	}
 
-	bool operator==(const Color &p_color) const {
+	constexpr bool operator==(const Color &p_color) const {
 		return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a);
 	}
-	bool operator!=(const Color &p_color) const {
+	constexpr bool operator!=(const Color &p_color) const {
 		return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a);
 	}
 
-	Color operator+(const Color &p_color) const;
-	void operator+=(const Color &p_color);
+	constexpr Color operator+(const Color &p_color) const;
+	constexpr void operator+=(const Color &p_color);
 
-	Color operator-() const;
-	Color operator-(const Color &p_color) const;
-	void operator-=(const Color &p_color);
+	constexpr Color operator-() const;
+	constexpr Color operator-(const Color &p_color) const;
+	constexpr void operator-=(const Color &p_color);
 
-	Color operator*(const Color &p_color) const;
-	Color operator*(float p_scalar) const;
-	void operator*=(const Color &p_color);
-	void operator*=(float p_scalar);
+	constexpr Color operator*(const Color &p_color) const;
+	constexpr Color operator*(float p_scalar) const;
+	constexpr void operator*=(const Color &p_color);
+	constexpr void operator*=(float p_scalar);
 
-	Color operator/(const Color &p_color) const;
-	Color operator/(float p_scalar) const;
-	void operator/=(const Color &p_color);
-	void operator/=(float p_scalar);
+	constexpr Color operator/(const Color &p_color) const;
+	constexpr Color operator/(float p_scalar) const;
+	constexpr void operator/=(const Color &p_color);
+	constexpr void operator/=(float p_scalar);
 
 	bool is_equal_approx(const Color &p_color) const;
 	bool is_same(const Color &p_color) const;
@@ -215,7 +217,7 @@ struct [[nodiscard]] Color {
 	static Color from_rgbe9995(uint32_t p_rgbe);
 	static Color from_rgba8(int64_t p_r8, int64_t p_g8, int64_t p_b8, int64_t p_a8 = 255);
 
-	_FORCE_INLINE_ bool operator<(const Color &p_color) const; // Used in set keys.
+	constexpr bool operator<(const Color &p_color) const; // Used in set keys.
 	operator String() const;
 
 	// For the binder.
@@ -235,39 +237,29 @@ struct [[nodiscard]] Color {
 	_FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l(), a); }
 	_FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l, a); }
 
-	_FORCE_INLINE_ Color() {}
+	constexpr Color() :
+			r(0), g(0), b(0), a(1) {}
 
 	/**
 	 * RGBA construct parameters.
 	 * Alpha is not optional as otherwise we can't bind the RGB version for scripting.
 	 */
-	_FORCE_INLINE_ Color(float p_r, float p_g, float p_b, float p_a) {
-		r = p_r;
-		g = p_g;
-		b = p_b;
-		a = p_a;
-	}
+	constexpr Color(float p_r, float p_g, float p_b, float p_a) :
+			r(p_r), g(p_g), b(p_b), a(p_a) {}
 
 	/**
 	 * RGB construct parameters.
 	 */
-	_FORCE_INLINE_ Color(float p_r, float p_g, float p_b) {
-		r = p_r;
-		g = p_g;
-		b = p_b;
-		a = 1.0f;
-	}
+	constexpr Color(float p_r, float p_g, float p_b) :
+			r(p_r), g(p_g), b(p_b), a(1) {}
 
 	/**
 	 * Construct a Color from another Color, but with the specified alpha value.
 	 */
-	_FORCE_INLINE_ Color(const Color &p_c, float p_a) {
-		r = p_c.r;
-		g = p_c.g;
-		b = p_c.b;
-		a = p_a;
-	}
+	constexpr Color(const Color &p_c, float p_a) :
+			r(p_c.r), g(p_c.g), b(p_c.b), a(p_a) {}
 
+	// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
 	Color(const String &p_code) {
 		if (html_is_valid(p_code)) {
 			*this = html(p_code);
@@ -280,9 +272,108 @@ struct [[nodiscard]] Color {
 		*this = Color(p_code);
 		a = p_a;
 	}
+	// NOLINTEND(cppcoreguidelines-pro-type-member-init)
 };
 
-bool Color::operator<(const Color &p_color) const {
+constexpr Color Color::operator+(const Color &p_color) const {
+	return Color(
+			r + p_color.r,
+			g + p_color.g,
+			b + p_color.b,
+			a + p_color.a);
+}
+
+constexpr void Color::operator+=(const Color &p_color) {
+	r = r + p_color.r;
+	g = g + p_color.g;
+	b = b + p_color.b;
+	a = a + p_color.a;
+}
+
+constexpr Color Color::operator-(const Color &p_color) const {
+	return Color(
+			r - p_color.r,
+			g - p_color.g,
+			b - p_color.b,
+			a - p_color.a);
+}
+
+constexpr void Color::operator-=(const Color &p_color) {
+	r = r - p_color.r;
+	g = g - p_color.g;
+	b = b - p_color.b;
+	a = a - p_color.a;
+}
+
+constexpr Color Color::operator*(const Color &p_color) const {
+	return Color(
+			r * p_color.r,
+			g * p_color.g,
+			b * p_color.b,
+			a * p_color.a);
+}
+
+constexpr Color Color::operator*(float p_scalar) const {
+	return Color(
+			r * p_scalar,
+			g * p_scalar,
+			b * p_scalar,
+			a * p_scalar);
+}
+
+constexpr void Color::operator*=(const Color &p_color) {
+	r = r * p_color.r;
+	g = g * p_color.g;
+	b = b * p_color.b;
+	a = a * p_color.a;
+}
+
+constexpr void Color::operator*=(float p_scalar) {
+	r = r * p_scalar;
+	g = g * p_scalar;
+	b = b * p_scalar;
+	a = a * p_scalar;
+}
+
+constexpr Color Color::operator/(const Color &p_color) const {
+	return Color(
+			r / p_color.r,
+			g / p_color.g,
+			b / p_color.b,
+			a / p_color.a);
+}
+
+constexpr Color Color::operator/(float p_scalar) const {
+	return Color(
+			r / p_scalar,
+			g / p_scalar,
+			b / p_scalar,
+			a / p_scalar);
+}
+
+constexpr void Color::operator/=(const Color &p_color) {
+	r = r / p_color.r;
+	g = g / p_color.g;
+	b = b / p_color.b;
+	a = a / p_color.a;
+}
+
+constexpr void Color::operator/=(float p_scalar) {
+	r = r / p_scalar;
+	g = g / p_scalar;
+	b = b / p_scalar;
+	a = a / p_scalar;
+}
+
+constexpr Color Color::operator-() const {
+	return Color(
+			1.0f - r,
+			1.0f - g,
+			1.0f - b,
+			1.0f - a);
+}
+
+constexpr bool Color::operator<(const Color &p_color) const {
 	if (r == p_color.r) {
 		if (g == p_color.g) {
 			if (b == p_color.b) {
@@ -298,6 +389,6 @@ bool Color::operator<(const Color &p_color) const {
 	}
 }
 
-_FORCE_INLINE_ Color operator*(float p_scalar, const Color &p_color) {
+constexpr Color operator*(float p_scalar, const Color &p_color) {
 	return p_color * p_scalar;
 }

+ 3 - 6
core/math/face3.h

@@ -78,12 +78,9 @@ struct [[nodiscard]] Face3 {
 	_FORCE_INLINE_ bool intersects_aabb2(const AABB &p_aabb) const;
 	operator String() const;
 
-	inline Face3() {}
-	inline Face3(const Vector3 &p_v1, const Vector3 &p_v2, const Vector3 &p_v3) {
-		vertex[0] = p_v1;
-		vertex[1] = p_v2;
-		vertex[2] = p_v3;
-	}
+	Face3() = default;
+	constexpr Face3(const Vector3 &p_v1, const Vector3 &p_v2, const Vector3 &p_v3) :
+			vertex{ p_v1, p_v2, p_v3 } {}
 };
 
 bool Face3::intersects_aabb2(const AABB &p_aabb) const {

+ 9 - 9
core/math/plane.h

@@ -70,22 +70,22 @@ struct [[nodiscard]] Plane {
 
 	/* misc */
 
-	Plane operator-() const { return Plane(-normal, -d); }
+	constexpr Plane operator-() const { return Plane(-normal, -d); }
 	bool is_equal_approx(const Plane &p_plane) const;
 	bool is_same(const Plane &p_plane) const;
 	bool is_equal_approx_any_side(const Plane &p_plane) const;
 	bool is_finite() const;
 
-	_FORCE_INLINE_ bool operator==(const Plane &p_plane) const;
-	_FORCE_INLINE_ bool operator!=(const Plane &p_plane) const;
+	constexpr bool operator==(const Plane &p_plane) const;
+	constexpr bool operator!=(const Plane &p_plane) const;
 	operator String() const;
 
-	_FORCE_INLINE_ Plane() {}
-	_FORCE_INLINE_ Plane(real_t p_a, real_t p_b, real_t p_c, real_t p_d) :
+	Plane() = default;
+	constexpr Plane(real_t p_a, real_t p_b, real_t p_c, real_t p_d) :
 			normal(p_a, p_b, p_c),
 			d(p_d) {}
 
-	_FORCE_INLINE_ Plane(const Vector3 &p_normal, real_t p_d = 0.0);
+	constexpr Plane(const Vector3 &p_normal, real_t p_d = 0.0);
 	_FORCE_INLINE_ Plane(const Vector3 &p_normal, const Vector3 &p_point);
 	_FORCE_INLINE_ Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir = CLOCKWISE);
 };
@@ -104,7 +104,7 @@ bool Plane::has_point(const Vector3 &p_point, real_t p_tolerance) const {
 	return (dist <= p_tolerance);
 }
 
-Plane::Plane(const Vector3 &p_normal, real_t p_d) :
+constexpr Plane::Plane(const Vector3 &p_normal, real_t p_d) :
 		normal(p_normal),
 		d(p_d) {
 }
@@ -125,11 +125,11 @@ Plane::Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_
 	d = normal.dot(p_point1);
 }
 
-bool Plane::operator==(const Plane &p_plane) const {
+constexpr bool Plane::operator==(const Plane &p_plane) const {
 	return normal == p_plane.normal && d == p_plane.d;
 }
 
-bool Plane::operator!=(const Plane &p_plane) const {
+constexpr bool Plane::operator!=(const Plane &p_plane) const {
 	return normal != p_plane.normal || d != p_plane.d;
 }
 

+ 0 - 37
core/math/projection.cpp

@@ -784,26 +784,6 @@ bool Projection::is_same(const Projection &p_cam) const {
 	return columns[0].is_same(p_cam.columns[0]) && columns[1].is_same(p_cam.columns[1]) && columns[2].is_same(p_cam.columns[2]) && columns[3].is_same(p_cam.columns[3]);
 }
 
-Projection::Projection() {
-	set_identity();
-}
-
-Projection Projection::operator*(const Projection &p_matrix) const {
-	Projection new_matrix;
-
-	for (int j = 0; j < 4; j++) {
-		for (int i = 0; i < 4; i++) {
-			real_t ab = 0;
-			for (int k = 0; k < 4; k++) {
-				ab += columns[k][i] * p_matrix.columns[j][k];
-			}
-			new_matrix.columns[j][i] = ab;
-		}
-	}
-
-	return new_matrix;
-}
-
 void Projection::set_depth_correction(bool p_flip_y, bool p_reverse_z, bool p_remap_z) {
 	// p_remap_z is used to convert from OpenGL-style clip space (-1 - 1) to Vulkan style (0 - 1).
 	real_t *m = &columns[0][0];
@@ -977,20 +957,6 @@ Projection::operator Transform3D() const {
 	return tr;
 }
 
-Projection::Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w) {
-	columns[0] = p_x;
-	columns[1] = p_y;
-	columns[2] = p_z;
-	columns[3] = p_w;
-}
-
-Projection::Projection(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_xw, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_yw, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_zw, real_t p_wx, real_t p_wy, real_t p_wz, real_t p_ww) {
-	columns[0] = Vector4(p_xx, p_xy, p_xz, p_xw);
-	columns[1] = Vector4(p_yx, p_yy, p_yz, p_yw);
-	columns[2] = Vector4(p_zx, p_zy, p_zz, p_zw);
-	columns[3] = Vector4(p_wx, p_wy, p_wz, p_ww);
-}
-
 Projection::Projection(const Transform3D &p_transform) {
 	const Transform3D &tr = p_transform;
 	real_t *m = &columns[0][0];
@@ -1012,6 +978,3 @@ Projection::Projection(const Transform3D &p_transform) {
 	m[14] = tr.origin.z;
 	m[15] = 1.0;
 }
-
-Projection::~Projection() {
-}

+ 37 - 10
core/math/projection.h

@@ -52,14 +52,19 @@ struct [[nodiscard]] Projection {
 		PLANE_BOTTOM
 	};
 
-	Vector4 columns[4];
+	Vector4 columns[4] = {
+		{ 1, 0, 0, 0 },
+		{ 0, 1, 0, 0 },
+		{ 0, 0, 1, 0 },
+		{ 0, 0, 0, 1 },
+	};
 
-	_FORCE_INLINE_ const Vector4 &operator[](int p_axis) const {
+	constexpr const Vector4 &operator[](int p_axis) const {
 		DEV_ASSERT((unsigned int)p_axis < 4);
 		return columns[p_axis];
 	}
 
-	_FORCE_INLINE_ Vector4 &operator[](int p_axis) {
+	constexpr Vector4 &operator[](int p_axis) {
 		DEV_ASSERT((unsigned int)p_axis < 4);
 		return columns[p_axis];
 	}
@@ -114,7 +119,7 @@ struct [[nodiscard]] Projection {
 	void invert();
 	Projection inverse() const;
 
-	Projection operator*(const Projection &p_matrix) const;
+	constexpr Projection operator*(const Projection &p_matrix) const;
 
 	Plane xform4(const Plane &p_vec4) const;
 	_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vec3) const;
@@ -134,7 +139,7 @@ struct [[nodiscard]] Projection {
 
 	bool is_same(const Projection &p_cam) const;
 
-	bool operator==(const Projection &p_cam) const {
+	constexpr bool operator==(const Projection &p_cam) const {
 		for (uint32_t i = 0; i < 4; i++) {
 			for (uint32_t j = 0; j < 4; j++) {
 				if (columns[i][j] != p_cam.columns[i][j]) {
@@ -145,19 +150,41 @@ struct [[nodiscard]] Projection {
 		return true;
 	}
 
-	bool operator!=(const Projection &p_cam) const {
+	constexpr bool operator!=(const Projection &p_cam) const {
 		return !(*this == p_cam);
 	}
 
 	real_t get_lod_multiplier() const;
 
-	Projection();
-	Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w);
-	Projection(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_xw, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_yw, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_zw, real_t p_wx, real_t p_wy, real_t p_wz, real_t p_ww);
+	Projection() = default;
+	constexpr Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w) :
+			columns{ p_x, p_y, p_z, p_w } {}
+	constexpr Projection(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_xw, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_yw, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_zw, real_t p_wx, real_t p_wy, real_t p_wz, real_t p_ww) :
+			columns{
+				{ p_xx, p_xy, p_xz, p_xw },
+				{ p_yx, p_yy, p_yz, p_yw },
+				{ p_zx, p_zy, p_zz, p_zw },
+				{ p_wx, p_wy, p_wz, p_ww },
+			} {}
 	Projection(const Transform3D &p_transform);
-	~Projection();
 };
 
+constexpr Projection Projection::operator*(const Projection &p_matrix) const {
+	Projection new_matrix;
+
+	for (int j = 0; j < 4; j++) {
+		for (int i = 0; i < 4; i++) {
+			real_t ab = 0;
+			for (int k = 0; k < 4; k++) {
+				ab += columns[k][i] * p_matrix.columns[j][k];
+			}
+			new_matrix.columns[j][i] = ab;
+		}
+	}
+
+	return new_matrix;
+}
+
 Vector3 Projection::xform(const Vector3 &p_vec3) const {
 	Vector3 ret;
 	ret.x = columns[0][0] * p_vec3.x + columns[1][0] * p_vec3.y + columns[2][0] * p_vec3.z + columns[3][0];

+ 0 - 16
core/math/quaternion.cpp

@@ -46,22 +46,6 @@ Vector3 Quaternion::get_euler(EulerOrder p_order) const {
 	return Basis(*this).get_euler(p_order);
 }
 
-void Quaternion::operator*=(const Quaternion &p_q) {
-	real_t xx = w * p_q.x + x * p_q.w + y * p_q.z - z * p_q.y;
-	real_t yy = w * p_q.y + y * p_q.w + z * p_q.x - x * p_q.z;
-	real_t zz = w * p_q.z + z * p_q.w + x * p_q.y - y * p_q.x;
-	w = w * p_q.w - x * p_q.x - y * p_q.y - z * p_q.z;
-	x = xx;
-	y = yy;
-	z = zz;
-}
-
-Quaternion Quaternion::operator*(const Quaternion &p_q) const {
-	Quaternion r = *this;
-	r *= p_q;
-	return r;
-}
-
 bool Quaternion::is_equal_approx(const Quaternion &p_quaternion) const {
 	return Math::is_equal_approx(x, p_quaternion.x) && Math::is_equal_approx(y, p_quaternion.y) && Math::is_equal_approx(z, p_quaternion.z) && Math::is_equal_approx(w, p_quaternion.w);
 }

+ 52 - 41
core/math/quaternion.h

@@ -36,6 +36,7 @@
 
 struct [[nodiscard]] Quaternion {
 	union {
+		// NOLINTBEGIN(modernize-use-default-member-init)
 		struct {
 			real_t x;
 			real_t y;
@@ -43,6 +44,7 @@ struct [[nodiscard]] Quaternion {
 			real_t w;
 		};
 		real_t components[4] = { 0, 0, 0, 1.0 };
+		// NOLINTEND(modernize-use-default-member-init)
 	};
 
 	_FORCE_INLINE_ real_t &operator[](int p_idx) {
@@ -84,8 +86,8 @@ struct [[nodiscard]] Quaternion {
 		r_axis.z = z * r;
 	}
 
-	void operator*=(const Quaternion &p_q);
-	Quaternion operator*(const Quaternion &p_q) const;
+	constexpr void operator*=(const Quaternion &p_q);
+	constexpr Quaternion operator*(const Quaternion &p_q) const;
 
 	_FORCE_INLINE_ Vector3 xform(const Vector3 &p_v) const {
 #ifdef MATH_CHECKS
@@ -100,40 +102,33 @@ struct [[nodiscard]] Quaternion {
 		return inverse().xform(p_v);
 	}
 
-	_FORCE_INLINE_ void operator+=(const Quaternion &p_q);
-	_FORCE_INLINE_ void operator-=(const Quaternion &p_q);
-	_FORCE_INLINE_ void operator*=(real_t p_s);
-	_FORCE_INLINE_ void operator/=(real_t p_s);
-	_FORCE_INLINE_ Quaternion operator+(const Quaternion &p_q2) const;
-	_FORCE_INLINE_ Quaternion operator-(const Quaternion &p_q2) const;
-	_FORCE_INLINE_ Quaternion operator-() const;
-	_FORCE_INLINE_ Quaternion operator*(real_t p_s) const;
-	_FORCE_INLINE_ Quaternion operator/(real_t p_s) const;
+	constexpr void operator+=(const Quaternion &p_q);
+	constexpr void operator-=(const Quaternion &p_q);
+	constexpr void operator*=(real_t p_s);
+	constexpr void operator/=(real_t p_s);
+	constexpr Quaternion operator+(const Quaternion &p_q2) const;
+	constexpr Quaternion operator-(const Quaternion &p_q2) const;
+	constexpr Quaternion operator-() const;
+	constexpr Quaternion operator*(real_t p_s) const;
+	constexpr Quaternion operator/(real_t p_s) const;
 
-	_FORCE_INLINE_ bool operator==(const Quaternion &p_quaternion) const;
-	_FORCE_INLINE_ bool operator!=(const Quaternion &p_quaternion) const;
+	constexpr bool operator==(const Quaternion &p_quaternion) const;
+	constexpr bool operator!=(const Quaternion &p_quaternion) const;
 
 	operator String() const;
 
-	_FORCE_INLINE_ Quaternion() {}
+	constexpr Quaternion() :
+			x(0), y(0), z(0), w(1) {}
 
-	_FORCE_INLINE_ Quaternion(real_t p_x, real_t p_y, real_t p_z, real_t p_w) :
-			x(p_x),
-			y(p_y),
-			z(p_z),
-			w(p_w) {
-	}
+	constexpr Quaternion(real_t p_x, real_t p_y, real_t p_z, real_t p_w) :
+			x(p_x), y(p_y), z(p_z), w(p_w) {}
 
 	Quaternion(const Vector3 &p_axis, real_t p_angle);
 
-	Quaternion(const Quaternion &p_q) :
-			x(p_q.x),
-			y(p_q.y),
-			z(p_q.z),
-			w(p_q.w) {
-	}
+	constexpr Quaternion(const Quaternion &p_q) :
+			x(p_q.x), y(p_q.y), z(p_q.z), w(p_q.w) {}
 
-	void operator=(const Quaternion &p_q) {
+	constexpr void operator=(const Quaternion &p_q) {
 		x = p_q.x;
 		y = p_q.y;
 		z = p_q.z;
@@ -178,62 +173,78 @@ real_t Quaternion::length_squared() const {
 	return dot(*this);
 }
 
-void Quaternion::operator+=(const Quaternion &p_q) {
+constexpr void Quaternion::operator+=(const Quaternion &p_q) {
 	x += p_q.x;
 	y += p_q.y;
 	z += p_q.z;
 	w += p_q.w;
 }
 
-void Quaternion::operator-=(const Quaternion &p_q) {
+constexpr void Quaternion::operator-=(const Quaternion &p_q) {
 	x -= p_q.x;
 	y -= p_q.y;
 	z -= p_q.z;
 	w -= p_q.w;
 }
 
-void Quaternion::operator*=(real_t p_s) {
+constexpr void Quaternion::operator*=(real_t p_s) {
 	x *= p_s;
 	y *= p_s;
 	z *= p_s;
 	w *= p_s;
 }
 
-void Quaternion::operator/=(real_t p_s) {
-	*this *= 1.0f / p_s;
+constexpr void Quaternion::operator/=(real_t p_s) {
+	*this *= (1 / p_s);
 }
 
-Quaternion Quaternion::operator+(const Quaternion &p_q2) const {
+constexpr Quaternion Quaternion::operator+(const Quaternion &p_q2) const {
 	const Quaternion &q1 = *this;
 	return Quaternion(q1.x + p_q2.x, q1.y + p_q2.y, q1.z + p_q2.z, q1.w + p_q2.w);
 }
 
-Quaternion Quaternion::operator-(const Quaternion &p_q2) const {
+constexpr Quaternion Quaternion::operator-(const Quaternion &p_q2) const {
 	const Quaternion &q1 = *this;
 	return Quaternion(q1.x - p_q2.x, q1.y - p_q2.y, q1.z - p_q2.z, q1.w - p_q2.w);
 }
 
-Quaternion Quaternion::operator-() const {
+constexpr Quaternion Quaternion::operator-() const {
 	const Quaternion &q2 = *this;
 	return Quaternion(-q2.x, -q2.y, -q2.z, -q2.w);
 }
 
-Quaternion Quaternion::operator*(real_t p_s) const {
+constexpr Quaternion Quaternion::operator*(real_t p_s) const {
 	return Quaternion(x * p_s, y * p_s, z * p_s, w * p_s);
 }
 
-Quaternion Quaternion::operator/(real_t p_s) const {
-	return *this * (1.0f / p_s);
+constexpr Quaternion Quaternion::operator/(real_t p_s) const {
+	return *this * (1 / p_s);
 }
 
-bool Quaternion::operator==(const Quaternion &p_quaternion) const {
+constexpr bool Quaternion::operator==(const Quaternion &p_quaternion) const {
 	return x == p_quaternion.x && y == p_quaternion.y && z == p_quaternion.z && w == p_quaternion.w;
 }
 
-bool Quaternion::operator!=(const Quaternion &p_quaternion) const {
+constexpr bool Quaternion::operator!=(const Quaternion &p_quaternion) const {
 	return x != p_quaternion.x || y != p_quaternion.y || z != p_quaternion.z || w != p_quaternion.w;
 }
 
-_FORCE_INLINE_ Quaternion operator*(real_t p_real, const Quaternion &p_quaternion) {
+constexpr void Quaternion::operator*=(const Quaternion &p_q) {
+	real_t xx = w * p_q.x + x * p_q.w + y * p_q.z - z * p_q.y;
+	real_t yy = w * p_q.y + y * p_q.w + z * p_q.x - x * p_q.z;
+	real_t zz = w * p_q.z + z * p_q.w + x * p_q.y - y * p_q.x;
+	w = w * p_q.w - x * p_q.x - y * p_q.y - z * p_q.z;
+	x = xx;
+	y = yy;
+	z = zz;
+}
+
+constexpr Quaternion Quaternion::operator*(const Quaternion &p_q) const {
+	Quaternion r = *this;
+	r *= p_q;
+	return r;
+}
+
+constexpr Quaternion operator*(real_t p_real, const Quaternion &p_quaternion) {
 	return p_quaternion * p_real;
 }

+ 5 - 5
core/math/rect2.h

@@ -205,8 +205,8 @@ struct [[nodiscard]] Rect2 {
 	bool is_same(const Rect2 &p_rect) const;
 	bool is_finite() const;
 
-	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; }
+	constexpr bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; }
+	constexpr bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
 
 	inline Rect2 grow(real_t p_amount) const {
 		Rect2 g = *this;
@@ -361,12 +361,12 @@ struct [[nodiscard]] Rect2 {
 	operator String() const;
 	operator Rect2i() const;
 
-	Rect2() {}
-	Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) :
+	Rect2() = default;
+	constexpr Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) :
 			position(Point2(p_x, p_y)),
 			size(Size2(p_width, p_height)) {
 	}
-	Rect2(const Point2 &p_pos, const Size2 &p_size) :
+	constexpr Rect2(const Point2 &p_pos, const Size2 &p_size) :
 			position(p_pos),
 			size(p_size) {
 	}

+ 5 - 5
core/math/rect2i.h

@@ -143,8 +143,8 @@ struct [[nodiscard]] Rect2i {
 		return true;
 	}
 
-	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; }
+	constexpr bool operator==(const Rect2i &p_rect) const { return position == p_rect.position && size == p_rect.size; }
+	constexpr bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; }
 
 	Rect2i grow(int p_amount) const {
 		Rect2i g = *this;
@@ -226,12 +226,12 @@ struct [[nodiscard]] Rect2i {
 	operator String() const;
 	operator Rect2() const;
 
-	Rect2i() {}
-	Rect2i(int p_x, int p_y, int p_width, int p_height) :
+	Rect2i() = default;
+	constexpr Rect2i(int p_x, int p_y, int p_width, int p_height) :
 			position(Point2i(p_x, p_y)),
 			size(Size2i(p_width, p_height)) {
 	}
-	Rect2i(const Point2i &p_pos, const Size2i &p_size) :
+	constexpr Rect2i(const Point2i &p_pos, const Size2i &p_size) :
 			position(p_pos),
 			size(p_size) {
 	}

+ 0 - 44
core/math/transform_2d.cpp

@@ -195,26 +195,6 @@ Transform2D Transform2D::looking_at(const Vector2 &p_target) const {
 	return return_trans;
 }
 
-bool Transform2D::operator==(const Transform2D &p_transform) const {
-	for (int i = 0; i < 3; i++) {
-		if (columns[i] != p_transform.columns[i]) {
-			return false;
-		}
-	}
-
-	return true;
-}
-
-bool Transform2D::operator!=(const Transform2D &p_transform) const {
-	for (int i = 0; i < 3; i++) {
-		if (columns[i] != p_transform.columns[i]) {
-			return true;
-		}
-	}
-
-	return false;
-}
-
 void Transform2D::operator*=(const Transform2D &p_transform) {
 	columns[2] = xform(p_transform.columns[2]);
 
@@ -287,30 +267,6 @@ Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t
 			get_origin().lerp(p_transform.get_origin(), p_weight));
 }
 
-void Transform2D::operator*=(real_t p_val) {
-	columns[0] *= p_val;
-	columns[1] *= p_val;
-	columns[2] *= p_val;
-}
-
-Transform2D Transform2D::operator*(real_t p_val) const {
-	Transform2D ret(*this);
-	ret *= p_val;
-	return ret;
-}
-
-void Transform2D::operator/=(real_t p_val) {
-	columns[0] /= p_val;
-	columns[1] /= p_val;
-	columns[2] /= p_val;
-}
-
-Transform2D Transform2D::operator/(real_t p_val) const {
-	Transform2D ret(*this);
-	ret /= p_val;
-	return ret;
-}
-
 Transform2D::operator String() const {
 	return "[X: " + columns[0].operator String() +
 			", Y: " + columns[1].operator String() +

+ 66 - 26
core/math/transform_2d.h

@@ -52,13 +52,17 @@ struct [[nodiscard]] Transform2D {
 	// WARNING: Be aware that unlike 3D code, 2D code uses a left-handed coordinate system:
 	// Y-axis points down, and angle is measure from +X to +Y in a clockwise-fashion.
 
-	Vector2 columns[3];
+	Vector2 columns[3] = {
+		{ 1, 0 },
+		{ 0, 1 },
+		{ 0, 0 },
+	};
 
 	_FORCE_INLINE_ real_t tdotx(const Vector2 &p_v) const { return columns[0][0] * p_v.x + columns[1][0] * p_v.y; }
 	_FORCE_INLINE_ real_t tdoty(const Vector2 &p_v) const { return columns[0][1] * p_v.x + columns[1][1] * p_v.y; }
 
-	const Vector2 &operator[](int p_idx) const { return columns[p_idx]; }
-	Vector2 &operator[](int p_idx) { return columns[p_idx]; }
+	constexpr const Vector2 &operator[](int p_idx) const { return columns[p_idx]; }
+	constexpr Vector2 &operator[](int p_idx) { return columns[p_idx]; }
 
 	void invert();
 	Transform2D inverse() const;
@@ -105,15 +109,15 @@ struct [[nodiscard]] Transform2D {
 
 	Transform2D looking_at(const Vector2 &p_target) const;
 
-	bool operator==(const Transform2D &p_transform) const;
-	bool operator!=(const Transform2D &p_transform) const;
+	constexpr bool operator==(const Transform2D &p_transform) const;
+	constexpr bool operator!=(const Transform2D &p_transform) const;
 
 	void operator*=(const Transform2D &p_transform);
 	Transform2D operator*(const Transform2D &p_transform) const;
-	void operator*=(real_t p_val);
-	Transform2D operator*(real_t p_val) const;
-	void operator/=(real_t p_val);
-	Transform2D operator/(real_t p_val) const;
+	constexpr void operator*=(real_t p_val);
+	constexpr Transform2D operator*(real_t p_val) const;
+	constexpr void operator/=(real_t p_val);
+	constexpr Transform2D operator/(real_t p_val) const;
 
 	Transform2D interpolate_with(const Transform2D &p_transform, real_t p_c) const;
 
@@ -128,31 +132,67 @@ struct [[nodiscard]] Transform2D {
 
 	operator String() const;
 
-	Transform2D(real_t p_xx, real_t p_xy, real_t p_yx, real_t p_yy, real_t p_ox, real_t p_oy) {
-		columns[0][0] = p_xx;
-		columns[0][1] = p_xy;
-		columns[1][0] = p_yx;
-		columns[1][1] = p_yy;
-		columns[2][0] = p_ox;
-		columns[2][1] = p_oy;
-	}
+	constexpr Transform2D(real_t p_xx, real_t p_xy, real_t p_yx, real_t p_yy, real_t p_ox, real_t p_oy) :
+			columns{
+				{ p_xx, p_xy },
+				{ p_yx, p_yy },
+				{ p_ox, p_oy },
+			} {}
 
-	Transform2D(const Vector2 &p_x, const Vector2 &p_y, const Vector2 &p_origin) {
-		columns[0] = p_x;
-		columns[1] = p_y;
-		columns[2] = p_origin;
-	}
+	constexpr Transform2D(const Vector2 &p_x, const Vector2 &p_y, const Vector2 &p_origin) :
+			columns{ p_x, p_y, p_origin } {}
 
 	Transform2D(real_t p_rot, const Vector2 &p_pos);
 
 	Transform2D(real_t p_rot, const Size2 &p_scale, real_t p_skew, const Vector2 &p_pos);
 
-	Transform2D() {
-		columns[0][0] = 1.0;
-		columns[1][1] = 1.0;
-	}
+	Transform2D() = default;
 };
 
+constexpr bool Transform2D::operator==(const Transform2D &p_transform) const {
+	for (int i = 0; i < 3; i++) {
+		if (columns[i] != p_transform.columns[i]) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+constexpr bool Transform2D::operator!=(const Transform2D &p_transform) const {
+	for (int i = 0; i < 3; i++) {
+		if (columns[i] != p_transform.columns[i]) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+constexpr void Transform2D::operator*=(real_t p_val) {
+	columns[0] *= p_val;
+	columns[1] *= p_val;
+	columns[2] *= p_val;
+}
+
+constexpr Transform2D Transform2D::operator*(real_t p_val) const {
+	Transform2D ret(*this);
+	ret *= p_val;
+	return ret;
+}
+
+constexpr void Transform2D::operator/=(real_t p_val) {
+	columns[0] /= p_val;
+	columns[1] /= p_val;
+	columns[2] /= p_val;
+}
+
+constexpr Transform2D Transform2D::operator/(real_t p_val) const {
+	Transform2D ret(*this);
+	ret /= p_val;
+	return ret;
+}
+
 Vector2 Transform2D::basis_xform(const Vector2 &p_vec) const {
 	return Vector2(
 			tdotx(p_vec),

+ 0 - 47
core/math/transform_3d.cpp

@@ -181,14 +181,6 @@ bool Transform3D::is_finite() const {
 	return basis.is_finite() && origin.is_finite();
 }
 
-bool Transform3D::operator==(const Transform3D &p_transform) const {
-	return (basis == p_transform.basis && origin == p_transform.origin);
-}
-
-bool Transform3D::operator!=(const Transform3D &p_transform) const {
-	return (basis != p_transform.basis || origin != p_transform.origin);
-}
-
 void Transform3D::operator*=(const Transform3D &p_transform) {
 	origin = xform(p_transform.origin);
 	basis *= p_transform.basis;
@@ -200,48 +192,9 @@ Transform3D Transform3D::operator*(const Transform3D &p_transform) const {
 	return t;
 }
 
-void Transform3D::operator*=(real_t p_val) {
-	origin *= p_val;
-	basis *= p_val;
-}
-
-Transform3D Transform3D::operator*(real_t p_val) const {
-	Transform3D ret(*this);
-	ret *= p_val;
-	return ret;
-}
-
-void Transform3D::operator/=(real_t p_val) {
-	basis /= p_val;
-	origin /= p_val;
-}
-
-Transform3D Transform3D::operator/(real_t p_val) const {
-	Transform3D ret(*this);
-	ret /= p_val;
-	return ret;
-}
-
 Transform3D::operator String() const {
 	return "[X: " + basis.get_column(0).operator String() +
 			", Y: " + basis.get_column(1).operator String() +
 			", Z: " + basis.get_column(2).operator String() +
 			", O: " + origin.operator String() + "]";
 }
-
-Transform3D::Transform3D(const Basis &p_basis, const Vector3 &p_origin) :
-		basis(p_basis),
-		origin(p_origin) {
-}
-
-Transform3D::Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin) :
-		origin(p_origin) {
-	basis.set_column(0, p_x);
-	basis.set_column(1, p_y);
-	basis.set_column(2, p_z);
-}
-
-Transform3D::Transform3D(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_ox, real_t p_oy, real_t p_oz) {
-	basis = Basis(p_xx, p_xy, p_xz, p_yx, p_yy, p_yz, p_zx, p_zy, p_zz);
-	origin = Vector3(p_ox, p_oy, p_oz);
-}

+ 46 - 10
core/math/transform_3d.h

@@ -77,8 +77,8 @@ struct [[nodiscard]] Transform3D {
 	bool is_same(const Transform3D &p_transform) const;
 	bool is_finite() const;
 
-	bool operator==(const Transform3D &p_transform) const;
-	bool operator!=(const Transform3D &p_transform) const;
+	constexpr bool operator==(const Transform3D &p_transform) const;
+	constexpr bool operator!=(const Transform3D &p_transform) const;
 
 	_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vector) const;
 	_FORCE_INLINE_ AABB xform(const AABB &p_aabb) const;
@@ -102,10 +102,10 @@ struct [[nodiscard]] Transform3D {
 
 	void operator*=(const Transform3D &p_transform);
 	Transform3D operator*(const Transform3D &p_transform) const;
-	void operator*=(real_t p_val);
-	Transform3D operator*(real_t p_val) const;
-	void operator/=(real_t p_val);
-	Transform3D operator/(real_t p_val) const;
+	constexpr void operator*=(real_t p_val);
+	constexpr Transform3D operator*(real_t p_val) const;
+	constexpr void operator/=(real_t p_val);
+	constexpr Transform3D operator/(real_t p_val) const;
 
 	Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const;
 
@@ -124,12 +124,48 @@ struct [[nodiscard]] Transform3D {
 
 	operator String() const;
 
-	Transform3D() {}
-	Transform3D(const Basis &p_basis, const Vector3 &p_origin = Vector3());
-	Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin);
-	Transform3D(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_ox, real_t p_oy, real_t p_oz);
+	Transform3D() = default;
+	constexpr Transform3D(const Basis &p_basis, const Vector3 &p_origin = Vector3()) :
+			basis(p_basis),
+			origin(p_origin) {}
+	constexpr Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin) :
+			basis(p_x, p_y, p_z),
+			origin(p_origin) {}
+	constexpr Transform3D(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_ox, real_t p_oy, real_t p_oz) :
+			basis(p_xx, p_xy, p_xz, p_yx, p_yy, p_yz, p_zx, p_zy, p_zz),
+			origin(p_ox, p_oy, p_oz) {}
 };
 
+constexpr bool Transform3D::operator==(const Transform3D &p_transform) const {
+	return (basis == p_transform.basis && origin == p_transform.origin);
+}
+
+constexpr bool Transform3D::operator!=(const Transform3D &p_transform) const {
+	return (basis != p_transform.basis || origin != p_transform.origin);
+}
+
+constexpr void Transform3D::operator*=(real_t p_val) {
+	origin *= p_val;
+	basis *= p_val;
+}
+
+constexpr Transform3D Transform3D::operator*(real_t p_val) const {
+	Transform3D ret(*this);
+	ret *= p_val;
+	return ret;
+}
+
+constexpr void Transform3D::operator/=(real_t p_val) {
+	basis /= p_val;
+	origin /= p_val;
+}
+
+constexpr Transform3D Transform3D::operator/(real_t p_val) const {
+	Transform3D ret(*this);
+	ret /= p_val;
+	return ret;
+}
+
 _FORCE_INLINE_ Vector3 Transform3D::xform(const Vector3 &p_vector) const {
 	return Vector3(
 			basis[0].dot(p_vector) + origin.x,

+ 51 - 49
core/math/vector2.h

@@ -45,18 +45,19 @@ struct [[nodiscard]] Vector2 {
 	};
 
 	union {
+		// NOLINTBEGIN(modernize-use-default-member-init)
 		struct {
-			union {
-				real_t x;
-				real_t width;
-			};
-			union {
-				real_t y;
-				real_t height;
-			};
+			real_t x;
+			real_t y;
+		};
+
+		struct {
+			real_t width;
+			real_t height;
 		};
 
 		real_t coord[2] = { 0 };
+		// NOLINTEND(modernize-use-default-member-init)
 	};
 
 	_FORCE_INLINE_ real_t &operator[](int p_axis) {
@@ -132,32 +133,32 @@ struct [[nodiscard]] Vector2 {
 	bool is_zero_approx() const;
 	bool is_finite() const;
 
-	Vector2 operator+(const Vector2 &p_v) const;
-	void operator+=(const Vector2 &p_v);
-	Vector2 operator-(const Vector2 &p_v) const;
-	void operator-=(const Vector2 &p_v);
-	Vector2 operator*(const Vector2 &p_v1) const;
+	constexpr Vector2 operator+(const Vector2 &p_v) const;
+	constexpr void operator+=(const Vector2 &p_v);
+	constexpr Vector2 operator-(const Vector2 &p_v) const;
+	constexpr void operator-=(const Vector2 &p_v);
+	constexpr Vector2 operator*(const Vector2 &p_v1) const;
 
-	Vector2 operator*(real_t p_rvalue) const;
-	void operator*=(real_t p_rvalue);
-	void operator*=(const Vector2 &p_rvalue) { *this = *this * p_rvalue; }
+	constexpr Vector2 operator*(real_t p_rvalue) const;
+	constexpr void operator*=(real_t p_rvalue);
+	constexpr void operator*=(const Vector2 &p_rvalue) { *this = *this * p_rvalue; }
 
-	Vector2 operator/(const Vector2 &p_v1) const;
+	constexpr Vector2 operator/(const Vector2 &p_v1) const;
 
-	Vector2 operator/(real_t p_rvalue) const;
+	constexpr Vector2 operator/(real_t p_rvalue) const;
 
-	void operator/=(real_t p_rvalue);
-	void operator/=(const Vector2 &p_rvalue) { *this = *this / p_rvalue; }
+	constexpr void operator/=(real_t p_rvalue);
+	constexpr void operator/=(const Vector2 &p_rvalue) { *this = *this / p_rvalue; }
 
-	Vector2 operator-() const;
+	constexpr Vector2 operator-() const;
 
-	bool operator==(const Vector2 &p_vec2) const;
-	bool operator!=(const Vector2 &p_vec2) const;
+	constexpr bool operator==(const Vector2 &p_vec2) const;
+	constexpr bool operator!=(const Vector2 &p_vec2) const;
 
-	bool operator<(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y < p_vec2.y) : (x < p_vec2.x); }
-	bool operator>(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y > p_vec2.y) : (x > p_vec2.x); }
-	bool operator<=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y <= p_vec2.y) : (x < p_vec2.x); }
-	bool operator>=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y >= p_vec2.y) : (x > p_vec2.x); }
+	constexpr bool operator<(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y < p_vec2.y) : (x < p_vec2.x); }
+	constexpr bool operator>(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y > p_vec2.y) : (x > p_vec2.x); }
+	constexpr bool operator<=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y <= p_vec2.y) : (x < p_vec2.x); }
+	constexpr bool operator>=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y >= p_vec2.y) : (x > p_vec2.x); }
 
 	real_t angle() const;
 	static Vector2 from_angle(real_t p_angle);
@@ -184,70 +185,71 @@ struct [[nodiscard]] Vector2 {
 	operator String() const;
 	operator Vector2i() const;
 
-	_FORCE_INLINE_ Vector2() {}
-	_FORCE_INLINE_ Vector2(real_t p_x, real_t p_y) {
-		x = p_x;
-		y = p_y;
-	}
+	// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
+	constexpr Vector2() :
+			x(0), y(0) {}
+	constexpr Vector2(real_t p_x, real_t p_y) :
+			x(p_x), y(p_y) {}
+	// NOLINTEND(cppcoreguidelines-pro-type-member-init)
 };
 
 _FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const {
 	return p_vec - *this * (dot(p_vec) - p_d);
 }
 
-_FORCE_INLINE_ Vector2 Vector2::operator+(const Vector2 &p_v) const {
+constexpr Vector2 Vector2::operator+(const Vector2 &p_v) const {
 	return Vector2(x + p_v.x, y + p_v.y);
 }
 
-_FORCE_INLINE_ void Vector2::operator+=(const Vector2 &p_v) {
+constexpr void Vector2::operator+=(const Vector2 &p_v) {
 	x += p_v.x;
 	y += p_v.y;
 }
 
-_FORCE_INLINE_ Vector2 Vector2::operator-(const Vector2 &p_v) const {
+constexpr Vector2 Vector2::operator-(const Vector2 &p_v) const {
 	return Vector2(x - p_v.x, y - p_v.y);
 }
 
-_FORCE_INLINE_ void Vector2::operator-=(const Vector2 &p_v) {
+constexpr void Vector2::operator-=(const Vector2 &p_v) {
 	x -= p_v.x;
 	y -= p_v.y;
 }
 
-_FORCE_INLINE_ Vector2 Vector2::operator*(const Vector2 &p_v1) const {
+constexpr Vector2 Vector2::operator*(const Vector2 &p_v1) const {
 	return Vector2(x * p_v1.x, y * p_v1.y);
 }
 
-_FORCE_INLINE_ Vector2 Vector2::operator*(real_t p_rvalue) const {
+constexpr Vector2 Vector2::operator*(real_t p_rvalue) const {
 	return Vector2(x * p_rvalue, y * p_rvalue);
 }
 
-_FORCE_INLINE_ void Vector2::operator*=(real_t p_rvalue) {
+constexpr void Vector2::operator*=(real_t p_rvalue) {
 	x *= p_rvalue;
 	y *= p_rvalue;
 }
 
-_FORCE_INLINE_ Vector2 Vector2::operator/(const Vector2 &p_v1) const {
+constexpr Vector2 Vector2::operator/(const Vector2 &p_v1) const {
 	return Vector2(x / p_v1.x, y / p_v1.y);
 }
 
-_FORCE_INLINE_ Vector2 Vector2::operator/(real_t p_rvalue) const {
+constexpr Vector2 Vector2::operator/(real_t p_rvalue) const {
 	return Vector2(x / p_rvalue, y / p_rvalue);
 }
 
-_FORCE_INLINE_ void Vector2::operator/=(real_t p_rvalue) {
+constexpr void Vector2::operator/=(real_t p_rvalue) {
 	x /= p_rvalue;
 	y /= p_rvalue;
 }
 
-_FORCE_INLINE_ Vector2 Vector2::operator-() const {
+constexpr Vector2 Vector2::operator-() const {
 	return Vector2(-x, -y);
 }
 
-_FORCE_INLINE_ bool Vector2::operator==(const Vector2 &p_vec2) const {
+constexpr bool Vector2::operator==(const Vector2 &p_vec2) const {
 	return x == p_vec2.x && y == p_vec2.y;
 }
 
-_FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const {
+constexpr bool Vector2::operator!=(const Vector2 &p_vec2) const {
 	return x != p_vec2.x || y != p_vec2.y;
 }
 
@@ -308,19 +310,19 @@ Vector2 Vector2::direction_to(const Vector2 &p_to) const {
 // Multiplication operators required to workaround issues with LLVM using implicit conversion
 // to Vector2i instead for integers where it should not.
 
-_FORCE_INLINE_ Vector2 operator*(float p_scalar, const Vector2 &p_vec) {
+constexpr Vector2 operator*(float p_scalar, const Vector2 &p_vec) {
 	return p_vec * p_scalar;
 }
 
-_FORCE_INLINE_ Vector2 operator*(double p_scalar, const Vector2 &p_vec) {
+constexpr Vector2 operator*(double p_scalar, const Vector2 &p_vec) {
 	return p_vec * p_scalar;
 }
 
-_FORCE_INLINE_ Vector2 operator*(int32_t p_scalar, const Vector2 &p_vec) {
+constexpr Vector2 operator*(int32_t p_scalar, const Vector2 &p_vec) {
 	return p_vec * p_scalar;
 }
 
-_FORCE_INLINE_ Vector2 operator*(int64_t p_scalar, const Vector2 &p_vec) {
+constexpr Vector2 operator*(int64_t p_scalar, const Vector2 &p_vec) {
 	return p_vec * p_scalar;
 }
 

+ 0 - 69
core/math/vector2i.cpp

@@ -65,75 +65,6 @@ double Vector2i::length() const {
 	return Math::sqrt((double)length_squared());
 }
 
-Vector2i Vector2i::operator+(const Vector2i &p_v) const {
-	return Vector2i(x + p_v.x, y + p_v.y);
-}
-
-void Vector2i::operator+=(const Vector2i &p_v) {
-	x += p_v.x;
-	y += p_v.y;
-}
-
-Vector2i Vector2i::operator-(const Vector2i &p_v) const {
-	return Vector2i(x - p_v.x, y - p_v.y);
-}
-
-void Vector2i::operator-=(const Vector2i &p_v) {
-	x -= p_v.x;
-	y -= p_v.y;
-}
-
-Vector2i Vector2i::operator*(const Vector2i &p_v1) const {
-	return Vector2i(x * p_v1.x, y * p_v1.y);
-}
-
-Vector2i Vector2i::operator*(int32_t p_rvalue) const {
-	return Vector2i(x * p_rvalue, y * p_rvalue);
-}
-
-void Vector2i::operator*=(int32_t p_rvalue) {
-	x *= p_rvalue;
-	y *= p_rvalue;
-}
-
-Vector2i Vector2i::operator/(const Vector2i &p_v1) const {
-	return Vector2i(x / p_v1.x, y / p_v1.y);
-}
-
-Vector2i Vector2i::operator/(int32_t p_rvalue) const {
-	return Vector2i(x / p_rvalue, y / p_rvalue);
-}
-
-void Vector2i::operator/=(int32_t p_rvalue) {
-	x /= p_rvalue;
-	y /= p_rvalue;
-}
-
-Vector2i Vector2i::operator%(const Vector2i &p_v1) const {
-	return Vector2i(x % p_v1.x, y % p_v1.y);
-}
-
-Vector2i Vector2i::operator%(int32_t p_rvalue) const {
-	return Vector2i(x % p_rvalue, y % p_rvalue);
-}
-
-void Vector2i::operator%=(int32_t p_rvalue) {
-	x %= p_rvalue;
-	y %= p_rvalue;
-}
-
-Vector2i Vector2i::operator-() const {
-	return Vector2i(-x, -y);
-}
-
-bool Vector2i::operator==(const Vector2i &p_vec2) const {
-	return x == p_vec2.x && y == p_vec2.y;
-}
-
-bool Vector2i::operator!=(const Vector2i &p_vec2) const {
-	return x != p_vec2.x || y != p_vec2.y;
-}
-
 Vector2i::operator String() const {
 	return "(" + itos(x) + ", " + itos(y) + ")";
 }

+ 108 - 37
core/math/vector2i.h

@@ -45,18 +45,19 @@ struct [[nodiscard]] Vector2i {
 	};
 
 	union {
+		// NOLINTBEGIN(modernize-use-default-member-init)
 		struct {
-			union {
-				int32_t x;
-				int32_t width;
-			};
-			union {
-				int32_t y;
-				int32_t height;
-			};
+			int32_t x;
+			int32_t y;
+		};
+
+		struct {
+			int32_t width;
+			int32_t height;
 		};
 
 		int32_t coord[2] = { 0 };
+		// NOLINTEND(modernize-use-default-member-init)
 	};
 
 	_FORCE_INLINE_ int32_t &operator[](int p_axis) {
@@ -100,32 +101,32 @@ struct [[nodiscard]] Vector2i {
 		return (p_to - *this).length_squared();
 	}
 
-	Vector2i operator+(const Vector2i &p_v) const;
-	void operator+=(const Vector2i &p_v);
-	Vector2i operator-(const Vector2i &p_v) const;
-	void operator-=(const Vector2i &p_v);
-	Vector2i operator*(const Vector2i &p_v1) const;
+	constexpr Vector2i operator+(const Vector2i &p_v) const;
+	constexpr void operator+=(const Vector2i &p_v);
+	constexpr Vector2i operator-(const Vector2i &p_v) const;
+	constexpr void operator-=(const Vector2i &p_v);
+	constexpr Vector2i operator*(const Vector2i &p_v1) const;
 
-	Vector2i operator*(int32_t p_rvalue) const;
-	void operator*=(int32_t p_rvalue);
+	constexpr Vector2i operator*(int32_t p_rvalue) const;
+	constexpr void operator*=(int32_t p_rvalue);
 
-	Vector2i operator/(const Vector2i &p_v1) const;
-	Vector2i operator/(int32_t p_rvalue) const;
-	void operator/=(int32_t p_rvalue);
+	constexpr Vector2i operator/(const Vector2i &p_v1) const;
+	constexpr Vector2i operator/(int32_t p_rvalue) const;
+	constexpr void operator/=(int32_t p_rvalue);
 
-	Vector2i operator%(const Vector2i &p_v1) const;
-	Vector2i operator%(int32_t p_rvalue) const;
-	void operator%=(int32_t p_rvalue);
+	constexpr Vector2i operator%(const Vector2i &p_v1) const;
+	constexpr Vector2i operator%(int32_t p_rvalue) const;
+	constexpr void operator%=(int32_t p_rvalue);
 
-	Vector2i operator-() const;
-	bool operator<(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); }
-	bool operator>(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y > p_vec2.y) : (x > p_vec2.x); }
+	constexpr Vector2i operator-() const;
+	constexpr bool operator<(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); }
+	constexpr bool operator>(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y > p_vec2.y) : (x > p_vec2.x); }
 
-	bool operator<=(const Vector2i &p_vec2) const { return x == p_vec2.x ? (y <= p_vec2.y) : (x < p_vec2.x); }
-	bool operator>=(const Vector2i &p_vec2) const { return x == p_vec2.x ? (y >= p_vec2.y) : (x > p_vec2.x); }
+	constexpr bool operator<=(const Vector2i &p_vec2) const { return x == p_vec2.x ? (y <= p_vec2.y) : (x < p_vec2.x); }
+	constexpr bool operator>=(const Vector2i &p_vec2) const { return x == p_vec2.x ? (y >= p_vec2.y) : (x > p_vec2.x); }
 
-	bool operator==(const Vector2i &p_vec2) const;
-	bool operator!=(const Vector2i &p_vec2) const;
+	constexpr bool operator==(const Vector2i &p_vec2) const;
+	constexpr bool operator!=(const Vector2i &p_vec2) const;
 
 	int64_t length_squared() const;
 	double length() const;
@@ -141,28 +142,98 @@ struct [[nodiscard]] Vector2i {
 	operator String() const;
 	operator Vector2() const;
 
-	inline Vector2i() {}
-	inline Vector2i(int32_t p_x, int32_t p_y) {
-		x = p_x;
-		y = p_y;
-	}
+	// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
+	constexpr Vector2i() :
+			x(0), y(0) {}
+	constexpr Vector2i(int32_t p_x, int32_t p_y) :
+			x(p_x), y(p_y) {}
+	// NOLINTEND(cppcoreguidelines-pro-type-member-init)
 };
 
+constexpr Vector2i Vector2i::operator+(const Vector2i &p_v) const {
+	return Vector2i(x + p_v.x, y + p_v.y);
+}
+
+constexpr void Vector2i::operator+=(const Vector2i &p_v) {
+	x += p_v.x;
+	y += p_v.y;
+}
+
+constexpr Vector2i Vector2i::operator-(const Vector2i &p_v) const {
+	return Vector2i(x - p_v.x, y - p_v.y);
+}
+
+constexpr void Vector2i::operator-=(const Vector2i &p_v) {
+	x -= p_v.x;
+	y -= p_v.y;
+}
+
+constexpr Vector2i Vector2i::operator*(const Vector2i &p_v1) const {
+	return Vector2i(x * p_v1.x, y * p_v1.y);
+}
+
+constexpr Vector2i Vector2i::operator*(int32_t p_rvalue) const {
+	return Vector2i(x * p_rvalue, y * p_rvalue);
+}
+
+constexpr void Vector2i::operator*=(int32_t p_rvalue) {
+	x *= p_rvalue;
+	y *= p_rvalue;
+}
+
+constexpr Vector2i Vector2i::operator/(const Vector2i &p_v1) const {
+	return Vector2i(x / p_v1.x, y / p_v1.y);
+}
+
+constexpr Vector2i Vector2i::operator/(int32_t p_rvalue) const {
+	return Vector2i(x / p_rvalue, y / p_rvalue);
+}
+
+constexpr void Vector2i::operator/=(int32_t p_rvalue) {
+	x /= p_rvalue;
+	y /= p_rvalue;
+}
+
+constexpr Vector2i Vector2i::operator%(const Vector2i &p_v1) const {
+	return Vector2i(x % p_v1.x, y % p_v1.y);
+}
+
+constexpr Vector2i Vector2i::operator%(int32_t p_rvalue) const {
+	return Vector2i(x % p_rvalue, y % p_rvalue);
+}
+
+constexpr void Vector2i::operator%=(int32_t p_rvalue) {
+	x %= p_rvalue;
+	y %= p_rvalue;
+}
+
+constexpr Vector2i Vector2i::operator-() const {
+	return Vector2i(-x, -y);
+}
+
+constexpr bool Vector2i::operator==(const Vector2i &p_vec2) const {
+	return x == p_vec2.x && y == p_vec2.y;
+}
+
+constexpr bool Vector2i::operator!=(const Vector2i &p_vec2) const {
+	return x != p_vec2.x || y != p_vec2.y;
+}
+
 // Multiplication operators required to workaround issues with LLVM using implicit conversion.
 
-_FORCE_INLINE_ Vector2i operator*(int32_t p_scalar, const Vector2i &p_vector) {
+constexpr Vector2i operator*(int32_t p_scalar, const Vector2i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-_FORCE_INLINE_ Vector2i operator*(int64_t p_scalar, const Vector2i &p_vector) {
+constexpr Vector2i operator*(int64_t p_scalar, const Vector2i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-_FORCE_INLINE_ Vector2i operator*(float p_scalar, const Vector2i &p_vector) {
+constexpr Vector2i operator*(float p_scalar, const Vector2i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-_FORCE_INLINE_ Vector2i operator*(double p_scalar, const Vector2i &p_vector) {
+constexpr Vector2i operator*(double p_scalar, const Vector2i &p_vector) {
 	return p_vector * p_scalar;
 }
 

+ 51 - 51
core/math/vector3.h

@@ -48,6 +48,7 @@ struct [[nodiscard]] Vector3 {
 	};
 
 	union {
+		// NOLINTBEGIN(modernize-use-default-member-init)
 		struct {
 			real_t x;
 			real_t y;
@@ -55,6 +56,7 @@ struct [[nodiscard]] Vector3 {
 		};
 
 		real_t coord[3] = { 0 };
+		// NOLINTEND(modernize-use-default-member-init)
 	};
 
 	_FORCE_INLINE_ const real_t &operator[](int p_axis) const {
@@ -161,38 +163,36 @@ struct [[nodiscard]] Vector3 {
 
 	/* Operators */
 
-	_FORCE_INLINE_ Vector3 &operator+=(const Vector3 &p_v);
-	_FORCE_INLINE_ Vector3 operator+(const Vector3 &p_v) const;
-	_FORCE_INLINE_ Vector3 &operator-=(const Vector3 &p_v);
-	_FORCE_INLINE_ Vector3 operator-(const Vector3 &p_v) const;
-	_FORCE_INLINE_ Vector3 &operator*=(const Vector3 &p_v);
-	_FORCE_INLINE_ Vector3 operator*(const Vector3 &p_v) const;
-	_FORCE_INLINE_ Vector3 &operator/=(const Vector3 &p_v);
-	_FORCE_INLINE_ Vector3 operator/(const Vector3 &p_v) const;
-
-	_FORCE_INLINE_ Vector3 &operator*=(real_t p_scalar);
-	_FORCE_INLINE_ Vector3 operator*(real_t p_scalar) const;
-	_FORCE_INLINE_ Vector3 &operator/=(real_t p_scalar);
-	_FORCE_INLINE_ Vector3 operator/(real_t p_scalar) const;
-
-	_FORCE_INLINE_ Vector3 operator-() const;
-
-	_FORCE_INLINE_ bool operator==(const Vector3 &p_v) const;
-	_FORCE_INLINE_ bool operator!=(const Vector3 &p_v) const;
-	_FORCE_INLINE_ bool operator<(const Vector3 &p_v) const;
-	_FORCE_INLINE_ bool operator<=(const Vector3 &p_v) const;
-	_FORCE_INLINE_ bool operator>(const Vector3 &p_v) const;
-	_FORCE_INLINE_ bool operator>=(const Vector3 &p_v) const;
+	constexpr Vector3 &operator+=(const Vector3 &p_v);
+	constexpr Vector3 operator+(const Vector3 &p_v) const;
+	constexpr Vector3 &operator-=(const Vector3 &p_v);
+	constexpr Vector3 operator-(const Vector3 &p_v) const;
+	constexpr Vector3 &operator*=(const Vector3 &p_v);
+	constexpr Vector3 operator*(const Vector3 &p_v) const;
+	constexpr Vector3 &operator/=(const Vector3 &p_v);
+	constexpr Vector3 operator/(const Vector3 &p_v) const;
+
+	constexpr Vector3 &operator*=(real_t p_scalar);
+	constexpr Vector3 operator*(real_t p_scalar) const;
+	constexpr Vector3 &operator/=(real_t p_scalar);
+	constexpr Vector3 operator/(real_t p_scalar) const;
+
+	constexpr Vector3 operator-() const;
+
+	constexpr bool operator==(const Vector3 &p_v) const;
+	constexpr bool operator!=(const Vector3 &p_v) const;
+	constexpr bool operator<(const Vector3 &p_v) const;
+	constexpr bool operator<=(const Vector3 &p_v) const;
+	constexpr bool operator>(const Vector3 &p_v) const;
+	constexpr bool operator>=(const Vector3 &p_v) const;
 
 	operator String() const;
 	operator Vector3i() const;
 
-	_FORCE_INLINE_ Vector3() {}
-	_FORCE_INLINE_ Vector3(real_t p_x, real_t p_y, real_t p_z) {
-		x = p_x;
-		y = p_y;
-		z = p_z;
-	}
+	constexpr Vector3() :
+			x(0), y(0), z(0) {}
+	constexpr Vector3(real_t p_x, real_t p_y, real_t p_z) :
+			x(p_x), y(p_y), z(p_z) {}
 };
 
 Vector3 Vector3::cross(const Vector3 &p_with) const {
@@ -339,51 +339,51 @@ Vector3 Vector3::get_any_perpendicular() const {
 
 /* Operators */
 
-Vector3 &Vector3::operator+=(const Vector3 &p_v) {
+constexpr Vector3 &Vector3::operator+=(const Vector3 &p_v) {
 	x += p_v.x;
 	y += p_v.y;
 	z += p_v.z;
 	return *this;
 }
 
-Vector3 Vector3::operator+(const Vector3 &p_v) const {
+constexpr Vector3 Vector3::operator+(const Vector3 &p_v) const {
 	return Vector3(x + p_v.x, y + p_v.y, z + p_v.z);
 }
 
-Vector3 &Vector3::operator-=(const Vector3 &p_v) {
+constexpr Vector3 &Vector3::operator-=(const Vector3 &p_v) {
 	x -= p_v.x;
 	y -= p_v.y;
 	z -= p_v.z;
 	return *this;
 }
 
-Vector3 Vector3::operator-(const Vector3 &p_v) const {
+constexpr Vector3 Vector3::operator-(const Vector3 &p_v) const {
 	return Vector3(x - p_v.x, y - p_v.y, z - p_v.z);
 }
 
-Vector3 &Vector3::operator*=(const Vector3 &p_v) {
+constexpr Vector3 &Vector3::operator*=(const Vector3 &p_v) {
 	x *= p_v.x;
 	y *= p_v.y;
 	z *= p_v.z;
 	return *this;
 }
 
-Vector3 Vector3::operator*(const Vector3 &p_v) const {
+constexpr Vector3 Vector3::operator*(const Vector3 &p_v) const {
 	return Vector3(x * p_v.x, y * p_v.y, z * p_v.z);
 }
 
-Vector3 &Vector3::operator/=(const Vector3 &p_v) {
+constexpr Vector3 &Vector3::operator/=(const Vector3 &p_v) {
 	x /= p_v.x;
 	y /= p_v.y;
 	z /= p_v.z;
 	return *this;
 }
 
-Vector3 Vector3::operator/(const Vector3 &p_v) const {
+constexpr Vector3 Vector3::operator/(const Vector3 &p_v) const {
 	return Vector3(x / p_v.x, y / p_v.y, z / p_v.z);
 }
 
-Vector3 &Vector3::operator*=(real_t p_scalar) {
+constexpr Vector3 &Vector3::operator*=(real_t p_scalar) {
 	x *= p_scalar;
 	y *= p_scalar;
 	z *= p_scalar;
@@ -393,50 +393,50 @@ Vector3 &Vector3::operator*=(real_t p_scalar) {
 // Multiplication operators required to workaround issues with LLVM using implicit conversion
 // to Vector3i instead for integers where it should not.
 
-_FORCE_INLINE_ Vector3 operator*(float p_scalar, const Vector3 &p_vec) {
+constexpr Vector3 operator*(float p_scalar, const Vector3 &p_vec) {
 	return p_vec * p_scalar;
 }
 
-_FORCE_INLINE_ Vector3 operator*(double p_scalar, const Vector3 &p_vec) {
+constexpr Vector3 operator*(double p_scalar, const Vector3 &p_vec) {
 	return p_vec * p_scalar;
 }
 
-_FORCE_INLINE_ Vector3 operator*(int32_t p_scalar, const Vector3 &p_vec) {
+constexpr Vector3 operator*(int32_t p_scalar, const Vector3 &p_vec) {
 	return p_vec * p_scalar;
 }
 
-_FORCE_INLINE_ Vector3 operator*(int64_t p_scalar, const Vector3 &p_vec) {
+constexpr Vector3 operator*(int64_t p_scalar, const Vector3 &p_vec) {
 	return p_vec * p_scalar;
 }
 
-Vector3 Vector3::operator*(real_t p_scalar) const {
+constexpr Vector3 Vector3::operator*(real_t p_scalar) const {
 	return Vector3(x * p_scalar, y * p_scalar, z * p_scalar);
 }
 
-Vector3 &Vector3::operator/=(real_t p_scalar) {
+constexpr Vector3 &Vector3::operator/=(real_t p_scalar) {
 	x /= p_scalar;
 	y /= p_scalar;
 	z /= p_scalar;
 	return *this;
 }
 
-Vector3 Vector3::operator/(real_t p_scalar) const {
+constexpr Vector3 Vector3::operator/(real_t p_scalar) const {
 	return Vector3(x / p_scalar, y / p_scalar, z / p_scalar);
 }
 
-Vector3 Vector3::operator-() const {
+constexpr Vector3 Vector3::operator-() const {
 	return Vector3(-x, -y, -z);
 }
 
-bool Vector3::operator==(const Vector3 &p_v) const {
+constexpr bool Vector3::operator==(const Vector3 &p_v) const {
 	return x == p_v.x && y == p_v.y && z == p_v.z;
 }
 
-bool Vector3::operator!=(const Vector3 &p_v) const {
+constexpr bool Vector3::operator!=(const Vector3 &p_v) const {
 	return x != p_v.x || y != p_v.y || z != p_v.z;
 }
 
-bool Vector3::operator<(const Vector3 &p_v) const {
+constexpr bool Vector3::operator<(const Vector3 &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			return z < p_v.z;
@@ -446,7 +446,7 @@ bool Vector3::operator<(const Vector3 &p_v) const {
 	return x < p_v.x;
 }
 
-bool Vector3::operator>(const Vector3 &p_v) const {
+constexpr bool Vector3::operator>(const Vector3 &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			return z > p_v.z;
@@ -456,7 +456,7 @@ bool Vector3::operator>(const Vector3 &p_v) const {
 	return x > p_v.x;
 }
 
-bool Vector3::operator<=(const Vector3 &p_v) const {
+constexpr bool Vector3::operator<=(const Vector3 &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			return z <= p_v.z;
@@ -466,7 +466,7 @@ bool Vector3::operator<=(const Vector3 &p_v) const {
 	return x < p_v.x;
 }
 
-bool Vector3::operator>=(const Vector3 &p_v) const {
+constexpr bool Vector3::operator>=(const Vector3 &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			return z >= p_v.z;

+ 59 - 59
core/math/vector3i.h

@@ -46,6 +46,7 @@ struct [[nodiscard]] Vector3i {
 	};
 
 	union {
+		// NOLINTBEGIN(modernize-use-default-member-init)
 		struct {
 			int32_t x;
 			int32_t y;
@@ -53,6 +54,7 @@ struct [[nodiscard]] Vector3i {
 		};
 
 		int32_t coord[3] = { 0 };
+		// NOLINTEND(modernize-use-default-member-init)
 	};
 
 	_FORCE_INLINE_ const int32_t &operator[](int p_axis) const {
@@ -101,42 +103,40 @@ struct [[nodiscard]] Vector3i {
 
 	/* Operators */
 
-	_FORCE_INLINE_ Vector3i &operator+=(const Vector3i &p_v);
-	_FORCE_INLINE_ Vector3i operator+(const Vector3i &p_v) const;
-	_FORCE_INLINE_ Vector3i &operator-=(const Vector3i &p_v);
-	_FORCE_INLINE_ Vector3i operator-(const Vector3i &p_v) const;
-	_FORCE_INLINE_ Vector3i &operator*=(const Vector3i &p_v);
-	_FORCE_INLINE_ Vector3i operator*(const Vector3i &p_v) const;
-	_FORCE_INLINE_ Vector3i &operator/=(const Vector3i &p_v);
-	_FORCE_INLINE_ Vector3i operator/(const Vector3i &p_v) const;
-	_FORCE_INLINE_ Vector3i &operator%=(const Vector3i &p_v);
-	_FORCE_INLINE_ Vector3i operator%(const Vector3i &p_v) const;
-
-	_FORCE_INLINE_ Vector3i &operator*=(int32_t p_scalar);
-	_FORCE_INLINE_ Vector3i operator*(int32_t p_scalar) const;
-	_FORCE_INLINE_ Vector3i &operator/=(int32_t p_scalar);
-	_FORCE_INLINE_ Vector3i operator/(int32_t p_scalar) const;
-	_FORCE_INLINE_ Vector3i &operator%=(int32_t p_scalar);
-	_FORCE_INLINE_ Vector3i operator%(int32_t p_scalar) const;
-
-	_FORCE_INLINE_ Vector3i operator-() const;
-
-	_FORCE_INLINE_ bool operator==(const Vector3i &p_v) const;
-	_FORCE_INLINE_ bool operator!=(const Vector3i &p_v) const;
-	_FORCE_INLINE_ bool operator<(const Vector3i &p_v) const;
-	_FORCE_INLINE_ bool operator<=(const Vector3i &p_v) const;
-	_FORCE_INLINE_ bool operator>(const Vector3i &p_v) const;
-	_FORCE_INLINE_ bool operator>=(const Vector3i &p_v) const;
+	constexpr Vector3i &operator+=(const Vector3i &p_v);
+	constexpr Vector3i operator+(const Vector3i &p_v) const;
+	constexpr Vector3i &operator-=(const Vector3i &p_v);
+	constexpr Vector3i operator-(const Vector3i &p_v) const;
+	constexpr Vector3i &operator*=(const Vector3i &p_v);
+	constexpr Vector3i operator*(const Vector3i &p_v) const;
+	constexpr Vector3i &operator/=(const Vector3i &p_v);
+	constexpr Vector3i operator/(const Vector3i &p_v) const;
+	constexpr Vector3i &operator%=(const Vector3i &p_v);
+	constexpr Vector3i operator%(const Vector3i &p_v) const;
+
+	constexpr Vector3i &operator*=(int32_t p_scalar);
+	constexpr Vector3i operator*(int32_t p_scalar) const;
+	constexpr Vector3i &operator/=(int32_t p_scalar);
+	constexpr Vector3i operator/(int32_t p_scalar) const;
+	constexpr Vector3i &operator%=(int32_t p_scalar);
+	constexpr Vector3i operator%(int32_t p_scalar) const;
+
+	constexpr Vector3i operator-() const;
+
+	constexpr bool operator==(const Vector3i &p_v) const;
+	constexpr bool operator!=(const Vector3i &p_v) const;
+	constexpr bool operator<(const Vector3i &p_v) const;
+	constexpr bool operator<=(const Vector3i &p_v) const;
+	constexpr bool operator>(const Vector3i &p_v) const;
+	constexpr bool operator>=(const Vector3i &p_v) const;
 
 	operator String() const;
 	operator Vector3() const;
 
-	_FORCE_INLINE_ Vector3i() {}
-	_FORCE_INLINE_ Vector3i(int32_t p_x, int32_t p_y, int32_t p_z) {
-		x = p_x;
-		y = p_y;
-		z = p_z;
-	}
+	constexpr Vector3i() :
+			x(0), y(0), z(0) {}
+	constexpr Vector3i(int32_t p_x, int32_t p_y, int32_t p_z) :
+			x(p_x), y(p_y), z(p_z) {}
 };
 
 int64_t Vector3i::length_squared() const {
@@ -165,125 +165,125 @@ int64_t Vector3i::distance_squared_to(const Vector3i &p_to) const {
 
 /* Operators */
 
-Vector3i &Vector3i::operator+=(const Vector3i &p_v) {
+constexpr Vector3i &Vector3i::operator+=(const Vector3i &p_v) {
 	x += p_v.x;
 	y += p_v.y;
 	z += p_v.z;
 	return *this;
 }
 
-Vector3i Vector3i::operator+(const Vector3i &p_v) const {
+constexpr Vector3i Vector3i::operator+(const Vector3i &p_v) const {
 	return Vector3i(x + p_v.x, y + p_v.y, z + p_v.z);
 }
 
-Vector3i &Vector3i::operator-=(const Vector3i &p_v) {
+constexpr Vector3i &Vector3i::operator-=(const Vector3i &p_v) {
 	x -= p_v.x;
 	y -= p_v.y;
 	z -= p_v.z;
 	return *this;
 }
 
-Vector3i Vector3i::operator-(const Vector3i &p_v) const {
+constexpr Vector3i Vector3i::operator-(const Vector3i &p_v) const {
 	return Vector3i(x - p_v.x, y - p_v.y, z - p_v.z);
 }
 
-Vector3i &Vector3i::operator*=(const Vector3i &p_v) {
+constexpr Vector3i &Vector3i::operator*=(const Vector3i &p_v) {
 	x *= p_v.x;
 	y *= p_v.y;
 	z *= p_v.z;
 	return *this;
 }
 
-Vector3i Vector3i::operator*(const Vector3i &p_v) const {
+constexpr Vector3i Vector3i::operator*(const Vector3i &p_v) const {
 	return Vector3i(x * p_v.x, y * p_v.y, z * p_v.z);
 }
 
-Vector3i &Vector3i::operator/=(const Vector3i &p_v) {
+constexpr Vector3i &Vector3i::operator/=(const Vector3i &p_v) {
 	x /= p_v.x;
 	y /= p_v.y;
 	z /= p_v.z;
 	return *this;
 }
 
-Vector3i Vector3i::operator/(const Vector3i &p_v) const {
+constexpr Vector3i Vector3i::operator/(const Vector3i &p_v) const {
 	return Vector3i(x / p_v.x, y / p_v.y, z / p_v.z);
 }
 
-Vector3i &Vector3i::operator%=(const Vector3i &p_v) {
+constexpr Vector3i &Vector3i::operator%=(const Vector3i &p_v) {
 	x %= p_v.x;
 	y %= p_v.y;
 	z %= p_v.z;
 	return *this;
 }
 
-Vector3i Vector3i::operator%(const Vector3i &p_v) const {
+constexpr Vector3i Vector3i::operator%(const Vector3i &p_v) const {
 	return Vector3i(x % p_v.x, y % p_v.y, z % p_v.z);
 }
 
-Vector3i &Vector3i::operator*=(int32_t p_scalar) {
+constexpr Vector3i &Vector3i::operator*=(int32_t p_scalar) {
 	x *= p_scalar;
 	y *= p_scalar;
 	z *= p_scalar;
 	return *this;
 }
 
-Vector3i Vector3i::operator*(int32_t p_scalar) const {
+constexpr Vector3i Vector3i::operator*(int32_t p_scalar) const {
 	return Vector3i(x * p_scalar, y * p_scalar, z * p_scalar);
 }
 
 // Multiplication operators required to workaround issues with LLVM using implicit conversion.
 
-_FORCE_INLINE_ Vector3i operator*(int32_t p_scalar, const Vector3i &p_vector) {
+constexpr Vector3i operator*(int32_t p_scalar, const Vector3i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-_FORCE_INLINE_ Vector3i operator*(int64_t p_scalar, const Vector3i &p_vector) {
+constexpr Vector3i operator*(int64_t p_scalar, const Vector3i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-_FORCE_INLINE_ Vector3i operator*(float p_scalar, const Vector3i &p_vector) {
+constexpr Vector3i operator*(float p_scalar, const Vector3i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-_FORCE_INLINE_ Vector3i operator*(double p_scalar, const Vector3i &p_vector) {
+constexpr Vector3i operator*(double p_scalar, const Vector3i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-Vector3i &Vector3i::operator/=(int32_t p_scalar) {
+constexpr Vector3i &Vector3i::operator/=(int32_t p_scalar) {
 	x /= p_scalar;
 	y /= p_scalar;
 	z /= p_scalar;
 	return *this;
 }
 
-Vector3i Vector3i::operator/(int32_t p_scalar) const {
+constexpr Vector3i Vector3i::operator/(int32_t p_scalar) const {
 	return Vector3i(x / p_scalar, y / p_scalar, z / p_scalar);
 }
 
-Vector3i &Vector3i::operator%=(int32_t p_scalar) {
+constexpr Vector3i &Vector3i::operator%=(int32_t p_scalar) {
 	x %= p_scalar;
 	y %= p_scalar;
 	z %= p_scalar;
 	return *this;
 }
 
-Vector3i Vector3i::operator%(int32_t p_scalar) const {
+constexpr Vector3i Vector3i::operator%(int32_t p_scalar) const {
 	return Vector3i(x % p_scalar, y % p_scalar, z % p_scalar);
 }
 
-Vector3i Vector3i::operator-() const {
+constexpr Vector3i Vector3i::operator-() const {
 	return Vector3i(-x, -y, -z);
 }
 
-bool Vector3i::operator==(const Vector3i &p_v) const {
+constexpr bool Vector3i::operator==(const Vector3i &p_v) const {
 	return (x == p_v.x && y == p_v.y && z == p_v.z);
 }
 
-bool Vector3i::operator!=(const Vector3i &p_v) const {
+constexpr bool Vector3i::operator!=(const Vector3i &p_v) const {
 	return (x != p_v.x || y != p_v.y || z != p_v.z);
 }
 
-bool Vector3i::operator<(const Vector3i &p_v) const {
+constexpr bool Vector3i::operator<(const Vector3i &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			return z < p_v.z;
@@ -295,7 +295,7 @@ bool Vector3i::operator<(const Vector3i &p_v) const {
 	}
 }
 
-bool Vector3i::operator>(const Vector3i &p_v) const {
+constexpr bool Vector3i::operator>(const Vector3i &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			return z > p_v.z;
@@ -307,7 +307,7 @@ bool Vector3i::operator>(const Vector3i &p_v) const {
 	}
 }
 
-bool Vector3i::operator<=(const Vector3i &p_v) const {
+constexpr bool Vector3i::operator<=(const Vector3i &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			return z <= p_v.z;
@@ -319,7 +319,7 @@ bool Vector3i::operator<=(const Vector3i &p_v) const {
 	}
 }
 
-bool Vector3i::operator>=(const Vector3i &p_v) const {
+constexpr bool Vector3i::operator>=(const Vector3i &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			return z >= p_v.z;

+ 51 - 52
core/math/vector4.h

@@ -48,6 +48,7 @@ struct [[nodiscard]] Vector4 {
 	};
 
 	union {
+		// NOLINTBEGIN(modernize-use-default-member-init)
 		struct {
 			real_t x;
 			real_t y;
@@ -55,6 +56,7 @@ struct [[nodiscard]] Vector4 {
 			real_t w;
 		};
 		real_t coord[4] = { 0, 0, 0, 0 };
+		// NOLINTEND(modernize-use-default-member-init)
 	};
 
 	_FORCE_INLINE_ real_t &operator[](int p_axis) {
@@ -120,37 +122,34 @@ struct [[nodiscard]] Vector4 {
 	Vector4 inverse() const;
 	_FORCE_INLINE_ real_t dot(const Vector4 &p_vec4) const;
 
-	_FORCE_INLINE_ void operator+=(const Vector4 &p_vec4);
-	_FORCE_INLINE_ void operator-=(const Vector4 &p_vec4);
-	_FORCE_INLINE_ void operator*=(const Vector4 &p_vec4);
-	_FORCE_INLINE_ void operator/=(const Vector4 &p_vec4);
-	_FORCE_INLINE_ void operator*=(real_t p_s);
-	_FORCE_INLINE_ void operator/=(real_t p_s);
-	_FORCE_INLINE_ Vector4 operator+(const Vector4 &p_vec4) const;
-	_FORCE_INLINE_ Vector4 operator-(const Vector4 &p_vec4) const;
-	_FORCE_INLINE_ Vector4 operator*(const Vector4 &p_vec4) const;
-	_FORCE_INLINE_ Vector4 operator/(const Vector4 &p_vec4) const;
-	_FORCE_INLINE_ Vector4 operator-() const;
-	_FORCE_INLINE_ Vector4 operator*(real_t p_s) const;
-	_FORCE_INLINE_ Vector4 operator/(real_t p_s) const;
-
-	_FORCE_INLINE_ bool operator==(const Vector4 &p_vec4) const;
-	_FORCE_INLINE_ bool operator!=(const Vector4 &p_vec4) const;
-	_FORCE_INLINE_ bool operator>(const Vector4 &p_vec4) const;
-	_FORCE_INLINE_ bool operator<(const Vector4 &p_vec4) const;
-	_FORCE_INLINE_ bool operator>=(const Vector4 &p_vec4) const;
-	_FORCE_INLINE_ bool operator<=(const Vector4 &p_vec4) const;
+	constexpr void operator+=(const Vector4 &p_vec4);
+	constexpr void operator-=(const Vector4 &p_vec4);
+	constexpr void operator*=(const Vector4 &p_vec4);
+	constexpr void operator/=(const Vector4 &p_vec4);
+	constexpr void operator*=(real_t p_s);
+	constexpr void operator/=(real_t p_s);
+	constexpr Vector4 operator+(const Vector4 &p_vec4) const;
+	constexpr Vector4 operator-(const Vector4 &p_vec4) const;
+	constexpr Vector4 operator*(const Vector4 &p_vec4) const;
+	constexpr Vector4 operator/(const Vector4 &p_vec4) const;
+	constexpr Vector4 operator-() const;
+	constexpr Vector4 operator*(real_t p_s) const;
+	constexpr Vector4 operator/(real_t p_s) const;
+
+	constexpr bool operator==(const Vector4 &p_vec4) const;
+	constexpr bool operator!=(const Vector4 &p_vec4) const;
+	constexpr bool operator>(const Vector4 &p_vec4) const;
+	constexpr bool operator<(const Vector4 &p_vec4) const;
+	constexpr bool operator>=(const Vector4 &p_vec4) const;
+	constexpr bool operator<=(const Vector4 &p_vec4) const;
 
 	operator String() const;
 	operator Vector4i() const;
 
-	_FORCE_INLINE_ Vector4() {}
-	_FORCE_INLINE_ Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) {
-		x = p_x;
-		y = p_y;
-		z = p_z;
-		w = p_w;
-	}
+	constexpr Vector4() :
+			x(0), y(0), z(0), w(0) {}
+	constexpr Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) :
+			x(p_x), y(p_y), z(p_z), w(p_w) {}
 };
 
 real_t Vector4::dot(const Vector4 &p_vec4) const {
@@ -161,81 +160,81 @@ real_t Vector4::length_squared() const {
 	return dot(*this);
 }
 
-void Vector4::operator+=(const Vector4 &p_vec4) {
+constexpr void Vector4::operator+=(const Vector4 &p_vec4) {
 	x += p_vec4.x;
 	y += p_vec4.y;
 	z += p_vec4.z;
 	w += p_vec4.w;
 }
 
-void Vector4::operator-=(const Vector4 &p_vec4) {
+constexpr void Vector4::operator-=(const Vector4 &p_vec4) {
 	x -= p_vec4.x;
 	y -= p_vec4.y;
 	z -= p_vec4.z;
 	w -= p_vec4.w;
 }
 
-void Vector4::operator*=(const Vector4 &p_vec4) {
+constexpr void Vector4::operator*=(const Vector4 &p_vec4) {
 	x *= p_vec4.x;
 	y *= p_vec4.y;
 	z *= p_vec4.z;
 	w *= p_vec4.w;
 }
 
-void Vector4::operator/=(const Vector4 &p_vec4) {
+constexpr void Vector4::operator/=(const Vector4 &p_vec4) {
 	x /= p_vec4.x;
 	y /= p_vec4.y;
 	z /= p_vec4.z;
 	w /= p_vec4.w;
 }
-void Vector4::operator*=(real_t p_s) {
+constexpr void Vector4::operator*=(real_t p_s) {
 	x *= p_s;
 	y *= p_s;
 	z *= p_s;
 	w *= p_s;
 }
 
-void Vector4::operator/=(real_t p_s) {
-	*this *= 1.0f / p_s;
+constexpr void Vector4::operator/=(real_t p_s) {
+	*this *= (1 / p_s);
 }
 
-Vector4 Vector4::operator+(const Vector4 &p_vec4) const {
+constexpr Vector4 Vector4::operator+(const Vector4 &p_vec4) const {
 	return Vector4(x + p_vec4.x, y + p_vec4.y, z + p_vec4.z, w + p_vec4.w);
 }
 
-Vector4 Vector4::operator-(const Vector4 &p_vec4) const {
+constexpr Vector4 Vector4::operator-(const Vector4 &p_vec4) const {
 	return Vector4(x - p_vec4.x, y - p_vec4.y, z - p_vec4.z, w - p_vec4.w);
 }
 
-Vector4 Vector4::operator*(const Vector4 &p_vec4) const {
+constexpr Vector4 Vector4::operator*(const Vector4 &p_vec4) const {
 	return Vector4(x * p_vec4.x, y * p_vec4.y, z * p_vec4.z, w * p_vec4.w);
 }
 
-Vector4 Vector4::operator/(const Vector4 &p_vec4) const {
+constexpr Vector4 Vector4::operator/(const Vector4 &p_vec4) const {
 	return Vector4(x / p_vec4.x, y / p_vec4.y, z / p_vec4.z, w / p_vec4.w);
 }
 
-Vector4 Vector4::operator-() const {
+constexpr Vector4 Vector4::operator-() const {
 	return Vector4(-x, -y, -z, -w);
 }
 
-Vector4 Vector4::operator*(real_t p_s) const {
+constexpr Vector4 Vector4::operator*(real_t p_s) const {
 	return Vector4(x * p_s, y * p_s, z * p_s, w * p_s);
 }
 
-Vector4 Vector4::operator/(real_t p_s) const {
-	return *this * (1.0f / p_s);
+constexpr Vector4 Vector4::operator/(real_t p_s) const {
+	return *this * (1 / p_s);
 }
 
-bool Vector4::operator==(const Vector4 &p_vec4) const {
+constexpr bool Vector4::operator==(const Vector4 &p_vec4) const {
 	return x == p_vec4.x && y == p_vec4.y && z == p_vec4.z && w == p_vec4.w;
 }
 
-bool Vector4::operator!=(const Vector4 &p_vec4) const {
+constexpr bool Vector4::operator!=(const Vector4 &p_vec4) const {
 	return x != p_vec4.x || y != p_vec4.y || z != p_vec4.z || w != p_vec4.w;
 }
 
-bool Vector4::operator<(const Vector4 &p_v) const {
+constexpr bool Vector4::operator<(const Vector4 &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			if (z == p_v.z) {
@@ -248,7 +247,7 @@ bool Vector4::operator<(const Vector4 &p_v) const {
 	return x < p_v.x;
 }
 
-bool Vector4::operator>(const Vector4 &p_v) const {
+constexpr bool Vector4::operator>(const Vector4 &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			if (z == p_v.z) {
@@ -261,7 +260,7 @@ bool Vector4::operator>(const Vector4 &p_v) const {
 	return x > p_v.x;
 }
 
-bool Vector4::operator<=(const Vector4 &p_v) const {
+constexpr bool Vector4::operator<=(const Vector4 &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			if (z == p_v.z) {
@@ -274,7 +273,7 @@ bool Vector4::operator<=(const Vector4 &p_v) const {
 	return x < p_v.x;
 }
 
-bool Vector4::operator>=(const Vector4 &p_v) const {
+constexpr bool Vector4::operator>=(const Vector4 &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			if (z == p_v.z) {
@@ -287,19 +286,19 @@ bool Vector4::operator>=(const Vector4 &p_v) const {
 	return x > p_v.x;
 }
 
-_FORCE_INLINE_ Vector4 operator*(float p_scalar, const Vector4 &p_vec) {
+constexpr Vector4 operator*(float p_scalar, const Vector4 &p_vec) {
 	return p_vec * p_scalar;
 }
 
-_FORCE_INLINE_ Vector4 operator*(double p_scalar, const Vector4 &p_vec) {
+constexpr Vector4 operator*(double p_scalar, const Vector4 &p_vec) {
 	return p_vec * p_scalar;
 }
 
-_FORCE_INLINE_ Vector4 operator*(int32_t p_scalar, const Vector4 &p_vec) {
+constexpr Vector4 operator*(int32_t p_scalar, const Vector4 &p_vec) {
 	return p_vec * p_scalar;
 }
 
-_FORCE_INLINE_ Vector4 operator*(int64_t p_scalar, const Vector4 &p_vec) {
+constexpr Vector4 operator*(int64_t p_scalar, const Vector4 &p_vec) {
 	return p_vec * p_scalar;
 }
 

+ 59 - 60
core/math/vector4i.h

@@ -47,6 +47,7 @@ struct [[nodiscard]] Vector4i {
 	};
 
 	union {
+		// NOLINTBEGIN(modernize-use-default-member-init)
 		struct {
 			int32_t x;
 			int32_t y;
@@ -55,6 +56,7 @@ struct [[nodiscard]] Vector4i {
 		};
 
 		int32_t coord[4] = { 0 };
+		// NOLINTEND(modernize-use-default-member-init)
 	};
 
 	_FORCE_INLINE_ const int32_t &operator[](int p_axis) const {
@@ -103,44 +105,41 @@ struct [[nodiscard]] Vector4i {
 
 	/* Operators */
 
-	_FORCE_INLINE_ Vector4i &operator+=(const Vector4i &p_v);
-	_FORCE_INLINE_ Vector4i operator+(const Vector4i &p_v) const;
-	_FORCE_INLINE_ Vector4i &operator-=(const Vector4i &p_v);
-	_FORCE_INLINE_ Vector4i operator-(const Vector4i &p_v) const;
-	_FORCE_INLINE_ Vector4i &operator*=(const Vector4i &p_v);
-	_FORCE_INLINE_ Vector4i operator*(const Vector4i &p_v) const;
-	_FORCE_INLINE_ Vector4i &operator/=(const Vector4i &p_v);
-	_FORCE_INLINE_ Vector4i operator/(const Vector4i &p_v) const;
-	_FORCE_INLINE_ Vector4i &operator%=(const Vector4i &p_v);
-	_FORCE_INLINE_ Vector4i operator%(const Vector4i &p_v) const;
-
-	_FORCE_INLINE_ Vector4i &operator*=(int32_t p_scalar);
-	_FORCE_INLINE_ Vector4i operator*(int32_t p_scalar) const;
-	_FORCE_INLINE_ Vector4i &operator/=(int32_t p_scalar);
-	_FORCE_INLINE_ Vector4i operator/(int32_t p_scalar) const;
-	_FORCE_INLINE_ Vector4i &operator%=(int32_t p_scalar);
-	_FORCE_INLINE_ Vector4i operator%(int32_t p_scalar) const;
-
-	_FORCE_INLINE_ Vector4i operator-() const;
-
-	_FORCE_INLINE_ bool operator==(const Vector4i &p_v) const;
-	_FORCE_INLINE_ bool operator!=(const Vector4i &p_v) const;
-	_FORCE_INLINE_ bool operator<(const Vector4i &p_v) const;
-	_FORCE_INLINE_ bool operator<=(const Vector4i &p_v) const;
-	_FORCE_INLINE_ bool operator>(const Vector4i &p_v) const;
-	_FORCE_INLINE_ bool operator>=(const Vector4i &p_v) const;
+	constexpr Vector4i &operator+=(const Vector4i &p_v);
+	constexpr Vector4i operator+(const Vector4i &p_v) const;
+	constexpr Vector4i &operator-=(const Vector4i &p_v);
+	constexpr Vector4i operator-(const Vector4i &p_v) const;
+	constexpr Vector4i &operator*=(const Vector4i &p_v);
+	constexpr Vector4i operator*(const Vector4i &p_v) const;
+	constexpr Vector4i &operator/=(const Vector4i &p_v);
+	constexpr Vector4i operator/(const Vector4i &p_v) const;
+	constexpr Vector4i &operator%=(const Vector4i &p_v);
+	constexpr Vector4i operator%(const Vector4i &p_v) const;
+
+	constexpr Vector4i &operator*=(int32_t p_scalar);
+	constexpr Vector4i operator*(int32_t p_scalar) const;
+	constexpr Vector4i &operator/=(int32_t p_scalar);
+	constexpr Vector4i operator/(int32_t p_scalar) const;
+	constexpr Vector4i &operator%=(int32_t p_scalar);
+	constexpr Vector4i operator%(int32_t p_scalar) const;
+
+	constexpr Vector4i operator-() const;
+
+	constexpr bool operator==(const Vector4i &p_v) const;
+	constexpr bool operator!=(const Vector4i &p_v) const;
+	constexpr bool operator<(const Vector4i &p_v) const;
+	constexpr bool operator<=(const Vector4i &p_v) const;
+	constexpr bool operator>(const Vector4i &p_v) const;
+	constexpr bool operator>=(const Vector4i &p_v) const;
 
 	operator String() const;
 	operator Vector4() const;
 
-	_FORCE_INLINE_ Vector4i() {}
+	constexpr Vector4i() :
+			x(0), y(0), z(0), w(0) {}
 	Vector4i(const Vector4 &p_vec4);
-	_FORCE_INLINE_ Vector4i(int32_t p_x, int32_t p_y, int32_t p_z, int32_t p_w) {
-		x = p_x;
-		y = p_y;
-		z = p_z;
-		w = p_w;
-	}
+	constexpr Vector4i(int32_t p_x, int32_t p_y, int32_t p_z, int32_t p_w) :
+			x(p_x), y(p_y), z(p_z), w(p_w) {}
 };
 
 int64_t Vector4i::length_squared() const {
@@ -169,7 +168,7 @@ Vector4i Vector4i::sign() const {
 
 /* Operators */
 
-Vector4i &Vector4i::operator+=(const Vector4i &p_v) {
+constexpr Vector4i &Vector4i::operator+=(const Vector4i &p_v) {
 	x += p_v.x;
 	y += p_v.y;
 	z += p_v.z;
@@ -177,11 +176,11 @@ Vector4i &Vector4i::operator+=(const Vector4i &p_v) {
 	return *this;
 }
 
-Vector4i Vector4i::operator+(const Vector4i &p_v) const {
+constexpr Vector4i Vector4i::operator+(const Vector4i &p_v) const {
 	return Vector4i(x + p_v.x, y + p_v.y, z + p_v.z, w + p_v.w);
 }
 
-Vector4i &Vector4i::operator-=(const Vector4i &p_v) {
+constexpr Vector4i &Vector4i::operator-=(const Vector4i &p_v) {
 	x -= p_v.x;
 	y -= p_v.y;
 	z -= p_v.z;
@@ -189,11 +188,11 @@ Vector4i &Vector4i::operator-=(const Vector4i &p_v) {
 	return *this;
 }
 
-Vector4i Vector4i::operator-(const Vector4i &p_v) const {
+constexpr Vector4i Vector4i::operator-(const Vector4i &p_v) const {
 	return Vector4i(x - p_v.x, y - p_v.y, z - p_v.z, w - p_v.w);
 }
 
-Vector4i &Vector4i::operator*=(const Vector4i &p_v) {
+constexpr Vector4i &Vector4i::operator*=(const Vector4i &p_v) {
 	x *= p_v.x;
 	y *= p_v.y;
 	z *= p_v.z;
@@ -201,11 +200,11 @@ Vector4i &Vector4i::operator*=(const Vector4i &p_v) {
 	return *this;
 }
 
-Vector4i Vector4i::operator*(const Vector4i &p_v) const {
+constexpr Vector4i Vector4i::operator*(const Vector4i &p_v) const {
 	return Vector4i(x * p_v.x, y * p_v.y, z * p_v.z, w * p_v.w);
 }
 
-Vector4i &Vector4i::operator/=(const Vector4i &p_v) {
+constexpr Vector4i &Vector4i::operator/=(const Vector4i &p_v) {
 	x /= p_v.x;
 	y /= p_v.y;
 	z /= p_v.z;
@@ -213,11 +212,11 @@ Vector4i &Vector4i::operator/=(const Vector4i &p_v) {
 	return *this;
 }
 
-Vector4i Vector4i::operator/(const Vector4i &p_v) const {
+constexpr Vector4i Vector4i::operator/(const Vector4i &p_v) const {
 	return Vector4i(x / p_v.x, y / p_v.y, z / p_v.z, w / p_v.w);
 }
 
-Vector4i &Vector4i::operator%=(const Vector4i &p_v) {
+constexpr Vector4i &Vector4i::operator%=(const Vector4i &p_v) {
 	x %= p_v.x;
 	y %= p_v.y;
 	z %= p_v.z;
@@ -225,11 +224,11 @@ Vector4i &Vector4i::operator%=(const Vector4i &p_v) {
 	return *this;
 }
 
-Vector4i Vector4i::operator%(const Vector4i &p_v) const {
+constexpr Vector4i Vector4i::operator%(const Vector4i &p_v) const {
 	return Vector4i(x % p_v.x, y % p_v.y, z % p_v.z, w % p_v.w);
 }
 
-Vector4i &Vector4i::operator*=(int32_t p_scalar) {
+constexpr Vector4i &Vector4i::operator*=(int32_t p_scalar) {
 	x *= p_scalar;
 	y *= p_scalar;
 	z *= p_scalar;
@@ -237,29 +236,29 @@ Vector4i &Vector4i::operator*=(int32_t p_scalar) {
 	return *this;
 }
 
-Vector4i Vector4i::operator*(int32_t p_scalar) const {
+constexpr Vector4i Vector4i::operator*(int32_t p_scalar) const {
 	return Vector4i(x * p_scalar, y * p_scalar, z * p_scalar, w * p_scalar);
 }
 
 // Multiplication operators required to workaround issues with LLVM using implicit conversion.
 
-_FORCE_INLINE_ Vector4i operator*(int32_t p_scalar, const Vector4i &p_vector) {
+constexpr Vector4i operator*(int32_t p_scalar, const Vector4i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-_FORCE_INLINE_ Vector4i operator*(int64_t p_scalar, const Vector4i &p_vector) {
+constexpr Vector4i operator*(int64_t p_scalar, const Vector4i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-_FORCE_INLINE_ Vector4i operator*(float p_scalar, const Vector4i &p_vector) {
+constexpr Vector4i operator*(float p_scalar, const Vector4i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-_FORCE_INLINE_ Vector4i operator*(double p_scalar, const Vector4i &p_vector) {
+constexpr Vector4i operator*(double p_scalar, const Vector4i &p_vector) {
 	return p_vector * p_scalar;
 }
 
-Vector4i &Vector4i::operator/=(int32_t p_scalar) {
+constexpr Vector4i &Vector4i::operator/=(int32_t p_scalar) {
 	x /= p_scalar;
 	y /= p_scalar;
 	z /= p_scalar;
@@ -267,11 +266,11 @@ Vector4i &Vector4i::operator/=(int32_t p_scalar) {
 	return *this;
 }
 
-Vector4i Vector4i::operator/(int32_t p_scalar) const {
+constexpr Vector4i Vector4i::operator/(int32_t p_scalar) const {
 	return Vector4i(x / p_scalar, y / p_scalar, z / p_scalar, w / p_scalar);
 }
 
-Vector4i &Vector4i::operator%=(int32_t p_scalar) {
+constexpr Vector4i &Vector4i::operator%=(int32_t p_scalar) {
 	x %= p_scalar;
 	y %= p_scalar;
 	z %= p_scalar;
@@ -279,23 +278,23 @@ Vector4i &Vector4i::operator%=(int32_t p_scalar) {
 	return *this;
 }
 
-Vector4i Vector4i::operator%(int32_t p_scalar) const {
+constexpr Vector4i Vector4i::operator%(int32_t p_scalar) const {
 	return Vector4i(x % p_scalar, y % p_scalar, z % p_scalar, w % p_scalar);
 }
 
-Vector4i Vector4i::operator-() const {
+constexpr Vector4i Vector4i::operator-() const {
 	return Vector4i(-x, -y, -z, -w);
 }
 
-bool Vector4i::operator==(const Vector4i &p_v) const {
+constexpr bool Vector4i::operator==(const Vector4i &p_v) const {
 	return (x == p_v.x && y == p_v.y && z == p_v.z && w == p_v.w);
 }
 
-bool Vector4i::operator!=(const Vector4i &p_v) const {
+constexpr bool Vector4i::operator!=(const Vector4i &p_v) const {
 	return (x != p_v.x || y != p_v.y || z != p_v.z || w != p_v.w);
 }
 
-bool Vector4i::operator<(const Vector4i &p_v) const {
+constexpr bool Vector4i::operator<(const Vector4i &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			if (z == p_v.z) {
@@ -311,7 +310,7 @@ bool Vector4i::operator<(const Vector4i &p_v) const {
 	}
 }
 
-bool Vector4i::operator>(const Vector4i &p_v) const {
+constexpr bool Vector4i::operator>(const Vector4i &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			if (z == p_v.z) {
@@ -327,7 +326,7 @@ bool Vector4i::operator>(const Vector4i &p_v) const {
 	}
 }
 
-bool Vector4i::operator<=(const Vector4i &p_v) const {
+constexpr bool Vector4i::operator<=(const Vector4i &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			if (z == p_v.z) {
@@ -343,7 +342,7 @@ bool Vector4i::operator<=(const Vector4i &p_v) const {
 	}
 }
 
-bool Vector4i::operator>=(const Vector4i &p_v) const {
+constexpr bool Vector4i::operator>=(const Vector4i &p_v) const {
 	if (x == p_v.x) {
 		if (y == p_v.y) {
 			if (z == p_v.z) {

+ 0 - 1
editor/import/3d/collada.cpp

@@ -208,7 +208,6 @@ Vector<float> Collada::AnimationTrack::get_value_at_time(float p_time) const {
 
 				Vector<float> ret;
 				ret.resize(16);
-				Transform3D tr;
 				// i wonder why collada matrices are transposed, given that's opposed to opengl..
 				ret.write[0] = interp.basis.rows[0][0];
 				ret.write[1] = interp.basis.rows[0][1];

+ 0 - 1
editor/plugins/canvas_item_editor_plugin.cpp

@@ -4872,7 +4872,6 @@ void CanvasItemEditor::_set_owner_for_node_and_children(Node *p_node, Node *p_ow
 }
 
 void CanvasItemEditor::_focus_selection(int p_op) {
-	Vector2 center(0.f, 0.f);
 	Rect2 rect;
 	int count = 0;
 

+ 0 - 1
editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp

@@ -210,7 +210,6 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 
 			Vector3 right, up;
 			Vector3 back(0, 0, -1.0);
-			Vector3 front(0, 0, 0);
 
 			if (aspect == Camera3D::KeepAspect::KEEP_WIDTH) {
 				right = Vector3(keep_size, 0, 0);

+ 1 - 1
editor/plugins/polygon_3d_editor_plugin.cpp

@@ -475,7 +475,7 @@ void Polygon3DEditor::_polygon_draw() {
 		va.resize(poly.size());
 		Vector3 *w = va.ptrw();
 		for (int i = 0; i < poly.size(); i++) {
-			Vector2 p, p2;
+			Vector2 p;
 			p = i == edited_point ? edited_point_pos : poly[i];
 
 			Vector3 point = Vector3(p.x, p.y, depth);

+ 1 - 1
modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.cpp

@@ -112,7 +112,7 @@ bool GodotConeTwistJoint3D::setup(real_t p_timestep) {
 	}
 
 	Vector3 b1Axis1, b1Axis2, b1Axis3;
-	Vector3 b2Axis1, b2Axis2;
+	Vector3 b2Axis1;
 
 	b1Axis1 = A->get_transform().basis.xform(m_rbAFrame.basis.get_column(0));
 	b2Axis1 = B->get_transform().basis.xform(m_rbBFrame.basis.get_column(0));

+ 0 - 1
modules/mobile_vr/mobile_vr_interface.cpp

@@ -135,7 +135,6 @@ void MobileVRInterface::set_position_from_sensors() {
 	// few things we need
 	Input *input = Input::get_singleton();
 	Vector3 down(0.0, -1.0, 0.0); // Down is Y negative
-	Vector3 north(0.0, 0.0, 1.0); // North is Z positive
 
 	// make copies of our inputs
 	bool has_grav = false;

+ 0 - 2
modules/openxr/openxr_api.cpp

@@ -2712,8 +2712,6 @@ Transform3D OpenXRAPI::transform_from_pose(const XrPosef &p_pose) {
 
 template <typename T>
 XRPose::TrackingConfidence _transform_from_location(const T &p_location, Transform3D &r_transform) {
-	Basis basis;
-	Vector3 origin;
 	XRPose::TrackingConfidence confidence = XRPose::XR_TRACKING_CONFIDENCE_NONE;
 	const XrPosef &pose = p_location.pose;
 

+ 0 - 1
platform/android/java_godot_lib_jni.cpp

@@ -79,7 +79,6 @@ enum StartupStep {
 
 static SafeNumeric<int> step; // Shared between UI and render threads
 
-static Size2 new_size;
 static Vector3 accelerometer;
 static Vector3 gravity;
 static Vector3 magnetometer;

+ 0 - 1
scene/gui/label.cpp

@@ -715,7 +715,6 @@ void Label::_notification(int p_what) {
 
 			bool has_settings = settings.is_valid();
 
-			Size2 string_size;
 			Ref<StyleBox> style = theme_cache.normal_style;
 			Ref<Font> font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
 			int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size;

+ 0 - 1
scene/resources/bit_map.cpp

@@ -523,7 +523,6 @@ static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_
 Vector<Vector<Vector2>> BitMap::clip_opaque_to_polygons(const Rect2i &p_rect, float p_epsilon) const {
 	Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect);
 
-	Point2i from;
 	Ref<BitMap> fill;
 	fill.instantiate();
 	fill->create(get_size());

+ 15 - 15
tests/core/math/test_aabb.h

@@ -37,8 +37,8 @@
 namespace TestAABB {
 
 TEST_CASE("[AABB] Constructor methods") {
-	const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
-	const AABB aabb_copy = AABB(aabb);
+	constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
+	constexpr AABB aabb_copy = AABB(aabb);
 
 	CHECK_MESSAGE(
 			aabb == aabb_copy,
@@ -52,7 +52,7 @@ TEST_CASE("[AABB] String conversion") {
 }
 
 TEST_CASE("[AABB] Basic getters") {
-	const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
+	constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
 	CHECK_MESSAGE(
 			aabb.get_position().is_equal_approx(Vector3(-1.5, 2, -2.5)),
 			"get_position() should return the expected value.");
@@ -143,7 +143,7 @@ TEST_CASE("[AABB] Surface getters") {
 }
 
 TEST_CASE("[AABB] Intersection") {
-	const AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
+	constexpr AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
 
 	AABB aabb_small = AABB(Vector3(-1.5, 2, -2.5), Vector3(1, 1, 1));
 	CHECK_MESSAGE(
@@ -229,7 +229,7 @@ TEST_CASE("[AABB] Intersection") {
 			"intersects_ray() should return false for being outside.");
 
 	// Finding ray intersections.
-	const AABB aabb_simple = AABB(Vector3(), Vector3(1, 1, 1));
+	constexpr AABB aabb_simple = AABB(Vector3(), Vector3(1, 1, 1));
 	bool inside = false;
 	Vector3 intersection_point;
 	Vector3 intersection_normal;
@@ -251,7 +251,7 @@ TEST_CASE("[AABB] Intersection") {
 	CHECK_MESSAGE(intersection_normal.is_equal_approx(Vector3(0, -1, 0)), "find_intersects_ray() inside intersection normal incorrect.");
 
 	// Zero sized AABB.
-	const AABB aabb_zero = AABB(Vector3(), Vector3(1, 0, 1));
+	constexpr AABB aabb_zero = AABB(Vector3(), Vector3(1, 0, 1));
 	aabb_zero.find_intersects_ray(Vector3(0.5, 0, 0.5), Vector3(0, 1, 0), inside, &intersection_point, &intersection_normal);
 	CHECK_MESSAGE(inside == false, "find_intersects_ray() should return outside on borders of zero sized AABB.");
 	CHECK_MESSAGE(intersection_point.is_equal_approx(Vector3(0.5, 0, 0.5)), "find_intersects_ray() border intersection point incorrect for zero sized AABB.");
@@ -267,7 +267,7 @@ TEST_CASE("[AABB] Intersection") {
 }
 
 TEST_CASE("[AABB] Merging") {
-	const AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
+	constexpr AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
 
 	AABB aabb_small = AABB(Vector3(-1.5, 2, -2.5), Vector3(1, 1, 1));
 	CHECK_MESSAGE(
@@ -286,7 +286,7 @@ TEST_CASE("[AABB] Merging") {
 }
 
 TEST_CASE("[AABB] Encloses") {
-	const AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
+	constexpr AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
 
 	CHECK_MESSAGE(
 			aabb_big.encloses(aabb_big),
@@ -314,7 +314,7 @@ TEST_CASE("[AABB] Encloses") {
 }
 
 TEST_CASE("[AABB] Get endpoints") {
-	const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
+	constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
 	CHECK_MESSAGE(
 			aabb.get_endpoint(0).is_equal_approx(Vector3(-1.5, 2, -2.5)),
 			"The endpoint at index 0 should match the expected value.");
@@ -351,7 +351,7 @@ TEST_CASE("[AABB] Get endpoints") {
 }
 
 TEST_CASE("[AABB] Get longest/shortest axis") {
-	const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
+	constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
 	CHECK_MESSAGE(
 			aabb.get_longest_axis() == Vector3(0, 0, 1),
 			"get_longest_axis() should return the expected value.");
@@ -374,7 +374,7 @@ TEST_CASE("[AABB] Get longest/shortest axis") {
 }
 
 TEST_CASE("[AABB] Get support") {
-	const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
+	constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
 	CHECK_MESSAGE(
 			aabb.get_support(Vector3(1, 0, 0)) == Vector3(2.5, 2, -2.5),
 			"get_support() should return the expected value.");
@@ -396,7 +396,7 @@ TEST_CASE("[AABB] Get support") {
 }
 
 TEST_CASE("[AABB] Grow") {
-	const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
+	constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
 	CHECK_MESSAGE(
 			aabb.grow(0.25).is_equal_approx(AABB(Vector3(-1.75, 1.75, -2.75), Vector3(4.5, 5.5, 6.5))),
 			"grow() with positive value should return the expected AABB.");
@@ -409,7 +409,7 @@ TEST_CASE("[AABB] Grow") {
 }
 
 TEST_CASE("[AABB] Has point") {
-	const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
+	constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
 	CHECK_MESSAGE(
 			aabb.has_point(Vector3(-1, 3, 0)),
 			"has_point() with contained point should return the expected value.");
@@ -441,7 +441,7 @@ TEST_CASE("[AABB] Has point") {
 }
 
 TEST_CASE("[AABB] Expanding") {
-	const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
+	constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
 	CHECK_MESSAGE(
 			aabb.expand(Vector3(-1, 3, 0)).is_equal_approx(aabb),
 			"expand() with contained point should return the expected AABB.");
@@ -460,7 +460,7 @@ TEST_CASE("[AABB] Expanding") {
 }
 
 TEST_CASE("[AABB] Finite number checks") {
-	const Vector3 x(0, 1, 2);
+	constexpr Vector3 x(0, 1, 2);
 	const Vector3 infinite(NAN, NAN, NAN);
 
 	CHECK_MESSAGE(

+ 1 - 1
tests/core/math/test_astar.h

@@ -214,7 +214,7 @@ TEST_CASE("[AStar3D] Add/Remove") {
 
 TEST_CASE("[Stress][AStar3D] Find paths") {
 	// Random stress tests with Floyd-Warshall.
-	const int N = 30;
+	constexpr int N = 30;
 	Math::seed(0);
 
 	for (int test = 0; test < 1000; test++) {

+ 1 - 1
tests/core/math/test_basis.h

@@ -269,7 +269,7 @@ TEST_CASE("[Basis] Set axis angle") {
 }
 
 TEST_CASE("[Basis] Finite number checks") {
-	const Vector3 x(0, 1, 2);
+	constexpr Vector3 x(0, 1, 2);
 	const Vector3 infinite(NAN, NAN, NAN);
 
 	CHECK_MESSAGE(

+ 12 - 12
tests/core/math/test_color.h

@@ -37,7 +37,7 @@
 namespace TestColor {
 
 TEST_CASE("[Color] Constructor methods") {
-	const Color blue_rgba = Color(0.25098, 0.376471, 1, 0.501961);
+	constexpr Color blue_rgba = Color(0.25098, 0.376471, 1, 0.501961);
 	const Color blue_html = Color::html("#4060ff80");
 	const Color blue_hex = Color::hex(0x4060ff80);
 	const Color blue_hex64 = Color::hex64(0x4040'6060'ffff'8080);
@@ -60,7 +60,7 @@ TEST_CASE("[Color] Constructor methods") {
 			html_invalid.is_equal_approx(Color()),
 			"Creation with invalid HTML notation should result in a Color with the default values.");
 
-	const Color green_rgba = Color(0, 1, 0, 0.25);
+	constexpr Color green_rgba = Color(0, 1, 0, 0.25);
 	const Color green_hsva = Color(0, 0, 0).from_hsv(120 / 360.0, 1, 1, 0.25);
 
 	CHECK_MESSAGE(
@@ -69,8 +69,8 @@ TEST_CASE("[Color] Constructor methods") {
 }
 
 TEST_CASE("[Color] Operators") {
-	const Color blue = Color(0.2, 0.2, 1);
-	const Color dark_red = Color(0.3, 0.1, 0.1);
+	constexpr Color blue = Color(0.2, 0.2, 1);
+	constexpr Color dark_red = Color(0.3, 0.1, 0.1);
 
 	// Color components may be negative. Also, the alpha component may be greater than 1.0.
 	CHECK_MESSAGE(
@@ -97,7 +97,7 @@ TEST_CASE("[Color] Operators") {
 }
 
 TEST_CASE("[Color] Reading methods") {
-	const Color dark_blue = Color(0, 0, 0.5, 0.4);
+	constexpr Color dark_blue = Color(0, 0, 0.5, 0.4);
 
 	CHECK_MESSAGE(
 			dark_blue.get_h() == doctest::Approx(240.0f / 360.0f),
@@ -111,8 +111,8 @@ TEST_CASE("[Color] Reading methods") {
 }
 
 TEST_CASE("[Color] Conversion methods") {
-	const Color cyan = Color(0, 1, 1);
-	const Color cyan_transparent = Color(0, 1, 1, 0);
+	constexpr Color cyan = Color(0, 1, 1);
+	constexpr Color cyan_transparent = Color(0, 1, 1, 0);
 
 	CHECK_MESSAGE(
 			cyan.to_html() == "00ffffff",
@@ -144,7 +144,7 @@ TEST_CASE("[Color] Conversion methods") {
 }
 
 TEST_CASE("[Color] Linear <-> sRGB conversion") {
-	const Color color = Color(0.35, 0.5, 0.6, 0.7);
+	constexpr Color color = Color(0.35, 0.5, 0.6, 0.7);
 	const Color color_linear = color.srgb_to_linear();
 	const Color color_srgb = color.linear_to_srgb();
 	CHECK_MESSAGE(
@@ -203,13 +203,13 @@ TEST_CASE("[Color] Validation methods") {
 }
 
 TEST_CASE("[Color] Manipulation methods") {
-	const Color blue = Color(0, 0, 1, 0.4);
+	constexpr Color blue = Color(0, 0, 1, 0.4);
 
 	CHECK_MESSAGE(
 			blue.inverted().is_equal_approx(Color(1, 1, 0, 0.4)),
 			"Inverted color should have its red, green and blue components inverted.");
 
-	const Color purple = Color(0.5, 0.2, 0.5, 0.25);
+	constexpr Color purple = Color(0.5, 0.2, 0.5, 0.25);
 
 	CHECK_MESSAGE(
 			purple.lightened(0.2).is_equal_approx(Color(0.6, 0.36, 0.6, 0.25)),
@@ -218,8 +218,8 @@ TEST_CASE("[Color] Manipulation methods") {
 			purple.darkened(0.2).is_equal_approx(Color(0.4, 0.16, 0.4, 0.25)),
 			"Color should be darkened by the expected amount.");
 
-	const Color red = Color(1, 0, 0, 0.2);
-	const Color yellow = Color(1, 1, 0, 0.8);
+	constexpr Color red = Color(1, 0, 0, 0.2);
+	constexpr Color yellow = Color(1, 1, 0, 0.8);
 
 	CHECK_MESSAGE(
 			red.lerp(yellow, 0.5).is_equal_approx(Color(1, 0.5, 0, 0.5)),

+ 8 - 8
tests/core/math/test_geometry_2d.h

@@ -163,11 +163,11 @@ TEST_CASE("[Geometry2D] Segment intersection") {
 }
 
 TEST_CASE("[Geometry2D] Segment intersection with circle") {
-	real_t minus_one = -1.0;
-	real_t zero = 0.0;
-	real_t one_quarter = 0.25;
-	real_t three_quarters = 0.75;
-	real_t one = 1.0;
+	constexpr real_t minus_one = -1.0;
+	constexpr real_t zero = 0.0;
+	constexpr real_t one_quarter = 0.25;
+	constexpr real_t three_quarters = 0.75;
+	constexpr real_t one = 1.0;
 
 	CHECK_MESSAGE(
 			Geometry2D::segment_intersects_circle(Vector2(0, 0), Vector2(4, 0), Vector2(0, 0), 1.0) == doctest::Approx(one_quarter),
@@ -261,19 +261,19 @@ TEST_CASE("[Geometry2D] Segment intersection with polygon") {
 }
 
 TEST_CASE("[Geometry2D] Closest point to segment") {
-	Vector2 s[] = { Vector2(-4, -4), Vector2(4, 4) };
+	constexpr Vector2 s[] = { Vector2(-4, -4), Vector2(4, 4) };
 	CHECK(Geometry2D::get_closest_point_to_segment(Vector2(4.1, 4.1), s).is_equal_approx(Vector2(4, 4)));
 	CHECK(Geometry2D::get_closest_point_to_segment(Vector2(-4.1, -4.1), s).is_equal_approx(Vector2(-4, -4)));
 	CHECK(Geometry2D::get_closest_point_to_segment(Vector2(-1, 1), s).is_equal_approx(Vector2(0, 0)));
 
-	Vector2 t[] = { Vector2(1, -2), Vector2(1, -2) };
+	constexpr Vector2 t[] = { Vector2(1, -2), Vector2(1, -2) };
 	CHECK_MESSAGE(
 			Geometry2D::get_closest_point_to_segment(Vector2(-3, 4), t).is_equal_approx(Vector2(1, -2)),
 			"Line segment is only a single point. This point should be the closest.");
 }
 
 TEST_CASE("[Geometry2D] Closest point to uncapped segment") {
-	Vector2 s[] = { Vector2(-4, -4), Vector2(4, 4) };
+	constexpr Vector2 s[] = { Vector2(-4, -4), Vector2(4, 4) };
 	CHECK(Geometry2D::get_closest_point_to_segment_uncapped(Vector2(-1, 1), s).is_equal_approx(Vector2(0, 0)));
 	CHECK(Geometry2D::get_closest_point_to_segment_uncapped(Vector2(-4, -6), s).is_equal_approx(Vector2(-5, -5)));
 	CHECK(Geometry2D::get_closest_point_to_segment_uncapped(Vector2(4, 6), s).is_equal_approx(Vector2(5, 5)));

+ 4 - 4
tests/core/math/test_geometry_3d.h

@@ -46,7 +46,7 @@ TEST_CASE("[Geometry3D] Closest Distance Between Segments") {
 }
 
 TEST_CASE("[Geometry3D] Build Box Planes") {
-	const Vector3 extents = Vector3(5, 5, 20);
+	constexpr Vector3 extents = Vector3(5, 5, 20);
 	Vector<Plane> box = Geometry3D::build_box_planes(extents);
 	CHECK(box.size() == 6);
 	CHECK(extents.x == box[0].d);
@@ -129,7 +129,7 @@ TEST_CASE("[Geometry3D] Compute Convex Mesh Points") {
 }
 
 TEST_CASE("[Geometry3D] Get Closest Point To Segment") {
-	Vector3 segment[2] = { Vector3(1, 1, 1), Vector3(5, 5, 5) };
+	constexpr Vector3 segment[2] = { Vector3(1, 1, 1), Vector3(5, 5, 5) };
 	Vector3 output = Geometry3D::get_closest_point_to_segment(Vector3(2, 1, 4), segment);
 	CHECK(output.is_equal_approx(Vector3(2.33333, 2.33333, 2.33333)));
 }
@@ -182,9 +182,9 @@ TEST_CASE("[Geometry3D] Segment Intersects Triangle") {
 }
 
 TEST_CASE("[Geometry3D] Triangle and Box Overlap") {
-	Vector3 good_triangle[3] = { Vector3(3, 2, 3), Vector3(2, 2, 1), Vector3(2, 1, 1) };
+	constexpr Vector3 good_triangle[3] = { Vector3(3, 2, 3), Vector3(2, 2, 1), Vector3(2, 1, 1) };
 	CHECK(Geometry3D::triangle_box_overlap(Vector3(0, 0, 0), Vector3(5, 5, 5), good_triangle) == true);
-	Vector3 bad_triangle[3] = { Vector3(100, 100, 100), Vector3(-100, -100, -100), Vector3(10, 10, 10) };
+	constexpr Vector3 bad_triangle[3] = { Vector3(100, 100, 100), Vector3(-100, -100, -100), Vector3(10, 10, 10) };
 	CHECK(Geometry3D::triangle_box_overlap(Vector3(1000, 1000, 1000), Vector3(1, 1, 1), bad_triangle) == false);
 }
 

+ 22 - 22
tests/core/math/test_plane.h

@@ -39,22 +39,22 @@ namespace TestPlane {
 // Plane
 
 TEST_CASE("[Plane] Constructor methods") {
-	const Plane plane = Plane(32, 22, 16, 3);
-	const Plane plane_vector = Plane(Vector3(32, 22, 16), 3);
-	const Plane plane_copy_plane = Plane(plane);
+	constexpr Plane plane = Plane(32, 22, 16, 3);
+	constexpr Plane plane_vector = Plane(Vector3(32, 22, 16), 3);
+	constexpr Plane plane_copy_plane = Plane(plane);
 
-	CHECK_MESSAGE(
+	static_assert(
 			plane == plane_vector,
 			"Planes created with same values but different methods should be equal.");
 
-	CHECK_MESSAGE(
+	static_assert(
 			plane == plane_copy_plane,
 			"Planes created with same values but different methods should be equal.");
 }
 
 TEST_CASE("[Plane] Basic getters") {
-	const Plane plane = Plane(32, 22, 16, 3);
-	const Plane plane_normalized = Plane(32.0 / 42, 22.0 / 42, 16.0 / 42, 3.0 / 42);
+	constexpr Plane plane = Plane(32, 22, 16, 3);
+	constexpr Plane plane_normalized = Plane(32.0 / 42, 22.0 / 42, 16.0 / 42, 3.0 / 42);
 
 	CHECK_MESSAGE(
 			plane.get_normal().is_equal_approx(Vector3(32, 22, 16)),
@@ -82,8 +82,8 @@ TEST_CASE("[Plane] Basic setters") {
 }
 
 TEST_CASE("[Plane] Plane-point operations") {
-	const Plane plane = Plane(32, 22, 16, 3);
-	const Plane y_facing_plane = Plane(0, 1, 0, 4);
+	constexpr Plane plane = Plane(32, 22, 16, 3);
+	constexpr Plane y_facing_plane = Plane(0, 1, 0, 4);
 
 	CHECK_MESSAGE(
 			plane.get_center().is_equal_approx(Vector3(32 * 3, 22 * 3, 16 * 3)),
@@ -101,16 +101,16 @@ TEST_CASE("[Plane] Plane-point operations") {
 }
 
 TEST_CASE("[Plane] Has point") {
-	const Plane x_facing_plane = Plane(1, 0, 0, 0);
-	const Plane y_facing_plane = Plane(0, 1, 0, 0);
-	const Plane z_facing_plane = Plane(0, 0, 1, 0);
+	constexpr Plane x_facing_plane = Plane(1, 0, 0, 0);
+	constexpr Plane y_facing_plane = Plane(0, 1, 0, 0);
+	constexpr Plane z_facing_plane = Plane(0, 0, 1, 0);
 
-	const Vector3 x_axis_point = Vector3(10, 0, 0);
-	const Vector3 y_axis_point = Vector3(0, 10, 0);
-	const Vector3 z_axis_point = Vector3(0, 0, 10);
+	constexpr Vector3 x_axis_point = Vector3(10, 0, 0);
+	constexpr Vector3 y_axis_point = Vector3(0, 10, 0);
+	constexpr Vector3 z_axis_point = Vector3(0, 0, 10);
 
-	const Plane x_facing_plane_with_d_offset = Plane(1, 0, 0, 1);
-	const Vector3 y_axis_point_with_d_offset = Vector3(1, 10, 0);
+	constexpr Plane x_facing_plane_with_d_offset = Plane(1, 0, 0, 1);
+	constexpr Vector3 y_axis_point_with_d_offset = Vector3(1, 10, 0);
 
 	CHECK_MESSAGE(
 			x_facing_plane.has_point(y_axis_point),
@@ -139,9 +139,9 @@ TEST_CASE("[Plane] Has point") {
 }
 
 TEST_CASE("[Plane] Intersection") {
-	const Plane x_facing_plane = Plane(1, 0, 0, 1);
-	const Plane y_facing_plane = Plane(0, 1, 0, 2);
-	const Plane z_facing_plane = Plane(0, 0, 1, 3);
+	constexpr Plane x_facing_plane = Plane(1, 0, 0, 1);
+	constexpr Plane y_facing_plane = Plane(0, 1, 0, 2);
+	constexpr Plane z_facing_plane = Plane(0, 0, 1, 3);
 
 	Vector3 vec_out;
 
@@ -168,9 +168,9 @@ TEST_CASE("[Plane] Intersection") {
 }
 
 TEST_CASE("[Plane] Finite number checks") {
-	const Vector3 x(0, 1, 2);
+	constexpr Vector3 x(0, 1, 2);
 	const Vector3 infinite_vec(NAN, NAN, NAN);
-	const real_t y = 0;
+	constexpr real_t y = 0;
 	const real_t infinite_y = NAN;
 
 	CHECK_MESSAGE(

+ 0 - 6
tests/core/math/test_projection.h

@@ -182,12 +182,6 @@ TEST_CASE("[Projection] Vector transformation") {
 			Vector4(4, 7, 11, 15),
 			Vector4(4, 8, 12, 16));
 
-	Projection inverse(
-			Vector4(-4.0 / 12, 0, 1, -8.0 / 12),
-			Vector4(8.0 / 12, -1, -1, 16.0 / 12),
-			Vector4(-20.0 / 12, 2, -1, 5.0 / 12),
-			Vector4(1, -1, 1, -0.75));
-
 	Vector4 vec4(1, 2, 3, 4);
 	CHECK(proj.xform(vec4).is_equal_approx(Vector4(33, 70, 112, 152)));
 	CHECK(proj.xform_inv(vec4).is_equal_approx(Vector4(90, 107, 111, 120)));

+ 27 - 27
tests/core/math/test_quaternion.h

@@ -56,7 +56,7 @@ Quaternion quat_euler_yxz_deg(Vector3 angle) {
 }
 
 TEST_CASE("[Quaternion] Default Construct") {
-	Quaternion q;
+	constexpr Quaternion q;
 
 	CHECK(q[0] == 0.0);
 	CHECK(q[1] == 0.0);
@@ -66,7 +66,7 @@ TEST_CASE("[Quaternion] Default Construct") {
 
 TEST_CASE("[Quaternion] Construct x,y,z,w") {
 	// Values are taken from actual use in another project & are valid (except roundoff error).
-	Quaternion q(0.2391, 0.099, 0.3696, 0.8924);
+	constexpr Quaternion q(0.2391, 0.099, 0.3696, 0.8924);
 
 	CHECK(q[0] == doctest::Approx(0.2391));
 	CHECK(q[1] == doctest::Approx(0.099));
@@ -107,7 +107,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 3") {
 
 TEST_CASE("[Quaternion] Construct AxisAngle 4") {
 	// More complex & hard to visualize, so test w/ data from online calculator.
-	Vector3 axis(1.0, 2.0, 0.5);
+	constexpr Vector3 axis(1.0, 2.0, 0.5);
 	Quaternion q(axis.normalized(), Math::deg_to_rad(35.0));
 
 	CHECK(q[0] == doctest::Approx(0.131239));
@@ -117,7 +117,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 4") {
 }
 
 TEST_CASE("[Quaternion] Construct from Quaternion") {
-	Vector3 axis(1.0, 2.0, 0.5);
+	constexpr Vector3 axis(1.0, 2.0, 0.5);
 	Quaternion q_src(axis.normalized(), Math::deg_to_rad(35.0));
 	Quaternion q(q_src);
 
@@ -198,17 +198,17 @@ TEST_CASE("[Quaternion] Construct Basis Euler") {
 
 TEST_CASE("[Quaternion] Construct Basis Axes") {
 	// Arbitrary Euler angles.
-	Vector3 euler_yxz(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34));
+	const Vector3 euler_yxz(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34));
 	// Basis vectors from online calculation of rotation matrix.
-	Vector3 i_unit(0.5545787, 0.1823950, 0.8118957);
-	Vector3 j_unit(-0.5249245, 0.8337420, 0.1712555);
-	Vector3 k_unit(-0.6456754, -0.5211586, 0.5581192);
+	constexpr Vector3 i_unit(0.5545787, 0.1823950, 0.8118957);
+	constexpr Vector3 j_unit(-0.5249245, 0.8337420, 0.1712555);
+	constexpr Vector3 k_unit(-0.6456754, -0.5211586, 0.5581192);
 	// Quaternion from online calculation.
-	Quaternion q_calc(0.2016913, -0.4245716, 0.206033, 0.8582598);
+	constexpr Quaternion q_calc(0.2016913, -0.4245716, 0.206033, 0.8582598);
 	// Quaternion from local calculation.
-	Quaternion q_local = quat_euler_yxz_deg(Vector3(31.41, -49.16, 12.34));
+	const Quaternion q_local = quat_euler_yxz_deg(Vector3(31.41, -49.16, 12.34));
 	// Quaternion from Euler angles constructor.
-	Quaternion q_euler = Quaternion::from_euler(euler_yxz);
+	const Quaternion q_euler = Quaternion::from_euler(euler_yxz);
 	CHECK(q_calc.is_equal_approx(q_local));
 	CHECK(q_local.is_equal_approx(q_euler));
 
@@ -286,10 +286,10 @@ TEST_CASE("[Quaternion] Get Euler Orders") {
 
 TEST_CASE("[Quaternion] Product (book)") {
 	// Example from "Quaternions and Rotation Sequences" by Jack Kuipers, p. 108.
-	Quaternion p(1.0, -2.0, 1.0, 3.0);
-	Quaternion q(-1.0, 2.0, 3.0, 2.0);
+	constexpr Quaternion p(1.0, -2.0, 1.0, 3.0);
+	constexpr Quaternion q(-1.0, 2.0, 3.0, 2.0);
 
-	Quaternion pq = p * q;
+	constexpr Quaternion pq = p * q;
 	CHECK(pq[0] == doctest::Approx(-9.0));
 	CHECK(pq[1] == doctest::Approx(-2.0));
 	CHECK(pq[2] == doctest::Approx(11.0));
@@ -382,13 +382,13 @@ TEST_CASE("[Quaternion] xform unit vectors") {
 
 TEST_CASE("[Quaternion] xform vector") {
 	// Arbitrary quaternion rotates an arbitrary vector.
-	Vector3 euler_yzx(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34));
-	Basis basis_axes = Basis::from_euler(euler_yzx);
-	Quaternion q(basis_axes);
+	const Vector3 euler_yzx(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34));
+	const Basis basis_axes = Basis::from_euler(euler_yzx);
+	const Quaternion q(basis_axes);
 
-	Vector3 v_arb(3.0, 4.0, 5.0);
-	Vector3 v_rot = q.xform(v_arb);
-	Vector3 v_compare = basis_axes.xform(v_arb);
+	constexpr Vector3 v_arb(3.0, 4.0, 5.0);
+	const Vector3 v_rot = q.xform(v_arb);
+	const Vector3 v_compare = basis_axes.xform(v_arb);
 
 	CHECK(v_rot.length_squared() == doctest::Approx(v_arb.length_squared()));
 	CHECK(v_rot.is_equal_approx(v_compare));
@@ -396,11 +396,11 @@ TEST_CASE("[Quaternion] xform vector") {
 
 // Test vector xform for a single combination of Quaternion and Vector.
 void test_quat_vec_rotate(Vector3 euler_yzx, Vector3 v_in) {
-	Basis basis_axes = Basis::from_euler(euler_yzx);
-	Quaternion q(basis_axes);
+	const Basis basis_axes = Basis::from_euler(euler_yzx);
+	const Quaternion q(basis_axes);
 
-	Vector3 v_rot = q.xform(v_in);
-	Vector3 v_compare = basis_axes.xform(v_in);
+	const Vector3 v_rot = q.xform(v_in);
+	const Vector3 v_compare = basis_axes.xform(v_in);
 
 	CHECK(v_rot.length_squared() == doctest::Approx(v_in.length_squared()));
 	CHECK(v_rot.is_equal_approx(v_compare));
@@ -410,9 +410,9 @@ TEST_CASE("[Stress][Quaternion] Many vector xforms") {
 	// Many arbitrary quaternions rotate many arbitrary vectors.
 	// For each trial, check that rotation by Quaternion yields same result as
 	// rotation by Basis.
-	const int STEPS = 100; // Number of test steps in each dimension
-	const double delta = 2.0 * Math_PI / STEPS; // Angle increment per step
-	const double delta_vec = 20.0 / STEPS; // Vector increment per step
+	constexpr int STEPS = 100; // Number of test steps in each dimension
+	constexpr double delta = 2.0 * Math_PI / STEPS; // Angle increment per step
+	constexpr double delta_vec = 20.0 / STEPS; // Vector increment per step
 	Vector3 vec_arb(1.0, 1.0, 1.0);
 	double x_angle = -Math_PI;
 	double y_angle = -Math_PI;

+ 7 - 7
tests/core/math/test_rect2.h

@@ -37,15 +37,15 @@
 
 namespace TestRect2 {
 TEST_CASE("[Rect2] Constructor methods") {
-	const Rect2 rect = Rect2(0, 100, 1280, 720);
-	const Rect2 rect_vector = Rect2(Vector2(0, 100), Vector2(1280, 720));
-	const Rect2 rect_copy_rect = Rect2(rect);
+	constexpr Rect2 rect = Rect2(0, 100, 1280, 720);
+	constexpr Rect2 rect_vector = Rect2(Vector2(0, 100), Vector2(1280, 720));
+	constexpr Rect2 rect_copy_rect = Rect2(rect);
 	const Rect2 rect_copy_recti = Rect2(Rect2i(0, 100, 1280, 720));
 
-	CHECK_MESSAGE(
+	static_assert(
 			rect == rect_vector,
 			"Rect2s created with the same dimensions but by different methods should be equal.");
-	CHECK_MESSAGE(
+	static_assert(
 			rect == rect_copy_rect,
 			"Rect2s created with the same dimensions but by different methods should be equal.");
 	CHECK_MESSAGE(
@@ -61,7 +61,7 @@ TEST_CASE("[Rect2] String conversion") {
 }
 
 TEST_CASE("[Rect2] Basic getters") {
-	const Rect2 rect = Rect2(0, 100, 1280, 720);
+	constexpr Rect2 rect = Rect2(0, 100, 1280, 720);
 	CHECK_MESSAGE(
 			rect.get_position().is_equal_approx(Vector2(0, 100)),
 			"get_position() should return the expected value.");
@@ -180,7 +180,7 @@ TEST_CASE("[Rect2] Expanding") {
 }
 
 TEST_CASE("[Rect2] Get support") {
-	const Rect2 rect = Rect2(Vector2(-1.5, 2), Vector2(4, 5));
+	constexpr Rect2 rect = Rect2(Vector2(-1.5, 2), Vector2(4, 5));
 	CHECK_MESSAGE(
 			rect.get_support(Vector2(1, 0)) == Vector2(2.5, 2),
 			"get_support() should return the expected value.");

+ 7 - 7
tests/core/math/test_rect2i.h

@@ -37,15 +37,15 @@
 
 namespace TestRect2i {
 TEST_CASE("[Rect2i] Constructor methods") {
-	Rect2i recti = Rect2i(0, 100, 1280, 720);
-	Rect2i recti_vector = Rect2i(Vector2i(0, 100), Vector2i(1280, 720));
-	Rect2i recti_copy_recti = Rect2i(recti);
-	Rect2i recti_copy_rect = Rect2i(Rect2(0, 100, 1280, 720));
+	constexpr Rect2i recti = Rect2i(0, 100, 1280, 720);
+	constexpr Rect2i recti_vector = Rect2i(Vector2i(0, 100), Vector2i(1280, 720));
+	constexpr Rect2i recti_copy_recti = Rect2i(recti);
+	const Rect2i recti_copy_rect = Rect2i(Rect2(0, 100, 1280, 720));
 
-	CHECK_MESSAGE(
+	static_assert(
 			recti == recti_vector,
 			"Rect2is created with the same dimensions but by different methods should be equal.");
-	CHECK_MESSAGE(
+	static_assert(
 			recti == recti_copy_recti,
 			"Rect2is created with the same dimensions but by different methods should be equal.");
 	CHECK_MESSAGE(
@@ -61,7 +61,7 @@ TEST_CASE("[Rect2i] String conversion") {
 }
 
 TEST_CASE("[Rect2i] Basic getters") {
-	const Rect2i rect = Rect2i(0, 100, 1280, 720);
+	constexpr Rect2i rect = Rect2i(0, 100, 1280, 720);
 	CHECK_MESSAGE(
 			rect.get_position() == Vector2i(0, 100),
 			"get_position() should return the expected value.");

+ 15 - 15
tests/core/math/test_transform_2d.h

@@ -57,7 +57,7 @@ TEST_CASE("[Transform2D] Copy constructor") {
 
 TEST_CASE("[Transform2D] Constructor from angle and position") {
 	constexpr float ROTATION = Math_PI / 4;
-	const Vector2 TRANSLATION = Vector2(20, -20);
+	constexpr Vector2 TRANSLATION = Vector2(20, -20);
 
 	const Transform2D test = Transform2D(ROTATION, TRANSLATION);
 	const Transform2D expected = Transform2D().rotated(ROTATION).translated(TRANSLATION);
@@ -66,9 +66,9 @@ TEST_CASE("[Transform2D] Constructor from angle and position") {
 
 TEST_CASE("[Transform2D] Constructor from angle, scale, skew and position") {
 	constexpr float ROTATION = Math_PI / 2;
-	const Vector2 SCALE = Vector2(2, 0.5);
+	constexpr Vector2 SCALE = Vector2(2, 0.5);
 	constexpr float SKEW = Math_PI / 4;
-	const Vector2 TRANSLATION = Vector2(30, 0);
+	constexpr Vector2 TRANSLATION = Vector2(30, 0);
 
 	const Transform2D test = Transform2D(ROTATION, SCALE, SKEW, TRANSLATION);
 	Transform2D expected = Transform2D().scaled(SCALE).rotated(ROTATION).translated(TRANSLATION);
@@ -78,26 +78,26 @@ TEST_CASE("[Transform2D] Constructor from angle, scale, skew and position") {
 }
 
 TEST_CASE("[Transform2D] Constructor from raw values") {
-	const Transform2D test = Transform2D(1, 2, 3, 4, 5, 6);
-	const Transform2D expected = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6));
-	CHECK(test == expected);
+	constexpr Transform2D test = Transform2D(1, 2, 3, 4, 5, 6);
+	constexpr Transform2D expected = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6));
+	static_assert(test == expected);
 }
 
 TEST_CASE("[Transform2D] xform") {
-	const Vector2 v = Vector2(2, 3);
-	const Transform2D T = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6));
-	const Vector2 expected = Vector2(1 * 2 + 3 * 3 + 5 * 1, 2 * 2 + 4 * 3 + 6 * 1);
+	constexpr Vector2 v = Vector2(2, 3);
+	constexpr Transform2D T = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6));
+	constexpr Vector2 expected = Vector2(1 * 2 + 3 * 3 + 5 * 1, 2 * 2 + 4 * 3 + 6 * 1);
 	CHECK(T.xform(v) == expected);
 }
 
 TEST_CASE("[Transform2D] Basis xform") {
-	const Vector2 v = Vector2(2, 2);
-	const Transform2D T1 = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(0, 0));
+	constexpr Vector2 v = Vector2(2, 2);
+	constexpr Transform2D T1 = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(0, 0));
 
 	// Both versions should be the same when the origin is (0,0).
 	CHECK(T1.basis_xform(v) == T1.xform(v));
 
-	const Transform2D T2 = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6));
+	constexpr Transform2D T2 = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6));
 
 	// Each version should be different when the origin is not (0,0).
 	CHECK_FALSE(T2.basis_xform(v) == T2.xform(v));
@@ -129,7 +129,7 @@ TEST_CASE("[Transform2D] Orthonormalized") {
 }
 
 TEST_CASE("[Transform2D] translation") {
-	const Vector2 offset = Vector2(1, 2);
+	constexpr Vector2 offset = Vector2(1, 2);
 
 	// Both versions should give the same result applied to identity.
 	CHECK(identity().translated(offset) == identity().translated_local(offset));
@@ -142,7 +142,7 @@ TEST_CASE("[Transform2D] translation") {
 }
 
 TEST_CASE("[Transform2D] scaling") {
-	const Vector2 scaling = Vector2(1, 2);
+	constexpr Vector2 scaling = Vector2(1, 2);
 
 	// Both versions should give the same result applied to identity.
 	CHECK(identity().scaled(scaling) == identity().scaled_local(scaling));
@@ -181,7 +181,7 @@ TEST_CASE("[Transform2D] Interpolation") {
 }
 
 TEST_CASE("[Transform2D] Finite number checks") {
-	const Vector2 x = Vector2(0, 1);
+	constexpr Vector2 x = Vector2(0, 1);
 	const Vector2 infinite = Vector2(NAN, NAN);
 
 	CHECK_MESSAGE(

+ 6 - 6
tests/core/math/test_transform_3d.h

@@ -45,7 +45,7 @@ Transform3D identity() {
 }
 
 TEST_CASE("[Transform3D] translation") {
-	Vector3 offset = Vector3(1, 2, 3);
+	constexpr Vector3 offset = Vector3(1, 2, 3);
 
 	// Both versions should give the same result applied to identity.
 	CHECK(identity().translated(offset) == identity().translated_local(offset));
@@ -58,7 +58,7 @@ TEST_CASE("[Transform3D] translation") {
 }
 
 TEST_CASE("[Transform3D] scaling") {
-	Vector3 scaling = Vector3(1, 2, 3);
+	constexpr Vector3 scaling = Vector3(1, 2, 3);
 
 	// Both versions should give the same result applied to identity.
 	CHECK(identity().scaled(scaling) == identity().scaled_local(scaling));
@@ -71,8 +71,8 @@ TEST_CASE("[Transform3D] scaling") {
 }
 
 TEST_CASE("[Transform3D] rotation") {
-	Vector3 axis = Vector3(1, 2, 3).normalized();
-	real_t phi = 1.0;
+	const Vector3 axis = Vector3(1, 2, 3).normalized();
+	constexpr real_t phi = 1.0;
 
 	// Both versions should give the same result applied to identity.
 	CHECK(identity().rotated(axis, phi) == identity().rotated_local(axis, phi));
@@ -85,9 +85,9 @@ TEST_CASE("[Transform3D] rotation") {
 }
 
 TEST_CASE("[Transform3D] Finite number checks") {
-	const Vector3 y(0, 1, 2);
+	constexpr Vector3 y(0, 1, 2);
 	const Vector3 infinite_vec(NAN, NAN, NAN);
-	const Basis x(y, y, y);
+	constexpr Basis x(y, y, y);
 	const Basis infinite_basis(infinite_vec, infinite_vec, infinite_vec);
 
 	CHECK_MESSAGE(

+ 40 - 40
tests/core/math/test_vector2.h

@@ -37,16 +37,16 @@
 namespace TestVector2 {
 
 TEST_CASE("[Vector2] Constructor methods") {
-	const Vector2 vector_empty = Vector2();
-	const Vector2 vector_zero = Vector2(0.0, 0.0);
-	CHECK_MESSAGE(
+	constexpr Vector2 vector_empty = Vector2();
+	constexpr Vector2 vector_zero = Vector2(0.0, 0.0);
+	static_assert(
 			vector_empty == vector_zero,
 			"Vector2 Constructor with no inputs should return a zero Vector2.");
 }
 
 TEST_CASE("[Vector2] Angle methods") {
-	const Vector2 vector_x = Vector2(1, 0);
-	const Vector2 vector_y = Vector2(0, 1);
+	constexpr Vector2 vector_x = Vector2(1, 0);
+	constexpr Vector2 vector_y = Vector2(0, 1);
 	CHECK_MESSAGE(
 			vector_x.angle_to(vector_y) == doctest::Approx((real_t)Math_TAU / 4),
 			"Vector2 angle_to should work as expected.");
@@ -79,8 +79,8 @@ TEST_CASE("[Vector2] Axis methods") {
 }
 
 TEST_CASE("[Vector2] Interpolation methods") {
-	const Vector2 vector1 = Vector2(1, 2);
-	const Vector2 vector2 = Vector2(4, 5);
+	constexpr Vector2 vector1 = Vector2(1, 2);
+	constexpr Vector2 vector2 = Vector2(4, 5);
 	CHECK_MESSAGE(
 			vector1.lerp(vector2, 0.5) == Vector2(2.5, 3.5),
 			"Vector2 lerp should work as expected.");
@@ -129,8 +129,8 @@ TEST_CASE("[Vector2] Interpolation methods") {
 }
 
 TEST_CASE("[Vector2] Length methods") {
-	const Vector2 vector1 = Vector2(10, 10);
-	const Vector2 vector2 = Vector2(20, 30);
+	constexpr Vector2 vector1 = Vector2(10, 10);
+	constexpr Vector2 vector2 = Vector2(20, 30);
 	CHECK_MESSAGE(
 			vector1.length_squared() == 200,
 			"Vector2 length_squared should work as expected and return exact result.");
@@ -152,7 +152,7 @@ TEST_CASE("[Vector2] Length methods") {
 }
 
 TEST_CASE("[Vector2] Limiting methods") {
-	const Vector2 vector = Vector2(10, 10);
+	constexpr Vector2 vector = Vector2(10, 10);
 	CHECK_MESSAGE(
 			vector.limit_length().is_equal_approx(Vector2(Math_SQRT12, Math_SQRT12)),
 			"Vector2 limit_length should work as expected.");
@@ -193,70 +193,70 @@ TEST_CASE("[Vector2] Normalization methods") {
 }
 
 TEST_CASE("[Vector2] Operators") {
-	const Vector2 decimal1 = Vector2(2.3, 4.9);
-	const Vector2 decimal2 = Vector2(1.2, 3.4);
-	const Vector2 power1 = Vector2(0.75, 1.5);
-	const Vector2 power2 = Vector2(0.5, 0.125);
-	const Vector2 int1 = Vector2(4, 5);
-	const Vector2 int2 = Vector2(1, 2);
+	constexpr Vector2 decimal1 = Vector2(2.3, 4.9);
+	constexpr Vector2 decimal2 = Vector2(1.2, 3.4);
+	constexpr Vector2 power1 = Vector2(0.75, 1.5);
+	constexpr Vector2 power2 = Vector2(0.5, 0.125);
+	constexpr Vector2 int1 = Vector2(4, 5);
+	constexpr Vector2 int2 = Vector2(1, 2);
 
 	CHECK_MESSAGE(
 			(decimal1 + decimal2).is_equal_approx(Vector2(3.5, 8.3)),
 			"Vector2 addition should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 + power2) == Vector2(1.25, 1.625),
 			"Vector2 addition with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 + int2) == Vector2(5, 7),
 			"Vector2 addition with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 - decimal2).is_equal_approx(Vector2(1.1, 1.5)),
 			"Vector2 subtraction should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 - power2) == Vector2(0.25, 1.375),
 			"Vector2 subtraction with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 - int2) == Vector2(3, 3),
 			"Vector2 subtraction with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 * decimal2).is_equal_approx(Vector2(2.76, 16.66)),
 			"Vector2 multiplication should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 * power2) == Vector2(0.375, 0.1875),
 			"Vector2 multiplication with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 * int2) == Vector2(4, 10),
 			"Vector2 multiplication with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 / decimal2).is_equal_approx(Vector2(1.91666666666666666, 1.44117647058823529)),
 			"Vector2 division should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 / power2) == Vector2(1.5, 12.0),
 			"Vector2 division with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 / int2) == Vector2(4, 2.5),
 			"Vector2 division with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 * 2).is_equal_approx(Vector2(4.6, 9.8)),
 			"Vector2 multiplication should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 * 2) == Vector2(1.5, 3),
 			"Vector2 multiplication with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 * 2) == Vector2(8, 10),
 			"Vector2 multiplication with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 / 2).is_equal_approx(Vector2(1.15, 2.45)),
 			"Vector2 division should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 / 2) == Vector2(0.375, 0.75),
 			"Vector2 division with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 / 2) == Vector2(2, 2.5),
 			"Vector2 division with integers should give exact results.");
 
@@ -291,7 +291,7 @@ TEST_CASE("[Vector2] Operators") {
 }
 
 TEST_CASE("[Vector2] Other methods") {
-	const Vector2 vector = Vector2(1.2, 3.4);
+	constexpr Vector2 vector = Vector2(1.2, 3.4);
 	CHECK_MESSAGE(
 			vector.aspect() == doctest::Approx((real_t)1.2 / (real_t)3.4),
 			"Vector2 aspect should work as expected.");
@@ -349,10 +349,10 @@ TEST_CASE("[Vector2] Other methods") {
 }
 
 TEST_CASE("[Vector2] Plane methods") {
-	const Vector2 vector = Vector2(1.2, 3.4);
-	const Vector2 vector_y = Vector2(0, 1);
-	const Vector2 vector_normal = Vector2(0.95879811270838721622267, 0.2840883296913739899919);
-	const real_t p_d = 99.1;
+	constexpr Vector2 vector = Vector2(1.2, 3.4);
+	constexpr Vector2 vector_y = Vector2(0, 1);
+	constexpr Vector2 vector_normal = Vector2(0.95879811270838721622267, 0.2840883296913739899919);
+	constexpr real_t p_d = 99.1;
 	CHECK_MESSAGE(
 			vector.bounce(vector_y) == Vector2(1.2, -3.4),
 			"Vector2 bounce on a plane with normal of the Y axis should.");
@@ -382,7 +382,7 @@ TEST_CASE("[Vector2] Plane methods") {
 			"Vector2 slide with normal should return expected value.");
 	// There's probably a better way to test these ones?
 #ifdef MATH_CHECKS
-	const Vector2 vector_non_normal = Vector2(5.4, 1.6);
+	constexpr Vector2 vector_non_normal = Vector2(5.4, 1.6);
 	ERR_PRINT_OFF;
 	CHECK_MESSAGE(
 			vector.bounce(vector_non_normal).is_equal_approx(Vector2()),
@@ -398,8 +398,8 @@ TEST_CASE("[Vector2] Plane methods") {
 }
 
 TEST_CASE("[Vector2] Rounding methods") {
-	const Vector2 vector1 = Vector2(1.2, 5.6);
-	const Vector2 vector2 = Vector2(1.2, -5.6);
+	constexpr Vector2 vector1 = Vector2(1.2, 5.6);
+	constexpr Vector2 vector2 = Vector2(1.2, -5.6);
 	CHECK_MESSAGE(
 			vector1.abs() == vector1,
 			"Vector2 abs should work as expected.");
@@ -437,10 +437,10 @@ TEST_CASE("[Vector2] Rounding methods") {
 }
 
 TEST_CASE("[Vector2] Linear algebra methods") {
-	const Vector2 vector_x = Vector2(1, 0);
-	const Vector2 vector_y = Vector2(0, 1);
-	const Vector2 a = Vector2(3.5, 8.5);
-	const Vector2 b = Vector2(5.2, 4.6);
+	constexpr Vector2 vector_x = Vector2(1, 0);
+	constexpr Vector2 vector_y = Vector2(0, 1);
+	constexpr Vector2 a = Vector2(3.5, 8.5);
+	constexpr Vector2 b = Vector2(5.2, 4.6);
 	CHECK_MESSAGE(
 			vector_x.cross(vector_y) == 1,
 			"Vector2 cross product of X and Y should give 1.");

+ 17 - 17
tests/core/math/test_vector2i.h

@@ -37,9 +37,9 @@
 namespace TestVector2i {
 
 TEST_CASE("[Vector2i] Constructor methods") {
-	const Vector2i vector_empty = Vector2i();
-	const Vector2i vector_zero = Vector2i(0, 0);
-	CHECK_MESSAGE(
+	constexpr Vector2i vector_empty = Vector2i();
+	constexpr Vector2i vector_zero = Vector2i(0, 0);
+	static_assert(
 			vector_empty == vector_zero,
 			"Vector2i Constructor with no inputs should return a zero Vector2i.");
 }
@@ -62,7 +62,7 @@ TEST_CASE("[Vector2i] Axis methods") {
 }
 
 TEST_CASE("[Vector2i] Clamp method") {
-	const Vector2i vector = Vector2i(10, 10);
+	constexpr Vector2i vector = Vector2i(10, 10);
 	CHECK_MESSAGE(
 			Vector2i(-5, 15).clamp(Vector2i(), vector) == Vector2i(0, 10),
 			"Vector2i clamp should work as expected.");
@@ -72,8 +72,8 @@ TEST_CASE("[Vector2i] Clamp method") {
 }
 
 TEST_CASE("[Vector2i] Length methods") {
-	const Vector2i vector1 = Vector2i(10, 10);
-	const Vector2i vector2 = Vector2i(20, 30);
+	constexpr Vector2i vector1 = Vector2i(10, 10);
+	constexpr Vector2i vector2 = Vector2i(20, 30);
 	CHECK_MESSAGE(
 			vector1.length_squared() == 200,
 			"Vector2i length_squared should work as expected and return exact result.");
@@ -95,26 +95,26 @@ TEST_CASE("[Vector2i] Length methods") {
 }
 
 TEST_CASE("[Vector2i] Operators") {
-	const Vector2i vector1 = Vector2i(5, 9);
-	const Vector2i vector2 = Vector2i(2, 3);
+	constexpr Vector2i vector1 = Vector2i(5, 9);
+	constexpr Vector2i vector2 = Vector2i(2, 3);
 
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 + vector2) == Vector2i(7, 12),
 			"Vector2i addition with integers should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 - vector2) == Vector2i(3, 6),
 			"Vector2i subtraction with integers should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 * vector2) == Vector2i(10, 27),
 			"Vector2i multiplication with integers should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 / vector2) == Vector2i(2, 3),
 			"Vector2i division with integers should give exact results.");
 
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 * 2) == Vector2i(10, 18),
 			"Vector2i multiplication with integers should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 / 2) == Vector2i(2, 4),
 			"Vector2i division with integers should give exact results.");
 
@@ -130,7 +130,7 @@ TEST_CASE("[Vector2i] Operators") {
 }
 
 TEST_CASE("[Vector2i] Other methods") {
-	const Vector2i vector = Vector2i(1, 3);
+	constexpr Vector2i vector = Vector2i(1, 3);
 	CHECK_MESSAGE(
 			vector.aspect() == doctest::Approx((real_t)1.0 / (real_t)3.0),
 			"Vector2i aspect should work as expected.");
@@ -149,8 +149,8 @@ TEST_CASE("[Vector2i] Other methods") {
 }
 
 TEST_CASE("[Vector2i] Abs and sign methods") {
-	const Vector2i vector1 = Vector2i(1, 3);
-	const Vector2i vector2 = Vector2i(1, -3);
+	constexpr Vector2i vector1 = Vector2i(1, 3);
+	constexpr Vector2i vector2 = Vector2i(1, -3);
 	CHECK_MESSAGE(
 			vector1.abs() == vector1,
 			"Vector2i abs should work as expected.");

+ 41 - 41
tests/core/math/test_vector3.h

@@ -39,17 +39,17 @@
 namespace TestVector3 {
 
 TEST_CASE("[Vector3] Constructor methods") {
-	const Vector3 vector_empty = Vector3();
-	const Vector3 vector_zero = Vector3(0.0, 0.0, 0.0);
-	CHECK_MESSAGE(
+	constexpr Vector3 vector_empty = Vector3();
+	constexpr Vector3 vector_zero = Vector3(0.0, 0.0, 0.0);
+	static_assert(
 			vector_empty == vector_zero,
 			"Vector3 Constructor with no inputs should return a zero Vector3.");
 }
 
 TEST_CASE("[Vector3] Angle methods") {
-	const Vector3 vector_x = Vector3(1, 0, 0);
-	const Vector3 vector_y = Vector3(0, 1, 0);
-	const Vector3 vector_yz = Vector3(0, 1, 1);
+	constexpr Vector3 vector_x = Vector3(1, 0, 0);
+	constexpr Vector3 vector_y = Vector3(0, 1, 0);
+	constexpr Vector3 vector_yz = Vector3(0, 1, 1);
 	CHECK_MESSAGE(
 			vector_x.angle_to(vector_y) == doctest::Approx((real_t)Math_TAU / 4),
 			"Vector3 angle_to should work as expected.");
@@ -96,8 +96,8 @@ TEST_CASE("[Vector3] Axis methods") {
 }
 
 TEST_CASE("[Vector3] Interpolation methods") {
-	const Vector3 vector1 = Vector3(1, 2, 3);
-	const Vector3 vector2 = Vector3(4, 5, 6);
+	constexpr Vector3 vector1 = Vector3(1, 2, 3);
+	constexpr Vector3 vector2 = Vector3(4, 5, 6);
 	CHECK_MESSAGE(
 			vector1.lerp(vector2, 0.5) == Vector3(2.5, 3.5, 4.5),
 			"Vector3 lerp should work as expected.");
@@ -146,8 +146,8 @@ TEST_CASE("[Vector3] Interpolation methods") {
 }
 
 TEST_CASE("[Vector3] Length methods") {
-	const Vector3 vector1 = Vector3(10, 10, 10);
-	const Vector3 vector2 = Vector3(20, 30, 40);
+	constexpr Vector3 vector1 = Vector3(10, 10, 10);
+	constexpr Vector3 vector2 = Vector3(20, 30, 40);
 	CHECK_MESSAGE(
 			vector1.length_squared() == 300,
 			"Vector3 length_squared should work as expected and return exact result.");
@@ -169,7 +169,7 @@ TEST_CASE("[Vector3] Length methods") {
 }
 
 TEST_CASE("[Vector3] Limiting methods") {
-	const Vector3 vector = Vector3(10, 10, 10);
+	constexpr Vector3 vector = Vector3(10, 10, 10);
 	CHECK_MESSAGE(
 			vector.limit_length().is_equal_approx(Vector3(Math_SQRT13, Math_SQRT13, Math_SQRT13)),
 			"Vector3 limit_length should work as expected.");
@@ -213,70 +213,70 @@ TEST_CASE("[Vector3] Normalization methods") {
 }
 
 TEST_CASE("[Vector3] Operators") {
-	const Vector3 decimal1 = Vector3(2.3, 4.9, 7.8);
-	const Vector3 decimal2 = Vector3(1.2, 3.4, 5.6);
-	const Vector3 power1 = Vector3(0.75, 1.5, 0.625);
-	const Vector3 power2 = Vector3(0.5, 0.125, 0.25);
-	const Vector3 int1 = Vector3(4, 5, 9);
-	const Vector3 int2 = Vector3(1, 2, 3);
+	constexpr Vector3 decimal1 = Vector3(2.3, 4.9, 7.8);
+	constexpr Vector3 decimal2 = Vector3(1.2, 3.4, 5.6);
+	constexpr Vector3 power1 = Vector3(0.75, 1.5, 0.625);
+	constexpr Vector3 power2 = Vector3(0.5, 0.125, 0.25);
+	constexpr Vector3 int1 = Vector3(4, 5, 9);
+	constexpr Vector3 int2 = Vector3(1, 2, 3);
 
 	CHECK_MESSAGE(
 			(decimal1 + decimal2).is_equal_approx(Vector3(3.5, 8.3, 13.4)),
 			"Vector3 addition should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 + power2) == Vector3(1.25, 1.625, 0.875),
 			"Vector3 addition with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 + int2) == Vector3(5, 7, 12),
 			"Vector3 addition with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 - decimal2).is_equal_approx(Vector3(1.1, 1.5, 2.2)),
 			"Vector3 subtraction should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 - power2) == Vector3(0.25, 1.375, 0.375),
 			"Vector3 subtraction with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 - int2) == Vector3(3, 3, 6),
 			"Vector3 subtraction with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 * decimal2).is_equal_approx(Vector3(2.76, 16.66, 43.68)),
 			"Vector3 multiplication should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 * power2) == Vector3(0.375, 0.1875, 0.15625),
 			"Vector3 multiplication with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 * int2) == Vector3(4, 10, 27),
 			"Vector3 multiplication with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 / decimal2).is_equal_approx(Vector3(1.91666666666666666, 1.44117647058823529, 1.39285714285714286)),
 			"Vector3 division should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 / power2) == Vector3(1.5, 12.0, 2.5),
 			"Vector3 division with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 / int2) == Vector3(4, 2.5, 3),
 			"Vector3 division with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 * 2).is_equal_approx(Vector3(4.6, 9.8, 15.6)),
 			"Vector3 multiplication should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 * 2) == Vector3(1.5, 3, 1.25),
 			"Vector3 multiplication with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 * 2) == Vector3(8, 10, 18),
 			"Vector3 multiplication with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 / 2).is_equal_approx(Vector3(1.15, 2.45, 3.9)),
 			"Vector3 division should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 / 2) == Vector3(0.375, 0.75, 0.3125),
 			"Vector3 division with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 / 2) == Vector3(2, 2.5, 4.5),
 			"Vector3 division with integers should give exact results.");
 
@@ -311,7 +311,7 @@ TEST_CASE("[Vector3] Operators") {
 }
 
 TEST_CASE("[Vector3] Other methods") {
-	const Vector3 vector = Vector3(1.2, 3.4, 5.6);
+	constexpr Vector3 vector = Vector3(1.2, 3.4, 5.6);
 	CHECK_MESSAGE(
 			vector.direction_to(Vector3()).is_equal_approx(-vector.normalized()),
 			"Vector3 direction_to should work as expected.");
@@ -364,9 +364,9 @@ TEST_CASE("[Vector3] Other methods") {
 }
 
 TEST_CASE("[Vector3] Plane methods") {
-	const Vector3 vector = Vector3(1.2, 3.4, 5.6);
-	const Vector3 vector_y = Vector3(0, 1, 0);
-	const Vector3 vector_normal = Vector3(0.88763458893247992491, 0.26300284116517923701, 0.37806658417494515320);
+	constexpr Vector3 vector = Vector3(1.2, 3.4, 5.6);
+	constexpr Vector3 vector_y = Vector3(0, 1, 0);
+	constexpr Vector3 vector_normal = Vector3(0.88763458893247992491, 0.26300284116517923701, 0.37806658417494515320);
 	CHECK_MESSAGE(
 			vector.bounce(vector_y) == Vector3(1.2, -3.4, 5.6),
 			"Vector3 bounce on a plane with normal of the Y axis should.");
@@ -393,7 +393,7 @@ TEST_CASE("[Vector3] Plane methods") {
 			"Vector3 slide with normal should return expected value.");
 	// There's probably a better way to test these ones?
 #ifdef MATH_CHECKS
-	const Vector3 vector_non_normal = Vector3(5.4, 1.6, 2.3);
+	constexpr Vector3 vector_non_normal = Vector3(5.4, 1.6, 2.3);
 	ERR_PRINT_OFF;
 	CHECK_MESSAGE(
 			vector.bounce(vector_non_normal).is_equal_approx(Vector3()),
@@ -409,8 +409,8 @@ TEST_CASE("[Vector3] Plane methods") {
 }
 
 TEST_CASE("[Vector3] Rounding methods") {
-	const Vector3 vector1 = Vector3(1.2, 3.4, 5.6);
-	const Vector3 vector2 = Vector3(1.2, -3.4, -5.6);
+	constexpr Vector3 vector1 = Vector3(1.2, 3.4, 5.6);
+	constexpr Vector3 vector2 = Vector3(1.2, -3.4, -5.6);
 	CHECK_MESSAGE(
 			vector1.abs() == vector1,
 			"Vector3 abs should work as expected.");
@@ -448,11 +448,11 @@ TEST_CASE("[Vector3] Rounding methods") {
 }
 
 TEST_CASE("[Vector3] Linear algebra methods") {
-	const Vector3 vector_x = Vector3(1, 0, 0);
-	const Vector3 vector_y = Vector3(0, 1, 0);
-	const Vector3 vector_z = Vector3(0, 0, 1);
-	const Vector3 a = Vector3(3.5, 8.5, 2.3);
-	const Vector3 b = Vector3(5.2, 4.6, 7.8);
+	constexpr Vector3 vector_x = Vector3(1, 0, 0);
+	constexpr Vector3 vector_y = Vector3(0, 1, 0);
+	constexpr Vector3 vector_z = Vector3(0, 0, 1);
+	constexpr Vector3 a = Vector3(3.5, 8.5, 2.3);
+	constexpr Vector3 b = Vector3(5.2, 4.6, 7.8);
 	CHECK_MESSAGE(
 			vector_x.cross(vector_y) == vector_z,
 			"Vector3 cross product of X and Y should give Z.");

+ 19 - 17
tests/core/math/test_vector3i.h

@@ -33,12 +33,14 @@
 #include "core/math/vector3i.h"
 #include "tests/test_macros.h"
 
+#define Math_SQRT3 1.7320508075688772935274463415059
+
 namespace TestVector3i {
 
 TEST_CASE("[Vector3i] Constructor methods") {
-	const Vector3i vector_empty = Vector3i();
-	const Vector3i vector_zero = Vector3i(0, 0, 0);
-	CHECK_MESSAGE(
+	constexpr Vector3i vector_empty = Vector3i();
+	constexpr Vector3i vector_zero = Vector3i(0, 0, 0);
+	static_assert(
 			vector_empty == vector_zero,
 			"Vector3i Constructor with no inputs should return a zero Vector3i.");
 }
@@ -65,7 +67,7 @@ TEST_CASE("[Vector3i] Axis methods") {
 }
 
 TEST_CASE("[Vector3i] Clamp method") {
-	const Vector3i vector = Vector3i(10, 10, 10);
+	constexpr Vector3i vector = Vector3i(10, 10, 10);
 	CHECK_MESSAGE(
 			Vector3i(-5, 5, 15).clamp(Vector3i(), vector) == Vector3i(0, 5, 10),
 			"Vector3i clamp should work as expected.");
@@ -75,8 +77,8 @@ TEST_CASE("[Vector3i] Clamp method") {
 }
 
 TEST_CASE("[Vector3i] Length methods") {
-	const Vector3i vector1 = Vector3i(10, 10, 10);
-	const Vector3i vector2 = Vector3i(20, 30, 40);
+	constexpr Vector3i vector1 = Vector3i(10, 10, 10);
+	constexpr Vector3i vector2 = Vector3i(20, 30, 40);
 	CHECK_MESSAGE(
 			vector1.length_squared() == 300,
 			"Vector3i length_squared should work as expected and return exact result.");
@@ -98,26 +100,26 @@ TEST_CASE("[Vector3i] Length methods") {
 }
 
 TEST_CASE("[Vector3i] Operators") {
-	const Vector3i vector1 = Vector3i(4, 5, 9);
-	const Vector3i vector2 = Vector3i(1, 2, 3);
+	constexpr Vector3i vector1 = Vector3i(4, 5, 9);
+	constexpr Vector3i vector2 = Vector3i(1, 2, 3);
 
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 + vector2) == Vector3i(5, 7, 12),
 			"Vector3i addition with integers should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 - vector2) == Vector3i(3, 3, 6),
 			"Vector3i subtraction with integers should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 * vector2) == Vector3i(4, 10, 27),
 			"Vector3i multiplication with integers should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 / vector2) == Vector3i(4, 2, 3),
 			"Vector3i division with integers should give exact results.");
 
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 * 2) == Vector3i(8, 10, 18),
 			"Vector3i multiplication with integers should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 / 2) == Vector3i(2, 2, 4),
 			"Vector3i division with integers should give exact results.");
 
@@ -133,7 +135,7 @@ TEST_CASE("[Vector3i] Operators") {
 }
 
 TEST_CASE("[Vector3i] Other methods") {
-	const Vector3i vector = Vector3i(1, 3, -7);
+	constexpr Vector3i vector = Vector3i(1, 3, -7);
 
 	CHECK_MESSAGE(
 			vector.min(Vector3i(3, 2, 5)) == Vector3i(1, 2, -7),
@@ -148,8 +150,8 @@ TEST_CASE("[Vector3i] Other methods") {
 }
 
 TEST_CASE("[Vector3i] Abs and sign methods") {
-	const Vector3i vector1 = Vector3i(1, 3, 5);
-	const Vector3i vector2 = Vector3i(1, -3, -5);
+	constexpr Vector3i vector1 = Vector3i(1, 3, 5);
+	constexpr Vector3i vector2 = Vector3i(1, -3, -5);
 	CHECK_MESSAGE(
 			vector1.abs() == vector1,
 			"Vector3i abs should work as expected.");

+ 35 - 35
tests/core/math/test_vector4.h

@@ -38,9 +38,9 @@
 namespace TestVector4 {
 
 TEST_CASE("[Vector4] Constructor methods") {
-	const Vector4 vector_empty = Vector4();
-	const Vector4 vector_zero = Vector4(0.0, 0.0, 0.0, 0.0);
-	CHECK_MESSAGE(
+	constexpr Vector4 vector_empty = Vector4();
+	constexpr Vector4 vector_zero = Vector4(0.0, 0.0, 0.0, 0.0);
+	static_assert(
 			vector_empty == vector_zero,
 			"Vector4 Constructor with no inputs should return a zero Vector4.");
 }
@@ -67,8 +67,8 @@ TEST_CASE("[Vector4] Axis methods") {
 }
 
 TEST_CASE("[Vector4] Interpolation methods") {
-	const Vector4 vector1 = Vector4(1, 2, 3, 4);
-	const Vector4 vector2 = Vector4(4, 5, 6, 7);
+	constexpr Vector4 vector1 = Vector4(1, 2, 3, 4);
+	constexpr Vector4 vector2 = Vector4(4, 5, 6, 7);
 	CHECK_MESSAGE(
 			vector1.lerp(vector2, 0.5) == Vector4(2.5, 3.5, 4.5, 5.5),
 			"Vector4 lerp should work as expected.");
@@ -84,8 +84,8 @@ TEST_CASE("[Vector4] Interpolation methods") {
 }
 
 TEST_CASE("[Vector4] Length methods") {
-	const Vector4 vector1 = Vector4(10, 10, 10, 10);
-	const Vector4 vector2 = Vector4(20, 30, 40, 50);
+	constexpr Vector4 vector1 = Vector4(10, 10, 10, 10);
+	constexpr Vector4 vector2 = Vector4(20, 30, 40, 50);
 	CHECK_MESSAGE(
 			vector1.length_squared() == 400,
 			"Vector4 length_squared should work as expected and return exact result.");
@@ -107,7 +107,7 @@ TEST_CASE("[Vector4] Length methods") {
 }
 
 TEST_CASE("[Vector4] Limiting methods") {
-	const Vector4 vector = Vector4(10, 10, 10, 10);
+	constexpr Vector4 vector = Vector4(10, 10, 10, 10);
 	CHECK_MESSAGE(
 			Vector4(-5, 5, 15, -15).clamp(Vector4(), vector) == Vector4(0, 5, 10, 0),
 			"Vector4 clamp should work as expected.");
@@ -135,73 +135,73 @@ TEST_CASE("[Vector4] Normalization methods") {
 }
 
 TEST_CASE("[Vector4] Operators") {
-	const Vector4 decimal1 = Vector4(2.3, 4.9, 7.8, 3.2);
-	const Vector4 decimal2 = Vector4(1.2, 3.4, 5.6, 1.7);
-	const Vector4 power1 = Vector4(0.75, 1.5, 0.625, 0.125);
-	const Vector4 power2 = Vector4(0.5, 0.125, 0.25, 0.75);
-	const Vector4 int1 = Vector4(4, 5, 9, 2);
-	const Vector4 int2 = Vector4(1, 2, 3, 1);
-
-	CHECK_MESSAGE(
+	constexpr Vector4 decimal1 = Vector4(2.3, 4.9, 7.8, 3.2);
+	constexpr Vector4 decimal2 = Vector4(1.2, 3.4, 5.6, 1.7);
+	constexpr Vector4 power1 = Vector4(0.75, 1.5, 0.625, 0.125);
+	constexpr Vector4 power2 = Vector4(0.5, 0.125, 0.25, 0.75);
+	constexpr Vector4 int1 = Vector4(4, 5, 9, 2);
+	constexpr Vector4 int2 = Vector4(1, 2, 3, 1);
+
+	static_assert(
 			-decimal1 == Vector4(-2.3, -4.9, -7.8, -3.2),
 			"Vector4 change of sign should work as expected.");
 	CHECK_MESSAGE(
 			(decimal1 + decimal2).is_equal_approx(Vector4(3.5, 8.3, 13.4, 4.9)),
 			"Vector4 addition should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 + power2) == Vector4(1.25, 1.625, 0.875, 0.875),
 			"Vector4 addition with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 + int2) == Vector4(5, 7, 12, 3),
 			"Vector4 addition with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 - decimal2).is_equal_approx(Vector4(1.1, 1.5, 2.2, 1.5)),
 			"Vector4 subtraction should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 - power2) == Vector4(0.25, 1.375, 0.375, -0.625),
 			"Vector4 subtraction with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 - int2) == Vector4(3, 3, 6, 1),
 			"Vector4 subtraction with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 * decimal2).is_equal_approx(Vector4(2.76, 16.66, 43.68, 5.44)),
 			"Vector4 multiplication should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 * power2) == Vector4(0.375, 0.1875, 0.15625, 0.09375),
 			"Vector4 multiplication with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 * int2) == Vector4(4, 10, 27, 2),
 			"Vector4 multiplication with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 / decimal2).is_equal_approx(Vector4(1.91666666666666666, 1.44117647058823529, 1.39285714285714286, 1.88235294118)),
 			"Vector4 division should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 / power2) == Vector4(1.5, 12.0, 2.5, 1.0 / 6.0),
 			"Vector4 division with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 / int2) == Vector4(4, 2.5, 3, 2),
 			"Vector4 division with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 * 2).is_equal_approx(Vector4(4.6, 9.8, 15.6, 6.4)),
 			"Vector4 multiplication should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 * 2) == Vector4(1.5, 3, 1.25, 0.25),
 			"Vector4 multiplication with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 * 2) == Vector4(8, 10, 18, 4),
 			"Vector4 multiplication with integers should give exact results.");
 
 	CHECK_MESSAGE(
 			(decimal1 / 2).is_equal_approx(Vector4(1.15, 2.45, 3.9, 1.6)),
 			"Vector4 division should behave as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(power1 / 2) == Vector4(0.375, 0.75, 0.3125, 0.0625),
 			"Vector4 division with powers of two should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(int1 / 2) == Vector4(2, 2.5, 4.5, 1),
 			"Vector4 division with integers should give exact results.");
 
@@ -226,7 +226,7 @@ TEST_CASE("[Vector4] Operators") {
 }
 
 TEST_CASE("[Vector4] Other methods") {
-	const Vector4 vector = Vector4(1.2, 3.4, 5.6, 1.6);
+	constexpr Vector4 vector = Vector4(1.2, 3.4, 5.6, 1.6);
 	CHECK_MESSAGE(
 			vector.direction_to(Vector4()).is_equal_approx(-vector.normalized()),
 			"Vector4 direction_to should work as expected.");
@@ -265,8 +265,8 @@ TEST_CASE("[Vector4] Other methods") {
 }
 
 TEST_CASE("[Vector4] Rounding methods") {
-	const Vector4 vector1 = Vector4(1.2, 3.4, 5.6, 1.6);
-	const Vector4 vector2 = Vector4(1.2, -3.4, -5.6, -1.6);
+	constexpr Vector4 vector1 = Vector4(1.2, 3.4, 5.6, 1.6);
+	constexpr Vector4 vector2 = Vector4(1.2, -3.4, -5.6, -1.6);
 	CHECK_MESSAGE(
 			vector1.abs() == vector1,
 			"Vector4 abs should work as expected.");
@@ -303,10 +303,10 @@ TEST_CASE("[Vector4] Rounding methods") {
 }
 
 TEST_CASE("[Vector4] Linear algebra methods") {
-	const Vector4 vector_x = Vector4(1, 0, 0, 0);
-	const Vector4 vector_y = Vector4(0, 1, 0, 0);
-	const Vector4 vector1 = Vector4(1.7, 2.3, 1, 9.1);
-	const Vector4 vector2 = Vector4(-8.2, -16, 3, 2.4);
+	constexpr Vector4 vector_x = Vector4(1, 0, 0, 0);
+	constexpr Vector4 vector_y = Vector4(0, 1, 0, 0);
+	constexpr Vector4 vector1 = Vector4(1.7, 2.3, 1, 9.1);
+	constexpr Vector4 vector2 = Vector4(-8.2, -16, 3, 2.4);
 
 	CHECK_MESSAGE(
 			vector_x.dot(vector_y) == 0.0,

+ 18 - 18
tests/core/math/test_vector4i.h

@@ -36,9 +36,9 @@
 namespace TestVector4i {
 
 TEST_CASE("[Vector4i] Constructor methods") {
-	const Vector4i vector_empty = Vector4i();
-	const Vector4i vector_zero = Vector4i(0, 0, 0, 0);
-	CHECK_MESSAGE(
+	constexpr Vector4i vector_empty = Vector4i();
+	constexpr Vector4i vector_zero = Vector4i(0, 0, 0, 0);
+	static_assert(
 			vector_empty == vector_zero,
 			"Vector4i Constructor with no inputs should return a zero Vector4i.");
 }
@@ -65,7 +65,7 @@ TEST_CASE("[Vector4i] Axis methods") {
 }
 
 TEST_CASE("[Vector4i] Clamp method") {
-	const Vector4i vector = Vector4i(10, 10, 10, 10);
+	constexpr Vector4i vector = Vector4i(10, 10, 10, 10);
 	CHECK_MESSAGE(
 			Vector4i(-5, 5, 15, INT_MAX).clamp(Vector4i(), vector) == Vector4i(0, 5, 10, 10),
 			"Vector4i clamp should work as expected.");
@@ -75,8 +75,8 @@ TEST_CASE("[Vector4i] Clamp method") {
 }
 
 TEST_CASE("[Vector4i] Length methods") {
-	const Vector4i vector1 = Vector4i(10, 10, 10, 10);
-	const Vector4i vector2 = Vector4i(20, 30, 40, 50);
+	constexpr Vector4i vector1 = Vector4i(10, 10, 10, 10);
+	constexpr Vector4i vector2 = Vector4i(20, 30, 40, 50);
 	CHECK_MESSAGE(
 			vector1.length_squared() == 400,
 			"Vector4i length_squared should work as expected and return exact result.");
@@ -98,29 +98,29 @@ TEST_CASE("[Vector4i] Length methods") {
 }
 
 TEST_CASE("[Vector4i] Operators") {
-	const Vector4i vector1 = Vector4i(4, 5, 9, 2);
-	const Vector4i vector2 = Vector4i(1, 2, 3, 4);
+	constexpr Vector4i vector1 = Vector4i(4, 5, 9, 2);
+	constexpr Vector4i vector2 = Vector4i(1, 2, 3, 4);
 
-	CHECK_MESSAGE(
+	static_assert(
 			-vector1 == Vector4i(-4, -5, -9, -2),
 			"Vector4i change of sign should work as expected.");
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 + vector2) == Vector4i(5, 7, 12, 6),
 			"Vector4i addition with integers should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 - vector2) == Vector4i(3, 3, 6, -2),
 			"Vector4i subtraction with integers should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 * vector2) == Vector4i(4, 10, 27, 8),
 			"Vector4i multiplication with integers should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 / vector2) == Vector4i(4, 2, 3, 0),
 			"Vector4i division with integers should give exact results.");
 
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 * 2) == Vector4i(8, 10, 18, 4),
 			"Vector4i multiplication with integers should give exact results.");
-	CHECK_MESSAGE(
+	static_assert(
 			(vector1 / 2) == Vector4i(2, 2, 4, 1),
 			"Vector4i division with integers should give exact results.");
 
@@ -136,7 +136,7 @@ TEST_CASE("[Vector4i] Operators") {
 }
 
 TEST_CASE("[Vector3i] Other methods") {
-	const Vector4i vector = Vector4i(1, 3, -7, 13);
+	constexpr Vector4i vector = Vector4i(1, 3, -7, 13);
 
 	CHECK_MESSAGE(
 			vector.min(Vector4i(3, 2, 5, 8)) == Vector4i(1, 2, -7, 8),
@@ -152,8 +152,8 @@ TEST_CASE("[Vector3i] Other methods") {
 }
 
 TEST_CASE("[Vector4i] Abs and sign methods") {
-	const Vector4i vector1 = Vector4i(1, 3, 5, 7);
-	const Vector4i vector2 = Vector4i(1, -3, -5, 7);
+	constexpr Vector4i vector1 = Vector4i(1, 3, 5, 7);
+	constexpr Vector4i vector2 = Vector4i(1, -3, -5, 7);
 	CHECK_MESSAGE(
 			vector1.abs() == vector1,
 			"Vector4i abs should work as expected.");