ray-tracer-challenge/intersections.h
2024-08-05 21:26:31 -05:00

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;
}