hs_math.h (9055B)
1 #ifndef HS_MATH_H_ 2 #define HS_MATH_H_ 3 4 #include <math.h> 5 #include <stdint.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 #ifndef NO_STDIO 10 #include <stdio.h> 11 #endif 12 13 #define sq(_x) (((_x)*(_x))) 14 #define castf(_val) ((float*)(_val)) 15 16 #define PI 3.141592653589793 17 #define HALF_PI 1.570796326794897 18 #define TWO_PI 6.283185307179586 19 #define EULER 2.718281828459045 20 21 #define deg2rad(deg) ((deg * PI) / 180.0) 22 23 #define MAT4_DIAG(__f) \ 24 {{__f, 0.f, 0.f, 0.f}, \ 25 {0.f, __f, 0.f, 0.f}, \ 26 {0.f, 0.f, __f, 0.f}, \ 27 {0.f, 0.f, 0.f, __f}} 28 #define MAT4_IDENTITY MAT4_DIAG(1.0f) 29 #define VEC3_SAME(__f) (vec3){__f, __f, __f} 30 31 #define min(a,b) ((a)<(b)?(a):(b)) 32 #define max(a,b) ((a)>(b)?(a):(b)) 33 #define CLAMP(x, a, b) ({x = x < a ? a : x; x = x > b ? b : x;}) 34 #define MAP(x, fL, fH, tL, tH) ((x - fL) * (tH - tL) / (fH - fL) + tL) 35 36 typedef union { 37 struct { 38 float x, y; 39 }; 40 float axis[2]; 41 float xy[2]; 42 } vec2; 43 44 typedef union { 45 struct { 46 int32_t x, y; 47 }; 48 int32_t axis[2]; 49 int32_t xy[2]; 50 } vec2i; 51 52 typedef union { 53 struct { 54 float x, y, z; 55 }; 56 struct { 57 float r, g, b; 58 }; 59 float xyz[3]; 60 float axis[4]; 61 float rgb[3]; 62 } vec3; 63 64 typedef union { 65 struct { 66 float x, y, z, w; 67 }; 68 struct { 69 float r, g, b, a; 70 }; 71 float xyzw[4]; 72 float axis[4]; 73 float rgba[4]; 74 } vec4; 75 76 typedef float mat2[2][2]; 77 typedef float mat3[3][3]; 78 typedef float mat4[4][4]; 79 80 inline static float 81 random_float() 82 { 83 // double for better rounding 84 return (float)((double)rand()/RAND_MAX); 85 } 86 87 inline static float 88 random_float_negative() 89 { 90 // double for better rounding 91 return (float)((double)rand()/(RAND_MAX) * 2.0 -1.0); 92 } 93 94 inline static float 95 vec2_len(vec2 vector) 96 { 97 return sqrtf(sq(vector.x) + sq(vector.y)); 98 } 99 100 inline static vec2 101 vec2_add(const vec2 v1, const vec2 v2) 102 { 103 return (vec2){v1.x + v2.x, v1.y + v2.y}; 104 } 105 106 inline static void 107 vec2_add_in_place(vec2* v1, const vec2 v2) 108 { 109 v1->x += v2.x; 110 v1->y += v2.y; 111 } 112 113 inline static vec2 114 vec2_sub(const vec2 v1, const vec2 v2) 115 { 116 return (vec2){v1.x - v2.x, v1.y - v2.y}; 117 } 118 119 inline static float 120 vec2_dot(const vec2 v1, const vec2 v2) 121 { 122 return v1.x * v2.x + v1.y * v2.y; 123 } 124 125 inline static float 126 vec2_cos(const vec2 v1, const vec2 v2) 127 { 128 return vec2_dot(v1, v2) / (vec2_len(v1) * vec2_len(v2)); 129 } 130 131 inline static vec2 132 vec2_mul(const vec2 v1, const vec2 v2) 133 { 134 return (vec2){ 135 v1.x * v2.x, 136 v1.y * v2.y, 137 }; 138 } 139 140 inline static vec2 141 vec2_scale(const vec2 vector, const float scalar) 142 { 143 return (vec2){ 144 vector.x * scalar, 145 vector.y * scalar, 146 }; 147 } 148 149 inline static vec2i 150 vec2i_scale(const vec2i vector, const int32_t scalar) 151 { 152 return (vec2i){ 153 vector.x * scalar, 154 vector.y * scalar, 155 }; 156 } 157 158 inline static vec2 159 vec2_norm(const vec2 vector) 160 { 161 float len = vec2_len(vector); 162 return len == 0.0f ? vector : vec2_scale(vector, 1.0f / len); 163 } 164 165 inline static uint32_t 166 vec2_null(const vec2 vector) 167 { 168 return (vector.x == 0 && vector.y == 0); 169 } 170 171 inline static vec2i 172 vec2i_div(const vec2i vector, const int32_t divisor) 173 { 174 return (vec2i){ 175 vector.x / divisor, 176 vector.y / divisor, 177 }; 178 } 179 180 inline static vec2i 181 vec2i_add(const vec2i v1, const vec2i v2) 182 { 183 return (vec2i){v1.x + v2.x, v1.y + v2.y}; 184 } 185 186 inline static vec2i 187 vec2i_sub(const vec2i v1, const vec2i v2) 188 { 189 return (vec2i){v1.x - v2.x, v1.y - v2.y}; 190 } 191 192 inline static float 193 vec3_len(const vec3 vector) 194 { 195 return sqrtf(sq(vector.x) + sq(vector.y) + sq(vector.z)); 196 } 197 198 inline static vec3 199 vec3_scale(const vec3 vector, const float scalar) 200 { 201 return (vec3){ 202 vector.x * scalar, 203 vector.y * scalar, 204 vector.z * scalar, 205 }; 206 } 207 208 inline static vec3 209 vec3_sub(const vec3 v1, const vec3 v2) 210 { 211 return (vec3){ 212 v1.x - v2.x, 213 v1.y - v2.y, 214 v1.z - v2.z 215 }; 216 } 217 218 inline static vec3 219 vec3_add(const vec3 v1, const vec3 v2) 220 { 221 return (vec3){ 222 v1.x + v2.x, 223 v1.y + v2.y, 224 v1.z + v2.z 225 }; 226 } 227 228 inline static vec3 229 vec3_mul(const vec3 v1, const vec3 v2) 230 { 231 return (vec3){ 232 v1.x * v2.x, 233 v1.y * v2.y, 234 v1.z * v2.z 235 }; 236 } 237 238 inline static vec3 239 vec3_cross(const vec3 v1, const vec3 v2) 240 { 241 return (vec3){ 242 v1.y * v2.z - v1.z * v2.y, 243 v1.z * v2.x - v1.x * v2.z, 244 v1.x * v2.y - v1.y * v2.x 245 }; 246 } 247 248 inline static vec3 249 vec3_norm(const vec3 vector) 250 { 251 float len = vec3_len(vector); 252 return len == 0.0f ? vector : vec3_scale(vector, 1.0f / len); 253 } 254 255 inline static float 256 vec3_dot(const vec3 v1, const vec3 v2) 257 { 258 return ((v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z)); 259 } 260 261 inline static vec4 262 vec4_scale(const vec4 vector, const float scalar) 263 { 264 return (vec4){ 265 vector.x * scalar, 266 vector.y * scalar, 267 vector.z * scalar, 268 vector.w * scalar, 269 }; 270 } 271 272 #ifndef NO_STDIO 273 inline static void 274 mat4_print(const mat4 mat) 275 { 276 for (uint32_t i = 0; i < 4; i++) 277 printf("mat[%d] is %f %f %f %f\n", i, mat[i][0], mat[i][1], mat[i][2], mat[i][3]); 278 } 279 inline static void 280 vec3_print(const vec3 vec) 281 { 282 printf("vec3 is %f %f %f\n", vec.x, vec.y, vec.z); 283 } 284 #endif 285 286 inline static void 287 mat4_mul(mat4 res, const mat4 m1, const mat4 m2) 288 { 289 memset(res, 0, sizeof(mat4)); 290 for (uint32_t y = 0; y < 4; y++) 291 for (uint32_t x = 0; x < 4; x++) 292 for (uint32_t e = 0; e < 4; e++) 293 res[x][y] += m1[x][e] * m2[e][y]; 294 } 295 296 inline static void 297 mat4_scale(mat4 mat, const vec3 vector) 298 { 299 for (unsigned i = 0; i < 3; i++) 300 mat[i][i] *= vector.xyz[i]; 301 } 302 303 inline static void 304 mat4_translate(mat4 mat, const vec3 vector) 305 { 306 for (unsigned i = 0; i < 3; i++) { 307 mat[3][i] += vector.xyz[i]; 308 } 309 } 310 311 inline static void 312 mat4_rotate(mat4 mat, const float angle, const vec3 axis) 313 { 314 mat4 matr = MAT4_IDENTITY; 315 316 float c = cosf(angle); 317 float s = sinf(angle); 318 319 vec3 naxis = vec3_norm(axis); 320 float x = naxis.x; 321 float y = naxis.y; 322 float z = naxis.z; 323 324 matr[0][0] = x * x * (1 - c) + c; 325 matr[0][1] = x * y * (1 - c) + z * s; 326 matr[0][2] = x * z * (1 - c) - y * s; 327 328 matr[1][0] = x * y * (1 - c) - z * s; 329 matr[1][1] = y * y * (1 - c) + c; 330 matr[1][2] = y * z * (1 - c) + x * s; 331 332 matr[2][0] = x * z * (1 - c) + y * s; 333 matr[2][1] = y * z * (1 - c) - x * s; 334 matr[2][2] = z * z * (1 - c) + c; 335 336 mat4 m2; 337 memcpy(m2, mat, sizeof(m2)); 338 mat4_mul(mat, m2, matr); 339 } 340 341 inline static void 342 mat4_ortho(mat4 res, const float l, const float r, const float b, const float t, const float n, const float f) 343 { 344 // Main diagonal 345 mat4_scale(res, (vec3){2.0f / (r - l), 2.0f / ( t - b ), -2.0f / (f - n)}); 346 return; 347 // Last column 348 mat4_translate(res, (vec3){-(r + l) / (r - l), -(t + b) / (t - b), -(f + n) / (f - n)}); 349 } 350 351 // Expects an empty identity mat4 352 inline static void 353 mat4_perspective(mat4 res, const float fov, const float asp_ratio, const float n, const float f) 354 { 355 float q = 1.0f / tanf(0.5f * fov); 356 357 res[0][0] = q / asp_ratio; 358 res[1][1] = q; 359 res[2][2] = (n + f) / (n - f); 360 res[3][2] = (2.0f * n * f) / (n - f); 361 res[2][3] = -1.0f; 362 } 363 364 inline static void 365 mat4_look_at(mat4 res, const vec3 position, const vec3 target, const vec3 up) 366 { 367 vec3 f = vec3_norm(vec3_sub(target, position)); 368 vec3 s = vec3_norm(vec3_cross(f, up)); 369 vec3 u = vec3_cross(s, f); 370 371 res[0][0] = s.x; 372 res[1][0] = s.y; 373 res[2][0] = s.z; 374 375 res[0][1] = u.x; 376 res[1][1] = u.y; 377 res[2][1] = u.z; 378 379 res[0][2] = -f.x; 380 res[1][2] = -f.y; 381 res[2][2] = -f.z; 382 383 res[3][0] = -vec3_dot(s, position); 384 res[3][1] = -vec3_dot(u, position); 385 res[3][2] = vec3_dot(f, position) + 1.0f; 386 } 387 388 /* inline static vec4 */ 389 /* mat4_mul_vec4(const mat4 mat, const vec4 vec) */ 390 /* { */ 391 /* vec4 res; */ 392 393 /* for (unsigned i = 0; i < 3; i++) */ 394 /* res.xyzw[i] = mat[i][i] * vec.xyzw[i] + mat[3][i]; */ 395 /* res.w = mat[3][3] * vec.w; */ 396 397 /* return res; */ 398 /* } */ 399 400 /* inline static vec4 */ 401 /* mat4_mul_vec3(const mat4 mat, const vec3 vec) */ 402 /* { */ 403 /* vec4 v = (vec4){vec.x, vec.y, vec.z, 1.0f}; */ 404 /* return mat4_mul_vec4(mat, v); */ 405 /* } */ 406 407 #endif // HS_MATH_H_