119 lines
3.4 KiB
C
119 lines
3.4 KiB
C
#define _GNU_SOURCE
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <CException.h>
|
|
#include <exceptions.h>
|
|
#include "ray.h"
|
|
|
|
RAY_Ray* RAY_new(double origin_x, double origin_y, double origin_z, double direction_x, double direction_y, double direction_z) {
|
|
RAY_Ray* ray = malloc(sizeof(RAY_Ray));
|
|
if (!ray)
|
|
Throw(E_MALLOC_FAILED);
|
|
|
|
RAY_init(ray, origin_x, origin_y, origin_z, direction_x, direction_y, direction_z);
|
|
return ray;
|
|
}
|
|
|
|
RAY_Ray* RAY_new_from_tuples(TUPLES_Point origin, TUPLES_Vector direction) {
|
|
RAY_Ray* ray = malloc(sizeof(RAY_Ray));
|
|
if (!ray)
|
|
Throw(E_MALLOC_FAILED);
|
|
ray->origin = origin;
|
|
ray->direction = direction;
|
|
return ray;
|
|
}
|
|
|
|
void RAY_init(RAY_Ray* ray, double origin_x, double origin_y, double origin_z, double direction_x, double direction_y, double direction_z) {
|
|
assert(ray);
|
|
ray->origin = TUPLES_point(origin_x, origin_y, origin_z);
|
|
ray->direction = TUPLES_vector(direction_x, direction_y, direction_z);
|
|
}
|
|
|
|
void RAY_init_from_tuples(RAY_Ray* ray, TUPLES_Point origin, TUPLES_Vector direction) {
|
|
ray->origin = origin;
|
|
ray->direction = direction;
|
|
}
|
|
|
|
void RAY_position(TUPLES_Point* pos, const RAY_Ray* ray, double t) {
|
|
assert(pos);
|
|
assert(ray);
|
|
TUPLES_Vector direction_t = TUPLES_multiply(ray->direction, t);
|
|
*pos = TUPLES_add(ray->origin, direction_t);
|
|
}
|
|
|
|
void RAY_transform(RAY_Ray* dest, const RAY_Ray* orig, const MATRIX_Matrix* matrix) {
|
|
assert(dest);
|
|
assert(orig);
|
|
assert(matrix);
|
|
assert(MATRIX_is_invertible(matrix));
|
|
dest->origin = MATRIX_multiply_tuple(matrix, orig->origin);
|
|
dest->direction = MATRIX_multiply_tuple(matrix, orig->direction);
|
|
}
|
|
|
|
void RAY_destroy(RAY_Ray* ray) {
|
|
assert(ray);
|
|
}
|
|
|
|
void RAY_delete(RAY_Ray* ray) {
|
|
assert(ray);
|
|
RAY_destroy(ray);
|
|
free(ray);
|
|
}
|
|
|
|
RAY_Intersections* RAY_new_intersections() {
|
|
RAY_Intersections* intersections = malloc(sizeof(RAY_Intersections));
|
|
if (!intersections)
|
|
Throw(E_MALLOC_FAILED);
|
|
|
|
intersections->count = 0;
|
|
intersections->xs = NULL;
|
|
|
|
return intersections;
|
|
}
|
|
|
|
static int compare_RAY_Xs(const void* a, const void* b) {
|
|
double ad = ((RAY_Xs*)a)->t;
|
|
double bd = ((RAY_Xs*)b)->t;
|
|
if (ad > bd) {
|
|
return 1;
|
|
} else if (ad < bd) {
|
|
return -1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void RAY_sort_intersections(RAY_Intersections* intersections) {
|
|
qsort(intersections->xs, intersections->count, sizeof(RAY_Xs), compare_RAY_Xs);
|
|
}
|
|
|
|
RAY_Xs* RAY_hit(RAY_Intersections* intersections) {
|
|
//TODO - improve this by just keeping a ptr to the smallest positive value on insertion
|
|
for (uint ndx=0; ndx < intersections->count; ndx++) {
|
|
if (intersections->xs[ndx].t > 0) {
|
|
return &intersections->xs[ndx];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void RAY_add_intersection(RAY_Intersections* intersections, double intersection, const void* object) {
|
|
RAY_Xs* tmpptr = reallocarray(intersections->xs, sizeof(RAY_Xs), intersections->count + 1);
|
|
if (!tmpptr) {
|
|
Throw(E_MALLOC_FAILED);
|
|
} else {
|
|
intersections->xs = tmpptr;
|
|
}
|
|
intersections->xs[intersections->count].t = intersection;
|
|
intersections->xs[intersections->count].object = object;
|
|
intersections->count++;
|
|
}
|
|
|
|
void RAY_delete_intersections(RAY_Intersections* intersections) {
|
|
if (intersections->count > 0 && intersections->xs) {
|
|
free(intersections->xs);
|
|
}
|
|
free(intersections);
|
|
}
|