775 lines
14 KiB
C++
775 lines
14 KiB
C++
|
/*
|
||
|
* Mr. 4th Dimention - Allen Webster
|
||
|
*
|
||
|
* 15.05.2015
|
||
|
*
|
||
|
* Math functions for 4coder
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
// TOP
|
||
|
|
||
|
/*
|
||
|
* Scalar operators
|
||
|
*/
|
||
|
|
||
|
#define C_MATH 1
|
||
|
|
||
|
#define DEG_TO_RAD 0.0174533f
|
||
|
|
||
|
#if C_MATH
|
||
|
#include <math.h>
|
||
|
#endif
|
||
|
|
||
|
inline f32
|
||
|
ABS(f32 x){
|
||
|
if (x < 0) x = -x;
|
||
|
return x;
|
||
|
}
|
||
|
|
||
|
inline f32
|
||
|
MOD(f32 x, i32 m){
|
||
|
#if C_MATH
|
||
|
f32 whole, frac;
|
||
|
frac = modff(x, &whole);
|
||
|
return ((i32)(whole) % m) + frac;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
inline f32
|
||
|
SQRT(f32 x){
|
||
|
#if C_MATH
|
||
|
return sqrt(x);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
inline f32
|
||
|
SIN(f32 x_degrees){
|
||
|
#if C_MATH
|
||
|
return sinf(x_degrees * DEG_TO_RAD);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
inline f32
|
||
|
COS(f32 x_degrees){
|
||
|
#if C_MATH
|
||
|
return cosf(x_degrees * DEG_TO_RAD);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Rounding
|
||
|
*/
|
||
|
|
||
|
inline i32
|
||
|
TRUNC32(real32 x) { return (i32)x; }
|
||
|
|
||
|
inline i32
|
||
|
FLOOR32(real32 x) { return (i32)(x)-((x!=(i32)(x) && x<0)?1:0); }
|
||
|
|
||
|
inline i32
|
||
|
CEIL32(real32 x) { return (i32)(x)+((x!=(i32)(x) && x>0)?1:0); }
|
||
|
|
||
|
inline i32
|
||
|
ROUND32(real32 x) { return FLOOR32(x + .5f); }
|
||
|
|
||
|
inline i32
|
||
|
DIVCEIL32(i32 n, i32 d) {
|
||
|
i32 q = (n/d);
|
||
|
return q + (q*d < n);
|
||
|
}
|
||
|
|
||
|
inline real32
|
||
|
FRACPART32(real32 x) { return x - (i32)x; }
|
||
|
|
||
|
inline u32
|
||
|
ROUNDPOT32(u32 v){
|
||
|
v--;
|
||
|
v |= v >> 1;
|
||
|
v |= v >> 2;
|
||
|
v |= v >> 4;
|
||
|
v |= v >> 8;
|
||
|
v |= v >> 16;
|
||
|
v++;
|
||
|
return v;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Rectangles
|
||
|
*/
|
||
|
|
||
|
struct i32_Rect{
|
||
|
i32 x0, y0;
|
||
|
i32 x1, y1;
|
||
|
};
|
||
|
|
||
|
struct f32_Rect{
|
||
|
f32 x0, y0;
|
||
|
f32 x1, y1;
|
||
|
};
|
||
|
|
||
|
inline i32_Rect
|
||
|
i32R(i32 l, i32 t, i32 r, i32 b){
|
||
|
i32_Rect rect;
|
||
|
rect.x0 = l; rect.y0 = t;
|
||
|
rect.x1 = r; rect.y1 = b;
|
||
|
return rect;
|
||
|
}
|
||
|
|
||
|
inline i32_Rect
|
||
|
i32R(f32_Rect r){
|
||
|
i32_Rect rect;
|
||
|
rect.x0 = (i32)r.x0;
|
||
|
rect.y0 = (i32)r.y0;
|
||
|
rect.x1 = (i32)r.x1;
|
||
|
rect.y1 = (i32)r.y1;
|
||
|
return rect;
|
||
|
}
|
||
|
|
||
|
inline i32_Rect
|
||
|
i32XYWH(i32 x, i32 y, i32 w, i32 h){
|
||
|
i32_Rect rect;
|
||
|
rect.x0 = x; rect.y0 = y;
|
||
|
rect.x1 = x+w; rect.y1 = y+h;
|
||
|
return rect;
|
||
|
}
|
||
|
|
||
|
inline f32_Rect
|
||
|
f32R(f32 l, f32 t, f32 r, f32 b){
|
||
|
f32_Rect rect;
|
||
|
rect.x0 = l; rect.y0 = t;
|
||
|
rect.x1 = r; rect.y1 = b;
|
||
|
return rect;
|
||
|
}
|
||
|
|
||
|
inline f32_Rect
|
||
|
f32R(i32_Rect r){
|
||
|
f32_Rect rect;
|
||
|
rect.x0 = (f32)r.x0;
|
||
|
rect.y0 = (f32)r.y0;
|
||
|
rect.x1 = (f32)r.x1;
|
||
|
rect.y1 = (f32)r.y1;
|
||
|
return rect;
|
||
|
}
|
||
|
|
||
|
inline f32_Rect
|
||
|
f32XYWH(f32 x, f32 y, f32 w, f32 h){
|
||
|
f32_Rect rect;
|
||
|
rect.x0 = x; rect.y0 = y;
|
||
|
rect.x1 = x+w; rect.y1 = y+h;
|
||
|
return rect;
|
||
|
}
|
||
|
|
||
|
inline b32
|
||
|
hit_check(i32 x, i32 y, i32 x0, i32 y0, i32 x1, i32 y1){
|
||
|
return (x >= x0 && x < x1 && y >= y0 && y < y1);
|
||
|
}
|
||
|
|
||
|
inline b32
|
||
|
hit_check(i32 x, i32 y, i32_Rect rect){
|
||
|
return (hit_check(x, y, rect.x0, rect.y0, rect.x1, rect.y1));
|
||
|
}
|
||
|
|
||
|
inline b32
|
||
|
hit_check(i32 x, i32 y, f32 x0, f32 y0, f32 x1, f32 y1){
|
||
|
return (x >= x0 && x < x1 && y >= y0 && y < y1);
|
||
|
}
|
||
|
|
||
|
inline b32
|
||
|
hit_check(i32 x, i32 y, f32_Rect rect){
|
||
|
return (hit_check(x, y, rect.x0, rect.y0, rect.x1, rect.y1));
|
||
|
}
|
||
|
|
||
|
inline b32
|
||
|
positive_area(i32_Rect rect){
|
||
|
return (rect.x0 < rect.x1 && rect.y0 < rect.y1);
|
||
|
}
|
||
|
|
||
|
inline i32_Rect
|
||
|
get_inner_rect(i32_Rect outer, i32 margin){
|
||
|
i32_Rect r;
|
||
|
r.x0 = outer.x0 + margin;
|
||
|
r.y0 = outer.y0 + margin;
|
||
|
r.x1 = outer.x1 - margin;
|
||
|
r.y1 = outer.y1 - margin;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
inline b32
|
||
|
fits_inside(i32_Rect rect, i32_Rect outer){
|
||
|
return (rect.x0 >= outer.x0 && rect.x1 <= outer.x1 &&
|
||
|
rect.y0 >= outer.y0 && rect.y1 <= outer.y1);
|
||
|
}
|
||
|
|
||
|
inline i32_Rect
|
||
|
rect_clamp_to_rect(i32_Rect rect, i32_Rect clamp_box){
|
||
|
if (rect.x0 < clamp_box.x0) rect.x0 = clamp_box.x0;
|
||
|
if (rect.y0 < clamp_box.y0) rect.y0 = clamp_box.y0;
|
||
|
if (rect.x1 > clamp_box.x1) rect.x1 = clamp_box.x1;
|
||
|
if (rect.y1 > clamp_box.y1) rect.y1 = clamp_box.y1;
|
||
|
return rect;
|
||
|
}
|
||
|
|
||
|
inline i32_Rect
|
||
|
rect_clamp_to_rect(i32 left, i32 top, i32 right, i32 bottom, i32_Rect clamp_box){
|
||
|
return rect_clamp_to_rect(i32R(left, top, right, bottom), clamp_box);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Vectors
|
||
|
*/
|
||
|
|
||
|
struct Vec2{
|
||
|
union{
|
||
|
struct{
|
||
|
real32 x, y;
|
||
|
};
|
||
|
struct{
|
||
|
real32 v[2];
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
struct Vec3{
|
||
|
union{
|
||
|
struct{
|
||
|
real32 x, y, z;
|
||
|
};
|
||
|
struct{
|
||
|
real32 r, g, b;
|
||
|
};
|
||
|
struct{
|
||
|
Vec2 xy;
|
||
|
real32 _z;
|
||
|
};
|
||
|
struct{
|
||
|
real32 _x;
|
||
|
Vec2 yz;
|
||
|
};
|
||
|
struct{
|
||
|
real32 v[3];
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
struct Vec4{
|
||
|
union{
|
||
|
struct{
|
||
|
real32 r, g, b, a;
|
||
|
};
|
||
|
|
||
|
struct{
|
||
|
real32 h, s, l, __a;
|
||
|
};
|
||
|
struct{
|
||
|
real32 x, y, z, w;
|
||
|
};
|
||
|
struct{
|
||
|
Vec3 rgb;
|
||
|
real32 _a;
|
||
|
};
|
||
|
struct{
|
||
|
Vec3 xyz;
|
||
|
real32 _w;
|
||
|
};
|
||
|
struct{
|
||
|
real32 _x;
|
||
|
Vec3 yzw;
|
||
|
};
|
||
|
struct{
|
||
|
real32 v[4];
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
inline internal Vec2
|
||
|
V2(real32 x, real32 y){
|
||
|
Vec2 result;
|
||
|
result.x = x;
|
||
|
result.y = y;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec3
|
||
|
V3(real32 x, real32 y, real32 z){
|
||
|
Vec3 result;
|
||
|
result.x = x;
|
||
|
result.y = y;
|
||
|
result.z = z;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec4
|
||
|
V4(real32 x, real32 y, real32 z, real32 w){
|
||
|
Vec4 result;
|
||
|
result.x = x;
|
||
|
result.y = y;
|
||
|
result.z = z;
|
||
|
result.w = w;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec2
|
||
|
operator+(Vec2 a, Vec2 b){
|
||
|
Vec2 result;
|
||
|
result.x = a.x + b.x;
|
||
|
result.y = a.y + b.y;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec3
|
||
|
operator+(Vec3 a, Vec3 b){
|
||
|
Vec3 result;
|
||
|
result.x = a.x + b.x;
|
||
|
result.y = a.y + b.y;
|
||
|
result.z = a.z + b.z;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec4
|
||
|
operator+(Vec4 a, Vec4 b){
|
||
|
Vec4 result;
|
||
|
result.x = a.x + b.x;
|
||
|
result.y = a.y + b.y;
|
||
|
result.z = a.z + b.z;
|
||
|
result.w = a.w + b.w;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec2
|
||
|
operator-(Vec2 a, Vec2 b){
|
||
|
Vec2 result;
|
||
|
result.x = a.x - b.x;
|
||
|
result.y = a.y - b.y;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec3
|
||
|
operator-(Vec3 a, Vec3 b){
|
||
|
Vec3 result;
|
||
|
result.x = a.x - b.x;
|
||
|
result.y = a.y - b.y;
|
||
|
result.z = a.z - b.z;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec4
|
||
|
operator-(Vec4 a, Vec4 b){
|
||
|
Vec4 result;
|
||
|
result.x = a.x - b.x;
|
||
|
result.y = a.y - b.y;
|
||
|
result.z = a.z - b.z;
|
||
|
result.w = a.w - b.w;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec2
|
||
|
operator*(Vec2 a, real32 k){
|
||
|
Vec2 result;
|
||
|
result.x = a.x * k;
|
||
|
result.y = a.y * k;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec3
|
||
|
operator*(Vec3 a, real32 k){
|
||
|
Vec3 result;
|
||
|
result.x = a.x * k;
|
||
|
result.y = a.y * k;
|
||
|
result.z = a.z * k;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec4
|
||
|
operator*(Vec4 a, real32 k){
|
||
|
Vec4 result;
|
||
|
result.x = a.x * k;
|
||
|
result.y = a.y * k;
|
||
|
result.z = a.z * k;
|
||
|
result.w = a.w * k;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec2
|
||
|
operator*(real32 k, Vec2 a){
|
||
|
Vec2 result;
|
||
|
result.x = a.x * k;
|
||
|
result.y = a.y * k;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec3
|
||
|
operator*(real32 k, Vec3 a){
|
||
|
Vec3 result;
|
||
|
result.x = a.x * k;
|
||
|
result.y = a.y * k;
|
||
|
result.z = a.z * k;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec4
|
||
|
operator*(real32 k, Vec4 a){
|
||
|
Vec4 result;
|
||
|
result.x = a.x * k;
|
||
|
result.y = a.y * k;
|
||
|
result.z = a.z * k;
|
||
|
result.w = a.w * k;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec2&
|
||
|
operator+=(Vec2 &a, Vec2 b){
|
||
|
a = (a + b);
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
inline internal Vec3&
|
||
|
operator+=(Vec3 &a, Vec3 b){
|
||
|
a = (a + b);
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
inline internal Vec4&
|
||
|
operator+=(Vec4 &a, Vec4 b){
|
||
|
a = (a + b);
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
inline internal Vec2&
|
||
|
operator-=(Vec2 &a, Vec2 b){
|
||
|
a = (a - b);
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
inline internal Vec3&
|
||
|
operator-=(Vec3 &a, Vec3 b){
|
||
|
a = (a - b);
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
inline internal Vec4&
|
||
|
operator-=(Vec4 &a, Vec4 b){
|
||
|
a = (a - b);
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
inline internal Vec2&
|
||
|
operator*=(Vec2 &a, real32 k){
|
||
|
a = (a * k);
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
inline internal Vec3&
|
||
|
operator*=(Vec3 &a, real32 k){
|
||
|
a = (a * k);
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
inline internal Vec4&
|
||
|
operator*=(Vec4 &a, real32 k){
|
||
|
a = (a * k);
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
inline internal real32
|
||
|
dot(Vec2 a, Vec2 b){
|
||
|
real32 result;
|
||
|
result = a.x*b.x + a.y*b.y;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal real32
|
||
|
dot(Vec3 a, Vec3 b){
|
||
|
real32 result;
|
||
|
result = a.x*b.x + a.y*b.y + a.z*b.z;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal real32
|
||
|
dot(Vec4 a, Vec4 b){
|
||
|
real32 result;
|
||
|
result = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec3
|
||
|
cross(Vec3 a, Vec3 b){
|
||
|
Vec3 result;
|
||
|
result.x = a.y*b.z - b.y*a.z;
|
||
|
result.y = a.z*b.x - b.z*a.x;
|
||
|
result.z = a.x*b.y - b.x*a.y;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec2
|
||
|
hadamard(Vec2 a, Vec2 b){
|
||
|
Vec2 result;
|
||
|
result.x = a.x*b.x;
|
||
|
result.y = a.y*b.y;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec3
|
||
|
hadamard(Vec3 a, Vec3 b){
|
||
|
Vec3 result;
|
||
|
result.x = a.x*b.x;
|
||
|
result.y = a.y*b.y;
|
||
|
result.z = a.z*b.z;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec4
|
||
|
hadamard(Vec4 a, Vec4 b){
|
||
|
Vec4 result;
|
||
|
result.x = a.x*b.x;
|
||
|
result.y = a.y*b.y;
|
||
|
result.z = a.z*b.z;
|
||
|
result.w = a.w*b.w;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline internal Vec2
|
||
|
perp(Vec2 v){
|
||
|
Vec2 result;
|
||
|
result.x = -v.y;
|
||
|
result.y = v.x;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline Vec2
|
||
|
polar_to_cartesian(real32 theta_degrees, real32 length){
|
||
|
Vec2 result;
|
||
|
result.x = COS(theta_degrees)*length;
|
||
|
result.y = SIN(theta_degrees)*length;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
inline Vec2
|
||
|
rotate(Vec2 v, real32 theta_degrees){
|
||
|
Vec2 result;
|
||
|
real32 c, s;
|
||
|
c = COS(theta_degrees);
|
||
|
s = SIN(theta_degrees);
|
||
|
result.x = v.x*c - v.y*s;
|
||
|
result.y = v.x*s + v.y*c;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Coordinates
|
||
|
*/
|
||
|
|
||
|
struct Matrix2{
|
||
|
Vec2 x_axis;
|
||
|
Vec2 y_axis;
|
||
|
};
|
||
|
|
||
|
internal Matrix2
|
||
|
invert(Vec2 x_axis, Vec2 y_axis){
|
||
|
Matrix2 result = {};
|
||
|
real32 det = 1.f / (x_axis.x*y_axis.y - x_axis.y*y_axis.x);
|
||
|
result.x_axis.x = y_axis.y*det;
|
||
|
result.y_axis.x = -y_axis.x*det;
|
||
|
result.x_axis.y = -x_axis.y*det;
|
||
|
result.y_axis.y = x_axis.x*det;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
internal Matrix2
|
||
|
invert(Matrix2 m){
|
||
|
Matrix2 result = {};
|
||
|
real32 det = 1.f / (m.x_axis.x*m.y_axis.y - m.x_axis.y*m.y_axis.x);
|
||
|
result.x_axis.x = m.y_axis.y*det;
|
||
|
result.y_axis.x = -m.y_axis.x*det;
|
||
|
result.x_axis.y = -m.x_axis.y*det;
|
||
|
result.y_axis.y = m.x_axis.x*det;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Lerps, Clamps, Thresholds, Etc
|
||
|
*/
|
||
|
|
||
|
inline real32
|
||
|
lerp(real32 a, real32 t, real32 b){
|
||
|
return a + (b-a)*t;
|
||
|
}
|
||
|
|
||
|
inline Vec2
|
||
|
lerp(Vec2 a, real32 t, Vec2 b){
|
||
|
return a + (b-a)*t;
|
||
|
}
|
||
|
|
||
|
inline Vec3
|
||
|
lerp(Vec3 a, real32 t, Vec3 b){
|
||
|
return a + (b-a)*t;
|
||
|
}
|
||
|
|
||
|
inline Vec4
|
||
|
lerp(Vec4 a, real32 t, Vec4 b){
|
||
|
return a + (b-a)*t;
|
||
|
}
|
||
|
|
||
|
inline real32
|
||
|
unlerp(real32 a, real32 x, real32 b){
|
||
|
return (x - a) / (b - a);
|
||
|
}
|
||
|
|
||
|
inline real32
|
||
|
clamp(real32 a, real32 n, real32 z){
|
||
|
return (n<a)?(a):((n>z)?(z):n);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Color
|
||
|
*/
|
||
|
|
||
|
// TODO(allen): Convert colors to Vec4
|
||
|
inline internal u32
|
||
|
color_blend(u32 a, real32 t, u32 b){
|
||
|
union{
|
||
|
u8 byte[4];
|
||
|
u32 comp;
|
||
|
} A, B, R;
|
||
|
|
||
|
A.comp = a;
|
||
|
B.comp = b;
|
||
|
|
||
|
R.byte[0] = (u8)lerp(A.byte[0], t, B.byte[0]);
|
||
|
R.byte[1] = (u8)lerp(A.byte[1], t, B.byte[1]);
|
||
|
R.byte[2] = (u8)lerp(A.byte[2], t, B.byte[2]);
|
||
|
R.byte[3] = (u8)lerp(A.byte[3], t, B.byte[3]);
|
||
|
|
||
|
return R.comp;
|
||
|
}
|
||
|
|
||
|
internal Vec3
|
||
|
unpack_color3(u32 color){
|
||
|
Vec3 result;
|
||
|
result.r = ((color >> 16) & 0xFF) / 255.f;
|
||
|
result.g = ((color >> 8) & 0xFF) / 255.f;
|
||
|
result.b = ((color >> 0) & 0xFF) / 255.f;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
internal Vec4
|
||
|
unpack_color4(u32 color){
|
||
|
Vec4 result;
|
||
|
result.a = ((color >> 24) & 0xFF) / 255.f;
|
||
|
result.r = ((color >> 16) & 0xFF) / 255.f;
|
||
|
result.g = ((color >> 8) & 0xFF) / 255.f;
|
||
|
result.b = ((color >> 0) & 0xFF) / 255.f;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
internal u32
|
||
|
pack_color4(Vec4 color){
|
||
|
u32 result =
|
||
|
((u8)(color.a * 255) << 24) |
|
||
|
((u8)(color.r * 255) << 16) |
|
||
|
((u8)(color.g * 255) << 8) |
|
||
|
((u8)(color.b * 255) << 0);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
internal Vec4
|
||
|
rgba_to_hsla(Vec4 rgba){
|
||
|
Vec4 hsla = {};
|
||
|
real32 max, min, delta;
|
||
|
i32 maxc;
|
||
|
hsla.a = rgba.a;
|
||
|
max = rgba.r; min = rgba.r;
|
||
|
maxc = 0;
|
||
|
if (rgba.r < rgba.g){
|
||
|
max = rgba.g;
|
||
|
maxc = 1;
|
||
|
}
|
||
|
if (rgba.b > max){
|
||
|
max = rgba.b;
|
||
|
maxc = 2;
|
||
|
}
|
||
|
if (rgba.r > rgba.g){
|
||
|
min = rgba.g;
|
||
|
}
|
||
|
if (rgba.b < min){
|
||
|
min = rgba.b;
|
||
|
}
|
||
|
delta = max - min;
|
||
|
|
||
|
hsla.z = (max + min) * .5f;
|
||
|
if (delta == 0){
|
||
|
hsla.x = 0.f;
|
||
|
hsla.y = 0.f;
|
||
|
}
|
||
|
else{
|
||
|
switch (maxc){
|
||
|
case 0:
|
||
|
{
|
||
|
hsla.x = (rgba.g - rgba.b) / delta;
|
||
|
hsla.x += (rgba.g < rgba.b) * 6.f;
|
||
|
}break;
|
||
|
|
||
|
case 1:
|
||
|
{
|
||
|
hsla.x = (rgba.b - rgba.r) / delta;
|
||
|
hsla.x += 2.f;
|
||
|
}break;
|
||
|
|
||
|
case 2:
|
||
|
{
|
||
|
hsla.x = (rgba.r - rgba.g) / delta;
|
||
|
hsla.x += 4.f;
|
||
|
}break;
|
||
|
}
|
||
|
hsla.x *= (1/6.f); // * 60 / 360
|
||
|
hsla.y = delta / (1.f - ABS(2.f*hsla.z - 1.f));
|
||
|
}
|
||
|
|
||
|
return hsla;
|
||
|
}
|
||
|
|
||
|
internal Vec4
|
||
|
hsla_to_rgba(Vec4 hsla){
|
||
|
if (hsla.h >= 1.f) hsla.h = 0.f;
|
||
|
Vec4 rgba = {};
|
||
|
real32 C, X, m;
|
||
|
i32 H;
|
||
|
rgba.a = hsla.a;
|
||
|
C = (1.f - ABS(2*hsla.z - 1.f)) * hsla.y;
|
||
|
X = C * (1.f-ABS(MOD(hsla.x*6.f, 2)-1.f));
|
||
|
m = hsla.z - C*.5f;
|
||
|
H = FLOOR32(hsla.x * 6.f);
|
||
|
switch (H){
|
||
|
case 0:
|
||
|
rgba.r = C; rgba.g = X; rgba.b = 0;
|
||
|
break;
|
||
|
|
||
|
case 1:
|
||
|
rgba.r = X; rgba.g = C; rgba.b = 0;
|
||
|
break;
|
||
|
|
||
|
case 2:
|
||
|
rgba.r = 0; rgba.g = C; rgba.b = X;
|
||
|
break;
|
||
|
|
||
|
case 3:
|
||
|
rgba.r = 0; rgba.g = X; rgba.b = C;
|
||
|
break;
|
||
|
|
||
|
case 4:
|
||
|
rgba.r = X; rgba.g = 0; rgba.b = C;
|
||
|
break;
|
||
|
|
||
|
case 5:
|
||
|
rgba.r = C; rgba.g = 0; rgba.b = X;
|
||
|
break;
|
||
|
}
|
||
|
rgba.r += m;
|
||
|
rgba.g += m;
|
||
|
rgba.b += m;
|
||
|
return rgba;
|
||
|
}
|
||
|
|
||
|
// BOTTOM
|
||
|
|