3241 lines
		
	
	
		
			76 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			3241 lines
		
	
	
		
			76 KiB
		
	
	
	
		
			C
		
	
	
| /*
 | |
|   HandmadeMath.h v1.11.0
 | |
| 
 | |
|   This is a single header file with a bunch of useful functions for game and
 | |
|   graphics math operations.
 | |
| 
 | |
|   =============================================================================
 | |
| 
 | |
|   You MUST
 | |
| 
 | |
|      #define HANDMADE_MATH_IMPLEMENTATION
 | |
| 
 | |
|   in EXACTLY one C or C++ file that includes this header, BEFORE the
 | |
|   include, like this:
 | |
| 
 | |
|      #define HANDMADE_MATH_IMPLEMENTATION
 | |
|      #include "HandmadeMath.h"
 | |
| 
 | |
|   All other files should just #include "HandmadeMath.h" without the #define.
 | |
| 
 | |
|   =============================================================================
 | |
| 
 | |
|   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_IMPLEMENTATION
 | |
|      #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
 | |
|      #define HANDMADE_MATH_IMPLEMENTATION
 | |
|      #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@gmail.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 <xmmintrin.h>
 | |
| #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)
 | |
| #pragma GCC diagnostic ignored "-Wmissing-braces"
 | |
| #endif
 | |
| #ifdef __clang__
 | |
| #pragma GCC diagnostic ignored "-Wgnu-anonymous-struct"
 | |
| #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
 | |
| #define HMM_EXTERN extern
 | |
| 
 | |
| #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 <math.h>
 | |
| #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)
 | |
|     {
 | |
|         float* col = Elements[Index];
 | |
| 
 | |
|         hmm_vec4 result;
 | |
|         result.Elements[0] = col[0];
 | |
|         result.Elements[1] = col[1];
 | |
|         result.Elements[2] = col[2];
 | |
|         result.Elements[3] = col[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);
 | |
| }
 | |
| 
 | |
| HMM_EXTERN float HMM_PREFIX(Power)(float Base, int Exponent);
 | |
| 
 | |
| 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);
 | |
| }
 | |
| 
 | |
| #ifdef HANDMADE_MATH__USE_SSE
 | |
| COVERAGE(HMM_Transpose, 1)
 | |
| HMM_INLINE hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix)
 | |
| {
 | |
|     ASSERT_COVERED(HMM_Transpose);
 | |
| 
 | |
|     hmm_mat4 Result = Matrix;
 | |
| 
 | |
|     _MM_TRANSPOSE4_PS(Result.Columns[0], Result.Columns[1], Result.Columns[2], Result.Columns[3]);
 | |
| 
 | |
|     return (Result);
 | |
| }
 | |
| #else
 | |
| HMM_EXTERN hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix);
 | |
| #endif
 | |
| 
 | |
| #ifdef HANDMADE_MATH__USE_SSE
 | |
| COVERAGE(HMM_AddMat4, 1)
 | |
| HMM_INLINE hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right)
 | |
| {
 | |
|     ASSERT_COVERED(HMM_AddMat4);
 | |
| 
 | |
|     hmm_mat4 Result;
 | |
| 
 | |
|     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]);
 | |
| 
 | |
|     return (Result);
 | |
| }
 | |
| #else
 | |
| HMM_EXTERN hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right);
 | |
| #endif
 | |
| 
 | |
| #ifdef HANDMADE_MATH__USE_SSE
 | |
| COVERAGE(HMM_SubtractMat4, 1)
 | |
| HMM_INLINE hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right)
 | |
| {
 | |
|     ASSERT_COVERED(HMM_SubtractMat4);
 | |
| 
 | |
|     hmm_mat4 Result;
 | |
| 
 | |
|     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]);
 | |
| 
 | |
|     return (Result);
 | |
| }
 | |
| #else
 | |
| HMM_EXTERN hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right);
 | |
| #endif
 | |
| 
 | |
| HMM_EXTERN hmm_mat4 HMM_PREFIX(MultiplyMat4)(hmm_mat4 Left, hmm_mat4 Right);
 | |
| 
 | |
| #ifdef HANDMADE_MATH__USE_SSE
 | |
| COVERAGE(HMM_MultiplyMat4f, 1)
 | |
| HMM_INLINE hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar)
 | |
| {
 | |
|     ASSERT_COVERED(HMM_MultiplyMat4f);
 | |
| 
 | |
|     hmm_mat4 Result;
 | |
| 
 | |
|     __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);
 | |
| 
 | |
|     return (Result);
 | |
| }
 | |
| #else
 | |
| HMM_EXTERN hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar);
 | |
| #endif
 | |
| 
 | |
| HMM_EXTERN hmm_vec4 HMM_PREFIX(MultiplyMat4ByVec4)(hmm_mat4 Matrix, hmm_vec4 Vector);
 | |
| 
 | |
| #ifdef HANDMADE_MATH__USE_SSE
 | |
| COVERAGE(HMM_DivideMat4f, 1)
 | |
| HMM_INLINE hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar)
 | |
| {
 | |
|     ASSERT_COVERED(HMM_DivideMat4f);
 | |
| 
 | |
|     hmm_mat4 Result;
 | |
| 
 | |
|     __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);
 | |
| 
 | |
|     return (Result);
 | |
| }
 | |
| #else
 | |
| HMM_EXTERN hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar);
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * 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);
 | |
| }
 | |
| 
 | |
| HMM_EXTERN hmm_mat4 HMM_PREFIX(Rotate)(float Angle, hmm_vec3 Axis);
 | |
| 
 | |
| 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);
 | |
| }
 | |
| 
 | |
| HMM_EXTERN hmm_mat4 HMM_PREFIX(LookAt)(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up);
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * 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);
 | |
| }
 | |
| 
 | |
| HMM_EXTERN hmm_quaternion HMM_PREFIX(InverseQuaternion)(hmm_quaternion Left);
 | |
| 
 | |
| 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_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);
 | |
| }
 | |
| 
 | |
| HMM_EXTERN hmm_quaternion HMM_PREFIX(Slerp)(hmm_quaternion Left, float Time, hmm_quaternion Right);
 | |
| HMM_EXTERN hmm_mat4 HMM_PREFIX(QuaternionToMat4)(hmm_quaternion Left);
 | |
| HMM_EXTERN hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 Left);
 | |
| HMM_EXTERN hmm_quaternion HMM_PREFIX(QuaternionFromAxisAngle)(hmm_vec3 Axis, float AngleOfRotation);
 | |
| 
 | |
| #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);
 | |
| }
 | |
| 
 | |
| #endif /* __cplusplus */
 | |
| 
 | |
| #if defined(__GNUC__) || defined(__clang__)
 | |
| #pragma GCC diagnostic pop
 | |
| #endif
 | |
| 
 | |
| #endif /* HANDMADE_MATH_H */
 | |
| 
 | |
| #ifdef HANDMADE_MATH_IMPLEMENTATION
 | |
| 
 | |
| COVERAGE(HMM_Power, 2)
 | |
| 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);
 | |
| }
 | |
| 
 | |
| #ifndef HANDMADE_MATH__USE_SSE
 | |
| COVERAGE(HMM_Transpose, 1)
 | |
| hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix)
 | |
| {
 | |
|     ASSERT_COVERED(HMM_Transpose);
 | |
| 
 | |
|     hmm_mat4 Result;
 | |
| 
 | |
|     int Columns;
 | |
|     for(Columns = 0; Columns < 4; ++Columns)
 | |
|     {
 | |
|         int Rows;
 | |
|         for(Rows = 0; Rows < 4; ++Rows)
 | |
|         {
 | |
|             Result.Elements[Rows][Columns] = Matrix.Elements[Columns][Rows];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return (Result);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifndef HANDMADE_MATH__USE_SSE
 | |
| COVERAGE(HMM_AddMat4, 1)
 | |
| hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right)
 | |
| {
 | |
|     ASSERT_COVERED(HMM_AddMat4);
 | |
| 
 | |
|     hmm_mat4 Result;
 | |
| 
 | |
|     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];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return (Result);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifndef HANDMADE_MATH__USE_SSE
 | |
| COVERAGE(HMM_SubtractMat4, 1)
 | |
| hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right)
 | |
| {
 | |
|     ASSERT_COVERED(HMM_SubtractMat4);
 | |
| 
 | |
|     hmm_mat4 Result;
 | |
| 
 | |
|     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];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return (Result);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| COVERAGE(HMM_MultiplyMat4, 1)
 | |
| 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);
 | |
| }
 | |
| 
 | |
| #ifndef HANDMADE_MATH__USE_SSE
 | |
| COVERAGE(HMM_MultiplyMat4f, 1)
 | |
| hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar)
 | |
| {
 | |
|     ASSERT_COVERED(HMM_MultiplyMat4f);
 | |
| 
 | |
|     hmm_mat4 Result;
 | |
| 
 | |
|     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;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return (Result);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| COVERAGE(HMM_MultiplyMat4ByVec4, 1)
 | |
| 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);
 | |
| }
 | |
| 
 | |
| #ifndef HANDMADE_MATH__USE_SSE
 | |
| COVERAGE(HMM_DivideMat4f, 1);
 | |
| hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar)
 | |
| {
 | |
|     ASSERT_COVERED(HMM_DivideMat4f);
 | |
| 
 | |
|     hmm_mat4 Result;
 | |
| 
 | |
|     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;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return (Result);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| COVERAGE(HMM_Rotate, 1)
 | |
| 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_LookAt, 1)
 | |
| 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);
 | |
| }
 | |
| 
 | |
| COVERAGE(HMM_InverseQuaternion, 1)
 | |
| hmm_quaternion HMM_PREFIX(InverseQuaternion)(hmm_quaternion Left)
 | |
| {
 | |
|     ASSERT_COVERED(HMM_InverseQuaternion);
 | |
| 
 | |
|     hmm_quaternion Conjugate;
 | |
|     hmm_quaternion Result;
 | |
|     float Norm = 0;
 | |
|     float NormSquared = 0;
 | |
| 
 | |
|     Conjugate.X = -Left.X;
 | |
|     Conjugate.Y = -Left.Y;
 | |
|     Conjugate.Z = -Left.Z;
 | |
|     Conjugate.W = Left.W;
 | |
| 
 | |
|     Norm = HMM_PREFIX(SquareRootF)(HMM_PREFIX(DotQuaternion)(Left, Left));
 | |
|     NormSquared = Norm * Norm;
 | |
| 
 | |
|     Result = HMM_PREFIX(DivideQuaternionF)(Conjugate, NormSquared);
 | |
| 
 | |
|     return (Result);
 | |
| }
 | |
| 
 | |
| COVERAGE(HMM_Slerp, 1)
 | |
| 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_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_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_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);
 | |
| }
 | |
| 
 | |
| #endif /* HANDMADE_MATH_IMPLEMENTATION */
 |