ray-tracer-challenge/test/test_transformations.c
2024-07-23 18:03:15 -05:00

235 lines
7.1 KiB
C

#include <stdbool.h>
#include <stdio.h>
#include "transformations.h"
#include "runner.h"
static bool transformations_test_0(const char ** scenario)
{
*scenario = "Multiplying by a translation matrix";
struct mat4x4 transform = translation(5.0f, -3.0f, 2.0f);
struct tuple p = point(-3.0f, 4.0f, 5.0f);
return tuple_equal(mat4x4_mul_t(&transform, &p), point(2.0f, 1.0f, 7.0f));
}
static bool transformations_test_1(const char ** scenario)
{
*scenario = "Multiplying by the inverse of a translation matrix";
struct mat4x4 transform = translation(5.0f, -3.0f, 2.0f);
struct mat4x4 inv = mat4x4_inverse(&transform);
struct tuple p = point(-3.0f, 4.0f, 5.0f);
return tuple_equal(mat4x4_mul_t(&inv, &p), point(-8.0f, 7.0f, 3.0f));
}
static bool transformations_test_2(const char ** scenario)
{
*scenario = "Translation does not affect vectors";
struct mat4x4 transform = translation(5.0f, -3.0f, 2.0f);
struct tuple v = vector(-3.0f, 4.0f, 5.0f);
return tuple_equal(mat4x4_mul_t(&transform, &v), v);
}
static bool transformations_test_3(const char ** scenario)
{
*scenario = "A scaling matrix applied to a point";
struct mat4x4 transform = scaling(2.0f, 3.0f, 4.0f);
struct tuple p = point(-4.0f, 6.0f, 8.0f);
return tuple_equal(mat4x4_mul_t(&transform, &p), point(-8.0f, 18.0f, 32.0f));
}
static bool transformations_test_4(const char ** scenario)
{
*scenario = "A scaling matrix applied to a vector";
struct mat4x4 transform = scaling(2.0f, 3.0f, 4.0f);
struct tuple v = vector(-4.0f, 6.0f, 8.0f);
return tuple_equal(mat4x4_mul_t(&transform, &v), vector(-8.0f, 18.0f, 32.0f));
}
static bool transformations_test_5(const char ** scenario)
{
*scenario = "Multiplying by the inverse of a scaling matrix";
struct mat4x4 transform = scaling(2.0f, 3.0f, 4.0f);
struct mat4x4 inv = mat4x4_inverse(&transform);
struct tuple v = vector(-4.0f, 6.0f, 8.0f);
return tuple_equal(mat4x4_mul_t(&inv, &v), vector(-2.0f, 2.0f, 2.0f));
}
static bool transformations_test_6(const char ** scenario)
{
*scenario = "Reflection is scaling by a negative value";
struct mat4x4 transform = scaling(-1.0f, 1.0f, 1.0f);
struct tuple p = point(2.0f, 3.0f, 4.0f);
return tuple_equal(mat4x4_mul_t(&transform, &p), point(-2.0f, 3.0f, 4.0f));
}
static bool transformations_test_7(const char ** scenario)
{
*scenario = "Rotating a point around the x axis";
struct tuple p = point(0.0f, 1.0f, 0.0f);
struct mat4x4 half_quarter = rotation_x(tau / 8);
struct mat4x4 full_quarter = rotation_x(tau / 4);
return
tuple_equal(mat4x4_mul_t(&half_quarter, &p), point(0.0f, 0.7071067811865476, 0.7071067811865476)) &&
tuple_equal(mat4x4_mul_t(&full_quarter, &p), point(0.0f, 0.0f, 1.0f));
}
static bool transformations_test_8(const char ** scenario)
{
*scenario = "Rotating a point around the y axis";
struct tuple p = point(0.0f, 0.0f, 1.0f);
struct mat4x4 half_quarter = rotation_y(tau / 8);
struct mat4x4 full_quarter = rotation_y(tau / 4);
return
tuple_equal(mat4x4_mul_t(&half_quarter, &p), point(0.7071067811865476, 0.0f, 0.7071067811865476)) &&
tuple_equal(mat4x4_mul_t(&full_quarter, &p), point(1.0f, 0.0f, 0.0f));
}
static bool transformations_test_9(const char ** scenario)
{
*scenario = "Rotating a point around the z axis";
struct tuple p = point(0.0f, 1.0f, 0.0f);
struct mat4x4 half_quarter = rotation_z(tau / 8);
struct mat4x4 full_quarter = rotation_z(tau / 4);
return
tuple_equal(mat4x4_mul_t(&half_quarter, &p), point(-0.7071067811865476, 0.7071067811865476, 0.0f)) &&
tuple_equal(mat4x4_mul_t(&full_quarter, &p), point(-1.0f, 0.0f, 0.0f));
}
static bool transformations_test_10(const char ** scenario)
{
*scenario = "A shearing transformation moves x in proportion to y";
struct mat4x4 transform = shearing(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
struct tuple p = point(2.0f, 3.0f, 4.0f);
return tuple_equal(mat4x4_mul_t(&transform, &p), point(5.0f, 3.0f, 4.0f));
}
static bool transformations_test_11(const char ** scenario)
{
*scenario = "A shearing transformation moves x in proportion to z";
struct mat4x4 transform = shearing(0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f);
struct tuple p = point(2.0f, 3.0f, 4.0f);
return tuple_equal(mat4x4_mul_t(&transform, &p), point(6.0f, 3.0f, 4.0f));
}
static bool transformations_test_12(const char ** scenario)
{
*scenario = "A shearing transformation moves y in proportion to x";
struct mat4x4 transform = shearing(0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
struct tuple p = point(2.0f, 3.0f, 4.0f);
return tuple_equal(mat4x4_mul_t(&transform, &p), point(2.0f, 5.0f, 4.0f));
}
static bool transformations_test_13(const char ** scenario)
{
*scenario = "A shearing transformation moves y in proportion to z";
struct mat4x4 transform = shearing(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
struct tuple p = point(2.0f, 3.0f, 4.0f);
return tuple_equal(mat4x4_mul_t(&transform, &p), point(2.0f, 7.0f, 4.0f));
}
static bool transformations_test_14(const char ** scenario)
{
*scenario = "A shearing transformation moves z in proportion to x";
struct mat4x4 transform = shearing(0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
struct tuple p = point(2.0f, 3.0f, 4.0f);
return tuple_equal(mat4x4_mul_t(&transform, &p), point(2.0f, 3.0f, 6.0f));
}
static bool transformations_test_15(const char ** scenario)
{
*scenario = "A shearing transformation moves z in proportion to y";
struct mat4x4 transform = shearing(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
struct tuple p = point(2.0f, 3.0f, 4.0f);
return tuple_equal(mat4x4_mul_t(&transform, &p), point(2.0f, 3.0f, 7.0f));
}
static bool transformations_test_16(const char ** scenario)
{
*scenario = "Individual transforms are applied in sequence";
struct tuple p = point(1.0f, 0.0f, 1.0f);
struct mat4x4 a = rotation_x(tau / 4.0f);
struct mat4x4 b = scaling(5.0f, 5.0f, 5.0f);
struct mat4x4 c = translation(10.0f, 5.0f, 7.0f);
struct tuple p2 = mat4x4_mul_t(&a, &p);
struct tuple p3 = mat4x4_mul_t(&b, &p2);
struct tuple p4 = mat4x4_mul_t(&c, &p3);
return
tuple_equal(p2, point(1.0f, -1.0f, 0.0f)) &&
tuple_equal(p3, point(5.0f, -5.0f, 0.0f)) &&
tuple_equal(p4, point(15.0f, 0.0f, 7.0f));
}
static bool transformations_test_17(const char ** scenario)
{
*scenario = "Chained transformations must be applied in reverse order";
struct tuple p = point(1.0f, 0.0f, 1.0f);
struct mat4x4 a = rotation_x(tau / 4.0f);
struct mat4x4 b = scaling(5.0f, 5.0f, 5.0f);
struct mat4x4 c = translation(10.0f, 5.0f, 7.0f);
struct mat4x4 t1 = mat4x4_mul_m(&c, &b);
struct mat4x4 t2 = mat4x4_mul_m(&t1, &a);
struct tuple p1 = mat4x4_mul_t(&t2, &p);
return tuple_equal(p1, point(15.0f, 0.0f, 7.0f));
}
test_t transformations_tests[] = {
transformations_test_0,
transformations_test_1,
transformations_test_2,
transformations_test_3,
transformations_test_4,
transformations_test_5,
transformations_test_6,
transformations_test_7,
transformations_test_8,
transformations_test_9,
transformations_test_10,
transformations_test_11,
transformations_test_12,
transformations_test_13,
transformations_test_14,
transformations_test_15,
transformations_test_16,
transformations_test_17,
};
RUNNER(transformations_tests)