202 lines
5.1 KiB
C
202 lines
5.1 KiB
C
#include "tuples.h"
|
|
#include "exceptions.h"
|
|
#include "utilities.h"
|
|
|
|
#include <CException.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
|
|
#define VECTOR 0.0
|
|
#define POINT 1.0
|
|
|
|
// may want to expose this later
|
|
void TUPLES_init_point(TUPLES_Point *t, double x, double y, double z) {
|
|
assert(t);
|
|
t->x = x;
|
|
t->y = y;
|
|
t->z = z;
|
|
t->w = POINT;
|
|
}
|
|
|
|
TUPLES_Tuple *TUPLES_new(void) {
|
|
TUPLES_Tuple *new_t = (TUPLES_Tuple *)malloc(sizeof(TUPLES_Tuple));
|
|
if (!new_t)
|
|
Throw(E_MALLOC_FAILED);
|
|
return new_t;
|
|
}
|
|
|
|
TUPLES_Color *TUPLES_new_color(double red, double green, double blue) {
|
|
TUPLES_Color *new_color = TUPLES_new();
|
|
TUPLES_init_color(new_color, red, green, blue);
|
|
return new_color;
|
|
}
|
|
|
|
TUPLES_Point *TUPLES_new_point(double x, double y, double z) {
|
|
TUPLES_Point *new_point = TUPLES_new();
|
|
TUPLES_init_point(new_point, x, y, z);
|
|
return new_point;
|
|
}
|
|
|
|
// may want to expose this later
|
|
void TUPLES_init_vector(TUPLES_Vector *v, double x, double y, double z) {
|
|
assert(v);
|
|
v->x = x;
|
|
v->y = y;
|
|
v->z = z;
|
|
v->w = VECTOR;
|
|
}
|
|
|
|
TUPLES_Vector *TUPLES_new_vector(double x, double y, double z) {
|
|
TUPLES_Vector *new_vector = TUPLES_new();
|
|
TUPLES_init_vector(new_vector, x, y, z);
|
|
return new_vector;
|
|
}
|
|
|
|
bool TUPLES_is_point(const TUPLES_Tuple *tuple) {
|
|
assert(tuple);
|
|
return double_equal(tuple->w, POINT);
|
|
}
|
|
|
|
bool TUPLES_is_vector(const TUPLES_Tuple *tuple) {
|
|
assert(tuple);
|
|
return double_equal(tuple->w, VECTOR);
|
|
}
|
|
|
|
void TUPLES_add(TUPLES_Tuple *dest, const TUPLES_Tuple *t1, const TUPLES_Tuple *t2) {
|
|
assert(t1);
|
|
assert(t2);
|
|
assert(dest);
|
|
dest->x = t1->x + t2->x;
|
|
dest->y = t1->y + t2->y;
|
|
dest->z = t1->z + t2->z;
|
|
dest->w = t1->w + t2->w;
|
|
assert(TUPLES_is_vector(dest) || TUPLES_is_point(dest));
|
|
}
|
|
void TUPLES_subtract(TUPLES_Tuple *dest, const TUPLES_Tuple *t1, const TUPLES_Tuple *t2) {
|
|
assert(t1);
|
|
assert(t2);
|
|
assert(dest);
|
|
dest->x = t1->x - t2->x;
|
|
dest->y = t1->y - t2->y;
|
|
dest->z = t1->z - t2->z;
|
|
dest->w = t1->w - t2->w;
|
|
assert(TUPLES_is_vector(dest) || TUPLES_is_point(dest));
|
|
}
|
|
|
|
void TUPLES_negate(TUPLES_Vector *vec) {
|
|
assert(vec);
|
|
assert(TUPLES_is_vector(vec));
|
|
vec->x = 0.0 - vec->x;
|
|
vec->y = 0.0 - vec->y;
|
|
vec->z = 0.0 - vec->z;
|
|
}
|
|
|
|
void TUPLES_reflect(TUPLES_Vector *dest, const TUPLES_Vector *v, const TUPLES_Vector *normal) {
|
|
// v - normal * 2 * dot(v, normal)
|
|
TUPLES_Vector intermediate;
|
|
TUPLES_multiply(&intermediate, normal, 2 * TUPLES_dot(v, normal));
|
|
TUPLES_subtract(dest, v, &intermediate);
|
|
}
|
|
|
|
void TUPLES_multiply(TUPLES_Tuple *dest, const TUPLES_Tuple *t1, const double mult) {
|
|
assert(t1);
|
|
assert(dest);
|
|
dest->x = t1->x * mult;
|
|
dest->y = t1->y * mult;
|
|
dest->z = t1->z * mult;
|
|
dest->w = t1->w;
|
|
assert(TUPLES_is_vector(dest) || TUPLES_is_point(dest));
|
|
}
|
|
|
|
void TUPLES_divide(TUPLES_Tuple *dest, const TUPLES_Tuple *t1, const double div) {
|
|
assert(t1);
|
|
assert(dest);
|
|
dest->x = t1->x / div;
|
|
dest->y = t1->y / div;
|
|
dest->z = t1->z / div;
|
|
dest->w = t1->w;
|
|
assert(TUPLES_is_vector(dest) || TUPLES_is_point(dest));
|
|
}
|
|
|
|
double TUPLES_magnitude(const TUPLES_Vector *v) {
|
|
assert(v);
|
|
assert(TUPLES_is_vector(v));
|
|
return sqrt(v->x * v->x + v->y * v->y + v->z * v->z);
|
|
}
|
|
|
|
void TUPLES_normalize(TUPLES_Vector *v) {
|
|
assert(v);
|
|
assert(TUPLES_is_vector(v));
|
|
double magnitude = TUPLES_magnitude(v);
|
|
assert(!double_equal(0, magnitude));
|
|
v->x = v->x / magnitude;
|
|
v->y = v->y / magnitude;
|
|
v->z = v->z / magnitude;
|
|
}
|
|
|
|
double TUPLES_dot(const TUPLES_Vector *v1, const TUPLES_Vector *v2) {
|
|
assert(v1);
|
|
assert(TUPLES_is_vector(v1));
|
|
assert(v2);
|
|
assert(TUPLES_is_vector(v2));
|
|
return v1->x * v2->x + v1->y * v2->y + v1->z * v2->z;
|
|
}
|
|
|
|
void TUPLES_cross(TUPLES_Vector *dest, const TUPLES_Vector *v1, const TUPLES_Vector *v2) {
|
|
assert(v1 && v2 && dest);
|
|
assert(TUPLES_is_vector(v1) && TUPLES_is_vector(v2));
|
|
dest->w = VECTOR;
|
|
dest->x = v1->y * v2->z - v1->z * v2->y;
|
|
dest->y = v1->z * v2->x - v1->x * v2->z;
|
|
dest->z = v1->x * v2->y - v1->y * v2->x;
|
|
}
|
|
|
|
void TUPLES_init_color(TUPLES_Color *c, double red, double green, double blue) {
|
|
assert(c);
|
|
c->red = red;
|
|
c->green = green;
|
|
c->blue = blue;
|
|
c->alpha = 0;
|
|
}
|
|
|
|
// aka Hadamard or Schur product
|
|
void TUPLES_multiply_colors(TUPLES_Color *dest, const TUPLES_Color *c1, const TUPLES_Color *c2) {
|
|
assert(dest);
|
|
assert(c1);
|
|
assert(c2);
|
|
dest->red = c1->red * c2->red;
|
|
dest->green = c1->green * c2->green;
|
|
dest->blue = c1->blue * c2->blue;
|
|
dest->alpha = c1->alpha * c2->alpha;
|
|
}
|
|
|
|
void TUPLES_copy(TUPLES_Tuple *dest, const TUPLES_Tuple *src) {
|
|
dest->x = src->x;
|
|
dest->y = src->y;
|
|
dest->z = src->z;
|
|
dest->w = src->w;
|
|
}
|
|
|
|
void TUPLES_destroy(TUPLES_Tuple *tuple) {
|
|
assert(tuple);
|
|
UNUSED(tuple);
|
|
}
|
|
|
|
void TUPLES_delete(TUPLES_Tuple *tuple) {
|
|
assert(tuple);
|
|
TUPLES_destroy(tuple);
|
|
free(tuple);
|
|
}
|
|
|
|
bool TUPLES_is_equal(const TUPLES_Tuple *t1, const TUPLES_Tuple *t2) {
|
|
return (double_equal(t1->x, t2->x) && double_equal(t1->y, t2->y) && double_equal(t1->z, t2->z) && double_equal(t1->w, t2->w));
|
|
}
|
|
|
|
char *TUPLES_to_string(const TUPLES_Tuple *t) {
|
|
assert(t);
|
|
char *str = NULL;
|
|
UTILITIES_sasprintf(str, "%.6f %.6f %.6f %.6f", t->x, t->y, t->z, t->w);
|
|
return str;
|
|
}
|