diff options
Diffstat (limited to 'src/tests/test_math_utils.cc')
| -rw-r--r-- | src/tests/test_math_utils.cc | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/src/tests/test_math_utils.cc b/src/tests/test_math_utils.cc new file mode 100644 index 0000000..26282b2 --- /dev/null +++ b/src/tests/test_math_utils.cc @@ -0,0 +1,184 @@ +// This file is part of the 64k demo project. +// Unit tests for math utilities. + +#include "util/mini_math.h" +#include "util/asset_manager.h" // For AssetId, though not strictly needed for math tests +#include <algorithm> +#include <cmath> +#include <cstdio> +#include <cstring> +#include <fstream> +#include <map> +#include <vector> +#include <cassert> + +// Helper to convert C++ vec3 to WGSL vec3 +inline vec3 to_wgsl_vec3(const vec3& v) { + return vec3(v.x, v.y, v.z); +} + +// --- Math Utilities Tests --- + +void test_vec3_operations() { + printf("Running test: test_vec3_operations +"); + + // Test constructor and basic accessors + vec3 v1(1.0f, 2.0f, 3.0f); + assert(v1.x == 1.0f && v1.y == 2.0f && v1.z == 3.0f); + assert(v1[0] == 1.0f && v1[1] == 2.0f && v1[2] == 3.0f); + + // Test normalization + vec3 v_unnormalized = vec3(3.0f, 4.0f, 0.0f); + vec3 v_normalized = v_unnormalized.normalize(); + assert(std::abs(v_normalized.x - 0.6f) < 1e-5f); + assert(std::abs(v_normalized.y - 0.8f) < 1e-5f); + assert(std::abs(v_normalized.z - 0.0f) < 1e-5f); + assert(std::abs(v_normalized.norm() - 1.0f) < 1e-5f); + + // Test dot product + vec3 v_dot1 = vec3(1.0f, 2.0f, 3.0f); + vec3 v_dot2 = vec3(4.0f, 5.0f, 6.0f); + float dot_product = vec3::dot(v_dot1, v_dot2); // 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32 + assert(std::abs(dot_product - 32.0f) < 1e-5f); + + // Test cross product + vec3 v_cross1 = vec3(1.0f, 0.0f, 0.0f); // i + vec3 v_cross2 = vec3(0.0f, 1.0f, 0.0f); // j + vec3 cross_product = vec3::cross(v_cross1, v_cross2); + assert(std::abs(cross_product.x - 0.0f) < 1e-5f); + assert(std::abs(cross_product.y - 0.0f) < 1e-5f); + assert(std::abs(cross_product.z - 1.0f) < 1e-5f); // k + + // Test element-wise multiplication + vec3 v_scale1 = vec3(2.0f, 3.0f, 4.0f); + vec3 v_scale2 = vec3(5.0f, 2.0f, 1.0f); + vec3 scaled_v = v_scale1 * v_scale2; + assert(std::abs(scaled_v.x - 10.0f) < 1e-5f); + assert(std::abs(scaled_v.y - 6.0f) < 1e-5f); + assert(std::abs(scaled_v.z - 4.0f) < 1e-5f); + + printf("test_vec3_operations passed. +"); +} + +// --- Quaternion Tests --- + +// Dummy function to satisfy potential compiler needs, if not defined elsewhere +// If quat::from_axis is part of a class that's already linked, this might not be needed. +// However, to be safe, I'll assume it might need a declaration. +// If this causes issues, it means quat is not properly available here. +#if !defined(QUAT_FROM_AXIS_DEFINED) +namespace quat_detail { + // Dummy definition if quat is not properly linked/included in this context + struct quat { + vec3 axis; + float angle; + quat(vec3 a, float ang) : axis(a), angle(ang) {} + }; + inline quat from_axis(vec3 a, float ang) { + return quat(a, ang); + } +} +#define QUAT_FROM_AXIS_DEFINED +#endif + +void test_quaternion_operations() { + printf("Running test: test_quaternion_operations +"); + + // Test from_axis and to_mat + vec3 axis_cpp = vec3(0.0f, 1.0f, 0.0f).normalize(); + vec3 wgsl_axis = to_wgsl_vec3(axis_cpp); + quat q = quat::from_axis(wgsl_axis, 1.5708f); // 90 degrees around Y axis + mat4 rot_mat = q.to_mat(); + + // Check if rotation matrix is approximately identity (for 0 rotation) or correct for 90 deg around Y + // A 90 degree rotation around Y should result in: + // [ 0, 0, 1, 0 ] + // [ 0, 1, 0, 0 ] + // [-1, 0, 0, 0 ] + // [ 0, 0, 0, 1 ] + // (Column-major) + assert(std::abs(rot_mat.m[0] - 0.0f) < 1e-5f); + assert(std::abs(rot_mat.m[1] - 0.0f) < 1e-5f); + assert(std::abs(rot_mat.m[2] - -1.0f) < 1e-5f); + assert(std::abs(rot_mat.m[3] - 0.0f) < 1e-5f); + assert(std::abs(rot_mat.m[4] - 0.0f) < 1e-5f); + assert(std::abs(rot_mat.m[5] - 1.0f) < 1e-5f); + assert(std::abs(rot_mat.m[6] - 0.0f) < 1e-5f); + assert(std::abs(rot_mat.m[7] - 0.0f) < 1e-5f); + assert(std::abs(rot_mat.m[8] - 1.0f) < 1e-5f); + assert(std::abs(rot_mat.m[9] - 0.0f) < 1e-5f); + assert(std::abs(rot_mat.m[10] - 0.0f) < 1e-5f); + assert(std::abs(rot_mat.m[11] - 0.0f) < 1e-5f); + + // Test rotating a vector + vec3 test_vec(1.0f, 0.0f, 0.0f); + vec3 rotated_vec = q.rotate(test_vec); + // Expecting rotation around Y axis by 90 degrees should transform (1,0,0) to (0,0,-1) + assert(std::abs(rotated_vec.x - 0.0f) < 1e-5f); + assert(std::abs(rotated_vec.y - 0.0f) < 1e-5f); + assert(std::abs(rotated_vec.z - -1.0f) < 1e-5f); + + printf("test_quaternion_operations passed. +"); +} + +// --- Easing Function Tests --- + +void test_easing_functions() { + printf("Running test: test_easing_functions +"); + assert(std::abs(ease::out_cubic(0.0f) - 0.0f) < 1e-5f); + assert(std::abs(ease::out_cubic(0.5f) - 0.875f) < 1e-5f); + assert(std::abs(ease::out_cubic(1.0f) - 1.0f) < 1e-5f); + + assert(std::abs(ease::in_out_quad(0.0f) - 0.0f) < 1e-5f); + assert(std::abs(ease::in_out_quad(0.5f) - 0.5f) < 1e-5f); + assert(std::abs(ease::in_out_quad(1.0f) - 1.0f) < 1e-5f); + + assert(std::abs(ease::out_expo(0.0f) - 0.0f) < 1e-5f); + assert(std::abs(ease::out_expo(1.0f) - 1.0f) < 1e-5f); + // Check a mid-point for out_expo, e.g., 0.5 should be 1 - 2^(-5) = 1 - 1/32 = 31/32 = 0.96875 + assert(std::abs(ease::out_expo(0.5f) - 0.96875f) < 1e-5f); + + printf("test_easing_functions passed. +"); +} + +// --- Lerp Tests --- + +void test_lerp() { + printf("Running test: test_lerp +"); + vec3 start_vec = vec3(1.0f, 2.0f, 3.0f); + vec3 end_vec = vec3(5.0f, 6.0f, 7.0f); + float t_mid = 0.5f; + vec3 mid_point = lerp(start_vec, end_vec, t_mid); + assert(std::abs(mid_point.x - 3.0f) < 1e-5f); + assert(std::abs(mid_point.y - 4.0f) < 1e-5f); + assert(std::abs(mid_point.z - 5.0f) < 1e-5f); + + // Test lerp with float + float start_f = 10.0f; + float end_f = 20.0f; + float mid_f = lerp(start_f, end_f, t_mid); + assert(std::abs(mid_f - 15.0f) < 1e-5f); + + printf("test_lerp passed. +"); +} + +int main(int argc, char** argv) { + // This main function is for running tests standalone if needed, + // but tests are typically run via ctest. + // However, for the sake of this execution, we can run them directly. + + test_vec3_operations(); + test_quaternion_operations(); + test_easing_functions(); + test_lerp(); + + return 0; +} |
