212 lines
6.5 KiB
C
212 lines
6.5 KiB
C
#include <unity.h>
|
|
|
|
#include "triangle.h"
|
|
|
|
#include "../testutils.h"
|
|
|
|
void setUp(void) {}
|
|
void tearDown(void) {}
|
|
|
|
void test_construct_a_triangle(void) {
|
|
TRIANGLE_Triangle *t = TRIANGLE_new(0, 1, 0, -1, 0, 0, 1, 0, 0);
|
|
TUPLES_Vector expected_e1, expected_e2, expected_normal;
|
|
TUPLES_init_vector(&expected_e1, -1, -1, 0);
|
|
TUPLES_init_vector(&expected_e2, 1, -1, 0);
|
|
TUPLES_init_vector(&expected_normal, 0, 0, -1);
|
|
test_tuples(&expected_e1, &t->e1);
|
|
test_tuples(&expected_e2, &t->e2);
|
|
test_tuples(&expected_normal, &t->normal);
|
|
TRIANGLE_delete(t);
|
|
}
|
|
|
|
void test_construct_a_triangle_from_points(void) {
|
|
TUPLES_Point p1, p2, p3;
|
|
TUPLES_init_point(&p1, 0, 1, 0);
|
|
TUPLES_init_point(&p2, -1, 0, 0);
|
|
TUPLES_init_point(&p3, 1, 0, 0);
|
|
TRIANGLE_Triangle *t = TRIANGLE_new_from_points(&p1, &p2, &p3);
|
|
TUPLES_Vector expected_e1, expected_e2, expected_normal;
|
|
TUPLES_init_vector(&expected_e1, -1, -1, 0);
|
|
TUPLES_init_vector(&expected_e2, 1, -1, 0);
|
|
TUPLES_init_vector(&expected_normal, 0, 0, -1);
|
|
test_tuples(&expected_e1, &t->e1);
|
|
test_tuples(&expected_e2, &t->e2);
|
|
test_tuples(&expected_normal, &t->normal);
|
|
TRIANGLE_delete(t);
|
|
}
|
|
|
|
void test_find_normal_on_a_triangle(void) {
|
|
TRIANGLE_Triangle *t = TRIANGLE_new(0, 1, 0, -1, 0, 0, 1, 0, 0);
|
|
TUPLES_Vector n1, n2, n3;
|
|
TUPLES_Point p1, p2, p3;
|
|
TUPLES_init_point(&p1, 0, 0.5, 0);
|
|
TUPLES_init_point(&p2, -0.5, 0.75, 0);
|
|
TUPLES_init_point(&p3, 0.5, 0.25, 0);
|
|
TRIANGLE_local_normal_at(&n1, (SHAPE_Shape *)t, &p1, NULL);
|
|
TRIANGLE_local_normal_at(&n2, (SHAPE_Shape *)t, &p2, NULL);
|
|
TRIANGLE_local_normal_at(&n3, (SHAPE_Shape *)t, &p3, NULL);
|
|
test_tuples(&t->normal, &n1);
|
|
test_tuples(&t->normal, &n2);
|
|
test_tuples(&t->normal, &n3);
|
|
TRIANGLE_delete(t);
|
|
}
|
|
|
|
void test_intersecting_ray_parallel_to_triangle(void) {
|
|
TRIANGLE_Triangle *t = TRIANGLE_new(0, 1, 0, -1, 0, 0, 1, 0, 0);
|
|
RAY_Ray ray;
|
|
RAY_init(&ray, 0, -1, -2, 0, 1, 0);
|
|
|
|
RAY_Intersections *xs = RAY_new_intersections();
|
|
TRIANGLE_local_intersect(xs, (SHAPE_Shape *)t, &ray);
|
|
TEST_ASSERT_EQUAL(0, xs->count);
|
|
RAY_delete_intersections(xs);
|
|
TRIANGLE_delete(t);
|
|
}
|
|
|
|
void helper_ray_misses_triangle(double ray_x, double ray_y, double ray_z) {
|
|
TRIANGLE_Triangle *t = TRIANGLE_new(0, 1, 0, -1, 0, 0, 1, 0, 0);
|
|
RAY_Ray ray;
|
|
RAY_init(&ray, ray_x, ray_y, ray_z, 0, 0, 1);
|
|
|
|
RAY_Intersections *xs = RAY_new_intersections();
|
|
TRIANGLE_local_intersect(xs, (SHAPE_Shape *)t, &ray);
|
|
TEST_ASSERT_EQUAL(0, xs->count);
|
|
RAY_delete_intersections(xs);
|
|
TRIANGLE_delete(t);
|
|
}
|
|
|
|
void test_ray_misses_p1_p3_edge(void) { helper_ray_misses_triangle(1, 1, -2); }
|
|
|
|
void test_ray_misses_p1_p2_edge(void) { helper_ray_misses_triangle(-1, 1, -2); }
|
|
|
|
void test_ray_misses_p2_p3_edge(void) { helper_ray_misses_triangle(0, -1, -2); }
|
|
|
|
void test_ray_strikes_triangle(void) {
|
|
TRIANGLE_Triangle *t = TRIANGLE_new(0, 1, 0, -1, 0, 0, 1, 0, 0);
|
|
RAY_Ray ray;
|
|
RAY_init(&ray, 0, 0.5, -2, 0, 0, 1);
|
|
|
|
RAY_Intersections *xs = RAY_new_intersections();
|
|
TRIANGLE_local_intersect(xs, (SHAPE_Shape *)t, &ray);
|
|
TEST_ASSERT_EQUAL(1, xs->count);
|
|
TEST_ASSERT_EQUAL_DOUBLE(2.0, xs->xs[0].t);
|
|
TEST_ASSERT_EQUAL_PTR(t, xs->xs[0].object);
|
|
RAY_delete_intersections(xs);
|
|
TRIANGLE_delete(t);
|
|
}
|
|
|
|
TRIANGLE_SmoothTriangle *create_smoothtriangle(void) {
|
|
TUPLES_Point p1, p2, p3;
|
|
TUPLES_init_point(&p1, 0, 1, 0);
|
|
TUPLES_init_point(&p2, -1, 0, 0);
|
|
TUPLES_init_point(&p3, 1, 0, 0);
|
|
|
|
TUPLES_Vector v1, v2, v3;
|
|
TUPLES_init_vector(&v1, 0, 1, 0);
|
|
TUPLES_init_vector(&v2, -1, 0, 0);
|
|
TUPLES_init_vector(&v3, 1, 0, 0);
|
|
TRIANGLE_SmoothTriangle *st = TRIANGLE_new_smooth_from_points(&p1, &p2, &p3, &v1, &v2, &v3);
|
|
TEST_ASSERT_NOT_NULL(st);
|
|
test_tuples(&p1, &st->p1);
|
|
test_tuples(&p2, &st->p2);
|
|
test_tuples(&p3, &st->p3);
|
|
test_tuples(&v1, &st->n1);
|
|
test_tuples(&v2, &st->n2);
|
|
test_tuples(&v3, &st->n3);
|
|
return st;
|
|
}
|
|
|
|
void test_create_smooth_triangle(void) {
|
|
TRIANGLE_SmoothTriangle *st = create_smoothtriangle();
|
|
TRIANGLE_delete_smooth(st);
|
|
}
|
|
|
|
void test_intersection_with_smooth_triangle_stores_u_and_v(void) {
|
|
TRIANGLE_SmoothTriangle *st = create_smoothtriangle();
|
|
|
|
RAY_Ray ray;
|
|
RAY_init(&ray, -0.2, 0.3, -2, 0, 0, 1);
|
|
|
|
RAY_Intersections *xs = RAY_new_intersections();
|
|
TRIANGLE_local_intersect(xs, (SHAPE_Shape *)st, &ray);
|
|
|
|
TEST_ASSERT_EQUAL_DOUBLE(0.45, xs->xs[0].u);
|
|
TEST_ASSERT_EQUAL_DOUBLE(0.25, xs->xs[0].v);
|
|
|
|
RAY_delete_intersections(xs);
|
|
TRIANGLE_delete_smooth(st);
|
|
}
|
|
|
|
void test_smooth_triangle_uses_u_v_to_interpolate_normal(void) {
|
|
TRIANGLE_SmoothTriangle *st = create_smoothtriangle();
|
|
|
|
RAY_Intersections *xs = RAY_new_intersections();
|
|
RAY_add_intersection_tri(xs, 1, (SHAPE_Shape *)st, 0.45, 0.25);
|
|
|
|
TUPLES_Point p;
|
|
TUPLES_init_point(&p, 0, 0, 0);
|
|
|
|
TUPLES_Vector expected, computed;
|
|
TUPLES_init_vector(&expected, -0.5547, 0.83205, 0);
|
|
|
|
SHAPE_normal_at(&computed, (SHAPE_Shape *)st, &p, &xs->xs[0]);
|
|
|
|
test_tuples(&expected, &computed);
|
|
|
|
RAY_delete_intersections(xs);
|
|
TRIANGLE_delete_smooth(st);
|
|
}
|
|
|
|
void test_prepare_normal_on_smooth_triangle(void) {
|
|
TRIANGLE_SmoothTriangle *st = create_smoothtriangle();
|
|
|
|
RAY_Intersections *xs = RAY_new_intersections();
|
|
RAY_add_intersection_tri(xs, 1, (SHAPE_Shape *)st, 0.45, 0.25);
|
|
|
|
RAY_Ray ray;
|
|
RAY_init(&ray, -0.2, 0.3, -2, 0, 0, 1);
|
|
|
|
RAY_Computations comps;
|
|
RAY_prepare_computations(&comps, &xs->xs[0], &ray, xs);
|
|
|
|
TUPLES_Vector expected;
|
|
TUPLES_init_vector(&expected, -0.5547, 0.83205, 0);
|
|
|
|
test_tuples(&expected, &comps.normalv);
|
|
|
|
RAY_delete_intersections(xs);
|
|
TRIANGLE_delete_smooth(st);
|
|
}
|
|
|
|
void test_triangle_bounding_box(void) {
|
|
TRIANGLE_Triangle *t = TRIANGLE_new(-3, 7, 2, 6, 2, -4, 2, -1, -1);
|
|
BOUND_Box box;
|
|
t->vtable->bounds_of((SHAPE_Shape *)t, &box);
|
|
TUPLES_Point min_expected, max_expected;
|
|
TUPLES_init_point(&min_expected, -3, -1, -4);
|
|
TUPLES_init_point(&max_expected, 6, 7, 2);
|
|
TEST_ASSERT_TRUE(TUPLES_is_equal(&min_expected, &box.min));
|
|
TEST_ASSERT_TRUE(TUPLES_is_equal(&max_expected, &box.max));
|
|
TRIANGLE_delete(t);
|
|
}
|
|
|
|
int main(void)
|
|
|
|
{
|
|
UNITY_BEGIN();
|
|
RUN_TEST(test_construct_a_triangle);
|
|
RUN_TEST(test_construct_a_triangle_from_points);
|
|
RUN_TEST(test_find_normal_on_a_triangle);
|
|
RUN_TEST(test_intersecting_ray_parallel_to_triangle);
|
|
RUN_TEST(test_ray_misses_p1_p2_edge);
|
|
RUN_TEST(test_ray_misses_p1_p3_edge);
|
|
RUN_TEST(test_ray_misses_p2_p3_edge);
|
|
RUN_TEST(test_ray_strikes_triangle);
|
|
RUN_TEST(test_create_smooth_triangle);
|
|
RUN_TEST(test_intersection_with_smooth_triangle_stores_u_and_v);
|
|
RUN_TEST(test_smooth_triangle_uses_u_v_to_interpolate_normal);
|
|
RUN_TEST(test_prepare_normal_on_smooth_triangle);
|
|
RUN_TEST(test_triangle_bounding_box);
|
|
return UNITY_END();
|
|
}
|