feat(examples): add the scene representation, camera and intersection

Sphere and plane records, camera ray generation from field of view and aspect
ratio, and the nearest-hit search across the scene.
This commit is contained in:
milner committed 2022-07-02 02:41:00 +00:00
1 parent f313b97363
commit 09d072a658
3 files changed
+137

No files matched your search

+27
View File
@@ -0,0 +1,27 @@
#include "rt_scene.h"
#include <math.h>
camera camera_make(vec3 look_from, vec3 look_at, vec3 up, double fov_deg, double aspect) {
double theta = fov_deg * 3.14159265358979323846 / 180.0;
double half_height = tan(theta / 2.0);
double half_width = aspect * half_height;
vec3 w = v3norm(v3sub(look_from, look_at));
vec3 u = v3norm(v3cross(up, w));
vec3 v = v3cross(w, u);
camera c;
c.origin = look_from;
c.horizontal = v3scale(u, 2.0 * half_width);
c.vertical = v3scale(v, 2.0 * half_height);
c.lower_left = v3sub(v3sub(v3sub(look_from, v3scale(u, half_width)), v3scale(v, half_height)), w);
return c;
}
ray camera_ray(const camera *c, double u, double v) {
vec3 target = v3add(v3add(c->lower_left, v3scale(c->horizontal, u)), v3scale(c->vertical, v));
ray r;
r.origin = c->origin;
r.dir = v3norm(v3sub(target, c->origin));
return r;
}
+43
View File
@@ -0,0 +1,43 @@
#include "rt_scene.h"
#include <math.h>
static int sphere_hit(const sphere *s, ray r, double tmin, double tmax, hit *out) {
vec3 oc = v3sub(r.origin, s->center);
double a = v3len2(r.dir);
double half_b = v3dot(oc, r.dir);
double c = v3len2(oc) - s->radius * s->radius;
double disc = half_b * half_b - a * c;
if (disc < 0.0) return 0;
double root = sqrt(disc);
double t = (-half_b - root) / a;
if (t < tmin || t > tmax) {
t = (-half_b + root) / a;
if (t < tmin || t > tmax) return 0;
}
out->t = t;
out->point = v3add(r.origin, v3scale(r.dir, t));
vec3 outward = v3scale(v3sub(out->point, s->center), 1.0 / s->radius);
out->front = v3dot(r.dir, outward) < 0.0;
out->normal = out->front ? outward : v3neg(outward);
out->mat = s->mat;
return 1;
}
int scene_hit(const scene *s, ray r, double tmin, double tmax, hit *out) {
hit best;
int found = 0;
double closest = tmax;
for (int i = 0; i < s->count; i++) {
hit h;
if (sphere_hit(&s->spheres[i], r, tmin, closest, &h)) {
found = 1;
closest = h.t;
best = h;
}
}
if (found) *out = best;
return found;
}