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