214 lines
5.9 KiB
C
214 lines
5.9 KiB
C
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
|
|
#include "intersections_shapes.h"
|
|
#include "transformations.h"
|
|
#include "runner.h"
|
|
|
|
static bool intersections_test_0(const char ** scenario)
|
|
{
|
|
*scenario = "An intersection encapsulates t and object";
|
|
|
|
struct shape s = sphere();
|
|
struct intersection i = intersection(3.5f, &s);
|
|
|
|
return
|
|
float_equal(i.t, 3.5f) &&
|
|
i.object == &s;
|
|
}
|
|
|
|
static bool intersections_test_1(const char ** scenario)
|
|
{
|
|
*scenario = "Aggregating intersections";
|
|
|
|
struct shape s = sphere();
|
|
struct intersection i1 = intersection(1.0f, &s);
|
|
struct intersection i2 = intersection(2.0f, &s);
|
|
struct intersections xs;
|
|
intersections(&xs, 2, i1, i2);
|
|
|
|
return
|
|
xs.count == 2 &&
|
|
float_equal(xs.i[0].t, 1.0f) &&
|
|
float_equal(xs.i[1].t, 2.0f);
|
|
}
|
|
|
|
static bool intersections_test_2(const char ** scenario)
|
|
{
|
|
*scenario = "The hit, when all intersections have positive t";
|
|
|
|
struct shape s = sphere();
|
|
struct intersection i1 = intersection(1.0f, &s);
|
|
struct intersection i2 = intersection(2.0f, &s);
|
|
struct intersections xs;
|
|
intersections(&xs, 2, i2, i1);
|
|
|
|
struct intersection * i = hit((struct intersections *)&xs);
|
|
|
|
return
|
|
i != NULL &&
|
|
i->t == i1.t &&
|
|
i->object == i1.object;
|
|
}
|
|
|
|
static bool intersections_test_3(const char ** scenario)
|
|
{
|
|
*scenario = "The hit, when some intersections have negative t";
|
|
|
|
struct shape s = sphere();
|
|
struct intersection i1 = intersection(-1.0f, &s);
|
|
struct intersection i2 = intersection( 1.0f, &s);
|
|
struct intersections xs;
|
|
intersections(&xs, 2, i2, i1);
|
|
|
|
struct intersection * i = hit((struct intersections *)&xs);
|
|
|
|
return
|
|
i != NULL &&
|
|
i->t == i2.t &&
|
|
i->object == i2.object;
|
|
}
|
|
|
|
static bool intersections_test_4(const char ** scenario)
|
|
{
|
|
*scenario = "The hit, when all intersections have negative t";
|
|
|
|
struct shape s = sphere();
|
|
struct intersection i1 = intersection(-2.0f, &s);
|
|
struct intersection i2 = intersection(-1.0f, &s);
|
|
struct intersections xs;
|
|
intersections(&xs, 2, i2, i1);
|
|
|
|
struct intersection * i = hit((struct intersections *)&xs);
|
|
|
|
return i == NULL;
|
|
}
|
|
|
|
static bool intersections_test_5(const char ** scenario)
|
|
{
|
|
*scenario = "The hit is always the lowest nonnegative intersection";
|
|
|
|
struct shape s = sphere();
|
|
struct intersection i1 = intersection( 5.0f, &s);
|
|
struct intersection i2 = intersection( 7.0f, &s);
|
|
struct intersection i3 = intersection(-3.0f, &s);
|
|
struct intersection i4 = intersection( 2.0f, &s);
|
|
struct intersections xs;
|
|
intersections(&xs, 4, i1, i2, i3, i4);
|
|
|
|
struct intersection * i = hit((struct intersections *)&xs);
|
|
|
|
return
|
|
i != NULL &&
|
|
i->t == i4.t &&
|
|
i->object == i4.object;
|
|
}
|
|
|
|
static bool intersections_test_6(const char ** scenario)
|
|
{
|
|
*scenario = "In-place ascending sort of intersections";
|
|
|
|
struct shape s1 = sphere();
|
|
s1.material.ambient = 1.0f;
|
|
struct shape s2 = sphere();
|
|
s2.material.ambient = 2.0f;
|
|
struct shape s3 = sphere();
|
|
s3.material.ambient = 3.0f;
|
|
struct shape s4 = sphere();
|
|
s4.material.ambient = 4.0f;
|
|
struct intersection i1 = intersection( 5.0f, &s1);
|
|
struct intersection i2 = intersection( 7.0f, &s2);
|
|
struct intersection i3 = intersection(-3.0f, &s3);
|
|
struct intersection i4 = intersection( 2.0f, &s4);
|
|
struct intersections xs;
|
|
intersections(&xs, 4, i1, i2, i3, i4);
|
|
|
|
intersections_sort(&xs);
|
|
|
|
return
|
|
float_equal(xs.i[0].t, -3.0f) &&
|
|
float_equal(xs.i[0].object->material.ambient, 3.0f) &&
|
|
float_equal(xs.i[1].t, 2.0f) &&
|
|
float_equal(xs.i[1].object->material.ambient, 4.0f) &&
|
|
float_equal(xs.i[2].t, 5.0f) &&
|
|
float_equal(xs.i[2].object->material.ambient, 1.0f) &&
|
|
float_equal(xs.i[3].t, 7.0f) &&
|
|
float_equal(xs.i[3].object->material.ambient, 2.0f);
|
|
}
|
|
|
|
static bool intersections_test_7(const char ** scenario)
|
|
{
|
|
*scenario = "Precomputing the state of an intersection";
|
|
|
|
struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f));
|
|
struct shape shape = sphere();
|
|
struct intersection i = intersection(4.0f, &shape);
|
|
struct computations comps = prepare_computations(i, r);
|
|
|
|
return
|
|
float_equal(comps.t, i.t) &&
|
|
comps.object == &shape &&
|
|
tuple_equal(comps.point, point(0.0f, 0.0f, -1.0f)) &&
|
|
tuple_equal(comps.eyev, vector(0.0f, 0.0f, -1.0f)) &&
|
|
tuple_equal(comps.normalv, vector(0.0f, 0.0f, -1.0f));
|
|
}
|
|
|
|
static bool intersections_test_8(const char ** scenario)
|
|
{
|
|
*scenario = "The hit, when an intersection occurs on the outside";
|
|
|
|
struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f));
|
|
struct shape shape = sphere();
|
|
struct intersection i = intersection(4.0f, &shape);
|
|
struct computations comps = prepare_computations(i, r);
|
|
|
|
return
|
|
comps.inside == false;
|
|
}
|
|
|
|
static bool intersections_test_9(const char ** scenario)
|
|
{
|
|
*scenario = "The hit, when an intersection occurs on the inside";
|
|
|
|
struct ray r = ray(point(0.0f, 0.0f, 0.0f), vector(0.0f, 0.0f, 1.0f));
|
|
struct shape shape = sphere();
|
|
struct intersection i = intersection(1.0f, &shape);
|
|
struct computations comps = prepare_computations(i, r);
|
|
|
|
return
|
|
tuple_equal(comps.point, point(0.0f, 0.0f, 1.0f)) &&
|
|
tuple_equal(comps.eyev, vector(0.0f, 0.0f, -1.0f)) &&
|
|
comps.inside == true &&
|
|
tuple_equal(comps.normalv, vector(0.0f, 0.0f, -1.0f));
|
|
}
|
|
|
|
static bool intersections_test_10(const char ** scenario)
|
|
{
|
|
*scenario = "The hit should offset the point";
|
|
|
|
struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f));
|
|
struct shape shape = sphere();
|
|
shape.transform = translation(0.0f, 0.0f, 1.0f);
|
|
struct intersection i = intersection(5.0f, &shape);
|
|
struct computations comps = prepare_computations(i, r);
|
|
return
|
|
comps.over_point.z < -epsilon / 2.0f &&
|
|
comps.point.z > comps.over_point.z;
|
|
}
|
|
|
|
test_t intersections_tests[] = {
|
|
intersections_test_0,
|
|
intersections_test_1,
|
|
intersections_test_2,
|
|
intersections_test_3,
|
|
intersections_test_4,
|
|
intersections_test_5,
|
|
intersections_test_6,
|
|
intersections_test_7,
|
|
intersections_test_8,
|
|
intersections_test_9,
|
|
intersections_test_10,
|
|
};
|
|
|
|
RUNNER(intersections_tests);
|