Compare commits

...

9 Commits

Author SHA1 Message Date
Ben Visness
9a913ac95b Expose NaNs in our tests
oops
2021-05-21 12:04:17 -05:00
Ben Visness
43afc87fa7 Remove non-functioning issue link 2021-03-24 10:04:17 -05:00
Ben Visness
5bbac2167e Update version and changelog 2021-03-24 10:02:08 -05:00
Wayde Reitsma
655c662528 Add brackets around HMM_MIN, HMM_MAX, and HMM_MOD (#133)
* Add brackets around HMM_MIN and HMM_MAX

* Add brackets around HMM_MOD
2021-03-24 09:54:13 -05:00
Zak Strange
1f0c6ba493 Update Docs. 2021-03-09 16:37:00 -08:00
Zak Strange
1d82b4f0bc Unary minus vectors (#130)
* Unary Minus operator for vec2, vec3, and vec4

* Update README.md

Co-authored-by: zak <zak@DESKTOP-V1AQ0IT>
2021-03-06 18:39:17 -06:00
Zak Strange
2fa0b36715 Add HMM_STATIC option to statically link instead of extern (#127)
Co-authored-by: zak <zak@DESKTOP-V1AQ0IT>
2021-02-17 19:36:05 -08:00
Ben Visness
ad169e649c Make HMM_Clamp branchless in optimized builds (#122) 2020-12-22 11:19:58 -06:00
Zak Strange
1900cc9275 Updated email in HandmadeMath.h 2020-07-09 18:22:22 -07:00
5 changed files with 134 additions and 31 deletions

View File

@@ -1,5 +1,5 @@
/*
HandmadeMath.h v1.11.0
HandmadeMath.h v1.12.1
This is a single header file with a bunch of useful functions for game and
graphics math operations.
@@ -84,7 +84,7 @@
CREDITS
Written by Zakary Strange (zak@strangedev.net && @strangezak)
Written by Zakary Strange (strangezak@protonmail.com && @strangezak)
Functionality:
Matt Mascarenhas (@miblo_)
@@ -165,7 +165,12 @@ extern "C"
#endif
#define HMM_INLINE static inline
#define HMM_EXTERN extern
#ifdef HMM_STATIC
#define HMM_DEF static
#else
#define HMM_DEF extern
#endif
#if !defined(HMM_SINF) || !defined(HMM_COSF) || !defined(HMM_TANF) || \
!defined(HMM_SQRTF) || !defined(HMM_EXPF) || !defined(HMM_LOGF) || \
@@ -212,10 +217,10 @@ extern "C"
#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_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_MOD(a, m) (((a) % (m)) >= 0 ? ((a) % (m)) : (((a) % (m)) + (m)))
#define HMM_SQUARE(x) ((x) * (x))
#ifndef HMM_PREFIX
@@ -547,7 +552,7 @@ HMM_INLINE float HMM_PREFIX(RSquareRootF)(float Float)
return(Result);
}
HMM_EXTERN float HMM_PREFIX(Power)(float Base, int Exponent);
HMM_DEF float HMM_PREFIX(Power)(float Base, int Exponent);
COVERAGE(HMM_PowerF, 1)
HMM_INLINE float HMM_PREFIX(PowerF)(float Base, float Exponent)
@@ -595,7 +600,8 @@ HMM_INLINE float HMM_PREFIX(Clamp)(float Min, float Value, float Max)
{
Result = Min;
}
else if(Result > Max)
if(Result > Max)
{
Result = Max;
}
@@ -1314,7 +1320,7 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix)
return (Result);
}
#else
HMM_EXTERN hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix);
HMM_DEF hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix);
#endif
#ifdef HANDMADE_MATH__USE_SSE
@@ -1333,7 +1339,7 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right)
return (Result);
}
#else
HMM_EXTERN hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right);
HMM_DEF hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right);
#endif
#ifdef HANDMADE_MATH__USE_SSE
@@ -1352,10 +1358,10 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right)
return (Result);
}
#else
HMM_EXTERN hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right);
HMM_DEF 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);
HMM_DEF hmm_mat4 HMM_PREFIX(MultiplyMat4)(hmm_mat4 Left, hmm_mat4 Right);
#ifdef HANDMADE_MATH__USE_SSE
COVERAGE(HMM_MultiplyMat4f, 1)
@@ -1374,10 +1380,10 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar)
return (Result);
}
#else
HMM_EXTERN hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar);
HMM_DEF hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar);
#endif
HMM_EXTERN hmm_vec4 HMM_PREFIX(MultiplyMat4ByVec4)(hmm_mat4 Matrix, hmm_vec4 Vector);
HMM_DEF hmm_vec4 HMM_PREFIX(MultiplyMat4ByVec4)(hmm_mat4 Matrix, hmm_vec4 Vector);
#ifdef HANDMADE_MATH__USE_SSE
COVERAGE(HMM_DivideMat4f, 1)
@@ -1396,7 +1402,7 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar)
return (Result);
}
#else
HMM_EXTERN hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar);
HMM_DEF hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar);
#endif
@@ -1458,7 +1464,7 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(Translate)(hmm_vec3 Translation)
return (Result);
}
HMM_EXTERN hmm_mat4 HMM_PREFIX(Rotate)(float Angle, hmm_vec3 Axis);
HMM_DEF hmm_mat4 HMM_PREFIX(Rotate)(float Angle, hmm_vec3 Axis);
COVERAGE(HMM_Scale, 1)
HMM_INLINE hmm_mat4 HMM_PREFIX(Scale)(hmm_vec3 Scale)
@@ -1474,7 +1480,7 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(Scale)(hmm_vec3 Scale)
return (Result);
}
HMM_EXTERN hmm_mat4 HMM_PREFIX(LookAt)(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up);
HMM_DEF hmm_mat4 HMM_PREFIX(LookAt)(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up);
/*
@@ -1632,7 +1638,7 @@ HMM_INLINE hmm_quaternion HMM_PREFIX(DivideQuaternionF)(hmm_quaternion Left, flo
return (Result);
}
HMM_EXTERN hmm_quaternion HMM_PREFIX(InverseQuaternion)(hmm_quaternion Left);
HMM_DEF hmm_quaternion HMM_PREFIX(InverseQuaternion)(hmm_quaternion Left);
COVERAGE(HMM_DotQuaternion, 1)
HMM_INLINE float HMM_PREFIX(DotQuaternion)(hmm_quaternion Left, hmm_quaternion Right)
@@ -1692,10 +1698,10 @@ HMM_INLINE hmm_quaternion HMM_PREFIX(NLerp)(hmm_quaternion Left, float Time, hmm
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);
HMM_DEF hmm_quaternion HMM_PREFIX(Slerp)(hmm_quaternion Left, float Time, hmm_quaternion Right);
HMM_DEF hmm_mat4 HMM_PREFIX(QuaternionToMat4)(hmm_quaternion Left);
HMM_DEF hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 Left);
HMM_DEF hmm_quaternion HMM_PREFIX(QuaternionFromAxisAngle)(hmm_vec3 Axis, float AngleOfRotation);
#ifdef __cplusplus
}
@@ -2789,6 +2795,46 @@ HMM_INLINE hmm_bool operator!=(hmm_vec4 Left, hmm_vec4 Right)
return !HMM_PREFIX(EqualsVec4)(Left, Right);
}
COVERAGE(HMM_UnaryMinusVec2, 1)
HMM_INLINE hmm_vec2 operator-(hmm_vec2 In)
{
ASSERT_COVERED(HMM_UnaryMinusVec2);
hmm_vec2 Result;
Result.X = -In.X;
Result.Y = -In.Y;
return(Result);
}
COVERAGE(HMM_UnaryMinusVec3, 1)
HMM_INLINE hmm_vec3 operator-(hmm_vec3 In)
{
ASSERT_COVERED(HMM_UnaryMinusVec3);
hmm_vec3 Result;
Result.X = -In.X;
Result.Y = -In.Y;
Result.Z = -In.Z;
return(Result);
}
COVERAGE(HMM_UnaryMinusVec4, 1)
HMM_INLINE hmm_vec4 operator-(hmm_vec4 In)
{
ASSERT_COVERED(HMM_UnaryMinusVec4);
hmm_vec4 Result;
#if HANDMADE_MATH__USE_SSE
Result.InternalElementsSSE = _mm_xor_ps(In.InternalElementsSSE, _mm_set1_ps(-0.0f));
#else
Result.X = -In.X;
Result.Y = -In.Y;
Result.Z = -In.Z;
Result.W = -In.W;
#endif
return(Result);
}
#endif /* __cplusplus */
#if defined(__GNUC__) || defined(__clang__)

View File

@@ -10,6 +10,8 @@ To get started, go download [the latest release](https://github.com/HandmadeMath
Version | Changes |
----------------|----------------|
**1.12.1** | Added extra parentheses around some macros |
**1.12.0** | Added Unary Minus operator for `HMM_Vec2`, `HMM_Vec3`, and `HMM_Vec4`. |
**1.11.1** | Added HMM_PREFIX macro to a few functions that were missing it. |
**1.11.0** | Added ability to customize or remove the default `HMM_` prefix on function names by defining a macro called `HMM_PREFIX(name)`. |
**1.10.1** | Removed stdint.h, this doesn't exist on some really old compilers and we didn't really use it anyways. |

View File

@@ -58,6 +58,7 @@
#define HANDMADETEST_H
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
@@ -152,7 +153,7 @@ INITIALIZER(_HMT_COVERCASE_FUNCNAME_INIT(name)) { \
_HMT_CASE_START(); \
float actual = (_actual); \
float diff = actual - (_expected); \
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
if (isnan(actual) || diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
_HMT_CASE_FAIL(); \
printf("Expected %f, got %f", (_expected), actual); \
} \
@@ -162,7 +163,7 @@ INITIALIZER(_HMT_COVERCASE_FUNCNAME_INIT(name)) { \
_HMT_CASE_START(); \
float actual = (_actual); \
float diff = actual - (_expected); \
if (diff < -(_epsilon) || (_epsilon) < diff) { \
if (isnan(actual) || diff < -(_epsilon) || (_epsilon) < diff) { \
_HMT_CASE_FAIL(); \
printf("Expected %f, got %f", (_expected), actual); \
} \

View File

@@ -66,14 +66,39 @@ TEST(QuaternionOps, NLerp)
TEST(QuaternionOps, Slerp)
{
hmm_quaternion from = HMM_Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
hmm_quaternion to = HMM_Quaternion(0.5f, 0.5f, -0.5f, 0.5f);
// Normal operation
{
hmm_quaternion from = HMM_Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
hmm_quaternion to = HMM_Quaternion(0.5f, 0.5f, -0.5f, 0.5f);
hmm_quaternion result = HMM_Slerp(from, 0.5f, to);
EXPECT_FLOAT_EQ(result.X, 0.28867513f);
EXPECT_FLOAT_EQ(result.Y, 0.28867513f);
EXPECT_FLOAT_EQ(result.Z, -0.28867513f);
EXPECT_FLOAT_EQ(result.W, 0.86602540f);
hmm_quaternion result = HMM_Slerp(from, 0.5f, to);
EXPECT_FLOAT_EQ(result.X, 0.28867513f);
EXPECT_FLOAT_EQ(result.Y, 0.28867513f);
EXPECT_FLOAT_EQ(result.Z, -0.28867513f);
EXPECT_FLOAT_EQ(result.W, 0.86602540f);
}
// Same quat twice
{
hmm_quaternion q = HMM_Quaternion(0.5f, 0.5f, 0.5f, 1.0f);
hmm_quaternion result = HMM_Slerp(q, 0.5f, q);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.5f);
EXPECT_FLOAT_EQ(result.Z, 0.5f);
EXPECT_FLOAT_EQ(result.W, 1.0f);
}
// Identity quat twice
{
hmm_quaternion q = HMM_Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
hmm_quaternion result = HMM_Slerp(q, 0.5f, q);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 0.0f);
EXPECT_FLOAT_EQ(result.W, 1.0f);
}
}
TEST(QuaternionOps, QuatToMat4)

View File

@@ -199,3 +199,32 @@ TEST(Subtraction, Quaternion)
EXPECT_FLOAT_EQ(q1.W, -4.0f);
#endif
}
#ifdef __cplusplus
TEST(UnaryMinus, Vec2)
{
hmm_vec2 VectorOne = {1.0f, 2.0f};
hmm_vec2 Result = -VectorOne;
EXPECT_FLOAT_EQ(Result.X, -1.0f);
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
}
TEST(UnaryMinus, Vec3)
{
hmm_vec3 VectorOne = {1.0f, 2.0f, 3.0f};
hmm_vec3 Result = -VectorOne;
EXPECT_FLOAT_EQ(Result.X, -1.0f);
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
EXPECT_FLOAT_EQ(Result.Z, -3.0f);
}
TEST(UnaryMinus, Vec4)
{
hmm_vec4 VectorOne = {1.0f, 2.0f, 3.0f, 4.0f};
hmm_vec4 Result = -VectorOne;
EXPECT_FLOAT_EQ(Result.X, -1.0f);
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
EXPECT_FLOAT_EQ(Result.Z, -3.0f);
EXPECT_FLOAT_EQ(Result.W, -4.0f);
}
#endif