#pragma once #include "defs.h" #include #include /// A 2D vector. typedef struct vec2 { R x, y; } vec2; /// Construct a vector from 2 coordinates. static inline vec2 vec2_make(R x, R y) { return (vec2){x, y}; } /// Construct a vector from an array. static inline vec2 vec2_from_array(const R xy[2]) { return (vec2){xy[0], xy[1]}; } /// Construct a vector from a single scalar value. /// x = y = z = val. static inline vec2 vec2_from_scalar(R val) { return (vec2){val, val}; } /// Return the vector's ith coordinate. static inline R vec2_ith(vec2 v, int i) { assert(i >= 0 && i < 2); return ((const R*)&v)[i]; } /// Negate the given vector. static inline vec2 vec2_neg(vec2 v) { return (vec2){-v.x, -v.y}; } /// Add two vectors. static inline vec2 vec2_add(vec2 a, vec2 b) { return (vec2){a.x + b.x, a.y + b.y}; } /// Subtract two vectors. static inline vec2 vec2_sub(vec2 a, vec2 b) { return (vec2){a.x - b.x, a.y - b.y}; } /// Modulate two vectors (component-wise multiplication). static inline vec2 vec2_mul(vec2 a, vec2 b) { return (vec2){a.x * b.x, a.y * b.y}; } /// Divide two vectors component-wise. static inline vec2 vec2_div(vec2 a, vec2 b) { return (vec2){a.x / b.x, a.y / b.y}; } /// Scale a vector by a scalar value. static inline vec2 vec2_scale(vec2 v, R s) { return (vec2){v.x * s, v.y * s}; } /// Compare two vectors for equality. static inline bool vec2_eq(vec2 a, vec2 b) { return a.x == b.x && a.y == b.y; } /// Return the absolute value of the vector. static inline vec2 vec2_abs(vec2 v) { return (vec2){rabs(v.x), rabs(v.y)}; } /// Compare two vectors for inequality. static inline bool vec2_ne(vec2 a, vec2 b) { return !(vec2_eq(a, b)); } /// Return the vector's squared magnitude. static inline R vec2_norm2(vec2 v) { return v.x * v.x + v.y * v.y; } /// Return the vector's magnitude. static inline R vec2_norm(vec2 v) { return sqrt(vec2_norm2(v)); } /// Return the squared distance between two points. static inline R vec2_dist2(vec2 a, vec2 b) { const vec2 v = vec2_sub(b, a); return vec2_norm2(v); } /// Return the distance between two points. static inline R vec2_dist(vec2 a, vec2 b) { return sqrt(vec2_dist2(a, b)); } /// Return the given vector divided by its magnitude. static inline vec2 vec2_normalize(vec2 v) { const R n = vec2_norm(v); assert(n > 0); return (vec2){v.x / n, v.y / n}; } /// Return the dot product of two vectors. static inline R vec2_dot(vec2 a, vec2 b) { return a.x * b.x + a.y * b.y; } /// Reflect the vector about the normal. static inline vec2 vec2_reflect(vec2 v, vec2 n) { // r = v - 2 * dot(v, n) * n return vec2_sub(v, vec2_scale(n, 2 * vec2_dot(v, n))); } /// Refract the vector about the normal. static inline vec2 vec2_refract(vec2 v, vec2 n, R e) { // k = 1 - e^2(1 - dot(n,v) * dot(n,v)) const R k = 1.0 - e * e * (1.0 - vec2_dot(n, v) * vec2_dot(n, v)); assert(k >= 0); // r = e*v - (e * dot(n,v) + sqrt(k)) * n return vec2_sub( vec2_scale(v, e), vec2_scale(n, e * vec2_dot(n, v) * sqrt(k))); } /// Elevate the vector to a power. static inline vec2 vec2_pow(vec2 v, R p) { return (vec2){pow(v.x, p), pow(v.y, p)}; } /// The (1, 0) vector. static inline vec2 right2() { return (vec2){1.0, 0.0}; } /// The (0, 1) vector. static inline vec2 up2() { return (const vec2){0.0, 1.0}; } /// The (0, 0) vector. static inline vec2 zero2() { return (const vec2){0.0, 0.0}; }