hs

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | LICENSE

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_