799 lines
21 KiB
C
799 lines
21 KiB
C
// 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 <stddef.h>
|
|
|
|
#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 <stdint.h>
|
|
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 <math.h>
|
|
|
|
#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
|