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