#if !defined(HANDMADE_MATH_H) /* ======================================================================== $File: $ $Date: $ $Revision: $ $Creator: Casey Muratori $ $Notice: (C) Copyright 2014 by Molly Rocket, Inc. All Rights Reserved. $ ======================================================================== */ inline v2 V2i(int32 X, int32 Y) { v2 Result = {(real32)X, (real32)Y}; return(Result); } inline v2 V2i(uint32 X, uint32 Y) { v2 Result = {(real32)X, (real32)Y}; return(Result); } inline v2 V2(real32 X, real32 Y) { v2 Result; Result.x = X; Result.y = Y; return(Result); } inline v3 V3(real32 X, real32 Y, real32 Z) { v3 Result; Result.x = X; Result.y = Y; Result.z = Z; return(Result); } inline v3 V3(v2 XY, real32 Z) { v3 Result; Result.x = XY.x; Result.y = XY.y; Result.z = Z; return(Result); } inline v4 V4(real32 X, real32 Y, real32 Z, real32 W) { v4 Result; Result.x = X; Result.y = Y; Result.z = Z; Result.w = W; return(Result); } inline v4 V4(v3 XYZ, real32 W) { v4 Result; Result.xyz = XYZ; Result.w = W; return(Result); } // // NOTE(casey): Scalar operations // inline real32 Square(real32 A) { real32 Result = A*A; return(Result); } inline real32 Lerp(real32 A, real32 t, real32 B) { real32 Result = (1.0f - t)*A + t*B; return(Result); } inline real32 Clamp(real32 Min, real32 Value, real32 Max) { real32 Result = Value; if(Result < Min) { Result = Min; } else if(Result > Max) { Result = Max; } return(Result); } inline real32 Clamp01(real32 Value) { real32 Result = Clamp(0.0f, Value, 1.0f); return(Result); } inline real32 Clamp01MapToRange(real32 Min, real32 t, real32 Max) { real32 Result = 0.0f; real32 Range = Max - Min; if(Range != 0.0f) { Result = Clamp01((t - Min) / Range); } return(Result); } inline real32 SafeRatioN(real32 Numerator, real32 Divisor, real32 N) { real32 Result = N; if(Divisor != 0.0f) { Result = Numerator / Divisor; } return(Result); } inline real32 SafeRatio0(real32 Numerator, real32 Divisor) { real32 Result = SafeRatioN(Numerator, Divisor, 0.0f); return(Result); } inline real32 SafeRatio1(real32 Numerator, real32 Divisor) { real32 Result = SafeRatioN(Numerator, Divisor, 1.0f); return(Result); } // // NOTE(casey): v2 operations // inline v2 Perp(v2 A) { v2 Result = {-A.y, A.x}; return(Result); } inline v2 operator*(real32 A, v2 B) { v2 Result; Result.x = A*B.x; Result.y = A*B.y; return(Result); } inline v2 operator*(v2 B, real32 A) { v2 Result = A*B; return(Result); } inline v2 & operator*=(v2 &B, real32 A) { B = A * B; return(B); } inline v2 operator-(v2 A) { v2 Result; Result.x = -A.x; Result.y = -A.y; return(Result); } inline v2 operator+(v2 A, v2 B) { v2 Result; Result.x = A.x + B.x; Result.y = A.y + B.y; return(Result); } inline v2 & operator+=(v2 &A, v2 B) { A = A + B; return(A); } inline v2 operator-(v2 A, v2 B) { v2 Result; Result.x = A.x - B.x; Result.y = A.y - B.y; return(Result); } inline v2 & operator-=(v2 &A, v2 B) { A = A - B; return(A); } inline v2 Hadamard(v2 A, v2 B) { v2 Result = {A.x*B.x, A.y*B.y}; return(Result); } inline real32 Inner(v2 A, v2 B) { real32 Result = A.x*B.x + A.y*B.y; return(Result); } inline real32 LengthSq(v2 A) { real32 Result = Inner(A, A); return(Result); } inline real32 Length(v2 A) { real32 Result = SquareRoot(LengthSq(A)); return(Result); } inline v2 Clamp01(v2 Value) { v2 Result; Result.x = Clamp01(Value.x); Result.y = Clamp01(Value.y); return(Result); } inline v2 Arm2(r32 Angle) { v2 Result = {Cos(Angle), Sin(Angle)}; return(Result); } // // NOTE(casey): v3 operations // inline v3 operator*(real32 A, v3 B) { v3 Result; Result.x = A*B.x; Result.y = A*B.y; Result.z = A*B.z; return(Result); } inline v3 operator*(v3 B, real32 A) { v3 Result = A*B; return(Result); } inline v3 & operator*=(v3 &B, real32 A) { B = A * B; return(B); } inline v3 operator-(v3 A) { v3 Result; Result.x = -A.x; Result.y = -A.y; Result.z = -A.z; return(Result); } inline v3 operator+(v3 A, v3 B) { v3 Result; Result.x = A.x + B.x; Result.y = A.y + B.y; Result.z = A.z + B.z; return(Result); } inline v3 & operator+=(v3 &A, v3 B) { A = A + B; return(A); } inline v3 operator-(v3 A, v3 B) { v3 Result; Result.x = A.x - B.x; Result.y = A.y - B.y; Result.z = A.z - B.z; return(Result); } inline v3 & operator-=(v3 &A, v3 B) { A = A - B; return(A); } inline v3 Hadamard(v3 A, v3 B) { v3 Result = {A.x*B.x, A.y*B.y, A.z*B.z}; return(Result); } inline real32 Inner(v3 A, v3 B) { real32 Result = A.x*B.x + A.y*B.y + A.z*B.z; return(Result); } inline real32 LengthSq(v3 A) { real32 Result = Inner(A, A); return(Result); } inline real32 Length(v3 A) { real32 Result = SquareRoot(LengthSq(A)); return(Result); } inline v3 Normalize(v3 A) { v3 Result = A * (1.0f / Length(A)); return(Result); } inline v3 Clamp01(v3 Value) { v3 Result; Result.x = Clamp01(Value.x); Result.y = Clamp01(Value.y); Result.z = Clamp01(Value.z); return(Result); } inline v3 Lerp(v3 A, real32 t, v3 B) { v3 Result = (1.0f - t)*A + t*B; return(Result); } // // NOTE(casey): v4 operations // inline v4 operator*(real32 A, v4 B) { v4 Result; Result.x = A*B.x; Result.y = A*B.y; Result.z = A*B.z; Result.w = A*B.w; return(Result); } inline v4 operator*(v4 B, real32 A) { v4 Result = A*B; return(Result); } inline v4 & operator*=(v4 &B, real32 A) { B = A * B; return(B); } inline v4 operator-(v4 A) { v4 Result; Result.x = -A.x; Result.y = -A.y; Result.z = -A.z; Result.w = -A.w; return(Result); } inline v4 operator+(v4 A, v4 B) { v4 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 v4 & operator+=(v4 &A, v4 B) { A = A + B; return(A); } inline v4 operator-(v4 A, v4 B) { v4 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 v4 & operator-=(v4 &A, v4 B) { A = A - B; return(A); } inline v4 Hadamard(v4 A, v4 B) { v4 Result = {A.x*B.x, A.y*B.y, A.z*B.z, A.w*B.w}; return(Result); } inline real32 Inner(v4 A, v4 B) { real32 Result = A.x*B.x + A.y*B.y + A.z*B.z + A.w*B.w; return(Result); } inline real32 LengthSq(v4 A) { real32 Result = Inner(A, A); return(Result); } inline real32 Length(v4 A) { real32 Result = SquareRoot(LengthSq(A)); return(Result); } inline v4 Clamp01(v4 Value) { v4 Result; Result.x = Clamp01(Value.x); Result.y = Clamp01(Value.y); Result.z = Clamp01(Value.z); Result.w = Clamp01(Value.w); return(Result); } inline v4 Lerp(v4 A, real32 t, v4 B) { v4 Result = (1.0f - t)*A + t*B; return(Result); } // // NOTE(casey): Rectangle2 // inline rectangle2 InvertedInfinityRectangle2(void) { rectangle2 Result; Result.Min.x = Result.Min.y = Real32Maximum; Result.Max.x = Result.Max.y = -Real32Maximum; return(Result); } inline rectangle2 Union(rectangle2 A, rectangle2 B) { rectangle2 Result; Result.Min.x = (A.Min.x < B.Min.x) ? A.Min.x : B.Min.x; Result.Min.y = (A.Min.y < B.Min.y) ? A.Min.y : B.Min.y; Result.Max.x = (A.Max.x > B.Max.x) ? A.Max.x : B.Max.x; Result.Max.y = (A.Max.y > B.Max.y) ? A.Max.y : B.Max.y; return(Result); } inline v2 GetMinCorner(rectangle2 Rect) { v2 Result = Rect.Min; return(Result); } inline v2 GetMaxCorner(rectangle2 Rect) { v2 Result = Rect.Max; return(Result); } inline v2 GetDim(rectangle2 Rect) { v2 Result = Rect.Max - Rect.Min; return(Result); } inline v2 GetCenter(rectangle2 Rect) { v2 Result = 0.5f*(Rect.Min + Rect.Max); return(Result); } inline rectangle2 RectMinMax(v2 Min, v2 Max) { rectangle2 Result; Result.Min = Min; Result.Max = Max; return(Result); } inline rectangle2 RectMinDim(v2 Min, v2 Dim) { rectangle2 Result; Result.Min = Min; Result.Max = Min + Dim; return(Result); } inline rectangle2 RectCenterHalfDim(v2 Center, v2 HalfDim) { rectangle2 Result; Result.Min = Center - HalfDim; Result.Max = Center + HalfDim; return(Result); } inline rectangle2 AddRadiusTo(rectangle2 A, v2 Radius) { rectangle2 Result; Result.Min = A.Min - Radius; Result.Max = A.Max + Radius; return(Result); } inline rectangle2 Offset(rectangle2 A, v2 Offset) { rectangle2 Result; Result.Min = A.Min + Offset; Result.Max = A.Max + Offset; return(Result); } inline rectangle2 RectCenterDim(v2 Center, v2 Dim) { rectangle2 Result = RectCenterHalfDim(Center, 0.5f*Dim); return(Result); } inline bool32 IsInRectangle(rectangle2 Rectangle, v2 Test) { bool32 Result = ((Test.x >= Rectangle.Min.x) && (Test.y >= Rectangle.Min.y) && (Test.x < Rectangle.Max.x) && (Test.y < Rectangle.Max.y)); return(Result); } inline v2 GetBarycentric(rectangle2 A, v2 P) { v2 Result; Result.x = SafeRatio0(P.x - A.Min.x, A.Max.x - A.Min.x); Result.y = SafeRatio0(P.y - A.Min.y, A.Max.y - A.Min.y); return(Result); } // // NOTE(casey): Rectangle3 // inline v3 GetMinCorner(rectangle3 Rect) { v3 Result = Rect.Min; return(Result); } inline v3 GetMaxCorner(rectangle3 Rect) { v3 Result = Rect.Max; return(Result); } inline v3 GetDim(rectangle3 Rect) { v3 Result = Rect.Max - Rect.Min; return(Result); } inline v3 GetCenter(rectangle3 Rect) { v3 Result = 0.5f*(Rect.Min + Rect.Max); return(Result); } inline rectangle3 RectMinMax(v3 Min, v3 Max) { rectangle3 Result; Result.Min = Min; Result.Max = Max; return(Result); } inline rectangle3 RectMinDim(v3 Min, v3 Dim) { rectangle3 Result; Result.Min = Min; Result.Max = Min + Dim; return(Result); } inline rectangle3 RectCenterHalfDim(v3 Center, v3 HalfDim) { rectangle3 Result; Result.Min = Center - HalfDim; Result.Max = Center + HalfDim; return(Result); } inline rectangle3 AddRadiusTo(rectangle3 A, v3 Radius) { rectangle3 Result; Result.Min = A.Min - Radius; Result.Max = A.Max + Radius; return(Result); } inline rectangle3 Offset(rectangle3 A, v3 Offset) { rectangle3 Result; Result.Min = A.Min + Offset; Result.Max = A.Max + Offset; return(Result); } inline rectangle3 RectCenterDim(v3 Center, v3 Dim) { rectangle3 Result = RectCenterHalfDim(Center, 0.5f*Dim); return(Result); } inline bool32 IsInRectangle(rectangle3 Rectangle, v3 Test) { bool32 Result = ((Test.x >= Rectangle.Min.x) && (Test.y >= Rectangle.Min.y) && (Test.z >= Rectangle.Min.z) && (Test.x < Rectangle.Max.x) && (Test.y < Rectangle.Max.y) && (Test.z < Rectangle.Max.z)); return(Result); } inline bool32 RectanglesIntersect(rectangle3 A, rectangle3 B) { bool32 Result = !((B.Max.x <= A.Min.x) || (B.Min.x >= A.Max.x) || (B.Max.y <= A.Min.y) || (B.Min.y >= A.Max.y) || (B.Max.z <= A.Min.z) || (B.Min.z >= A.Max.z)); return(Result); } inline v3 GetBarycentric(rectangle3 A, v3 P) { v3 Result; Result.x = SafeRatio0(P.x - A.Min.x, A.Max.x - A.Min.x); Result.y = SafeRatio0(P.y - A.Min.y, A.Max.y - A.Min.y); Result.z = SafeRatio0(P.z - A.Min.z, A.Max.z - A.Min.z); return(Result); } inline rectangle2 ToRectangleXY(rectangle3 A) { rectangle2 Result; Result.Min = A.Min.xy; Result.Max = A.Max.xy; return(Result); } // // // struct rectangle2i { int32 MinX, MinY; int32 MaxX, MaxY; }; inline rectangle2i Intersect(rectangle2i A, rectangle2i B) { rectangle2i Result; Result.MinX = (A.MinX < B.MinX) ? B.MinX : A.MinX; Result.MinY = (A.MinY < B.MinY) ? B.MinY : A.MinY; Result.MaxX = (A.MaxX > B.MaxX) ? B.MaxX : A.MaxX; Result.MaxY = (A.MaxY > B.MaxY) ? B.MaxY : A.MaxY; return(Result); } inline rectangle2i Union(rectangle2i A, rectangle2i B) { rectangle2i Result; Result.MinX = (A.MinX < B.MinX) ? A.MinX : B.MinX; Result.MinY = (A.MinY < B.MinY) ? A.MinY : B.MinY; Result.MaxX = (A.MaxX > B.MaxX) ? A.MaxX : B.MaxX; Result.MaxY = (A.MaxY > B.MaxY) ? A.MaxY : B.MaxY; return(Result); } inline int32 GetClampedRectArea(rectangle2i A) { int32 Width = (A.MaxX - A.MinX); int32 Height = (A.MaxY - A.MinY); int32 Result = 0; if((Width > 0) && (Height > 0)) { Result = Width*Height; } return(Result); } inline bool32 HasArea(rectangle2i A) { bool32 Result = ((A.MinX < A.MaxX) && (A.MinY < A.MaxY)); return(Result); } inline rectangle2i InvertedInfinityRectangle2i(void) { rectangle2i Result; Result.MinX = Result.MinY = INT_MAX; Result.MaxX = Result.MaxY = -INT_MAX; return(Result); } inline v4 SRGB255ToLinear1(v4 C) { v4 Result; real32 Inv255 = 1.0f / 255.0f; Result.r = Square(Inv255*C.r); Result.g = Square(Inv255*C.g); Result.b = Square(Inv255*C.b); Result.a = Inv255*C.a; return(Result); } inline v4 Linear1ToSRGB255(v4 C) { v4 Result; real32 One255 = 255.0f; Result.r = One255*SquareRoot(C.r); Result.g = One255*SquareRoot(C.g); Result.b = One255*SquareRoot(C.b); Result.a = One255*C.a; return(Result); } #define HANDMADE_MATH_H #endif