Compare commits

...

25 Commits

Author SHA1 Message Date
Ben Visness
142ba3cd9d Align backslashes for great aesthetics (very important) 2025-02-24 17:45:35 -06:00
Ben Visness
8c2ac269ba Redo test scripts 2025-02-23 20:33:06 -06:00
Ben Visness
736ebaaf23 Test and fix _Generic 2025-02-23 20:33:06 -06:00
Ben Visness
bdc7dd2a51 Merge pull request #172 from jonasgf/whitespace
Remove trailing whitespace and extra newlines at end of file
2024-05-28 09:46:45 -05:00
Ben Visness
b4ce44823b Merge pull request #171 from jonasgf/missing-braces
Ignore missing braces warning for all GCC versions
2024-05-28 09:46:22 -05:00
Jonas
2901e70ca3 Remove trailing whitespace and extra newlines at end of file 2024-04-27 22:56:11 +02:00
Jonas
21b4a0d209 Ignore missing braces warning for all GCC versions 2024-04-27 22:46:15 +02:00
Ben Visness
43836aa3a6 Merge pull request #170 from B-Y-P/master
Add HMM_QFromNormPair() and HMM_QFromVecPair()
2024-04-11 11:08:32 -05:00
BYP
bdc04881de Add HMM_QFromNormPair() and HMM_QFromVecPair() 2024-04-08 21:21:54 -04:00
Ben Visness
322826bcee Merge pull request #169 from Jack-Punter/neon_support
Neon support
2023-12-15 20:14:20 -06:00
jack punter
4e1e97522d Address Ben's changes 2023-12-14 21:39:50 +00:00
Jack Punter
6603c796cc Update test Makefile to use NO_SIMD over NO_SSE 2023-12-12 01:53:43 +00:00
Jack Punter
623215b228 NEON Quaternion Multiply 2023-12-12 01:47:01 +00:00
Jack Punter
fcc510f767 Fix scalar 2023-12-12 01:42:37 +00:00
Jack Punter
133a595b6f Better Neon tranpose
vld can de-interleave up to 4-float element structures in one go into multiple registers. This allows us to load each column of the matrix and put each element into a corresponding vector, essentially doing the entire transpose in 1 instruction

Fixed it
2023-12-12 01:42:37 +00:00
Jack Punter
5f20d693c9 Add Neon implementations for all but Quaternion multiply 2023-12-11 22:57:19 +00:00
Ben Visness
e210d8729b Add HMM_RotateV2 2023-11-03 11:34:49 -05:00
dev_dwarf
a1c84320f9 Style tweaks to RotateV3Q + axis angle variant 2023-10-31 13:09:20 -06:00
Olivier Perret
8df5da57f5 Clean trailing whitespace in HandmadeMath.h 2023-10-29 18:33:31 +01:00
Olivier Perret
149c18d449 Add HMM_RotateQV3(), for rotating a vec3 by a quaternion 2023-10-29 18:32:09 +01:00
Olivier Perret
98748f702c Provide const versions of operator[] (#166)
This makes it possible use to do something like

const HMM_Vec3 v{1,2,3};
float val = v[1];
2023-10-27 13:15:58 -05:00
Logan Forman
6cf6226c57 remove most references from operators (#164) 2023-08-05 12:57:56 -04:00
Ben Visness
aaa767bf0b Update README.md 2023-02-20 13:29:24 -06:00
Ben Visness
422bc588e9 Fix inverse perspective 2023-02-20 13:03:46 -06:00
Ben Visness
beb837a3c6 Tweak docs, add tests, find bugs 2023-02-02 19:18:24 -06:00
16 changed files with 1007 additions and 637 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,36 +1,43 @@
# Handmade Math # Handmade Math
A single-file, cross-platform, public domain game math library for both C and C++. Supports vectors, matrices, quaternions, and all the utilities you'd expect. A single-file, cross-platform, public domain graphics math library for both C and C++. Supports vectors, matrices, quaternions, and all the utilities you'd expect.
To get started, go download [the latest release](https://github.com/HandmadeMath/HandmadeMath/releases). To get started, go download [the latest release](https://github.com/HandmadeMath/HandmadeMath/releases).
> If you are upgrading to version 2 of Handmade Math, save yourself some time and use our [automatic update tool](./update). > If you are upgrading to Handmade Math 2.0, save yourself some time and use our [automatic update tool](./update).
Here's what sets Handmade Math apart: Here's what sets Handmade Math apart:
- **A simple single-header library.** Just `#include "HandmadeMath.h"`. - **A simple single-header library.** Just `#include "HandmadeMath.h"`.
- **Supports both C and C++.** While libraries like GLM only support C++, Handmade Math supports both C and C++, with convenient overloads wherever possible. For example, C++ codebases get operator overloading, and C11 codebases get `_Generic` versions of common operations. - **Supports both C and C++.** While libraries like GLM only support C++, Handmade Math supports both C and C++, with convenient overloads wherever possible. For example, C++ codebases get operator overloading, and C11 codebases get `_Generic` versions of common operations.
- **Supports all graphics APIs.** Handmade Math has left- and right-handed versions of each operation, as well as support for zero-to-one and negative-one-to-one NDC conventions.
- **Swizzling, sort of.** Handmade Math's vector types use unions to provide several ways of accessing the same underlying data. For example, the components of an `HMM_Vec3` can be accessed as `XYZ`, `RGB`, or `UVW` - or subsets can be accessed like `.XY` and `.YZ`. - **Swizzling, sort of.** Handmade Math's vector types use unions to provide several ways of accessing the same underlying data. For example, the components of an `HMM_Vec3` can be accessed as `XYZ`, `RGB`, or `UVW` - or subsets can be accessed like `.XY` and `.YZ`.
- **Your choice of angle unit.** While Handmade Math uses radians by default, you can configure it to use degrees or [turns](https://www.computerenhance.com/p/turns-are-better-than-radians) instead. - **Your choice of angle unit.** While Handmade Math uses radians by default, you can configure it to use degrees or [turns](https://www.computerenhance.com/p/turns-are-better-than-radians) instead.
## Usage ## Usage
Simply `#include "HandmadeMath.h"`. All functions are `static inline`, so no need for an "implementation" file as with some other single-header libraries. Simply `#include "HandmadeMath.h"`. All functions are `static inline`, so there is no need for an "implementation" file as with some other single-header libraries.
A few config options are available. See the header comment in [the source](./HandmadeMath.h) for details. A few config options are available. See the header comment in [the source](./HandmadeMath.h) for details.
## FAQ ## FAQ
**What conventions does HMM use, e.g. row vs. column major, handedness, etc.?**
Handmade Math's matrices are column-major, i.e. data is stored by columns, then rows. It also assumes column vectors, i.e. vectors are written vertically and matrix-vector multiplication is `M * V` instead of `V * M`. For more information, see [this issue](https://github.com/HandmadeMath/HandmadeMath/issues/124#issuecomment-775737253).
For other properties, we provide variants for each common convention. Functions that care about handedness have left-handed (`LH`) and right-handed (`RH`) variants. Projection functions have zero-to-one (`ZO`) and negative-one-to-one (`NO`) variants for different NDC conventions.
**What if I don't want the `HMM_` prefix?**
Do a find and replace in the library source.
**What's the license?** **What's the license?**
This library is in the public domain. You can do whatever you want with it. This library is in the public domain. You can do whatever you want with it.
**Where can I contact you to ask questions?** **Where can I contact you to ask questions?**
Feel free to make Github issues for any questions, concerns, or problems you encounter. Feel free to make GitHub issues for any questions, concerns, or problems you encounter.
**What if I don't want the `HMM_` prefix?**
Do a find and replace in the library source.

View File

@@ -148,25 +148,35 @@ INITIALIZER(_HMT_COVERCASE_FUNCNAME_INIT(name)) { \
} \ } \
} \ } \
#define HMT_EXPECT_FLOAT_EQ(_actual, _expected) { \ #define HMT_EXPECT_FLOAT_EQ_MSG(_actual, _expected, _msg) { \
_HMT_CASE_START(); \ _HMT_CASE_START(); \
float actual = (_actual); \ float actual = (_actual); \
float diff = actual - (_expected); \ float diff = actual - (_expected); \
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \ if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
_HMT_CASE_FAIL(); \ _HMT_CASE_FAIL(); \
printf("Expected %f, got %f", (_expected), actual); \ if ((_msg)[0] == 0) { \
printf("Expected %f, got %f (error: %.9g)", (_expected), actual, diff); \
} else { \
printf("%s: Expected %f, got %f (error: %.9g)", (_msg), (_expected), actual, diff); \
} \
} \ } \
} \ }
#define HMT_EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ_MSG(_actual, _expected, "");
#define HMT_EXPECT_NEAR(_actual, _expected, _epsilon) { \ #define HMT_EXPECT_NEAR_MSG(_actual, _expected, _epsilon, _msg) { \
_HMT_CASE_START(); \ _HMT_CASE_START(); \
float actual = (_actual); \ float actual = (_actual); \
float diff = actual - (_expected); \ float diff = actual - (_expected); \
if (diff < -(_epsilon) || (_epsilon) < diff) { \ if (diff < -(_epsilon) || (_epsilon) < diff) { \
_HMT_CASE_FAIL(); \ _HMT_CASE_FAIL(); \
printf("Expected %f, got %f", (_expected), actual); \ if ((_msg)[0] == 0) { \
printf("Expected %f, got %f", (_expected), actual); \
} else { \
printf("%s: Expected %f, got %f", (_msg), (_expected), actual); \
} \
} \ } \
} \ }
#define HMT_EXPECT_NEAR(_actual, _expected, _epsilon) HMT_EXPECT_NEAR_MSG(_actual, _expected, _epsilon, "");
#define HMT_EXPECT_LT(_actual, _expected) { \ #define HMT_EXPECT_LT(_actual, _expected) { \
_HMT_CASE_START(); \ _HMT_CASE_START(); \
@@ -192,7 +202,46 @@ INITIALIZER(_HMT_COVERCASE_FUNCNAME_INIT(name)) { \
#define EXPECT_TRUE(_actual) HMT_EXPECT_TRUE(_actual) #define EXPECT_TRUE(_actual) HMT_EXPECT_TRUE(_actual)
#define EXPECT_FALSE(_actual) HMT_EXPECT_FALSE(_actual) #define EXPECT_FALSE(_actual) HMT_EXPECT_FALSE(_actual)
#define EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ(_actual, _expected) #define EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ(_actual, _expected)
#define EXPECT_V4_EQ(_actual, _expected) \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.X, _expected.X, "incorrect X"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Y, _expected.Y, "incorrect Y"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Z, _expected.Z, "incorrect Z"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.W, _expected.W, "incorrect W");
#define EXPECT_M4_EQ(_actual, _expected) \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[0][0], _expected.Elements[0][0], "incorrect [0][0]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[0][1], _expected.Elements[0][1], "incorrect [0][1]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[0][2], _expected.Elements[0][2], "incorrect [0][2]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[0][3], _expected.Elements[0][3], "incorrect [0][3]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[1][0], _expected.Elements[1][0], "incorrect [1][0]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[1][1], _expected.Elements[1][1], "incorrect [1][1]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[1][2], _expected.Elements[1][2], "incorrect [1][2]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[1][3], _expected.Elements[1][3], "incorrect [1][3]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[2][0], _expected.Elements[2][0], "incorrect [2][0]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[2][1], _expected.Elements[2][1], "incorrect [2][1]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[2][2], _expected.Elements[2][2], "incorrect [2][2]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[2][3], _expected.Elements[2][3], "incorrect [2][3]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[3][0], _expected.Elements[3][0], "incorrect [3][0]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[3][1], _expected.Elements[3][1], "incorrect [3][1]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[3][2], _expected.Elements[3][2], "incorrect [3][2]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[3][3], _expected.Elements[3][3], "incorrect [3][3]");
#define EXPECT_NEAR(_actual, _expected, _epsilon) HMT_EXPECT_NEAR(_actual, _expected, _epsilon) #define EXPECT_NEAR(_actual, _expected, _epsilon) HMT_EXPECT_NEAR(_actual, _expected, _epsilon)
#define EXPECT_M4_NEAR(_actual, _expected, _epsilon) \
HMT_EXPECT_NEAR_MSG(_actual.Elements[0][0], _expected.Elements[0][0], _epsilon, "incorrect [0][0]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[0][1], _expected.Elements[0][1], _epsilon, "incorrect [0][1]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[0][2], _expected.Elements[0][2], _epsilon, "incorrect [0][2]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[0][3], _expected.Elements[0][3], _epsilon, "incorrect [0][3]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[1][0], _expected.Elements[1][0], _epsilon, "incorrect [1][0]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[1][1], _expected.Elements[1][1], _epsilon, "incorrect [1][1]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[1][2], _expected.Elements[1][2], _epsilon, "incorrect [1][2]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[1][3], _expected.Elements[1][3], _epsilon, "incorrect [1][3]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[2][0], _expected.Elements[2][0], _epsilon, "incorrect [2][0]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[2][1], _expected.Elements[2][1], _epsilon, "incorrect [2][1]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[2][2], _expected.Elements[2][2], _epsilon, "incorrect [2][2]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[2][3], _expected.Elements[2][3], _epsilon, "incorrect [2][3]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[3][0], _expected.Elements[3][0], _epsilon, "incorrect [3][0]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[3][1], _expected.Elements[3][1], _epsilon, "incorrect [3][1]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[3][2], _expected.Elements[3][2], _epsilon, "incorrect [3][2]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[3][3], _expected.Elements[3][3], _epsilon, "incorrect [3][3]");
#define EXPECT_LT(_actual, _expected) HMT_EXPECT_LT(_actual, _expected) #define EXPECT_LT(_actual, _expected) HMT_EXPECT_LT(_actual, _expected)
#define EXPECT_GT(_actual, _expected) HMT_EXPECT_GT(_actual, _expected) #define EXPECT_GT(_actual, _expected) HMT_EXPECT_GT(_actual, _expected)
#endif // HMT_SAFE_MACROS #endif // HMT_SAFE_MACROS

View File

@@ -2,77 +2,123 @@ BUILD_DIR=./build
CXXFLAGS+=-g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers -Wfloat-equal CXXFLAGS+=-g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers -Wfloat-equal
all: c c_no_sse cpp cpp_no_sse build_c_without_coverage build_cpp_without_coverage .PHONY: all all_c all_cpp
all: all_c all_cpp
build_all: build_c build_c_no_sse build_cpp build_cpp_no_sse all_c: c99 c99_no_simd c11 c17
all_cpp: cpp98 cpp98_no_simd cpp03 cpp11 cpp14 cpp17 cpp20
.PHONY: clean
clean: clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)
c: build_c .PHONY: c99
$(BUILD_DIR)/hmm_test_c c99:
@echo "\nCompiling as C99"
build_c: HandmadeMath.c test_impl
@echo "\nCompiling in C mode"
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR)\ cd $(BUILD_DIR)\
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \ && $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
-c ../HandmadeMath.c ../hmm_test.c \ ../HandmadeMath.c ../hmm_test.c \
-lm \ -lm -o hmm_test_c99 \
&& $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm && ./hmm_test_c99
c_no_sse: build_c_no_sse .PHONY: c99_no_simd
$(BUILD_DIR)/hmm_test_c_no_sse c99_no_simd:
@echo "\nCompiling as C99 (no SIMD)"
build_c_no_sse: HandmadeMath.c test_impl
@echo "\nCompiling in C mode (no SSE)"
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \ cd $(BUILD_DIR) \
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \ && $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
-DHANDMADE_MATH_NO_SSE \ -DHANDMADE_MATH_NO_SIMD \
-c ../HandmadeMath.c ../hmm_test.c \ ../HandmadeMath.c ../hmm_test.c \
-lm \ -lm -o hmm_test_c99_no_simd \
&& $(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm && ./hmm_test_c99_no_simd
cpp: build_cpp .PHONY: c11
$(BUILD_DIR)/hmm_test_cpp c11:
@echo "\nCompiling as C11"
build_cpp: HandmadeMath.cpp test_impl
@echo "\nCompiling in C++ mode"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp \
-DHANDMADE_MATH_CPP_MODE \
../HandmadeMath.cpp ../hmm_test.cpp
cpp_no_sse: build_cpp_no_sse
$(BUILD_DIR)/hmm_test_cpp_no_sse
build_cpp_no_sse: HandmadeMath.cpp test_impl
@echo "\nCompiling in C++ mode (no SSE)"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse \
-DHANDMADE_MATH_CPP_MODE -DHANDMADE_MATH_NO_SSE \
../HandmadeMath.cpp ../hmm_test.cpp
test_impl: hmm_test.cpp hmm_test.c
build_c_without_coverage: HandmadeMath.c test_impl
@echo "\nCompiling in C mode"
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR)\ cd $(BUILD_DIR)\
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \ && $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c11 \
-DWITHOUT_COVERAGE \ ../HandmadeMath.c ../hmm_test.c \
-c ../HandmadeMath.c ../hmm_test.c \ -lm -o hmm_test_c11 \
-lm \ && ./hmm_test_c11
&& $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
build_cpp_without_coverage: HandmadeMath.cpp test_impl .PHONY: c17
@echo "\nCompiling in C++ mode (no SSE)" c17:
@echo "\nCompiling as C17"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR)\
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c17 \
../HandmadeMath.c ../hmm_test.c \
-lm -o hmm_test_c17 \
&& ./hmm_test_c17
.PHONY: cpp98
cpp98:
@echo "\nCompiling as C++98"
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \ cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse \ && $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++98 \
-DHANDMADE_MATH_CPP_MODE -DWITHOUT_COVERAGE \ ../HandmadeMath.cpp ../hmm_test.cpp \
../HandmadeMath.cpp ../hmm_test.cpp -lm -o hmm_test_cpp98 \
&& ./hmm_test_cpp98
.PHONY: cpp98_no_simd
cpp98_no_simd:
@echo "\nCompiling as C++98 (no SIMD)"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++98 \
-DHANDMADE_MATH_NO_SIMD \
../HandmadeMath.cpp ../hmm_test.cpp \
-lm -o hmm_test_cpp98 \
&& ./hmm_test_cpp98
.PHONY: cpp03
cpp03:
@echo "\nCompiling as C++03"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++03 \
../HandmadeMath.cpp ../hmm_test.cpp \
-lm -o hmm_test_cpp03 \
&& ./hmm_test_cpp03
.PHONY: cpp11
cpp11:
@echo "\nCompiling as C++11"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++11 \
../HandmadeMath.cpp ../hmm_test.cpp \
-lm -o hmm_test_cpp11 \
&& ./hmm_test_cpp11
.PHONY: cpp14
cpp14:
@echo "\nCompiling as C++14"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++14 \
../HandmadeMath.cpp ../hmm_test.cpp \
-lm -o hmm_test_cpp14 \
&& ./hmm_test_cpp14
.PHONY: cpp17
cpp17:
@echo "\nCompiling as C++17"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++17 \
../HandmadeMath.cpp ../hmm_test.cpp \
-lm -o hmm_test_cpp17 \
&& ./hmm_test_cpp17
.PHONY: cpp20
cpp20:
@echo "\nCompiling as C++20"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++20 \
../HandmadeMath.cpp ../hmm_test.cpp \
-lm -o hmm_test_cpp20 \
&& ./hmm_test_cpp20

View File

@@ -10,12 +10,14 @@ TEST(Addition, Vec2)
EXPECT_FLOAT_EQ(result.X, 4.0f); EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec2 result = HMM_Add(v2_1, v2_2); HMM_Vec2 result = HMM_Add(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 4.0f); EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec2 result = v2_1 + v2_2; HMM_Vec2 result = v2_1 + v2_2;
EXPECT_FLOAT_EQ(result.X, 4.0f); EXPECT_FLOAT_EQ(result.X, 4.0f);
@@ -39,13 +41,15 @@ TEST(Addition, Vec3)
EXPECT_FLOAT_EQ(result.Y, 7.0f); EXPECT_FLOAT_EQ(result.Y, 7.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f); EXPECT_FLOAT_EQ(result.Z, 9.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec3 result = HMM_Add(v3_1, v3_2); HMM_Vec3 result = HMM_Add(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 5.0f); EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 7.0f); EXPECT_FLOAT_EQ(result.Y, 7.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f); EXPECT_FLOAT_EQ(result.Z, 9.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec3 result = v3_1 + v3_2; HMM_Vec3 result = v3_1 + v3_2;
EXPECT_FLOAT_EQ(result.X, 5.0f); EXPECT_FLOAT_EQ(result.X, 5.0f);
@@ -72,7 +76,7 @@ TEST(Addition, Vec4)
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f); EXPECT_FLOAT_EQ(result.W, 12.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec4 result = HMM_Add(v4_1, v4_2); HMM_Vec4 result = HMM_Add(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 6.0f); EXPECT_FLOAT_EQ(result.X, 6.0f);
@@ -80,6 +84,8 @@ TEST(Addition, Vec4)
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f); EXPECT_FLOAT_EQ(result.W, 12.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec4 result = v4_1 + v4_2; HMM_Vec4 result = v4_1 + v4_2;
EXPECT_FLOAT_EQ(result.X, 6.0f); EXPECT_FLOAT_EQ(result.X, 6.0f);
@@ -125,14 +131,16 @@ TEST(Addition, Mat2)
EXPECT_FLOAT_EQ(result.Elements[1][1], 12.0f); EXPECT_FLOAT_EQ(result.Elements[1][1], 12.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat2 result = HMM_Add(a, b); HMM_Mat2 result = HMM_Add(a, b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 6.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 8.0f); EXPECT_FLOAT_EQ(result.Elements[0][1], 8.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 10.0f); EXPECT_FLOAT_EQ(result.Elements[1][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 12.0f); EXPECT_FLOAT_EQ(result.Elements[1][1], 12.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat2 result = a + b; HMM_Mat2 result = a + b;
EXPECT_FLOAT_EQ(result.Elements[0][0], 6.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 6.0f);
@@ -182,19 +190,21 @@ TEST(Addition, Mat3)
EXPECT_FLOAT_EQ(result.Elements[2][2], 27.0f); EXPECT_FLOAT_EQ(result.Elements[2][2], 27.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat3 result = HMM_Add(a, b); HMM_Mat3 result = HMM_Add(a, b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 11.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 11.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 13.0f); EXPECT_FLOAT_EQ(result.Elements[0][1], 13.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 15.0f); EXPECT_FLOAT_EQ(result.Elements[0][2], 15.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 17.0f); EXPECT_FLOAT_EQ(result.Elements[1][0], 17.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 19.0f); EXPECT_FLOAT_EQ(result.Elements[1][1], 19.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f); EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 23.0f); EXPECT_FLOAT_EQ(result.Elements[2][0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 25.0f); EXPECT_FLOAT_EQ(result.Elements[2][1], 25.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 27.0f); EXPECT_FLOAT_EQ(result.Elements[2][2], 27.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat3 result = a + b; HMM_Mat3 result = a + b;
EXPECT_FLOAT_EQ(result.Elements[0][0], 11.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 11.0f);
@@ -257,7 +267,7 @@ TEST(Addition, Mat4)
} }
} }
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat4 result = HMM_Add(m4_1, m4_2); HMM_Mat4 result = HMM_Add(m4_1, m4_2);
float Expected = 18.0f; float Expected = 18.0f;
@@ -270,6 +280,8 @@ TEST(Addition, Mat4)
} }
} }
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat4 result = m4_1 + m4_2; HMM_Mat4 result = m4_1 + m4_2;
float Expected = 18.0f; float Expected = 18.0f;
@@ -308,7 +320,7 @@ TEST(Addition, Quaternion)
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f); EXPECT_FLOAT_EQ(result.W, 12.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Quat result = HMM_Add(q1, q2); HMM_Quat result = HMM_Add(q1, q2);
EXPECT_FLOAT_EQ(result.X, 6.0f); EXPECT_FLOAT_EQ(result.X, 6.0f);
@@ -316,6 +328,8 @@ TEST(Addition, Quaternion)
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f); EXPECT_FLOAT_EQ(result.W, 12.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Quat result = q1 + q2; HMM_Quat result = q1 + q2;
EXPECT_FLOAT_EQ(result.X, 6.0f); EXPECT_FLOAT_EQ(result.X, 6.0f);

View File

@@ -10,12 +10,14 @@ TEST(Division, Vec2Vec2)
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f); EXPECT_FLOAT_EQ(result.Y, 0.75f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec2 result = HMM_Div(v2_1, v2_2); HMM_Vec2 result = HMM_Div(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f); EXPECT_FLOAT_EQ(result.Y, 0.75f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec2 result = v2_1 / v2_2; HMM_Vec2 result = v2_1 / v2_2;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -38,12 +40,14 @@ TEST(Division, Vec2Scalar)
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f); EXPECT_FLOAT_EQ(result.Y, 1.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec2 result = HMM_Div(v2, s); HMM_Vec2 result = HMM_Div(v2, s);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f); EXPECT_FLOAT_EQ(result.Y, 1.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec2 result = v2 / s; HMM_Vec2 result = v2 / s;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -67,13 +71,15 @@ TEST(Division, Vec3Vec3)
EXPECT_FLOAT_EQ(result.Y, 0.75f); EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec3 result = HMM_Div(v3_1, v3_2); HMM_Vec3 result = HMM_Div(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f); EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec3 result = v3_1 / v3_2; HMM_Vec3 result = v3_1 / v3_2;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -99,13 +105,15 @@ TEST(Division, Vec3Scalar)
EXPECT_FLOAT_EQ(result.Y, 1.0f); EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f); EXPECT_FLOAT_EQ(result.Z, 1.5f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec3 result = HMM_Div(v3, s); HMM_Vec3 result = HMM_Div(v3, s);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f); EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f); EXPECT_FLOAT_EQ(result.Z, 1.5f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec3 result = v3 / s; HMM_Vec3 result = v3 / s;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -132,7 +140,7 @@ TEST(Division, Vec4Vec4)
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 0.25f); EXPECT_FLOAT_EQ(result.W, 0.25f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec4 result = HMM_Div(v4_1, v4_2); HMM_Vec4 result = HMM_Div(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -140,6 +148,8 @@ TEST(Division, Vec4Vec4)
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 0.25f); EXPECT_FLOAT_EQ(result.W, 0.25f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec4 result = v4_1 / v4_2; HMM_Vec4 result = v4_1 / v4_2;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -168,7 +178,7 @@ TEST(Division, Vec4Scalar)
EXPECT_FLOAT_EQ(result.Z, 1.5f); EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f); EXPECT_FLOAT_EQ(result.W, 2.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec4 result = HMM_Div(v4, s); HMM_Vec4 result = HMM_Div(v4, s);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -176,6 +186,8 @@ TEST(Division, Vec4Scalar)
EXPECT_FLOAT_EQ(result.Z, 1.5f); EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f); EXPECT_FLOAT_EQ(result.W, 2.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec4 result = v4 / s; HMM_Vec4 result = v4 / s;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -212,7 +224,7 @@ TEST(Division, Mat2Scalar)
EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f); EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat2 result = HMM_Div(m, s); HMM_Mat2 result = HMM_Div(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
@@ -220,7 +232,9 @@ TEST(Division, Mat2Scalar)
EXPECT_FLOAT_EQ(result.Elements[1][0], 6.0f); EXPECT_FLOAT_EQ(result.Elements[1][0], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f); EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat2 result = m / s; HMM_Mat2 result = m / s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
@@ -257,7 +271,7 @@ TEST(Division, Mat3Scalar)
EXPECT_FLOAT_EQ(result.Elements[2][2], 18.0f); EXPECT_FLOAT_EQ(result.Elements[2][2], 18.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat3 result = HMM_Div(m, s); HMM_Mat3 result = HMM_Div(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
@@ -270,7 +284,9 @@ TEST(Division, Mat3Scalar)
EXPECT_FLOAT_EQ(result.Elements[2][1], 16.0f); EXPECT_FLOAT_EQ(result.Elements[2][1], 16.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 18.0f); EXPECT_FLOAT_EQ(result.Elements[2][2], 18.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat3 result = m / s; HMM_Mat3 result = m / s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
@@ -322,7 +338,7 @@ TEST(Division, Mat4Scalar)
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f); EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f); EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat4 result = HMM_Div(m4, s); HMM_Mat4 result = HMM_Div(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f); EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
@@ -342,6 +358,8 @@ TEST(Division, Mat4Scalar)
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f); EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f); EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat4 result = m4 / s; HMM_Mat4 result = m4 / s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f); EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
@@ -394,7 +412,7 @@ TEST(Division, QuaternionScalar)
EXPECT_FLOAT_EQ(result.Z, 1.5f); EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f); EXPECT_FLOAT_EQ(result.W, 2.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Quat result = HMM_Div(q, f); HMM_Quat result = HMM_Div(q, f);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -402,6 +420,8 @@ TEST(Division, QuaternionScalar)
EXPECT_FLOAT_EQ(result.Z, 1.5f); EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f); EXPECT_FLOAT_EQ(result.W, 2.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Quat result = q / f; HMM_Quat result = q / f;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);

View File

@@ -9,10 +9,12 @@ TEST(Equality, Vec2)
EXPECT_TRUE(HMM_EqV2(a, b)); EXPECT_TRUE(HMM_EqV2(a, b));
EXPECT_FALSE(HMM_EqV2(a, c)); EXPECT_FALSE(HMM_EqV2(a, c));
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_TRUE(HMM_Eq(a, b)); EXPECT_TRUE(HMM_Eq(a, b));
EXPECT_FALSE(HMM_Eq(a, c)); EXPECT_FALSE(HMM_Eq(a, c));
#endif
#ifdef __cplusplus
EXPECT_TRUE(a == b); EXPECT_TRUE(a == b);
EXPECT_FALSE(a == c); EXPECT_FALSE(a == c);
@@ -30,10 +32,12 @@ TEST(Equality, Vec3)
EXPECT_TRUE(HMM_EqV3(a, b)); EXPECT_TRUE(HMM_EqV3(a, b));
EXPECT_FALSE(HMM_EqV3(a, c)); EXPECT_FALSE(HMM_EqV3(a, c));
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_TRUE(HMM_Eq(a, b)); EXPECT_TRUE(HMM_Eq(a, b));
EXPECT_FALSE(HMM_Eq(a, c)); EXPECT_FALSE(HMM_Eq(a, c));
#endif
#ifdef __cplusplus
EXPECT_TRUE(a == b); EXPECT_TRUE(a == b);
EXPECT_FALSE(a == c); EXPECT_FALSE(a == c);
@@ -51,10 +55,12 @@ TEST(Equality, Vec4)
EXPECT_TRUE(HMM_EqV4(a, b)); EXPECT_TRUE(HMM_EqV4(a, b));
EXPECT_FALSE(HMM_EqV4(a, c)); EXPECT_FALSE(HMM_EqV4(a, c));
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_TRUE(HMM_Eq(a, b)); EXPECT_TRUE(HMM_Eq(a, b));
EXPECT_FALSE(HMM_Eq(a, c)); EXPECT_FALSE(HMM_Eq(a, c));
#endif
#ifdef __cplusplus
EXPECT_TRUE(a == b); EXPECT_TRUE(a == b);
EXPECT_FALSE(a == c); EXPECT_FALSE(a == c);

View File

@@ -19,7 +19,7 @@ TEST(InvMatrix, Transpose)
EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]); EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]); EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat2 result = HMM_Transpose(Matrix); HMM_Mat2 result = HMM_Transpose(Matrix);
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]); EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
@@ -54,7 +54,7 @@ TEST(InvMatrix, Transpose)
EXPECT_FLOAT_EQ(result.Elements[2][1], Expect.Elements[2][1]); EXPECT_FLOAT_EQ(result.Elements[2][1], Expect.Elements[2][1]);
EXPECT_FLOAT_EQ(result.Elements[2][2], Expect.Elements[2][2]); EXPECT_FLOAT_EQ(result.Elements[2][2], Expect.Elements[2][2]);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat3 result = HMM_Transpose(Matrix); HMM_Mat3 result = HMM_Transpose(Matrix);
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]); EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
@@ -94,7 +94,7 @@ TEST(InvMatrix, Transpose)
EXPECT_FLOAT_EQ(result.Elements[2][1], Expect.Elements[2][1]); EXPECT_FLOAT_EQ(result.Elements[2][1], Expect.Elements[2][1]);
EXPECT_FLOAT_EQ(result.Elements[2][2], Expect.Elements[2][2]); EXPECT_FLOAT_EQ(result.Elements[2][2], Expect.Elements[2][2]);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat4 result = HMM_Transpose(Matrix); HMM_Mat4 result = HMM_Transpose(Matrix);
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]); EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
@@ -129,22 +129,22 @@ TEST(InvMatrix, InvGeneral)
float Det = HMM_DeterminantM4(Matrix); float Det = HMM_DeterminantM4(Matrix);
EXPECT_FLOAT_EQ(Det, -80.0f); EXPECT_FLOAT_EQ(Det, -80.0f);
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]); EXPECT_NEAR(Result.Elements[0][0], Expect.Elements[0][0], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]); EXPECT_NEAR(Result.Elements[0][1], Expect.Elements[0][1], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]); EXPECT_NEAR(Result.Elements[0][2], Expect.Elements[0][2], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[0][3], Expect.Elements[0][3]); EXPECT_NEAR(Result.Elements[0][3], Expect.Elements[0][3], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]); EXPECT_NEAR(Result.Elements[1][0], Expect.Elements[1][0], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]); EXPECT_NEAR(Result.Elements[1][1], Expect.Elements[1][1], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]); EXPECT_NEAR(Result.Elements[1][2], Expect.Elements[1][2], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[1][3], Expect.Elements[1][3]); EXPECT_NEAR(Result.Elements[1][3], Expect.Elements[1][3], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]); EXPECT_NEAR(Result.Elements[2][0], Expect.Elements[2][0], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]); EXPECT_NEAR(Result.Elements[2][1], Expect.Elements[2][1], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]); EXPECT_NEAR(Result.Elements[2][2], Expect.Elements[2][2], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[2][3], Expect.Elements[2][3]); EXPECT_NEAR(Result.Elements[2][3], Expect.Elements[2][3], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[3][0], Expect.Elements[3][0]); EXPECT_NEAR(Result.Elements[3][0], Expect.Elements[3][0], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[3][1], Expect.Elements[3][1]); EXPECT_NEAR(Result.Elements[3][1], Expect.Elements[3][1], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[3][2], Expect.Elements[3][2]); EXPECT_NEAR(Result.Elements[3][2], Expect.Elements[3][2], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[3][3], Expect.Elements[3][3]); EXPECT_NEAR(Result.Elements[3][3], Expect.Elements[3][3], 0.00001f);
#ifdef __cplusplus #ifdef __cplusplus
Inverse = HMM_InvGeneral(Matrix); Inverse = HMM_InvGeneral(Matrix);
@@ -153,22 +153,22 @@ TEST(InvMatrix, InvGeneral)
Det = HMM_Determinant(Matrix); Det = HMM_Determinant(Matrix);
EXPECT_FLOAT_EQ(Det, -80.0f); EXPECT_FLOAT_EQ(Det, -80.0f);
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]); EXPECT_NEAR(Result.Elements[0][0], Expect.Elements[0][0], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]); EXPECT_NEAR(Result.Elements[0][1], Expect.Elements[0][1], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]); EXPECT_NEAR(Result.Elements[0][2], Expect.Elements[0][2], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[0][3], Expect.Elements[0][3]); EXPECT_NEAR(Result.Elements[0][3], Expect.Elements[0][3], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]); EXPECT_NEAR(Result.Elements[1][0], Expect.Elements[1][0], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]); EXPECT_NEAR(Result.Elements[1][1], Expect.Elements[1][1], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]); EXPECT_NEAR(Result.Elements[1][2], Expect.Elements[1][2], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[1][3], Expect.Elements[1][3]); EXPECT_NEAR(Result.Elements[1][3], Expect.Elements[1][3], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]); EXPECT_NEAR(Result.Elements[2][0], Expect.Elements[2][0], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]); EXPECT_NEAR(Result.Elements[2][1], Expect.Elements[2][1], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]); EXPECT_NEAR(Result.Elements[2][2], Expect.Elements[2][2], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[2][3], Expect.Elements[2][3]); EXPECT_NEAR(Result.Elements[2][3], Expect.Elements[2][3], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[3][0], Expect.Elements[3][0]); EXPECT_NEAR(Result.Elements[3][0], Expect.Elements[3][0], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[3][1], Expect.Elements[3][1]); EXPECT_NEAR(Result.Elements[3][1], Expect.Elements[3][1], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[3][2], Expect.Elements[3][2]); EXPECT_NEAR(Result.Elements[3][2], Expect.Elements[3][2], 0.00001f);
EXPECT_FLOAT_EQ(Result.Elements[3][3], Expect.Elements[3][3]); EXPECT_NEAR(Result.Elements[3][3], Expect.Elements[3][3], 0.00001f);
#endif #endif
} }
@@ -246,60 +246,56 @@ TEST(InvMatrix, InvGeneral)
} }
} }
TEST(InvMatrix, Mat4Inverses) TEST(InvMatrix, InvOrthographic)
{ {
{ {
HMM_Mat4 Matrix = HMM_Orthographic_RH_NO(-160+100, 160+100, -90+200, 90+200, 10, 10000); HMM_Mat4 Matrix = HMM_Orthographic_RH_NO(-160+100, 160+100, -90+200, 90+200, 10, 10000);
HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix); HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse); EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]);
EXPECT_FLOAT_EQ(Result.Elements[0][3], Expect.Elements[0][3]);
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]);
EXPECT_FLOAT_EQ(Result.Elements[1][3], Expect.Elements[1][3]);
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]);
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]);
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]);
EXPECT_FLOAT_EQ(Result.Elements[2][3], Expect.Elements[2][3]);
EXPECT_FLOAT_EQ(Result.Elements[3][0], Expect.Elements[3][0]);
EXPECT_FLOAT_EQ(Result.Elements[3][1], Expect.Elements[3][1]);
EXPECT_FLOAT_EQ(Result.Elements[3][2], Expect.Elements[3][2]);
EXPECT_FLOAT_EQ(Result.Elements[3][3], Expect.Elements[3][3]);
} }
{ {
HMM_Mat4 Matrix = HMM_Perspective_RH_NO(HMM_AngleDeg(120), 16.0/9.0, 10, 10000); HMM_Mat4 Matrix = HMM_Orthographic_RH_ZO(-160+100, 160+100, -90+200, 90+200, 10, 10000);
HMM_Mat4 Expect = HMM_M4D(1.0f); HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix);
HMM_Mat4 Inverse = HMM_InvPerspective(Matrix); EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]);
EXPECT_FLOAT_EQ(Result.Elements[0][3], Expect.Elements[0][3]);
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]);
EXPECT_FLOAT_EQ(Result.Elements[1][3], Expect.Elements[1][3]);
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]);
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]);
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]);
EXPECT_FLOAT_EQ(Result.Elements[2][3], Expect.Elements[2][3]);
EXPECT_FLOAT_EQ(Result.Elements[3][0], Expect.Elements[3][0]);
EXPECT_FLOAT_EQ(Result.Elements[3][1], Expect.Elements[3][1]);
EXPECT_FLOAT_EQ(Result.Elements[3][2], Expect.Elements[3][2]);
EXPECT_FLOAT_EQ(Result.Elements[3][3], Expect.Elements[3][3]);
} }
{
HMM_Mat4 Matrix = HMM_Orthographic_LH_NO(-160+100, 160+100, -90+200, 90+200, 10, 10000);
HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
{
HMM_Mat4 Matrix = HMM_Orthographic_LH_ZO(-160+100, 160+100, -90+200, 90+200, 10, 10000);
HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
}
TEST(InvMatrix, InvPerspective)
{
{
HMM_Mat4 Matrix = HMM_Perspective_RH_NO(HMM_AngleDeg(120), 16.0/9.0, 10, 10000);
HMM_Mat4 Inverse = HMM_InvPerspective_RH(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
{
HMM_Mat4 Matrix = HMM_Perspective_RH_ZO(HMM_AngleDeg(120), 16.0/9.0, 10, 10000);
HMM_Mat4 Inverse = HMM_InvPerspective_RH(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
{
HMM_Mat4 Matrix = HMM_Perspective_LH_NO(HMM_AngleDeg(120), 16.0/9.0, 10, 10000);
HMM_Mat4 Inverse = HMM_InvPerspective_LH(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
{
HMM_Mat4 Matrix = HMM_Perspective_LH_ZO(HMM_AngleDeg(120), 16.0/9.0, 10, 10000);
HMM_Mat4 Inverse = HMM_InvPerspective_LH(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
}
TEST(InvMatrix, InvLookAt)
{
{ {
HMM_Vec3 Eye = {10.0f, 10.0f, 10.0f}; HMM_Vec3 Eye = {10.0f, 10.0f, 10.0f};
HMM_Vec3 Center = {100.0f, 200.0f, 30.0f}; HMM_Vec3 Center = {100.0f, 200.0f, 30.0f};
@@ -308,106 +304,56 @@ TEST(InvMatrix, Mat4Inverses)
HMM_Mat4 Expect = HMM_M4D(1.0f); HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvLookAt(Matrix); HMM_Mat4 Inverse = HMM_InvLookAt(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse); HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_NEAR(Result, Expect, 0.001f);
EXPECT_NEAR(Result.Elements[0][0], Expect.Elements[0][0], 0.001f);
EXPECT_NEAR(Result.Elements[0][1], Expect.Elements[0][1], 0.001f);
EXPECT_NEAR(Result.Elements[0][2], Expect.Elements[0][2], 0.001f);
EXPECT_NEAR(Result.Elements[0][3], Expect.Elements[0][3], 0.001f);
EXPECT_NEAR(Result.Elements[1][0], Expect.Elements[1][0], 0.001f);
EXPECT_NEAR(Result.Elements[1][1], Expect.Elements[1][1], 0.001f);
EXPECT_NEAR(Result.Elements[1][2], Expect.Elements[1][2], 0.001f);
EXPECT_NEAR(Result.Elements[1][3], Expect.Elements[1][3], 0.001f);
EXPECT_NEAR(Result.Elements[2][0], Expect.Elements[2][0], 0.001f);
EXPECT_NEAR(Result.Elements[2][1], Expect.Elements[2][1], 0.001f);
EXPECT_NEAR(Result.Elements[2][2], Expect.Elements[2][2], 0.001f);
EXPECT_NEAR(Result.Elements[2][3], Expect.Elements[2][3], 0.001f);
EXPECT_NEAR(Result.Elements[3][0], Expect.Elements[3][0], 0.001f);
EXPECT_NEAR(Result.Elements[3][1], Expect.Elements[3][1], 0.001f);
EXPECT_NEAR(Result.Elements[3][2], Expect.Elements[3][2], 0.001f);
EXPECT_NEAR(Result.Elements[3][3], Expect.Elements[3][3], 0.001f);
} }
{
HMM_Vec3 Eye = {10.0f, 10.0f, 10.0f};
HMM_Vec3 Center = {100.0f, 200.0f, 30.0f};
HMM_Vec3 Up = {0.0f, 0.0f, 1.0f};
HMM_Mat4 Matrix = HMM_LookAt_LH(Eye, Center, Up);
HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvLookAt(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_NEAR(Result, Expect, 0.001f);
}
}
TEST(InvMatrix, InvRotate)
{
{ {
HMM_Vec3 Axis = {1.0f, -1.0f, 0.5f}; HMM_Vec3 Axis = {1.0f, -1.0f, 0.5f};
HMM_Mat4 Matrix = HMM_Rotate_RH(HMM_AngleDeg(30), HMM_NormV3(Axis)); HMM_Mat4 Matrix = HMM_Rotate_RH(HMM_AngleDeg(30), HMM_NormV3(Axis));
HMM_Mat4 Expect = HMM_M4D(1.0f); HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvRotate(Matrix); HMM_Mat4 Inverse = HMM_InvRotate(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse); HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_NEAR(Result, Expect, 0.001f);
EXPECT_NEAR(Result.Elements[0][0], Expect.Elements[0][0], 0.001f);
EXPECT_NEAR(Result.Elements[0][1], Expect.Elements[0][1], 0.001f);
EXPECT_NEAR(Result.Elements[0][2], Expect.Elements[0][2], 0.001f);
EXPECT_NEAR(Result.Elements[0][3], Expect.Elements[0][3], 0.001f);
EXPECT_NEAR(Result.Elements[1][0], Expect.Elements[1][0], 0.001f);
EXPECT_NEAR(Result.Elements[1][1], Expect.Elements[1][1], 0.001f);
EXPECT_NEAR(Result.Elements[1][2], Expect.Elements[1][2], 0.001f);
EXPECT_NEAR(Result.Elements[1][3], Expect.Elements[1][3], 0.001f);
EXPECT_NEAR(Result.Elements[2][0], Expect.Elements[2][0], 0.001f);
EXPECT_NEAR(Result.Elements[2][1], Expect.Elements[2][1], 0.001f);
EXPECT_NEAR(Result.Elements[2][2], Expect.Elements[2][2], 0.001f);
EXPECT_NEAR(Result.Elements[2][3], Expect.Elements[2][3], 0.001f);
EXPECT_NEAR(Result.Elements[3][0], Expect.Elements[3][0], 0.001f);
EXPECT_NEAR(Result.Elements[3][1], Expect.Elements[3][1], 0.001f);
EXPECT_NEAR(Result.Elements[3][2], Expect.Elements[3][2], 0.001f);
EXPECT_NEAR(Result.Elements[3][3], Expect.Elements[3][3], 0.001f);
} }
{ {
HMM_Vec3 Scale = {1.0f, -1.0f, 0.5f}; HMM_Vec3 Axis = {1.0f, -1.0f, 0.5f};
HMM_Mat4 Matrix = HMM_Scale(Scale); HMM_Mat4 Matrix = HMM_Rotate_LH(HMM_AngleDeg(30), HMM_NormV3(Axis));
HMM_Mat4 Expect = HMM_M4D(1.0f); HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvScale(Matrix); HMM_Mat4 Inverse = HMM_InvRotate(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse); HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_NEAR(Result, Expect, 0.001f);
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]);
EXPECT_FLOAT_EQ(Result.Elements[0][3], Expect.Elements[0][3]);
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]);
EXPECT_FLOAT_EQ(Result.Elements[1][3], Expect.Elements[1][3]);
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]);
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]);
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]);
EXPECT_FLOAT_EQ(Result.Elements[2][3], Expect.Elements[2][3]);
EXPECT_FLOAT_EQ(Result.Elements[3][0], Expect.Elements[3][0]);
EXPECT_FLOAT_EQ(Result.Elements[3][1], Expect.Elements[3][1]);
EXPECT_FLOAT_EQ(Result.Elements[3][2], Expect.Elements[3][2]);
EXPECT_FLOAT_EQ(Result.Elements[3][3], Expect.Elements[3][3]);
} }
{ }
HMM_Vec3 Move = {1.0f, -1.0f, 0.5f};
HMM_Mat4 Matrix = HMM_Translate(Move); TEST(InvMatrix, InvScale)
HMM_Mat4 Expect = HMM_M4D(1.0f); {
HMM_Mat4 Inverse = HMM_InvTranslate(Matrix); HMM_Vec3 Scale = {1.0f, -1.0f, 0.5f};
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse); HMM_Mat4 Matrix = HMM_Scale(Scale);
HMM_Mat4 Expect = HMM_M4D(1.0f);
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]); HMM_Mat4 Inverse = HMM_InvScale(Matrix);
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]); HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]); EXPECT_M4_EQ(Result, Expect);
EXPECT_FLOAT_EQ(Result.Elements[0][3], Expect.Elements[0][3]); }
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]); TEST(InvMatrix, InvTranslate)
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]); {
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]); HMM_Vec3 Move = {1.0f, -1.0f, 0.5f};
EXPECT_FLOAT_EQ(Result.Elements[1][3], Expect.Elements[1][3]); HMM_Mat4 Matrix = HMM_Translate(Move);
HMM_Mat4 Expect = HMM_M4D(1.0f);
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]); HMM_Mat4 Inverse = HMM_InvTranslate(Matrix);
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]); HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]); EXPECT_M4_EQ(Result, Expect);
EXPECT_FLOAT_EQ(Result.Elements[2][3], Expect.Elements[2][3]);
EXPECT_FLOAT_EQ(Result.Elements[3][0], Expect.Elements[3][0]);
EXPECT_FLOAT_EQ(Result.Elements[3][1], Expect.Elements[3][1]);
EXPECT_FLOAT_EQ(Result.Elements[3][2], Expect.Elements[3][2]);
EXPECT_FLOAT_EQ(Result.Elements[3][3], Expect.Elements[3][3]);
}
} }

View File

@@ -10,12 +10,14 @@ TEST(Multiplication, Vec2Vec2)
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f); EXPECT_FLOAT_EQ(result.Y, 8.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec2 result = HMM_Mul(v2_1, v2_2); HMM_Vec2 result = HMM_Mul(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f); EXPECT_FLOAT_EQ(result.Y, 8.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec2 result = v2_1 * v2_2; HMM_Vec2 result = v2_1 * v2_2;
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
@@ -38,12 +40,14 @@ TEST(Multiplication, Vec2Scalar)
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec2 result = HMM_Mul(v2, s); HMM_Vec2 result = HMM_Mul(v2, s);
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec2 result = v2 * s; HMM_Vec2 result = v2 * s;
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
@@ -72,13 +76,15 @@ TEST(Multiplication, Vec3Vec3)
EXPECT_FLOAT_EQ(result.Y, 10.0f); EXPECT_FLOAT_EQ(result.Y, 10.0f);
EXPECT_FLOAT_EQ(result.Z, 18.0f); EXPECT_FLOAT_EQ(result.Z, 18.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec3 result = HMM_Mul(v3_1, v3_2); HMM_Vec3 result = HMM_Mul(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 4.0f); EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 10.0f); EXPECT_FLOAT_EQ(result.Y, 10.0f);
EXPECT_FLOAT_EQ(result.Z, 18.0f); EXPECT_FLOAT_EQ(result.Z, 18.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec3 result = v3_1 * v3_2; HMM_Vec3 result = v3_1 * v3_2;
EXPECT_FLOAT_EQ(result.X, 4.0f); EXPECT_FLOAT_EQ(result.X, 4.0f);
@@ -104,13 +110,15 @@ TEST(Multiplication, Vec3Scalar)
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f); EXPECT_FLOAT_EQ(result.Z, 9.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec3 result = HMM_Mul(v3, s); HMM_Vec3 result = HMM_Mul(v3, s);
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f); EXPECT_FLOAT_EQ(result.Z, 9.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec3 result = v3 * s; HMM_Vec3 result = v3 * s;
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
@@ -143,7 +151,7 @@ TEST(Multiplication, Vec4Vec4)
EXPECT_FLOAT_EQ(result.Z, 21.0f); EXPECT_FLOAT_EQ(result.Z, 21.0f);
EXPECT_FLOAT_EQ(result.W, 32.0f); EXPECT_FLOAT_EQ(result.W, 32.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec4 result = HMM_Mul(v4_1, v4_2); HMM_Vec4 result = HMM_Mul(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 5.0f); EXPECT_FLOAT_EQ(result.X, 5.0f);
@@ -151,6 +159,8 @@ TEST(Multiplication, Vec4Vec4)
EXPECT_FLOAT_EQ(result.Z, 21.0f); EXPECT_FLOAT_EQ(result.Z, 21.0f);
EXPECT_FLOAT_EQ(result.W, 32.0f); EXPECT_FLOAT_EQ(result.W, 32.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec4 result = v4_1 * v4_2; HMM_Vec4 result = v4_1 * v4_2;
EXPECT_FLOAT_EQ(result.X, 5.0f); EXPECT_FLOAT_EQ(result.X, 5.0f);
@@ -179,7 +189,7 @@ TEST(Multiplication, Vec4Scalar)
EXPECT_FLOAT_EQ(result.Z, 9.0f); EXPECT_FLOAT_EQ(result.Z, 9.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f); EXPECT_FLOAT_EQ(result.W, 12.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec4 result = HMM_Mul(v4, s); HMM_Vec4 result = HMM_Mul(v4, s);
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
@@ -187,6 +197,8 @@ TEST(Multiplication, Vec4Scalar)
EXPECT_FLOAT_EQ(result.Z, 9.0f); EXPECT_FLOAT_EQ(result.Z, 9.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f); EXPECT_FLOAT_EQ(result.W, 12.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec4 result = v4 * s; HMM_Vec4 result = v4 * s;
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
@@ -234,15 +246,17 @@ TEST(Multiplication, Mat2Mat2) {
EXPECT_FLOAT_EQ(result.Elements[1][1], 46.0f); EXPECT_FLOAT_EQ(result.Elements[1][1], 46.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat2 result = HMM_Mul(a,b); HMM_Mat2 result = HMM_Mul(a,b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 23.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 34.0f); EXPECT_FLOAT_EQ(result.Elements[0][1], 34.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 31.0f); EXPECT_FLOAT_EQ(result.Elements[1][0], 31.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 46.0f); EXPECT_FLOAT_EQ(result.Elements[1][1], 46.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat2 result = a * b; HMM_Mat2 result = a * b;
EXPECT_FLOAT_EQ(result.Elements[0][0], 23.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 23.0f);
@@ -271,7 +285,7 @@ TEST(Multiplication, Mat2Scalar) {
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f); EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f); EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat2 result = HMM_Mul(m, s); HMM_Mat2 result = HMM_Mul(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
@@ -279,6 +293,8 @@ TEST(Multiplication, Mat2Scalar) {
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f); EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f); EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat2 result = m * s; HMM_Mat2 result = m * s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
@@ -322,13 +338,15 @@ TEST(Multiplication, Mat2Vec2) {
EXPECT_FLOAT_EQ(result.Elements[1], 34.0f); EXPECT_FLOAT_EQ(result.Elements[1], 34.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec2 result = HMM_Mul(m, v); HMM_Vec2 result = HMM_Mul(m, v);
EXPECT_FLOAT_EQ(result.Elements[0], 23.0f); EXPECT_FLOAT_EQ(result.Elements[0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 34.0f); EXPECT_FLOAT_EQ(result.Elements[1], 34.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec2 result = m * v; HMM_Vec2 result = m * v;
EXPECT_FLOAT_EQ(result.Elements[0], 23.0f); EXPECT_FLOAT_EQ(result.Elements[0], 23.0f);
@@ -368,7 +386,7 @@ TEST(Multiplication, Mat3Mat3)
EXPECT_FLOAT_EQ(result.Elements[2][2], 312.0f); EXPECT_FLOAT_EQ(result.Elements[2][2], 312.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat3 result = HMM_Mul(a,b); HMM_Mat3 result = HMM_Mul(a,b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 138.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 138.0f);
@@ -381,7 +399,9 @@ TEST(Multiplication, Mat3Mat3)
EXPECT_FLOAT_EQ(result.Elements[2][1], 261.0f); EXPECT_FLOAT_EQ(result.Elements[2][1], 261.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 312.0f); EXPECT_FLOAT_EQ(result.Elements[2][2], 312.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat3 result = a * b; HMM_Mat3 result = a * b;
EXPECT_FLOAT_EQ(result.Elements[0][0], 138.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 138.0f);
@@ -420,7 +440,7 @@ TEST(Multiplication, Mat3Scalar) {
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f); EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f); EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat3 result = HMM_Mul(m, s); HMM_Mat3 result = HMM_Mul(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
@@ -433,6 +453,8 @@ TEST(Multiplication, Mat3Scalar) {
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f); EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f); EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat3 result = m * s; HMM_Mat3 result = m * s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
@@ -491,14 +513,15 @@ TEST(Multiplication, Mat3Vec3) {
EXPECT_FLOAT_EQ(result.Elements[1], 171.0f); EXPECT_FLOAT_EQ(result.Elements[1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[2], 204.0f); EXPECT_FLOAT_EQ(result.Elements[2], 204.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec3 result = HMM_Mul(m, v); HMM_Vec3 result = HMM_Mul(m, v);
EXPECT_FLOAT_EQ(result.Elements[0], 138.0f); EXPECT_FLOAT_EQ(result.Elements[0], 138.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 171.0f); EXPECT_FLOAT_EQ(result.Elements[1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[2], 204.0f); EXPECT_FLOAT_EQ(result.Elements[2], 204.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec3 result = m * v; HMM_Vec3 result = m * v;
EXPECT_FLOAT_EQ(result.Elements[0], 138.0f); EXPECT_FLOAT_EQ(result.Elements[0], 138.0f);
@@ -552,7 +575,7 @@ TEST(Multiplication, Mat4Mat4)
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f); EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f); EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat4 result = HMM_Mul(m4_1, m4_2); HMM_Mat4 result = HMM_Mul(m4_1, m4_2);
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
@@ -572,6 +595,8 @@ TEST(Multiplication, Mat4Mat4)
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f); EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f); EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat4 result = m4_1 * m4_2; HMM_Mat4 result = m4_1 * m4_2;
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
@@ -634,7 +659,7 @@ TEST(Multiplication, Mat4Scalar)
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f); EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f); EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat4 result = HMM_Mul(m4, s); HMM_Mat4 result = HMM_Mul(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
@@ -654,6 +679,8 @@ TEST(Multiplication, Mat4Scalar)
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f); EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f); EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat4 result = m4 * s; HMM_Mat4 result = m4 * s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
@@ -737,7 +764,7 @@ TEST(Multiplication, Mat4Vec4)
EXPECT_FLOAT_EQ(result.Z, 110.0f); EXPECT_FLOAT_EQ(result.Z, 110.0f);
EXPECT_FLOAT_EQ(result.W, 120.0f); EXPECT_FLOAT_EQ(result.W, 120.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec4 result = HMM_Mul(m4, v4); HMM_Vec4 result = HMM_Mul(m4, v4);
EXPECT_FLOAT_EQ(result.X, 90.0f); EXPECT_FLOAT_EQ(result.X, 90.0f);
@@ -745,6 +772,8 @@ TEST(Multiplication, Mat4Vec4)
EXPECT_FLOAT_EQ(result.Z, 110.0f); EXPECT_FLOAT_EQ(result.Z, 110.0f);
EXPECT_FLOAT_EQ(result.W, 120.0f); EXPECT_FLOAT_EQ(result.W, 120.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec4 result = m4 * v4; HMM_Vec4 result = m4 * v4;
EXPECT_FLOAT_EQ(result.X, 90.0f); EXPECT_FLOAT_EQ(result.X, 90.0f);
@@ -769,7 +798,7 @@ TEST(Multiplication, QuaternionQuaternion)
EXPECT_FLOAT_EQ(result.Z, 48.0f); EXPECT_FLOAT_EQ(result.Z, 48.0f);
EXPECT_FLOAT_EQ(result.W, -6.0f); EXPECT_FLOAT_EQ(result.W, -6.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Quat result = HMM_Mul(q1, q2); HMM_Quat result = HMM_Mul(q1, q2);
EXPECT_FLOAT_EQ(result.X, 24.0f); EXPECT_FLOAT_EQ(result.X, 24.0f);
@@ -777,6 +806,8 @@ TEST(Multiplication, QuaternionQuaternion)
EXPECT_FLOAT_EQ(result.Z, 48.0f); EXPECT_FLOAT_EQ(result.Z, 48.0f);
EXPECT_FLOAT_EQ(result.W, -6.0f); EXPECT_FLOAT_EQ(result.W, -6.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Quat result = q1 * q2; HMM_Quat result = q1 * q2;
EXPECT_FLOAT_EQ(result.X, 24.0f); EXPECT_FLOAT_EQ(result.X, 24.0f);
@@ -803,7 +834,7 @@ TEST(Multiplication, QuaternionScalar)
EXPECT_FLOAT_EQ(result.Z, 6.0f); EXPECT_FLOAT_EQ(result.Z, 6.0f);
EXPECT_FLOAT_EQ(result.W, 8.0f); EXPECT_FLOAT_EQ(result.W, 8.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Quat result = HMM_Mul(q, f); HMM_Quat result = HMM_Mul(q, f);
EXPECT_FLOAT_EQ(result.X, 2.0f); EXPECT_FLOAT_EQ(result.X, 2.0f);
@@ -811,6 +842,8 @@ TEST(Multiplication, QuaternionScalar)
EXPECT_FLOAT_EQ(result.Z, 6.0f); EXPECT_FLOAT_EQ(result.Z, 6.0f);
EXPECT_FLOAT_EQ(result.W, 8.0f); EXPECT_FLOAT_EQ(result.W, 8.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Quat result = q * f; HMM_Quat result = q * f;
EXPECT_FLOAT_EQ(result.X, 2.0f); EXPECT_FLOAT_EQ(result.X, 2.0f);

View File

@@ -2,67 +2,84 @@
TEST(Projection, Orthographic) TEST(Projection, Orthographic)
{ {
#define ORTHO_BOUNDS -8.0f, 12.0f, 5.0f, 10.0f, 1.0f, 100.0f
// Right-handed
{ {
HMM_Mat4 projection = HMM_Orthographic_RH_NO(-10.0f, 10.0f, -5.0f, 5.0f, 1.0f, 10.0f); // Near and far distances correspond to negative Z, hence the Z coordinates here are negative.
HMM_Vec4 original = HMM_V4(5.0f, 5.0f, -1.0f, 1.0); HMM_Vec4 minCorner = HMM_V4(-8.0f, 5.0f, -1.0f, 1.0);
HMM_Vec4 projected = HMM_MulM4V4(projection, original); HMM_Vec4 maxCorner = HMM_V4(12.0f, 10.0f, -100.0f, 1.0);
EXPECT_FLOAT_EQ(projected.X, 0.5f); // Z from -1 to 1 (GL convention)
EXPECT_FLOAT_EQ(projected.Y, 1.0f); {
EXPECT_FLOAT_EQ(projected.Z, -1.0f); HMM_Mat4 projection = HMM_Orthographic_RH_NO(ORTHO_BOUNDS);
EXPECT_FLOAT_EQ(projected.W, 1.0f); EXPECT_V4_EQ(HMM_MulM4V4(projection, minCorner), HMM_V4(-1.0f, -1.0f, -1.0f, 1.0f));
EXPECT_V4_EQ(HMM_MulM4V4(projection, maxCorner), HMM_V4(1.0f, 1.0f, 1.0f, 1.0f));
}
/* Z0 */ // Z from 0 to 1 (DX convention)
projection = HMM_Orthographic_RH_ZO(-10.0f, 10.0f, -5.0f, 5.0f, 1.0f, -10.0f); {
projected = HMM_MulM4V4(projection, original); HMM_Mat4 projection = HMM_Orthographic_RH_ZO(ORTHO_BOUNDS);
EXPECT_FLOAT_EQ(projected.Z, 0.0f); EXPECT_V4_EQ(HMM_MulM4V4(projection, minCorner), HMM_V4(-1.0f, -1.0f, 0.0f, 1.0f));
EXPECT_V4_EQ(HMM_MulM4V4(projection, maxCorner), HMM_V4(1.0f, 1.0f, 1.0f, 1.0f));
}
} }
{
HMM_Mat4 projection = HMM_Orthographic_LH_NO(-10.0f, 10.0f, -5.0f, 5.0f, 1.0f, -10.0f);
HMM_Vec4 original = HMM_V4(5.0f, 5.0f, 1.0f, 1.0);
HMM_Vec4 projected = HMM_MulM4V4(projection, original);
EXPECT_FLOAT_EQ(projected.X, 0.5f);
EXPECT_FLOAT_EQ(projected.Y, 1.0f);
EXPECT_FLOAT_EQ(projected.Z, -1.0f);
EXPECT_FLOAT_EQ(projected.W, 1.0f);
/* Z0 */ // Left-handed
projection = HMM_Orthographic_LH_ZO(-10.0f, 10.0f, -5.0f, 5.0f, 1.0f, -10.0f); {
projected = HMM_MulM4V4(projection, original); // Near and far distances correspond to positive Z, hence the Z coordinates here are positive.
EXPECT_FLOAT_EQ(projected.Z, 0.0f); HMM_Vec4 minCorner = HMM_V4(-8.0f, 5.0f, 1.0f, 1.0);
HMM_Vec4 maxCorner = HMM_V4(12.0f, 10.0f, 100.0f, 1.0);
// Z from -1 to 1 (GL convention)
{
HMM_Mat4 projection = HMM_Orthographic_LH_NO(ORTHO_BOUNDS);
EXPECT_V4_EQ(HMM_MulM4V4(projection, minCorner), HMM_V4(-1.0f, -1.0f, -1.0f, 1.0f));
EXPECT_V4_EQ(HMM_MulM4V4(projection, maxCorner), HMM_V4(1.0f, 1.0f, 1.0f, 1.0f));
}
// Z from 0 to 1 (DX convention)
{
HMM_Mat4 projection = HMM_Orthographic_LH_ZO(ORTHO_BOUNDS);
EXPECT_V4_EQ(HMM_MulM4V4(projection, minCorner), HMM_V4(-1.0f, -1.0f, 0.0f, 1.0f));
EXPECT_V4_EQ(HMM_MulM4V4(projection, maxCorner), HMM_V4(1.0f, 1.0f, 1.0f, 1.0f));
}
} }
} }
TEST(Projection, Perspective) TEST(Projection, Perspective)
{ {
// Right-handed
{ {
HMM_Mat4 projection = HMM_Perspective_RH_NO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f); // Z from -1 to 1 (GL convention)
HMM_Vec4 original = HMM_V4(5.0f, 5.0f, -1.0f, 1.0f); {
HMM_Vec4 projected = HMM_MulM4V4(projection, original); HMM_Mat4 projection = HMM_Perspective_RH_NO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f);
EXPECT_FLOAT_EQ(projected.X, 2.5f); HMM_Vec4 original = HMM_V4(5.0f, 5.0f, -1.0f, 1.0f);
EXPECT_FLOAT_EQ(projected.Y, 5.0f); EXPECT_V4_EQ(HMM_MulM4V4(projection, original), HMM_V4(2.5f, 5.0f, -1.0f, 1.0f));
EXPECT_FLOAT_EQ(projected.Z, -1.0f); }
EXPECT_FLOAT_EQ(projected.W, 1.0f);
/* ZO */ // Z from 0 to 1 (DX convention)
projection = HMM_Perspective_RH_ZO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f); {
projected = HMM_MulM4V4(projection, original); HMM_Mat4 projection = HMM_Perspective_RH_ZO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f);
EXPECT_FLOAT_EQ(projected.Z, 0.0f); HMM_Vec4 original = HMM_V4(5.0f, 5.0f, -1.0f, 1.0f);
EXPECT_V4_EQ(HMM_MulM4V4(projection, original), HMM_V4(2.5f, 5.0f, 0.0f, 1.0f));
}
} }
// Left-handed
{ {
HMM_Mat4 projection = HMM_Perspective_LH_NO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f); // Z from -1 to 1 (GL convention)
HMM_Vec4 original = HMM_V4(5.0f, 5.0f, 1.0f, 1.0f); {
HMM_Vec4 projected = HMM_MulM4V4(projection, original); HMM_Mat4 projection = HMM_Perspective_LH_NO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f);
EXPECT_FLOAT_EQ(projected.X, 2.5f); HMM_Vec4 original = HMM_V4(5.0f, 5.0f, 1.0f, 1.0f);
EXPECT_FLOAT_EQ(projected.Y, 5.0f); EXPECT_V4_EQ(HMM_MulM4V4(projection, original), HMM_V4(2.5f, 5.0f, -1.0f, 1.0f));
EXPECT_FLOAT_EQ(projected.Z, -1.0f); }
EXPECT_FLOAT_EQ(projected.W, 1.0f);
// Z from 0 to 1 (DX convention)
/* ZO */ {
projection = HMM_Perspective_LH_ZO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f); HMM_Mat4 projection = HMM_Perspective_LH_ZO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f);
projected = HMM_MulM4V4(projection, original); HMM_Vec4 original = HMM_V4(5.0f, 5.0f, 1.0f, 1.0f);
EXPECT_FLOAT_EQ(projected.Z, 0.0f); EXPECT_V4_EQ(HMM_MulM4V4(projection, original), HMM_V4(2.5f, 5.0f, 0.0f, 1.0f));
}
} }
} }

View File

@@ -22,7 +22,7 @@ TEST(QuaternionOps, Dot)
float result = HMM_DotQ(q1, q2); float result = HMM_DotQ(q1, q2);
EXPECT_FLOAT_EQ(result, 70.0f); EXPECT_FLOAT_EQ(result, 70.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
float result = HMM_Dot(q1, q2); float result = HMM_Dot(q1, q2);
EXPECT_FLOAT_EQ(result, 70.0f); EXPECT_FLOAT_EQ(result, 70.0f);
@@ -41,7 +41,7 @@ TEST(QuaternionOps, Normalize)
EXPECT_NEAR(result.Z, 0.5477225575f, 0.001f); EXPECT_NEAR(result.Z, 0.5477225575f, 0.001f);
EXPECT_NEAR(result.W, 0.7302967433f, 0.001f); EXPECT_NEAR(result.W, 0.7302967433f, 0.001f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Quat result = HMM_Norm(q); HMM_Quat result = HMM_Norm(q);
EXPECT_NEAR(result.X, 0.1825741858f, 0.001f); EXPECT_NEAR(result.X, 0.1825741858f, 0.001f);
@@ -97,7 +97,7 @@ TEST(QuaternionOps, SLerp)
EXPECT_NEAR(result.Z, -0.40824830f, 0.001f); EXPECT_NEAR(result.Z, -0.40824830f, 0.001f);
EXPECT_NEAR(result.W, 0.70710676f, 0.001f); EXPECT_NEAR(result.W, 0.70710676f, 0.001f);
} }
{ {
HMM_Quat result = HMM_SLerp(from, 1.0f, to); HMM_Quat result = HMM_SLerp(from, 1.0f, to);
EXPECT_NEAR(result.X, 0.5f, 0.001f); EXPECT_NEAR(result.X, 0.5f, 0.001f);
EXPECT_NEAR(result.Y, 0.5f, 0.001f); EXPECT_NEAR(result.Y, 0.5f, 0.001f);
@@ -254,23 +254,44 @@ TEST(QuaternionOps, Mat4ToQuat)
} }
} }
TEST(QuaternionOps, FromAxisAngle) TEST(QuaternionOps, RotateVectorAxisAngle)
{ {
HMM_Vec3 axis = HMM_V3(1.0f, 0.0f, 0.0f);
float angle = HMM_PI32 / 2.0f;
{ {
HMM_Quat result = HMM_QFromAxisAngle_RH(axis, angle); HMM_Vec3 axis = HMM_V3(0.0f, 1.0f, 0.0f);
EXPECT_NEAR(result.X, 0.707107f, 0.001f); float angle = HMM_AngleTurn(1.0/4);
HMM_Vec3 result = HMM_RotateV3AxisAngle_LH(HMM_V3(1.0f, 0.0f, 0.0f), axis, angle);
EXPECT_NEAR(result.X, 0.0f, 0.001f);
EXPECT_NEAR(result.Y, 0.0f, 0.001f); EXPECT_NEAR(result.Y, 0.0f, 0.001f);
EXPECT_NEAR(result.Z, 0.0f, 0.001f); EXPECT_NEAR(result.Z, 1.0f, 0.001f);
EXPECT_NEAR(result.W, 0.707107f, 0.001f);
} }
{ {
HMM_Quat result = HMM_QFromAxisAngle_LH(axis, angle); HMM_Vec3 axis = HMM_V3(1.0f, 0.0f, 0.0f);
EXPECT_NEAR(result.X, -0.707107f, 0.001f); float angle = HMM_AngleTurn(1.0/8);
EXPECT_NEAR(result.Y, 0.0f, 0.001f); HMM_Vec3 result = HMM_RotateV3AxisAngle_RH(HMM_V3(0.0f, 0.0f, 1.0f), axis, angle);
EXPECT_NEAR(result.Z, 0.0f, 0.001f); EXPECT_NEAR(result.X, 0.0f, 0.001f);
EXPECT_NEAR(result.W, 0.707107f, 0.001f); EXPECT_NEAR(result.Y, -0.707170f, 0.001f);
EXPECT_NEAR(result.Z, 0.707170f, 0.001f);
}
}
TEST(QuaternionOps, QuatFromPairs)
{
{
HMM_Vec3 n1 = HMM_V3(0.0f, 1.0f, 0.0f);
HMM_Vec3 n2 = HMM_V3(0.0f, 0.0f, 1.0f);
HMM_Quat q = HMM_QFromNormPair(n1, n2);
HMM_Vec3 result = HMM_RotateV3Q(n1, q);
EXPECT_NEAR(result.X, n2.X, 0.001f);
EXPECT_NEAR(result.Y, n2.Y, 0.001f);
EXPECT_NEAR(result.Z, n2.Z, 0.001f);
}
{
HMM_Vec3 v1 = HMM_V3(2.0f, 2.0f, 2.0f);
HMM_Vec3 v2 = HMM_V3(3.0f, 0.0f, 0.0f);
HMM_Quat q = HMM_QFromVecPair(v1, v2);
HMM_Vec3 result = HMM_RotateV3Q(HMM_V3(0.0f, 1.0f, 0.0f), q);
EXPECT_NEAR(result.X, 0.577350, 0.001f);
EXPECT_NEAR(result.Y, 0.788675, 0.001f);
EXPECT_NEAR(result.Z, -0.211325, 0.001f);
} }
} }

View File

@@ -10,12 +10,14 @@ TEST(Subtraction, Vec2)
EXPECT_FLOAT_EQ(result.X, -2.0f); EXPECT_FLOAT_EQ(result.X, -2.0f);
EXPECT_FLOAT_EQ(result.Y, -2.0f); EXPECT_FLOAT_EQ(result.Y, -2.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec2 result = HMM_Sub(v2_1, v2_2); HMM_Vec2 result = HMM_Sub(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, -2.0f); EXPECT_FLOAT_EQ(result.X, -2.0f);
EXPECT_FLOAT_EQ(result.Y, -2.0f); EXPECT_FLOAT_EQ(result.Y, -2.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec2 result = v2_1 - v2_2; HMM_Vec2 result = v2_1 - v2_2;
EXPECT_FLOAT_EQ(result.X, -2.0f); EXPECT_FLOAT_EQ(result.X, -2.0f);
@@ -39,13 +41,15 @@ TEST(Subtraction, Vec3)
EXPECT_FLOAT_EQ(result.Y, -3.0f); EXPECT_FLOAT_EQ(result.Y, -3.0f);
EXPECT_FLOAT_EQ(result.Z, -3.0f); EXPECT_FLOAT_EQ(result.Z, -3.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec3 result = HMM_Sub(v3_1, v3_2); HMM_Vec3 result = HMM_Sub(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, -3.0f); EXPECT_FLOAT_EQ(result.X, -3.0f);
EXPECT_FLOAT_EQ(result.Y, -3.0f); EXPECT_FLOAT_EQ(result.Y, -3.0f);
EXPECT_FLOAT_EQ(result.Z, -3.0f); EXPECT_FLOAT_EQ(result.Z, -3.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec3 result = v3_1 - v3_2; HMM_Vec3 result = v3_1 - v3_2;
EXPECT_FLOAT_EQ(result.X, -3.0f); EXPECT_FLOAT_EQ(result.X, -3.0f);
@@ -72,7 +76,7 @@ TEST(Subtraction, Vec4)
EXPECT_FLOAT_EQ(result.Z, -4.0f); EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f); EXPECT_FLOAT_EQ(result.W, -4.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec4 result = HMM_Sub(v4_1, v4_2); HMM_Vec4 result = HMM_Sub(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, -4.0f); EXPECT_FLOAT_EQ(result.X, -4.0f);
@@ -80,6 +84,8 @@ TEST(Subtraction, Vec4)
EXPECT_FLOAT_EQ(result.Z, -4.0f); EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f); EXPECT_FLOAT_EQ(result.W, -4.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Vec4 result = v4_1 - v4_2; HMM_Vec4 result = v4_1 - v4_2;
EXPECT_FLOAT_EQ(result.X, -4.0f); EXPECT_FLOAT_EQ(result.X, -4.0f);
@@ -124,7 +130,7 @@ TEST(Subtraction, Mat2)
EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0); EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0); EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat2 result = HMM_Sub(b,a); HMM_Mat2 result = HMM_Sub(b,a);
EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0); EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0);
@@ -132,7 +138,8 @@ TEST(Subtraction, Mat2)
EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0); EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0); EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat2 result = b - a; HMM_Mat2 result = b - a;
EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0); EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0);
@@ -183,7 +190,7 @@ TEST(Subtraction, Mat3)
EXPECT_FLOAT_EQ(result.Elements[2][1], 9.0); EXPECT_FLOAT_EQ(result.Elements[2][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][2], 9.0); EXPECT_FLOAT_EQ(result.Elements[2][2], 9.0);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat3 result = HMM_Sub(b,a); HMM_Mat3 result = HMM_Sub(b,a);
EXPECT_FLOAT_EQ(result.Elements[0][0], 9.0); EXPECT_FLOAT_EQ(result.Elements[0][0], 9.0);
@@ -196,7 +203,9 @@ TEST(Subtraction, Mat3)
EXPECT_FLOAT_EQ(result.Elements[2][1], 9.0); EXPECT_FLOAT_EQ(result.Elements[2][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][2], 9.0); EXPECT_FLOAT_EQ(result.Elements[2][2], 9.0);
} }
#endif
#ifdef __cplusplus
b -= a; b -= a;
EXPECT_FLOAT_EQ(b.Elements[0][0], 9.0); EXPECT_FLOAT_EQ(b.Elements[0][0], 9.0);
EXPECT_FLOAT_EQ(b.Elements[0][1], 9.0); EXPECT_FLOAT_EQ(b.Elements[0][1], 9.0);
@@ -245,7 +254,7 @@ TEST(Subtraction, Mat4)
} }
} }
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Mat4 result = HMM_Sub(m4_1, m4_2); HMM_Mat4 result = HMM_Sub(m4_1, m4_2);
for (int Column = 0; Column < 4; ++Column) for (int Column = 0; Column < 4; ++Column)
@@ -256,6 +265,8 @@ TEST(Subtraction, Mat4)
} }
} }
} }
#endif
#ifdef __cplusplus
{ {
HMM_Mat4 result = m4_1 - m4_2; HMM_Mat4 result = m4_1 - m4_2;
for (int Column = 0; Column < 4; ++Column) for (int Column = 0; Column < 4; ++Column)
@@ -290,7 +301,7 @@ TEST(Subtraction, Quaternion)
EXPECT_FLOAT_EQ(result.Z, -4.0f); EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f); EXPECT_FLOAT_EQ(result.W, -4.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Quat result = HMM_Sub(q1, q2); HMM_Quat result = HMM_Sub(q1, q2);
EXPECT_FLOAT_EQ(result.X, -4.0f); EXPECT_FLOAT_EQ(result.X, -4.0f);
@@ -298,6 +309,8 @@ TEST(Subtraction, Quaternion)
EXPECT_FLOAT_EQ(result.Z, -4.0f); EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f); EXPECT_FLOAT_EQ(result.W, -4.0f);
} }
#endif
#ifdef __cplusplus
{ {
HMM_Quat result = q1 - q2; HMM_Quat result = q1 - q2;
EXPECT_FLOAT_EQ(result.X, -4.0f); EXPECT_FLOAT_EQ(result.X, -4.0f);

View File

@@ -63,7 +63,8 @@ TEST(Transformations, LookAt)
{ {
const float abs_error = 0.001f; const float abs_error = 0.001f;
{ HMM_Mat4 result = HMM_LookAt_RH(HMM_V3(1.0f, 0.0f, 0.0f), HMM_V3(0.0f, 2.0f, 1.0f), HMM_V3(2.0f, 1.0f, 1.0f)); {
HMM_Mat4 result = HMM_LookAt_RH(HMM_V3(1.0f, 0.0f, 0.0f), HMM_V3(0.0f, 2.0f, 1.0f), HMM_V3(2.0f, 1.0f, 1.0f));
EXPECT_NEAR(result.Elements[0][0], 0.169031f, abs_error); EXPECT_NEAR(result.Elements[0][0], 0.169031f, abs_error);
EXPECT_NEAR(result.Elements[0][1], 0.897085f, abs_error); EXPECT_NEAR(result.Elements[0][1], 0.897085f, abs_error);
@@ -103,3 +104,30 @@ TEST(Transformations, LookAt)
EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error); EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error);
} }
} }
TEST(Transformations, RotateV2)
{
HMM_Vec2 v2 = HMM_V2(1, 2);
float epsilon = 0.000001f;
{
HMM_Vec2 res = HMM_RotateV2(v2, HMM_AngleDeg(90));
EXPECT_NEAR(res.X, -2.0f, epsilon);
EXPECT_NEAR(res.Y, 1.0f, epsilon);
}
{
HMM_Vec2 res = HMM_RotateV2(v2, HMM_AngleDeg(180));
EXPECT_NEAR(res.X, -1.0f, epsilon);
EXPECT_NEAR(res.Y, -2.0f, epsilon);
}
{
HMM_Vec2 res = HMM_RotateV2(v2, HMM_AngleDeg(270));
EXPECT_NEAR(res.X, 2.0f, epsilon);
EXPECT_NEAR(res.Y, -1.0f, epsilon);
}
{
HMM_Vec2 res = HMM_RotateV2(v2, HMM_AngleDeg(360));
EXPECT_NEAR(res.X, 1.0f, epsilon);
EXPECT_NEAR(res.Y, 2.0f, epsilon);
}
}

View File

@@ -10,7 +10,7 @@ TEST(VectorOps, LengthSquared)
EXPECT_FLOAT_EQ(HMM_LenSqrV3(v3), 14.0f); EXPECT_FLOAT_EQ(HMM_LenSqrV3(v3), 14.0f);
EXPECT_FLOAT_EQ(HMM_LenSqrV4(v4), 15.0f); EXPECT_FLOAT_EQ(HMM_LenSqrV4(v4), 15.0f);
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_LenSqr(v2), 5.0f); EXPECT_FLOAT_EQ(HMM_LenSqr(v2), 5.0f);
EXPECT_FLOAT_EQ(HMM_LenSqr(v3), 14.0f); EXPECT_FLOAT_EQ(HMM_LenSqr(v3), 14.0f);
EXPECT_FLOAT_EQ(HMM_LenSqr(v4), 15.0f); EXPECT_FLOAT_EQ(HMM_LenSqr(v4), 15.0f);
@@ -27,7 +27,7 @@ TEST(VectorOps, Length)
EXPECT_FLOAT_EQ(HMM_LenV3(v3), 7.0f); EXPECT_FLOAT_EQ(HMM_LenV3(v3), 7.0f);
EXPECT_FLOAT_EQ(HMM_LenV4(v4), 13.892444f); EXPECT_FLOAT_EQ(HMM_LenV4(v4), 13.892444f);
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_Len(v2), 9.0553856f); EXPECT_FLOAT_EQ(HMM_Len(v2), 9.0553856f);
EXPECT_FLOAT_EQ(HMM_Len(v3), 7.0f); EXPECT_FLOAT_EQ(HMM_Len(v3), 7.0f);
EXPECT_FLOAT_EQ(HMM_Len(v4), 13.892444f); EXPECT_FLOAT_EQ(HMM_Len(v4), 13.892444f);
@@ -62,7 +62,7 @@ TEST(VectorOps, Normalize)
EXPECT_LT(result.W, 0.0f); EXPECT_LT(result.W, 0.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec2 result = HMM_Norm(v2); HMM_Vec2 result = HMM_Norm(v2);
EXPECT_NEAR(HMM_LenV2(result), 1.0f, 0.001f); EXPECT_NEAR(HMM_LenV2(result), 1.0f, 0.001f);
@@ -112,7 +112,7 @@ TEST(VectorOps, NormalizeZero)
EXPECT_FLOAT_EQ(result.W, 0.0f); EXPECT_FLOAT_EQ(result.W, 0.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec2 result = HMM_Norm(v2); HMM_Vec2 result = HMM_Norm(v2);
EXPECT_FLOAT_EQ(result.X, 0.0f); EXPECT_FLOAT_EQ(result.X, 0.0f);
@@ -152,7 +152,7 @@ TEST(VectorOps, DotVec2)
HMM_Vec2 v2 = HMM_V2(3.0f, 4.0f); HMM_Vec2 v2 = HMM_V2(3.0f, 4.0f);
EXPECT_FLOAT_EQ(HMM_DotV2(v1, v2), 11.0f); EXPECT_FLOAT_EQ(HMM_DotV2(v1, v2), 11.0f);
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 11.0f); EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 11.0f);
#endif #endif
} }
@@ -163,7 +163,7 @@ TEST(VectorOps, DotVec3)
HMM_Vec3 v2 = HMM_V3(4.0f, 5.0f, 6.0f); HMM_Vec3 v2 = HMM_V3(4.0f, 5.0f, 6.0f);
EXPECT_FLOAT_EQ(HMM_DotV3(v1, v2), 32.0f); EXPECT_FLOAT_EQ(HMM_DotV3(v1, v2), 32.0f);
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 32.0f); EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 32.0f);
#endif #endif
} }
@@ -174,7 +174,7 @@ TEST(VectorOps, DotVec4)
HMM_Vec4 v2 = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f); HMM_Vec4 v2 = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f);
EXPECT_FLOAT_EQ(HMM_DotV4(v1, v2), 70.0f); EXPECT_FLOAT_EQ(HMM_DotV4(v1, v2), 70.0f);
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 70.0f); EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 70.0f);
#endif #endif
} }
@@ -189,7 +189,7 @@ TEST(VectorOps, LerpV2)
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.5f); EXPECT_FLOAT_EQ(result.Y, 0.5f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec2 result = HMM_Lerp(v1, 0.5, v2); HMM_Vec2 result = HMM_Lerp(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -209,7 +209,7 @@ TEST(VectorOps, LerpV3)
EXPECT_FLOAT_EQ(result.Y, 1.0f); EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 0.5f); EXPECT_FLOAT_EQ(result.Z, 0.5f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec3 result = HMM_Lerp(v1, 0.5, v2); HMM_Vec3 result = HMM_Lerp(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -231,7 +231,7 @@ TEST(VectorOps, LerpV4)
EXPECT_FLOAT_EQ(result.Z, 0.5f); EXPECT_FLOAT_EQ(result.Z, 0.5f);
EXPECT_FLOAT_EQ(result.W, 1.0f); EXPECT_FLOAT_EQ(result.W, 1.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
HMM_Vec4 result = HMM_Lerp(v1, 0.5, v2); HMM_Vec4 result = HMM_Lerp(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);

View File

@@ -3,16 +3,25 @@
if not exist "build" mkdir build if not exist "build" mkdir build
pushd build pushd build
clang-cl /Fehmm_test_c.exe ..\HandmadeMath.c ..\hmm_test.c clang-cl /std:c11 /Fehmm_test_c11.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c hmm_test_c11 || exit /b 1
clang-cl /Fehmm_test_c_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.c ..\hmm_test.c clang-cl /std:c11 /Fehmm_test_c11_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c_no_sse hmm_test_c11_no_simd || exit /b 1
clang-cl /Fehmm_test_cpp.exe ..\HandmadeMath.cpp ..\hmm_test.cpp clang-cl /std:c17 /Fehmm_test_c17.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_cpp hmm_test_c17 || exit /b 1
clang-cl /Fehmm_test_cpp_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.cpp ..\hmm_test.cpp clang-cl /std:c++14 /Fehmm_test_cpp14.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp_no_sse hmm_test_cpp14 || exit /b 1
clang-cl /std:c++14 /Fehmm_test_cpp14_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp14_no_simd || exit /b 1
clang-cl /std:c++17 /Fehmm_test_cpp17.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp17 || exit /b 1
clang-cl /std:c++20 /Fehmm_test_cpp20.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp20 || exit /b 1
popd popd

View File

@@ -1,27 +1,32 @@
@echo off @echo off
if "%1%"=="travis" ( where /q cl
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools\VsDevCmd.bat" -host_arch=amd64 -arch=amd64 if ERRORLEVEL 1 (
) else ( for /f "delims=" %%a in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -find VC\Auxiliary\Build\vcvarsall.bat') do (%%a x64)
where /q cl
if ERRORLEVEL 1 (
for /f "delims=" %%a in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -find VC\Auxiliary\Build\vcvarsall.bat') do (%%a x64)
)
) )
if not exist "build" mkdir build if not exist "build" mkdir build
pushd build pushd build
cl /Fehmm_test_c.exe ..\HandmadeMath.c ..\hmm_test.c cl /std:c11 /Fehmm_test_c11.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c hmm_test_c11 || exit /b 1
cl /Fehmm_test_c_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.c ..\hmm_test.c cl /std:c11 /Fehmm_test_c11_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c_no_sse hmm_test_c11_no_simd || exit /b 1
cl /Fehmm_test_cpp.exe ..\HandmadeMath.cpp ..\hmm_test.cpp cl /std:c17 /Fehmm_test_c17.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_cpp hmm_test_c17 || exit /b 1
cl /Fehmm_test_cpp_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.cpp ..\hmm_test.cpp cl /std:c++14 /Fehmm_test_cpp14.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp_no_sse hmm_test_cpp14 || exit /b 1
cl /std:c++14 /Fehmm_test_cpp14_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp14_no_simd || exit /b 1
cl /std:c++17 /Fehmm_test_cpp17.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp17 || exit /b 1
cl /std:c++20 /Fehmm_test_cpp20.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp20 || exit /b 1
popd popd