From e905674daae8622d0f86a592b8b3008673a524f6 Mon Sep 17 00:00:00 2001 From: Marc Sunet Date: Thu, 30 Dec 2021 02:20:49 -0800 Subject: Add 2D and 4D vector math. --- include/math/vec2.h | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/math/vec3.h | 11 +---- include/math/vec4.h | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 239 insertions(+), 10 deletions(-) diff --git a/include/math/vec2.h b/include/math/vec2.h index 0a3f692..ebf0d78 100644 --- a/include/math/vec2.h +++ b/include/math/vec2.h @@ -2,9 +2,126 @@ #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}; } diff --git a/include/math/vec3.h b/include/math/vec3.h index 3c3b053..caa212e 100644 --- a/include/math/vec3.h +++ b/include/math/vec3.h @@ -22,13 +22,6 @@ static inline vec3 vec3_from_array(const R xyz[3]) { /// x = y = z = val. static inline vec3 vec3_from_scalar(R val) { return (vec3){val, val, val}; } -/// Normalize the vector. -static inline vec3 vec3_normalize(vec3 v) { - R n = sqrt(v.x * v.x + v.y * v.y + v.z * v.z); - assert(n > 0); - return (vec3){v.x / n, v.y / n, v.z / n}; -} - /// Return the vector's ith coordinate. static inline R vec3_ith(vec3 v, int i) { assert(i >= 0 && i < 3); @@ -92,7 +85,7 @@ static inline R vec3_dist2(vec3 a, vec3 b) { static inline R vec3_dist(vec3 a, vec3 b) { return sqrt(vec3_dist2(a, b)); } /// Return the given vector divided by its magnitude. -static inline vec3 normalize(vec3 v) { +static inline vec3 vec3_normalize(vec3 v) { const R n = vec3_norm(v); assert(n > 0); return (vec3){v.x / n, v.y / n, v.z / n}; @@ -116,7 +109,7 @@ static inline vec3 vec3_reflect(vec3 v, vec3 n) { } /// Refract the vector about the normal. -static inline vec3 refract(vec3 v, vec3 n, R e) { +static inline vec3 vec3_refract(vec3 v, vec3 n, R e) { // k = 1 - e^2(1 - dot(n,v) * dot(n,v)) const R k = 1.0 - e * e * (1.0 - vec3_dot(n, v) * vec3_dot(n, v)); assert(k >= 0); diff --git a/include/math/vec4.h b/include/math/vec4.h index 4ab843b..60da464 100644 --- a/include/math/vec4.h +++ b/include/math/vec4.h @@ -2,8 +2,12 @@ #include "defs.h" +#include +#include + +/// A 4D vector. typedef struct vec4 { - R x, y, w, z; + R x, y, z, w; } vec4; /// Construct a vector from 4 coordinates. @@ -13,3 +17,118 @@ static inline vec4 vec4_make(R x, R y, R z, R w) { return (vec4){x, y, z, w}; } static inline vec4 vec4_from_array(const R xyzw[4]) { return (vec4){xyzw[0], xyzw[1], xyzw[2], xyzw[3]}; } + +/// Construct a vector from a single scalar value. +/// x = y = z = val. +static inline vec4 vec4_from_scalar(R val) { + return (vec4){val, val, val, val}; +} + +/// Return the vector's ith coordinate. +static inline R vec4_ith(vec4 v, int i) { + assert(i >= 0 && i < 4); + return ((const R*)&v)[i]; +} + +/// Negate the given vector. +static inline vec4 vec4_neg(vec4 v) { return (vec4){-v.x, -v.y, -v.z, -v.w}; } + +/// Add two vectors. +static inline vec4 vec4_add(vec4 a, vec4 b) { + return (vec4){a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w}; +} + +/// Subtract two vectors. +static inline vec4 vec4_sub(vec4 a, vec4 b) { + return (vec4){a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w}; +} + +/// Modulate two vectors (component-wise multiplication). +static inline vec4 vec4_mul(vec4 a, vec4 b) { + return (vec4){a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w}; +} + +/// Divide two vectors component-wise. +static inline vec4 vec4_div(vec4 a, vec4 b) { + return (vec4){a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w}; +} + +/// Scale a vector by a scalar value. +static inline vec4 vec4_scale(vec4 v, R s) { + return (vec4){v.x * s, v.y * s, v.z * s, v.w * s}; +} + +/// Compare two vectors for equality. +static inline bool vec4_eq(vec4 a, vec4 b) { + return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; +} + +/// Return the absolute value of the vector. +static inline vec4 vec4_abs(vec4 v) { + return (vec4){rabs(v.x), rabs(v.y), rabs(v.z), rabs(v.w)}; +} + +/// Compare two vectors for inequality. +static inline bool vec4_ne(vec4 a, vec4 b) { return !(vec4_eq(a, b)); } + +/// Return the vector's squared magnitude. +static inline R vec4_norm2(vec4 v) { + return v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w; +} + +/// Return the vector's magnitude. +static inline R vec4_norm(vec4 v) { return sqrt(vec4_norm2(v)); } + +/// Return the squared distance between two points. +static inline R vec4_dist2(vec4 a, vec4 b) { + const vec4 v = vec4_sub(b, a); + return vec4_norm2(v); +} + +/// Return the distance between two points. +static inline R vec4_dist(vec4 a, vec4 b) { return sqrt(vec4_dist2(a, b)); } + +/// Return the given vector divided by its magnitude. +static inline vec4 vec4_normalize(vec4 v) { + const R n = vec4_norm(v); + assert(n > 0); + return (vec4){v.x / n, v.y / n, v.z / n, v.w / n}; +} + +/// Return the dot product of two vectors. +static inline R vec4_dot(vec4 a, vec4 b) { + return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; +} + +/// Reflect the vector about the normal. +static inline vec4 vec4_reflect(vec4 v, vec4 n) { + // r = v - 2 * dot(v, n) * n + return vec4_sub(v, vec4_scale(n, 2 * vec4_dot(v, n))); +} + +/// Refract the vector about the normal. +static inline vec4 vec4_refract(vec4 v, vec4 n, R e) { + // k = 1 - e^2(1 - dot(n,v) * dot(n,v)) + const R k = 1.0 - e * e * (1.0 - vec4_dot(n, v) * vec4_dot(n, v)); + assert(k >= 0); + // r = e*v - (e * dot(n,v) + sqrt(k)) * n + return vec4_sub(vec4_scale(v, e), + vec4_scale(n, e * vec4_dot(n, v) * sqrt(k))); +} + +/// Elevate the vector to a power. +static inline vec4 vec4_pow(vec4 v, R p) { + return (vec4){pow(v.x, p), pow(v.y, p), pow(v.z, p), pow(v.w, p)}; +} + +/// The (1, 0, 0, 0) vector. +static inline vec4 right4() { return (vec4){1.0, 0.0, 0.0, 0.0}; } + +/// The (0, 1, 0, 0) vector. +static inline vec4 up4() { return (const vec4){0.0, 1.0, 0.0, 0.0}; } + +/// The (0, 0, -1, 0) vector. +static inline vec4 forward4() { return (const vec4){0.0, 0.0, -1.0, 0.0}; } + +/// The (0, 0, 0, 0) vector. +static inline vec4 zero4() { return (const vec4){0.0, 0.0, 0.0, 0.0}; } -- cgit v1.2.3