aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Sunet <msunet@shellblade.net>2021-12-30 02:20:49 -0800
committerMarc Sunet <msunet@shellblade.net>2021-12-30 02:20:49 -0800
commite905674daae8622d0f86a592b8b3008673a524f6 (patch)
treec868fddb96a82d0ba9da956b00061efc8e44a41e
parent2098eba3d01c7d6b46f0cddb25772f71288bcf6b (diff)
Add 2D and 4D vector math.
-rw-r--r--include/math/vec2.h117
-rw-r--r--include/math/vec3.h11
-rw-r--r--include/math/vec4.h121
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 @@
2 2
3#include "defs.h" 3#include "defs.h"
4 4
5#include <assert.h>
6#include <stdbool.h>
7
8/// A 2D vector.
5typedef struct vec2 { 9typedef struct vec2 {
6 R x, y; 10 R x, y;
7} vec2; 11} vec2;
8 12
9/// Construct a vector from 2 coordinates. 13/// Construct a vector from 2 coordinates.
10static inline vec2 vec2_make(R x, R y) { return (vec2){x, y}; } 14static inline vec2 vec2_make(R x, R y) { return (vec2){x, y}; }
15
16/// Construct a vector from an array.
17static inline vec2 vec2_from_array(const R xy[2]) {
18 return (vec2){xy[0], xy[1] };
19}
20
21/// Construct a vector from a single scalar value.
22/// x = y = z = val.
23static inline vec2 vec2_from_scalar(R val) { return (vec2){val, val}; }
24
25/// Return the vector's ith coordinate.
26static inline R vec2_ith(vec2 v, int i) {
27 assert(i >= 0 && i < 2);
28 return ((const R*)&v)[i];
29}
30
31/// Negate the given vector.
32static inline vec2 vec2_neg(vec2 v) { return (vec2){-v.x, -v.y}; }
33
34/// Add two vectors.
35static inline vec2 vec2_add(vec2 a, vec2 b) {
36 return (vec2){a.x + b.x, a.y + b.y};
37}
38
39/// Subtract two vectors.
40static inline vec2 vec2_sub(vec2 a, vec2 b) {
41 return (vec2){a.x - b.x, a.y - b.y};
42}
43
44/// Modulate two vectors (component-wise multiplication).
45static inline vec2 vec2_mul(vec2 a, vec2 b) {
46 return (vec2){a.x * b.x, a.y * b.y};
47}
48
49/// Divide two vectors component-wise.
50static inline vec2 vec2_div(vec2 a, vec2 b) {
51 return (vec2){a.x / b.x, a.y / b.y};
52}
53
54/// Scale a vector by a scalar value.
55static inline vec2 vec2_scale(vec2 v, R s) {
56 return (vec2){v.x * s, v.y * s};
57}
58
59/// Compare two vectors for equality.
60static inline bool vec2_eq(vec2 a, vec2 b) {
61 return a.x == b.x && a.y == b.y;
62}
63
64/// Return the absolute value of the vector.
65static inline vec2 vec2_abs(vec2 v) {
66 return (vec2){rabs(v.x), rabs(v.y)};
67}
68
69/// Compare two vectors for inequality.
70static inline bool vec2_ne(vec2 a, vec2 b) { return !(vec2_eq(a, b)); }
71
72/// Return the vector's squared magnitude.
73static inline R vec2_norm2(vec2 v) { return v.x * v.x + v.y * v.y; }
74
75/// Return the vector's magnitude.
76static inline R vec2_norm(vec2 v) { return sqrt(vec2_norm2(v)); }
77
78/// Return the squared distance between two points.
79static inline R vec2_dist2(vec2 a, vec2 b) {
80 const vec2 v = vec2_sub(b, a);
81 return vec2_norm2(v);
82}
83
84/// Return the distance between two points.
85static inline R vec2_dist(vec2 a, vec2 b) { return sqrt(vec2_dist2(a, b)); }
86
87/// Return the given vector divided by its magnitude.
88static inline vec2 vec2_normalize(vec2 v) {
89 const R n = vec2_norm(v);
90 assert(n > 0);
91 return (vec2){v.x / n, v.y / n};
92}
93
94/// Return the dot product of two vectors.
95static inline R vec2_dot(vec2 a, vec2 b) {
96 return a.x * b.x + a.y * b.y;
97}
98
99/// Reflect the vector about the normal.
100static inline vec2 vec2_reflect(vec2 v, vec2 n) {
101 // r = v - 2 * dot(v, n) * n
102 return vec2_sub(v, vec2_scale(n, 2 * vec2_dot(v, n)));
103}
104
105/// Refract the vector about the normal.
106static inline vec2 vec2_refract(vec2 v, vec2 n, R e) {
107 // k = 1 - e^2(1 - dot(n,v) * dot(n,v))
108 const R k = 1.0 - e * e * (1.0 - vec2_dot(n, v) * vec2_dot(n, v));
109 assert(k >= 0);
110 // r = e*v - (e * dot(n,v) + sqrt(k)) * n
111 return vec2_sub(vec2_scale(v, e),
112 vec2_scale(n, e * vec2_dot(n, v) * sqrt(k)));
113}
114
115/// Elevate the vector to a power.
116static inline vec2 vec2_pow(vec2 v, R p) {
117 return (vec2){pow(v.x, p), pow(v.y, p)};
118}
119
120/// The (1, 0) vector.
121static inline vec2 right2() { return (vec2){1.0, 0.0}; }
122
123/// The (0, 1) vector.
124static inline vec2 up2() { return (const vec2){0.0, 1.0}; }
125
126/// The (0, 0) vector.
127static 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]) {
22/// x = y = z = val. 22/// x = y = z = val.
23static inline vec3 vec3_from_scalar(R val) { return (vec3){val, val, val}; } 23static inline vec3 vec3_from_scalar(R val) { return (vec3){val, val, val}; }
24 24
25/// Normalize the vector.
26static inline vec3 vec3_normalize(vec3 v) {
27 R n = sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
28 assert(n > 0);
29 return (vec3){v.x / n, v.y / n, v.z / n};
30}
31
32/// Return the vector's ith coordinate. 25/// Return the vector's ith coordinate.
33static inline R vec3_ith(vec3 v, int i) { 26static inline R vec3_ith(vec3 v, int i) {
34 assert(i >= 0 && i < 3); 27 assert(i >= 0 && i < 3);
@@ -92,7 +85,7 @@ static inline R vec3_dist2(vec3 a, vec3 b) {
92static inline R vec3_dist(vec3 a, vec3 b) { return sqrt(vec3_dist2(a, b)); } 85static inline R vec3_dist(vec3 a, vec3 b) { return sqrt(vec3_dist2(a, b)); }
93 86
94/// Return the given vector divided by its magnitude. 87/// Return the given vector divided by its magnitude.
95static inline vec3 normalize(vec3 v) { 88static inline vec3 vec3_normalize(vec3 v) {
96 const R n = vec3_norm(v); 89 const R n = vec3_norm(v);
97 assert(n > 0); 90 assert(n > 0);
98 return (vec3){v.x / n, v.y / n, v.z / n}; 91 return (vec3){v.x / n, v.y / n, v.z / n};
@@ -116,7 +109,7 @@ static inline vec3 vec3_reflect(vec3 v, vec3 n) {
116} 109}
117 110
118/// Refract the vector about the normal. 111/// Refract the vector about the normal.
119static inline vec3 refract(vec3 v, vec3 n, R e) { 112static inline vec3 vec3_refract(vec3 v, vec3 n, R e) {
120 // k = 1 - e^2(1 - dot(n,v) * dot(n,v)) 113 // k = 1 - e^2(1 - dot(n,v) * dot(n,v))
121 const R k = 1.0 - e * e * (1.0 - vec3_dot(n, v) * vec3_dot(n, v)); 114 const R k = 1.0 - e * e * (1.0 - vec3_dot(n, v) * vec3_dot(n, v));
122 assert(k >= 0); 115 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 @@
2 2
3#include "defs.h" 3#include "defs.h"
4 4
5#include <assert.h>
6#include <stdbool.h>
7
8/// A 4D vector.
5typedef struct vec4 { 9typedef struct vec4 {
6 R x, y, w, z; 10 R x, y, z, w;
7} vec4; 11} vec4;
8 12
9/// Construct a vector from 4 coordinates. 13/// 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}; }
13static inline vec4 vec4_from_array(const R xyzw[4]) { 17static inline vec4 vec4_from_array(const R xyzw[4]) {
14 return (vec4){xyzw[0], xyzw[1], xyzw[2], xyzw[3]}; 18 return (vec4){xyzw[0], xyzw[1], xyzw[2], xyzw[3]};
15} 19}
20
21/// Construct a vector from a single scalar value.
22/// x = y = z = val.
23static inline vec4 vec4_from_scalar(R val) {
24 return (vec4){val, val, val, val};
25}
26
27/// Return the vector's ith coordinate.
28static inline R vec4_ith(vec4 v, int i) {
29 assert(i >= 0 && i < 4);
30 return ((const R*)&v)[i];
31}
32
33/// Negate the given vector.
34static inline vec4 vec4_neg(vec4 v) { return (vec4){-v.x, -v.y, -v.z, -v.w}; }
35
36/// Add two vectors.
37static inline vec4 vec4_add(vec4 a, vec4 b) {
38 return (vec4){a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w};
39}
40
41/// Subtract two vectors.
42static inline vec4 vec4_sub(vec4 a, vec4 b) {
43 return (vec4){a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w};
44}
45
46/// Modulate two vectors (component-wise multiplication).
47static inline vec4 vec4_mul(vec4 a, vec4 b) {
48 return (vec4){a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w};
49}
50
51/// Divide two vectors component-wise.
52static inline vec4 vec4_div(vec4 a, vec4 b) {
53 return (vec4){a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w};
54}
55
56/// Scale a vector by a scalar value.
57static inline vec4 vec4_scale(vec4 v, R s) {
58 return (vec4){v.x * s, v.y * s, v.z * s, v.w * s};
59}
60
61/// Compare two vectors for equality.
62static inline bool vec4_eq(vec4 a, vec4 b) {
63 return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w;
64}
65
66/// Return the absolute value of the vector.
67static inline vec4 vec4_abs(vec4 v) {
68 return (vec4){rabs(v.x), rabs(v.y), rabs(v.z), rabs(v.w)};
69}
70
71/// Compare two vectors for inequality.
72static inline bool vec4_ne(vec4 a, vec4 b) { return !(vec4_eq(a, b)); }
73
74/// Return the vector's squared magnitude.
75static inline R vec4_norm2(vec4 v) {
76 return v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w;
77}
78
79/// Return the vector's magnitude.
80static inline R vec4_norm(vec4 v) { return sqrt(vec4_norm2(v)); }
81
82/// Return the squared distance between two points.
83static inline R vec4_dist2(vec4 a, vec4 b) {
84 const vec4 v = vec4_sub(b, a);
85 return vec4_norm2(v);
86}
87
88/// Return the distance between two points.
89static inline R vec4_dist(vec4 a, vec4 b) { return sqrt(vec4_dist2(a, b)); }
90
91/// Return the given vector divided by its magnitude.
92static inline vec4 vec4_normalize(vec4 v) {
93 const R n = vec4_norm(v);
94 assert(n > 0);
95 return (vec4){v.x / n, v.y / n, v.z / n, v.w / n};
96}
97
98/// Return the dot product of two vectors.
99static inline R vec4_dot(vec4 a, vec4 b) {
100 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
101}
102
103/// Reflect the vector about the normal.
104static inline vec4 vec4_reflect(vec4 v, vec4 n) {
105 // r = v - 2 * dot(v, n) * n
106 return vec4_sub(v, vec4_scale(n, 2 * vec4_dot(v, n)));
107}
108
109/// Refract the vector about the normal.
110static inline vec4 vec4_refract(vec4 v, vec4 n, R e) {
111 // k = 1 - e^2(1 - dot(n,v) * dot(n,v))
112 const R k = 1.0 - e * e * (1.0 - vec4_dot(n, v) * vec4_dot(n, v));
113 assert(k >= 0);
114 // r = e*v - (e * dot(n,v) + sqrt(k)) * n
115 return vec4_sub(vec4_scale(v, e),
116 vec4_scale(n, e * vec4_dot(n, v) * sqrt(k)));
117}
118
119/// Elevate the vector to a power.
120static inline vec4 vec4_pow(vec4 v, R p) {
121 return (vec4){pow(v.x, p), pow(v.y, p), pow(v.z, p), pow(v.w, p)};
122}
123
124/// The (1, 0, 0, 0) vector.
125static inline vec4 right4() { return (vec4){1.0, 0.0, 0.0, 0.0}; }
126
127/// The (0, 1, 0, 0) vector.
128static inline vec4 up4() { return (const vec4){0.0, 1.0, 0.0, 0.0}; }
129
130/// The (0, 0, -1, 0) vector.
131static inline vec4 forward4() { return (const vec4){0.0, 0.0, -1.0, 0.0}; }
132
133/// The (0, 0, 0, 0) vector.
134static inline vec4 zero4() { return (const vec4){0.0, 0.0, 0.0, 0.0}; }