260 lines
6.7 KiB
C
260 lines
6.7 KiB
C
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
|
|
#include "rays.h"
|
|
#include "spheres.h"
|
|
#include "intersections.h"
|
|
#include "runner.h"
|
|
#include "matrices.h"
|
|
#include "transformations.h"
|
|
|
|
static bool spheres_test_0(const char ** scenario)
|
|
{
|
|
*scenario = "A ray intersects a sphere at two points";
|
|
|
|
struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f));
|
|
struct sphere s = sphere();
|
|
struct intersections2 xs = intersect(&s, r);
|
|
|
|
return
|
|
xs.count == 2 &&
|
|
float_equal(xs.i[0].t, 4.0f) &&
|
|
float_equal(xs.i[1].t, 6.0f);
|
|
}
|
|
|
|
static bool spheres_test_1(const char ** scenario)
|
|
{
|
|
*scenario = "A ray intersects a sphere at a tangent";
|
|
|
|
struct ray r = ray(point(0.0f, 1.0f, -5.0f), vector(0.0f, 0.0f, 1.0f));
|
|
struct sphere s = sphere();
|
|
struct intersections2 xs = intersect(&s, r);
|
|
|
|
return
|
|
xs.count == 2 &&
|
|
float_equal(xs.i[0].t, 5.0f) &&
|
|
float_equal(xs.i[1].t, 5.0f);
|
|
}
|
|
|
|
static bool spheres_test_2(const char ** scenario)
|
|
{
|
|
*scenario = "A ray misses a sphere";
|
|
|
|
struct ray r = ray(point(0.0f, 2.0f, -5.0f), vector(0.0f, 0.0f, 1.0f));
|
|
struct sphere s = sphere();
|
|
struct intersections2 xs = intersect(&s, r);
|
|
|
|
return xs.count == 0;
|
|
}
|
|
|
|
static bool spheres_test_3(const char ** scenario)
|
|
{
|
|
*scenario = "A ray originates in a sphere";
|
|
|
|
struct ray r = ray(point(0.0f, 0.0f, 0.0f), vector(0.0f, 0.0f, 1.0f));
|
|
struct sphere s = sphere();
|
|
struct intersections2 xs = intersect(&s, r);
|
|
|
|
return
|
|
xs.count == 2 &&
|
|
float_equal(xs.i[0].t, -1.0f) &&
|
|
float_equal(xs.i[1].t, 1.0f);
|
|
}
|
|
|
|
static bool spheres_test_4(const char ** scenario)
|
|
{
|
|
*scenario = "A sphere is behind a ray";
|
|
|
|
struct ray r = ray(point(0.0f, 0.0f, 5.0f), vector(0.0f, 0.0f, 1.0f));
|
|
struct sphere s = sphere();
|
|
struct intersections2 xs = intersect(&s, r);
|
|
|
|
return
|
|
xs.count == 2 &&
|
|
float_equal(xs.i[0].t, -6.0f) &&
|
|
float_equal(xs.i[1].t, -4.0f);
|
|
}
|
|
|
|
static bool spheres_test_5(const char ** scenario)
|
|
{
|
|
*scenario = "Intersect sets the object on the intersection";
|
|
|
|
struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f));
|
|
struct sphere s = sphere();
|
|
struct intersections2 xs = intersect(&s, r);
|
|
|
|
return
|
|
xs.count == 2 &&
|
|
xs.i[0].object == &s &&
|
|
xs.i[1].object == &s;
|
|
}
|
|
|
|
static bool spheres_test_6(const char ** scenario)
|
|
{
|
|
*scenario = "A sphere's default transformation";
|
|
|
|
struct sphere s = sphere();
|
|
struct mat4x4 identity = mat4x4_identity();
|
|
|
|
return mat4x4_equal(&s.transform, &identity);
|
|
}
|
|
|
|
static bool spheres_test_7(const char ** scenario)
|
|
{
|
|
*scenario = "Changing a sphere's transformation";
|
|
|
|
struct sphere s = sphere();
|
|
struct mat4x4 t = translation(2.0f, 3.0f, 4.0f);
|
|
s.transform = t;
|
|
|
|
return mat4x4_equal(&s.transform, &t);
|
|
}
|
|
|
|
static bool spheres_test_8(const char ** scenario)
|
|
{
|
|
*scenario = "Intersecting a scaled sphere with a ray";
|
|
|
|
struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f));
|
|
struct sphere s = sphere();
|
|
s.transform = scaling(2.0f, 2.0f, 2.0f);
|
|
struct intersections2 xs = intersect(&s, r);
|
|
|
|
return
|
|
xs.count == 2 &&
|
|
float_equal(xs.i[0].t, 3.0f) &&
|
|
float_equal(xs.i[1].t, 7.0f);
|
|
}
|
|
|
|
static bool spheres_test_9(const char ** scenario)
|
|
{
|
|
*scenario = "Intersecting a translated sphere with a ray";
|
|
|
|
struct ray r = ray(point(0.0f, 0.0f, 5.0f), vector(0.0f, 0.0f, 1.0f));
|
|
struct sphere s = sphere();
|
|
s.transform = translation(5.0f, 0.0f, 0.0f);
|
|
struct intersections2 xs = intersect(&s, r);
|
|
|
|
return xs.count == 0;
|
|
}
|
|
|
|
static bool spheres_test_10(const char ** scenario)
|
|
{
|
|
*scenario = "The normal on a sphere at a point on the x axis";
|
|
|
|
struct sphere s = sphere();
|
|
struct tuple n = sphere_normal_at(&s, point(1.0f, 0.0f, 0.0f));
|
|
return tuple_equal(n, vector(1.0f, 0.0f, 0.0f));
|
|
}
|
|
|
|
static bool spheres_test_11(const char ** scenario)
|
|
{
|
|
*scenario = "The normal on a sphere at a point on the y axis";
|
|
|
|
struct sphere s = sphere();
|
|
struct tuple n = sphere_normal_at(&s, point(0.0f, 1.0f, 0.0f));
|
|
return tuple_equal(n, vector(0.0f, 1.0f, 0.0f));
|
|
}
|
|
|
|
static bool spheres_test_12(const char ** scenario)
|
|
{
|
|
*scenario = "The normal on a sphere at a point on the z axis";
|
|
|
|
struct sphere s = sphere();
|
|
struct tuple n = sphere_normal_at(&s, point(0.0f, 0.0f, 1.0f));
|
|
return tuple_equal(n, vector(0.0f, 0.0f, 1.0f));
|
|
}
|
|
|
|
static bool spheres_test_13(const char ** scenario)
|
|
{
|
|
*scenario = "The normal on a sphere at a nonaxial point";
|
|
|
|
struct sphere s = sphere();
|
|
struct tuple n = sphere_normal_at(&s, point(0.5773502691896257,
|
|
0.5773502691896257,
|
|
0.5773502691896257));
|
|
return tuple_equal(n, vector(0.5773502691896257,
|
|
0.5773502691896257,
|
|
0.5773502691896257));
|
|
}
|
|
|
|
static bool spheres_test_14(const char ** scenario)
|
|
{
|
|
*scenario = "The normal is a normalized vector";
|
|
|
|
struct sphere s = sphere();
|
|
struct tuple n = sphere_normal_at(&s, point(0.5773502691896257,
|
|
0.5773502691896257,
|
|
0.5773502691896257));
|
|
return tuple_equal(n, tuple_normalize(n));
|
|
}
|
|
|
|
static bool spheres_test_15(const char ** scenario)
|
|
{
|
|
*scenario = "Computing the normal on a translated sphere";
|
|
|
|
struct sphere s = sphere();
|
|
s.transform = translation(0.0f, 1.0f, 0.0f);
|
|
struct tuple n = sphere_normal_at(&s, point(0.0f, 1.70711f, -0.70711));
|
|
|
|
return tuple_equal(n, vector(0.0f, 0.70711f, -0.70711f));
|
|
}
|
|
|
|
static bool spheres_test_16(const char ** scenario)
|
|
{
|
|
*scenario = "Computing the normal on a transformed sphere";
|
|
|
|
struct sphere s = sphere();
|
|
struct mat4x4 scale = scaling(1.0f, 0.5f, 1.0f);
|
|
struct mat4x4 rotate = rotation_z(pi / 5.0f);
|
|
struct mat4x4 m = mat4x4_mul_m(&scale, &rotate);
|
|
s.transform = m;
|
|
|
|
struct tuple n = sphere_normal_at(&s, point(0.0f, 0.7071067811865476, -0.7071067811865476));
|
|
|
|
return tuple_equal(n, vector(0.0f, 0.97014f, -0.24254f));
|
|
}
|
|
|
|
static bool spheres_test_17(const char ** scenario)
|
|
{
|
|
*scenario = "A sphere has a default material";
|
|
|
|
struct sphere s = sphere();
|
|
struct material m = s.material;
|
|
return material_equal(m, material());
|
|
}
|
|
|
|
static bool spheres_test_18(const char ** scenario)
|
|
{
|
|
*scenario = "A sphere may be assigned a material";
|
|
|
|
struct sphere s = sphere();
|
|
struct material m = material();
|
|
m.ambient = 1.0f;
|
|
s.material = m;
|
|
return material_equal(s.material, m);
|
|
}
|
|
|
|
test_t spheres_tests[] = {
|
|
spheres_test_0,
|
|
spheres_test_1,
|
|
spheres_test_2,
|
|
spheres_test_3,
|
|
spheres_test_4,
|
|
spheres_test_5,
|
|
spheres_test_6,
|
|
spheres_test_7,
|
|
spheres_test_8,
|
|
spheres_test_9,
|
|
spheres_test_10,
|
|
spheres_test_11,
|
|
spheres_test_12,
|
|
spheres_test_13,
|
|
spheres_test_14,
|
|
spheres_test_15,
|
|
spheres_test_16,
|
|
spheres_test_17,
|
|
spheres_test_18,
|
|
};
|
|
|
|
RUNNER(spheres_tests);
|