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:
3 files changed
+137
No files matched your search
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user