raytracer-c/module_shapes/cube.c
2020-10-23 23:41:36 -04:00

69 lines
2.2 KiB
C

#include "cube.h"
#include <assert.h>
#include <math.h>
void CUBE_bounds_of(const SHAPE_Shape *shape, BOUND_Box *box) {
assert(shape);
assert(box);
UNUSED(shape);
BOUND_init(box);
BOUND_add_point(box, 1, 1, 1);
BOUND_add_point(box, -1, -1, -1);
}
const SHAPE_vtable CUBE_vtable = {&CUBE_local_intersect, &SHAPE_delete, &CUBE_local_normal_at, &SHAPE_default_shape_contains, &CUBE_bounds_of, NULL};
void CUBE_local_normal_at(TUPLES_Vector *local_normal, SHAPE_Shape *cube, const TUPLES_Point *local_point, const RAY_Xs *hit) {
assert(local_normal);
assert(cube);
assert(local_point);
UNUSED(cube);
UNUSED(hit);
double maxc = UTILITIES_max(fabs(local_point->x), fabs(local_point->y), fabs(local_point->z));
if (maxc == fabs(local_point->x)) {
TUPLES_init_vector(local_normal, local_point->x, 0, 0);
} else if (maxc == fabs(local_point->y)) {
TUPLES_init_vector(local_normal, 0, local_point->y, 0);
} else {
TUPLES_init_vector(local_normal, 0, 0, local_point->z);
}
}
void CUBE_check_axis(double *tmin, double *tmax, double origin, double direction, double min, double max) {
double tmin_numerator = min - origin;
double tmax_numerator = max - origin;
if (fabs(direction) >= EPSILON) {
*tmin = tmin_numerator / direction;
*tmax = tmax_numerator / direction;
} else {
*tmin = tmin_numerator * INFINITY;
*tmax = tmax_numerator * INFINITY;
}
if (*tmin > *tmax) {
double tmp = *tmax;
*tmax = *tmin;
*tmin = tmp;
}
}
void CUBE_local_intersect(RAY_Intersections *intersections, SHAPE_Shape *cube, const RAY_Ray *local_ray) {
assert(intersections);
assert(cube);
assert(local_ray);
double xtmin, xtmax, ytmin, ytmax, ztmin, ztmax;
CUBE_check_axis(&xtmin, &xtmax, local_ray->origin.x, local_ray->direction.x, -1, 1);
CUBE_check_axis(&ytmin, &ytmax, local_ray->origin.y, local_ray->direction.y, -1, 1);
CUBE_check_axis(&ztmin, &ztmax, local_ray->origin.z, local_ray->direction.z, -1, 1);
double tmin = UTILITIES_max(xtmin, ytmin, ztmin);
double tmax = UTILITIES_min(xtmax, ytmax, ztmax);
if (tmin < tmax) {
RAY_add_intersection(intersections, tmin, cube);
RAY_add_intersection(intersections, tmax, cube);
}
}