summaryrefslogtreecommitdiff
path: root/tests/core
diff options
context:
space:
mode:
Diffstat (limited to 'tests/core')
-rw-r--r--tests/core/input/test_input_event_key.h2
-rw-r--r--tests/core/io/test_image.h2
-rw-r--r--tests/core/math/test_basis.h48
-rw-r--r--tests/core/math/test_geometry_2d.h2
-rw-r--r--tests/core/math/test_math_funcs.h556
-rw-r--r--tests/core/math/test_quaternion.h57
-rw-r--r--tests/core/math/test_vector2.h6
-rw-r--r--tests/core/math/test_vector3.h6
8 files changed, 626 insertions, 53 deletions
diff --git a/tests/core/input/test_input_event_key.h b/tests/core/input/test_input_event_key.h
index ef0a656b18..b852f3ccb9 100644
--- a/tests/core/input/test_input_event_key.h
+++ b/tests/core/input/test_input_event_key.h
@@ -102,7 +102,7 @@ TEST_CASE("[InputEventKey] Key correctly converts itself to text") {
// as text. These cases are a bit weird, since None has no textual representation
// (find_keycode_name(Key::NONE) results in a nullptr). Thus, these tests look weird
// with only (Physical) or a lonely modifier with (Physical) but (as far as I
- // understand the code, that is intended behaviour.
+ // understand the code, that is intended behavior.
// Key is None without a physical key.
none_key.set_keycode(Key::NONE);
diff --git a/tests/core/io/test_image.h b/tests/core/io/test_image.h
index 181d9a8a54..1559c59b5c 100644
--- a/tests/core/io/test_image.h
+++ b/tests/core/io/test_image.h
@@ -162,7 +162,7 @@ TEST_CASE("[Image] Basic getters") {
CHECK(image->get_size() == Vector2(8, 4));
CHECK(image->get_format() == Image::FORMAT_LA8);
CHECK(image->get_used_rect() == Rect2i(0, 0, 0, 0));
- Ref<Image> image_get_rect = image->get_rect(Rect2i(0, 0, 2, 1));
+ Ref<Image> image_get_rect = image->get_region(Rect2i(0, 0, 2, 1));
CHECK(image_get_rect->get_size() == Vector2(2, 1));
}
diff --git a/tests/core/math/test_basis.h b/tests/core/math/test_basis.h
index f52b715cd7..a4099ebf7d 100644
--- a/tests/core/math/test_basis.h
+++ b/tests/core/math/test_basis.h
@@ -46,26 +46,26 @@ Vector3 rad2deg(const Vector3 &p_rotation) {
return p_rotation / Math_PI * 180.0;
}
-String get_rot_order_name(Basis::EulerOrder ro) {
+String get_rot_order_name(EulerOrder ro) {
switch (ro) {
- case Basis::EULER_ORDER_XYZ:
+ case EulerOrder::XYZ:
return "XYZ";
- case Basis::EULER_ORDER_XZY:
+ case EulerOrder::XZY:
return "XZY";
- case Basis::EULER_ORDER_YZX:
+ case EulerOrder::YZX:
return "YZX";
- case Basis::EULER_ORDER_YXZ:
+ case EulerOrder::YXZ:
return "YXZ";
- case Basis::EULER_ORDER_ZXY:
+ case EulerOrder::ZXY:
return "ZXY";
- case Basis::EULER_ORDER_ZYX:
+ case EulerOrder::ZYX:
return "ZYX";
default:
return "[Not supported]";
}
}
-void test_rotation(Vector3 deg_original_euler, Basis::EulerOrder rot_order) {
+void test_rotation(Vector3 deg_original_euler, EulerOrder rot_order) {
// This test:
// 1. Converts the rotation vector from deg to rad.
// 2. Converts euler to basis.
@@ -98,8 +98,8 @@ void test_rotation(Vector3 deg_original_euler, Basis::EulerOrder rot_order) {
CHECK_MESSAGE((res.get_column(2) - Vector3(0.0, 0.0, 1.0)).length() <= 0.1, vformat("Fail due to Z %s\n", String(res.get_column(2))).utf8().ptr());
// Double check `to_rotation` decomposing with XYZ rotation order.
- const Vector3 euler_xyz_from_rotation = to_rotation.get_euler(Basis::EULER_ORDER_XYZ);
- Basis rotation_from_xyz_computed_euler = Basis::from_euler(euler_xyz_from_rotation, Basis::EULER_ORDER_XYZ);
+ const Vector3 euler_xyz_from_rotation = to_rotation.get_euler(EulerOrder::XYZ);
+ Basis rotation_from_xyz_computed_euler = Basis::from_euler(euler_xyz_from_rotation, EulerOrder::XYZ);
res = to_rotation.inverse() * rotation_from_xyz_computed_euler;
@@ -113,13 +113,13 @@ void test_rotation(Vector3 deg_original_euler, Basis::EulerOrder rot_order) {
}
TEST_CASE("[Basis] Euler conversions") {
- Vector<Basis::EulerOrder> euler_order_to_test;
- euler_order_to_test.push_back(Basis::EULER_ORDER_XYZ);
- euler_order_to_test.push_back(Basis::EULER_ORDER_XZY);
- euler_order_to_test.push_back(Basis::EULER_ORDER_YZX);
- euler_order_to_test.push_back(Basis::EULER_ORDER_YXZ);
- euler_order_to_test.push_back(Basis::EULER_ORDER_ZXY);
- euler_order_to_test.push_back(Basis::EULER_ORDER_ZYX);
+ Vector<EulerOrder> euler_order_to_test;
+ euler_order_to_test.push_back(EulerOrder::XYZ);
+ euler_order_to_test.push_back(EulerOrder::XZY);
+ euler_order_to_test.push_back(EulerOrder::YZX);
+ euler_order_to_test.push_back(EulerOrder::YXZ);
+ euler_order_to_test.push_back(EulerOrder::ZXY);
+ euler_order_to_test.push_back(EulerOrder::ZYX);
Vector<Vector3> vectors_to_test;
@@ -185,13 +185,13 @@ TEST_CASE("[Basis] Euler conversions") {
}
TEST_CASE("[Stress][Basis] Euler conversions") {
- Vector<Basis::EulerOrder> euler_order_to_test;
- euler_order_to_test.push_back(Basis::EULER_ORDER_XYZ);
- euler_order_to_test.push_back(Basis::EULER_ORDER_XZY);
- euler_order_to_test.push_back(Basis::EULER_ORDER_YZX);
- euler_order_to_test.push_back(Basis::EULER_ORDER_YXZ);
- euler_order_to_test.push_back(Basis::EULER_ORDER_ZXY);
- euler_order_to_test.push_back(Basis::EULER_ORDER_ZYX);
+ Vector<EulerOrder> euler_order_to_test;
+ euler_order_to_test.push_back(EulerOrder::XYZ);
+ euler_order_to_test.push_back(EulerOrder::XZY);
+ euler_order_to_test.push_back(EulerOrder::YZX);
+ euler_order_to_test.push_back(EulerOrder::YXZ);
+ euler_order_to_test.push_back(EulerOrder::ZXY);
+ euler_order_to_test.push_back(EulerOrder::ZYX);
Vector<Vector3> vectors_to_test;
// Add 1000 random vectors with weirds numbers.
diff --git a/tests/core/math/test_geometry_2d.h b/tests/core/math/test_geometry_2d.h
index db4e6e2177..54893a0b87 100644
--- a/tests/core/math/test_geometry_2d.h
+++ b/tests/core/math/test_geometry_2d.h
@@ -64,7 +64,7 @@ TEST_CASE("[Geometry2D] Point in triangle") {
// This tests points on the edge of the triangle. They are treated as being outside the triangle.
// In `is_point_in_circle` and `is_point_in_polygon` they are treated as being inside, so in order the make
- // the behaviour consistent this may change in the future (see issue #44717 and PR #44274).
+ // the behavior consistent this may change in the future (see issue #44717 and PR #44274).
CHECK_FALSE(Geometry2D::is_point_in_triangle(Vector2(1, 1), Vector2(-1, 1), Vector2(0, -1), Vector2(1, 1)));
CHECK_FALSE(Geometry2D::is_point_in_triangle(Vector2(0, 1), Vector2(-1, 1), Vector2(0, -1), Vector2(1, 1)));
}
diff --git a/tests/core/math/test_math_funcs.h b/tests/core/math/test_math_funcs.h
new file mode 100644
index 0000000000..c468e73b74
--- /dev/null
+++ b/tests/core/math/test_math_funcs.h
@@ -0,0 +1,556 @@
+/*************************************************************************/
+/* test_math_funcs.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TEST_MATH_FUNCS_H
+#define TEST_MATH_FUNCS_H
+
+#include "tests/test_macros.h"
+
+namespace TestMath {
+
+TEST_CASE("[Math] C++ macros") {
+ CHECK(MIN(-2, 2) == -2);
+ CHECK(MIN(600, 2) == 2);
+
+ CHECK(MAX(-2, 2) == 2);
+ CHECK(MAX(600, 2) == 600);
+
+ CHECK(CLAMP(600, -2, 2) == 2);
+ CHECK(CLAMP(620, 600, 650) == 620);
+ // `max` is lower than `min`.
+ CHECK(CLAMP(620, 600, 50) == 50);
+
+ CHECK(ABS(-5) == 5);
+ CHECK(ABS(0) == 0);
+ CHECK(ABS(5) == 5);
+
+ CHECK(SIGN(-5) == -1.0);
+ CHECK(SIGN(0) == 0.0);
+ CHECK(SIGN(5) == 1.0);
+}
+
+TEST_CASE("[Math] Power of two functions") {
+ CHECK(next_power_of_2(0) == 0);
+ CHECK(next_power_of_2(1) == 1);
+ CHECK(next_power_of_2(16) == 16);
+ CHECK(next_power_of_2(17) == 32);
+ CHECK(next_power_of_2(65535) == 65536);
+
+ CHECK(previous_power_of_2(0) == 0);
+ CHECK(previous_power_of_2(1) == 1);
+ CHECK(previous_power_of_2(16) == 16);
+ CHECK(previous_power_of_2(17) == 16);
+ CHECK(previous_power_of_2(65535) == 32768);
+
+ CHECK(closest_power_of_2(0) == 0);
+ CHECK(closest_power_of_2(1) == 1);
+ CHECK(closest_power_of_2(16) == 16);
+ CHECK(closest_power_of_2(17) == 16);
+ CHECK(closest_power_of_2(65535) == 65536);
+
+ CHECK(get_shift_from_power_of_2(0) == -1);
+ CHECK(get_shift_from_power_of_2(1) == 0);
+ CHECK(get_shift_from_power_of_2(16) == 4);
+ CHECK(get_shift_from_power_of_2(17) == -1);
+ CHECK(get_shift_from_power_of_2(65535) == -1);
+
+ CHECK(nearest_shift(0) == 0);
+ CHECK(nearest_shift(1) == 1);
+ CHECK(nearest_shift(16) == 5);
+ CHECK(nearest_shift(17) == 5);
+ CHECK(nearest_shift(65535) == 16);
+}
+
+TEST_CASE("[Math] abs") {
+ // int
+ CHECK(Math::abs(-1) == 1);
+ CHECK(Math::abs(0) == 0);
+ CHECK(Math::abs(1) == 1);
+
+ // double
+ CHECK(Math::abs(-0.1) == 0.1);
+ CHECK(Math::abs(0.0) == 0.0);
+ CHECK(Math::abs(0.1) == 0.1);
+
+ // float
+ CHECK(Math::abs(-0.1f) == 0.1f);
+ CHECK(Math::abs(0.0f) == 0.0f);
+ CHECK(Math::abs(0.1f) == 0.1f);
+}
+
+TEST_CASE("[Math] round/floor/ceil") {
+ CHECK(Math::round(1.5) == 2.0);
+ CHECK(Math::round(1.6) == 2.0);
+ CHECK(Math::round(-1.5) == -2.0);
+ CHECK(Math::round(-1.1) == -1.0);
+
+ CHECK(Math::floor(1.5) == 1.0);
+ CHECK(Math::floor(-1.5) == -2.0);
+
+ CHECK(Math::ceil(1.5) == 2.0);
+ CHECK(Math::ceil(-1.9) == -1.0);
+}
+
+TEST_CASE("[Math] sin/cos/tan") {
+ CHECK(Math::sin(-0.1) == doctest::Approx(-0.0998334166));
+ CHECK(Math::sin(0.1) == doctest::Approx(0.0998334166));
+ CHECK(Math::sin(0.5) == doctest::Approx(0.4794255386));
+ CHECK(Math::sin(1.0) == doctest::Approx(0.8414709848));
+ CHECK(Math::sin(1.5) == doctest::Approx(0.9974949866));
+ CHECK(Math::sin(450.0) == doctest::Approx(-0.683283725));
+
+ CHECK(Math::cos(-0.1) == doctest::Approx(0.99500416530));
+ CHECK(Math::cos(0.1) == doctest::Approx(0.9950041653));
+ CHECK(Math::cos(0.5) == doctest::Approx(0.8775825619));
+ CHECK(Math::cos(1.0) == doctest::Approx(0.5403023059));
+ CHECK(Math::cos(1.5) == doctest::Approx(0.0707372017));
+ CHECK(Math::cos(450.0) == doctest::Approx(-0.7301529642));
+
+ CHECK(Math::tan(-0.1) == doctest::Approx(-0.1003346721));
+ CHECK(Math::tan(0.1) == doctest::Approx(0.1003346721));
+ CHECK(Math::tan(0.5) == doctest::Approx(0.5463024898));
+ CHECK(Math::tan(1.0) == doctest::Approx(1.5574077247));
+ CHECK(Math::tan(1.5) == doctest::Approx(14.1014199472));
+ CHECK(Math::tan(450.0) == doctest::Approx(0.9358090134));
+}
+
+TEST_CASE("[Math] sinh/cosh/tanh") {
+ CHECK(Math::sinh(-0.1) == doctest::Approx(-0.10016675));
+ CHECK(Math::sinh(0.1) == doctest::Approx(0.10016675));
+ CHECK(Math::sinh(0.5) == doctest::Approx(0.5210953055));
+ CHECK(Math::sinh(1.0) == doctest::Approx(1.1752011936));
+ CHECK(Math::sinh(1.5) == doctest::Approx(2.1292794551));
+
+ CHECK(Math::cosh(-0.1) == doctest::Approx(1.0050041681));
+ CHECK(Math::cosh(0.1) == doctest::Approx(1.0050041681));
+ CHECK(Math::cosh(0.5) == doctest::Approx(1.1276259652));
+ CHECK(Math::cosh(1.0) == doctest::Approx(1.5430806348));
+ CHECK(Math::cosh(1.5) == doctest::Approx(2.3524096152));
+
+ CHECK(Math::tanh(-0.1) == doctest::Approx(-0.0996679946));
+ CHECK(Math::tanh(0.1) == doctest::Approx(0.0996679946));
+ CHECK(Math::tanh(0.5) == doctest::Approx(0.4621171573));
+ CHECK(Math::tanh(1.0) == doctest::Approx(0.761594156));
+ CHECK(Math::tanh(1.5) == doctest::Approx(0.9051482536));
+ CHECK(Math::tanh(450.0) == doctest::Approx(1.0));
+}
+
+TEST_CASE("[Math] asin/acos/atan") {
+ CHECK(Math::asin(-0.1) == doctest::Approx(-0.1001674212));
+ CHECK(Math::asin(0.1) == doctest::Approx(0.1001674212));
+ CHECK(Math::asin(0.5) == doctest::Approx(0.5235987756));
+ CHECK(Math::asin(1.0) == doctest::Approx(1.5707963268));
+ CHECK(Math::is_nan(Math::asin(1.5)));
+ CHECK(Math::is_nan(Math::asin(450.0)));
+
+ CHECK(Math::acos(-0.1) == doctest::Approx(1.670963748));
+ CHECK(Math::acos(0.1) == doctest::Approx(1.4706289056));
+ CHECK(Math::acos(0.5) == doctest::Approx(1.0471975512));
+ CHECK(Math::acos(1.0) == doctest::Approx(0.0));
+ CHECK(Math::is_nan(Math::acos(1.5)));
+ CHECK(Math::is_nan(Math::acos(450.0)));
+
+ CHECK(Math::atan(-0.1) == doctest::Approx(-0.0996686525));
+ CHECK(Math::atan(0.1) == doctest::Approx(0.0996686525));
+ CHECK(Math::atan(0.5) == doctest::Approx(0.463647609));
+ CHECK(Math::atan(1.0) == doctest::Approx(0.7853981634));
+ CHECK(Math::atan(1.5) == doctest::Approx(0.9827937232));
+ CHECK(Math::atan(450.0) == doctest::Approx(1.5685741082));
+}
+
+TEST_CASE("[Math] sinc/sincn/atan2") {
+ CHECK(Math::sinc(-0.1) == doctest::Approx(0.9983341665));
+ CHECK(Math::sinc(0.1) == doctest::Approx(0.9983341665));
+ CHECK(Math::sinc(0.5) == doctest::Approx(0.9588510772));
+ CHECK(Math::sinc(1.0) == doctest::Approx(0.8414709848));
+ CHECK(Math::sinc(1.5) == doctest::Approx(0.6649966577));
+ CHECK(Math::sinc(450.0) == doctest::Approx(-0.0015184083));
+
+ CHECK(Math::sincn(-0.1) == doctest::Approx(0.9836316431));
+ CHECK(Math::sincn(0.1) == doctest::Approx(0.9836316431));
+ CHECK(Math::sincn(0.5) == doctest::Approx(0.6366197724));
+ CHECK(Math::sincn(1.0) == doctest::Approx(0.0));
+ CHECK(Math::sincn(1.5) == doctest::Approx(-0.2122065908));
+ CHECK(Math::sincn(450.0) == doctest::Approx(0.0));
+
+ CHECK(Math::atan2(-0.1, 0.5) == doctest::Approx(-0.1973955598));
+ CHECK(Math::atan2(0.1, -0.5) == doctest::Approx(2.9441970937));
+ CHECK(Math::atan2(0.5, 1.5) == doctest::Approx(0.3217505544));
+ CHECK(Math::atan2(1.0, 2.5) == doctest::Approx(0.3805063771));
+ CHECK(Math::atan2(1.5, 1.0) == doctest::Approx(0.9827937232));
+ CHECK(Math::atan2(450.0, 1.0) == doctest::Approx(1.5685741082));
+}
+
+TEST_CASE("[Math] pow/log/log2/exp/sqrt") {
+ CHECK(Math::pow(-0.1, 2.0) == doctest::Approx(0.01));
+ CHECK(Math::pow(0.1, 2.5) == doctest::Approx(0.0031622777));
+ CHECK(Math::pow(0.5, 0.5) == doctest::Approx(0.7071067812));
+ CHECK(Math::pow(1.0, 1.0) == doctest::Approx(1.0));
+ CHECK(Math::pow(1.5, -1.0) == doctest::Approx(0.6666666667));
+ CHECK(Math::pow(450.0, -2.0) == doctest::Approx(0.0000049383));
+ CHECK(Math::pow(450.0, 0.0) == doctest::Approx(1.0));
+
+ CHECK(Math::is_nan(Math::log(-0.1)));
+ CHECK(Math::log(0.1) == doctest::Approx(-2.302585093));
+ CHECK(Math::log(0.5) == doctest::Approx(-0.6931471806));
+ CHECK(Math::log(1.0) == doctest::Approx(0.0));
+ CHECK(Math::log(1.5) == doctest::Approx(0.4054651081));
+ CHECK(Math::log(450.0) == doctest::Approx(6.1092475828));
+
+ CHECK(Math::is_nan(Math::log2(-0.1)));
+ CHECK(Math::log2(0.1) == doctest::Approx(-3.3219280949));
+ CHECK(Math::log2(0.5) == doctest::Approx(-1.0));
+ CHECK(Math::log2(1.0) == doctest::Approx(0.0));
+ CHECK(Math::log2(1.5) == doctest::Approx(0.5849625007));
+ CHECK(Math::log2(450.0) == doctest::Approx(8.8137811912));
+
+ CHECK(Math::exp(-0.1) == doctest::Approx(0.904837418));
+ CHECK(Math::exp(0.1) == doctest::Approx(1.1051709181));
+ CHECK(Math::exp(0.5) == doctest::Approx(1.6487212707));
+ CHECK(Math::exp(1.0) == doctest::Approx(2.7182818285));
+ CHECK(Math::exp(1.5) == doctest::Approx(4.4816890703));
+
+ CHECK(Math::is_nan(Math::sqrt(-0.1)));
+ CHECK(Math::sqrt(0.1) == doctest::Approx(0.316228));
+ CHECK(Math::sqrt(0.5) == doctest::Approx(0.707107));
+ CHECK(Math::sqrt(1.0) == doctest::Approx(1.0));
+ CHECK(Math::sqrt(1.5) == doctest::Approx(1.224745));
+}
+
+TEST_CASE("[Math] is_nan/is_inf") {
+ CHECK(!Math::is_nan(0.0));
+ CHECK(Math::is_nan(NAN));
+
+ CHECK(!Math::is_inf(0.0));
+ CHECK(Math::is_inf(INFINITY));
+}
+
+TEST_CASE("[Math] linear_to_db") {
+ CHECK(Math::linear_to_db(1.0) == doctest::Approx(0.0));
+ CHECK(Math::linear_to_db(20.0) == doctest::Approx(26.0206));
+ CHECK(Math::is_inf(Math::linear_to_db(0.0)));
+ CHECK(Math::is_nan(Math::linear_to_db(-20.0)));
+}
+
+TEST_CASE("[Math] db_to_linear") {
+ CHECK(Math::db_to_linear(0.0) == doctest::Approx(1.0));
+ CHECK(Math::db_to_linear(1.0) == doctest::Approx(1.122018));
+ CHECK(Math::db_to_linear(20.0) == doctest::Approx(10.0));
+ CHECK(Math::db_to_linear(-20.0) == doctest::Approx(0.1));
+}
+
+TEST_CASE("[Math] step_decimals") {
+ CHECK(Math::step_decimals(-0.5) == 1);
+ CHECK(Math::step_decimals(0) == 0);
+ CHECK(Math::step_decimals(1) == 0);
+ CHECK(Math::step_decimals(0.1) == 1);
+ CHECK(Math::step_decimals(0.01) == 2);
+ CHECK(Math::step_decimals(0.001) == 3);
+ CHECK(Math::step_decimals(0.0001) == 4);
+ CHECK(Math::step_decimals(0.00001) == 5);
+ CHECK(Math::step_decimals(0.000001) == 6);
+ CHECK(Math::step_decimals(0.0000001) == 7);
+ CHECK(Math::step_decimals(0.00000001) == 8);
+ CHECK(Math::step_decimals(0.000000001) == 9);
+ // Too many decimals to handle.
+ CHECK(Math::step_decimals(0.0000000001) == 0);
+}
+
+TEST_CASE("[Math] range_step_decimals") {
+ CHECK(Math::range_step_decimals(0.000000001) == 9);
+ // Too many decimals to handle.
+ CHECK(Math::range_step_decimals(0.0000000001) == 0);
+ // Should be treated as a step of 0 for use by the editor.
+ CHECK(Math::range_step_decimals(0.0) == 16);
+ CHECK(Math::range_step_decimals(-0.5) == 16);
+}
+
+TEST_CASE("[Math] lerp") {
+ CHECK(Math::lerp(2.0, 5.0, -0.1) == doctest::Approx(1.7));
+ CHECK(Math::lerp(2.0, 5.0, 0.0) == doctest::Approx(2.0));
+ CHECK(Math::lerp(2.0, 5.0, 0.1) == doctest::Approx(2.3));
+ CHECK(Math::lerp(2.0, 5.0, 1.0) == doctest::Approx(5.0));
+ CHECK(Math::lerp(2.0, 5.0, 2.0) == doctest::Approx(8.0));
+
+ CHECK(Math::lerp(-2.0, -5.0, -0.1) == doctest::Approx(-1.7));
+ CHECK(Math::lerp(-2.0, -5.0, 0.0) == doctest::Approx(-2.0));
+ CHECK(Math::lerp(-2.0, -5.0, 0.1) == doctest::Approx(-2.3));
+ CHECK(Math::lerp(-2.0, -5.0, 1.0) == doctest::Approx(-5.0));
+ CHECK(Math::lerp(-2.0, -5.0, 2.0) == doctest::Approx(-8.0));
+}
+
+TEST_CASE("[Math] inverse_lerp") {
+ CHECK(Math::inverse_lerp(2.0, 5.0, 1.7) == doctest::Approx(-0.1));
+ CHECK(Math::inverse_lerp(2.0, 5.0, 2.0) == doctest::Approx(0.0));
+ CHECK(Math::inverse_lerp(2.0, 5.0, 2.3) == doctest::Approx(0.1));
+ CHECK(Math::inverse_lerp(2.0, 5.0, 5.0) == doctest::Approx(1.0));
+ CHECK(Math::inverse_lerp(2.0, 5.0, 8.0) == doctest::Approx(2.0));
+
+ CHECK(Math::inverse_lerp(-2.0, -5.0, -1.7) == doctest::Approx(-0.1));
+ CHECK(Math::inverse_lerp(-2.0, -5.0, -2.0) == doctest::Approx(0.0));
+ CHECK(Math::inverse_lerp(-2.0, -5.0, -2.3) == doctest::Approx(0.1));
+ CHECK(Math::inverse_lerp(-2.0, -5.0, -5.0) == doctest::Approx(1.0));
+ CHECK(Math::inverse_lerp(-2.0, -5.0, -8.0) == doctest::Approx(2.0));
+}
+
+TEST_CASE("[Math] remap") {
+ CHECK(Math::remap(50.0, 100.0, 200.0, 0.0, 1000.0) == doctest::Approx(-500.0));
+ CHECK(Math::remap(100.0, 100.0, 200.0, 0.0, 1000.0) == doctest::Approx(0.0));
+ CHECK(Math::remap(200.0, 100.0, 200.0, 0.0, 1000.0) == doctest::Approx(1000.0));
+ CHECK(Math::remap(250.0, 100.0, 200.0, 0.0, 1000.0) == doctest::Approx(1500.0));
+
+ CHECK(Math::remap(-50.0, -100.0, -200.0, 0.0, 1000.0) == doctest::Approx(-500.0));
+ CHECK(Math::remap(-100.0, -100.0, -200.0, 0.0, 1000.0) == doctest::Approx(0.0));
+ CHECK(Math::remap(-200.0, -100.0, -200.0, 0.0, 1000.0) == doctest::Approx(1000.0));
+ CHECK(Math::remap(-250.0, -100.0, -200.0, 0.0, 1000.0) == doctest::Approx(1500.0));
+
+ CHECK(Math::remap(-50.0, -100.0, -200.0, 0.0, -1000.0) == doctest::Approx(500.0));
+ CHECK(Math::remap(-100.0, -100.0, -200.0, 0.0, -1000.0) == doctest::Approx(0.0));
+ CHECK(Math::remap(-200.0, -100.0, -200.0, 0.0, -1000.0) == doctest::Approx(-1000.0));
+ CHECK(Math::remap(-250.0, -100.0, -200.0, 0.0, -1000.0) == doctest::Approx(-1500.0));
+}
+
+TEST_CASE("[Math] lerp_angle") {
+ // Counter-clockwise rotation.
+ CHECK(Math::lerp_angle(0.24 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx(-0.005 * Math_TAU));
+ // Counter-clockwise rotation.
+ CHECK(Math::lerp_angle(0.25 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx(0.0));
+ // Clockwise rotation.
+ CHECK(Math::lerp_angle(0.26 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx(0.505 * Math_TAU));
+
+ CHECK(Math::lerp_angle(-0.25 * Math_TAU, 1.25 * Math_TAU, 0.5) == doctest::Approx(-0.5 * Math_TAU));
+ CHECK(Math::lerp_angle(0.72 * Math_TAU, 1.44 * Math_TAU, 0.96) == doctest::Approx(0.4512 * Math_TAU));
+ CHECK(Math::lerp_angle(0.72 * Math_TAU, 1.44 * Math_TAU, 1.04) == doctest::Approx(0.4288 * Math_TAU));
+
+ // Initial and final angles are effectively identical, so the value returned
+ // should always be the same regardless of the `weight` parameter.
+ CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, -1.0) == doctest::Approx(-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, 0.0) == doctest::Approx(-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, 0.5) == doctest::Approx(-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, 1.0) == doctest::Approx(-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, 500.0) == doctest::Approx(-4.0 * Math_TAU));
+}
+
+TEST_CASE("[Math] move_toward") {
+ CHECK(Math::move_toward(2.0, 5.0, -1.0) == doctest::Approx(1.0));
+ CHECK(Math::move_toward(2.0, 5.0, 2.5) == doctest::Approx(4.5));
+ CHECK(Math::move_toward(2.0, 5.0, 4.0) == doctest::Approx(5.0));
+ CHECK(Math::move_toward(-2.0, -5.0, -1.0) == doctest::Approx(-1.0));
+ CHECK(Math::move_toward(-2.0, -5.0, 2.5) == doctest::Approx(-4.5));
+ CHECK(Math::move_toward(-2.0, -5.0, 4.0) == doctest::Approx(-5.0));
+}
+
+TEST_CASE("[Math] smoothstep") {
+ CHECK(Math::smoothstep(0.0, 2.0, -5.0) == doctest::Approx(0.0));
+ CHECK(Math::smoothstep(0.0, 2.0, 0.5) == doctest::Approx(0.15625));
+ CHECK(Math::smoothstep(0.0, 2.0, 1.0) == doctest::Approx(0.5));
+ CHECK(Math::smoothstep(0.0, 2.0, 2.0) == doctest::Approx(1.0));
+}
+
+TEST_CASE("[Math] ease") {
+ CHECK(Math::ease(0.1, 1.0) == doctest::Approx(0.1));
+ CHECK(Math::ease(0.1, 2.0) == doctest::Approx(0.01));
+ CHECK(Math::ease(0.1, 0.5) == doctest::Approx(0.19));
+ CHECK(Math::ease(0.1, 0.0) == doctest::Approx(0));
+ CHECK(Math::ease(0.1, -0.5) == doctest::Approx(0.2236067977));
+ CHECK(Math::ease(0.1, -1.0) == doctest::Approx(0.1));
+ CHECK(Math::ease(0.1, -2.0) == doctest::Approx(0.02));
+
+ CHECK(Math::ease(-1.0, 1.0) == doctest::Approx(0));
+ CHECK(Math::ease(-1.0, 2.0) == doctest::Approx(0));
+ CHECK(Math::ease(-1.0, 0.5) == doctest::Approx(0));
+ CHECK(Math::ease(-1.0, 0.0) == doctest::Approx(0));
+ CHECK(Math::ease(-1.0, -0.5) == doctest::Approx(0));
+ CHECK(Math::ease(-1.0, -1.0) == doctest::Approx(0));
+ CHECK(Math::ease(-1.0, -2.0) == doctest::Approx(0));
+}
+
+TEST_CASE("[Math] snapped") {
+ CHECK(Math::snapped(0.5, 0.04) == doctest::Approx(0.52));
+ CHECK(Math::snapped(-0.5, 0.04) == doctest::Approx(-0.48));
+ CHECK(Math::snapped(0.0, 0.04) == doctest::Approx(0));
+ CHECK(Math::snapped(128'000.025, 0.04) == doctest::Approx(128'000.04));
+
+ CHECK(Math::snapped(0.5, 400) == doctest::Approx(0));
+ CHECK(Math::snapped(-0.5, 400) == doctest::Approx(0));
+ CHECK(Math::snapped(0.0, 400) == doctest::Approx(0));
+ CHECK(Math::snapped(128'000.025, 400) == doctest::Approx(128'000.0));
+
+ CHECK(Math::snapped(0.5, 0.0) == doctest::Approx(0.5));
+ CHECK(Math::snapped(-0.5, 0.0) == doctest::Approx(-0.5));
+ CHECK(Math::snapped(0.0, 0.0) == doctest::Approx(0.0));
+ CHECK(Math::snapped(128'000.025, 0.0) == doctest::Approx(128'000.0));
+
+ CHECK(Math::snapped(0.5, -1.0) == doctest::Approx(0));
+ CHECK(Math::snapped(-0.5, -1.0) == doctest::Approx(-1.0));
+ CHECK(Math::snapped(0.0, -1.0) == doctest::Approx(0));
+ CHECK(Math::snapped(128'000.025, -1.0) == doctest::Approx(128'000.0));
+}
+
+TEST_CASE("[Math] larger_prime") {
+ CHECK(Math::larger_prime(0) == 5);
+ CHECK(Math::larger_prime(1) == 5);
+ CHECK(Math::larger_prime(2) == 5);
+ CHECK(Math::larger_prime(5) == 13);
+ CHECK(Math::larger_prime(500) == 769);
+ CHECK(Math::larger_prime(1'000'000) == 1'572'869);
+ CHECK(Math::larger_prime(1'000'000'000) == 1'610'612'741);
+
+ // The next prime is larger than `INT32_MAX` and is not present in the built-in prime table.
+ ERR_PRINT_OFF;
+ CHECK(Math::larger_prime(2'000'000'000) == 0);
+ ERR_PRINT_ON;
+}
+
+TEST_CASE("[Math] fmod") {
+ CHECK(Math::fmod(-2.0, 0.3) == doctest::Approx(-0.2));
+ CHECK(Math::fmod(0.0, 0.3) == doctest::Approx(0.0));
+ CHECK(Math::fmod(2.0, 0.3) == doctest::Approx(0.2));
+
+ CHECK(Math::fmod(-2.0, -0.3) == doctest::Approx(-0.2));
+ CHECK(Math::fmod(0.0, -0.3) == doctest::Approx(0.0));
+ CHECK(Math::fmod(2.0, -0.3) == doctest::Approx(0.2));
+}
+
+TEST_CASE("[Math] fposmod") {
+ CHECK(Math::fposmod(-2.0, 0.3) == doctest::Approx(0.1));
+ CHECK(Math::fposmod(0.0, 0.3) == doctest::Approx(0.0));
+ CHECK(Math::fposmod(2.0, 0.3) == doctest::Approx(0.2));
+
+ CHECK(Math::fposmod(-2.0, -0.3) == doctest::Approx(-0.2));
+ CHECK(Math::fposmod(0.0, -0.3) == doctest::Approx(0.0));
+ CHECK(Math::fposmod(2.0, -0.3) == doctest::Approx(-0.1));
+}
+
+TEST_CASE("[Math] fposmodp") {
+ CHECK(Math::fposmodp(-2.0, 0.3) == doctest::Approx(0.1));
+ CHECK(Math::fposmodp(0.0, 0.3) == doctest::Approx(0.0));
+ CHECK(Math::fposmodp(2.0, 0.3) == doctest::Approx(0.2));
+
+ CHECK(Math::fposmodp(-2.0, -0.3) == doctest::Approx(-0.5));
+ CHECK(Math::fposmodp(0.0, -0.3) == doctest::Approx(0.0));
+ CHECK(Math::fposmodp(2.0, -0.3) == doctest::Approx(0.2));
+}
+
+TEST_CASE("[Math] posmod") {
+ CHECK(Math::posmod(-20, 3) == 1);
+ CHECK(Math::posmod(0, 3) == 0);
+ CHECK(Math::posmod(20, 3) == 2);
+ CHECK(Math::posmod(-20, -3) == -2);
+ CHECK(Math::posmod(0, -3) == 0);
+ CHECK(Math::posmod(20, -3) == -1);
+}
+
+TEST_CASE("[Math] wrapi") {
+ CHECK(Math::wrapi(-30, -20, 160) == 150);
+ CHECK(Math::wrapi(30, -20, 160) == 30);
+ CHECK(Math::wrapi(300, -20, 160) == 120);
+ CHECK(Math::wrapi(300'000'000'000, -20, 160) == 120);
+}
+
+TEST_CASE("[Math] wrapf") {
+ CHECK(Math::wrapf(-30.0, -20.0, 160.0) == doctest::Approx(150.0));
+ CHECK(Math::wrapf(30.0, -2.0, 160.0) == doctest::Approx(30.0));
+ CHECK(Math::wrapf(300.0, -20.0, 160.0) == doctest::Approx(120.0));
+ CHECK(Math::wrapf(300'000'000'000.0, -20.0, 160.0) == doctest::Approx(120.0));
+}
+
+TEST_CASE("[Math] fract") {
+ CHECK(Math::fract(1.0) == doctest::Approx(0.0));
+ CHECK(Math::fract(77.8) == doctest::Approx(0.8));
+ CHECK(Math::fract(-10.1) == doctest::Approx(0.9));
+}
+
+TEST_CASE("[Math] pingpong") {
+ CHECK(Math::pingpong(0.0, 0.0) == doctest::Approx(0.0));
+ CHECK(Math::pingpong(1.0, 1.0) == doctest::Approx(1.0));
+ CHECK(Math::pingpong(0.5, 2.0) == doctest::Approx(0.5));
+ CHECK(Math::pingpong(3.5, 2.0) == doctest::Approx(0.5));
+ CHECK(Math::pingpong(11.5, 2.0) == doctest::Approx(0.5));
+ CHECK(Math::pingpong(-2.5, 2.0) == doctest::Approx(1.5));
+}
+
+TEST_CASE("[Math] deg_to_rad/rad_to_deg") {
+ CHECK(Math::deg_to_rad(180.0) == doctest::Approx(Math_PI));
+ CHECK(Math::deg_to_rad(-27.0) == doctest::Approx(-0.471239));
+
+ CHECK(Math::rad_to_deg(Math_PI) == doctest::Approx(180.0));
+ CHECK(Math::rad_to_deg(-1.5) == doctest::Approx(-85.94366927));
+}
+
+TEST_CASE("[Math] cubic_interpolate") {
+ CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 0.0) == doctest::Approx(0.2));
+ CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 0.25) == doctest::Approx(0.33125));
+ CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 0.5) == doctest::Approx(0.5));
+ CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 0.75) == doctest::Approx(0.66875));
+ CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 1.0) == doctest::Approx(0.8));
+
+ CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, -50.0) == doctest::Approx(-6662732.3));
+ CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, -5.0) == doctest::Approx(-9356.3));
+ CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, 0.0) == doctest::Approx(20.2));
+ CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, 1.0) == doctest::Approx(30.1));
+ CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, 4.0) == doctest::Approx(1853.2));
+}
+
+TEST_CASE("[Math] cubic_interpolate_angle") {
+ CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.0) == doctest::Approx(Math_PI * (1.0 / 6.0)));
+ CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.25) == doctest::Approx(0.973566));
+ CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.5) == doctest::Approx(Math_PI / 2.0));
+ CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.75) == doctest::Approx(2.16803));
+ CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 1.0) == doctest::Approx(Math_PI * (5.0 / 6.0)));
+}
+
+TEST_CASE("[Math] cubic_interpolate_in_time") {
+ CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 0.0, 0.5, 0.0, 1.0) == doctest::Approx(0.0));
+ CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 0.25, 0.5, 0.0, 1.0) == doctest::Approx(0.1625));
+ CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 0.5, 0.5, 0.0, 1.0) == doctest::Approx(0.4));
+ CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 0.75, 0.5, 0.0, 1.0) == doctest::Approx(0.6375));
+ CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 1.0, 0.5, 0.0, 1.0) == doctest::Approx(0.8));
+}
+
+TEST_CASE("[Math] cubic_interpolate_angle_in_time") {
+ CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.0, 0.5, 0.0, 1.0) == doctest::Approx(0.0));
+ CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.25, 0.5, 0.0, 1.0) == doctest::Approx(0.494964));
+ CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.5, 0.5, 0.0, 1.0) == doctest::Approx(1.27627));
+ CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.75, 0.5, 0.0, 1.0) == doctest::Approx(2.07394));
+ CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 1.0, 0.5, 0.0, 1.0) == doctest::Approx(Math_PI * (5.0 / 6.0)));
+}
+
+TEST_CASE("[Math] bezier_interpolate") {
+ CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 0.0) == doctest::Approx(0.0));
+ CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 0.25) == doctest::Approx(0.2125));
+ CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 0.5) == doctest::Approx(0.5));
+ CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 0.75) == doctest::Approx(0.7875));
+ CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 1.0) == doctest::Approx(1.0));
+}
+
+} // namespace TestMath
+
+#endif // TEST_MATH_FUNCS_H
diff --git a/tests/core/math/test_quaternion.h b/tests/core/math/test_quaternion.h
index eb5fea1d2d..c3ae322991 100644
--- a/tests/core/math/test_quaternion.h
+++ b/tests/core/math/test_quaternion.h
@@ -47,9 +47,9 @@ Quaternion quat_euler_yxz_deg(Vector3 angle) {
// Generate YXZ (Z-then-X-then-Y) Quaternion using single-axis Euler
// constructor and quaternion product, both tested separately.
- Quaternion q_y(Vector3(0.0, yaw, 0.0));
- Quaternion q_p(Vector3(pitch, 0.0, 0.0));
- Quaternion q_r(Vector3(0.0, 0.0, roll));
+ Quaternion q_y = Quaternion::from_euler(Vector3(0.0, yaw, 0.0));
+ Quaternion q_p = Quaternion::from_euler(Vector3(pitch, 0.0, 0.0));
+ Quaternion q_r = Quaternion::from_euler(Vector3(0.0, 0.0, roll));
// Roll-Z is followed by Pitch-X, then Yaw-Y.
Quaternion q_yxz = q_y * q_p * q_r;
@@ -134,21 +134,21 @@ TEST_CASE("[Quaternion] Construct Euler SingleAxis") {
double roll = Math::deg_to_rad(10.0);
Vector3 euler_y(0.0, yaw, 0.0);
- Quaternion q_y(euler_y);
+ Quaternion q_y = Quaternion::from_euler(euler_y);
CHECK(q_y[0] == doctest::Approx(0.0));
CHECK(q_y[1] == doctest::Approx(0.382684));
CHECK(q_y[2] == doctest::Approx(0.0));
CHECK(q_y[3] == doctest::Approx(0.923879));
Vector3 euler_p(pitch, 0.0, 0.0);
- Quaternion q_p(euler_p);
+ Quaternion q_p = Quaternion::from_euler(euler_p);
CHECK(q_p[0] == doctest::Approx(0.258819));
CHECK(q_p[1] == doctest::Approx(0.0));
CHECK(q_p[2] == doctest::Approx(0.0));
CHECK(q_p[3] == doctest::Approx(0.965926));
Vector3 euler_r(0.0, 0.0, roll);
- Quaternion q_r(euler_r);
+ Quaternion q_r = Quaternion::from_euler(euler_r);
CHECK(q_r[0] == doctest::Approx(0.0));
CHECK(q_r[1] == doctest::Approx(0.0));
CHECK(q_r[2] == doctest::Approx(0.0871558));
@@ -163,27 +163,27 @@ TEST_CASE("[Quaternion] Construct Euler YXZ dynamic axes") {
// Generate YXZ comparison data (Z-then-X-then-Y) using single-axis Euler
// constructor and quaternion product, both tested separately.
Vector3 euler_y(0.0, yaw, 0.0);
- Quaternion q_y(euler_y);
+ Quaternion q_y = Quaternion::from_euler(euler_y);
Vector3 euler_p(pitch, 0.0, 0.0);
- Quaternion q_p(euler_p);
+ Quaternion q_p = Quaternion::from_euler(euler_p);
Vector3 euler_r(0.0, 0.0, roll);
- Quaternion q_r(euler_r);
+ Quaternion q_r = Quaternion::from_euler(euler_r);
- // Roll-Z is followed by Pitch-X.
- Quaternion check_xz = q_p * q_r;
- // Then Yaw-Y follows both.
- Quaternion check_yxz = q_y * check_xz;
+ // Instrinsically, Yaw-Y then Pitch-X then Roll-Z.
+ // Extrinsically, Roll-Z is followed by Pitch-X, then Yaw-Y.
+ Quaternion check_yxz = q_y * q_p * q_r;
// Test construction from YXZ Euler angles.
Vector3 euler_yxz(pitch, yaw, roll);
- Quaternion q(euler_yxz);
+ Quaternion q = Quaternion::from_euler(euler_yxz);
CHECK(q[0] == doctest::Approx(check_yxz[0]));
CHECK(q[1] == doctest::Approx(check_yxz[1]));
CHECK(q[2] == doctest::Approx(check_yxz[2]));
CHECK(q[3] == doctest::Approx(check_yxz[3]));
- // Sneak in a test of is_equal_approx.
CHECK(q.is_equal_approx(check_yxz));
+ CHECK(q.get_euler().is_equal_approx(euler_yxz));
+ CHECK(check_yxz.get_euler().is_equal_approx(euler_yxz));
}
TEST_CASE("[Quaternion] Construct Basis Euler") {
@@ -191,7 +191,7 @@ TEST_CASE("[Quaternion] Construct Basis Euler") {
double pitch = Math::deg_to_rad(30.0);
double roll = Math::deg_to_rad(10.0);
Vector3 euler_yxz(pitch, yaw, roll);
- Quaternion q_yxz(euler_yxz);
+ Quaternion q_yxz = Quaternion::from_euler(euler_yxz);
Basis basis_axes = Basis::from_euler(euler_yxz);
Quaternion q(basis_axes);
CHECK(q.is_equal_approx(q_yxz));
@@ -209,7 +209,7 @@ TEST_CASE("[Quaternion] Construct Basis Axes") {
// Quaternion from local calculation.
Quaternion q_local = quat_euler_yxz_deg(Vector3(31.41, -49.16, 12.34));
// Quaternion from Euler angles constructor.
- Quaternion q_euler(euler_yxz);
+ Quaternion q_euler = Quaternion::from_euler(euler_yxz);
CHECK(q_calc.is_equal_approx(q_local));
CHECK(q_local.is_equal_approx(q_euler));
@@ -235,6 +235,23 @@ TEST_CASE("[Quaternion] Construct Basis Axes") {
CHECK(q[3] == doctest::Approx(0.8582598));
}
+TEST_CASE("[Quaternion] Get Euler Orders") {
+ double x = Math::deg_to_rad(30.0);
+ double y = Math::deg_to_rad(45.0);
+ double z = Math::deg_to_rad(10.0);
+ Vector3 euler(x, y, z);
+ for (int i = 0; i < 6; i++) {
+ EulerOrder order = (EulerOrder)i;
+ Basis basis = Basis::from_euler(euler, order);
+ Quaternion q = Quaternion(basis);
+ Vector3 check = q.get_euler(order);
+ CHECK_MESSAGE(check.is_equal_approx(euler),
+ "Quaternion get_euler method should return the original angles.");
+ CHECK_MESSAGE(check.is_equal_approx(basis.get_euler(order)),
+ "Quaternion get_euler method should behave the same as Basis get_euler.");
+ }
+}
+
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);
@@ -253,21 +270,21 @@ TEST_CASE("[Quaternion] Product") {
double roll = Math::deg_to_rad(10.0);
Vector3 euler_y(0.0, yaw, 0.0);
- Quaternion q_y(euler_y);
+ Quaternion q_y = Quaternion::from_euler(euler_y);
CHECK(q_y[0] == doctest::Approx(0.0));
CHECK(q_y[1] == doctest::Approx(0.382684));
CHECK(q_y[2] == doctest::Approx(0.0));
CHECK(q_y[3] == doctest::Approx(0.923879));
Vector3 euler_p(pitch, 0.0, 0.0);
- Quaternion q_p(euler_p);
+ Quaternion q_p = Quaternion::from_euler(euler_p);
CHECK(q_p[0] == doctest::Approx(0.258819));
CHECK(q_p[1] == doctest::Approx(0.0));
CHECK(q_p[2] == doctest::Approx(0.0));
CHECK(q_p[3] == doctest::Approx(0.965926));
Vector3 euler_r(0.0, 0.0, roll);
- Quaternion q_r(euler_r);
+ Quaternion q_r = Quaternion::from_euler(euler_r);
CHECK(q_r[0] == doctest::Approx(0.0));
CHECK(q_r[1] == doctest::Approx(0.0));
CHECK(q_r[2] == doctest::Approx(0.0871558));
diff --git a/tests/core/math/test_vector2.h b/tests/core/math/test_vector2.h
index a87b9ffc02..f7e9259329 100644
--- a/tests/core/math/test_vector2.h
+++ b/tests/core/math/test_vector2.h
@@ -382,13 +382,13 @@ TEST_CASE("[Vector2] Plane methods") {
ERR_PRINT_OFF;
CHECK_MESSAGE(
vector.bounce(vector_non_normal).is_equal_approx(Vector2()),
- "Vector2 bounce should return empty Vector2 with non-normalised input.");
+ "Vector2 bounce should return empty Vector2 with non-normalized input.");
CHECK_MESSAGE(
vector.reflect(vector_non_normal).is_equal_approx(Vector2()),
- "Vector2 reflect should return empty Vector2 with non-normalised input.");
+ "Vector2 reflect should return empty Vector2 with non-normalized input.");
CHECK_MESSAGE(
vector.slide(vector_non_normal).is_equal_approx(Vector2()),
- "Vector2 slide should return empty Vector2 with non-normalised input.");
+ "Vector2 slide should return empty Vector2 with non-normalized input.");
ERR_PRINT_ON;
}
diff --git a/tests/core/math/test_vector3.h b/tests/core/math/test_vector3.h
index 4932cd04db..77d3a9d93c 100644
--- a/tests/core/math/test_vector3.h
+++ b/tests/core/math/test_vector3.h
@@ -389,13 +389,13 @@ TEST_CASE("[Vector3] Plane methods") {
ERR_PRINT_OFF;
CHECK_MESSAGE(
vector.bounce(vector_non_normal).is_equal_approx(Vector3()),
- "Vector3 bounce should return empty Vector3 with non-normalised input.");
+ "Vector3 bounce should return empty Vector3 with non-normalized input.");
CHECK_MESSAGE(
vector.reflect(vector_non_normal).is_equal_approx(Vector3()),
- "Vector3 reflect should return empty Vector3 with non-normalised input.");
+ "Vector3 reflect should return empty Vector3 with non-normalized input.");
CHECK_MESSAGE(
vector.slide(vector_non_normal).is_equal_approx(Vector3()),
- "Vector3 slide should return empty Vector3 with non-normalised input.");
+ "Vector3 slide should return empty Vector3 with non-normalized input.");
ERR_PRINT_ON;
}