#pragma once #include "math.h" #include "float.h" struct tuple { union { struct { float x; float y; float z; float w; }; struct { float r; float g; float b; float a; }; struct { float e[4]; }; }; }; inline static struct tuple tuple(float x, float y, float z, float w) { return (struct tuple){{{ x, y, z, w }}}; } inline static bool tuple_is_point(struct tuple t) { return t.w == 1.0f; } inline static bool tuple_is_vector(struct tuple t) { return t.w == 0.0f; } inline static bool tuple_equal(struct tuple a, struct tuple b) { return float_equal(a.x, b.x) && float_equal(a.y, b.y) && float_equal(a.z, b.z) && float_equal(a.w, b.w); } inline static struct tuple point(float x, float y, float z) { return tuple(x, y, z, 1.0f); } inline static struct tuple vector(float x, float y, float z) { return tuple(x, y, z, 0.0f); } inline static struct tuple color(float r, float g, float b) { return tuple(r, g, b, 0.0f); } inline static struct tuple tuple_add(struct tuple a, struct tuple b) { return tuple( a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w ); } inline static struct tuple tuple_sub(struct tuple a, struct tuple b) { return tuple( a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w ); } inline static struct tuple tuple_neg(struct tuple a) { return tuple( -a.x, -a.y, -a.z, -a.w ); } inline static struct tuple tuple_mul(struct tuple a, float s) { return tuple( a.x * s, a.y * s, a.z * s, a.w * s ); } inline static struct tuple tuple_div(struct tuple a, float s) { return tuple( a.x / s, a.y / s, a.z / s, a.w / s ); } inline static float tuple_magnitude(struct tuple a) { return sqrtf(a.x * a.x + a.y * a.y + a.z * a.z + a.w * a.w); } inline static struct tuple tuple_normalize(struct tuple a) { float magnitude = tuple_magnitude(a); return tuple_div(a, magnitude); } inline static float tuple_dot(struct tuple a, struct tuple b) { return a.x * b.x + a.y * b.y + a.z * b.z; } inline static struct tuple tuple_cross(struct tuple a, struct tuple b) { return tuple( a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x, 0.0f ); } inline static struct tuple hadmard_product(struct tuple c1, struct tuple c2) { return tuple( c1.r * c2.r, c1.g * c2.g, c1.b * c2.b, 0.0f ); } inline static struct tuple tuple_reflect(struct tuple in, struct tuple normal) { float dot = tuple_dot(in, normal); return tuple_sub(in, tuple_mul(tuple_mul(normal, 2.0f), dot)); }