chapter 9
This commit is contained in:
parent
e312755e3d
commit
cbecc15fb8
2
.gitignore
vendored
2
.gitignore
vendored
@ -12,6 +12,8 @@ test/test_materials
|
||||
test/test_spheres
|
||||
test/test_world
|
||||
test/test_camera
|
||||
test/test_shapes
|
||||
test/test_planes
|
||||
raytracer
|
||||
*.ppm
|
||||
*.png
|
||||
|
6
camera.h
6
camera.h
@ -50,11 +50,11 @@ struct ray camera_ray_for_pixel(struct camera * camera, float px, float py)
|
||||
float world_x = camera->half_width - xoffset;
|
||||
float world_y = camera->half_height - yoffset;
|
||||
|
||||
struct mat4x4 t_inverse = mat4x4_inverse(&camera->transform);
|
||||
struct mat4x4 t_inverse = mat4x4_inverse(camera->transform);
|
||||
struct tuple world_point = point(world_x, world_y, -1.0f);
|
||||
struct tuple pixel = mat4x4_mul_t(&t_inverse, &world_point);
|
||||
struct tuple pixel = mat4x4_mul_t(t_inverse, world_point);
|
||||
struct tuple world_origin = point(0.0f, 0.0f, 0.0f);
|
||||
struct tuple origin = mat4x4_mul_t(&t_inverse, &world_origin);
|
||||
struct tuple origin = mat4x4_mul_t(t_inverse, world_origin);
|
||||
struct tuple direction = tuple_normalize(tuple_sub(pixel, origin));
|
||||
|
||||
return ray(origin, direction);
|
||||
|
133
intersections.h
133
intersections.h
@ -1,29 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "spheres.h"
|
||||
#include "rays.h"
|
||||
|
||||
struct intersection {
|
||||
float t;
|
||||
struct sphere const * object;
|
||||
struct shape const * object;
|
||||
};
|
||||
|
||||
struct intersection intersection(float t, struct sphere const * const object)
|
||||
{
|
||||
return (struct intersection){ t, object };
|
||||
}
|
||||
|
||||
#define MAX_INTERSECTIONS 1024
|
||||
#ifndef INTERSECTIONS_MAX
|
||||
#define INTERSECTIONS_MAX 1024
|
||||
#endif
|
||||
|
||||
struct intersections {
|
||||
int count;
|
||||
struct intersection i[MAX_INTERSECTIONS];
|
||||
struct intersection i[INTERSECTIONS_MAX];
|
||||
};
|
||||
|
||||
struct intersection intersection(float t, struct shape const * const object)
|
||||
{
|
||||
return (struct intersection){ t, object };
|
||||
}
|
||||
|
||||
inline static void intersections(struct intersections * intersections, int count, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@ -35,113 +32,3 @@ inline static void intersections(struct intersections * intersections, int count
|
||||
|
||||
intersections->count = count;
|
||||
}
|
||||
|
||||
inline static void intersect(struct sphere const * const s, struct ray r, struct intersections * intersections)
|
||||
{
|
||||
struct mat4x4 m = mat4x4_inverse(&s->transform);
|
||||
struct ray r2 = ray_transform(r, &m);
|
||||
struct tuple sphere_to_ray = tuple_sub(r2.origin, point(0.0f, 0.0f, 0.0f));
|
||||
|
||||
float a = tuple_dot(r2.direction, r2.direction);
|
||||
float b = 2 * tuple_dot(r2.direction, sphere_to_ray);
|
||||
float c = tuple_dot(sphere_to_ray, sphere_to_ray) - 1;
|
||||
|
||||
float discriminant = b * b - 4 * a * c;
|
||||
|
||||
if (discriminant < 0) {
|
||||
return;
|
||||
} else {
|
||||
float root = sqrtf(discriminant);
|
||||
float t1 = (-b - root) / (2 * a);
|
||||
float t2 = (-b + root) / (2 * a);
|
||||
|
||||
intersections->i[intersections->count++] = intersection(t1, s);
|
||||
intersections->i[intersections->count++] = intersection(t2, s);
|
||||
assert(intersections->count < MAX_INTERSECTIONS);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
inline static struct intersection * hit(struct intersections * xs)
|
||||
{
|
||||
struct intersection * i = NULL;
|
||||
for (int n = 0; n < xs->count; n++) {
|
||||
if (xs->i[n].t >= 0) {
|
||||
if (i == NULL || i->t > xs->i[n].t)
|
||||
i = &xs->i[n];
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
inline static void intersections_sort(struct intersections * xs)
|
||||
{
|
||||
#define left_child(i) (2 * i + 1)
|
||||
|
||||
int start = xs->count / 2;
|
||||
int end = xs->count;
|
||||
while (end > 1) {
|
||||
if (start > 0) {
|
||||
start = start - 1;
|
||||
} else {
|
||||
end = end - 1;
|
||||
struct intersection tmp = xs->i[0];
|
||||
xs->i[0] = xs->i[end];
|
||||
xs->i[end] = tmp;
|
||||
}
|
||||
|
||||
int root = start;
|
||||
while (left_child(root) < end) {
|
||||
int child = left_child(root);
|
||||
if (child + 1 < end && xs->i[child].t < xs->i[child+1].t) {
|
||||
child = child + 1;
|
||||
}
|
||||
if (xs->i[root].t < xs->i[child].t) {
|
||||
struct intersection tmp = xs->i[root];
|
||||
xs->i[root] = xs->i[child];
|
||||
xs->i[child] = tmp;
|
||||
root = child;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef left_child
|
||||
}
|
||||
|
||||
struct computations {
|
||||
float t;
|
||||
struct sphere const * object;
|
||||
struct tuple point;
|
||||
struct tuple eyev;
|
||||
struct tuple normalv;
|
||||
bool inside;
|
||||
struct tuple over_point;
|
||||
};
|
||||
|
||||
inline static struct computations prepare_computations(struct intersection intersection, struct ray ray)
|
||||
{
|
||||
struct tuple point = ray_position(ray, intersection.t);
|
||||
struct tuple eyev = tuple_neg(ray.direction);
|
||||
struct tuple normalv = sphere_normal_at(intersection.object, point);
|
||||
|
||||
bool inside = false;
|
||||
if (tuple_dot(normalv, eyev) < 0.0f) {
|
||||
inside = true;
|
||||
normalv = tuple_neg(normalv);
|
||||
}
|
||||
|
||||
struct tuple over_point = tuple_add(point, tuple_mul(normalv, epsilon * 100));
|
||||
|
||||
return (struct computations){
|
||||
intersection.t,
|
||||
intersection.object,
|
||||
point,
|
||||
eyev,
|
||||
normalv,
|
||||
inside,
|
||||
over_point
|
||||
};
|
||||
}
|
||||
|
153
intersections_shapes.h
Normal file
153
intersections_shapes.h
Normal file
@ -0,0 +1,153 @@
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "rays.h"
|
||||
#include "shapes.h"
|
||||
#include "intersections.h"
|
||||
#include "spheres.h"
|
||||
#include "planes.h"
|
||||
|
||||
#ifdef TEST
|
||||
struct ray intersections_saved_ray;
|
||||
#endif
|
||||
|
||||
inline static void intersect(struct shape const * const s, struct ray r, struct intersections * intersections)
|
||||
{
|
||||
struct mat4x4 m = mat4x4_inverse(s->transform);
|
||||
struct ray local_ray = ray_transform(r, m);
|
||||
|
||||
switch (s->type) {
|
||||
#ifdef TEST
|
||||
case SHAPE_TEST:
|
||||
intersections_saved_ray = local_ray;
|
||||
break;
|
||||
#endif
|
||||
case SHAPE_SPHERE:
|
||||
sphere_intersect(s, local_ray, intersections);
|
||||
break;
|
||||
case SHAPE_PLANE:
|
||||
plane_intersect(s, local_ray, intersections);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
assert(intersections->count < INTERSECTIONS_MAX);
|
||||
}
|
||||
|
||||
inline static struct intersection * hit(struct intersections * xs)
|
||||
{
|
||||
struct intersection * i = NULL;
|
||||
for (int n = 0; n < xs->count; n++) {
|
||||
if (xs->i[n].t >= 0) {
|
||||
if (i == NULL || i->t > xs->i[n].t)
|
||||
i = &xs->i[n];
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
inline static void intersections_sort(struct intersections * xs)
|
||||
{
|
||||
#define left_child(i) (2 * i + 1)
|
||||
|
||||
int start = xs->count / 2;
|
||||
int end = xs->count;
|
||||
while (end > 1) {
|
||||
if (start > 0) {
|
||||
start = start - 1;
|
||||
} else {
|
||||
end = end - 1;
|
||||
struct intersection tmp = xs->i[0];
|
||||
xs->i[0] = xs->i[end];
|
||||
xs->i[end] = tmp;
|
||||
}
|
||||
|
||||
int root = start;
|
||||
while (left_child(root) < end) {
|
||||
int child = left_child(root);
|
||||
if (child + 1 < end && xs->i[child].t < xs->i[child+1].t) {
|
||||
child = child + 1;
|
||||
}
|
||||
if (xs->i[root].t < xs->i[child].t) {
|
||||
struct intersection tmp = xs->i[root];
|
||||
xs->i[root] = xs->i[child];
|
||||
xs->i[child] = tmp;
|
||||
root = child;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef left_child
|
||||
}
|
||||
|
||||
struct computations {
|
||||
float t;
|
||||
struct shape const * object;
|
||||
struct tuple point;
|
||||
struct tuple eyev;
|
||||
struct tuple normalv;
|
||||
bool inside;
|
||||
struct tuple over_point;
|
||||
};
|
||||
|
||||
inline static struct tuple normal_at(struct shape const * const s, struct tuple world_point)
|
||||
{
|
||||
struct mat4x4 inv = mat4x4_inverse(s->transform);
|
||||
struct mat4x4 inv_t = mat4x4_transpose(inv);
|
||||
|
||||
struct tuple local_point = mat4x4_mul_t(inv, world_point);
|
||||
struct tuple local_normal;
|
||||
|
||||
switch (s->type) {
|
||||
#ifdef TEST
|
||||
case SHAPE_TEST:
|
||||
local_normal = vector(local_point.x, local_point.y, local_point.z);
|
||||
break;
|
||||
#endif
|
||||
case SHAPE_SPHERE:
|
||||
local_normal = sphere_normal_at(local_point);
|
||||
break;
|
||||
case SHAPE_PLANE:
|
||||
local_normal = plane_normal_at(local_point);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
struct tuple world_normal = mat4x4_mul_t(inv_t, local_normal);
|
||||
world_normal.w = 0.0f;
|
||||
|
||||
return tuple_normalize(world_normal);
|
||||
}
|
||||
|
||||
inline static struct computations prepare_computations(struct intersection intersection, struct ray ray)
|
||||
{
|
||||
struct tuple point = ray_position(ray, intersection.t);
|
||||
struct tuple eyev = tuple_neg(ray.direction);
|
||||
struct tuple normalv = normal_at(intersection.object, point);
|
||||
|
||||
bool inside = false;
|
||||
if (tuple_dot(normalv, eyev) < 0.0f) {
|
||||
inside = true;
|
||||
normalv = tuple_neg(normalv);
|
||||
}
|
||||
|
||||
struct tuple over_point = tuple_add(point, tuple_mul(normalv, epsilon * 100));
|
||||
|
||||
return (struct computations){
|
||||
intersection.t,
|
||||
intersection.object,
|
||||
point,
|
||||
eyev,
|
||||
normalv,
|
||||
inside,
|
||||
over_point
|
||||
};
|
||||
}
|
1
math.h
1
math.h
@ -6,6 +6,7 @@
|
||||
#define sinf __builtin_sinf
|
||||
#define powf __builtin_powf
|
||||
#define tanf __builtin_tanf
|
||||
#define fabsf __builtin_fabsf
|
||||
|
||||
static const float tau = 6.283185307179586f;
|
||||
static const float pi = tau / 2.0f;
|
||||
|
150
matrices.h
150
matrices.h
@ -48,61 +48,61 @@ inline static struct mat2x2 mat2x2(float a1, float a2,
|
||||
}};
|
||||
}
|
||||
|
||||
inline static bool mat4x4_equal(struct mat4x4 const * const a,
|
||||
struct mat4x4 const * const b)
|
||||
inline static bool mat4x4_equal(struct mat4x4 a,
|
||||
struct mat4x4 b)
|
||||
{
|
||||
return
|
||||
float_equal(a->e[0][0], b->e[0][0]) &&
|
||||
float_equal(a->e[0][1], b->e[0][1]) &&
|
||||
float_equal(a->e[0][2], b->e[0][2]) &&
|
||||
float_equal(a->e[0][3], b->e[0][3]) &&
|
||||
float_equal(a->e[1][0], b->e[1][0]) &&
|
||||
float_equal(a->e[1][1], b->e[1][1]) &&
|
||||
float_equal(a->e[1][2], b->e[1][2]) &&
|
||||
float_equal(a->e[1][3], b->e[1][3]) &&
|
||||
float_equal(a->e[2][0], b->e[2][0]) &&
|
||||
float_equal(a->e[2][1], b->e[2][1]) &&
|
||||
float_equal(a->e[2][2], b->e[2][2]) &&
|
||||
float_equal(a->e[2][3], b->e[2][3]) &&
|
||||
float_equal(a->e[3][0], b->e[3][0]) &&
|
||||
float_equal(a->e[3][1], b->e[3][1]) &&
|
||||
float_equal(a->e[3][2], b->e[3][2]) &&
|
||||
float_equal(a->e[3][3], b->e[3][3]);
|
||||
float_equal(a.e[0][0], b.e[0][0]) &&
|
||||
float_equal(a.e[0][1], b.e[0][1]) &&
|
||||
float_equal(a.e[0][2], b.e[0][2]) &&
|
||||
float_equal(a.e[0][3], b.e[0][3]) &&
|
||||
float_equal(a.e[1][0], b.e[1][0]) &&
|
||||
float_equal(a.e[1][1], b.e[1][1]) &&
|
||||
float_equal(a.e[1][2], b.e[1][2]) &&
|
||||
float_equal(a.e[1][3], b.e[1][3]) &&
|
||||
float_equal(a.e[2][0], b.e[2][0]) &&
|
||||
float_equal(a.e[2][1], b.e[2][1]) &&
|
||||
float_equal(a.e[2][2], b.e[2][2]) &&
|
||||
float_equal(a.e[2][3], b.e[2][3]) &&
|
||||
float_equal(a.e[3][0], b.e[3][0]) &&
|
||||
float_equal(a.e[3][1], b.e[3][1]) &&
|
||||
float_equal(a.e[3][2], b.e[3][2]) &&
|
||||
float_equal(a.e[3][3], b.e[3][3]);
|
||||
}
|
||||
|
||||
inline static bool mat3x3_equal(struct mat3x3 * a,
|
||||
struct mat3x3 * b)
|
||||
inline static bool mat3x3_equal(struct mat3x3 a,
|
||||
struct mat3x3 b)
|
||||
{
|
||||
return
|
||||
float_equal(a->e[0][0], b->e[0][0]) &&
|
||||
float_equal(a->e[0][1], b->e[0][1]) &&
|
||||
float_equal(a->e[0][2], b->e[0][2]) &&
|
||||
float_equal(a->e[1][0], b->e[1][0]) &&
|
||||
float_equal(a->e[1][1], b->e[1][1]) &&
|
||||
float_equal(a->e[1][2], b->e[1][2]) &&
|
||||
float_equal(a->e[2][0], b->e[2][0]) &&
|
||||
float_equal(a->e[2][1], b->e[2][1]) &&
|
||||
float_equal(a->e[2][2], b->e[2][2]);
|
||||
float_equal(a.e[0][0], b.e[0][0]) &&
|
||||
float_equal(a.e[0][1], b.e[0][1]) &&
|
||||
float_equal(a.e[0][2], b.e[0][2]) &&
|
||||
float_equal(a.e[1][0], b.e[1][0]) &&
|
||||
float_equal(a.e[1][1], b.e[1][1]) &&
|
||||
float_equal(a.e[1][2], b.e[1][2]) &&
|
||||
float_equal(a.e[2][0], b.e[2][0]) &&
|
||||
float_equal(a.e[2][1], b.e[2][1]) &&
|
||||
float_equal(a.e[2][2], b.e[2][2]);
|
||||
}
|
||||
|
||||
inline static bool mat2x2_equal(struct mat2x2 * a,
|
||||
struct mat2x2 * b)
|
||||
inline static bool mat2x2_equal(struct mat2x2 a,
|
||||
struct mat2x2 b)
|
||||
{
|
||||
return
|
||||
float_equal(a->e[0][0], b->e[0][0]) &&
|
||||
float_equal(a->e[0][1], b->e[0][1]) &&
|
||||
float_equal(a->e[1][0], b->e[1][0]) &&
|
||||
float_equal(a->e[1][1], b->e[1][1]);
|
||||
float_equal(a.e[0][0], b.e[0][0]) &&
|
||||
float_equal(a.e[0][1], b.e[0][1]) &&
|
||||
float_equal(a.e[1][0], b.e[1][0]) &&
|
||||
float_equal(a.e[1][1], b.e[1][1]);
|
||||
}
|
||||
|
||||
inline static struct mat4x4 mat4x4_mul_m(struct mat4x4 const * const a,
|
||||
struct mat4x4 const * const b)
|
||||
inline static struct mat4x4 mat4x4_mul_m(struct mat4x4 a,
|
||||
struct mat4x4 b)
|
||||
{
|
||||
#define dot(row, col) \
|
||||
a->e[row][0] * b->e[0][col] + \
|
||||
a->e[row][1] * b->e[1][col] + \
|
||||
a->e[row][2] * b->e[2][col] + \
|
||||
a->e[row][3] * b->e[3][col]
|
||||
a.e[row][0] * b.e[0][col] + \
|
||||
a.e[row][1] * b.e[1][col] + \
|
||||
a.e[row][2] * b.e[2][col] + \
|
||||
a.e[row][3] * b.e[3][col]
|
||||
|
||||
return mat4x4(dot(0, 0), dot(0, 1), dot(0, 2), dot(0, 3),
|
||||
dot(1, 0), dot(1, 1), dot(1, 2), dot(1, 3),
|
||||
@ -112,14 +112,14 @@ inline static struct mat4x4 mat4x4_mul_m(struct mat4x4 const * const a,
|
||||
#undef dot
|
||||
}
|
||||
|
||||
inline static struct tuple mat4x4_mul_t(struct mat4x4 const * const a,
|
||||
struct tuple * b)
|
||||
inline static struct tuple mat4x4_mul_t(struct mat4x4 a,
|
||||
struct tuple b)
|
||||
{
|
||||
#define dot(row) \
|
||||
a->e[row][0] * b->e[0] + \
|
||||
a->e[row][1] * b->e[1] + \
|
||||
a->e[row][2] * b->e[2] + \
|
||||
a->e[row][3] * b->e[3]
|
||||
a.e[row][0] * b.e[0] + \
|
||||
a.e[row][1] * b.e[1] + \
|
||||
a.e[row][2] * b.e[2] + \
|
||||
a.e[row][3] * b.e[3]
|
||||
|
||||
return tuple(dot(0), dot(1), dot(2), dot(3));
|
||||
#undef dot
|
||||
@ -133,20 +133,20 @@ inline static struct mat4x4 mat4x4_identity()
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
inline static struct mat4x4 mat4x4_transpose(struct mat4x4 const * const a)
|
||||
inline static struct mat4x4 mat4x4_transpose(struct mat4x4 a)
|
||||
{
|
||||
return mat4x4(a->e[0][0], a->e[1][0], a->e[2][0], a->e[3][0],
|
||||
a->e[0][1], a->e[1][1], a->e[2][1], a->e[3][1],
|
||||
a->e[0][2], a->e[1][2], a->e[2][2], a->e[3][2],
|
||||
a->e[0][3], a->e[1][3], a->e[2][3], a->e[3][3]);
|
||||
return mat4x4(a.e[0][0], a.e[1][0], a.e[2][0], a.e[3][0],
|
||||
a.e[0][1], a.e[1][1], a.e[2][1], a.e[3][1],
|
||||
a.e[0][2], a.e[1][2], a.e[2][2], a.e[3][2],
|
||||
a.e[0][3], a.e[1][3], a.e[2][3], a.e[3][3]);
|
||||
}
|
||||
|
||||
inline static float mat2x2_determinant(struct mat2x2 * a)
|
||||
inline static float mat2x2_determinant(struct mat2x2 a)
|
||||
{
|
||||
return a->e[0][0] * a->e[1][1] - a->e[0][1] * a->e[1][0];
|
||||
return a.e[0][0] * a.e[1][1] - a.e[0][1] * a.e[1][0];
|
||||
}
|
||||
|
||||
inline static struct mat2x2 mat3x3_submatrix(struct mat3x3 * a, int r, int c)
|
||||
inline static struct mat2x2 mat3x3_submatrix(struct mat3x3 a, int r, int c)
|
||||
{
|
||||
struct mat2x2 b;
|
||||
int row2 = 0;
|
||||
@ -155,7 +155,7 @@ inline static struct mat2x2 mat3x3_submatrix(struct mat3x3 * a, int r, int c)
|
||||
int col2 = 0;
|
||||
for (int col3 = 0; col3 < 3; col3++) {
|
||||
if (col3 == c) continue;
|
||||
b.e[row2][col2] = a->e[row3][col3];
|
||||
b.e[row2][col2] = a.e[row3][col3];
|
||||
col2++;
|
||||
}
|
||||
row2++;
|
||||
@ -163,7 +163,7 @@ inline static struct mat2x2 mat3x3_submatrix(struct mat3x3 * a, int r, int c)
|
||||
return b;
|
||||
}
|
||||
|
||||
inline static struct mat3x3 mat4x4_submatrix(struct mat4x4 const * const a, int r, int c)
|
||||
inline static struct mat3x3 mat4x4_submatrix(struct mat4x4 a, int r, int c)
|
||||
{
|
||||
struct mat3x3 b;
|
||||
int row3 = 0;
|
||||
@ -172,7 +172,7 @@ inline static struct mat3x3 mat4x4_submatrix(struct mat4x4 const * const a, int
|
||||
int col3 = 0;
|
||||
for (int col4 = 0; col4 < 4; col4++) {
|
||||
if (col4 == c) continue;
|
||||
b.e[row3][col3] = a->e[row4][col4];
|
||||
b.e[row3][col3] = a.e[row4][col4];
|
||||
col3++;
|
||||
}
|
||||
row3++;
|
||||
@ -180,14 +180,14 @@ inline static struct mat3x3 mat4x4_submatrix(struct mat4x4 const * const a, int
|
||||
return b;
|
||||
}
|
||||
|
||||
inline static float mat3x3_minor(struct mat3x3 * a, int r, int c)
|
||||
inline static float mat3x3_minor(struct mat3x3 a, int r, int c)
|
||||
{
|
||||
struct mat2x2 s = mat3x3_submatrix(a, r, c);
|
||||
float ret = mat2x2_determinant(&s);
|
||||
float ret = mat2x2_determinant(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static float mat3x3_cofactor(struct mat3x3 * a, int r, int c)
|
||||
inline static float mat3x3_cofactor(struct mat3x3 a, int r, int c)
|
||||
{
|
||||
float minor = mat3x3_minor(a, r, c);
|
||||
if ((r + c) & 1)
|
||||
@ -196,25 +196,25 @@ inline static float mat3x3_cofactor(struct mat3x3 * a, int r, int c)
|
||||
return minor;
|
||||
}
|
||||
|
||||
inline static float mat3x3_determinant(struct mat3x3 * a)
|
||||
inline static float mat3x3_determinant(struct mat3x3 a)
|
||||
{
|
||||
float f0 = mat3x3_cofactor(a, 0, 0);
|
||||
float f1 = mat3x3_cofactor(a, 0, 1);
|
||||
float f2 = mat3x3_cofactor(a, 0, 2);
|
||||
return
|
||||
a->e[0][0] * f0 +
|
||||
a->e[0][1] * f1 +
|
||||
a->e[0][2] * f2;
|
||||
a.e[0][0] * f0 +
|
||||
a.e[0][1] * f1 +
|
||||
a.e[0][2] * f2;
|
||||
}
|
||||
|
||||
inline static float mat4x4_minor(struct mat4x4 const * const a, int r, int c)
|
||||
inline static float mat4x4_minor(struct mat4x4 a, int r, int c)
|
||||
{
|
||||
struct mat3x3 s = mat4x4_submatrix(a, r, c);
|
||||
float ret = mat3x3_determinant(&s);
|
||||
float ret = mat3x3_determinant(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static float mat4x4_cofactor(struct mat4x4 const * const a, int r, int c)
|
||||
inline static float mat4x4_cofactor(struct mat4x4 a, int r, int c)
|
||||
{
|
||||
float minor = mat4x4_minor(a, r, c);
|
||||
if ((r + c) & 1)
|
||||
@ -223,25 +223,25 @@ inline static float mat4x4_cofactor(struct mat4x4 const * const a, int r, int c)
|
||||
return minor;
|
||||
}
|
||||
|
||||
inline static float mat4x4_determinant(struct mat4x4 const * const a)
|
||||
inline static float mat4x4_determinant(struct mat4x4 a)
|
||||
{
|
||||
float f0 = mat4x4_cofactor(a, 0, 0);
|
||||
float f1 = mat4x4_cofactor(a, 0, 1);
|
||||
float f2 = mat4x4_cofactor(a, 0, 2);
|
||||
float f3 = mat4x4_cofactor(a, 0, 3);
|
||||
return
|
||||
a->e[0][0] * f0 +
|
||||
a->e[0][1] * f1 +
|
||||
a->e[0][2] * f2 +
|
||||
a->e[0][3] * f3;
|
||||
a.e[0][0] * f0 +
|
||||
a.e[0][1] * f1 +
|
||||
a.e[0][2] * f2 +
|
||||
a.e[0][3] * f3;
|
||||
}
|
||||
|
||||
inline static bool mat4x4_is_invertible(struct mat4x4 const * const a)
|
||||
inline static bool mat4x4_is_invertible(struct mat4x4 a)
|
||||
{
|
||||
return !float_equal(mat4x4_determinant(a), 0.f);
|
||||
}
|
||||
|
||||
inline static struct mat4x4 mat4x4_inverse(struct mat4x4 const * const a)
|
||||
inline static struct mat4x4 mat4x4_inverse(struct mat4x4 a)
|
||||
{
|
||||
struct mat4x4 m;
|
||||
float det = mat4x4_determinant(a);
|
||||
|
35
planes.h
Normal file
35
planes.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "math.h"
|
||||
#include "matrices.h"
|
||||
#include "materials.h"
|
||||
#include "shapes.h"
|
||||
#include "rays.h"
|
||||
#include "intersections.h"
|
||||
|
||||
inline static struct shape plane()
|
||||
{
|
||||
return (struct shape){
|
||||
mat4x4_identity(),
|
||||
material(),
|
||||
SHAPE_PLANE,
|
||||
};
|
||||
}
|
||||
|
||||
inline static struct tuple plane_normal_at(struct tuple local_point)
|
||||
{
|
||||
return vector(0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
|
||||
inline static void plane_intersect(struct shape const * const s, struct ray local_ray, struct intersections * intersections)
|
||||
{
|
||||
if (fabsf(local_ray.direction.y) < epsilon) {
|
||||
return;
|
||||
}
|
||||
|
||||
float t = -local_ray.origin.y / local_ray.direction.y;
|
||||
|
||||
intersections->i[intersections->count++] = intersection(t, s);
|
||||
|
||||
return;
|
||||
}
|
7
rays.h
7
rays.h
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "spheres.h"
|
||||
#include "tuples.h"
|
||||
#include "matrices.h"
|
||||
|
||||
@ -19,8 +18,8 @@ inline static struct tuple ray_position(struct ray ray, float t)
|
||||
return tuple_add(ray.origin, tuple_mul(ray.direction, t));
|
||||
}
|
||||
|
||||
inline static struct ray ray_transform(struct ray r, struct mat4x4 const * const m)
|
||||
inline static struct ray ray_transform(struct ray r, struct mat4x4 m)
|
||||
{
|
||||
return ray(mat4x4_mul_t(m, &r.origin),
|
||||
mat4x4_mul_t(m, &r.direction));
|
||||
return ray(mat4x4_mul_t(m, r.origin),
|
||||
mat4x4_mul_t(m, r.direction));
|
||||
}
|
||||
|
125
raytracer.c
125
raytracer.c
@ -22,59 +22,60 @@ int main()
|
||||
float pixel_size = wall_size / (float)canvas_pixels;
|
||||
float half = wall_size / 2.0f;
|
||||
|
||||
struct sphere floor = sphere();
|
||||
floor.transform = scaling(10.0f, 0.01f, 10.0f);
|
||||
struct shape floor = plane();
|
||||
floor.material.color = color(1.0f, 0.9f, 0.9f);
|
||||
floor.material.specular = 0.0f;
|
||||
|
||||
struct sphere left_wall = sphere();
|
||||
/*
|
||||
struct shape left_wall = sphere();
|
||||
{
|
||||
struct mat4x4 _translation = translation(0.0f, 0.0f, 5.0f);
|
||||
struct mat4x4 _rotation_y = rotation_y(-pi / 4.0f);
|
||||
struct mat4x4 _rotation_x = rotation_x(pi / 2.0f);
|
||||
struct mat4x4 _scaling = scaling(10.0f, 0.05f, 10.0f);
|
||||
|
||||
struct mat4x4 t0 = mat4x4_mul_m(&_rotation_x, &_scaling);
|
||||
struct mat4x4 t1 = mat4x4_mul_m(&_rotation_y, &t0);
|
||||
struct mat4x4 t2 = mat4x4_mul_m(&_translation, &t1);
|
||||
struct mat4x4 t0 = mat4x4_mul_m(_rotation_x, _scaling);
|
||||
struct mat4x4 t1 = mat4x4_mul_m(_rotation_y, t0);
|
||||
struct mat4x4 t2 = mat4x4_mul_m(_translation, t1);
|
||||
|
||||
left_wall.transform = t2;
|
||||
}
|
||||
left_wall.material = floor.material;
|
||||
|
||||
struct sphere right_wall = sphere();
|
||||
struct shape right_wall = sphere();
|
||||
{
|
||||
struct mat4x4 _translation = translation(0.0f, 0.0f, 5.0f);
|
||||
struct mat4x4 _rotation_y = rotation_y(pi / 4.0f);
|
||||
struct mat4x4 _rotation_x = rotation_x(pi / 2.0f);
|
||||
struct mat4x4 _scaling = scaling(10.0f, 0.05f, 10.0f);
|
||||
|
||||
struct mat4x4 t0 = mat4x4_mul_m(&_rotation_x, &_scaling);
|
||||
struct mat4x4 t1 = mat4x4_mul_m(&_rotation_y, &t0);
|
||||
struct mat4x4 t2 = mat4x4_mul_m(&_translation, &t1);
|
||||
struct mat4x4 t0 = mat4x4_mul_m(_rotation_x, _scaling);
|
||||
struct mat4x4 t1 = mat4x4_mul_m(_rotation_y, t0);
|
||||
struct mat4x4 t2 = mat4x4_mul_m(_translation, t1);
|
||||
|
||||
right_wall.transform = t2;
|
||||
}
|
||||
right_wall.material = floor.material;
|
||||
*/
|
||||
|
||||
struct sphere middle = sphere();
|
||||
struct shape middle = sphere();
|
||||
middle.transform = translation(-0.5f, 1.0f, 0.5f);
|
||||
middle.material.color = color((float)0xfc / 255.f , (float)0x6d / 255.f, (float)0x09 / 255.f);
|
||||
middle.material.diffuse = 0.7;
|
||||
middle.material.specular = 0.3;
|
||||
|
||||
struct sphere right = sphere();
|
||||
struct shape right = sphere();
|
||||
struct mat4x4 right_t = translation(1.5f, 0.5f, -0.5f);
|
||||
struct mat4x4 right_s = scaling(0.5f, 0.5f, 0.5f);
|
||||
right.transform = mat4x4_mul_m(&right_t, &right_s);
|
||||
right.transform = mat4x4_mul_m(right_t, right_s);
|
||||
right.material.color = color(0.5f, 1.0f, 0.1f);
|
||||
right.material.diffuse = 0.7;
|
||||
right.material.specular = 0.3;
|
||||
|
||||
struct sphere left = sphere();
|
||||
struct shape left = sphere();
|
||||
struct mat4x4 left_t = translation(-1.5f, 0.33f, -0.75f);
|
||||
struct mat4x4 left_s = scaling(0.33f, 0.33f, 0.33f);
|
||||
left.transform = mat4x4_mul_m(&left_t, &left_s);
|
||||
left.transform = mat4x4_mul_m(left_t, left_s);
|
||||
left.material.color = color((float)0x12 / 255.f, (float)0xc9 / 255.f, (float)0xcc / 255.f);
|
||||
left.material.diffuse = 0.7;
|
||||
left.material.specular = 0.3;
|
||||
@ -83,42 +84,104 @@ int main()
|
||||
struct tuple light_color = color(1.0f, 1.0f, 1.0f);
|
||||
struct light light = point_light(light_position, light_color);
|
||||
|
||||
|
||||
struct shape h1 = plane();
|
||||
struct shape h2 = plane();
|
||||
struct shape h3 = plane();
|
||||
struct shape h4 = plane();
|
||||
struct shape h5 = plane();
|
||||
struct shape h6 = plane();
|
||||
struct mat4x4 h1_t = translation(0, 8, 8);
|
||||
struct mat4x4 h2_t = translation(4, 0, 6.9282);
|
||||
struct mat4x4 h3_t = translation(-4, 0, 6.9282);
|
||||
struct mat4x4 h4_t = translation(0, -8, 8);
|
||||
struct mat4x4 h5_t = translation(-4, 0, -6.9282);
|
||||
struct mat4x4 h6_t = translation(4, 0, -6.9282);
|
||||
struct mat4x4 h1_r = rotation_x(tau / 4.0f);
|
||||
struct mat4x4 h2_r = rotation_x(tau / 4.0f);
|
||||
struct mat4x4 h3_r = rotation_x(tau / 4.0f);
|
||||
struct mat4x4 h4_r = rotation_x(tau / 4.0f);
|
||||
struct mat4x4 h5_r = rotation_x(tau / 4.0f);
|
||||
struct mat4x4 h6_r = rotation_x(tau / 4.0f);
|
||||
|
||||
struct mat4x4 h1_rr = rotation_y(tau / 4.0f * 0);
|
||||
h1.transform = mat4x4_mul_m(h1_t, h1_r);
|
||||
h1.transform = mat4x4_mul_m(h1_rr, h1.transform);
|
||||
|
||||
struct mat4x4 h2_rr = rotation_y(tau / 4.0f * 1);
|
||||
h2.transform = mat4x4_mul_m(h2_t, h2_r);
|
||||
h2.transform = mat4x4_mul_m(h2_rr, h2.transform);
|
||||
|
||||
struct mat4x4 h3_rr = rotation_y(tau / 4.0f * 2);
|
||||
h3.transform = mat4x4_mul_m(h3_t, h3_r);
|
||||
h3.transform = mat4x4_mul_m(h3_rr, h3.transform);
|
||||
|
||||
struct mat4x4 h4_rr = rotation_y(tau / 4.0f * 3);
|
||||
h4.transform = mat4x4_mul_m(h4_t, h4_r);
|
||||
h4.transform = mat4x4_mul_m(h4_rr, h4.transform);
|
||||
|
||||
struct mat4x4 h5_rr = rotation_y(tau / 4.0f);
|
||||
h5.transform = mat4x4_mul_m(h5_rr, h5_r);
|
||||
h5.transform = mat4x4_mul_m(h5_t, h5.transform);
|
||||
|
||||
struct mat4x4 h6_rr = rotation_y(tau / 4.0f);
|
||||
h6.transform = mat4x4_mul_m(h6_rr, h6_r);
|
||||
h6.transform = mat4x4_mul_m(h6_t, h6.transform);
|
||||
|
||||
h1.material = floor.material;
|
||||
h1.material.color = color(1.0f, 0.0f, 0.0f);
|
||||
h2.material = floor.material;
|
||||
h2.material.color = color(0.0f, 1.0f, 0.0f);
|
||||
h3.material = floor.material;
|
||||
h3.material.color = color(0.0f, 0.0f, 1.0f);
|
||||
h4.material = floor.material;
|
||||
h4.material.color = color(1.0f, 1.0f, 0.0f);
|
||||
h5.material = floor.material;
|
||||
h5.material.color = color(0.0f, 1.0f, 1.0f);
|
||||
h6.material = floor.material;
|
||||
h6.material.color = color(1.0f, 0.0f, 1.0f);
|
||||
|
||||
struct world world;
|
||||
world.light = light;
|
||||
world.object_count = 6;
|
||||
world.object_count = 4 + 4;
|
||||
world.objects[0] = floor;
|
||||
world.objects[1] = left_wall;
|
||||
world.objects[2] = right_wall;
|
||||
world.objects[3] = middle;
|
||||
world.objects[4] = right;
|
||||
world.objects[5] = left;
|
||||
world.objects[1] = middle;
|
||||
world.objects[2] = right;
|
||||
world.objects[3] = left;
|
||||
|
||||
struct camera _camera = camera(1600.0f, 800.0f, pi / 3.0f);
|
||||
world.objects[4] = h1;
|
||||
world.objects[5] = h2;
|
||||
world.objects[6] = h3;
|
||||
world.objects[7] = h4;
|
||||
world.objects[8] = h5;
|
||||
world.objects[9] = h6;
|
||||
|
||||
struct camera _camera = camera(1600.0f, 800.0f, pi / 4.f);
|
||||
_camera.transform = view_transform(point(0.0f, 1.5f, -5.0f),
|
||||
point(0.0f, 1.0f, 0.0f),
|
||||
vector(0.0f, 1.0f, 0.0f));
|
||||
|
||||
struct mat4x4 middle_t = world.objects[3].transform;
|
||||
struct mat4x4 middle_t = world.objects[1].transform;
|
||||
|
||||
for (int i = 0; i < 360; i++) {
|
||||
|
||||
_camera.transform = view_transform(point(5.0f * cosf(pi / 360 * (float)i / 10),
|
||||
1.5f,
|
||||
-5.0f * sinf(pi / 360 * (float)i / 10)),
|
||||
_camera.transform = view_transform(point(2.0f * cosf(pi / 360 * (float)i * 0.5),
|
||||
8.5f,
|
||||
1.0f * sinf(pi / 360 * (float)i * 0.5)),
|
||||
point(0.0f, 1.0f, 0.0f),
|
||||
vector(0.0f, 1.0f, 0.0f));
|
||||
|
||||
struct tuple light_position = point(-10.0f * cosf(pi / 360 * (float)i),
|
||||
struct tuple light_position = point(-6.0f * cosf(pi / 360 * (float)i * 3),
|
||||
10.0f,
|
||||
-10.0f * sinf(pi / 360 * (float)i));
|
||||
-6.0f * sinf(pi / 360 * (float)i * 3));
|
||||
world.light.position = light_position;
|
||||
|
||||
struct mat4x4 middle_s = scaling(1.0f, 0.4f, 1.0f);
|
||||
struct mat4x4 middle_rz = rotation_z(tau / 360.f * (float)i);
|
||||
struct mat4x4 middle_ry = rotation_y(tau / 360.f * (float)i);
|
||||
struct mat4x4 middle_r = mat4x4_mul_m(&middle_rz, &middle_ry);
|
||||
struct mat4x4 middle_transform = mat4x4_mul_m(&middle_r, &middle_s);
|
||||
world.objects[3].transform = mat4x4_mul_m(&middle_t, &middle_transform);
|
||||
struct mat4x4 middle_r = mat4x4_mul_m(middle_rz, middle_ry);
|
||||
struct mat4x4 middle_transform = mat4x4_mul_m(middle_r, middle_s);
|
||||
world.objects[1].transform = mat4x4_mul_m(middle_t, middle_transform);
|
||||
|
||||
camera_render(&_camera, &world, &_canvas);
|
||||
|
||||
|
25
shapes.h
Normal file
25
shapes.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "matrices.h"
|
||||
#include "materials.h"
|
||||
|
||||
enum shape_type {
|
||||
SHAPE_TEST,
|
||||
SHAPE_SPHERE,
|
||||
SHAPE_PLANE,
|
||||
};
|
||||
|
||||
struct shape {
|
||||
struct mat4x4 transform;
|
||||
struct material material;
|
||||
enum shape_type type;
|
||||
};
|
||||
|
||||
inline static struct shape shape()
|
||||
{
|
||||
return (struct shape){
|
||||
mat4x4_identity(),
|
||||
material(),
|
||||
SHAPE_TEST,
|
||||
};
|
||||
}
|
48
spheres.h
48
spheres.h
@ -2,27 +2,43 @@
|
||||
|
||||
#include "matrices.h"
|
||||
#include "materials.h"
|
||||
#include "shapes.h"
|
||||
#include "rays.h"
|
||||
#include "intersections.h"
|
||||
|
||||
struct sphere {
|
||||
struct mat4x4 transform;
|
||||
struct material material;
|
||||
};
|
||||
|
||||
inline static struct sphere sphere()
|
||||
inline static struct shape sphere()
|
||||
{
|
||||
return (struct sphere){
|
||||
return (struct shape){
|
||||
mat4x4_identity(),
|
||||
material()
|
||||
material(),
|
||||
SHAPE_SPHERE,
|
||||
};
|
||||
}
|
||||
|
||||
inline static struct tuple sphere_normal_at(struct sphere const * const s, struct tuple world_point)
|
||||
inline static struct tuple sphere_normal_at(struct tuple local_point)
|
||||
{
|
||||
struct mat4x4 inv = mat4x4_inverse(&s->transform);
|
||||
struct tuple object_point = mat4x4_mul_t(&inv, &world_point);
|
||||
struct tuple object_normal = tuple_sub(object_point, point(0.0f, 0.0f, 0.0f));
|
||||
struct mat4x4 inv_t = mat4x4_transpose(&inv);
|
||||
struct tuple world_normal = mat4x4_mul_t(&inv_t, &object_normal);
|
||||
world_normal.w = 0.0f;
|
||||
return tuple_normalize(world_normal);
|
||||
return tuple_sub(local_point, point(0.0f, 0.0f, 0.0f));
|
||||
}
|
||||
|
||||
inline static void sphere_intersect(struct shape const * const s, struct ray local_ray, struct intersections * intersections)
|
||||
{
|
||||
struct tuple sphere_to_ray = tuple_sub(local_ray.origin, point(0.0f, 0.0f, 0.0f));
|
||||
|
||||
float a = tuple_dot(local_ray.direction, local_ray.direction);
|
||||
float b = 2 * tuple_dot(local_ray.direction, sphere_to_ray);
|
||||
float c = tuple_dot(sphere_to_ray, sphere_to_ray) - 1;
|
||||
|
||||
float discriminant = b * b - 4 * a * c;
|
||||
|
||||
if (discriminant < 0) {
|
||||
return;
|
||||
} else {
|
||||
float root = sqrtf(discriminant);
|
||||
float t1 = (-b - root) / (2 * a);
|
||||
float t2 = (-b + root) / (2 * a);
|
||||
|
||||
intersections->i[intersections->count++] = intersection(t1, s);
|
||||
intersections->i[intersections->count++] = intersection(t2, s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,13 @@
|
||||
|
||||
set -eux
|
||||
|
||||
for name in tuples canvas matrices transformations rays intersections spheres lights materials world camera; do
|
||||
|
||||
for name in tuples canvas matrices transformations rays intersections shapes spheres planes lights materials world camera; do
|
||||
gcc -g -gdwarf-5 \
|
||||
-Wall -Werror -Wfatal-errors \
|
||||
-Wno-error=unused-variable \
|
||||
-I. \
|
||||
-DTEST \
|
||||
test/test_${name}.c -o test/test_${name} -O0 -lm
|
||||
./test/test_${name}
|
||||
done
|
||||
|
@ -21,7 +21,7 @@ static bool camera_test_0(const char ** scenario)
|
||||
float_equal(c.hsize, 160.0f) &&
|
||||
float_equal(c.vsize, 120.0f) &&
|
||||
float_equal(c.field_of_view, pi / 2.0f) &&
|
||||
mat4x4_equal(&c.transform, &identity_matrix);
|
||||
mat4x4_equal(c.transform, identity_matrix);
|
||||
}
|
||||
|
||||
static bool camera_test_1(const char ** scenario)
|
||||
@ -73,7 +73,7 @@ static bool camera_test_5(const char ** scenario)
|
||||
struct camera c = camera(201.0f, 101.0f, pi / 2.0f);
|
||||
struct mat4x4 rotate = rotation_y(pi / 4.0f);
|
||||
struct mat4x4 translate = translation(0.0f, -2.0f, 5.0f);
|
||||
c.transform = mat4x4_mul_m(&rotate, &translate);
|
||||
c.transform = mat4x4_mul_m(rotate, translate);
|
||||
struct ray r = camera_ray_for_pixel(&c, 100.0f, 50.0f);
|
||||
|
||||
return
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "intersections.h"
|
||||
#include "intersections_shapes.h"
|
||||
#include "transformations.h"
|
||||
#include "runner.h"
|
||||
|
||||
@ -9,7 +9,7 @@ static bool intersections_test_0(const char ** scenario)
|
||||
{
|
||||
*scenario = "An intersection encapsulates t and object";
|
||||
|
||||
struct sphere s = sphere();
|
||||
struct shape s = sphere();
|
||||
struct intersection i = intersection(3.5f, &s);
|
||||
|
||||
return
|
||||
@ -21,7 +21,7 @@ static bool intersections_test_1(const char ** scenario)
|
||||
{
|
||||
*scenario = "Aggregating intersections";
|
||||
|
||||
struct sphere s = sphere();
|
||||
struct shape s = sphere();
|
||||
struct intersection i1 = intersection(1.0f, &s);
|
||||
struct intersection i2 = intersection(2.0f, &s);
|
||||
struct intersections xs;
|
||||
@ -37,7 +37,7 @@ static bool intersections_test_2(const char ** scenario)
|
||||
{
|
||||
*scenario = "The hit, when all intersections have positive t";
|
||||
|
||||
struct sphere s = sphere();
|
||||
struct shape s = sphere();
|
||||
struct intersection i1 = intersection(1.0f, &s);
|
||||
struct intersection i2 = intersection(2.0f, &s);
|
||||
struct intersections xs;
|
||||
@ -55,7 +55,7 @@ static bool intersections_test_3(const char ** scenario)
|
||||
{
|
||||
*scenario = "The hit, when some intersections have negative t";
|
||||
|
||||
struct sphere s = sphere();
|
||||
struct shape s = sphere();
|
||||
struct intersection i1 = intersection(-1.0f, &s);
|
||||
struct intersection i2 = intersection( 1.0f, &s);
|
||||
struct intersections xs;
|
||||
@ -73,7 +73,7 @@ static bool intersections_test_4(const char ** scenario)
|
||||
{
|
||||
*scenario = "The hit, when all intersections have negative t";
|
||||
|
||||
struct sphere s = sphere();
|
||||
struct shape s = sphere();
|
||||
struct intersection i1 = intersection(-2.0f, &s);
|
||||
struct intersection i2 = intersection(-1.0f, &s);
|
||||
struct intersections xs;
|
||||
@ -88,7 +88,7 @@ static bool intersections_test_5(const char ** scenario)
|
||||
{
|
||||
*scenario = "The hit is always the lowest nonnegative intersection";
|
||||
|
||||
struct sphere s = sphere();
|
||||
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);
|
||||
@ -108,13 +108,13 @@ static bool intersections_test_6(const char ** scenario)
|
||||
{
|
||||
*scenario = "In-place ascending sort of intersections";
|
||||
|
||||
struct sphere s1 = sphere();
|
||||
struct shape s1 = sphere();
|
||||
s1.material.ambient = 1.0f;
|
||||
struct sphere s2 = sphere();
|
||||
struct shape s2 = sphere();
|
||||
s2.material.ambient = 2.0f;
|
||||
struct sphere s3 = sphere();
|
||||
struct shape s3 = sphere();
|
||||
s3.material.ambient = 3.0f;
|
||||
struct sphere s4 = sphere();
|
||||
struct shape s4 = sphere();
|
||||
s4.material.ambient = 4.0f;
|
||||
struct intersection i1 = intersection( 5.0f, &s1);
|
||||
struct intersection i2 = intersection( 7.0f, &s2);
|
||||
@ -141,7 +141,7 @@ 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 sphere shape = sphere();
|
||||
struct shape shape = sphere();
|
||||
struct intersection i = intersection(4.0f, &shape);
|
||||
struct computations comps = prepare_computations(i, r);
|
||||
|
||||
@ -158,7 +158,7 @@ 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 sphere shape = sphere();
|
||||
struct shape shape = sphere();
|
||||
struct intersection i = intersection(4.0f, &shape);
|
||||
struct computations comps = prepare_computations(i, r);
|
||||
|
||||
@ -171,7 +171,7 @@ 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 sphere shape = sphere();
|
||||
struct shape shape = sphere();
|
||||
struct intersection i = intersection(1.0f, &shape);
|
||||
struct computations comps = prepare_computations(i, r);
|
||||
|
||||
@ -187,7 +187,7 @@ 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 sphere shape = sphere();
|
||||
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);
|
||||
|
@ -58,7 +58,7 @@ static bool matrices_test_3(const char ** scenario)
|
||||
9.0f, 8.0f, 7.0f, 6.0f,
|
||||
5.0f, 4.0f, 3.0f, 2.0f);
|
||||
|
||||
return mat4x4_equal(&a, &b);
|
||||
return mat4x4_equal(a, b);
|
||||
}
|
||||
|
||||
static bool matrices_test_4(const char ** scenario)
|
||||
@ -75,7 +75,7 @@ static bool matrices_test_4(const char ** scenario)
|
||||
8.0f, 7.0f, 6.0f, 5.0f,
|
||||
4.0f, 3.0f, 2.0f, 1.0f);
|
||||
|
||||
return !mat4x4_equal(&a, &b);
|
||||
return !mat4x4_equal(a, b);
|
||||
}
|
||||
|
||||
static bool matrices_test_5(const char ** scenario)
|
||||
@ -92,12 +92,12 @@ static bool matrices_test_5(const char ** scenario)
|
||||
4.0f, 3.0f, 6.0f, 5.0f,
|
||||
1.0f, 2.0f, 7.0f, 8.0f);
|
||||
|
||||
struct mat4x4 m1 = mat4x4_mul_m(&a, &b);
|
||||
struct mat4x4 m1 = mat4x4_mul_m(a, b);
|
||||
struct mat4x4 m2 = mat4x4(20.0f, 22.0f, 50.0f, 48.0f,
|
||||
44.0f, 54.0f, 114.0f, 108.0f,
|
||||
40.0f, 58.0f, 110.0f, 102.0f,
|
||||
16.0f, 26.0f, 46.0f, 42.0f);
|
||||
return mat4x4_equal(&m1, &m2);
|
||||
return mat4x4_equal(m1, m2);
|
||||
}
|
||||
|
||||
static bool matrices_test_6(const char ** scenario)
|
||||
@ -110,7 +110,7 @@ static bool matrices_test_6(const char ** scenario)
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
struct tuple b = tuple(1.0f, 2.0f, 3.0f, 1.0f);
|
||||
|
||||
struct tuple c = mat4x4_mul_t(&a, &b);
|
||||
struct tuple c = mat4x4_mul_t(a, b);
|
||||
return tuple_equal(c, tuple(18, 24, 33, 1));
|
||||
}
|
||||
|
||||
@ -124,8 +124,8 @@ static bool matrices_test_7(const char ** scenario)
|
||||
4.0f, 8.0f, 16.0f, 32.0f);
|
||||
|
||||
struct mat4x4 id = mat4x4_identity();
|
||||
struct mat4x4 c = mat4x4_mul_m(&a, &id);
|
||||
return mat4x4_equal(&a, &c);
|
||||
struct mat4x4 c = mat4x4_mul_m(a, id);
|
||||
return mat4x4_equal(a, c);
|
||||
}
|
||||
|
||||
static bool matrices_test_8(const char ** scenario)
|
||||
@ -135,7 +135,7 @@ static bool matrices_test_8(const char ** scenario)
|
||||
struct tuple a = tuple(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
|
||||
struct mat4x4 id = mat4x4_identity();
|
||||
struct tuple c = mat4x4_mul_t(&id, &a);
|
||||
struct tuple c = mat4x4_mul_t(id, a);
|
||||
return tuple_equal(a, c);
|
||||
}
|
||||
|
||||
@ -153,9 +153,9 @@ static bool matrices_test_9(const char ** scenario)
|
||||
3.0f, 0.0f, 5.0f, 5.0f,
|
||||
0.0f, 8.0f, 3.0f, 8.0f);
|
||||
|
||||
struct mat4x4 c = mat4x4_transpose(&a);
|
||||
struct mat4x4 c = mat4x4_transpose(a);
|
||||
|
||||
return mat4x4_equal(&c, &b);
|
||||
return mat4x4_equal(c, b);
|
||||
}
|
||||
|
||||
static bool matrices_test_10(const char ** scenario)
|
||||
@ -164,9 +164,9 @@ static bool matrices_test_10(const char ** scenario)
|
||||
|
||||
struct mat4x4 a = mat4x4_identity();
|
||||
|
||||
struct mat4x4 c = mat4x4_transpose(&a);
|
||||
struct mat4x4 c = mat4x4_transpose(a);
|
||||
|
||||
return mat4x4_equal(&a, &c);
|
||||
return mat4x4_equal(a, c);
|
||||
}
|
||||
|
||||
static bool matrices_test_11(const char ** scenario)
|
||||
@ -176,7 +176,7 @@ static bool matrices_test_11(const char ** scenario)
|
||||
struct mat2x2 a = mat2x2( 1.0f, 5.0f,
|
||||
-3.0f, 2.0f);
|
||||
|
||||
return float_equal(mat2x2_determinant(&a), 17);
|
||||
return float_equal(mat2x2_determinant(a), 17);
|
||||
}
|
||||
|
||||
static bool matrices_test_12(const char ** scenario)
|
||||
@ -187,11 +187,11 @@ static bool matrices_test_12(const char ** scenario)
|
||||
-3.0f, 2.0f, 7.0f,
|
||||
0.0f, 6.0f, -3.0f);
|
||||
|
||||
struct mat2x2 b = mat3x3_submatrix(&a, 0, 2);
|
||||
struct mat2x2 b = mat3x3_submatrix(a, 0, 2);
|
||||
struct mat2x2 c = mat2x2(-3.0f, 2.0f,
|
||||
0.0f, 6.0f);
|
||||
|
||||
return mat2x2_equal(&b, &c);
|
||||
return mat2x2_equal(b, c);
|
||||
}
|
||||
|
||||
static bool matrices_test_13(const char ** scenario)
|
||||
@ -203,12 +203,12 @@ static bool matrices_test_13(const char ** scenario)
|
||||
-1.0f, 0.0f, 8.0f, 2.0f,
|
||||
-7.0f, 1.0f, -1.0f, 1.0f);
|
||||
|
||||
struct mat3x3 b = mat4x4_submatrix(&a, 2, 1);
|
||||
struct mat3x3 b = mat4x4_submatrix(a, 2, 1);
|
||||
struct mat3x3 c = mat3x3(-6.0f, 1.0f, 6.0f,
|
||||
-8.0f, 8.0f, 6.0f,
|
||||
-7.0f, -1.0f, 1.0f);
|
||||
|
||||
return mat3x3_equal(&b, &c);
|
||||
return mat3x3_equal(b, c);
|
||||
}
|
||||
|
||||
static bool matrices_test_14(const char ** scenario)
|
||||
@ -218,11 +218,11 @@ static bool matrices_test_14(const char ** scenario)
|
||||
struct mat3x3 a = mat3x3(3, 5, 0,
|
||||
2, -1, -7,
|
||||
6, -1, 5);
|
||||
struct mat2x2 b = mat3x3_submatrix(&a, 1, 0);
|
||||
struct mat2x2 b = mat3x3_submatrix(a, 1, 0);
|
||||
|
||||
return
|
||||
float_equal(mat2x2_determinant(&b), 25.0f) &&
|
||||
float_equal(mat3x3_minor(&a, 1, 0), 25.0f);
|
||||
float_equal(mat2x2_determinant(b), 25.0f) &&
|
||||
float_equal(mat3x3_minor(a, 1, 0), 25.0f);
|
||||
}
|
||||
|
||||
static bool matrices_test_15(const char ** scenario)
|
||||
@ -234,11 +234,11 @@ static bool matrices_test_15(const char ** scenario)
|
||||
6, -1, 5);
|
||||
|
||||
return
|
||||
float_equal(mat3x3_minor(&a, 0, 0), -12.0f) &&
|
||||
float_equal(mat3x3_cofactor(&a, 0, 0), -12.0f) &&
|
||||
float_equal(mat3x3_minor(&a, 1, 0), 25.0f) &&
|
||||
float_equal(mat3x3_cofactor(&a, 1, 0), -25.0f) &&
|
||||
float_equal(mat3x3_cofactor(&a, 2, 1), 21.0f);
|
||||
float_equal(mat3x3_minor(a, 0, 0), -12.0f) &&
|
||||
float_equal(mat3x3_cofactor(a, 0, 0), -12.0f) &&
|
||||
float_equal(mat3x3_minor(a, 1, 0), 25.0f) &&
|
||||
float_equal(mat3x3_cofactor(a, 1, 0), -25.0f) &&
|
||||
float_equal(mat3x3_cofactor(a, 2, 1), 21.0f);
|
||||
|
||||
}
|
||||
|
||||
@ -251,10 +251,10 @@ static bool matrices_test_16(const char ** scenario)
|
||||
2.0f, 6.0f, 4.0f);
|
||||
|
||||
return
|
||||
float_equal(mat3x3_cofactor(&a, 0, 0), 56.0f) &&
|
||||
float_equal(mat3x3_cofactor(&a, 0, 1), 12.0f) &&
|
||||
float_equal(mat3x3_cofactor(&a, 0, 2), -46.0f) &&
|
||||
float_equal(mat3x3_determinant(&a), -196.0f);
|
||||
float_equal(mat3x3_cofactor(a, 0, 0), 56.0f) &&
|
||||
float_equal(mat3x3_cofactor(a, 0, 1), 12.0f) &&
|
||||
float_equal(mat3x3_cofactor(a, 0, 2), -46.0f) &&
|
||||
float_equal(mat3x3_determinant(a), -196.0f);
|
||||
}
|
||||
|
||||
static bool matrices_test_17(const char ** scenario)
|
||||
@ -267,11 +267,11 @@ static bool matrices_test_17(const char ** scenario)
|
||||
-6.0f, 7.0f, 7.0f, -9.0f);
|
||||
|
||||
return
|
||||
float_equal(mat4x4_cofactor(&a, 0, 0), 690.0f) &&
|
||||
float_equal(mat4x4_cofactor(&a, 0, 1), 447.0f) &&
|
||||
float_equal(mat4x4_cofactor(&a, 0, 2), 210.0f) &&
|
||||
float_equal(mat4x4_cofactor(&a, 0, 3), 51.0f) &&
|
||||
float_equal(mat4x4_determinant(&a), -4071.0f);
|
||||
float_equal(mat4x4_cofactor(a, 0, 0), 690.0f) &&
|
||||
float_equal(mat4x4_cofactor(a, 0, 1), 447.0f) &&
|
||||
float_equal(mat4x4_cofactor(a, 0, 2), 210.0f) &&
|
||||
float_equal(mat4x4_cofactor(a, 0, 3), 51.0f) &&
|
||||
float_equal(mat4x4_determinant(a), -4071.0f);
|
||||
}
|
||||
|
||||
static bool matrices_test_18(const char ** scenario)
|
||||
@ -284,8 +284,8 @@ static bool matrices_test_18(const char ** scenario)
|
||||
9.0f, 1.0f, 7.0f, -6.0f);
|
||||
|
||||
return
|
||||
float_equal(mat4x4_determinant(&a), -2120.0f) &&
|
||||
mat4x4_is_invertible(&a);
|
||||
float_equal(mat4x4_determinant(a), -2120.0f) &&
|
||||
mat4x4_is_invertible(a);
|
||||
}
|
||||
|
||||
static bool matrices_test_19(const char ** scenario)
|
||||
@ -298,8 +298,8 @@ static bool matrices_test_19(const char ** scenario)
|
||||
0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
return
|
||||
float_equal(mat4x4_determinant(&a), 0.0f) &&
|
||||
!mat4x4_is_invertible(&a);
|
||||
float_equal(mat4x4_determinant(a), 0.0f) &&
|
||||
!mat4x4_is_invertible(a);
|
||||
}
|
||||
|
||||
static bool matrices_test_20(const char ** scenario)
|
||||
@ -310,7 +310,7 @@ static bool matrices_test_20(const char ** scenario)
|
||||
1.0, -5.0, 1.0, 8.0,
|
||||
7.0, 7.0, -6.0, -7.0,
|
||||
1.0, -3.0, 7.0, 4.0);
|
||||
struct mat4x4 b = mat4x4_inverse(&a);
|
||||
struct mat4x4 b = mat4x4_inverse(a);
|
||||
|
||||
struct mat4x4 c = mat4x4( 0.218045f, 0.451128f, 0.240602f, -0.045113f,
|
||||
-0.808271f, -1.456767f, -0.443609f, 0.520677f,
|
||||
@ -318,12 +318,12 @@ static bool matrices_test_20(const char ** scenario)
|
||||
-0.522564f, -0.813910f, -0.300752f, 0.306391f);
|
||||
|
||||
return
|
||||
float_equal(mat4x4_determinant(&a), 532.0f) &&
|
||||
float_equal(mat4x4_cofactor(&a, 2, 3), -160.0f) &&
|
||||
float_equal(mat4x4_determinant(a), 532.0f) &&
|
||||
float_equal(mat4x4_cofactor(a, 2, 3), -160.0f) &&
|
||||
float_equal(b.e[3][2], -160.0f/532.0f) &&
|
||||
float_equal(mat4x4_cofactor(&a, 3, 2), 105.0f) &&
|
||||
float_equal(mat4x4_cofactor(a, 3, 2), 105.0f) &&
|
||||
float_equal(b.e[2][3], 105.0f/532.0f) &&
|
||||
mat4x4_equal(&b, &c);
|
||||
mat4x4_equal(b, c);
|
||||
}
|
||||
|
||||
static bool matrices_test_21(const char ** scenario)
|
||||
@ -335,14 +335,14 @@ static bool matrices_test_21(const char ** scenario)
|
||||
-6.0f, 0.0f, 9.0f, 6.0f,
|
||||
-3.0f, 0.0f, -9.0f, -4.0f);
|
||||
|
||||
struct mat4x4 b = mat4x4_inverse(&a);
|
||||
struct mat4x4 b = mat4x4_inverse(a);
|
||||
|
||||
struct mat4x4 c = mat4x4(-0.15385f, -0.15385f, -0.28205f, -0.53846f,
|
||||
-0.07692f, 0.12308f, 0.02564f, 0.03077f,
|
||||
0.35897f, 0.35897f, 0.43590f, 0.92308f,
|
||||
-0.69231f, -0.69231f, -0.76923f, -1.92308f);
|
||||
|
||||
return mat4x4_equal(&b, &c);
|
||||
return mat4x4_equal(b, c);
|
||||
}
|
||||
|
||||
static bool matrices_test_22(const char ** scenario)
|
||||
@ -354,14 +354,14 @@ static bool matrices_test_22(const char ** scenario)
|
||||
-4.0f, 9.0f, 6.0f, 4.0f,
|
||||
-7.0f, 6.0f, 6.0f, 2.0f);
|
||||
|
||||
struct mat4x4 b = mat4x4_inverse(&a);
|
||||
struct mat4x4 b = mat4x4_inverse(a);
|
||||
|
||||
struct mat4x4 c = mat4x4(-0.04074f, -0.07778f, 0.14444f, -0.22222f,
|
||||
-0.07778f, 0.03333f, 0.36667f, -0.33333f,
|
||||
-0.02901f, -0.14630f, -0.10926f, 0.12963f,
|
||||
0.17778f, 0.06667f, -0.26667f, 0.33333f);
|
||||
|
||||
return mat4x4_equal(&b, &c);
|
||||
return mat4x4_equal(b, c);
|
||||
}
|
||||
|
||||
static bool matrices_test_23(const char ** scenario)
|
||||
@ -378,12 +378,12 @@ static bool matrices_test_23(const char ** scenario)
|
||||
7.0f, 0.0f, 5.0f, 4.0f,
|
||||
6.0f, -2.0f, 0.0f, 5.0f);
|
||||
|
||||
struct mat4x4 c = mat4x4_mul_m(&a, &b);
|
||||
struct mat4x4 c = mat4x4_mul_m(a, b);
|
||||
|
||||
struct mat4x4 b_i = mat4x4_inverse(&b);
|
||||
struct mat4x4 d = mat4x4_mul_m(&c, &b_i);
|
||||
struct mat4x4 b_i = mat4x4_inverse(b);
|
||||
struct mat4x4 d = mat4x4_mul_m(c, b_i);
|
||||
|
||||
return mat4x4_equal(&d, &a);
|
||||
return mat4x4_equal(d, a);
|
||||
}
|
||||
|
||||
test_t matrices_tests[] = {
|
||||
|
86
test/test_planes.c
Normal file
86
test/test_planes.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "rays.h"
|
||||
#include "planes.h"
|
||||
#include "intersections_shapes.h"
|
||||
#include "runner.h"
|
||||
#include "matrices.h"
|
||||
#include "transformations.h"
|
||||
|
||||
static bool planes_test_0(const char ** scenario)
|
||||
{
|
||||
*scenario = "The normal of a plane is constant everywhere";
|
||||
|
||||
struct tuple n1 = plane_normal_at(point(0.0f, 0.0f, 0.0f));
|
||||
struct tuple n2 = plane_normal_at(point(10.0f, 0.0f, -10.0f));
|
||||
struct tuple n3 = plane_normal_at(point(-5.0f, 0.0f, 150.0f));
|
||||
return
|
||||
tuple_equal(n1, vector(0.0f, 1.0f, 0.0f)) &&
|
||||
tuple_equal(n2, vector(0.0f, 1.0f, 0.0f)) &&
|
||||
tuple_equal(n3, vector(0.0f, 1.0f, 0.0f));
|
||||
}
|
||||
|
||||
static bool planes_test_1(const char ** scenario)
|
||||
{
|
||||
*scenario = "Intersect with a ray parallel to the plane";
|
||||
|
||||
struct shape p = plane();
|
||||
struct ray r = ray(point(0.0f, 10.0f, 0.0f), vector(0.0f, 0.0f, 1.0f));
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
plane_intersect(&p, r, &xs);
|
||||
return xs.count == 0;
|
||||
}
|
||||
|
||||
static bool planes_test_2(const char ** scenario)
|
||||
{
|
||||
*scenario = "Intersect with a coplanar ray";
|
||||
|
||||
struct shape p = plane();
|
||||
struct ray r = ray(point(0.0f, 0.0f, 0.0f), vector(0.0f, 0.0f, 1.0f));
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
plane_intersect(&p, r, &xs);
|
||||
return xs.count == 0;
|
||||
}
|
||||
|
||||
static bool planes_test_3(const char ** scenario)
|
||||
{
|
||||
*scenario = "A ray intersecting a plane from above";
|
||||
|
||||
struct shape p = plane();
|
||||
struct ray r = ray(point(0.0f, 1.0f, 0.0f), vector(0.0f, -1.0f, 0.0f));
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
plane_intersect(&p, r, &xs);
|
||||
return
|
||||
xs.count == 1 &&
|
||||
float_equal(xs.i[0].t, 1.0f) &&
|
||||
xs.i[0].object == &p;
|
||||
}
|
||||
|
||||
static bool planes_test_4(const char ** scenario)
|
||||
{
|
||||
*scenario = "A ray intersecting a plane from below";
|
||||
|
||||
struct shape p = plane();
|
||||
struct ray r = ray(point(0.0f, -1.0f, 0.0f), vector(0.0f, 1.0f, 1.0f));
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
plane_intersect(&p, r, &xs);
|
||||
return
|
||||
xs.count == 1 &&
|
||||
float_equal(xs.i[0].t, 1.0f) &&
|
||||
xs.i[0].object == &p;
|
||||
}
|
||||
|
||||
test_t planes_tests[] = {
|
||||
planes_test_0,
|
||||
planes_test_1,
|
||||
planes_test_2,
|
||||
planes_test_3,
|
||||
planes_test_4,
|
||||
};
|
||||
|
||||
RUNNER(planes_tests);
|
@ -38,7 +38,7 @@ static bool rays_test_2(const char ** scenario)
|
||||
|
||||
struct ray r = ray(point(1.0f, 2.0f, 3.0f), vector(0.0f, 1.0f, 0.0f));
|
||||
struct mat4x4 m = translation(3.0f, 4.0f, 5.0f);
|
||||
struct ray r2 = ray_transform(r, &m);
|
||||
struct ray r2 = ray_transform(r, m);
|
||||
|
||||
return
|
||||
tuple_equal(r2.origin, point(4.0f, 6.0f, 8.0f)) &&
|
||||
@ -51,7 +51,7 @@ static bool rays_test_3(const char ** scenario)
|
||||
|
||||
struct ray r = ray(point(1.0f, 2.0f, 3.0f), vector(0.0f, 1.0f, 0.0f));
|
||||
struct mat4x4 m = scaling(2.0f, 3.0f, 4.0f);
|
||||
struct ray r2 = ray_transform(r, &m);
|
||||
struct ray r2 = ray_transform(r, m);
|
||||
|
||||
return
|
||||
tuple_equal(r2.origin, point(2.0f, 6.0f, 12.0f)) &&
|
||||
|
121
test/test_shapes.c
Normal file
121
test/test_shapes.c
Normal file
@ -0,0 +1,121 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shapes.h"
|
||||
#include "intersections_shapes.h"
|
||||
#include "transformations.h"
|
||||
#include "runner.h"
|
||||
#include "rays.h"
|
||||
#include "spheres.h"
|
||||
|
||||
static bool shapes_test_0(const char ** scenario)
|
||||
{
|
||||
*scenario = "A shape's default transformation";
|
||||
|
||||
struct shape s = shape();
|
||||
struct mat4x4 identity = mat4x4_identity();
|
||||
|
||||
return mat4x4_equal(s.transform, identity);
|
||||
}
|
||||
|
||||
static bool shapes_test_1(const char ** scenario)
|
||||
{
|
||||
*scenario = "Changing a shape's transformation";
|
||||
|
||||
struct shape s = shape();
|
||||
struct mat4x4 t = translation(2.0f, 3.0f, 4.0f);
|
||||
s.transform = t;
|
||||
|
||||
return mat4x4_equal(s.transform, t);
|
||||
}
|
||||
|
||||
static bool shapes_test_2(const char ** scenario)
|
||||
{
|
||||
*scenario = "A shape has a default material";
|
||||
|
||||
struct shape s = shape();
|
||||
struct material m = s.material;
|
||||
return material_equal(m, material());
|
||||
}
|
||||
|
||||
static bool shapes_test_3(const char ** scenario)
|
||||
{
|
||||
*scenario = "A shape may be assigned a material";
|
||||
|
||||
struct shape s = shape();
|
||||
struct material m = material();
|
||||
m.ambient = 1.0f;
|
||||
s.material = m;
|
||||
return material_equal(s.material, m);
|
||||
}
|
||||
|
||||
static bool shapes_test_4(const char ** scenario)
|
||||
{
|
||||
*scenario = "Intersecting a scaled shape with a ray";
|
||||
|
||||
struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f));
|
||||
struct shape s = shape();
|
||||
s.transform = scaling(2.0f, 2.0f, 2.0f);
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
intersect(&s, r, &xs);
|
||||
|
||||
return
|
||||
tuple_equal(intersections_saved_ray.origin, point(0.0f, 0.0f, -2.5f)) &&
|
||||
tuple_equal(intersections_saved_ray.direction, vector(0.0f, 0.0f, 0.5f));
|
||||
}
|
||||
|
||||
static bool shapes_test_5(const char ** scenario)
|
||||
{
|
||||
*scenario = "Intersecting a translated shape with a ray";
|
||||
|
||||
struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f));
|
||||
struct shape s = shape();
|
||||
s.transform = translation(5.0f, 0.0f, 0.0f);
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
intersect(&s, r, &xs);
|
||||
|
||||
return
|
||||
tuple_equal(intersections_saved_ray.origin, point(-5.0f, 0.0f, -5.0f)) &&
|
||||
tuple_equal(intersections_saved_ray.direction, vector(0.0f, 0.0f, 1.0f));
|
||||
}
|
||||
|
||||
static bool shapes_test_6(const char ** scenario)
|
||||
{
|
||||
*scenario = "Computing the normal on a translated shape";
|
||||
|
||||
struct shape s = shape();
|
||||
s.transform = translation(0.0f, 1.0f, 0.0f);
|
||||
|
||||
struct tuple n = normal_at(&s, point(0.0f, 1.70711f, -0.70711));
|
||||
|
||||
return tuple_equal(n, vector(0.0f, 0.70711f, -0.70711f));
|
||||
}
|
||||
|
||||
static bool shapes_test_7(const char ** scenario)
|
||||
{
|
||||
*scenario = "Computing the normal on a transformed shape";
|
||||
struct shape s = shape();
|
||||
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 = normal_at(&s, point(0.0f, 0.7071067811865476, -0.7071067811865476));
|
||||
|
||||
return tuple_equal(n, vector(0.0f, 0.97014f, -0.24254f));
|
||||
}
|
||||
|
||||
test_t shape_tests[] = {
|
||||
shapes_test_0,
|
||||
shapes_test_1,
|
||||
shapes_test_2,
|
||||
shapes_test_3,
|
||||
shapes_test_4,
|
||||
shapes_test_5,
|
||||
shapes_test_6,
|
||||
shapes_test_7,
|
||||
};
|
||||
|
||||
RUNNER(shape_tests)
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "rays.h"
|
||||
#include "spheres.h"
|
||||
#include "intersections.h"
|
||||
#include "intersections_shapes.h"
|
||||
#include "runner.h"
|
||||
#include "matrices.h"
|
||||
#include "transformations.h"
|
||||
@ -13,7 +13,7 @@ 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 shape s = sphere();
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
intersect(&s, r, &xs);
|
||||
@ -29,7 +29,7 @@ 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 shape s = sphere();
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
intersect(&s, r, &xs);
|
||||
@ -45,7 +45,7 @@ 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 shape s = sphere();
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
intersect(&s, r, &xs);
|
||||
@ -58,7 +58,7 @@ 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 shape s = sphere();
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
intersect(&s, r, &xs);
|
||||
@ -74,7 +74,7 @@ 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 shape s = sphere();
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
intersect(&s, r, &xs);
|
||||
@ -90,7 +90,7 @@ 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 shape s = sphere();
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
intersect(&s, r, &xs);
|
||||
@ -102,32 +102,11 @@ static bool spheres_test_5(const char ** scenario)
|
||||
}
|
||||
|
||||
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();
|
||||
struct shape s = sphere();
|
||||
s.transform = scaling(2.0f, 2.0f, 2.0f);
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
@ -139,12 +118,12 @@ static bool spheres_test_8(const char ** scenario)
|
||||
float_equal(xs.i[1].t, 7.0f);
|
||||
}
|
||||
|
||||
static bool spheres_test_9(const char ** scenario)
|
||||
static bool spheres_test_7(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();
|
||||
struct shape s = sphere();
|
||||
s.transform = translation(5.0f, 0.0f, 0.0f);
|
||||
struct intersections xs;
|
||||
xs.count = 0;
|
||||
@ -153,39 +132,39 @@ static bool spheres_test_9(const char ** scenario)
|
||||
return xs.count == 0;
|
||||
}
|
||||
|
||||
static bool spheres_test_10(const char ** scenario)
|
||||
static bool spheres_test_8(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));
|
||||
struct shape s = sphere();
|
||||
struct tuple n = 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_9(const char ** scenario)
|
||||
{
|
||||
*scenario = "The normal on a sphere at a point on the y axis";
|
||||
|
||||
struct shape s = sphere();
|
||||
struct tuple n = 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_10(const char ** scenario)
|
||||
{
|
||||
*scenario = "The normal on a sphere at a point on the z axis";
|
||||
|
||||
struct shape s = sphere();
|
||||
struct tuple n = 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_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,
|
||||
struct shape s = sphere();
|
||||
struct tuple n = normal_at(&s, point(0.5773502691896257,
|
||||
0.5773502691896257,
|
||||
0.5773502691896257));
|
||||
return tuple_equal(n, vector(0.5773502691896257,
|
||||
@ -193,63 +172,43 @@ static bool spheres_test_13(const char ** scenario)
|
||||
0.5773502691896257));
|
||||
}
|
||||
|
||||
static bool spheres_test_14(const char ** scenario)
|
||||
static bool spheres_test_12(const char ** scenario)
|
||||
{
|
||||
*scenario = "The normal is a normalized vector";
|
||||
|
||||
struct sphere s = sphere();
|
||||
struct tuple n = sphere_normal_at(&s, point(0.5773502691896257,
|
||||
struct shape s = sphere();
|
||||
struct tuple n = 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)
|
||||
static bool spheres_test_13(const char ** scenario)
|
||||
{
|
||||
*scenario = "Computing the normal on a translated sphere";
|
||||
|
||||
struct sphere s = sphere();
|
||||
struct shape 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));
|
||||
struct tuple n = 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)
|
||||
static bool spheres_test_14(const char ** scenario)
|
||||
{
|
||||
*scenario = "Computing the normal on a transformed sphere";
|
||||
|
||||
struct sphere s = sphere();
|
||||
struct shape 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);
|
||||
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));
|
||||
struct tuple n = 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,
|
||||
@ -266,10 +225,6 @@ test_t spheres_tests[] = {
|
||||
spheres_test_12,
|
||||
spheres_test_13,
|
||||
spheres_test_14,
|
||||
spheres_test_15,
|
||||
spheres_test_16,
|
||||
spheres_test_17,
|
||||
spheres_test_18,
|
||||
};
|
||||
|
||||
RUNNER(spheres_tests);
|
||||
|
@ -11,7 +11,7 @@ static bool transformations_test_0(const char ** scenario)
|
||||
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));
|
||||
return tuple_equal(mat4x4_mul_t(transform, p), point(2.0f, 1.0f, 7.0f));
|
||||
}
|
||||
|
||||
static bool transformations_test_1(const char ** scenario)
|
||||
@ -19,10 +19,10 @@ 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 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));
|
||||
return tuple_equal(mat4x4_mul_t(inv, p), point(-8.0f, 7.0f, 3.0f));
|
||||
}
|
||||
|
||||
static bool transformations_test_2(const char ** scenario)
|
||||
@ -32,7 +32,7 @@ static bool transformations_test_2(const char ** scenario)
|
||||
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);
|
||||
return tuple_equal(mat4x4_mul_t(transform, v), v);
|
||||
}
|
||||
|
||||
static bool transformations_test_3(const char ** scenario)
|
||||
@ -42,7 +42,7 @@ static bool transformations_test_3(const char ** scenario)
|
||||
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));
|
||||
return tuple_equal(mat4x4_mul_t(transform, p), point(-8.0f, 18.0f, 32.0f));
|
||||
}
|
||||
|
||||
static bool transformations_test_4(const char ** scenario)
|
||||
@ -52,7 +52,7 @@ static bool transformations_test_4(const char ** scenario)
|
||||
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));
|
||||
return tuple_equal(mat4x4_mul_t(transform, v), vector(-8.0f, 18.0f, 32.0f));
|
||||
}
|
||||
|
||||
static bool transformations_test_5(const char ** scenario)
|
||||
@ -60,10 +60,10 @@ 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 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));
|
||||
return tuple_equal(mat4x4_mul_t(inv, v), vector(-2.0f, 2.0f, 2.0f));
|
||||
}
|
||||
|
||||
static bool transformations_test_6(const char ** scenario)
|
||||
@ -73,7 +73,7 @@ static bool transformations_test_6(const char ** scenario)
|
||||
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));
|
||||
return tuple_equal(mat4x4_mul_t(transform, p), point(-2.0f, 3.0f, 4.0f));
|
||||
}
|
||||
|
||||
static bool transformations_test_7(const char ** scenario)
|
||||
@ -85,8 +85,8 @@ static bool transformations_test_7(const char ** scenario)
|
||||
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));
|
||||
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)
|
||||
@ -98,8 +98,8 @@ static bool transformations_test_8(const char ** scenario)
|
||||
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));
|
||||
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)
|
||||
@ -111,8 +111,8 @@ static bool transformations_test_9(const char ** scenario)
|
||||
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));
|
||||
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)
|
||||
@ -122,7 +122,7 @@ static bool transformations_test_10(const char ** scenario)
|
||||
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));
|
||||
return tuple_equal(mat4x4_mul_t(transform, p), point(5.0f, 3.0f, 4.0f));
|
||||
}
|
||||
|
||||
static bool transformations_test_11(const char ** scenario)
|
||||
@ -132,7 +132,7 @@ static bool transformations_test_11(const char ** scenario)
|
||||
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));
|
||||
return tuple_equal(mat4x4_mul_t(transform, p), point(6.0f, 3.0f, 4.0f));
|
||||
}
|
||||
|
||||
static bool transformations_test_12(const char ** scenario)
|
||||
@ -142,7 +142,7 @@ static bool transformations_test_12(const char ** scenario)
|
||||
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));
|
||||
return tuple_equal(mat4x4_mul_t(transform, p), point(2.0f, 5.0f, 4.0f));
|
||||
}
|
||||
|
||||
static bool transformations_test_13(const char ** scenario)
|
||||
@ -152,7 +152,7 @@ static bool transformations_test_13(const char ** scenario)
|
||||
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));
|
||||
return tuple_equal(mat4x4_mul_t(transform, p), point(2.0f, 7.0f, 4.0f));
|
||||
}
|
||||
|
||||
static bool transformations_test_14(const char ** scenario)
|
||||
@ -162,7 +162,7 @@ static bool transformations_test_14(const char ** scenario)
|
||||
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));
|
||||
return tuple_equal(mat4x4_mul_t(transform, p), point(2.0f, 3.0f, 6.0f));
|
||||
}
|
||||
|
||||
static bool transformations_test_15(const char ** scenario)
|
||||
@ -172,7 +172,7 @@ static bool transformations_test_15(const char ** scenario)
|
||||
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));
|
||||
return tuple_equal(mat4x4_mul_t(transform, p), point(2.0f, 3.0f, 7.0f));
|
||||
}
|
||||
|
||||
static bool transformations_test_16(const char ** scenario)
|
||||
@ -184,9 +184,9 @@ static bool transformations_test_16(const char ** scenario)
|
||||
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);
|
||||
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)) &&
|
||||
@ -203,9 +203,9 @@ static bool transformations_test_17(const char ** scenario)
|
||||
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);
|
||||
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));
|
||||
}
|
||||
@ -220,7 +220,7 @@ static bool transformations_test_18(const char ** scenario)
|
||||
struct mat4x4 t = view_transform(from, to, up);
|
||||
|
||||
struct mat4x4 identity_matrix = mat4x4_identity();
|
||||
return mat4x4_equal(&t, &identity_matrix);
|
||||
return mat4x4_equal(t, identity_matrix);
|
||||
}
|
||||
|
||||
static bool transformations_test_19(const char ** scenario)
|
||||
@ -233,7 +233,7 @@ static bool transformations_test_19(const char ** scenario)
|
||||
struct mat4x4 t = view_transform(from, to, up);
|
||||
|
||||
struct mat4x4 scaled = scaling(-1.0f, 1.0f, -1.0f);
|
||||
return mat4x4_equal(&t, &scaled);
|
||||
return mat4x4_equal(t, scaled);
|
||||
}
|
||||
|
||||
static bool transformations_test_20(const char ** scenario)
|
||||
@ -246,7 +246,7 @@ static bool transformations_test_20(const char ** scenario)
|
||||
struct mat4x4 t = view_transform(from, to, up);
|
||||
|
||||
struct mat4x4 translated = translation(0.0f, 0.0f, -8.0f);
|
||||
return mat4x4_equal(&t, &translated);
|
||||
return mat4x4_equal(t, translated);
|
||||
}
|
||||
|
||||
static bool transformations_test_21(const char ** scenario)
|
||||
@ -263,7 +263,7 @@ static bool transformations_test_21(const char ** scenario)
|
||||
-0.35857f, 0.59761f, -0.71714f, 0.00000f,
|
||||
0.00000f, 0.00000f, 0.00000f, 1.00000f
|
||||
);
|
||||
return mat4x4_equal(&t, &expected);
|
||||
return mat4x4_equal(t, expected);
|
||||
}
|
||||
|
||||
test_t transformations_tests[] = {
|
||||
|
@ -20,11 +20,11 @@ static bool world_test_1(const char ** scenario)
|
||||
*scenario = "The default world";
|
||||
|
||||
struct light light = point_light(point(-10.0f, 10.0f, -10.0f), color(1.0f, 1.0f, 1.0f));
|
||||
struct sphere s1 = sphere();
|
||||
struct shape s1 = sphere();
|
||||
s1.material.color = color(0.8f, 1.0f, 0.6f);
|
||||
s1.material.diffuse = 0.7f;
|
||||
s1.material.specular = 0.2f;
|
||||
struct sphere s2 = sphere();
|
||||
struct shape s2 = sphere();
|
||||
s2.transform = scaling(0.5f, 0.5f, 0.5f);
|
||||
struct world w = world_default();
|
||||
return
|
||||
@ -34,7 +34,7 @@ static bool world_test_1(const char ** scenario)
|
||||
tuple_equal(w.objects[0].material.color, s1.material.color) &&
|
||||
float_equal(w.objects[0].material.diffuse, s1.material.diffuse) &&
|
||||
float_equal(w.objects[0].material.specular, s1.material.specular) &&
|
||||
mat4x4_equal(&w.objects[1].transform, &s2.transform);
|
||||
mat4x4_equal(w.objects[1].transform, s2.transform);
|
||||
}
|
||||
|
||||
static bool world_test_2(const char ** scenario)
|
||||
@ -61,7 +61,7 @@ static bool world_test_3(const char ** scenario)
|
||||
|
||||
struct world w = world_default();
|
||||
struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f));
|
||||
struct sphere * shape = &w.objects[0];
|
||||
struct shape * shape = &w.objects[0];
|
||||
struct intersection i = intersection(4.0f, shape);
|
||||
struct computations comps = prepare_computations(i, r);
|
||||
struct tuple c = world_shade_hit(&w, &comps);
|
||||
@ -76,7 +76,7 @@ static bool world_test_4(const char ** scenario)
|
||||
struct world w = world_default();
|
||||
w.light = point_light(point(0.0f, 0.25f, 0.0f), color(1.0f, 1.0f, 1.0f));
|
||||
struct ray r = ray(point(0.0f, 0.0f, 0.0f), vector(0.0f, 0.0f, 1.0f));
|
||||
struct sphere * shape = &w.objects[1];
|
||||
struct shape * shape = &w.objects[1];
|
||||
struct intersection i = intersection(0.5f, shape);
|
||||
struct computations comps = prepare_computations(i, r);
|
||||
struct tuple c = world_shade_hit(&w, &comps);
|
||||
@ -111,9 +111,9 @@ static bool world_test_7(const char ** scenario)
|
||||
*scenario = "The color with an intersection behind the ray";
|
||||
|
||||
struct world w = world_default();
|
||||
struct sphere * outer = &w.objects[0];
|
||||
struct shape * outer = &w.objects[0];
|
||||
outer->material.ambient = 1.0f;
|
||||
struct sphere * inner = &w.objects[1];
|
||||
struct shape * inner = &w.objects[1];
|
||||
inner->material.ambient = 1.0f;
|
||||
struct ray r = ray(point(0.0f, 0.0f, 0.75f), vector(0.0f, 0.0f, -1.0f));
|
||||
struct tuple c = world_color_at(&w, r);
|
||||
@ -167,9 +167,9 @@ static bool world_test_12(const char ** scenario)
|
||||
|
||||
struct world w = world();
|
||||
w.light = point_light(point(0.0f, 0.0f, -10.0f), color(1.0f, 1.0f, 1.0f));
|
||||
struct sphere s1 = sphere();
|
||||
struct shape s1 = sphere();
|
||||
w.objects[0] = s1;
|
||||
struct sphere s2 = sphere();
|
||||
struct shape s2 = sphere();
|
||||
s2.transform = translation(0.0f, 0.0f, 10.0f);
|
||||
w.objects[1] = s2;
|
||||
w.object_count = 2;
|
||||
|
@ -70,5 +70,5 @@ inline static struct mat4x4 view_transform(struct tuple from,
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
struct mat4x4 translate = translation(-from.x, -from.y, -from.z);
|
||||
return mat4x4_mul_m(&orientation, &translate);
|
||||
return mat4x4_mul_m(orientation, translate);
|
||||
}
|
||||
|
8
world.h
8
world.h
@ -3,7 +3,7 @@
|
||||
#include "lights.h"
|
||||
#include "spheres.h"
|
||||
#include "transformations.h"
|
||||
#include "intersections.h"
|
||||
#include "intersections_shapes.h"
|
||||
#include "rays.h"
|
||||
#include "materials.h"
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
struct world {
|
||||
struct light light;
|
||||
int object_count;
|
||||
struct sphere objects[WORLD_MAX_OBJECTS];
|
||||
struct shape objects[WORLD_MAX_OBJECTS];
|
||||
};
|
||||
|
||||
inline static struct world world()
|
||||
@ -25,11 +25,11 @@ inline static struct world world()
|
||||
|
||||
inline static struct world world_default()
|
||||
{
|
||||
struct sphere s1 = sphere();
|
||||
struct shape s1 = sphere();
|
||||
s1.material.color = color(0.8f, 1.0f, 0.6f);
|
||||
s1.material.diffuse = 0.7f;
|
||||
s1.material.specular = 0.2f;
|
||||
struct sphere s2 = sphere();
|
||||
struct shape s2 = sphere();
|
||||
s2.transform = scaling(0.5f, 0.5f, 0.5f);
|
||||
|
||||
return (struct world){
|
||||
|
Loading…
x
Reference in New Issue
Block a user