/* HandmadeMath.h v1.13.0 This is a single header file with a bunch of useful functions for game and graphics math operations. ============================================================================= To disable SSE intrinsics, you MUST #define HANDMADE_MATH_NO_SSE in EXACTLY one C or C++ file that includes this header, BEFORE the include, like this: #define HANDMADE_MATH_NO_SSE #include "HandmadeMath.h" ============================================================================= If you would prefer not to use the HMM_ prefix on function names, you can #define HMM_PREFIX To use a custom prefix instead, you can #define HMM_PREFIX(name) YOUR_PREFIX_##name ============================================================================= To use HandmadeMath without the CRT, you MUST #define HMM_SINF MySinF #define HMM_COSF MyCosF #define HMM_TANF MyTanF #define HMM_SQRTF MySqrtF #define HMM_EXPF MyExpF #define HMM_LOGF MyLogF #define HMM_ACOSF MyACosF #define HMM_ATANF MyATanF #define HMM_ATAN2F MYATan2F Provide your own implementations of SinF, CosF, TanF, ACosF, ATanF, ATan2F, ExpF, and LogF in EXACTLY one C or C++ file that includes this header, BEFORE the include, like this: #define HMM_SINF MySinF #define HMM_COSF MyCosF #define HMM_TANF MyTanF #define HMM_SQRTF MySqrtF #define HMM_EXPF MyExpF #define HMM_LOGF MyLogF #define HMM_ACOSF MyACosF #define HMM_ATANF MyATanF #define HMM_ATAN2F MyATan2F #include "HandmadeMath.h" If you do not define all of these, HandmadeMath.h will use the versions of these functions that are provided by the CRT. ============================================================================= 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. CREDITS Written by Zakary Strange (strangezak@protonmail.com && @strangezak) Functionality: Matt Mascarenhas (@miblo_) Aleph FieryDrake (@fierydrake) Gingerbill (@TheGingerBill) Ben Visness (@bvisness) Trinton Bullard (@Peliex_Dev) @AntonDan Fixes: Jeroen van Rijn (@J_vanRijn) Kiljacken (@Kiljacken) Insofaras (@insofaras) Daniel Gibson (@DanielGibson) */ // Dummy macros for when test framework is not present. #ifndef COVERAGE #define COVERAGE(a, b) #endif #ifndef ASSERT_COVERED #define ASSERT_COVERED(a) #endif /* let's figure out if SSE is really available (unless disabled anyway) (it isn't on non-x86/x86_64 platforms or even x86 without explicit SSE support) => only use "#ifdef HANDMADE_MATH__USE_SSE" to check for SSE support below this block! */ #ifndef HANDMADE_MATH_NO_SSE # ifdef _MSC_VER /* MSVC supports SSE in amd64 mode or _M_IX86_FP >= 1 (2 means SSE2) */ # if defined(_M_AMD64) || ( defined(_M_IX86_FP) && _M_IX86_FP >= 1 ) # define HANDMADE_MATH__USE_SSE 1 # endif # else /* not MSVC, probably GCC, clang, icc or something that doesn't support SSE anyway */ # ifdef __SSE__ /* they #define __SSE__ if it's supported */ # define HANDMADE_MATH__USE_SSE 1 # endif /* __SSE__ */ # endif /* not _MSC_VER */ #endif /* #ifndef HANDMADE_MATH_NO_SSE */ #ifdef HANDMADE_MATH__USE_SSE #include #endif #ifndef HANDMADE_MATH_H #define HANDMADE_MATH_H #ifdef _MSC_VER #pragma warning(disable:4201) #endif #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" #if (defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) || defined(__clang__) #pragma GCC diagnostic ignored "-Wmissing-braces" #endif #ifdef __clang__ #pragma GCC diagnostic ignored "-Wgnu-anonymous-struct" #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif #endif #if defined(__GNUC__) || defined(__clang__) #define HMM_DEPRECATED(msg) __attribute__((deprecated(msg))) #elif defined(_MSC_VER) #define HMM_DEPRECATED(msg) __declspec(deprecated(msg)) #else #define HMM_DEPRECATED(msg) #endif #ifdef __cplusplus extern "C" { #endif #define HMM_INLINE static inline #if !defined(HMM_SINF) || !defined(HMM_COSF) || !defined(HMM_TANF) || \ !defined(HMM_SQRTF) || !defined(HMM_EXPF) || !defined(HMM_LOGF) || \ !defined(HMM_ACOSF) || !defined(HMM_ATANF)|| !defined(HMM_ATAN2F) #include #endif #ifndef HMM_SINF #define HMM_SINF sinf #endif #ifndef HMM_COSF #define HMM_COSF cosf #endif #ifndef HMM_TANF #define HMM_TANF tanf #endif #ifndef HMM_SQRTF #define HMM_SQRTF sqrtf #endif #ifndef HMM_EXPF #define HMM_EXPF expf #endif #ifndef HMM_LOGF #define HMM_LOGF logf #endif #ifndef HMM_ACOSF #define HMM_ACOSF acosf #endif #ifndef HMM_ATANF #define HMM_ATANF atanf #endif #ifndef HMM_ATAN2F #define HMM_ATAN2F atan2f #endif #define HMM_PI32 3.14159265359f #define HMM_PI 3.14159265358979323846 #define HMM_MIN(a, b) ((a) > (b) ? (b) : (a)) #define HMM_MAX(a, b) ((a) < (b) ? (b) : (a)) #define HMM_ABS(a) ((a) > 0 ? (a) : -(a)) #define HMM_MOD(a, m) (((a) % (m)) >= 0 ? ((a) % (m)) : (((a) % (m)) + (m))) #define HMM_SQUARE(x) ((x) * (x)) #ifndef HMM_PREFIX #define HMM_PREFIX(name) HMM_##name #endif typedef union hmm_vec2 { struct { float X, Y; }; struct { float U, V; }; struct { float Left, Right; }; struct { float Width, Height; }; float Elements[2]; #ifdef __cplusplus inline float &operator[](const int &Index) { return Elements[Index]; } #endif } hmm_vec2; typedef union hmm_vec3 { struct { float X, Y, Z; }; struct { float U, V, W; }; struct { float R, G, B; }; struct { hmm_vec2 XY; float Ignored0_; }; struct { float Ignored1_; hmm_vec2 YZ; }; struct { hmm_vec2 UV; float Ignored2_; }; struct { float Ignored3_; hmm_vec2 VW; }; float Elements[3]; #ifdef __cplusplus inline float &operator[](const int &Index) { return Elements[Index]; } #endif } hmm_vec3; typedef union hmm_vec4 { struct { union { hmm_vec3 XYZ; struct { float X, Y, Z; }; }; float W; }; struct { union { hmm_vec3 RGB; struct { float R, G, B; }; }; float A; }; struct { hmm_vec2 XY; float Ignored0_; float Ignored1_; }; struct { float Ignored2_; hmm_vec2 YZ; float Ignored3_; }; struct { float Ignored4_; float Ignored5_; hmm_vec2 ZW; }; float Elements[4]; #ifdef HANDMADE_MATH__USE_SSE __m128 InternalElementsSSE; #endif #ifdef __cplusplus inline float &operator[](const int &Index) { return Elements[Index]; } #endif } hmm_vec4; typedef union hmm_mat4 { float Elements[4][4]; #ifdef HANDMADE_MATH__USE_SSE __m128 Columns[4]; HMM_DEPRECATED("Our matrices are column-major, so this was named incorrectly. Use Columns instead.") __m128 Rows[4]; #endif #ifdef __cplusplus inline hmm_vec4 operator[](const int &Index) { hmm_vec4 Result; float* Column = Elements[Index]; Result.Elements[0] = Column[0]; Result.Elements[1] = Column[1]; Result.Elements[2] = Column[2]; Result.Elements[3] = Column[3]; return Result; } #endif } hmm_mat4; typedef union hmm_quaternion { struct { union { hmm_vec3 XYZ; struct { float X, Y, Z; }; }; float W; }; float Elements[4]; #ifdef HANDMADE_MATH__USE_SSE __m128 InternalElementsSSE; #endif } hmm_quaternion; typedef signed int hmm_bool; typedef hmm_vec2 hmm_v2; typedef hmm_vec3 hmm_v3; typedef hmm_vec4 hmm_v4; typedef hmm_mat4 hmm_m4; /* * Floating-point math functions */ COVERAGE(HMM_SinF, 1) HMM_INLINE float HMM_PREFIX(SinF)(float Radians) { ASSERT_COVERED(HMM_SinF); float Result = HMM_SINF(Radians); return (Result); } COVERAGE(HMM_CosF, 1) HMM_INLINE float HMM_PREFIX(CosF)(float Radians) { ASSERT_COVERED(HMM_CosF); float Result = HMM_COSF(Radians); return (Result); } COVERAGE(HMM_TanF, 1) HMM_INLINE float HMM_PREFIX(TanF)(float Radians) { ASSERT_COVERED(HMM_TanF); float Result = HMM_TANF(Radians); return (Result); } COVERAGE(HMM_ACosF, 1) HMM_INLINE float HMM_PREFIX(ACosF)(float Radians) { ASSERT_COVERED(HMM_ACosF); float Result = HMM_ACOSF(Radians); return (Result); } COVERAGE(HMM_ATanF, 1) HMM_INLINE float HMM_PREFIX(ATanF)(float Radians) { ASSERT_COVERED(HMM_ATanF); float Result = HMM_ATANF(Radians); return (Result); } COVERAGE(HMM_ATan2F, 1) HMM_INLINE float HMM_PREFIX(ATan2F)(float Left, float Right) { ASSERT_COVERED(HMM_ATan2F); float Result = HMM_ATAN2F(Left, Right); return (Result); } COVERAGE(HMM_ExpF, 1) HMM_INLINE float HMM_PREFIX(ExpF)(float Float) { ASSERT_COVERED(HMM_ExpF); float Result = HMM_EXPF(Float); return (Result); } COVERAGE(HMM_LogF, 1) HMM_INLINE float HMM_PREFIX(LogF)(float Float) { ASSERT_COVERED(HMM_LogF); float Result = HMM_LOGF(Float); return (Result); } COVERAGE(HMM_SquareRootF, 1) HMM_INLINE float HMM_PREFIX(SquareRootF)(float Float) { ASSERT_COVERED(HMM_SquareRootF); float Result; #ifdef HANDMADE_MATH__USE_SSE __m128 In = _mm_set_ss(Float); __m128 Out = _mm_sqrt_ss(In); Result = _mm_cvtss_f32(Out); #else Result = HMM_SQRTF(Float); #endif return(Result); } COVERAGE(HMM_RSquareRootF, 1) HMM_INLINE float HMM_PREFIX(RSquareRootF)(float Float) { ASSERT_COVERED(HMM_RSquareRootF); float Result; #ifdef HANDMADE_MATH__USE_SSE __m128 In = _mm_set_ss(Float); __m128 Out = _mm_rsqrt_ss(In); Result = _mm_cvtss_f32(Out); #else Result = 1.0f/HMM_PREFIX(SquareRootF)(Float); #endif return(Result); } COVERAGE(HMM_Power, 2) HMM_INLINE float HMM_PREFIX(Power)(float Base, int Exponent) { ASSERT_COVERED(HMM_Power); float Result = 1.0f; float Mul = Exponent < 0 ? 1.f / Base : Base; int X = Exponent < 0 ? -Exponent : Exponent; while (X) { if (X & 1) { ASSERT_COVERED(HMM_Power); Result *= Mul; } Mul *= Mul; X >>= 1; } return (Result); } COVERAGE(HMM_PowerF, 1) HMM_INLINE float HMM_PREFIX(PowerF)(float Base, float Exponent) { ASSERT_COVERED(HMM_PowerF); float Result = HMM_EXPF(Exponent * HMM_LOGF(Base)); return (Result); } /* * Utility functions */ COVERAGE(HMM_ToRadians, 1) HMM_INLINE float HMM_PREFIX(ToRadians)(float Degrees) { ASSERT_COVERED(HMM_ToRadians); float Result = Degrees * (HMM_PI32 / 180.0f); return (Result); } COVERAGE(HMM_Lerp, 1) HMM_INLINE float HMM_PREFIX(Lerp)(float A, float Time, float B) { ASSERT_COVERED(HMM_Lerp); float Result = (1.0f - Time) * A + Time * B; return (Result); } COVERAGE(HMM_Clamp, 1) HMM_INLINE float HMM_PREFIX(Clamp)(float Min, float Value, float Max) { ASSERT_COVERED(HMM_Clamp); float Result = Value; if(Result < Min) { Result = Min; } if(Result > Max) { Result = Max; } return (Result); } /* * Vector initialization */ COVERAGE(HMM_Vec2, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(Vec2)(float X, float Y) { ASSERT_COVERED(HMM_Vec2); hmm_vec2 Result; Result.X = X; Result.Y = Y; return (Result); } COVERAGE(HMM_Vec2i, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(Vec2i)(int X, int Y) { ASSERT_COVERED(HMM_Vec2i); hmm_vec2 Result; Result.X = (float)X; Result.Y = (float)Y; return (Result); } COVERAGE(HMM_Vec3, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(Vec3)(float X, float Y, float Z) { ASSERT_COVERED(HMM_Vec3); hmm_vec3 Result; Result.X = X; Result.Y = Y; Result.Z = Z; return (Result); } COVERAGE(HMM_Vec3i, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(Vec3i)(int X, int Y, int Z) { ASSERT_COVERED(HMM_Vec3i); hmm_vec3 Result; Result.X = (float)X; Result.Y = (float)Y; Result.Z = (float)Z; return (Result); } COVERAGE(HMM_Vec4, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(Vec4)(float X, float Y, float Z, float W) { ASSERT_COVERED(HMM_Vec4); hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_setr_ps(X, Y, Z, W); #else Result.X = X; Result.Y = Y; Result.Z = Z; Result.W = W; #endif return (Result); } COVERAGE(HMM_Vec4i, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(Vec4i)(int X, int Y, int Z, int W) { ASSERT_COVERED(HMM_Vec4i); hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_setr_ps((float)X, (float)Y, (float)Z, (float)W); #else Result.X = (float)X; Result.Y = (float)Y; Result.Z = (float)Z; Result.W = (float)W; #endif return (Result); } COVERAGE(HMM_Vec4v, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(Vec4v)(hmm_vec3 Vector, float W) { ASSERT_COVERED(HMM_Vec4v); hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_setr_ps(Vector.X, Vector.Y, Vector.Z, W); #else Result.XYZ = Vector; Result.W = W; #endif return (Result); } /* * Binary vector operations */ COVERAGE(HMM_AddVec2, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(AddVec2)(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_AddVec2); hmm_vec2 Result; Result.X = Left.X + Right.X; Result.Y = Left.Y + Right.Y; return (Result); } COVERAGE(HMM_AddVec3, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(AddVec3)(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_AddVec3); hmm_vec3 Result; Result.X = Left.X + Right.X; Result.Y = Left.Y + Right.Y; Result.Z = Left.Z + Right.Z; return (Result); } COVERAGE(HMM_AddVec4, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(AddVec4)(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_AddVec4); hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_add_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); #else Result.X = Left.X + Right.X; Result.Y = Left.Y + Right.Y; Result.Z = Left.Z + Right.Z; Result.W = Left.W + Right.W; #endif return (Result); } COVERAGE(HMM_SubtractVec2, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(SubtractVec2)(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_SubtractVec2); hmm_vec2 Result; Result.X = Left.X - Right.X; Result.Y = Left.Y - Right.Y; return (Result); } COVERAGE(HMM_SubtractVec3, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(SubtractVec3)(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_SubtractVec3); hmm_vec3 Result; Result.X = Left.X - Right.X; Result.Y = Left.Y - Right.Y; Result.Z = Left.Z - Right.Z; return (Result); } COVERAGE(HMM_SubtractVec4, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(SubtractVec4)(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_SubtractVec4); hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_sub_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); #else Result.X = Left.X - Right.X; Result.Y = Left.Y - Right.Y; Result.Z = Left.Z - Right.Z; Result.W = Left.W - Right.W; #endif return (Result); } COVERAGE(HMM_MultiplyVec2, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(MultiplyVec2)(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_MultiplyVec2); hmm_vec2 Result; Result.X = Left.X * Right.X; Result.Y = Left.Y * Right.Y; return (Result); } COVERAGE(HMM_MultiplyVec2f, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(MultiplyVec2f)(hmm_vec2 Left, float Right) { ASSERT_COVERED(HMM_MultiplyVec2f); hmm_vec2 Result; Result.X = Left.X * Right; Result.Y = Left.Y * Right; return (Result); } COVERAGE(HMM_MultiplyVec3, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(MultiplyVec3)(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_MultiplyVec3); hmm_vec3 Result; Result.X = Left.X * Right.X; Result.Y = Left.Y * Right.Y; Result.Z = Left.Z * Right.Z; return (Result); } COVERAGE(HMM_MultiplyVec3f, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(MultiplyVec3f)(hmm_vec3 Left, float Right) { ASSERT_COVERED(HMM_MultiplyVec3f); hmm_vec3 Result; Result.X = Left.X * Right; Result.Y = Left.Y * Right; Result.Z = Left.Z * Right; return (Result); } COVERAGE(HMM_MultiplyVec4, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(MultiplyVec4)(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_MultiplyVec4); hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); #else Result.X = Left.X * Right.X; Result.Y = Left.Y * Right.Y; Result.Z = Left.Z * Right.Z; Result.W = Left.W * Right.W; #endif return (Result); } COVERAGE(HMM_MultiplyVec4f, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(MultiplyVec4f)(hmm_vec4 Left, float Right) { ASSERT_COVERED(HMM_MultiplyVec4f); hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE __m128 Scalar = _mm_set1_ps(Right); Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Scalar); #else Result.X = Left.X * Right; Result.Y = Left.Y * Right; Result.Z = Left.Z * Right; Result.W = Left.W * Right; #endif return (Result); } COVERAGE(HMM_DivideVec2, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(DivideVec2)(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_DivideVec2); hmm_vec2 Result; Result.X = Left.X / Right.X; Result.Y = Left.Y / Right.Y; return (Result); } COVERAGE(HMM_DivideVec2f, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(DivideVec2f)(hmm_vec2 Left, float Right) { ASSERT_COVERED(HMM_DivideVec2f); hmm_vec2 Result; Result.X = Left.X / Right; Result.Y = Left.Y / Right; return (Result); } COVERAGE(HMM_DivideVec3, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(DivideVec3)(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_DivideVec3); hmm_vec3 Result; Result.X = Left.X / Right.X; Result.Y = Left.Y / Right.Y; Result.Z = Left.Z / Right.Z; return (Result); } COVERAGE(HMM_DivideVec3f, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(DivideVec3f)(hmm_vec3 Left, float Right) { ASSERT_COVERED(HMM_DivideVec3f); hmm_vec3 Result; Result.X = Left.X / Right; Result.Y = Left.Y / Right; Result.Z = Left.Z / Right; return (Result); } COVERAGE(HMM_DivideVec4, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(DivideVec4)(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_DivideVec4); hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); #else Result.X = Left.X / Right.X; Result.Y = Left.Y / Right.Y; Result.Z = Left.Z / Right.Z; Result.W = Left.W / Right.W; #endif return (Result); } COVERAGE(HMM_DivideVec4f, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(DivideVec4f)(hmm_vec4 Left, float Right) { ASSERT_COVERED(HMM_DivideVec4f); hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE __m128 Scalar = _mm_set1_ps(Right); Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Scalar); #else Result.X = Left.X / Right; Result.Y = Left.Y / Right; Result.Z = Left.Z / Right; Result.W = Left.W / Right; #endif return (Result); } COVERAGE(HMM_EqualsVec2, 1) HMM_INLINE hmm_bool HMM_PREFIX(EqualsVec2)(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_EqualsVec2); hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y); return (Result); } COVERAGE(HMM_EqualsVec3, 1) HMM_INLINE hmm_bool HMM_PREFIX(EqualsVec3)(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_EqualsVec3); hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z); return (Result); } COVERAGE(HMM_EqualsVec4, 1) HMM_INLINE hmm_bool HMM_PREFIX(EqualsVec4)(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_EqualsVec4); hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z && Left.W == Right.W); return (Result); } COVERAGE(HMM_DotVec2, 1) HMM_INLINE float HMM_PREFIX(DotVec2)(hmm_vec2 VecOne, hmm_vec2 VecTwo) { ASSERT_COVERED(HMM_DotVec2); float Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y); return (Result); } COVERAGE(HMM_DotVec3, 1) HMM_INLINE float HMM_PREFIX(DotVec3)(hmm_vec3 VecOne, hmm_vec3 VecTwo) { ASSERT_COVERED(HMM_DotVec3); float Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y) + (VecOne.Z * VecTwo.Z); return (Result); } COVERAGE(HMM_DotVec4, 1) HMM_INLINE float HMM_PREFIX(DotVec4)(hmm_vec4 VecOne, hmm_vec4 VecTwo) { ASSERT_COVERED(HMM_DotVec4); float Result; // NOTE(zak): IN the future if we wanna check what version SSE is support // we can use _mm_dp_ps (4.3) but for now we will use the old way. // Or a r = _mm_mul_ps(v1, v2), r = _mm_hadd_ps(r, r), r = _mm_hadd_ps(r, r) for SSE3 #ifdef HANDMADE_MATH__USE_SSE __m128 SSEResultOne = _mm_mul_ps(VecOne.InternalElementsSSE, VecTwo.InternalElementsSSE); __m128 SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(2, 3, 0, 1)); SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(0, 1, 2, 3)); SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); _mm_store_ss(&Result, SSEResultOne); #else Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y) + (VecOne.Z * VecTwo.Z) + (VecOne.W * VecTwo.W); #endif return (Result); } COVERAGE(HMM_Cross, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(Cross)(hmm_vec3 VecOne, hmm_vec3 VecTwo) { ASSERT_COVERED(HMM_Cross); hmm_vec3 Result; Result.X = (VecOne.Y * VecTwo.Z) - (VecOne.Z * VecTwo.Y); Result.Y = (VecOne.Z * VecTwo.X) - (VecOne.X * VecTwo.Z); Result.Z = (VecOne.X * VecTwo.Y) - (VecOne.Y * VecTwo.X); return (Result); } /* * Unary vector operations */ COVERAGE(HMM_LengthSquaredVec2, 1) HMM_INLINE float HMM_PREFIX(LengthSquaredVec2)(hmm_vec2 A) { ASSERT_COVERED(HMM_LengthSquaredVec2); float Result = HMM_PREFIX(DotVec2)(A, A); return (Result); } COVERAGE(HMM_LengthSquaredVec3, 1) HMM_INLINE float HMM_PREFIX(LengthSquaredVec3)(hmm_vec3 A) { ASSERT_COVERED(HMM_LengthSquaredVec3); float Result = HMM_PREFIX(DotVec3)(A, A); return (Result); } COVERAGE(HMM_LengthSquaredVec4, 1) HMM_INLINE float HMM_PREFIX(LengthSquaredVec4)(hmm_vec4 A) { ASSERT_COVERED(HMM_LengthSquaredVec4); float Result = HMM_PREFIX(DotVec4)(A, A); return (Result); } COVERAGE(HMM_LengthVec2, 1) HMM_INLINE float HMM_PREFIX(LengthVec2)(hmm_vec2 A) { ASSERT_COVERED(HMM_LengthVec2); float Result = HMM_PREFIX(SquareRootF)(HMM_PREFIX(LengthSquaredVec2)(A)); return (Result); } COVERAGE(HMM_LengthVec3, 1) HMM_INLINE float HMM_PREFIX(LengthVec3)(hmm_vec3 A) { ASSERT_COVERED(HMM_LengthVec3); float Result = HMM_PREFIX(SquareRootF)(HMM_PREFIX(LengthSquaredVec3)(A)); return (Result); } COVERAGE(HMM_LengthVec4, 1) HMM_INLINE float HMM_PREFIX(LengthVec4)(hmm_vec4 A) { ASSERT_COVERED(HMM_LengthVec4); float Result = HMM_PREFIX(SquareRootF)(HMM_PREFIX(LengthSquaredVec4)(A)); return(Result); } COVERAGE(HMM_NormalizeVec2, 2) HMM_INLINE hmm_vec2 HMM_PREFIX(NormalizeVec2)(hmm_vec2 A) { ASSERT_COVERED(HMM_NormalizeVec2); hmm_vec2 Result = {0}; float VectorLength = HMM_PREFIX(LengthVec2)(A); /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ if (VectorLength != 0.0f) { ASSERT_COVERED(HMM_NormalizeVec2); Result.X = A.X * (1.0f / VectorLength); Result.Y = A.Y * (1.0f / VectorLength); } return (Result); } COVERAGE(HMM_NormalizeVec3, 2) HMM_INLINE hmm_vec3 HMM_PREFIX(NormalizeVec3)(hmm_vec3 A) { ASSERT_COVERED(HMM_NormalizeVec3); hmm_vec3 Result = {0}; float VectorLength = HMM_PREFIX(LengthVec3)(A); /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ if (VectorLength != 0.0f) { ASSERT_COVERED(HMM_NormalizeVec3); Result.X = A.X * (1.0f / VectorLength); Result.Y = A.Y * (1.0f / VectorLength); Result.Z = A.Z * (1.0f / VectorLength); } return (Result); } COVERAGE(HMM_NormalizeVec4, 2) HMM_INLINE hmm_vec4 HMM_PREFIX(NormalizeVec4)(hmm_vec4 A) { ASSERT_COVERED(HMM_NormalizeVec4); hmm_vec4 Result = {0}; float VectorLength = HMM_PREFIX(LengthVec4)(A); /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ if (VectorLength != 0.0f) { ASSERT_COVERED(HMM_NormalizeVec4); float Multiplier = 1.0f / VectorLength; #ifdef HANDMADE_MATH__USE_SSE __m128 SSEMultiplier = _mm_set1_ps(Multiplier); Result.InternalElementsSSE = _mm_mul_ps(A.InternalElementsSSE, SSEMultiplier); #else Result.X = A.X * Multiplier; Result.Y = A.Y * Multiplier; Result.Z = A.Z * Multiplier; Result.W = A.W * Multiplier; #endif } return (Result); } COVERAGE(HMM_FastNormalizeVec2, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(FastNormalizeVec2)(hmm_vec2 A) { ASSERT_COVERED(HMM_FastNormalizeVec2); return HMM_PREFIX(MultiplyVec2f)(A, HMM_PREFIX(RSquareRootF)(HMM_PREFIX(DotVec2)(A, A))); } COVERAGE(HMM_FastNormalizeVec3, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(FastNormalizeVec3)(hmm_vec3 A) { ASSERT_COVERED(HMM_FastNormalizeVec3); return HMM_PREFIX(MultiplyVec3f)(A, HMM_PREFIX(RSquareRootF)(HMM_PREFIX(DotVec3)(A, A))); } COVERAGE(HMM_FastNormalizeVec4, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(FastNormalizeVec4)(hmm_vec4 A) { ASSERT_COVERED(HMM_FastNormalizeVec4); return HMM_PREFIX(MultiplyVec4f)(A, HMM_PREFIX(RSquareRootF)(HMM_PREFIX(DotVec4)(A, A))); } /* * SSE stuff */ #ifdef HANDMADE_MATH__USE_SSE COVERAGE(HMM_LinearCombineSSE, 1) HMM_INLINE __m128 HMM_PREFIX(LinearCombineSSE)(__m128 Left, hmm_mat4 Right) { ASSERT_COVERED(HMM_LinearCombineSSE); __m128 Result; Result = _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x00), Right.Columns[0]); Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x55), Right.Columns[1])); Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xaa), Right.Columns[2])); Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xff), Right.Columns[3])); return (Result); } #endif /* * Matrix functions */ COVERAGE(HMM_Mat4, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(Mat4)(void) { ASSERT_COVERED(HMM_Mat4); hmm_mat4 Result = {0}; return (Result); } COVERAGE(HMM_Mat4d, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(Mat4d)(float Diagonal) { ASSERT_COVERED(HMM_Mat4d); hmm_mat4 Result = HMM_PREFIX(Mat4)(); Result.Elements[0][0] = Diagonal; Result.Elements[1][1] = Diagonal; Result.Elements[2][2] = Diagonal; Result.Elements[3][3] = Diagonal; return (Result); } COVERAGE(HMM_Transpose, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix) { ASSERT_COVERED(HMM_Transpose); hmm_mat4 Result = Matrix; #ifdef HANDMADE_MATH__USE_SSE _MM_TRANSPOSE4_PS(Result.Columns[0], Result.Columns[1], Result.Columns[2], Result.Columns[3]); #else int Columns; for(Columns = 0; Columns < 4; ++Columns) { int Rows; for(Rows = 0; Rows < 4; ++Rows) { Result.Elements[Rows][Columns] = Matrix.Elements[Columns][Rows]; } } #endif return (Result); } COVERAGE(HMM_AddMat4, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right) { ASSERT_COVERED(HMM_AddMat4); hmm_mat4 Result; #ifdef HANDMADE_MATH__USE_SSE Result.Columns[0] = _mm_add_ps(Left.Columns[0], Right.Columns[0]); Result.Columns[1] = _mm_add_ps(Left.Columns[1], Right.Columns[1]); Result.Columns[2] = _mm_add_ps(Left.Columns[2], Right.Columns[2]); Result.Columns[3] = _mm_add_ps(Left.Columns[3], Right.Columns[3]); #else int Columns; for(Columns = 0; Columns < 4; ++Columns) { int Rows; for(Rows = 0; Rows < 4; ++Rows) { Result.Elements[Columns][Rows] = Left.Elements[Columns][Rows] + Right.Elements[Columns][Rows]; } } #endif return (Result); } COVERAGE(HMM_SubtractMat4, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right) { ASSERT_COVERED(HMM_SubtractMat4); hmm_mat4 Result; #ifdef HANDMADE_MATH__USE_SSE Result.Columns[0] = _mm_sub_ps(Left.Columns[0], Right.Columns[0]); Result.Columns[1] = _mm_sub_ps(Left.Columns[1], Right.Columns[1]); Result.Columns[2] = _mm_sub_ps(Left.Columns[2], Right.Columns[2]); Result.Columns[3] = _mm_sub_ps(Left.Columns[3], Right.Columns[3]); #else int Columns; for(Columns = 0; Columns < 4; ++Columns) { int Rows; for(Rows = 0; Rows < 4; ++Rows) { Result.Elements[Columns][Rows] = Left.Elements[Columns][Rows] - Right.Elements[Columns][Rows]; } } #endif return (Result); } COVERAGE(HMM_MultiplyMat4, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(MultiplyMat4)(hmm_mat4 Left, hmm_mat4 Right) { ASSERT_COVERED(HMM_MultiplyMat4); hmm_mat4 Result; #ifdef HANDMADE_MATH__USE_SSE Result.Columns[0] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[0], Left); Result.Columns[1] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[1], Left); Result.Columns[2] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[2], Left); Result.Columns[3] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[3], Left); #else int Columns; for(Columns = 0; Columns < 4; ++Columns) { int Rows; for(Rows = 0; Rows < 4; ++Rows) { float Sum = 0; int CurrentMatrice; for(CurrentMatrice = 0; CurrentMatrice < 4; ++CurrentMatrice) { Sum += Left.Elements[CurrentMatrice][Rows] * Right.Elements[Columns][CurrentMatrice]; } Result.Elements[Columns][Rows] = Sum; } } #endif return (Result); } COVERAGE(HMM_MultiplyMat4f, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar) { ASSERT_COVERED(HMM_MultiplyMat4f); hmm_mat4 Result; #ifdef HANDMADE_MATH__USE_SSE __m128 SSEScalar = _mm_set1_ps(Scalar); Result.Columns[0] = _mm_mul_ps(Matrix.Columns[0], SSEScalar); Result.Columns[1] = _mm_mul_ps(Matrix.Columns[1], SSEScalar); Result.Columns[2] = _mm_mul_ps(Matrix.Columns[2], SSEScalar); Result.Columns[3] = _mm_mul_ps(Matrix.Columns[3], SSEScalar); #else int Columns; for(Columns = 0; Columns < 4; ++Columns) { int Rows; for(Rows = 0; Rows < 4; ++Rows) { Result.Elements[Columns][Rows] = Matrix.Elements[Columns][Rows] * Scalar; } } #endif return (Result); } COVERAGE(HMM_MultiplyMat4ByVec4, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(MultiplyMat4ByVec4)(hmm_mat4 Matrix, hmm_vec4 Vector) { ASSERT_COVERED(HMM_MultiplyMat4ByVec4); hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = HMM_PREFIX(LinearCombineSSE)(Vector.InternalElementsSSE, Matrix); #else int Columns, Rows; for(Rows = 0; Rows < 4; ++Rows) { float Sum = 0; for(Columns = 0; Columns < 4; ++Columns) { Sum += Matrix.Elements[Columns][Rows] * Vector.Elements[Columns]; } Result.Elements[Rows] = Sum; } #endif return (Result); } COVERAGE(HMM_DivideMat4f, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar) { ASSERT_COVERED(HMM_DivideMat4f); hmm_mat4 Result; #ifdef HANDMADE_MATH__USE_SSE __m128 SSEScalar = _mm_set1_ps(Scalar); Result.Columns[0] = _mm_div_ps(Matrix.Columns[0], SSEScalar); Result.Columns[1] = _mm_div_ps(Matrix.Columns[1], SSEScalar); Result.Columns[2] = _mm_div_ps(Matrix.Columns[2], SSEScalar); Result.Columns[3] = _mm_div_ps(Matrix.Columns[3], SSEScalar); #else int Columns; for(Columns = 0; Columns < 4; ++Columns) { int Rows; for(Rows = 0; Rows < 4; ++Rows) { Result.Elements[Columns][Rows] = Matrix.Elements[Columns][Rows] / Scalar; } } #endif return (Result); } /* * Common graphics transformations */ COVERAGE(HMM_Orthographic, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(Orthographic)(float Left, float Right, float Bottom, float Top, float Near, float Far) { ASSERT_COVERED(HMM_Orthographic); hmm_mat4 Result = HMM_PREFIX(Mat4)(); Result.Elements[0][0] = 2.0f / (Right - Left); Result.Elements[1][1] = 2.0f / (Top - Bottom); Result.Elements[2][2] = 2.0f / (Near - Far); Result.Elements[3][3] = 1.0f; Result.Elements[3][0] = (Left + Right) / (Left - Right); Result.Elements[3][1] = (Bottom + Top) / (Bottom - Top); Result.Elements[3][2] = (Far + Near) / (Near - Far); return (Result); } COVERAGE(HMM_Perspective, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(Perspective)(float FOV, float AspectRatio, float Near, float Far) { ASSERT_COVERED(HMM_Perspective); hmm_mat4 Result = HMM_PREFIX(Mat4)(); // See https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml float Cotangent = 1.0f / HMM_PREFIX(TanF)(FOV * (HMM_PI32 / 360.0f)); Result.Elements[0][0] = Cotangent / AspectRatio; Result.Elements[1][1] = Cotangent; Result.Elements[2][3] = -1.0f; Result.Elements[2][2] = (Near + Far) / (Near - Far); Result.Elements[3][2] = (2.0f * Near * Far) / (Near - Far); Result.Elements[3][3] = 0.0f; return (Result); } COVERAGE(HMM_Translate, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(Translate)(hmm_vec3 Translation) { ASSERT_COVERED(HMM_Translate); hmm_mat4 Result = HMM_PREFIX(Mat4d)(1.0f); Result.Elements[3][0] = Translation.X; Result.Elements[3][1] = Translation.Y; Result.Elements[3][2] = Translation.Z; return (Result); } COVERAGE(HMM_Rotate, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(Rotate)(float Angle, hmm_vec3 Axis) { ASSERT_COVERED(HMM_Rotate); hmm_mat4 Result = HMM_PREFIX(Mat4d)(1.0f); Axis = HMM_PREFIX(NormalizeVec3)(Axis); float SinTheta = HMM_PREFIX(SinF)(HMM_PREFIX(ToRadians)(Angle)); float CosTheta = HMM_PREFIX(CosF)(HMM_PREFIX(ToRadians)(Angle)); float CosValue = 1.0f - CosTheta; Result.Elements[0][0] = (Axis.X * Axis.X * CosValue) + CosTheta; Result.Elements[0][1] = (Axis.X * Axis.Y * CosValue) + (Axis.Z * SinTheta); Result.Elements[0][2] = (Axis.X * Axis.Z * CosValue) - (Axis.Y * SinTheta); Result.Elements[1][0] = (Axis.Y * Axis.X * CosValue) - (Axis.Z * SinTheta); Result.Elements[1][1] = (Axis.Y * Axis.Y * CosValue) + CosTheta; Result.Elements[1][2] = (Axis.Y * Axis.Z * CosValue) + (Axis.X * SinTheta); Result.Elements[2][0] = (Axis.Z * Axis.X * CosValue) + (Axis.Y * SinTheta); Result.Elements[2][1] = (Axis.Z * Axis.Y * CosValue) - (Axis.X * SinTheta); Result.Elements[2][2] = (Axis.Z * Axis.Z * CosValue) + CosTheta; return (Result); } COVERAGE(HMM_Scale, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(Scale)(hmm_vec3 Scale) { ASSERT_COVERED(HMM_Scale); hmm_mat4 Result = HMM_PREFIX(Mat4d)(1.0f); Result.Elements[0][0] = Scale.X; Result.Elements[1][1] = Scale.Y; Result.Elements[2][2] = Scale.Z; return (Result); } COVERAGE(HMM_LookAt, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(LookAt)(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up) { ASSERT_COVERED(HMM_LookAt); hmm_mat4 Result; hmm_vec3 F = HMM_PREFIX(NormalizeVec3)(HMM_PREFIX(SubtractVec3)(Center, Eye)); hmm_vec3 S = HMM_PREFIX(NormalizeVec3)(HMM_PREFIX(Cross)(F, Up)); hmm_vec3 U = HMM_PREFIX(Cross)(S, F); Result.Elements[0][0] = S.X; Result.Elements[0][1] = U.X; Result.Elements[0][2] = -F.X; Result.Elements[0][3] = 0.0f; Result.Elements[1][0] = S.Y; Result.Elements[1][1] = U.Y; Result.Elements[1][2] = -F.Y; Result.Elements[1][3] = 0.0f; Result.Elements[2][0] = S.Z; Result.Elements[2][1] = U.Z; Result.Elements[2][2] = -F.Z; Result.Elements[2][3] = 0.0f; Result.Elements[3][0] = -HMM_PREFIX(DotVec3)(S, Eye); Result.Elements[3][1] = -HMM_PREFIX(DotVec3)(U, Eye); Result.Elements[3][2] = HMM_PREFIX(DotVec3)(F, Eye); Result.Elements[3][3] = 1.0f; return (Result); } /* * Quaternion operations */ COVERAGE(HMM_Quaternion, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(Quaternion)(float X, float Y, float Z, float W) { ASSERT_COVERED(HMM_Quaternion); hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_setr_ps(X, Y, Z, W); #else Result.X = X; Result.Y = Y; Result.Z = Z; Result.W = W; #endif return (Result); } COVERAGE(HMM_QuaternionV4, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(QuaternionV4)(hmm_vec4 Vector) { ASSERT_COVERED(HMM_QuaternionV4); hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = Vector.InternalElementsSSE; #else Result.X = Vector.X; Result.Y = Vector.Y; Result.Z = Vector.Z; Result.W = Vector.W; #endif return (Result); } COVERAGE(HMM_AddQuaternion, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(AddQuaternion)(hmm_quaternion Left, hmm_quaternion Right) { ASSERT_COVERED(HMM_AddQuaternion); hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_add_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); #else Result.X = Left.X + Right.X; Result.Y = Left.Y + Right.Y; Result.Z = Left.Z + Right.Z; Result.W = Left.W + Right.W; #endif return (Result); } COVERAGE(HMM_SubtractQuaternion, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(SubtractQuaternion)(hmm_quaternion Left, hmm_quaternion Right) { ASSERT_COVERED(HMM_SubtractQuaternion); hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_sub_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); #else Result.X = Left.X - Right.X; Result.Y = Left.Y - Right.Y; Result.Z = Left.Z - Right.Z; Result.W = Left.W - Right.W; #endif return (Result); } COVERAGE(HMM_MultiplyQuaternion, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(MultiplyQuaternion)(hmm_quaternion Left, hmm_quaternion Right) { ASSERT_COVERED(HMM_MultiplyQuaternion); hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE __m128 SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(0, 0, 0, 0)), _mm_setr_ps(0.f, -0.f, 0.f, -0.f)); __m128 SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(0, 1, 2, 3)); __m128 SSEResultThree = _mm_mul_ps(SSEResultTwo, SSEResultOne); SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(1, 1, 1, 1)) , _mm_setr_ps(0.f, 0.f, -0.f, -0.f)); SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(1, 0, 3, 2)); SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(2, 2, 2, 2)), _mm_setr_ps(-0.f, 0.f, 0.f, -0.f)); SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(2, 3, 0, 1)); SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); SSEResultOne = _mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(3, 3, 3, 3)); SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(3, 2, 1, 0)); Result.InternalElementsSSE = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); #else Result.X = (Left.X * Right.W) + (Left.Y * Right.Z) - (Left.Z * Right.Y) + (Left.W * Right.X); Result.Y = (-Left.X * Right.Z) + (Left.Y * Right.W) + (Left.Z * Right.X) + (Left.W * Right.Y); Result.Z = (Left.X * Right.Y) - (Left.Y * Right.X) + (Left.Z * Right.W) + (Left.W * Right.Z); Result.W = (-Left.X * Right.X) - (Left.Y * Right.Y) - (Left.Z * Right.Z) + (Left.W * Right.W); #endif return (Result); } COVERAGE(HMM_MultiplyQuaternionF, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(MultiplyQuaternionF)(hmm_quaternion Left, float Multiplicative) { ASSERT_COVERED(HMM_MultiplyQuaternionF); hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE __m128 Scalar = _mm_set1_ps(Multiplicative); Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Scalar); #else Result.X = Left.X * Multiplicative; Result.Y = Left.Y * Multiplicative; Result.Z = Left.Z * Multiplicative; Result.W = Left.W * Multiplicative; #endif return (Result); } COVERAGE(HMM_DivideQuaternionF, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(DivideQuaternionF)(hmm_quaternion Left, float Dividend) { ASSERT_COVERED(HMM_DivideQuaternionF); hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE __m128 Scalar = _mm_set1_ps(Dividend); Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Scalar); #else Result.X = Left.X / Dividend; Result.Y = Left.Y / Dividend; Result.Z = Left.Z / Dividend; Result.W = Left.W / Dividend; #endif return (Result); } COVERAGE(HMM_DotQuaternion, 1) HMM_INLINE float HMM_PREFIX(DotQuaternion)(hmm_quaternion Left, hmm_quaternion Right) { ASSERT_COVERED(HMM_DotQuaternion); float Result; #ifdef HANDMADE_MATH__USE_SSE __m128 SSEResultOne = _mm_mul_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); __m128 SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(2, 3, 0, 1)); SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(0, 1, 2, 3)); SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); _mm_store_ss(&Result, SSEResultOne); #else Result = (Left.X * Right.X) + (Left.Y * Right.Y) + (Left.Z * Right.Z) + (Left.W * Right.W); #endif return (Result); } COVERAGE(HMM_InverseQuaternion, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(InverseQuaternion)(hmm_quaternion Left) { ASSERT_COVERED(HMM_InverseQuaternion); hmm_quaternion Result; Result.X = -Left.X; Result.Y = -Left.Y; Result.Z = -Left.Z; Result.W = Left.W; Result = HMM_PREFIX(DivideQuaternionF)(Result, (HMM_PREFIX(DotQuaternion)(Left, Left))); return (Result); } COVERAGE(HMM_NormalizeQuaternion, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(NormalizeQuaternion)(hmm_quaternion Left) { ASSERT_COVERED(HMM_NormalizeQuaternion); hmm_quaternion Result; float Length = HMM_PREFIX(SquareRootF)(HMM_PREFIX(DotQuaternion)(Left, Left)); Result = HMM_PREFIX(DivideQuaternionF)(Left, Length); return (Result); } COVERAGE(HMM_NLerp, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(NLerp)(hmm_quaternion Left, float Time, hmm_quaternion Right) { ASSERT_COVERED(HMM_NLerp); hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE __m128 ScalarLeft = _mm_set1_ps(1.0f - Time); __m128 ScalarRight = _mm_set1_ps(Time); __m128 SSEResultOne = _mm_mul_ps(Left.InternalElementsSSE, ScalarLeft); __m128 SSEResultTwo = _mm_mul_ps(Right.InternalElementsSSE, ScalarRight); Result.InternalElementsSSE = _mm_add_ps(SSEResultOne, SSEResultTwo); #else Result.X = HMM_PREFIX(Lerp)(Left.X, Time, Right.X); Result.Y = HMM_PREFIX(Lerp)(Left.Y, Time, Right.Y); Result.Z = HMM_PREFIX(Lerp)(Left.Z, Time, Right.Z); Result.W = HMM_PREFIX(Lerp)(Left.W, Time, Right.W); #endif Result = HMM_PREFIX(NormalizeQuaternion)(Result); return (Result); } COVERAGE(HMM_Slerp, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(Slerp)(hmm_quaternion Left, float Time, hmm_quaternion Right) { ASSERT_COVERED(HMM_Slerp); hmm_quaternion Result; hmm_quaternion QuaternionLeft; hmm_quaternion QuaternionRight; float Cos_Theta = HMM_PREFIX(DotQuaternion)(Left, Right); float Angle = HMM_PREFIX(ACosF)(Cos_Theta); float S1 = HMM_PREFIX(SinF)((1.0f - Time) * Angle); float S2 = HMM_PREFIX(SinF)(Time * Angle); float Is = 1.0f / HMM_PREFIX(SinF)(Angle); QuaternionLeft = HMM_PREFIX(MultiplyQuaternionF)(Left, S1); QuaternionRight = HMM_PREFIX(MultiplyQuaternionF)(Right, S2); Result = HMM_PREFIX(AddQuaternion)(QuaternionLeft, QuaternionRight); Result = HMM_PREFIX(MultiplyQuaternionF)(Result, Is); return (Result); } COVERAGE(HMM_QuaternionToMat4, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(QuaternionToMat4)(hmm_quaternion Left) { ASSERT_COVERED(HMM_QuaternionToMat4); hmm_mat4 Result; hmm_quaternion NormalizedQuaternion = HMM_PREFIX(NormalizeQuaternion)(Left); float XX, YY, ZZ, XY, XZ, YZ, WX, WY, WZ; XX = NormalizedQuaternion.X * NormalizedQuaternion.X; YY = NormalizedQuaternion.Y * NormalizedQuaternion.Y; ZZ = NormalizedQuaternion.Z * NormalizedQuaternion.Z; XY = NormalizedQuaternion.X * NormalizedQuaternion.Y; XZ = NormalizedQuaternion.X * NormalizedQuaternion.Z; YZ = NormalizedQuaternion.Y * NormalizedQuaternion.Z; WX = NormalizedQuaternion.W * NormalizedQuaternion.X; WY = NormalizedQuaternion.W * NormalizedQuaternion.Y; WZ = NormalizedQuaternion.W * NormalizedQuaternion.Z; Result.Elements[0][0] = 1.0f - 2.0f * (YY + ZZ); Result.Elements[0][1] = 2.0f * (XY + WZ); Result.Elements[0][2] = 2.0f * (XZ - WY); Result.Elements[0][3] = 0.0f; Result.Elements[1][0] = 2.0f * (XY - WZ); Result.Elements[1][1] = 1.0f - 2.0f * (XX + ZZ); Result.Elements[1][2] = 2.0f * (YZ + WX); Result.Elements[1][3] = 0.0f; Result.Elements[2][0] = 2.0f * (XZ + WY); Result.Elements[2][1] = 2.0f * (YZ - WX); Result.Elements[2][2] = 1.0f - 2.0f * (XX + YY); Result.Elements[2][3] = 0.0f; Result.Elements[3][0] = 0.0f; Result.Elements[3][1] = 0.0f; Result.Elements[3][2] = 0.0f; Result.Elements[3][3] = 1.0f; return (Result); } // This method taken from Mike Day at Insomniac Games. // https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf // // Note that as mentioned at the top of the paper, the paper assumes the matrix // would be *post*-multiplied to a vector to rotate it, meaning the matrix is // the transpose of what we're dealing with. But, because our matrices are // stored in column-major order, the indices *appear* to match the paper. // // For example, m12 in the paper is row 1, column 2. We need to transpose it to // row 2, column 1. But, because the column comes first when referencing // elements, it looks like M.Elements[1][2]. // // Don't be confused! Or if you must be confused, at least trust this // comment. :) COVERAGE(HMM_Mat4ToQuaternion, 4) HMM_INLINE hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 M) { float T; hmm_quaternion Q; if (M.Elements[2][2] < 0.0f) { if (M.Elements[0][0] > M.Elements[1][1]) { ASSERT_COVERED(HMM_Mat4ToQuaternion); T = 1 + M.Elements[0][0] - M.Elements[1][1] - M.Elements[2][2]; Q = HMM_PREFIX(Quaternion)( T, M.Elements[0][1] + M.Elements[1][0], M.Elements[2][0] + M.Elements[0][2], M.Elements[1][2] - M.Elements[2][1] ); } else { ASSERT_COVERED(HMM_Mat4ToQuaternion); T = 1 - M.Elements[0][0] + M.Elements[1][1] - M.Elements[2][2]; Q = HMM_PREFIX(Quaternion)( M.Elements[0][1] + M.Elements[1][0], T, M.Elements[1][2] + M.Elements[2][1], M.Elements[2][0] - M.Elements[0][2] ); } } else { if (M.Elements[0][0] < -M.Elements[1][1]) { ASSERT_COVERED(HMM_Mat4ToQuaternion); T = 1 - M.Elements[0][0] - M.Elements[1][1] + M.Elements[2][2]; Q = HMM_PREFIX(Quaternion)( M.Elements[2][0] + M.Elements[0][2], M.Elements[1][2] + M.Elements[2][1], T, M.Elements[0][1] - M.Elements[1][0] ); } else { ASSERT_COVERED(HMM_Mat4ToQuaternion); T = 1 + M.Elements[0][0] + M.Elements[1][1] + M.Elements[2][2]; Q = HMM_PREFIX(Quaternion)( M.Elements[1][2] - M.Elements[2][1], M.Elements[2][0] - M.Elements[0][2], M.Elements[0][1] - M.Elements[1][0], T ); } } Q = HMM_PREFIX(MultiplyQuaternionF)(Q, 0.5f / HMM_PREFIX(SquareRootF)(T)); return Q; } COVERAGE(HMM_QuaternionFromAxisAngle, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(QuaternionFromAxisAngle)(hmm_vec3 Axis, float AngleOfRotation) { ASSERT_COVERED(HMM_QuaternionFromAxisAngle); hmm_quaternion Result; hmm_vec3 AxisNormalized = HMM_PREFIX(NormalizeVec3)(Axis); float SineOfRotation = HMM_PREFIX(SinF)(AngleOfRotation / 2.0f); Result.XYZ = HMM_PREFIX(MultiplyVec3f)(AxisNormalized, SineOfRotation); Result.W = HMM_PREFIX(CosF)(AngleOfRotation / 2.0f); return (Result); } #ifdef __cplusplus } #endif #ifdef __cplusplus COVERAGE(HMM_LengthVec2CPP, 1) HMM_INLINE float HMM_PREFIX(Length)(hmm_vec2 A) { ASSERT_COVERED(HMM_LengthVec2CPP); float Result = HMM_PREFIX(LengthVec2)(A); return (Result); } COVERAGE(HMM_LengthVec3CPP, 1) HMM_INLINE float HMM_PREFIX(Length)(hmm_vec3 A) { ASSERT_COVERED(HMM_LengthVec3CPP); float Result = HMM_PREFIX(LengthVec3)(A); return (Result); } COVERAGE(HMM_LengthVec4CPP, 1) HMM_INLINE float HMM_PREFIX(Length)(hmm_vec4 A) { ASSERT_COVERED(HMM_LengthVec4CPP); float Result = HMM_PREFIX(LengthVec4)(A); return (Result); } COVERAGE(HMM_LengthSquaredVec2CPP, 1) HMM_INLINE float HMM_PREFIX(LengthSquared)(hmm_vec2 A) { ASSERT_COVERED(HMM_LengthSquaredVec2CPP); float Result = HMM_PREFIX(LengthSquaredVec2)(A); return (Result); } COVERAGE(HMM_LengthSquaredVec3CPP, 1) HMM_INLINE float HMM_PREFIX(LengthSquared)(hmm_vec3 A) { ASSERT_COVERED(HMM_LengthSquaredVec3CPP); float Result = HMM_PREFIX(LengthSquaredVec3)(A); return (Result); } COVERAGE(HMM_LengthSquaredVec4CPP, 1) HMM_INLINE float HMM_PREFIX(LengthSquared)(hmm_vec4 A) { ASSERT_COVERED(HMM_LengthSquaredVec4CPP); float Result = HMM_PREFIX(LengthSquaredVec4)(A); return (Result); } COVERAGE(HMM_NormalizeVec2CPP, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(Normalize)(hmm_vec2 A) { ASSERT_COVERED(HMM_NormalizeVec2CPP); hmm_vec2 Result = HMM_PREFIX(NormalizeVec2)(A); return (Result); } COVERAGE(HMM_NormalizeVec3CPP, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(Normalize)(hmm_vec3 A) { ASSERT_COVERED(HMM_NormalizeVec3CPP); hmm_vec3 Result = HMM_PREFIX(NormalizeVec3)(A); return (Result); } COVERAGE(HMM_NormalizeVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(Normalize)(hmm_vec4 A) { ASSERT_COVERED(HMM_NormalizeVec4CPP); hmm_vec4 Result = HMM_PREFIX(NormalizeVec4)(A); return (Result); } COVERAGE(HMM_FastNormalizeVec2CPP, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(FastNormalize)(hmm_vec2 A) { ASSERT_COVERED(HMM_FastNormalizeVec2CPP); hmm_vec2 Result = HMM_PREFIX(FastNormalizeVec2)(A); return (Result); } COVERAGE(HMM_FastNormalizeVec3CPP, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(FastNormalize)(hmm_vec3 A) { ASSERT_COVERED(HMM_FastNormalizeVec3CPP); hmm_vec3 Result = HMM_PREFIX(FastNormalizeVec3)(A); return (Result); } COVERAGE(HMM_FastNormalizeVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(FastNormalize)(hmm_vec4 A) { ASSERT_COVERED(HMM_FastNormalizeVec4CPP); hmm_vec4 Result = HMM_PREFIX(FastNormalizeVec4)(A); return (Result); } COVERAGE(HMM_NormalizeQuaternionCPP, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(Normalize)(hmm_quaternion A) { ASSERT_COVERED(HMM_NormalizeQuaternionCPP); hmm_quaternion Result = HMM_PREFIX(NormalizeQuaternion)(A); return (Result); } COVERAGE(HMM_DotVec2CPP, 1) HMM_INLINE float HMM_PREFIX(Dot)(hmm_vec2 VecOne, hmm_vec2 VecTwo) { ASSERT_COVERED(HMM_DotVec2CPP); float Result = HMM_PREFIX(DotVec2)(VecOne, VecTwo); return (Result); } COVERAGE(HMM_DotVec3CPP, 1) HMM_INLINE float HMM_PREFIX(Dot)(hmm_vec3 VecOne, hmm_vec3 VecTwo) { ASSERT_COVERED(HMM_DotVec3CPP); float Result = HMM_PREFIX(DotVec3)(VecOne, VecTwo); return (Result); } COVERAGE(HMM_DotVec4CPP, 1) HMM_INLINE float HMM_PREFIX(Dot)(hmm_vec4 VecOne, hmm_vec4 VecTwo) { ASSERT_COVERED(HMM_DotVec4CPP); float Result = HMM_PREFIX(DotVec4)(VecOne, VecTwo); return (Result); } COVERAGE(HMM_DotQuaternionCPP, 1) HMM_INLINE float HMM_PREFIX(Dot)(hmm_quaternion QuatOne, hmm_quaternion QuatTwo) { ASSERT_COVERED(HMM_DotQuaternionCPP); float Result = HMM_PREFIX(DotQuaternion)(QuatOne, QuatTwo); return (Result); } COVERAGE(HMM_AddVec2CPP, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(Add)(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_AddVec2CPP); hmm_vec2 Result = HMM_PREFIX(AddVec2)(Left, Right); return (Result); } COVERAGE(HMM_AddVec3CPP, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(Add)(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_AddVec3CPP); hmm_vec3 Result = HMM_PREFIX(AddVec3)(Left, Right); return (Result); } COVERAGE(HMM_AddVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(Add)(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_AddVec4CPP); hmm_vec4 Result = HMM_PREFIX(AddVec4)(Left, Right); return (Result); } COVERAGE(HMM_AddMat4CPP, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(Add)(hmm_mat4 Left, hmm_mat4 Right) { ASSERT_COVERED(HMM_AddMat4CPP); hmm_mat4 Result = HMM_PREFIX(AddMat4)(Left, Right); return (Result); } COVERAGE(HMM_AddQuaternionCPP, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(Add)(hmm_quaternion Left, hmm_quaternion Right) { ASSERT_COVERED(HMM_AddQuaternionCPP); hmm_quaternion Result = HMM_PREFIX(AddQuaternion)(Left, Right); return (Result); } COVERAGE(HMM_SubtractVec2CPP, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(Subtract)(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_SubtractVec2CPP); hmm_vec2 Result = HMM_PREFIX(SubtractVec2)(Left, Right); return (Result); } COVERAGE(HMM_SubtractVec3CPP, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(Subtract)(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_SubtractVec3CPP); hmm_vec3 Result = HMM_PREFIX(SubtractVec3)(Left, Right); return (Result); } COVERAGE(HMM_SubtractVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(Subtract)(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_SubtractVec4CPP); hmm_vec4 Result = HMM_PREFIX(SubtractVec4)(Left, Right); return (Result); } COVERAGE(HMM_SubtractMat4CPP, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(Subtract)(hmm_mat4 Left, hmm_mat4 Right) { ASSERT_COVERED(HMM_SubtractMat4CPP); hmm_mat4 Result = HMM_PREFIX(SubtractMat4)(Left, Right); return (Result); } COVERAGE(HMM_SubtractQuaternionCPP, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(Subtract)(hmm_quaternion Left, hmm_quaternion Right) { ASSERT_COVERED(HMM_SubtractQuaternionCPP); hmm_quaternion Result = HMM_PREFIX(SubtractQuaternion)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyVec2CPP, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(Multiply)(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_MultiplyVec2CPP); hmm_vec2 Result = HMM_PREFIX(MultiplyVec2)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyVec2fCPP, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(Multiply)(hmm_vec2 Left, float Right) { ASSERT_COVERED(HMM_MultiplyVec2fCPP); hmm_vec2 Result = HMM_PREFIX(MultiplyVec2f)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyVec3CPP, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(Multiply)(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_MultiplyVec3CPP); hmm_vec3 Result = HMM_PREFIX(MultiplyVec3)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyVec3fCPP, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(Multiply)(hmm_vec3 Left, float Right) { ASSERT_COVERED(HMM_MultiplyVec3fCPP); hmm_vec3 Result = HMM_PREFIX(MultiplyVec3f)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(Multiply)(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_MultiplyVec4CPP); hmm_vec4 Result = HMM_PREFIX(MultiplyVec4)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyVec4fCPP, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(Multiply)(hmm_vec4 Left, float Right) { ASSERT_COVERED(HMM_MultiplyVec4fCPP); hmm_vec4 Result = HMM_PREFIX(MultiplyVec4f)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyMat4CPP, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(Multiply)(hmm_mat4 Left, hmm_mat4 Right) { ASSERT_COVERED(HMM_MultiplyMat4CPP); hmm_mat4 Result = HMM_PREFIX(MultiplyMat4)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyMat4fCPP, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(Multiply)(hmm_mat4 Left, float Right) { ASSERT_COVERED(HMM_MultiplyMat4fCPP); hmm_mat4 Result = HMM_PREFIX(MultiplyMat4f)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyMat4ByVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(Multiply)(hmm_mat4 Matrix, hmm_vec4 Vector) { ASSERT_COVERED(HMM_MultiplyMat4ByVec4CPP); hmm_vec4 Result = HMM_PREFIX(MultiplyMat4ByVec4)(Matrix, Vector); return (Result); } COVERAGE(HMM_MultiplyQuaternionCPP, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(Multiply)(hmm_quaternion Left, hmm_quaternion Right) { ASSERT_COVERED(HMM_MultiplyQuaternionCPP); hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternion)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyQuaternionFCPP, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(Multiply)(hmm_quaternion Left, float Right) { ASSERT_COVERED(HMM_MultiplyQuaternionFCPP); hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternionF)(Left, Right); return (Result); } COVERAGE(HMM_DivideVec2CPP, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(Divide)(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_DivideVec2CPP); hmm_vec2 Result = HMM_PREFIX(DivideVec2)(Left, Right); return (Result); } COVERAGE(HMM_DivideVec2fCPP, 1) HMM_INLINE hmm_vec2 HMM_PREFIX(Divide)(hmm_vec2 Left, float Right) { ASSERT_COVERED(HMM_DivideVec2fCPP); hmm_vec2 Result = HMM_PREFIX(DivideVec2f)(Left, Right); return (Result); } COVERAGE(HMM_DivideVec3CPP, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(Divide)(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_DivideVec3CPP); hmm_vec3 Result = HMM_PREFIX(DivideVec3)(Left, Right); return (Result); } COVERAGE(HMM_DivideVec3fCPP, 1) HMM_INLINE hmm_vec3 HMM_PREFIX(Divide)(hmm_vec3 Left, float Right) { ASSERT_COVERED(HMM_DivideVec3fCPP); hmm_vec3 Result = HMM_PREFIX(DivideVec3f)(Left, Right); return (Result); } COVERAGE(HMM_DivideVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(Divide)(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_DivideVec4CPP); hmm_vec4 Result = HMM_PREFIX(DivideVec4)(Left, Right); return (Result); } COVERAGE(HMM_DivideVec4fCPP, 1) HMM_INLINE hmm_vec4 HMM_PREFIX(Divide)(hmm_vec4 Left, float Right) { ASSERT_COVERED(HMM_DivideVec4fCPP); hmm_vec4 Result = HMM_PREFIX(DivideVec4f)(Left, Right); return (Result); } COVERAGE(HMM_DivideMat4fCPP, 1) HMM_INLINE hmm_mat4 HMM_PREFIX(Divide)(hmm_mat4 Left, float Right) { ASSERT_COVERED(HMM_DivideMat4fCPP); hmm_mat4 Result = HMM_PREFIX(DivideMat4f)(Left, Right); return (Result); } COVERAGE(HMM_DivideQuaternionFCPP, 1) HMM_INLINE hmm_quaternion HMM_PREFIX(Divide)(hmm_quaternion Left, float Right) { ASSERT_COVERED(HMM_DivideQuaternionFCPP); hmm_quaternion Result = HMM_PREFIX(DivideQuaternionF)(Left, Right); return (Result); } COVERAGE(HMM_EqualsVec2CPP, 1) HMM_INLINE hmm_bool HMM_PREFIX(Equals)(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_EqualsVec2CPP); hmm_bool Result = HMM_PREFIX(EqualsVec2)(Left, Right); return (Result); } COVERAGE(HMM_EqualsVec3CPP, 1) HMM_INLINE hmm_bool HMM_PREFIX(Equals)(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_EqualsVec3CPP); hmm_bool Result = HMM_PREFIX(EqualsVec3)(Left, Right); return (Result); } COVERAGE(HMM_EqualsVec4CPP, 1) HMM_INLINE hmm_bool HMM_PREFIX(Equals)(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_EqualsVec4CPP); hmm_bool Result = HMM_PREFIX(EqualsVec4)(Left, Right); return (Result); } COVERAGE(HMM_AddVec2Op, 1) HMM_INLINE hmm_vec2 operator+(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_AddVec2Op); hmm_vec2 Result = HMM_PREFIX(AddVec2)(Left, Right); return (Result); } COVERAGE(HMM_AddVec3Op, 1) HMM_INLINE hmm_vec3 operator+(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_AddVec3Op); hmm_vec3 Result = HMM_PREFIX(AddVec3)(Left, Right); return (Result); } COVERAGE(HMM_AddVec4Op, 1) HMM_INLINE hmm_vec4 operator+(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_AddVec4Op); hmm_vec4 Result = HMM_PREFIX(AddVec4)(Left, Right); return (Result); } COVERAGE(HMM_AddMat4Op, 1) HMM_INLINE hmm_mat4 operator+(hmm_mat4 Left, hmm_mat4 Right) { ASSERT_COVERED(HMM_AddMat4Op); hmm_mat4 Result = HMM_PREFIX(AddMat4)(Left, Right); return (Result); } COVERAGE(HMM_AddQuaternionOp, 1) HMM_INLINE hmm_quaternion operator+(hmm_quaternion Left, hmm_quaternion Right) { ASSERT_COVERED(HMM_AddQuaternionOp); hmm_quaternion Result = HMM_PREFIX(AddQuaternion)(Left, Right); return (Result); } COVERAGE(HMM_SubtractVec2Op, 1) HMM_INLINE hmm_vec2 operator-(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_SubtractVec2Op); hmm_vec2 Result = HMM_PREFIX(SubtractVec2)(Left, Right); return (Result); } COVERAGE(HMM_SubtractVec3Op, 1) HMM_INLINE hmm_vec3 operator-(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_SubtractVec3Op); hmm_vec3 Result = HMM_PREFIX(SubtractVec3)(Left, Right); return (Result); } COVERAGE(HMM_SubtractVec4Op, 1) HMM_INLINE hmm_vec4 operator-(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_SubtractVec4Op); hmm_vec4 Result = HMM_PREFIX(SubtractVec4)(Left, Right); return (Result); } COVERAGE(HMM_SubtractMat4Op, 1) HMM_INLINE hmm_mat4 operator-(hmm_mat4 Left, hmm_mat4 Right) { ASSERT_COVERED(HMM_SubtractMat4Op); hmm_mat4 Result = HMM_PREFIX(SubtractMat4)(Left, Right); return (Result); } COVERAGE(HMM_SubtractQuaternionOp, 1) HMM_INLINE hmm_quaternion operator-(hmm_quaternion Left, hmm_quaternion Right) { ASSERT_COVERED(HMM_SubtractQuaternionOp); hmm_quaternion Result = HMM_PREFIX(SubtractQuaternion)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyVec2Op, 1) HMM_INLINE hmm_vec2 operator*(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_MultiplyVec2Op); hmm_vec2 Result = HMM_PREFIX(MultiplyVec2)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyVec3Op, 1) HMM_INLINE hmm_vec3 operator*(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_MultiplyVec3Op); hmm_vec3 Result = HMM_PREFIX(MultiplyVec3)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyVec4Op, 1) HMM_INLINE hmm_vec4 operator*(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_MultiplyVec4Op); hmm_vec4 Result = HMM_PREFIX(MultiplyVec4)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyMat4Op, 1) HMM_INLINE hmm_mat4 operator*(hmm_mat4 Left, hmm_mat4 Right) { ASSERT_COVERED(HMM_MultiplyMat4Op); hmm_mat4 Result = HMM_PREFIX(MultiplyMat4)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyQuaternionOp, 1) HMM_INLINE hmm_quaternion operator*(hmm_quaternion Left, hmm_quaternion Right) { ASSERT_COVERED(HMM_MultiplyQuaternionOp); hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternion)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyVec2fOp, 1) HMM_INLINE hmm_vec2 operator*(hmm_vec2 Left, float Right) { ASSERT_COVERED(HMM_MultiplyVec2fOp); hmm_vec2 Result = HMM_PREFIX(MultiplyVec2f)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyVec3fOp, 1) HMM_INLINE hmm_vec3 operator*(hmm_vec3 Left, float Right) { ASSERT_COVERED(HMM_MultiplyVec3fOp); hmm_vec3 Result = HMM_PREFIX(MultiplyVec3f)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyVec4fOp, 1) HMM_INLINE hmm_vec4 operator*(hmm_vec4 Left, float Right) { ASSERT_COVERED(HMM_MultiplyVec4fOp); hmm_vec4 Result = HMM_PREFIX(MultiplyVec4f)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyMat4fOp, 1) HMM_INLINE hmm_mat4 operator*(hmm_mat4 Left, float Right) { ASSERT_COVERED(HMM_MultiplyMat4fOp); hmm_mat4 Result = HMM_PREFIX(MultiplyMat4f)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyQuaternionFOp, 1) HMM_INLINE hmm_quaternion operator*(hmm_quaternion Left, float Right) { ASSERT_COVERED(HMM_MultiplyQuaternionFOp); hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternionF)(Left, Right); return (Result); } COVERAGE(HMM_MultiplyVec2fOpLeft, 1) HMM_INLINE hmm_vec2 operator*(float Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_MultiplyVec2fOpLeft); hmm_vec2 Result = HMM_PREFIX(MultiplyVec2f)(Right, Left); return (Result); } COVERAGE(HMM_MultiplyVec3fOpLeft, 1) HMM_INLINE hmm_vec3 operator*(float Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_MultiplyVec3fOpLeft); hmm_vec3 Result = HMM_PREFIX(MultiplyVec3f)(Right, Left); return (Result); } COVERAGE(HMM_MultiplyVec4fOpLeft, 1) HMM_INLINE hmm_vec4 operator*(float Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_MultiplyVec4fOpLeft); hmm_vec4 Result = HMM_PREFIX(MultiplyVec4f)(Right, Left); return (Result); } COVERAGE(HMM_MultiplyMat4fOpLeft, 1) HMM_INLINE hmm_mat4 operator*(float Left, hmm_mat4 Right) { ASSERT_COVERED(HMM_MultiplyMat4fOpLeft); hmm_mat4 Result = HMM_PREFIX(MultiplyMat4f)(Right, Left); return (Result); } COVERAGE(HMM_MultiplyQuaternionFOpLeft, 1) HMM_INLINE hmm_quaternion operator*(float Left, hmm_quaternion Right) { ASSERT_COVERED(HMM_MultiplyQuaternionFOpLeft); hmm_quaternion Result = HMM_PREFIX(MultiplyQuaternionF)(Right, Left); return (Result); } COVERAGE(HMM_MultiplyMat4ByVec4Op, 1) HMM_INLINE hmm_vec4 operator*(hmm_mat4 Matrix, hmm_vec4 Vector) { ASSERT_COVERED(HMM_MultiplyMat4ByVec4Op); hmm_vec4 Result = HMM_PREFIX(MultiplyMat4ByVec4)(Matrix, Vector); return (Result); } COVERAGE(HMM_DivideVec2Op, 1) HMM_INLINE hmm_vec2 operator/(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_DivideVec2Op); hmm_vec2 Result = HMM_PREFIX(DivideVec2)(Left, Right); return (Result); } COVERAGE(HMM_DivideVec3Op, 1) HMM_INLINE hmm_vec3 operator/(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_DivideVec3Op); hmm_vec3 Result = HMM_PREFIX(DivideVec3)(Left, Right); return (Result); } COVERAGE(HMM_DivideVec4Op, 1) HMM_INLINE hmm_vec4 operator/(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_DivideVec4Op); hmm_vec4 Result = HMM_PREFIX(DivideVec4)(Left, Right); return (Result); } COVERAGE(HMM_DivideVec2fOp, 1) HMM_INLINE hmm_vec2 operator/(hmm_vec2 Left, float Right) { ASSERT_COVERED(HMM_DivideVec2fOp); hmm_vec2 Result = HMM_PREFIX(DivideVec2f)(Left, Right); return (Result); } COVERAGE(HMM_DivideVec3fOp, 1) HMM_INLINE hmm_vec3 operator/(hmm_vec3 Left, float Right) { ASSERT_COVERED(HMM_DivideVec3fOp); hmm_vec3 Result = HMM_PREFIX(DivideVec3f)(Left, Right); return (Result); } COVERAGE(HMM_DivideVec4fOp, 1) HMM_INLINE hmm_vec4 operator/(hmm_vec4 Left, float Right) { ASSERT_COVERED(HMM_DivideVec4fOp); hmm_vec4 Result = HMM_PREFIX(DivideVec4f)(Left, Right); return (Result); } COVERAGE(HMM_DivideMat4fOp, 1) HMM_INLINE hmm_mat4 operator/(hmm_mat4 Left, float Right) { ASSERT_COVERED(HMM_DivideMat4fOp); hmm_mat4 Result = HMM_PREFIX(DivideMat4f)(Left, Right); return (Result); } COVERAGE(HMM_DivideQuaternionFOp, 1) HMM_INLINE hmm_quaternion operator/(hmm_quaternion Left, float Right) { ASSERT_COVERED(HMM_DivideQuaternionFOp); hmm_quaternion Result = HMM_PREFIX(DivideQuaternionF)(Left, Right); return (Result); } COVERAGE(HMM_AddVec2Assign, 1) HMM_INLINE hmm_vec2 &operator+=(hmm_vec2 &Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_AddVec2Assign); return (Left = Left + Right); } COVERAGE(HMM_AddVec3Assign, 1) HMM_INLINE hmm_vec3 &operator+=(hmm_vec3 &Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_AddVec3Assign); return (Left = Left + Right); } COVERAGE(HMM_AddVec4Assign, 1) HMM_INLINE hmm_vec4 &operator+=(hmm_vec4 &Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_AddVec4Assign); return (Left = Left + Right); } COVERAGE(HMM_AddMat4Assign, 1) HMM_INLINE hmm_mat4 &operator+=(hmm_mat4 &Left, hmm_mat4 Right) { ASSERT_COVERED(HMM_AddMat4Assign); return (Left = Left + Right); } COVERAGE(HMM_AddQuaternionAssign, 1) HMM_INLINE hmm_quaternion &operator+=(hmm_quaternion &Left, hmm_quaternion Right) { ASSERT_COVERED(HMM_AddQuaternionAssign); return (Left = Left + Right); } COVERAGE(HMM_SubtractVec2Assign, 1) HMM_INLINE hmm_vec2 &operator-=(hmm_vec2 &Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_SubtractVec2Assign); return (Left = Left - Right); } COVERAGE(HMM_SubtractVec3Assign, 1) HMM_INLINE hmm_vec3 &operator-=(hmm_vec3 &Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_SubtractVec3Assign); return (Left = Left - Right); } COVERAGE(HMM_SubtractVec4Assign, 1) HMM_INLINE hmm_vec4 &operator-=(hmm_vec4 &Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_SubtractVec4Assign); return (Left = Left - Right); } COVERAGE(HMM_SubtractMat4Assign, 1) HMM_INLINE hmm_mat4 &operator-=(hmm_mat4 &Left, hmm_mat4 Right) { ASSERT_COVERED(HMM_SubtractMat4Assign); return (Left = Left - Right); } COVERAGE(HMM_SubtractQuaternionAssign, 1) HMM_INLINE hmm_quaternion &operator-=(hmm_quaternion &Left, hmm_quaternion Right) { ASSERT_COVERED(HMM_SubtractQuaternionAssign); return (Left = Left - Right); } COVERAGE(HMM_MultiplyVec2Assign, 1) HMM_INLINE hmm_vec2 &operator*=(hmm_vec2 &Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_MultiplyVec2Assign); return (Left = Left * Right); } COVERAGE(HMM_MultiplyVec3Assign, 1) HMM_INLINE hmm_vec3 &operator*=(hmm_vec3 &Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_MultiplyVec3Assign); return (Left = Left * Right); } COVERAGE(HMM_MultiplyVec4Assign, 1) HMM_INLINE hmm_vec4 &operator*=(hmm_vec4 &Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_MultiplyVec4Assign); return (Left = Left * Right); } COVERAGE(HMM_MultiplyVec2fAssign, 1) HMM_INLINE hmm_vec2 &operator*=(hmm_vec2 &Left, float Right) { ASSERT_COVERED(HMM_MultiplyVec2fAssign); return (Left = Left * Right); } COVERAGE(HMM_MultiplyVec3fAssign, 1) HMM_INLINE hmm_vec3 &operator*=(hmm_vec3 &Left, float Right) { ASSERT_COVERED(HMM_MultiplyVec3fAssign); return (Left = Left * Right); } COVERAGE(HMM_MultiplyVec4fAssign, 1) HMM_INLINE hmm_vec4 &operator*=(hmm_vec4 &Left, float Right) { ASSERT_COVERED(HMM_MultiplyVec4fAssign); return (Left = Left * Right); } COVERAGE(HMM_MultiplyMat4fAssign, 1) HMM_INLINE hmm_mat4 &operator*=(hmm_mat4 &Left, float Right) { ASSERT_COVERED(HMM_MultiplyMat4fAssign); return (Left = Left * Right); } COVERAGE(HMM_MultiplyQuaternionFAssign, 1) HMM_INLINE hmm_quaternion &operator*=(hmm_quaternion &Left, float Right) { ASSERT_COVERED(HMM_MultiplyQuaternionFAssign); return (Left = Left * Right); } COVERAGE(HMM_DivideVec2Assign, 1) HMM_INLINE hmm_vec2 &operator/=(hmm_vec2 &Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_DivideVec2Assign); return (Left = Left / Right); } COVERAGE(HMM_DivideVec3Assign, 1) HMM_INLINE hmm_vec3 &operator/=(hmm_vec3 &Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_DivideVec3Assign); return (Left = Left / Right); } COVERAGE(HMM_DivideVec4Assign, 1) HMM_INLINE hmm_vec4 &operator/=(hmm_vec4 &Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_DivideVec4Assign); return (Left = Left / Right); } COVERAGE(HMM_DivideVec2fAssign, 1) HMM_INLINE hmm_vec2 &operator/=(hmm_vec2 &Left, float Right) { ASSERT_COVERED(HMM_DivideVec2fAssign); return (Left = Left / Right); } COVERAGE(HMM_DivideVec3fAssign, 1) HMM_INLINE hmm_vec3 &operator/=(hmm_vec3 &Left, float Right) { ASSERT_COVERED(HMM_DivideVec3fAssign); return (Left = Left / Right); } COVERAGE(HMM_DivideVec4fAssign, 1) HMM_INLINE hmm_vec4 &operator/=(hmm_vec4 &Left, float Right) { ASSERT_COVERED(HMM_DivideVec4fAssign); return (Left = Left / Right); } COVERAGE(HMM_DivideMat4fAssign, 1) HMM_INLINE hmm_mat4 &operator/=(hmm_mat4 &Left, float Right) { ASSERT_COVERED(HMM_DivideMat4fAssign); return (Left = Left / Right); } COVERAGE(HMM_DivideQuaternionFAssign, 1) HMM_INLINE hmm_quaternion &operator/=(hmm_quaternion &Left, float Right) { ASSERT_COVERED(HMM_DivideQuaternionFAssign); return (Left = Left / Right); } COVERAGE(HMM_EqualsVec2Op, 1) HMM_INLINE hmm_bool operator==(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_EqualsVec2Op); return HMM_PREFIX(EqualsVec2)(Left, Right); } COVERAGE(HMM_EqualsVec3Op, 1) HMM_INLINE hmm_bool operator==(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_EqualsVec3Op); return HMM_PREFIX(EqualsVec3)(Left, Right); } COVERAGE(HMM_EqualsVec4Op, 1) HMM_INLINE hmm_bool operator==(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_EqualsVec4Op); return HMM_PREFIX(EqualsVec4)(Left, Right); } COVERAGE(HMM_EqualsVec2OpNot, 1) HMM_INLINE hmm_bool operator!=(hmm_vec2 Left, hmm_vec2 Right) { ASSERT_COVERED(HMM_EqualsVec2OpNot); return !HMM_PREFIX(EqualsVec2)(Left, Right); } COVERAGE(HMM_EqualsVec3OpNot, 1) HMM_INLINE hmm_bool operator!=(hmm_vec3 Left, hmm_vec3 Right) { ASSERT_COVERED(HMM_EqualsVec3OpNot); return !HMM_PREFIX(EqualsVec3)(Left, Right); } COVERAGE(HMM_EqualsVec4OpNot, 1) HMM_INLINE hmm_bool operator!=(hmm_vec4 Left, hmm_vec4 Right) { ASSERT_COVERED(HMM_EqualsVec4OpNot); return !HMM_PREFIX(EqualsVec4)(Left, Right); } COVERAGE(HMM_UnaryMinusVec2, 1) HMM_INLINE hmm_vec2 operator-(hmm_vec2 In) { ASSERT_COVERED(HMM_UnaryMinusVec2); hmm_vec2 Result; Result.X = -In.X; Result.Y = -In.Y; return(Result); } COVERAGE(HMM_UnaryMinusVec3, 1) HMM_INLINE hmm_vec3 operator-(hmm_vec3 In) { ASSERT_COVERED(HMM_UnaryMinusVec3); hmm_vec3 Result; Result.X = -In.X; Result.Y = -In.Y; Result.Z = -In.Z; return(Result); } COVERAGE(HMM_UnaryMinusVec4, 1) HMM_INLINE hmm_vec4 operator-(hmm_vec4 In) { ASSERT_COVERED(HMM_UnaryMinusVec4); hmm_vec4 Result; #if HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_xor_ps(In.InternalElementsSSE, _mm_set1_ps(-0.0f)); #else Result.X = -In.X; Result.Y = -In.Y; Result.Z = -In.Z; Result.W = -In.W; #endif return(Result); } #endif /* __cplusplus */ #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic pop #endif #endif /* HANDMADE_MATH_H */