// gb_math.h - v0.03 - public domain C math library - no warranty implied; use at your own risk // A C math library geared towards game development /* Version History: 0.03 - Complete Replacement 0.01 - Initial Version LICENSE This software is in the public domain. Where that dedication is not recognized, you are granted a perpetual, irrevocable license to copy, distribute, and modify this file as you see fit. WARNING - This library is _slightly_ experimental and features may not work as expected. - This also means that many functions are not documented. CONTENTS - Common Macros - Types - Vec(2,3,4) - Mat(2,3,4) - Float(2,3,4) - Rect(2,3) - Aabb(2,3) - Operations - Functions - Type Functions - Random TODO - Complex - Quaternion - More Math Functions */ #ifndef GB_MATH_INCLUDE_GB_MATH_H #define GB_MATH_INCLUDE_GB_MATH_H #include #ifdef GB_MATH_STATIC #define GB_MATH_DEF static #else #define GB_MATH_DEF extern #endif typedef union Vec2 { struct { float x, y; }; float e[2]; } Vec2; typedef union Vec3 { struct { float x, y, z; }; struct { float r, g, b; }; Vec2 xy; float e[2]; } Vec3; typedef union Vec4 { struct { float x, y, z, w; }; struct { float r, g, b, a; }; struct { Vec2 xy, zw; }; Vec3 xyz; Vec3 rgb; float e[4]; } Vec4; typedef union Mat2 { struct { Vec2 x, y; }; Vec4 col[2]; float e[4]; } Mat2; typedef union Mat3 { struct { Vec3 x, y, z; }; Vec4 col[3]; float e[9]; } Mat3; typedef union Mat4 { struct { Vec4 x, y, z, w; }; Vec4 col[4]; float e[16]; } Mat4; typedef float Float2[2]; typedef float Float3[3]; typedef float Float4[4]; typedef struct Rect2 { Vec2 pos, dim; } Rect2; typedef struct Rect3 { Vec3 pos, dim; } Rect3; typedef struct Aabb2 { Vec2 center, half_size; } Aabb2; typedef struct Aabb3 { Vec3 center, half_size; } Aabb3; #if defined(_MSC_VER) typedef unsigned __int8 gb_math_u8; typedef unsigned __int32 gb_math_u32; typedef unsigned __int64 gb_math_u64; #else #include typedef uint8_t gb_math_u8; typedef uint32_t gb_math_u32; typedef uint64_t gb_math_u64; #endif // Constants #define MATH_TAU 6.28318530718f #if defined(__cplusplus) extern "C" { #endif // Vector GB_MATH_DEF Vec2 vec2_zero(void); GB_MATH_DEF Vec2 vec2(float x, float y); GB_MATH_DEF Vec2 vec2v(float x[2]); GB_MATH_DEF Vec3 vec3_zero(void); GB_MATH_DEF Vec3 vec3(float x, float y, float z); GB_MATH_DEF Vec3 vec3v(float x[3]); GB_MATH_DEF Vec4 vec4_zero(void); GB_MATH_DEF Vec4 vec4(float x, float y, float z, float w); GB_MATH_DEF Vec4 vec4v(float x[4]); GB_MATH_DEF void vec2_add(Vec2 *d, Vec2 v0, Vec2 v1); GB_MATH_DEF void vec2_sub(Vec2 *d, Vec2 v0, Vec2 v1); GB_MATH_DEF void vec2_mul(Vec2 *d, Vec2 v, float s); GB_MATH_DEF void vec2_div(Vec2 *d, Vec2 v, float s); GB_MATH_DEF void vec3_add(Vec3 *d, Vec3 v0, Vec3 v1); GB_MATH_DEF void vec3_sub(Vec3 *d, Vec3 v0, Vec3 v1); GB_MATH_DEF void vec3_mul(Vec3 *d, Vec3 v, float s); GB_MATH_DEF void vec3_div(Vec3 *d, Vec3 v, float s); GB_MATH_DEF void vec4_add(Vec4 *d, Vec4 v0, Vec4 v1); GB_MATH_DEF void vec4_sub(Vec4 *d, Vec4 v0, Vec4 v1); GB_MATH_DEF void vec4_mul(Vec4 *d, Vec4 v, float s); GB_MATH_DEF void vec4_div(Vec4 *d, Vec4 v, float s); GB_MATH_DEF void vec2_addeq(Vec2 *d, Vec2 v); GB_MATH_DEF void vec2_subeq(Vec2 *d, Vec2 v); GB_MATH_DEF void vec2_muleq(Vec2 *d, float s); GB_MATH_DEF void vec2_diveq(Vec2 *d, float s); GB_MATH_DEF void vec3_addeq(Vec3 *d, Vec3 v); GB_MATH_DEF void vec3_subeq(Vec3 *d, Vec3 v); GB_MATH_DEF void vec3_muleq(Vec3 *d, float s); GB_MATH_DEF void vec3_diveq(Vec3 *d, float s); GB_MATH_DEF void vec4_addeq(Vec4 *d, Vec4 v); GB_MATH_DEF void vec4_subeq(Vec4 *d, Vec4 v); GB_MATH_DEF void vec4_muleq(Vec4 *d, float s); GB_MATH_DEF void vec4_diveq(Vec4 *d, float s); GB_MATH_DEF float vec2_dot(Vec2 v0, Vec2 v1); GB_MATH_DEF float vec3_dot(Vec3 v0, Vec3 v1); GB_MATH_DEF float vec4_dot(Vec4 v0, Vec4 v1); GB_MATH_DEF void vec2_cross(float *d, Vec2 v0, Vec2 v1); GB_MATH_DEF void vec3_cross(Vec3 *d, Vec3 v0, Vec3 v1); GB_MATH_DEF float vec2_mag2(Vec2 v); GB_MATH_DEF float vec3_mag2(Vec3 v); GB_MATH_DEF float vec4_mag2(Vec4 v); GB_MATH_DEF float vec2_mag(Vec2 v); GB_MATH_DEF float vec3_mag(Vec3 v); GB_MATH_DEF float vec4_mag(Vec4 v); GB_MATH_DEF void vec2_norm(Vec2 *d, Vec2 v); GB_MATH_DEF void vec3_norm(Vec3 *d, Vec3 v); GB_MATH_DEF void vec4_norm(Vec4 *d, Vec4 v); GB_MATH_DEF float vec2_aspect(Vec2 v); // Matrix GB_MATH_DEF void mat2_identity(Mat2 *m); GB_MATH_DEF void float22_identity(float m[2][2]); GB_MATH_DEF void mat2_transpose(Mat2 *m); GB_MATH_DEF void mat2_mul(Mat2 *out, Mat2 *m1, Mat2 *m2); GB_MATH_DEF void mat2_mul_vec2(Vec2 *out, Mat2 *m, Vec2 in); GB_MATH_DEF Mat2 *mat2_v(Vec2 m[2]); GB_MATH_DEF Mat2 *mat2_f(float m[2][2]); GB_MATH_DEF Float2 *float22_m(Mat2 *m); GB_MATH_DEF Float2 *float22_v(Vec2 m[2]); GB_MATH_DEF Float2 *float22_4(float m[4]); GB_MATH_DEF void float22_transpose(float (*vec)[2]); GB_MATH_DEF void float22_mul(float (*out)[2], float (*mat1)[2], float (*mat2)[2]); GB_MATH_DEF void float22_mul_vec2(Vec2 *out, float m[2][2], Vec2 in); GB_MATH_DEF void mat3_identity(Mat3 *m); GB_MATH_DEF void float33_identity(float m[3][3]); GB_MATH_DEF void mat3_transpose(Mat3 *m); GB_MATH_DEF void mat3_mul(Mat3 *out, Mat3 *m1, Mat3 *m2); GB_MATH_DEF void mat3_mul_vec3(Vec3 *out, Mat3 *m, Vec3 in); GB_MATH_DEF Mat3 *mat3_v(Vec3 m[3]); GB_MATH_DEF Mat3 *mat3_f(float m[3][3]); GB_MATH_DEF Float3 *float33_m(Mat3 *m); GB_MATH_DEF Float3 *float33_v(Vec3 m[3]); GB_MATH_DEF Float3 *float33_9(float m[9]); GB_MATH_DEF void float33_transpose(float (*vec)[3]); GB_MATH_DEF void float33_mul(float (*out)[3], float (*mat1)[3], float (*mat2)[3]); GB_MATH_DEF void float33_mul_vec3(Vec3 *out, float m[3][3], Vec3 in); GB_MATH_DEF void mat4_identity(Mat4 *m); GB_MATH_DEF void float44_identity(float m[4][4]); GB_MATH_DEF void mat4_transpose(Mat4 *m); GB_MATH_DEF void mat4_mul(Mat4 *out, Mat4 *m1, Mat4 *m2); GB_MATH_DEF void mat4_mul_vec4(Vec4 *out, Mat4 *m, Vec4 in); GB_MATH_DEF Mat4 *mat4_v(Vec4 m[4]); GB_MATH_DEF Mat4 *mat4_f(float m[4][4]); GB_MATH_DEF Float4 *float44_m(Mat4 *m); GB_MATH_DEF Float4 *float44_v(Vec4 m[4]); GB_MATH_DEF Float4 *float44_16(float m[16]); GB_MATH_DEF void float44_transpose(float (*vec)[4]); GB_MATH_DEF void float44_mul(float (*out)[4], float (*mat1)[4], float (*mat2)[4]); GB_MATH_DEF void float44_mul_vec4(Vec4 *out, float m[4][4], Vec4 in); // Hermite Interpolations GB_MATH_DEF float lerp(float a, float b, float t); GB_MATH_DEF float smooth_step(float a, float b, float t); GB_MATH_DEF float smoother_step(float a, float b, float t); GB_MATH_DEF void vec2_lerp(Vec2 *d, Vec2 a, Vec2 b, float t); GB_MATH_DEF void vec3_lerp(Vec3 *d, Vec3 a, Vec3 b, float t); GB_MATH_DEF void vec4_lerp(Vec4 *d, Vec4 a, Vec4 b, float t); // Angles GB_MATH_DEF float to_radians(float degrees); GB_MATH_DEF float to_degrees(float radians); // Projections // NOTE(bill): Uses OpenGL Projection Conventions (-1 to 1) // NOTE(bill): If Direct3D is needed, use custom projection to shift-z to (0 to 1) GB_MATH_DEF void mat4_ortho2d(Mat4 *out, float left, float right, float bottom, float top); GB_MATH_DEF void mat4_ortho3d(Mat4 *out, float left, float right, float bottom, float top, float z_near, float z_far); #ifndef MURMUR64_SEED #define MURMUR64_SEED 0x9747b28c #endif // Hashing GB_MATH_DEF gb_math_u64 hash_murmur64(void const *key, size_t num_bytes); // Random // TODO(bill): Use a generator for the random numbers GB_MATH_DEF float random_range_float(float min_inc, float max_inc); GB_MATH_DEF int random_range_int(int min_inc, int max_inc); #if defined(__cplusplus) } #endif #endif // GB_MATH_INCLUDE_GB_MATH_H //////////////////// // // // Implementation // // // //////////////////// #if defined(GB_MATH_IMPLEMENTATION) #include #define VEC2_2OP(a,c,post) \ a->x = c.x post; \ a->y = c.y post; #define VEC2_3OP(a,b,op,c,post) \ a->x = b.x op c.x post; \ a->y = b.y op c.y post; #define VEC3_2OP(a,c,post) \ a->x = c.x post; \ a->y = c.y post; \ a->z = c.z post; #define VEC3_3OP(a,b,op,c,post) \ a->x = b.x op c.x post; \ a->y = b.y op c.y post; \ a->z = b.z op c.z post; #define VEC4_2OP(a,c,post) \ a->x = c.x post; \ a->y = c.y post; \ a->z = c.z post; \ a->w = c.w post; #define VEC4_3OP(a,b,op,c,post) \ a->x = b.x op c.x post; \ a->y = b.y op c.y post; \ a->z = b.z op c.z post; \ a->w = b.w op c.w post; Vec2 vec2_zero(void) { Vec2 v = {0, 0}; return v; } Vec2 vec2(float x, float y) { Vec2 v = {x, y}; return v; } Vec2 vec2v(float x[2]) { Vec2 v = {x[0], x[1]}; return v; } Vec3 vec3_zero(void) { Vec3 v = {0, 0, 0}; return v; } Vec3 vec3(float x, float y, float z) { Vec3 v = {x, y, z}; return v; } Vec3 vec3v(float x[3]) { Vec3 v = {x[0], x[1], x[2]}; return v; } Vec4 vec4_zero(void) { Vec4 v = {0, 0, 0, 0}; return v; } Vec4 vec4(float x, float y, float z, float w) { Vec4 v = {x, y, z, w}; return v; } Vec4 vec4v(float x[4]) { Vec4 v = {x[0], x[1], x[2], x[3]}; return v; } void vec2_add(Vec2 *d, Vec2 v0, Vec2 v1) { VEC2_3OP(d,v0,+,v1,+0); } void vec2_sub(Vec2 *d, Vec2 v0, Vec2 v1) { VEC2_3OP(d,v0,-,v1,+0); } void vec2_mul(Vec2 *d, Vec2 v, float s) { VEC2_2OP(d,v,* s); } void vec2_div(Vec2 *d, Vec2 v, float s) { VEC2_2OP(d,v,/ s); } void vec3_add(Vec3 *d, Vec3 v0, Vec3 v1) { VEC3_3OP(d,v0,+,v1,+0); } void vec3_sub(Vec3 *d, Vec3 v0, Vec3 v1) { VEC3_3OP(d,v0,-,v1,+0); } void vec3_mul(Vec3 *d, Vec3 v, float s) { VEC3_2OP(d,v,* s); } void vec3_div(Vec3 *d, Vec3 v, float s) { VEC3_2OP(d,v,/ s); } void vec4_add(Vec4 *d, Vec4 v0, Vec4 v1) { VEC4_3OP(d,v0,+,v1,+0); } void vec4_sub(Vec4 *d, Vec4 v0, Vec4 v1) { VEC4_3OP(d,v0,-,v1,+0); } void vec4_mul(Vec4 *d, Vec4 v, float s) { VEC4_2OP(d,v,* s); } void vec4_div(Vec4 *d, Vec4 v, float s) { VEC4_2OP(d,v,/ s); } void vec2_addeq(Vec2 *d, Vec2 v) { VEC2_3OP(d,(*d),+,v,+0); } void vec2_subeq(Vec2 *d, Vec2 v) { VEC2_3OP(d,(*d),-,v,+0); } void vec2_muleq(Vec2 *d, float s) { VEC2_2OP(d,(*d),* s); } void vec2_diveq(Vec2 *d, float s) { VEC2_2OP(d,(*d),/ s); } void vec3_addeq(Vec3 *d, Vec3 v) { VEC3_3OP(d,(*d),+,v,+0); } void vec3_subeq(Vec3 *d, Vec3 v) { VEC3_3OP(d,(*d),-,v,+0); } void vec3_muleq(Vec3 *d, float s) { VEC3_2OP(d,(*d),* s); } void vec3_diveq(Vec3 *d, float s) { VEC3_2OP(d,(*d),/ s); } void vec4_addeq(Vec4 *d, Vec4 v) { VEC4_3OP(d,(*d),+,v,+0); } void vec4_subeq(Vec4 *d, Vec4 v) { VEC4_3OP(d,(*d),-,v,+0); } void vec4_muleq(Vec4 *d, float s) { VEC4_2OP(d,(*d),* s); } void vec4_diveq(Vec4 *d, float s) { VEC4_2OP(d,(*d),/ s); } float vec2_dot(Vec2 v0, Vec2 v1) { return v0.x*v1.x + v0.y*v1.y; } float vec3_dot(Vec3 v0, Vec3 v1) { return v0.x*v1.x + v0.y*v1.y + v0.z*v1.z; } float vec4_dot(Vec4 v0, Vec4 v1) { return v0.x*v1.x + v0.y*v1.y + v0.z*v1.z + v0.w*v1.w; } void vec2_cross(float *d, Vec2 v0, Vec2 v1) { *d = v0.x*v1.y - v1.x*v0.y; } void vec3_cross(Vec3 *d, Vec3 v0, Vec3 v1) { d->x = v0.y*v1.z - v0.z*v1.y; d->y = v0.z*v1.x - v0.x*v1.z; d->z = v0.x*v1.y - v0.y*v1.x; } float vec2_mag2(Vec2 v) { return vec2_dot(v, v); } float vec3_mag2(Vec3 v) { return vec3_dot(v, v); } float vec4_mag2(Vec4 v) { return vec4_dot(v, v); } // TODO(bill): Create custom sqrt function float vec2_mag(Vec2 v) { return sqrtf(vec2_dot(v, v)); } float vec3_mag(Vec3 v) { return sqrtf(vec3_dot(v, v)); } float vec4_mag(Vec4 v) { return sqrtf(vec4_dot(v, v)); } // TODO(bill): Should I calculate inv_sqrt directly? void vec2_norm(Vec2 *d, Vec2 v) { vec2_div(d, v, vec2_mag(v)); } void vec3_norm(Vec3 *d, Vec3 v) { vec3_div(d, v, vec3_mag(v)); } void vec4_norm(Vec4 *d, Vec4 v) { vec4_div(d, v, vec4_mag(v)); } float vec2_aspect(Vec2 v) { if (v.y < 0.0001f) return 0.0f; return v.x/v.y; } void mat2_transpose(Mat2 *m) { float22_transpose(float22_m(m)); } void mat2_identity(Mat2 *m) { float22_identity(float22_m(m)); } void mat2_mul(Mat2 *out, Mat2 *m1, Mat2 *m2) { float22_mul(float22_m(out), float22_m(m1), float22_m(m2)); } void float22_identity(float m[2][2]) { m[0][0] = 1; m[0][1] = 0; m[1][0] = 0; m[1][1] = 1; } void mat2_mul_vec2(Vec2 *out, Mat2 *m, Vec2 in) { float22_mul_vec2(out, float22_m(m), in); } Mat2 *mat2_v(Vec2 m[2]) { return (Mat2 *)m; } Mat2 *mat2_f(float m[2][2]) { return (Mat2 *)m; } Float2 *float22_m(Mat2 *m) { return (Float2 *)m; } Float2 *float22_v(Vec2 m[2]) { return (Float2 *)m; } Float2 *float22_4(float m[4]) { return (Float2 *)m; } void float22_transpose(float (*vec)[2]) { int i, j; for (j = 0; j < 2; j++) { for (i = j + 1; i < 2; i++) { float t = vec[i][j]; vec[i][j] = vec[j][i]; vec[j][i] = t; } } } void float22_mul(float (*out)[2], float (*mat1)[2], float (*mat2)[2]) { int i, j; float temp1[2][2], temp2[2][2]; if (mat1 == out) { memcpy(temp1, mat1, sizeof(temp1)); mat1 = temp1; } if (mat2 == out) { memcpy(temp2, mat2, sizeof(temp2)); mat2 = temp2; } for (j = 0; j < 2; j++) { for (i = 0; i < 2; i++) { out[j][i] = mat1[0][i]*mat2[j][0] + mat1[1][i]*mat2[j][1]; } } } void float22_mul_vec2(Vec2 *out, float m[2][2], Vec2 v) { out->x = m[0][0] * v.x + m[0][1] * v.y; out->y = m[1][0] * v.x + m[1][1] * v.y; } void mat3_transpose(Mat3 *m) { float33_transpose(float33_m(m)); } void mat3_identity(Mat3 *m) { float33_identity(float33_m(m)); } void mat3_mul(Mat3 *out, Mat3 *m1, Mat3 *m2) { float33_mul(float33_m(out), float33_m(m1), float33_m(m2)); } void float33_identity(float m[3][3]) { m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; } void mat3_mul_vec3(Vec3 *out, Mat3 *m, Vec3 in) { float33_mul_vec3(out, float33_m(m), in); } Mat3 *mat3_v(Vec3 m[3]) { return (Mat3 *)m; } Mat3 *mat3_f(float m[3][3]) { return (Mat3 *)m; } Float3 *float33_m(Mat3 *m) { return (Float3 *)m; } Float3 *float33_v(Vec3 m[3]) { return (Float3 *)m; } Float3 *float33_16(float m[9]) { return (Float3 *)m; } void float33_transpose(float (*vec)[3]) { int i, j; for (j = 0; j < 3; j++) { for (i = j + 1; i < 3; i++) { float t = vec[i][j]; vec[i][j] = vec[j][i]; vec[j][i] = t; } } } void float33_mul(float (*out)[3], float (*mat1)[3], float (*mat2)[3]) { int i, j; float temp1[3][3], temp2[3][3]; if (mat1 == out) { memcpy(temp1, mat1, sizeof(temp1)); mat1 = temp1; } if (mat2 == out) { memcpy(temp2, mat2, sizeof(temp2)); mat2 = temp2; } for (j = 0; j < 3; j++) { for (i = 0; i < 3; i++) { out[j][i] = mat1[0][i]*mat2[j][0] + mat1[1][i]*mat2[j][1] + mat1[2][i]*mat2[j][2]; } } } void float33_mul_vec3(Vec3 *out, float m[3][3], Vec3 v) { out->x = m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z; out->y = m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z; out->z = m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z; } void mat4_transpose(Mat4 *m) { float44_transpose(float44_m(m)); } void mat4_identity(Mat4 *m) { float44_identity(float44_m(m)); } void mat4_mul(Mat4 *out, Mat4 *m1, Mat4 *m2) { float44_mul(float44_m(out), float44_m(m1), float44_m(m2)); } void float44_identity(float m[4][4]) { m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0; m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = 0; m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = 0; m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1; } void mat4_mul_vec4(Vec4 *out, Mat4 *m, Vec4 in) { float44_mul_vec4(out, float44_m(m), in); } Mat4 *mat4_v(Vec4 m[4]) { return (Mat4 *)m; } Mat4 *mat4_f(float m[4][4]) { return (Mat4 *)m; } Float4 *float44_m(Mat4 *m) { return (Float4 *)m; } Float4 *float44_v(Vec4 m[4]) { return (Float4 *)m; } Float4 *float44_16(float m[16]) { return (Float4 *)m; } void float44_transpose(float (*vec)[4]) { int i, j; for (j = 0; j < 4; j++) { for (i = j + 1; i < 4; i++) { float t = vec[i][j]; vec[i][j] = vec[j][i]; vec[j][i] = t; } } } void float44_mul(float (*out)[4], float (*mat1)[4], float (*mat2)[4]) { int i, j; float temp1[4][4], temp2[4][4]; if (mat1 == out) { memcpy(temp1, mat1, sizeof(temp1)); mat1 = temp1; } if (mat2 == out) { memcpy(temp2, mat2, sizeof(temp2)); mat2 = temp2; } for (j = 0; j < 4; j++) { for (i = 0; i < 4; i++) { out[j][i] = mat1[0][i]*mat2[j][0] + mat1[1][i]*mat2[j][1] + mat1[2][i]*mat2[j][2] + mat1[3][i]*mat2[j][3]; } } } void float44_mul_vec4(Vec4 *out, float m[4][4], Vec4 v) { out->x = m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w; out->y = m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w; out->z = m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w; out->w = m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w; } float lerp(float a, float b, float t) { return a*(1.0f-t) + b*t; } float smooth_step(float a, float b, float t) { float x = (t - a)/(b - a); return x*x*(3.0f - 2.0f*x); } float smoother_step(float a, float b, float t) { float x = (t - a)/(b - a); return x*x*x*(x*(6.0f*x - 15.0f) + 10.0f); } #define VEC_LERPN(N, d, a, b, t) Vec##N db; vec##N##_mul(&db, b, t); vec##N##_add(d, a, db) void vec2_lerp(Vec2 *d, Vec2 a, Vec2 b, float t) { VEC_LERPN(2, d, a, b, t); } void vec3_lerp(Vec3 *d, Vec3 a, Vec3 b, float t) { VEC_LERPN(3, d, a, b, t); } void vec4_lerp(Vec4 *d, Vec4 a, Vec4 b, float t) { VEC_LERPN(4, d, a, b, t); } float to_radians(float degrees) { return degrees * MATH_TAU / 360.0f; } float to_degrees(float radians) { return radians * 360.0f / MATH_TAU; } void mat4_ortho2d(Mat4 *out, float left, float right, float bottom, float top) { Float4 *m; mat4_identity(out); m = float44_m(out); m[0][0] = 2.0f / (right - left); m[1][1] = 2.0f / (top - bottom); m[2][2] = -1.0f; m[3][0] = -(right + left) / (right - left); m[3][1] = -(top + bottom) / (top - bottom); } void mat4_ortho3d(Mat4 *out, float left, float right, float bottom, float top, float z_near, float z_far) { Float4 *m; mat4_identity(out); m = float44_m(out); m[0][0] = +2.0f / (right - left); m[1][1] = +2.0f / (top - bottom); m[2][2] = -2.0f / (z_far - z_near); m[3][0] = -(right + left) / (right - left); m[3][1] = -(top + bottom) / (top - bottom); m[3][2] = -(z_far + z_near) / (z_far - z_near); } #if defined(__x86_64__) || defined(__ppc64__) u64 hash_murmur64(void const *key, size_t num_bytes) { u64 const m = 0xc6a4a7935bd1e995ULL; int const r = 47; u64 h = MURMUR64_SEED ^ (num_bytes * m); u64 *data = (u64 *)(key); u64 *end = data + (num_bytes / 8); u8 *data2; while (data != end) { u64 k = *data++; k *= m; k ^= k >> r; k *= m; h ^= k; h *= m; } data2 = (u8 *)data; switch (num_bytes & 7) { case 7: h ^= (u64)data2[6] << 48; case 6: h ^= (u64)data2[5] << 40; case 5: h ^= (u64)data2[4] << 32; case 4: h ^= (u64)data2[3] << 24; case 3: h ^= (u64)data2[2] << 16; case 2: h ^= (u64)data2[1] << 8; case 1: h ^= (u64)data2[0]; h *= m; }; h ^= h >> r; h *= m; h ^= h >> r; return h; } #else gb_math_u64 hash_murmur64(void const *key, size_t num_bytes) { gb_math_u32 const m = 0x5bd1e995; gb_math_u32 const r = 24; gb_math_u64 h = 0; gb_math_u32 h1 = (gb_math_u32)MURMUR64_SEED ^ (gb_math_u32)num_bytes; gb_math_u32 h2 = (gb_math_u32)((gb_math_u64)MURMUR64_SEED >> 32); gb_math_u32 *data = (gb_math_u32 *)key; while (num_bytes >= 8) { gb_math_u32 k1, k2; k1 = *data++; k1 *= m; k1 ^= k1 >> r; k1 *= m; h1 *= m; h1 ^= k1; num_bytes -= 4; k2 = *data++; k2 *= m; k2 ^= k2 >> r; k2 *= m; h2 *= m; h2 ^= k2; num_bytes -= 4; } if (num_bytes >= 4) { gb_math_u32 k1 = *data++; k1 *= m; k1 ^= k1 >> r; k1 *= m; h1 *= m; h1 ^= k1; num_bytes -= 4; } switch (num_bytes) { case 3: h2 ^= (gb_math_u32)((gb_math_u8 *)(data)[2]) << 16; case 2: h2 ^= (gb_math_u32)((gb_math_u8 *)(data)[1]) << 8; case 1: h2 ^= (gb_math_u32)((gb_math_u8 *)(data)[0]) << 0; h2 *= m; }; h1 ^= h2 >> 18; h1 *= m; h2 ^= h1 >> 22; h2 *= m; h1 ^= h2 >> 17; h1 *= m; h2 ^= h1 >> 19; h2 *= m; h = (gb_math_u64)(h << 32) | (gb_math_u64)h2; return h; } #endif // TODO(bill): Make better random number generators float random_range_float(float min_inc, float max_inc) { static int random_value = 0xdeadbeef; // Random Value float result; random_value = random_value * 2147001325 + 715136305; // BCPL generator result = *(float *)&random_value; // bits result /= 4294967295.0f; result *= (max_inc - min_inc); result += min_inc; return result; } int random_range_int(int min_inc, int max_inc) { static int random_value = 0xdeadbeef; // Random Value int diff, result; random_value = random_value * 2147001325 + 715136305; // BCPL generator diff = max_inc - min_inc + 1; result = random_value % diff; result += min_inc; return result; } #endif // GB_MATH_IMPLEMENTATION