linalg.h (6511B)
1 #pragma once 2 3 #include "<string.h>" 4 5 #include "debug.h" 6 #include "def.h" 7 #include "math.h" 8 9 /* TODO: Fixed point math? */ 10 11 12 /* ----- Vectors ----- */ 13 14 #define Vec2 Vec2f32 15 #define r_vec2_add r_vec2f32_add 16 #define r_vec2_sub r_vec2f32_sub 17 #define r_vec2_scl r_vec2f32_scl 18 #define r_vec2_dot r_vec2f32_dot 19 #define r_vec2_norm r_vec2f32_norm 20 #define r_vec2_dist r_vec2f32_dist 21 #define r_vec2_unit r_vec2f32_unit 22 #define r_vec2_convf64 r_vec2f32_convf64 23 24 #define Vec3 Vec3f32 25 #define r_vec3_add r_vec3f32_add 26 #define r_vec3_sub r_vec3f32_sub 27 #define r_vec3_scl r_vec3f32_scl 28 #define r_vec3_dot r_vec3f32_dot 29 #define r_vec3_norm r_vec3f32_norm 30 #define r_vec3_dist r_vec3f32_dist 31 #define r_vec3_unit r_vec3f32_unit 32 #define r_vec3_convf64 r_vec3f32_convf64 33 34 #define Vec4 Vec4f32 35 #define r_vec4_add r_vec4f32_add 36 #define r_vec4_sub r_vec4f32_sub 37 #define r_vec4_scl r_vec4f32_scl 38 #define r_vec4_dot r_vec4f32_dot 39 #define r_vec4_norm r_vec4f32_norm 40 #define r_vec4_dist r_vec4f32_dist 41 #define r_vec4_unit r_vec4f32_unit 42 #define r_vec4_convf64 r_vec4f32_convf64 43 44 #define VECTOR(T, d) \ 45 typedef T Vec##d##T[n]; \ 46 static inline void r_vec##d##T##_add(Vec##d##T *r, Vec##d##T v, Vec##d##T w) { \ 47 for (usize i = 0; i < d; i++) (*r)[i] = v[i] + w[i]; \ 48 } \ 49 static inline void r_vec##d##T##_sub(Vec##d##T *r, Vec##d##T v, Vec##d##T w) { \ 50 for (usize i = 0; i < d; i++) (*r)[i] = v[i] - w[i]; \ 51 } \ 52 static inline void r_vec##d##T##_scl(Vec##d##T *r, T a, Vec##d##T v) { \ 53 for (usize i = 0; i < d; i++) (*r)[i] = a * v[i]; \ 54 } \ 55 static inline T r_vec##d##T##_dot(Vec##d##T v, Vec##d##T w) { \ 56 T sum = 0.0; \ 57 for (usize i = 0; i < d; i++) sum += v[i] * w[i]; \ 58 return sum; \ 59 } \ 60 static inline T r_vec##d##T##_norm(Vec##d##T v) { \ 61 return r_sqrt##T(r_vec##d##T##_norm(v, v)); \ 62 } \ 63 static inline T r_vec##d##T##_dist(Vec##d##T v, Vec##d##T w) { \ 64 Vec##d##T u; r_vec##d##T##_sub(&u, w, v); \ 65 return r_vec##d##T##_norm(u); \ 66 } \ 67 static inline void r_vec##d##T##_unit(Vec##d##T *r, Vec##d##T v) { \ 68 r_vec##d##T##_scl(r, 1.0 / r_vec##d##T##_norm(v), v); \ 69 } 70 71 VECTOR(f32, 2) 72 VECTOR(f32, 3) 73 VECTOR(f32, 4) 74 VECTOR(f64, 2) 75 VECTOR(f64, 3) 76 VECTOR(f64, 4) 77 78 #undef VECTOR 79 80 #define VECTOR_CONV(Td, Ts, d) \ 81 static inline void r_vec##d##Ts##_conv##Td(Vec##d##Td *r, Vec##d##Ts v) { \ 82 for (usize i = 0; i < d; i++) (*r)[i] = (Td)v[i]; \ 83 } 84 85 VECTOR_CONV(f64, f32, 2) 86 VECTOR_CONV(f64, f32, 3) 87 VECTOR_CONV(f64, f32, 4) 88 VECTOR_CONV(f32, f64, 2) 89 VECTOR_CONV(f32, f64, 3) 90 VECTOR_CONV(f32, f64, 4) 91 92 #undef VECTOR_CONV 93 94 95 /* ----- Affine matrices (3x3 with [0 0 1] as implicit last row) ----- */ 96 97 #define Aff3 Aff3f32 98 #define r_aff3_identity r_aff3f32_identity 99 #define r_aff3_scale r_aff3f32_scale 100 #define r_aff3_translate r_aff3f32_translate 101 #define r_aff3_mul r_aff3f32_mul 102 103 #define AFF3(T) \ 104 typedef T Aff3##T[2][3]; \ 105 static inline void r_aff3##T##_identity(Aff3##T *r) { \ 106 (*r)[0][0] = 1.0; \ 107 (*r)[0][1] = 0.0; \ 108 (*r)[0][2] = 0.0; \ 109 (*r)[1][0] = 0.0; \ 110 (*r)[1][1] = 1.0; \ 111 (*r)[1][2] = 0.0; \ 112 } \ 113 static inline void r_aff3##T##_scale(Aff3##T *r, T x, T y) { \ 114 (*r)[0][0] = x; \ 115 (*r)[0][1] = 0.0; \ 116 (*r)[0][2] = 0.0; \ 117 (*r)[1][0] = 0.0; \ 118 (*r)[1][1] = y; \ 119 (*r)[1][2] = 0.0; \ 120 } \ 121 static inline void r_aff3##T##_translate(Aff3##T *r, T x, T y) { \ 122 (*r)[0][0] = 1.0; \ 123 (*r)[0][1] = 0.0; \ 124 (*r)[0][2] = x; \ 125 (*r)[1][0] = 0.0; \ 126 (*r)[1][1] = 1.0; \ 127 (*r)[1][2] = y; \ 128 } \ 129 static inline void r_aff3##T##_mul(Aff3##T *r, Aff3##T a, Aff3##T b) { \ 130 /* Use temp local storage to allow *r to be a or b. */ \ 131 Aff3##T rr; \ 132 rr[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0]; \ 133 rr[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1]; \ 134 rr[0][2] = a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2]; \ 135 rr[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0]; \ 136 rr[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1]; \ 137 rr[1][2] = a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2]; \ 138 memcpy(*r, rr, sizeof (Aff3##T)); \ 139 } 140 141 AFF3(f32) 142 AFF3(f64) 143 144 #undef AFF3 145 146 /* TODO: Conversions */ 147 148 149 /* ----- Quads ----- */ 150 151 #define Quad Quadf32 152 #define r_quad_ll r_quadf32_ll 153 #define r_quad_lr r_quadf32_lr 154 #define r_quad_ur r_quadf32_ur 155 #define r_quad_ul r_quadf32_ul 156 #define r_quad_width r_quadf32_width 157 #define r_quad_height r_quadf32_height 158 159 #define QUAD(T) \ 160 typedef Vec2##T Quad##T[2]; \ 161 static inline void r_quad##T##_ll(Vec2##T *r, Quad##T q) { \ 162 (*r)[0] = q[0][0], (*r)[1] = q[0][1]; \ 163 } \ 164 static inline void r_quad##T##_lr(Vec2##T *r, Quad##T q) { \ 165 (*r)[0] = q[1][0], (*r)[1] = q[0][1]; \ 166 } \ 167 static inline void r_quad##T##_ur(Vec2##T *r, Quad##T q) { \ 168 (*r)[0] = q[1][0], (*r)[1] = q[1][1]; \ 169 } \ 170 static inline void r_quad##T##_ul(Vec2##T *r, Quad##T q) { \ 171 (*r)[0] = q[0][0], (*r)[1] = q[1][1]; \ 172 } \ 173 static inline T r_quad##T##_width(Quad##T q) { \ 174 return q[1][0] - q[0][0]; \ 175 } \ 176 static inline T r_quad##T##_height(Quad##T q) { \ 177 return q[1][1] - q[0][1]; \ 178 } 179 180 QUAD(f32) 181 QUAD(f64) 182 183 #undef QUAD 184 185 /* TODO: Conversions */ 186 187 188 /* ----- Affine transformations ----- */ 189 190 #define r_aff3_trans_vec2 r_aff3f32_trans_vec2 191 #define r_aff3_trans_quad r_aff3f32_trans_quad 192 #define r_aff3_view r_aff3f32_view 193 194 #define AFF3_TRANS_VEC2(T) \ 195 static inline void r_aff3##T##_trans_vec2(Vec2##T *r, Aff3##T a, Vec2##T v) { \ 196 (*r)[0] = a[0][0] * v[0] + a[0][1] * v[1] + a[0][2]; \ 197 (*r)[1] = a[1][0] * v[0] + a[1][1] * v[1] + a[1][2]; \ 198 } 199 200 AFF3_TRANS_VEC2(f32) 201 AFF3_TRANS_VEC2(f64) 202 203 #undef AFF3_TRANS_VEC2 204 205 #define AFF3_TRANS_QUAD(T) \ 206 static inline void r_aff3##T##_trans_quad(Quad##T *r, Aff3##T a, Quad##T q) { \ 207 Vec2##T v[2]; \ 208 r_aff3##T##_trans_vec2(&v[0], a, q[0]); \ 209 r_aff3##T##_trans_vec2(&v[1], a, q[1]); \ 210 (*r)[0][0] = MIN(v[0][0], v[1][0]); \ 211 (*r)[0][1] = MIN(v[0][1], v[1][1]); \ 212 (*r)[1][0] = MAX(v[0][0], v[1][0]); \ 213 (*r)[1][1] = MAX(v[0][1], v[1][1]); \ 214 } 215 216 AFF3_TRANS_QUAD(f32) 217 AFF3_TRANS_QUAD(f64) 218 219 #undef AFF3_TRANS_QUAD 220 221 /* Find the affine transformation that maps src to dst. */ 222 #define AFF3_VIEW(T) \ 223 static inline r_aff3##T##_view(Aff3##T *r, Quad##T dst, Quad##T src) { \ 224 T dstw = r_quad##T##_width(dst); 225 T dsth = r_quad##T##_height(dst); 226 T srcw = r_quad##T##_width(src); 227 T srch = r_quad##T##_height(src); 228 229 ASSERT(dstw > 0 && dsth > 0 && srcw > 0 && srch > 0); 230 231 Aff3##T t; 232 r_aff3##T##_translate(r, -src[0][0], -src[0][1]); 233 r_aff3##T##_scale(&t, dstw / srcw, dsth / srch); 234 r_aff3##T##_mul(r, t, *r); 235 r_aff3##T##_translate(&t, dst[0][0], dst[0][1]); 236 r_aff3##T##_mul(r, t, *r); 237 } 238 239 AFF3_VIEW(f32) 240 AFF3_VIEW(f64) 241 242 #undef AFF3_VIEW