77 lines
1.8 KiB
C
77 lines
1.8 KiB
C
#pragma once
|
|
|
|
#include "spheres.h"
|
|
#include "rays.h"
|
|
|
|
struct intersection {
|
|
float t;
|
|
struct sphere const * const object;
|
|
};
|
|
|
|
struct intersection intersection(float t, struct sphere const * const object)
|
|
{
|
|
return (struct intersection){ t, object };
|
|
}
|
|
|
|
struct intersections {
|
|
int count;
|
|
struct intersection i[];
|
|
};
|
|
|
|
struct intersections2 {
|
|
int count;
|
|
struct intersection i[2];
|
|
};
|
|
|
|
struct intersections4 {
|
|
int count;
|
|
struct intersection i[4];
|
|
};
|
|
|
|
struct intersections2 intersections2(struct intersection a, struct intersection b)
|
|
{
|
|
return (struct intersections2){ 2, {a, b} };
|
|
}
|
|
|
|
struct intersections4 intersections4(struct intersection a, struct intersection b, struct intersection c, struct intersection d)
|
|
{
|
|
return (struct intersections4){ 4, {a, b, c, d} };
|
|
}
|
|
|
|
inline static struct intersections2 intersect(struct sphere const * const s, struct ray r)
|
|
{
|
|
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 (struct intersections2) { 0 };
|
|
} else {
|
|
float root = sqrtf(discriminant);
|
|
float t1 = (-b - root) / (2 * a);
|
|
float t2 = (-b + root) / (2 * a);
|
|
|
|
return
|
|
intersections2(intersection(t1, s),
|
|
intersection(t2, s));
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|