Compare commits

..

6 Commits

29 changed files with 2785 additions and 6221 deletions

View File

@@ -1,34 +0,0 @@
name: CI
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
test:
name: Test on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v3
- uses: TheMrMilchmann/setup-msvc-dev@v2
with:
arch: x64
if: matrix.os == 'windows-latest'
- name: Test (Windows, MSVC)
run: ./run_test_msvc.bat
working-directory: ./test
if: matrix.os == 'windows-latest'
- name: Test (Windows, clang)
run: ./run_test_clang.bat
working-directory: ./test
if: matrix.os == 'windows-latest'
- name: Test (${{ matrix.os }})
run: make all
working-directory: ./test
if: matrix.os != 'windows-latest'

0
.gitmodules vendored Normal file
View File

12
.travis.yml Normal file
View File

@@ -0,0 +1,12 @@
language: cpp
compiler:
- clang
- gcc
install:
- cd test
- make
script:
- build/hmm_test_c
- build/hmm_test_c_no_sse
- build/hmm_test_cpp
- build/hmm_test_cpp_no_sse

43
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,43 @@
# Understanding the structure of Handmade Math
Most of the functions in Handmade Math are very short, and are the kind of functions you want to have inlined. Because of this, most functions in Handmade Math are defined with `HINLINE`, which is defined as `static inline`.
The exceptions are functions like `HMM_Rotate`, which are long enough that it doesn't make sense to inline them. These functions are defined with an `HEXTERN` prototype, and implemented in the `#ifdef HANDMADE_MATH_IMPLEMENTATION` block.
# Quick style guide
* Put braces on a new line
* Float literals should have digits both before and after the decimal.
```cpp
// Good
0.0f;
0.5f;
1.0f;
3.14159f;
// Bad
1.f
.0f
```
* Put parentheses around the returned value:
```cpp
HINLINE float
HMM_MyFunction()
{
return (1.0f);
}
```
## Other style notes
* If a new function is defined with different names for different datatypes, also add C++ overloaded versions of the functions. For example, if you have `HMM_LengthVec2(hmm_vec2)` and `HMM_LengthVec3(hmm_vec3)`, also provide `HMM_Length(hmm_vec2)` and `HMM_Length(hmm_vec3)`.
It is fine for the overloaded versions to call the C versions.
* Only use operator overloading for analogous operators in C. That means `+` for vector addition is fine, but no using `^` for cross product or `|` for dot product.
* Try to define functions in the same order as the prototypes.
* Don't forget that Handmade Math uses column-major order for matrices!
# Versioning
We use [semantic versioning](http://semver.org/) because it's reasonable.

File diff suppressed because it is too large Load Diff

View File

@@ -1,43 +1,48 @@
# Handmade Math
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.
[![Build Status](https://travis-ci.org/HandmadeMath/Handmade-Math.svg?branch=master)](https://travis-ci.org/StrangeZak/Handmade-Math)
To get started, go download [the latest release](https://github.com/HandmadeMath/HandmadeMath/releases).
A single-file, cross-platform, public domain game math library for C/C++.
> If you are upgrading to Handmade Math 2.0, save yourself some time and use our [automatic update tool](./update).
To get started, go download [the latest release](https://github.com/HandmadeMath/Handmade-Math/releases).
Here's what sets Handmade Math apart:
-----
- **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 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`.
- **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
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.
Version | Changes |
----------------|----------------|
**1.6.0** | Added array subscript operators for vector and matrix types in C++. This is provided as a convenience, but be aware that it may incur an extra function call in unoptimized builds.
**1.5.1** | Fixed a bug with uninitialized elements in HMM_LookAt.
**1.5.0** | Changed internal structure for better performance and inlining. As a result, `HANDMADE_MATH_NO_INLINE` has been removed and no longer has any effect.
**1.4.0** | Fixed bug when using C mode. SSE'd all vec4 operations. Removed zeroing for better performance.
**1.3.0** | Removed need to `#define HANDMADE_MATH_CPP_MODE`. C++ definitions are now included automatically in C++ environments.
**1.2.0** | Added equality functions for `HMM_Vec2`, `HMM_Vec3`, and `HMM_Vec4`, and SSE'd `HMM_MultiplyMat4` and `HMM_Transpose`.
**1.1.5** | Added `Width` and `Height` to `HMM_Vec2`, and made it so you can supply your own `SqrtF`.
**1.1.4** | Fixed SSE being included on platforms that don't support it, and fixed divide-by-zero errors when normalizing zero vectors.
**1.1.3** | Fixed compile error in C mode
**1.1.2** | Fixed invalid HMMDEF's in the function definitions
**1.1.1** | Resolved compiler warnings on gcc and g++
**1.1** | Quaternions! |
**1.0** | Lots of testing |
**0.7** | Added HMM_Vec2, and HMM_Vec4 versions of HMM_LengthSquared, HMM_Length, and HMM_Normalize. |
**0.6** | Made HMM_Power faster, Fixed possible efficiency problem with HMM_Normalize, RENAMED HMM_LengthSquareRoot to HMM_LengthSquared, RENAMED HMM_RSqrtF to HMM_RSquareRootF, RENAMED HMM_SqrtF to HMM_SquareRootF, REMOVED Inner function (user should use Dot now), REMOVED HMM_FastInverseSquareRoot function declaration |
**0.5.2** | Fixed SSE code in HMM_SqrtF and HMM_RSqrtF |
**0.5.1** | Fixed HMM_Translate producing row-major matrices, ensured column-major order for matrices throughout |
**0.5** | Added scalar operations on vectors and matrices, added += and -= for hmm_mat4, reconciled headers and implementations, tidied up in general |
**0.4** | Added SSE Optimized HMM_SqrtF, HMM_RSqrtF, Removed use of C Runtime |
**0.3** | Added +=,-=, *=, /= for hmm_vec2, hmm_vec3, hmm_vec4 |
**0.2b** | Disabled warning C4201 on MSVC, Added 64bit percision on HMM_PI |
**0.2a** | Prefixed Macros |
**0.2** | Updated Documentation, Fixed C Compliance, Prefixed all functions, and added better operator overloading |
**0.1** | Initial Version |
-----
## 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?**
This library is in the public domain. You can do whatever you want with it.
**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.

View File

@@ -1,5 +1,3 @@
#ifndef WITHOUT_COVERAGE
#include "HandmadeTest.h"
#endif
#define HANDMADE_MATH_IMPLEMENTATION
#define HANDMADE_MATH_NO_INLINE
#include "../HandmadeMath.h"

View File

@@ -4,46 +4,19 @@
This is Handmade Math's test framework. It is fully compatible with both C
and C++, although it requires some compiler-specific features.
To use Handmade Test, you must #define HANDMADE_TEST_IMPLEMENTATION in
exactly one C or C++ file that includes the header, like this:
#define HANDMADE_TEST_IMPLEMENTATION
#include "HandmadeTest.h"
The basic way of creating a test is using the TEST macro, which registers a
single test to be run:
TEST(MyCategory, MyTestName) {
TEST(MyCategory, MyTestName) {
// test code, including asserts/expects
}
}
Handmade Test also provides macros you can use to check the coverage of
important parts of your code. Define a coverage case by using the COVERAGE
macro outside the function you wish to test, providing both a name and the
number of asserts you expect to see covered over the course of your test.
Then use the ASSERT_COVERED macro in every part of the function you wish to
check coverage on. For example:
The main function of your test code should then call hmt_run_all_tests and
return the result:
COVERAGE(MyCoverageCase, 3)
void MyFunction(int a, int b) {
if (a > b) {
ASSERT_COVERED(MyCoverageCase);
return 10;
} else if (a < b) {
ASSERT_COVERED(MyCoverageCase);
return -10;
}
ASSERT_COVERED(MyCoverageCase);
return 0;
}
The main function of your test code should then call hmt_run_all_tests (and
optionally hmt_check_all_coverage) and return the result:
int main() {
return hmt_run_all_tests() || hmt_check_all_coverage();
}
int main() {
return hmt_run_all_tests();
}
=============================================================================
@@ -67,7 +40,7 @@
#define HMT_RED "\033[31m"
#define HMT_GREEN "\033[32m"
#define HMT_ARRAY_SIZE 1024
#define HMT_INITIAL_ARRAY_SIZE 1024
typedef struct hmt_testresult_struct {
int count_cases;
@@ -84,188 +57,20 @@ typedef struct hmt_test_struct {
typedef struct hmt_category_struct {
const char* name;
int num_tests;
int tests_capacity;
hmt_test* tests;
} hmt_category;
typedef struct hmt_covercase_struct {
const char* name;
int expected_asserts;
int actual_asserts;
int* asserted_lines;
} hmt_covercase;
hmt_category _hmt_new_category(const char* name);
hmt_test _hmt_new_test(const char* name, hmt_test_func func);
hmt_covercase _hmt_new_covercase(const char* name, int expected);
void _hmt_register_test(const char* category, const char* name, hmt_test_func func);
void _hmt_register_covercase(const char* name, const char* expected_asserts);
void _hmt_count_cover(const char* name, int line);
#define _HMT_TEST_FUNCNAME(category, name) _hmt_test_ ## category ## _ ## name
#define _HMT_TEST_FUNCNAME_INIT(category, name) _hmt_test_ ## category ## _ ## name ## _init
#define _HMT_COVERCASE_FUNCNAME_INIT(name) _hmt_covercase_ ## name ## _init
#define HMT_TEST(category, name) \
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result); \
INITIALIZER(_HMT_TEST_FUNCNAME_INIT(category, name)) { \
_hmt_register_test(#category, #name, _HMT_TEST_FUNCNAME(category, name)); \
} \
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result)
#define _HMT_CASE_START() \
_result->count_cases++;
#define _HMT_CASE_FAIL() \
_result->count_failures++; \
printf("\n - " HMT_RED "[FAIL] (line %d) " HMT_RESET, __LINE__);
#define HMT_COVERAGE(name, num_asserts) \
INITIALIZER(_HMT_COVERCASE_FUNCNAME_INIT(name)) { \
_hmt_register_covercase(#name, #num_asserts); \
} \
#define HMT_ASSERT_COVERED(name) \
{ \
_hmt_count_cover(#name, __LINE__); \
} \
/*
* Asserts and expects
*/
#define HMT_EXPECT_TRUE(_actual) { \
_HMT_CASE_START(); \
if (!(_actual)) { \
_HMT_CASE_FAIL(); \
printf("Expected true but got something false"); \
} \
} \
#define HMT_EXPECT_FALSE(_actual) { \
_HMT_CASE_START(); \
if (_actual) { \
_HMT_CASE_FAIL(); \
printf("Expected false but got something true"); \
} \
} \
#define HMT_EXPECT_FLOAT_EQ_MSG(_actual, _expected, _msg) { \
_HMT_CASE_START(); \
float actual = (_actual); \
float diff = actual - (_expected); \
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
_HMT_CASE_FAIL(); \
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_MSG(_actual, _expected, _epsilon, _msg) { \
_HMT_CASE_START(); \
float actual = (_actual); \
float diff = actual - (_expected); \
if (diff < -(_epsilon) || (_epsilon) < diff) { \
_HMT_CASE_FAIL(); \
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) { \
_HMT_CASE_START(); \
if ((_actual) >= (_expected)) { \
_HMT_CASE_FAIL(); \
printf("Expected %f to be less than %f", (_actual), (_expected)); \
} \
} \
#define HMT_EXPECT_GT(_actual, _expected) { \
_HMT_CASE_START(); \
if ((_actual) <= (_expected)) { \
_HMT_CASE_FAIL(); \
printf("Expected %f to be greater than %f", (_actual), (_expected)); \
} \
} \
#ifndef HMT_SAFE_MACROS
// Friendly defines
#define TEST(category, name) HMT_TEST(category, name)
#define COVERAGE(name, expected_asserts) HMT_COVERAGE(name, expected_asserts)
#define ASSERT_COVERED(name) HMT_ASSERT_COVERED(name)
#define EXPECT_TRUE(_actual) HMT_EXPECT_TRUE(_actual)
#define EXPECT_FALSE(_actual) HMT_EXPECT_FALSE(_actual)
#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_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_GT(_actual, _expected) HMT_EXPECT_GT(_actual, _expected)
#endif // HMT_SAFE_MACROS
#endif // HANDMADETEST_H
#ifdef HANDMADE_TEST_IMPLEMENTATION
#ifndef HANDMADE_TEST_IMPLEMENTATION_GUARD
#define HANDMADE_TEST_IMPLEMENTATION_GUARD
int _hmt_num_categories = 0;
hmt_category* _hmt_categories = 0;
int _hmt_num_covercases = 0;
hmt_covercase* _hmt_covercases = 0;
int _hmt_num_covererrors = 0;
int hmt_num_categories = 0;
int hmt_category_capacity = HMT_INITIAL_ARRAY_SIZE;
hmt_category* categories = 0;
hmt_category _hmt_new_category(const char* name) {
hmt_category cat = {
name, // name
0, // num_tests
(hmt_test*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_test)), // tests
.name = name,
.num_tests = 0,
.tests_capacity = HMT_INITIAL_ARRAY_SIZE,
.tests = (hmt_test*) malloc(HMT_INITIAL_ARRAY_SIZE * sizeof(hmt_test))
};
return cat;
@@ -273,106 +78,60 @@ hmt_category _hmt_new_category(const char* name) {
hmt_test _hmt_new_test(const char* name, hmt_test_func func) {
hmt_test test = {
name, // name
func, // func
.name = name,
.func = func
};
return test;
}
hmt_covercase _hmt_new_covercase(const char* name, int expected) {
hmt_covercase covercase = {
name, // name
expected, // expected_asserts
0, // actual_asserts
(int*) malloc(HMT_ARRAY_SIZE * sizeof(int)), // asserted_lines
};
return covercase;
}
void _hmt_register_test(const char* category, const char* name, hmt_test_func func) {
int hmt_register_test(const char* category, const char* name, hmt_test_func func) {
// initialize categories array if not initialized
if (!_hmt_categories) {
_hmt_categories = (hmt_category*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_category));
if (!categories) {
categories = (hmt_category*) malloc(hmt_category_capacity * sizeof(hmt_category));
}
// Find the matching category, if possible
int cat_index;
for (cat_index = 0; cat_index < _hmt_num_categories; cat_index++) {
if (strcmp(_hmt_categories[cat_index].name, category) == 0) {
for (cat_index = 0; cat_index < hmt_num_categories; cat_index++) {
if (strcmp(categories[cat_index].name, category) == 0) {
break;
}
}
// Add a new category if necessary
if (cat_index >= _hmt_num_categories) {
_hmt_categories[cat_index] = _hmt_new_category(category);
_hmt_num_categories++;
// Expand the array of categories if necessary
if (cat_index >= hmt_category_capacity) {
// TODO: If/when we ever split HandmadeTest off into its own package,
// we should start with a smaller initial capacity and dynamically expand.
}
hmt_category* cat = &_hmt_categories[cat_index];
// Add a new category if necessary
if (cat_index >= hmt_num_categories) {
categories[cat_index] = _hmt_new_category(category);
hmt_num_categories++;
}
hmt_category* cat = &categories[cat_index];
// Add the test to the category
if (cat->num_tests >= cat->tests_capacity) {
// TODO: If/when we ever split HandmadeTest off into its own package,
// we should start with a smaller initial capacity and dynamically expand.
}
cat->tests[cat->num_tests] = _hmt_new_test(name, func);
cat->num_tests++;
}
void _hmt_register_covercase(const char* name, const char* expected_asserts) {
// initialize cases array if not initialized
if (!_hmt_covercases) {
_hmt_covercases = (hmt_covercase*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_covercase));
}
// check for existing case with that name, because the macro can run multiple
// times in different translation units
for (int i = 0; i < _hmt_num_covercases; i++) {
if (strcmp(_hmt_covercases[i].name, name) == 0) {
return;
}
}
_hmt_covercases[_hmt_num_covercases] = _hmt_new_covercase(name, atoi(expected_asserts));
_hmt_num_covercases++;
}
hmt_covercase* _hmt_find_covercase(const char* name) {
for (int i = 0; i < _hmt_num_covercases; i++) {
if (strcmp(_hmt_covercases[i].name, name) == 0) {
return &_hmt_covercases[i];
}
}
return 0;
}
void _hmt_count_cover(const char* name, int line) {
hmt_covercase* covercase = _hmt_find_covercase(name);
if (covercase == 0) {
printf(HMT_RED "ERROR (line %d): Could not find coverage case with name \"%s\".\n" HMT_RESET, line, name);
_hmt_num_covererrors++;
return;
}
// see if this line has already been covered
for (int i = 0; i < covercase->actual_asserts; i++) {
if (covercase->asserted_lines[i] == line) {
return;
}
}
covercase->asserted_lines[covercase->actual_asserts] = line;
covercase->actual_asserts++;
}
int hmt_run_all_tests() {
int count_alltests = 0;
int count_allfailedtests = 0; // failed test cases
int count_allfailures = 0; // failed asserts
for (int i = 0; i < _hmt_num_categories; i++) {
hmt_category cat = _hmt_categories[i];
int count_catfailedtests = 0;
for (int i = 0; i < hmt_num_categories; i++) {
hmt_category cat = categories[i];
int count_catfailedtests = 0;
int count_catfailures = 0;
printf("\n%s:\n", cat.name);
@@ -383,8 +142,8 @@ int hmt_run_all_tests() {
printf(" %s:", test.name);
hmt_testresult result = {
0, // count_cases
0, // count_failures
.count_cases = 0,
.count_failures = 0
};
test.func(&result);
@@ -418,38 +177,87 @@ int hmt_run_all_tests() {
return (count_allfailedtests > 0);
}
int hmt_check_all_coverage() {
printf("Coverage:\n");
#define _HMT_TEST_FUNCNAME(category, name) category ## _ ## name
#define _HMT_TEST_FUNCNAME_INIT(category, name) category ## _ ## name ## _init
int count_failures = 0;
#define HMT_TEST(category, name) \
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result); \
INITIALIZER(_HMT_TEST_FUNCNAME_INIT(category, name)) { \
hmt_register_test(#category, #name, _HMT_TEST_FUNCNAME(category, name)); \
} \
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result)
for (int i = 0; i < _hmt_num_covercases; i++) {
hmt_covercase covercase = _hmt_covercases[i];
#define _HMT_CASE_START() \
_result->count_cases++;
if (covercase.expected_asserts != covercase.actual_asserts) {
count_failures++;
printf("%s: " HMT_RED "FAIL (expected %d asserts, got %d)\n" HMT_RESET, covercase.name, covercase.expected_asserts, covercase.actual_asserts);
}
}
#define _HMT_CASE_FAIL() \
_result->count_failures++; \
printf("\n - " HMT_RED "[FAIL] (%d) " HMT_RESET, __LINE__);
if (count_failures > 0) {
printf("\n");
printf(HMT_RED);
} else {
printf(HMT_GREEN);
}
printf("%d coverage cases tested, %d failures\n", _hmt_num_covercases, count_failures);
printf(HMT_RESET);
/*
* Asserts and expects
*/
#define HMT_EXPECT_TRUE(_actual) do { \
_HMT_CASE_START(); \
if (!(_actual)) { \
_HMT_CASE_FAIL(); \
printf("Expected true but got something false"); \
} \
} while (0)
printf("\n");
#define HMT_EXPECT_FALSE(_actual) do { \
_HMT_CASE_START(); \
if (_actual) { \
_HMT_CASE_FAIL(); \
printf("Expected false but got something true"); \
} \
} while (0)
if (_hmt_num_covererrors > 0) {
printf(HMT_RED "There were %d other coverage errors; scroll up to see them.\n", _hmt_num_covererrors);
return 1;
}
#define HMT_EXPECT_FLOAT_EQ(_actual, _expected) do { \
_HMT_CASE_START(); \
float actual = (_actual); \
float diff = actual - (_expected); \
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
_HMT_CASE_FAIL(); \
printf("Expected %f, got %f", (_expected), actual); \
} \
} while (0)
return (count_failures > 0);
}
#define HMT_EXPECT_NEAR(_actual, _expected, _epsilon) do { \
_HMT_CASE_START(); \
float actual = (_actual); \
float diff = actual - (_expected); \
if (diff < -(_epsilon) || (_epsilon) < diff) { \
_HMT_CASE_FAIL(); \
printf("Expected %f, got %f", (_expected), actual); \
} \
} while (0)
#endif // HANDMADE_TEST_IMPLEMENTATION_GUARD
#endif // HANDMADE_TEST_IMPLEMENTATION
#define HMT_EXPECT_LT(_actual, _expected) do { \
_HMT_CASE_START(); \
if ((_actual) >= (_expected)) { \
_HMT_CASE_FAIL(); \
printf("Expected %f to be less than %f", (_actual), (_expected)); \
} \
} while (0)
#define HMT_EXPECT_GT(_actual, _expected) do { \
_HMT_CASE_START(); \
if ((_actual) <= (_expected)) { \
_HMT_CASE_FAIL(); \
printf("Expected %f to be greater than %f", (_actual), (_expected)); \
} \
} while (0)
#ifndef HMT_SAFE_MACROS
// Friendly defines
#define TEST(category, name) HMT_TEST(category, name)
#define EXPECT_TRUE(_actual) HMT_EXPECT_TRUE(_actual)
#define EXPECT_FALSE(_actual) HMT_EXPECT_FALSE(_actual)
#define EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ(_actual, _expected)
#define EXPECT_NEAR(_actual, _expected, _epsilon) HMT_EXPECT_NEAR(_actual, _expected, _epsilon)
#define EXPECT_LT(_actual, _expected) HMT_EXPECT_LT(_actual, _expected)
#define EXPECT_GT(_actual, _expected) HMT_EXPECT_GT(_actual, _expected)
#endif // HMT_SAFE_MACROS
#endif // HANDMADETEST_H

View File

@@ -1,124 +1,45 @@
BUILD_DIR=./build
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
.PHONY: all all_c all_cpp
all: all_c all_cpp
all_c: c99 c99_no_simd c11 c17
all_cpp: cpp98 cpp98_no_simd cpp03 cpp11 cpp14 cpp17 cpp20
all: c c_no_sse cpp cpp_no_sse
.PHONY: clean
clean:
rm -rf $(BUILD_DIR)
.PHONY: c99
c99:
@echo "\nCompiling as C99"
c: HandmadeMath.c test_impl
@echo "\nCompiling in C mode"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR)\
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
../HandmadeMath.c ../hmm_test.c \
-lm -o hmm_test_c99 \
&& ./hmm_test_c99
-c ../HandmadeMath.c ../hmm_test.c \
-lm \
&& $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
.PHONY: c99_no_simd
c99_no_simd:
@echo "\nCompiling as C99 (no SIMD)"
c_no_sse: HandmadeMath.c test_impl
@echo "\nCompiling in C mode (no SSE)"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
-DHANDMADE_MATH_NO_SIMD \
../HandmadeMath.c ../hmm_test.c \
-lm -o hmm_test_c99_no_simd \
&& ./hmm_test_c99_no_simd
-DHANDMADE_MATH_NO_SSE \
-c ../HandmadeMath.c ../hmm_test.c \
-lm \
&& $(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm
.PHONY: c11
c11:
@echo "\nCompiling as C11"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR)\
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c11 \
../HandmadeMath.c ../hmm_test.c \
-lm -o hmm_test_c11 \
&& ./hmm_test_c11
.PHONY: c17
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"
cpp: HandmadeMath.cpp test_impl
@echo "\nCompiling in C++ mode"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++98 \
../HandmadeMath.cpp ../hmm_test.cpp \
-lm -o hmm_test_cpp98 \
&& ./hmm_test_cpp98
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp \
-DHANDMADE_MATH_CPP_MODE \
../HandmadeMath.cpp ../hmm_test.cpp
.PHONY: cpp98_no_simd
cpp98_no_simd:
@echo "\nCompiling as C++98 (no SIMD)"
cpp_no_sse: HandmadeMath.cpp test_impl
@echo "\nCompiling in C++ mode (no SSE)"
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
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse \
-DHANDMADE_MATH_CPP_MODE -DHANDMADE_MATH_NO_SSE \
../HandmadeMath.cpp ../hmm_test.cpp
.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
test_impl: hmm_test.cpp hmm_test.c

View File

@@ -4,13 +4,8 @@ You can compile and run the tests yourself by running:
```
make
```
To run a specific test configuration, run one of:
```
make c
make c_no_sse
make cpp
make cpp_no_sse
build/hmm_test_c
build/hmm_test_c_no_sse
build/hmm_test_cpp
build/hmm_test_cpp_no_sse
```

View File

@@ -2,24 +2,22 @@
TEST(Addition, Vec2)
{
HMM_Vec2 v2_1 = HMM_V2(1.0f, 2.0f);
HMM_Vec2 v2_2 = HMM_V2(3.0f, 4.0f);
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 v2_2 = HMM_Vec2(3.0f, 4.0f);
{
HMM_Vec2 result = HMM_AddV2(v2_1, v2_2);
hmm_vec2 result = HMM_AddVec2(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Add(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec2 result = v2_1 + v2_2;
hmm_vec2 result = HMM_Add(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
{
hmm_vec2 result = v2_1 + v2_2;
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
@@ -32,26 +30,24 @@ TEST(Addition, Vec2)
TEST(Addition, Vec3)
{
HMM_Vec3 v3_1 = HMM_V3(1.0f, 2.0f, 3.0f);
HMM_Vec3 v3_2 = HMM_V3(4.0f, 5.0f, 6.0f);
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3_2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
{
HMM_Vec3 result = HMM_AddV3(v3_1, v3_2);
hmm_vec3 result = HMM_AddVec3(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 7.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Add(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 7.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec3 result = v3_1 + v3_2;
hmm_vec3 result = HMM_Add(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 7.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
{
hmm_vec3 result = v3_1 + v3_2;
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 7.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
@@ -66,28 +62,26 @@ TEST(Addition, Vec3)
TEST(Addition, Vec4)
{
HMM_Vec4 v4_1 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Vec4 v4_2 = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f);
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v4_2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
{
HMM_Vec4 result = HMM_AddV4(v4_1, v4_2);
hmm_vec4 result = HMM_AddVec4(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Add(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec4 result = v4_1 + v4_2;
hmm_vec4 result = HMM_Add(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
{
hmm_vec4 result = v4_1 + v4_2;
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
@@ -102,138 +96,10 @@ TEST(Addition, Vec4)
#endif
}
TEST(Addition, Mat2)
{
HMM_Mat2 a = HMM_M2();
HMM_Mat2 b = HMM_M2();
int Counter = 1;
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
a.Elements[Column][Row] = Counter++;
}
}
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
b.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat2 result = HMM_AddM2(a, b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 6.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][1], 12.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat2 result = HMM_Add(a, b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 6.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][1], 12.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat2 result = a + b;
EXPECT_FLOAT_EQ(result.Elements[0][0], 6.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][1], 12.0f);
}
a += b;
EXPECT_FLOAT_EQ(a.Elements[0][0], 6.0f);
EXPECT_FLOAT_EQ(a.Elements[0][1], 8.0f);
EXPECT_FLOAT_EQ(a.Elements[1][0], 10.0f);
EXPECT_FLOAT_EQ(a.Elements[1][1], 12.0f);
#endif
}
TEST(Addition, Mat3)
{
HMM_Mat3 a = HMM_M3();
HMM_Mat3 b = HMM_M3();
int Counter = 1;
for (int Column = 0; Column < 3; ++Column)
{
for (int Row = 0; Row < 3; ++Row)
{
a.Elements[Column][Row] = Counter++;
}
}
for (int Column = 0; Column < 3; ++Column)
{
for (int Row = 0; Row < 3; ++Row)
{
b.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat3 result = HMM_AddM3(a, b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 11.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 13.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][1], 19.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][1], 25.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 27.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat3 result = HMM_Add(a, b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 11.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 13.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][1], 19.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][1], 25.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 27.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat3 result = a + b;
EXPECT_FLOAT_EQ(result.Elements[0][0], 11.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 13.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][1], 19.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][1], 25.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 27.0f);
}
a += b;
EXPECT_FLOAT_EQ(a.Elements[0][0], 11.0f);
EXPECT_FLOAT_EQ(a.Elements[0][1], 13.0f);
EXPECT_FLOAT_EQ(a.Elements[0][2], 15.0f);
EXPECT_FLOAT_EQ(a.Elements[1][0], 17.0f);
EXPECT_FLOAT_EQ(a.Elements[1][1], 19.0f);
EXPECT_FLOAT_EQ(a.Elements[1][2], 21.0f);
EXPECT_FLOAT_EQ(a.Elements[2][0], 23.0f);
EXPECT_FLOAT_EQ(a.Elements[2][1], 25.0f);
EXPECT_FLOAT_EQ(a.Elements[2][2], 27.0f);
#endif
}
TEST(Addition, Mat4)
{
HMM_Mat4 m4_1 = HMM_M4(); // will have 1 - 16
HMM_Mat4 m4_2 = HMM_M4(); // will have 17 - 32
hmm_mat4 m4_1 = HMM_Mat4(); // will have 1 - 16
hmm_mat4 m4_2 = HMM_Mat4(); // will have 17 - 32
// Fill the matrices
int Counter = 1;
@@ -256,7 +122,7 @@ TEST(Addition, Mat4)
// Test the results
{
HMM_Mat4 result = HMM_AddM4(m4_1, m4_2);
hmm_mat4 result = HMM_AddMat4(m4_1, m4_2);
float Expected = 18.0f;
for (int Column = 0; Column < 4; ++Column)
{
@@ -267,23 +133,21 @@ TEST(Addition, Mat4)
}
}
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat4 result = HMM_Add(m4_1, m4_2);
float Expected = 18.0f;
for (int Column = 0; Column < 4; ++Column)
{
for (int Row = 0; Row < 4; ++Row)
{
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected);
Expected += 2.0f;
}
}
}
#endif
#ifdef __cplusplus
{
HMM_Mat4 result = m4_1 + m4_2;
hmm_mat4 result = HMM_Add(m4_1, m4_2);
float Expected = 18.0f;
for (int Column = 0; Column < 4; ++Column)
{
for (int Row = 0; Row < 4; ++Row)
{
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected);
Expected += 2.0f;
}
}
}
{
hmm_mat4 result = m4_1 + m4_2;
float Expected = 18.0f;
for (int Column = 0; Column < 4; ++Column)
{
@@ -310,28 +174,26 @@ TEST(Addition, Mat4)
TEST(Addition, Quaternion)
{
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f);
{
HMM_Quat result = HMM_AddQ(q1, q2);
hmm_quaternion result = HMM_AddQuaternion(q1, q2);
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Quat result = HMM_Add(q1, q2);
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Quat result = q1 + q2;
hmm_quaternion result = HMM_Add(q1, q2);
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
{
hmm_quaternion result = q1 + q2;
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);

View File

@@ -2,24 +2,22 @@
TEST(Division, Vec2Vec2)
{
HMM_Vec2 v2_1 = HMM_V2(1.0f, 3.0f);
HMM_Vec2 v2_2 = HMM_V2(2.0f, 4.0f);
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 3.0f);
hmm_vec2 v2_2 = HMM_Vec2(2.0f, 4.0f);
{
HMM_Vec2 result = HMM_DivV2(v2_1, v2_2);
hmm_vec2 result = HMM_DivideVec2(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Div(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec2 result = v2_1 / v2_2;
hmm_vec2 result = HMM_Divide(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
}
{
hmm_vec2 result = v2_1 / v2_2;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
}
@@ -32,24 +30,22 @@ TEST(Division, Vec2Vec2)
TEST(Division, Vec2Scalar)
{
HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f);
float s = 2;
{
HMM_Vec2 result = HMM_DivV2F(v2, s);
hmm_vec2 result = HMM_DivideVec2f(v2, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Div(v2, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec2 result = v2 / s;
hmm_vec2 result = HMM_Divide(v2, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
}
{
hmm_vec2 result = v2 / s;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
}
@@ -62,26 +58,24 @@ TEST(Division, Vec2Scalar)
TEST(Division, Vec3Vec3)
{
HMM_Vec3 v3_1 = HMM_V3(1.0f, 3.0f, 5.0f);
HMM_Vec3 v3_2 = HMM_V3(2.0f, 4.0f, 0.5f);
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 3.0f, 5.0f);
hmm_vec3 v3_2 = HMM_Vec3(2.0f, 4.0f, 0.5f);
{
HMM_Vec3 result = HMM_DivV3(v3_1, v3_2);
hmm_vec3 result = HMM_DivideVec3(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Div(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec3 result = v3_1 / v3_2;
hmm_vec3 result = HMM_Divide(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
}
{
hmm_vec3 result = v3_1 / v3_2;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
@@ -96,26 +90,24 @@ TEST(Division, Vec3Vec3)
TEST(Division, Vec3Scalar)
{
HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3 = HMM_Vec3(1.0f, 2.0f, 3.0f);
float s = 2;
{
HMM_Vec3 result = HMM_DivV3F(v3, s);
hmm_vec3 result = HMM_DivideVec3f(v3, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Div(v3, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec3 result = v3 / s;
hmm_vec3 result = HMM_Divide(v3, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
}
{
hmm_vec3 result = v3 / s;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
@@ -130,28 +122,26 @@ TEST(Division, Vec3Scalar)
TEST(Division, Vec4Vec4)
{
HMM_Vec4 v4_1 = HMM_V4(1.0f, 3.0f, 5.0f, 1.0f);
HMM_Vec4 v4_2 = HMM_V4(2.0f, 4.0f, 0.5f, 4.0f);
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 3.0f, 5.0f, 1.0f);
hmm_vec4 v4_2 = HMM_Vec4(2.0f, 4.0f, 0.5f, 4.0f);
{
HMM_Vec4 result = HMM_DivV4(v4_1, v4_2);
hmm_vec4 result = HMM_DivideVec4(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 0.25f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Div(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 0.25f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec4 result = v4_1 / v4_2;
hmm_vec4 result = HMM_Divide(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 0.25f);
}
{
hmm_vec4 result = v4_1 / v4_2;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
@@ -168,28 +158,26 @@ TEST(Division, Vec4Vec4)
TEST(Division, Vec4Scalar)
{
HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v4 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
float s = 2;
{
HMM_Vec4 result = HMM_DivV4F(v4, s);
hmm_vec4 result = HMM_DivideVec4f(v4, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Div(v4, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec4 result = v4 / s;
hmm_vec4 result = HMM_Divide(v4, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f);
}
{
hmm_vec4 result = v4 / s;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
@@ -204,107 +192,9 @@ TEST(Division, Vec4Scalar)
#endif
}
TEST(Division, Mat2Scalar)
{
HMM_Mat2 m = HMM_M2();
float s = 0.5f;
int Counter = 1;
for (int Column = 0; Column < 2; ++Column) {
for (int Row = 0; Row < 2; ++Row) {
m.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat2 result = HMM_DivM2F(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat2 result = HMM_Div(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat2 result = m / s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f);
}
#endif
}
TEST(Division, Mat3Scalar)
{
HMM_Mat3 m = HMM_M3();
float s = 0.5f;
int Counter = 1;
for (int Column = 0; Column < 3; ++Column) {
for (int Row = 0; Row < 3; ++Row) {
m.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat3 result = HMM_DivM3F(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 8.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 12.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 14.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 16.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 18.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat3 result = HMM_Div(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 8.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 12.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 14.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 16.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 18.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat3 result = m / s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 8.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 12.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 14.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 16.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 18.0f);
}
#endif
}
TEST(Division, Mat4Scalar)
{
HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
hmm_mat4 m4 = HMM_Mat4(); // will have 1 - 16
float s = 2;
// Fill the matrix
@@ -320,7 +210,7 @@ TEST(Division, Mat4Scalar)
// Test the results
{
HMM_Mat4 result = HMM_DivM4F(m4, s);
hmm_mat4 result = HMM_DivideMat4f(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
@@ -338,30 +228,28 @@ TEST(Division, Mat4Scalar)
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat4 result = HMM_Div(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
EXPECT_FLOAT_EQ(result.Elements[0][3], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 2.5f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 3.5f);
EXPECT_FLOAT_EQ(result.Elements[1][3], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 4.5f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 5.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 5.5f);
EXPECT_FLOAT_EQ(result.Elements[2][3], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[3][0], 6.5f);
EXPECT_FLOAT_EQ(result.Elements[3][1], 7.0f);
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat4 result = m4 / s;
hmm_mat4 result = HMM_Divide(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
EXPECT_FLOAT_EQ(result.Elements[0][3], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 2.5f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 3.5f);
EXPECT_FLOAT_EQ(result.Elements[1][3], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 4.5f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 5.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 5.5f);
EXPECT_FLOAT_EQ(result.Elements[2][3], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[3][0], 6.5f);
EXPECT_FLOAT_EQ(result.Elements[3][1], 7.0f);
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
}
{
hmm_mat4 result = m4 / s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
@@ -402,28 +290,26 @@ TEST(Division, Mat4Scalar)
TEST(Division, QuaternionScalar)
{
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
float f = 2.0f;
{
HMM_Quat result = HMM_DivQF(q, f);
hmm_quaternion result = HMM_DivideQuaternionF(q, f);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Quat result = HMM_Div(q, f);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Quat result = q / f;
hmm_quaternion result = HMM_Divide(q, f);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f);
}
{
hmm_quaternion result = q / f;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);

View File

@@ -2,69 +2,54 @@
TEST(Equality, Vec2)
{
HMM_Vec2 a = HMM_V2(1.0f, 2.0f);
HMM_Vec2 b = HMM_V2(1.0f, 2.0f);
HMM_Vec2 c = HMM_V2(3.0f, 4.0f);
hmm_vec2 a = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 b = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 c = HMM_Vec2(3.0f, 4.0f);
EXPECT_TRUE(HMM_EqV2(a, b));
EXPECT_FALSE(HMM_EqV2(a, c));
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_TRUE(HMM_Eq(a, b));
EXPECT_FALSE(HMM_Eq(a, c));
#endif
EXPECT_TRUE(HMM_EqualsVec2(a, b));
EXPECT_FALSE(HMM_EqualsVec2(a, c));
#ifdef __cplusplus
EXPECT_TRUE(HMM_Equals(a, b));
EXPECT_FALSE(HMM_Equals(a, c));
EXPECT_TRUE(a == b);
EXPECT_FALSE(a == c);
EXPECT_FALSE(a != b);
EXPECT_TRUE(a != c);
#endif
}
TEST(Equality, Vec3)
{
HMM_Vec3 a = HMM_V3(1.0f, 2.0f, 3.0f);
HMM_Vec3 b = HMM_V3(1.0f, 2.0f, 3.0f);
HMM_Vec3 c = HMM_V3(4.0f, 5.0f, 6.0f);
hmm_vec3 a = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 b = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 c = HMM_Vec3(4.0f, 5.0f, 6.0f);
EXPECT_TRUE(HMM_EqV3(a, b));
EXPECT_FALSE(HMM_EqV3(a, c));
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_TRUE(HMM_Eq(a, b));
EXPECT_FALSE(HMM_Eq(a, c));
#endif
EXPECT_TRUE(HMM_EqualsVec3(a, b));
EXPECT_FALSE(HMM_EqualsVec3(a, c));
#ifdef __cplusplus
EXPECT_TRUE(HMM_Equals(a, b));
EXPECT_FALSE(HMM_Equals(a, c));
EXPECT_TRUE(a == b);
EXPECT_FALSE(a == c);
EXPECT_FALSE(a != b);
EXPECT_TRUE(a != c);
#endif
}
TEST(Equality, Vec4)
{
HMM_Vec4 a = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Vec4 b = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Vec4 c = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f);
hmm_vec4 a = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 b = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 c = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
EXPECT_TRUE(HMM_EqV4(a, b));
EXPECT_FALSE(HMM_EqV4(a, c));
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_TRUE(HMM_Eq(a, b));
EXPECT_FALSE(HMM_Eq(a, c));
#endif
EXPECT_TRUE(HMM_EqualsVec4(a, b));
EXPECT_FALSE(HMM_EqualsVec4(a, c));
#ifdef __cplusplus
EXPECT_TRUE(HMM_Equals(a, b));
EXPECT_FALSE(HMM_Equals(a, c));
EXPECT_TRUE(a == b);
EXPECT_FALSE(a == c);
EXPECT_FALSE(a != b);
EXPECT_TRUE(a != c);
#endif
}

View File

@@ -4,8 +4,9 @@ TEST(Initialization, Vectors)
{
//
// Test vec2
//
HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
//
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 v2i = HMM_Vec2(1, 2);
EXPECT_FLOAT_EQ(v2.X, 1.0f);
EXPECT_FLOAT_EQ(v2.Y, 2.0f);
@@ -22,10 +23,26 @@ TEST(Initialization, Vectors)
EXPECT_FLOAT_EQ(v2[1], 2.0f);
#endif
EXPECT_FLOAT_EQ(v2i.X, 1.0f);
EXPECT_FLOAT_EQ(v2i.Y, 2.0f);
EXPECT_FLOAT_EQ(v2i.U, 1.0f);
EXPECT_FLOAT_EQ(v2i.V, 2.0f);
EXPECT_FLOAT_EQ(v2i.Left, 1.0f);
EXPECT_FLOAT_EQ(v2i.Right, 2.0f);
EXPECT_FLOAT_EQ(v2i.Width, 1.0f);
EXPECT_FLOAT_EQ(v2i.Height, 2.0f);
EXPECT_FLOAT_EQ(v2i.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v2i.Elements[1], 2.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(v2i[0], 1.0f);
EXPECT_FLOAT_EQ(v2i[1], 2.0f);
#endif
//
// Test vec3
//
HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3 = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3i = HMM_Vec3i(1, 2, 3);
EXPECT_FLOAT_EQ(v3.X, 1.0f);
EXPECT_FLOAT_EQ(v3.Y, 2.0f);
@@ -53,11 +70,38 @@ TEST(Initialization, Vectors)
EXPECT_FLOAT_EQ(v3[2], 3.0f);
#endif
EXPECT_FLOAT_EQ(v3i.X, 1.0f);
EXPECT_FLOAT_EQ(v3i.Y, 2.0f);
EXPECT_FLOAT_EQ(v3i.Z, 3.0f);
EXPECT_FLOAT_EQ(v3i.U, 1.0f);
EXPECT_FLOAT_EQ(v3i.V, 2.0f);
EXPECT_FLOAT_EQ(v3i.W, 3.0f);
EXPECT_FLOAT_EQ(v3i.R, 1.0f);
EXPECT_FLOAT_EQ(v3i.G, 2.0f);
EXPECT_FLOAT_EQ(v3i.B, 3.0f);
EXPECT_FLOAT_EQ(v3i.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v3i.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v3i.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(v3i.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v3i.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v3i.YZ.Elements[0], 2.0f);
EXPECT_FLOAT_EQ(v3i.YZ.Elements[1], 3.0f);
EXPECT_FLOAT_EQ(v3i.UV.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v3i.UV.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v3i.VW.Elements[0], 2.0f);
EXPECT_FLOAT_EQ(v3i.VW.Elements[1], 3.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(v3i[0], 1.0f);
EXPECT_FLOAT_EQ(v3i[1], 2.0f);
EXPECT_FLOAT_EQ(v3i[2], 3.0f);
#endif
//
// Test vec4
//
HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Vec4 v4v = HMM_V4V(v3, 4.0f);
hmm_vec4 v4 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v4i = HMM_Vec4i(1, 2, 3, 4);
hmm_vec4 v4v = HMM_Vec4v(v3, 4.0f);
EXPECT_FLOAT_EQ(v4.X, 1.0f);
EXPECT_FLOAT_EQ(v4.Y, 2.0f);
@@ -88,6 +132,35 @@ TEST(Initialization, Vectors)
EXPECT_FLOAT_EQ(v4[3], 4.0f);
#endif
EXPECT_FLOAT_EQ(v4i.X, 1.0f);
EXPECT_FLOAT_EQ(v4i.Y, 2.0f);
EXPECT_FLOAT_EQ(v4i.Z, 3.0f);
EXPECT_FLOAT_EQ(v4i.W, 4.0f);
EXPECT_FLOAT_EQ(v4i.R, 1.0f);
EXPECT_FLOAT_EQ(v4i.G, 2.0f);
EXPECT_FLOAT_EQ(v4i.B, 3.0f);
EXPECT_FLOAT_EQ(v4i.A, 4.0f);
EXPECT_FLOAT_EQ(v4i.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4i.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4i.YZ.Elements[0], 2.0f);
EXPECT_FLOAT_EQ(v4i.YZ.Elements[1], 3.0f);
EXPECT_FLOAT_EQ(v4i.ZW.Elements[0], 3.0f);
EXPECT_FLOAT_EQ(v4i.ZW.Elements[1], 4.0f);
EXPECT_FLOAT_EQ(v4i.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4i.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4i.XYZ.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4i.XYZ.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4i.XYZ.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(v4i.RGB.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4i.RGB.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4i.RGB.Elements[2], 3.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(v4i[0], 1.0f);
EXPECT_FLOAT_EQ(v4i[1], 2.0f);
EXPECT_FLOAT_EQ(v4i[2], 3.0f);
EXPECT_FLOAT_EQ(v4i[3], 4.0f);
#endif
EXPECT_FLOAT_EQ(v4v.X, 1.0f);
EXPECT_FLOAT_EQ(v4v.Y, 2.0f);
EXPECT_FLOAT_EQ(v4v.Z, 3.0f);
@@ -120,40 +193,7 @@ TEST(Initialization, Vectors)
TEST(Initialization, MatrixEmpty)
{
//
// Test mat2
//
HMM_Mat2 m2 = HMM_M2();
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
EXPECT_FLOAT_EQ(m2.Elements[Column][Row], 0.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(m2[Column][Row], 0.0f);
#endif
}
}
//
// Test mat3
//
HMM_Mat3 m3 = HMM_M3();
for (int Column = 0; Column < 3; ++Column)
{
for (int Row = 0; Row < 3; ++Row)
{
EXPECT_FLOAT_EQ(m3.Elements[Column][Row], 0.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(m3[Column][Row], 0.0f);
#endif
}
}
//
// Test mat4
//
HMM_Mat4 m4 = HMM_M4();
hmm_mat4 m4 = HMM_Mat4();
for (int Column = 0; Column < 4; ++Column)
{
for (int Row = 0; Row < 4; ++Row)
@@ -168,42 +208,7 @@ TEST(Initialization, MatrixEmpty)
TEST(Initialization, MatrixDiagonal)
{
//
// Test mat2
//
HMM_Mat2 m2d = HMM_M2D(1.0f);
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
if (Column == Row) {
EXPECT_FLOAT_EQ(m2d.Elements[Column][Row], 1.0f);
} else {
EXPECT_FLOAT_EQ(m2d.Elements[Column][Row], 0.0f);
}
}
}
//
// Test mat3
//
HMM_Mat3 m3d = HMM_M3D(1.0f);
for (int Column = 0; Column < 3; ++Column)
{
for (int Row = 0; Row < 3; ++Row)
{
if (Column == Row) {
EXPECT_FLOAT_EQ(m3d.Elements[Column][Row], 1.0f);
} else {
EXPECT_FLOAT_EQ(m3d.Elements[Column][Row], 0.0f);
}
}
}
//
// Test mat4
//
HMM_Mat4 m4d = HMM_M4D(1.0f);
hmm_mat4 m4d = HMM_Mat4d(1.0f);
for (int Column = 0; Column < 4; ++Column)
{
for (int Row = 0; Row < 4; ++Row)
@@ -219,7 +224,7 @@ TEST(Initialization, MatrixDiagonal)
TEST(Initialization, Quaternion)
{
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
EXPECT_FLOAT_EQ(q.X, 1.0f);
EXPECT_FLOAT_EQ(q.Y, 2.0f);
@@ -231,91 +236,11 @@ TEST(Initialization, Quaternion)
EXPECT_FLOAT_EQ(q.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(q.Elements[3], 4.0f);
HMM_Vec4 v = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Quat qv = HMM_QV4(v);
hmm_vec4 v = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion qv = HMM_QuaternionV4(v);
EXPECT_FLOAT_EQ(qv.X, 1.0f);
EXPECT_FLOAT_EQ(qv.Y, 2.0f);
EXPECT_FLOAT_EQ(qv.Z, 3.0f);
EXPECT_FLOAT_EQ(qv.W, 4.0f);
}
#ifdef __cplusplus
TEST(Initialization, MatrixOverloads)
{
// Operator overloads for matrix columns must allow mutation.
//
// Test mat2
//
HMM_Mat2 m2 = {0};
m2[0][0] = 1.0f;
m2[0][1] = 2.0f;
m2[1][0] = 3.0f;
m2[1][1] = 4.0f;
EXPECT_FLOAT_EQ(m2.Elements[0][0], 1.0f);
EXPECT_FLOAT_EQ(m2.Elements[0][1], 2.0f);
EXPECT_FLOAT_EQ(m2.Elements[1][0], 3.0f);
EXPECT_FLOAT_EQ(m2.Elements[1][1], 4.0f);
//
// Test mat3
//
HMM_Mat3 m3 = {0};
m3[0][0] = 1.0f;
m3[0][1] = 2.0f;
m3[0][2] = 3.0f;
m3[1][0] = 4.0f;
m3[1][1] = 5.0f;
m3[1][2] = 6.0f;
m3[2][0] = 7.0f;
m3[2][1] = 8.0f;
m3[2][2] = 9.0f;
EXPECT_FLOAT_EQ(m3.Elements[0][0], 1.0f);
EXPECT_FLOAT_EQ(m3.Elements[0][1], 2.0f);
EXPECT_FLOAT_EQ(m3.Elements[0][2], 3.0f);
EXPECT_FLOAT_EQ(m3.Elements[1][0], 4.0f);
EXPECT_FLOAT_EQ(m3.Elements[1][1], 5.0f);
EXPECT_FLOAT_EQ(m3.Elements[1][2], 6.0f);
EXPECT_FLOAT_EQ(m3.Elements[2][0], 7.0f);
EXPECT_FLOAT_EQ(m3.Elements[2][1], 8.0f);
EXPECT_FLOAT_EQ(m3.Elements[2][2], 9.0f);
//
// Test mat4
//
HMM_Mat4 m4 = {0};
m4[0][0] = 1.0f;
m4[0][1] = 2.0f;
m4[0][2] = 3.0f;
m4[0][3] = 4.0f;
m4[1][0] = 5.0f;
m4[1][1] = 6.0f;
m4[1][2] = 7.0f;
m4[1][3] = 8.0f;
m4[2][0] = 9.0f;
m4[2][1] = 10.0f;
m4[2][2] = 11.0f;
m4[2][3] = 12.0f;
m4[3][0] = 13.0f;
m4[3][1] = 14.0f;
m4[3][2] = 15.0f;
m4[3][3] = 16.0f;
EXPECT_FLOAT_EQ(m4.Elements[0][0], 1.0f);
EXPECT_FLOAT_EQ(m4.Elements[0][1], 2.0f);
EXPECT_FLOAT_EQ(m4.Elements[0][2], 3.0f);
EXPECT_FLOAT_EQ(m4.Elements[0][3], 4.0f);
EXPECT_FLOAT_EQ(m4.Elements[1][0], 5.0f);
EXPECT_FLOAT_EQ(m4.Elements[1][1], 6.0f);
EXPECT_FLOAT_EQ(m4.Elements[1][2], 7.0f);
EXPECT_FLOAT_EQ(m4.Elements[1][3], 8.0f);
EXPECT_FLOAT_EQ(m4.Elements[2][0], 9.0f);
EXPECT_FLOAT_EQ(m4.Elements[2][1], 10.0f);
EXPECT_FLOAT_EQ(m4.Elements[2][2], 11.0f);
EXPECT_FLOAT_EQ(m4.Elements[2][3], 12.0f);
EXPECT_FLOAT_EQ(m4.Elements[3][0], 13.0f);
EXPECT_FLOAT_EQ(m4.Elements[3][1], 14.0f);
EXPECT_FLOAT_EQ(m4.Elements[3][2], 15.0f);
EXPECT_FLOAT_EQ(m4.Elements[3][3], 16.0f);
}
#endif

View File

@@ -1,359 +0,0 @@
#include "../HandmadeTest.h"
TEST(InvMatrix, Transpose)
{
{
HMM_Mat2 Matrix = {
1.0f, 3.0f,
2.0f, 4.0f,
};
HMM_Mat2 Expect = {
1.0f, 2.0f,
3.0f, 4.0f,
};
{
HMM_Mat2 result = HMM_TransposeM2(Matrix);
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[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat2 result = HMM_Transpose(Matrix);
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[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
}
#endif
}
{
HMM_Mat3 Matrix = {
1.0f, 4.0f, 7.0f,
2.0f, 5.0f, 8.0f,
3.0f, 6.0f, 9.0f,
};
HMM_Mat3 Expect = {
1.0f, 2.0f, 3.0f,
4.0f, 5.0f, 6.0f,
7.0f, 8.0f, 9.0f
};
{
HMM_Mat3 result = HMM_TransposeM3(Matrix);
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[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[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]);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat3 result = HMM_Transpose(Matrix);
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[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[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]);
}
#endif
}
{
HMM_Mat4 Matrix = {
1.0f, 5.0f, 9.0f, 13.0f,
2.0f, 6.0f, 10.0f, 14.0f,
3.0f, 7.0f, 11.0f, 15.0f,
4.0f, 8.0f, 12.0f, 16.0f
};
HMM_Mat4 Expect = {
1.0f, 2.0f, 3.0f, 4.0f,
5.0f, 6.0f, 7.0f, 8.0f,
9.0f, 10.0f, 11.0f, 12.0f,
13.0f, 14.0f, 15.0f, 16.0f,
};
{
HMM_Mat4 result = HMM_TransposeM4(Matrix);
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[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[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]);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat4 result = HMM_Transpose(Matrix);
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[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[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]);
}
#endif
}
}
TEST(InvMatrix, InvGeneral)
{
{
HMM_Mat4 Matrix = {
12.0f, 2.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 5.0f, 1.0f,
11.0f, 1.0f, 0.0f, 10.0f
};
HMM_Mat4 Expect = HMM_M4D(1.0);
HMM_Mat4 Inverse = HMM_InvGeneralM4(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
float Det = HMM_DeterminantM4(Matrix);
EXPECT_FLOAT_EQ(Det, -80.0f);
EXPECT_NEAR(Result.Elements[0][0], Expect.Elements[0][0], 0.00001f);
EXPECT_NEAR(Result.Elements[0][1], Expect.Elements[0][1], 0.00001f);
EXPECT_NEAR(Result.Elements[0][2], Expect.Elements[0][2], 0.00001f);
EXPECT_NEAR(Result.Elements[0][3], Expect.Elements[0][3], 0.00001f);
EXPECT_NEAR(Result.Elements[1][0], Expect.Elements[1][0], 0.00001f);
EXPECT_NEAR(Result.Elements[1][1], Expect.Elements[1][1], 0.00001f);
EXPECT_NEAR(Result.Elements[1][2], Expect.Elements[1][2], 0.00001f);
EXPECT_NEAR(Result.Elements[1][3], Expect.Elements[1][3], 0.00001f);
EXPECT_NEAR(Result.Elements[2][0], Expect.Elements[2][0], 0.00001f);
EXPECT_NEAR(Result.Elements[2][1], Expect.Elements[2][1], 0.00001f);
EXPECT_NEAR(Result.Elements[2][2], Expect.Elements[2][2], 0.00001f);
EXPECT_NEAR(Result.Elements[2][3], Expect.Elements[2][3], 0.00001f);
EXPECT_NEAR(Result.Elements[3][0], Expect.Elements[3][0], 0.00001f);
EXPECT_NEAR(Result.Elements[3][1], Expect.Elements[3][1], 0.00001f);
EXPECT_NEAR(Result.Elements[3][2], Expect.Elements[3][2], 0.00001f);
EXPECT_NEAR(Result.Elements[3][3], Expect.Elements[3][3], 0.00001f);
#ifdef __cplusplus
Inverse = HMM_InvGeneral(Matrix);
Result = HMM_Mul(Matrix, Inverse);
Det = HMM_Determinant(Matrix);
EXPECT_FLOAT_EQ(Det, -80.0f);
EXPECT_NEAR(Result.Elements[0][0], Expect.Elements[0][0], 0.00001f);
EXPECT_NEAR(Result.Elements[0][1], Expect.Elements[0][1], 0.00001f);
EXPECT_NEAR(Result.Elements[0][2], Expect.Elements[0][2], 0.00001f);
EXPECT_NEAR(Result.Elements[0][3], Expect.Elements[0][3], 0.00001f);
EXPECT_NEAR(Result.Elements[1][0], Expect.Elements[1][0], 0.00001f);
EXPECT_NEAR(Result.Elements[1][1], Expect.Elements[1][1], 0.00001f);
EXPECT_NEAR(Result.Elements[1][2], Expect.Elements[1][2], 0.00001f);
EXPECT_NEAR(Result.Elements[1][3], Expect.Elements[1][3], 0.00001f);
EXPECT_NEAR(Result.Elements[2][0], Expect.Elements[2][0], 0.00001f);
EXPECT_NEAR(Result.Elements[2][1], Expect.Elements[2][1], 0.00001f);
EXPECT_NEAR(Result.Elements[2][2], Expect.Elements[2][2], 0.00001f);
EXPECT_NEAR(Result.Elements[2][3], Expect.Elements[2][3], 0.00001f);
EXPECT_NEAR(Result.Elements[3][0], Expect.Elements[3][0], 0.00001f);
EXPECT_NEAR(Result.Elements[3][1], Expect.Elements[3][1], 0.00001f);
EXPECT_NEAR(Result.Elements[3][2], Expect.Elements[3][2], 0.00001f);
EXPECT_NEAR(Result.Elements[3][3], Expect.Elements[3][3], 0.00001f);
#endif
}
{
HMM_Mat3 Matrix = {
12.0f, 2.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 5.0f
};
HMM_Mat3 Expect = HMM_M3D(1.0);
HMM_Mat3 Inverse = HMM_InvGeneralM3(Matrix);
HMM_Mat3 Result = HMM_MulM3(Matrix, Inverse);
float Det = HMM_DeterminantM3(Matrix);
EXPECT_FLOAT_EQ(Det, -12.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[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[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]);
#ifdef __cplusplus
Inverse = HMM_InvGeneral(Matrix);
Result = HMM_Mul(Matrix, Inverse);
Det = HMM_Determinant(Matrix);
EXPECT_FLOAT_EQ(Det, -12.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[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[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]);
#endif
}
{
HMM_Mat2 Matrix = {
12.0f, 2.0f,
1.0f, 5.0f
};
HMM_Mat2 Expect = HMM_M2D(1.0);
HMM_Mat2 Inverse = HMM_InvGeneralM2(Matrix);
HMM_Mat2 Result = HMM_MulM2(Matrix, Inverse);
float Det = HMM_DeterminantM2(Matrix);
EXPECT_FLOAT_EQ(Det, 58.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[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
#ifdef __cplusplus
Inverse = HMM_InvGeneral(Matrix);
Result = HMM_Mul(Matrix, Inverse);
Det = HMM_Determinant(Matrix);
EXPECT_FLOAT_EQ(Det, 58.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[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
#endif
}
}
TEST(InvMatrix, InvOrthographic)
{
{
HMM_Mat4 Matrix = HMM_Orthographic_RH_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_RH_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));
}
{
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 Center = {100.0f, 200.0f, 30.0f};
HMM_Vec3 Up = {0.0f, 0.0f, 1.0f};
HMM_Mat4 Matrix = HMM_LookAt_RH(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);
}
{
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_Mat4 Matrix = HMM_Rotate_RH(HMM_AngleDeg(30), HMM_NormV3(Axis));
HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvRotate(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_NEAR(Result, Expect, 0.001f);
}
{
HMM_Vec3 Axis = {1.0f, -1.0f, 0.5f};
HMM_Mat4 Matrix = HMM_Rotate_LH(HMM_AngleDeg(30), HMM_NormV3(Axis));
HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvRotate(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_NEAR(Result, Expect, 0.001f);
}
}
TEST(InvMatrix, InvScale)
{
HMM_Vec3 Scale = {1.0f, -1.0f, 0.5f};
HMM_Mat4 Matrix = HMM_Scale(Scale);
HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvScale(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_EQ(Result, Expect);
}
TEST(InvMatrix, InvTranslate)
{
HMM_Vec3 Move = {1.0f, -1.0f, 0.5f};
HMM_Mat4 Matrix = HMM_Translate(Move);
HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvTranslate(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_EQ(Result, Expect);
}

View File

@@ -2,24 +2,22 @@
TEST(Multiplication, Vec2Vec2)
{
HMM_Vec2 v2_1 = HMM_V2(1.0f, 2.0f);
HMM_Vec2 v2_2 = HMM_V2(3.0f, 4.0f);
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 v2_2 = HMM_Vec2(3.0f, 4.0f);
{
HMM_Vec2 result = HMM_MulV2(v2_1, v2_2);
hmm_vec2 result = HMM_MultiplyVec2(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Mul(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec2 result = v2_1 * v2_2;
hmm_vec2 result = HMM_Multiply(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
}
{
hmm_vec2 result = v2_1 * v2_2;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
}
@@ -32,29 +30,27 @@ TEST(Multiplication, Vec2Vec2)
TEST(Multiplication, Vec2Scalar)
{
HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f);
float s = 3.0f;
{
HMM_Vec2 result = HMM_MulV2F(v2, s);
hmm_vec2 result = HMM_MultiplyVec2f(v2, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Mul(v2, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec2 result = v2 * s;
hmm_vec2 result = HMM_Multiply(v2, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
{
HMM_Vec2 result = s * v2;
hmm_vec2 result = v2 * s;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
{
hmm_vec2 result = s * v2;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
@@ -67,26 +63,24 @@ TEST(Multiplication, Vec2Scalar)
TEST(Multiplication, Vec3Vec3)
{
HMM_Vec3 v3_1 = HMM_V3(1.0f, 2.0f, 3.0f);
HMM_Vec3 v3_2 = HMM_V3(4.0f, 5.0f, 6.0f);
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3_2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
{
HMM_Vec3 result = HMM_MulV3(v3_1, v3_2);
hmm_vec3 result = HMM_MultiplyVec3(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 10.0f);
EXPECT_FLOAT_EQ(result.Z, 18.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Mul(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 10.0f);
EXPECT_FLOAT_EQ(result.Z, 18.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec3 result = v3_1 * v3_2;
hmm_vec3 result = HMM_Multiply(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 10.0f);
EXPECT_FLOAT_EQ(result.Z, 18.0f);
}
{
hmm_vec3 result = v3_1 * v3_2;
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 10.0f);
EXPECT_FLOAT_EQ(result.Z, 18.0f);
@@ -101,32 +95,30 @@ TEST(Multiplication, Vec3Vec3)
TEST(Multiplication, Vec3Scalar)
{
HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3 = HMM_Vec3(1.0f, 2.0f, 3.0f);
float s = 3.0f;
{
HMM_Vec3 result = HMM_MulV3F(v3, s);
hmm_vec3 result = HMM_MultiplyVec3f(v3, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Mul(v3, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec3 result = v3 * s;
hmm_vec3 result = HMM_Multiply(v3, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
{
HMM_Vec3 result = s * v3;
hmm_vec3 result = v3 * s;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
{
hmm_vec3 result = s * v3;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
@@ -141,28 +133,26 @@ TEST(Multiplication, Vec3Scalar)
TEST(Multiplication, Vec4Vec4)
{
HMM_Vec4 v4_1 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Vec4 v4_2 = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f);
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v4_2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
{
HMM_Vec4 result = HMM_MulV4(v4_1, v4_2);
hmm_vec4 result = HMM_MultiplyVec4(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 12.0f);
EXPECT_FLOAT_EQ(result.Z, 21.0f);
EXPECT_FLOAT_EQ(result.W, 32.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Mul(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 12.0f);
EXPECT_FLOAT_EQ(result.Z, 21.0f);
EXPECT_FLOAT_EQ(result.W, 32.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec4 result = v4_1 * v4_2;
hmm_vec4 result = HMM_Multiply(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 12.0f);
EXPECT_FLOAT_EQ(result.Z, 21.0f);
EXPECT_FLOAT_EQ(result.W, 32.0f);
}
{
hmm_vec4 result = v4_1 * v4_2;
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 12.0f);
EXPECT_FLOAT_EQ(result.Z, 21.0f);
@@ -179,35 +169,33 @@ TEST(Multiplication, Vec4Vec4)
TEST(Multiplication, Vec4Scalar)
{
HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v4 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
float s = 3.0f;
{
HMM_Vec4 result = HMM_MulV4F(v4, s);
hmm_vec4 result = HMM_MultiplyVec4f(v4, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Mul(v4, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec4 result = v4 * s;
hmm_vec4 result = HMM_Multiply(v4, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
{
HMM_Vec4 result = s * v4;
hmm_vec4 result = v4 * s;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
{
hmm_vec4 result = s * v4;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
@@ -221,320 +209,10 @@ TEST(Multiplication, Vec4Scalar)
#endif
}
TEST(Multiplication, Mat2Mat2) {
HMM_Mat2 a = HMM_M2();
HMM_Mat2 b = HMM_M2();
int counter = 1;
for (int Column = 0; Column < 2; Column++) {
for (int Row = 0; Row < 2; Row++) {
a.Elements[Column][Row] = counter++;
}
}
for (int Column = 0; Column < 2; Column++) {
for (int Row = 0; Row < 2; Row++) {
b.Elements[Column][Row] = counter++;
}
}
{
HMM_Mat2 result = HMM_MulM2(a,b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 23.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][1], 46.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat2 result = HMM_Mul(a,b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 23.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][1], 46.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat2 result = a * b;
EXPECT_FLOAT_EQ(result.Elements[0][0], 23.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][1], 46.0f);
}
#endif
}
TEST(Multiplication, Mat2Scalar) {
HMM_Mat2 m = HMM_M2();
float s = 10.0f;
int counter = 1;
for (int Column = 0; Column < 2; Column++) {
for (int Row = 0; Row < 2; Row++) {
m.Elements[Column][Row] = counter++;
}
}
{
HMM_Mat2 result = HMM_MulM2F(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat2 result = HMM_Mul(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat2 result = m * s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
}
{
HMM_Mat2 result = s * m;
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
}
m *= s;
EXPECT_FLOAT_EQ(m.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(m.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(m.Elements[1][0], 30.0f);
EXPECT_FLOAT_EQ(m.Elements[1][1], 40.0f);
#endif
}
TEST(Multiplication, Mat2Vec2) {
HMM_Mat2 m = HMM_M2();
HMM_Vec2 v = HMM_V2(0.0f, 0.0f);
int counter = 1;
for (int Column = 0; Column < 2; Column++) {
for (int Row = 0; Row < 2; Row++) {
m.Elements[Column][Row] = counter++;
}
}
for (int Row = 0; Row < 2; Row++) {
v.Elements[Row] = counter++;
}
{
HMM_Vec2 result = HMM_MulM2V2(m, v);
EXPECT_FLOAT_EQ(result.Elements[0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 34.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Mul(m, v);
EXPECT_FLOAT_EQ(result.Elements[0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 34.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec2 result = m * v;
EXPECT_FLOAT_EQ(result.Elements[0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 34.0f);
}
#endif
}
TEST(Multiplication, Mat3Mat3)
{
HMM_Mat3 a = HMM_M3();
HMM_Mat3 b = HMM_M3();
int counter = 1;
for (int Column = 0; Column < 3; Column++) {
for (int Row = 0; Row < 3; Row++) {
a.Elements[Column][Row] = counter++;
}
}
for (int Column = 0; Column < 3; Column++) {
for (int Row = 0; Row < 3; Row++) {
b.Elements[Column][Row] = counter++;
}
}
{
HMM_Mat3 result = HMM_MulM3(a,b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 138.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 204.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 174.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 216.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 258.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 210.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 261.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 312.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat3 result = HMM_Mul(a,b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 138.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 204.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 174.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 216.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 258.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 210.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 261.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 312.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat3 result = a * b;
EXPECT_FLOAT_EQ(result.Elements[0][0], 138.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 204.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 174.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 216.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 258.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 210.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 261.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 312.0f);
}
#endif
}
TEST(Multiplication, Mat3Scalar) {
HMM_Mat3 m = HMM_M3();
float s = 10.0f;
int counter = 1;
for (int Column = 0; Column < 3; Column++) {
for (int Row = 0; Row < 3; Row++) {
m.Elements[Column][Row] = counter++;
}
}
{
HMM_Mat3 result = HMM_MulM3F(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 40.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 50.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 60.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 70.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat3 result = HMM_Mul(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 40.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 50.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 60.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 70.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat3 result = m * s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 40.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 50.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 60.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 70.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
}
{
HMM_Mat3 result = s * m;
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 40.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 50.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 60.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 70.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
}
m *= s;
EXPECT_FLOAT_EQ(m.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(m.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(m.Elements[0][2], 30.0f);
EXPECT_FLOAT_EQ(m.Elements[1][0], 40.0f);
EXPECT_FLOAT_EQ(m.Elements[1][1], 50.0f);
EXPECT_FLOAT_EQ(m.Elements[1][2], 60.0f);
EXPECT_FLOAT_EQ(m.Elements[2][0], 70.0f);
EXPECT_FLOAT_EQ(m.Elements[2][1], 80.0f);
EXPECT_FLOAT_EQ(m.Elements[2][2], 90.0f);
#endif
}
TEST(Multiplication, Mat3Vec3) {
HMM_Mat3 m = HMM_M3();
HMM_Vec3 v = HMM_V3(0.0f, 0.0f, 0.0f);
int counter = 1;
for (int Column = 0; Column < 3; Column++) {
for (int Row = 0; Row < 3; Row++) {
m.Elements[Column][Row] = counter++;
}
}
for (int Row = 0; Row < 3; Row++) {
v.Elements[Row] = counter++;
}
{
HMM_Vec3 result = HMM_MulM3V3(m, v);
EXPECT_FLOAT_EQ(result.Elements[0], 138.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[2], 204.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Mul(m, v);
EXPECT_FLOAT_EQ(result.Elements[0], 138.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[2], 204.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec3 result = m * v;
EXPECT_FLOAT_EQ(result.Elements[0], 138.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[2], 204.0f);
}
#endif
}
TEST(Multiplication, Mat4Mat4)
{
HMM_Mat4 m4_1 = HMM_M4(); // will have 1 - 16
HMM_Mat4 m4_2 = HMM_M4(); // will have 17 - 32
hmm_mat4 m4_1 = HMM_Mat4(); // will have 1 - 16
hmm_mat4 m4_2 = HMM_Mat4(); // will have 17 - 32
// Fill the matrices
int Counter = 1;
@@ -557,7 +235,7 @@ TEST(Multiplication, Mat4Mat4)
// Test the results
{
HMM_Mat4 result = HMM_MulM4(m4_1, m4_2);
hmm_mat4 result = HMM_MultiplyMat4(m4_1, m4_2);
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
@@ -575,30 +253,28 @@ TEST(Multiplication, Mat4Mat4)
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat4 result = HMM_Mul(m4_1, m4_2);
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
EXPECT_FLOAT_EQ(result.Elements[0][3], 760.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 650.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 740.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 830.0f);
EXPECT_FLOAT_EQ(result.Elements[1][3], 920.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 762.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 868.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 974.0f);
EXPECT_FLOAT_EQ(result.Elements[2][3], 1080.0f);
EXPECT_FLOAT_EQ(result.Elements[3][0], 874.0f);
EXPECT_FLOAT_EQ(result.Elements[3][1], 996.0f);
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat4 result = m4_1 * m4_2;
hmm_mat4 result = HMM_Multiply(m4_1, m4_2);
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
EXPECT_FLOAT_EQ(result.Elements[0][3], 760.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 650.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 740.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 830.0f);
EXPECT_FLOAT_EQ(result.Elements[1][3], 920.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 762.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 868.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 974.0f);
EXPECT_FLOAT_EQ(result.Elements[2][3], 1080.0f);
EXPECT_FLOAT_EQ(result.Elements[3][0], 874.0f);
EXPECT_FLOAT_EQ(result.Elements[3][1], 996.0f);
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
}
{
hmm_mat4 result = m4_1 * m4_2;
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
@@ -625,7 +301,7 @@ TEST(Multiplication, Mat4Mat4)
TEST(Multiplication, Mat4Scalar)
{
HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
hmm_mat4 m4 = HMM_Mat4(); // will have 1 - 16
float s = 3;
// Fill the matrix
@@ -641,7 +317,7 @@ TEST(Multiplication, Mat4Scalar)
// Test the results
{
HMM_Mat4 result = HMM_MulM4F(m4, s);
hmm_mat4 result = HMM_MultiplyMat4f(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
@@ -659,30 +335,9 @@ TEST(Multiplication, Mat4Scalar)
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat4 result = HMM_Mul(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
EXPECT_FLOAT_EQ(result.Elements[0][3], 12.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 15.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 18.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
EXPECT_FLOAT_EQ(result.Elements[1][3], 24.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 27.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 33.0f);
EXPECT_FLOAT_EQ(result.Elements[2][3], 36.0f);
EXPECT_FLOAT_EQ(result.Elements[3][0], 39.0f);
EXPECT_FLOAT_EQ(result.Elements[3][1], 42.0f);
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat4 result = m4 * s;
hmm_mat4 result = HMM_Multiply(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
@@ -701,7 +356,26 @@ TEST(Multiplication, Mat4Scalar)
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
}
{
HMM_Mat4 result = s * m4;
hmm_mat4 result = m4 * s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
EXPECT_FLOAT_EQ(result.Elements[0][3], 12.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 15.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 18.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
EXPECT_FLOAT_EQ(result.Elements[1][3], 24.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 27.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 33.0f);
EXPECT_FLOAT_EQ(result.Elements[2][3], 36.0f);
EXPECT_FLOAT_EQ(result.Elements[3][0], 39.0f);
EXPECT_FLOAT_EQ(result.Elements[3][1], 42.0f);
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
}
{
hmm_mat4 result = s * m4;
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
@@ -742,8 +416,8 @@ TEST(Multiplication, Mat4Scalar)
TEST(Multiplication, Mat4Vec4)
{
HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_mat4 m4 = HMM_Mat4(); // will have 1 - 16
hmm_vec4 v4 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
// Fill the matrix
int Counter = 1;
@@ -758,24 +432,22 @@ TEST(Multiplication, Mat4Vec4)
// Test the results
{
HMM_Vec4 result = HMM_MulM4V4(m4, v4);
hmm_vec4 result = HMM_MultiplyMat4ByVec4(m4, v4);
EXPECT_FLOAT_EQ(result.X, 90.0f);
EXPECT_FLOAT_EQ(result.Y, 100.0f);
EXPECT_FLOAT_EQ(result.Z, 110.0f);
EXPECT_FLOAT_EQ(result.W, 120.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Mul(m4, v4);
EXPECT_FLOAT_EQ(result.X, 90.0f);
EXPECT_FLOAT_EQ(result.Y, 100.0f);
EXPECT_FLOAT_EQ(result.Z, 110.0f);
EXPECT_FLOAT_EQ(result.W, 120.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec4 result = m4 * v4;
hmm_vec4 result = HMM_Multiply(m4, v4);
EXPECT_FLOAT_EQ(result.X, 90.0f);
EXPECT_FLOAT_EQ(result.Y, 100.0f);
EXPECT_FLOAT_EQ(result.Z, 110.0f);
EXPECT_FLOAT_EQ(result.W, 120.0f);
}
{
hmm_vec4 result = m4 * v4;
EXPECT_FLOAT_EQ(result.X, 90.0f);
EXPECT_FLOAT_EQ(result.Y, 100.0f);
EXPECT_FLOAT_EQ(result.Z, 110.0f);
@@ -788,28 +460,26 @@ TEST(Multiplication, Mat4Vec4)
TEST(Multiplication, QuaternionQuaternion)
{
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f);
{
HMM_Quat result = HMM_MulQ(q1, q2);
hmm_quaternion result = HMM_MultiplyQuaternion(q1, q2);
EXPECT_FLOAT_EQ(result.X, 24.0f);
EXPECT_FLOAT_EQ(result.Y, 48.0f);
EXPECT_FLOAT_EQ(result.Z, 48.0f);
EXPECT_FLOAT_EQ(result.W, -6.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Quat result = HMM_Mul(q1, q2);
EXPECT_FLOAT_EQ(result.X, 24.0f);
EXPECT_FLOAT_EQ(result.Y, 48.0f);
EXPECT_FLOAT_EQ(result.Z, 48.0f);
EXPECT_FLOAT_EQ(result.W, -6.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Quat result = q1 * q2;
hmm_quaternion result = HMM_Multiply(q1, q2);
EXPECT_FLOAT_EQ(result.X, 24.0f);
EXPECT_FLOAT_EQ(result.Y, 48.0f);
EXPECT_FLOAT_EQ(result.Z, 48.0f);
EXPECT_FLOAT_EQ(result.W, -6.0f);
}
{
hmm_quaternion result = q1 * q2;
EXPECT_FLOAT_EQ(result.X, 24.0f);
EXPECT_FLOAT_EQ(result.Y, 48.0f);
EXPECT_FLOAT_EQ(result.Z, 48.0f);
@@ -824,35 +494,33 @@ TEST(Multiplication, QuaternionQuaternion)
TEST(Multiplication, QuaternionScalar)
{
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
float f = 2.0f;
{
HMM_Quat result = HMM_MulQF(q, f);
hmm_quaternion result = HMM_MultiplyQuaternionF(q, f);
EXPECT_FLOAT_EQ(result.X, 2.0f);
EXPECT_FLOAT_EQ(result.Y, 4.0f);
EXPECT_FLOAT_EQ(result.Z, 6.0f);
EXPECT_FLOAT_EQ(result.W, 8.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Quat result = HMM_Mul(q, f);
EXPECT_FLOAT_EQ(result.X, 2.0f);
EXPECT_FLOAT_EQ(result.Y, 4.0f);
EXPECT_FLOAT_EQ(result.Z, 6.0f);
EXPECT_FLOAT_EQ(result.W, 8.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Quat result = q * f;
hmm_quaternion result = HMM_Multiply(q, f);
EXPECT_FLOAT_EQ(result.X, 2.0f);
EXPECT_FLOAT_EQ(result.Y, 4.0f);
EXPECT_FLOAT_EQ(result.Z, 6.0f);
EXPECT_FLOAT_EQ(result.W, 8.0f);
}
{
HMM_Quat result = f * q;
hmm_quaternion result = q * f;
EXPECT_FLOAT_EQ(result.X, 2.0f);
EXPECT_FLOAT_EQ(result.Y, 4.0f);
EXPECT_FLOAT_EQ(result.Z, 6.0f);
EXPECT_FLOAT_EQ(result.W, 8.0f);
}
{
hmm_quaternion result = f * q;
EXPECT_FLOAT_EQ(result.X, 2.0f);
EXPECT_FLOAT_EQ(result.Y, 4.0f);
EXPECT_FLOAT_EQ(result.Z, 6.0f);

View File

@@ -2,84 +2,35 @@
TEST(Projection, Orthographic)
{
#define ORTHO_BOUNDS -8.0f, 12.0f, 5.0f, 10.0f, 1.0f, 100.0f
hmm_mat4 projection = HMM_Orthographic(-10.0f, 10.0f, -5.0f, 5.0f, 0.0f, -10.0f);
// Right-handed
{
// Near and far distances correspond to negative Z, hence the Z coordinates here are negative.
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);
hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -5.0f);
hmm_vec4 projected = HMM_MultiplyMat4ByVec4(projection, HMM_Vec4v(original, 1));
// Z from -1 to 1 (GL convention)
{
HMM_Mat4 projection = HMM_Orthographic_RH_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_RH_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));
}
}
// Left-handed
{
// Near and far distances correspond to positive Z, hence the Z coordinates here are positive.
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));
}
}
EXPECT_FLOAT_EQ(projected.X, 0.5f);
EXPECT_FLOAT_EQ(projected.Y, 1.0f);
EXPECT_FLOAT_EQ(projected.Z, -2.0f);
EXPECT_FLOAT_EQ(projected.W, 1.0f);
}
TEST(Projection, Perspective)
{
// Right-handed
{
// Z from -1 to 1 (GL convention)
{
HMM_Mat4 projection = HMM_Perspective_RH_NO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.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, -1.0f, 1.0f));
}
hmm_mat4 projection = HMM_Perspective(90.0f, 2.0f, 5.0f, 15.0f);
// Z from 0 to 1 (DX convention)
{
HMM_Mat4 projection = HMM_Perspective_RH_ZO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.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));
}
{
hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -15.0f);
hmm_vec4 projected = HMM_MultiplyMat4ByVec4(projection, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(projected.X, 5.0f);
EXPECT_FLOAT_EQ(projected.Y, 10.0f);
EXPECT_FLOAT_EQ(projected.Z, 15.0f);
EXPECT_FLOAT_EQ(projected.W, 15.0f);
}
// Left-handed
{
// Z from -1 to 1 (GL convention)
{
HMM_Mat4 projection = HMM_Perspective_LH_NO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.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, -1.0f, 1.0f));
}
// Z from 0 to 1 (DX convention)
{
HMM_Mat4 projection = HMM_Perspective_LH_ZO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.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));
}
hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -5.0f);
hmm_vec4 projected = HMM_MultiplyMat4ByVec4(projection, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(projected.X, 5.0f);
EXPECT_FLOAT_EQ(projected.Y, 10.0f);
EXPECT_FLOAT_EQ(projected.Z, -5.0f);
EXPECT_FLOAT_EQ(projected.W, 5.0f);
}
}

View File

@@ -2,10 +2,10 @@
TEST(QuaternionOps, Inverse)
{
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Quat inverse = HMM_InvQ(q1);
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion inverse = HMM_InverseQuaternion(q1);
HMM_Quat result = HMM_MulQ(q1, inverse);
hmm_quaternion result = HMM_MultiplyQuaternion(q1, inverse);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
@@ -15,14 +15,14 @@ TEST(QuaternionOps, Inverse)
TEST(QuaternionOps, Dot)
{
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f);
{
float result = HMM_DotQ(q1, q2);
float result = HMM_DotQuaternion(q1, q2);
EXPECT_FLOAT_EQ(result, 70.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
#ifdef __cplusplus
{
float result = HMM_Dot(q1, q2);
EXPECT_FLOAT_EQ(result, 70.0f);
@@ -32,87 +32,57 @@ TEST(QuaternionOps, Dot)
TEST(QuaternionOps, Normalize)
{
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
{
HMM_Quat result = HMM_NormQ(q);
EXPECT_NEAR(result.X, 0.1825741858f, 0.001f);
EXPECT_NEAR(result.Y, 0.3651483717f, 0.001f);
EXPECT_NEAR(result.Z, 0.5477225575f, 0.001f);
EXPECT_NEAR(result.W, 0.7302967433f, 0.001f);
hmm_quaternion result = HMM_NormalizeQuaternion(q);
EXPECT_FLOAT_EQ(result.X, 0.1825741858f);
EXPECT_FLOAT_EQ(result.Y, 0.3651483717f);
EXPECT_FLOAT_EQ(result.Z, 0.5477225575f);
EXPECT_FLOAT_EQ(result.W, 0.7302967433f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
#ifdef __cplusplus
{
HMM_Quat result = HMM_Norm(q);
EXPECT_NEAR(result.X, 0.1825741858f, 0.001f);
EXPECT_NEAR(result.Y, 0.3651483717f, 0.001f);
EXPECT_NEAR(result.Z, 0.5477225575f, 0.001f);
EXPECT_NEAR(result.W, 0.7302967433f, 0.001f);
hmm_quaternion result = HMM_Normalize(q);
EXPECT_FLOAT_EQ(result.X, 0.1825741858f);
EXPECT_FLOAT_EQ(result.Y, 0.3651483717f);
EXPECT_FLOAT_EQ(result.Z, 0.5477225575f);
EXPECT_FLOAT_EQ(result.W, 0.7302967433f);
}
#endif
}
TEST(QuaternionOps, NLerp)
{
HMM_Quat from = HMM_Q(0.0f, 0.0f, 0.0f, 1.0f);
HMM_Quat to = HMM_Q(0.5f, 0.5f, -0.5f, 0.5f);
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_Quat result = HMM_NLerp(from, 0.5f, to);
EXPECT_NEAR(result.X, 0.28867513f, 0.001f);
EXPECT_NEAR(result.Y, 0.28867513f, 0.001f);
EXPECT_NEAR(result.Z, -0.28867513f, 0.001f);
EXPECT_NEAR(result.W, 0.86602540f, 0.001f);
hmm_quaternion result = HMM_NLerp(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);
}
TEST(QuaternionOps, SLerp)
TEST(QuaternionOps, Slerp)
{
HMM_Quat from = HMM_Q(0.0f, 0.0f, 0.0f, 1.0f);
HMM_Quat to = HMM_Q(0.5f, 0.5f, -0.5f, 0.5f);
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_Quat result = HMM_SLerp(from, 0.0f, to);
EXPECT_NEAR(result.X, 0.0f, 0.001f);
EXPECT_NEAR(result.Y, 0.0f, 0.001f);
EXPECT_NEAR(result.Z, 0.0f, 0.001f);
EXPECT_NEAR(result.W, 1.0, 0.001f);
}
{
HMM_Quat result = HMM_SLerp(from, 0.25f, to);
EXPECT_NEAR(result.X, 0.149429246f, 0.001f);
EXPECT_NEAR(result.Y, 0.149429246f, 0.001f);
EXPECT_NEAR(result.Z, -0.149429246f, 0.001f);
EXPECT_NEAR(result.W, 0.965925812f, 0.001f);
}
{
HMM_Quat result = HMM_SLerp(from, 0.5f, to);
EXPECT_NEAR(result.X, 0.28867513f, 0.001f);
EXPECT_NEAR(result.Y, 0.28867513f, 0.001f);
EXPECT_NEAR(result.Z, -0.28867513f, 0.001f);
EXPECT_NEAR(result.W, 0.86602540f, 0.001f);
}
{
HMM_Quat result = HMM_SLerp(from, 0.75f, to);
EXPECT_NEAR(result.X, 0.40824830f, 0.001f);
EXPECT_NEAR(result.Y, 0.40824830f, 0.001f);
EXPECT_NEAR(result.Z, -0.40824830f, 0.001f);
EXPECT_NEAR(result.W, 0.70710676f, 0.001f);
}
{
HMM_Quat result = HMM_SLerp(from, 1.0f, to);
EXPECT_NEAR(result.X, 0.5f, 0.001f);
EXPECT_NEAR(result.Y, 0.5f, 0.001f);
EXPECT_NEAR(result.Z, -0.5f, 0.001f);
EXPECT_NEAR(result.W, 0.5f, 0.001f);
}
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);
}
TEST(QuaternionOps, QuatToMat4)
TEST(QuaternionOps, ToMat4)
{
const float abs_error = 0.001f;
const float abs_error = 0.0001f;
HMM_Quat rot = HMM_Q(0.707107f, 0.0f, 0.0f, 0.707107f);
hmm_quaternion rot = HMM_Quaternion(0.707107f, 0.0f, 0.0f, 0.707107f);
HMM_Mat4 result = HMM_QToM4(rot);
hmm_mat4 result = HMM_QuaternionToMat4(rot);
EXPECT_NEAR(result.Elements[0][0], 1.0f, abs_error);
EXPECT_NEAR(result.Elements[0][1], 0.0f, abs_error);
@@ -135,163 +105,14 @@ TEST(QuaternionOps, QuatToMat4)
EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error);
}
TEST(QuaternionOps, Mat4ToQuat)
TEST(QuaternionOps, FromAxisAngle)
{
const float abs_error = 0.0001f;
hmm_vec3 axis = HMM_Vec3(1.0f, 0.0f, 0.0f);
float angle = HMM_PI32 / 2.0f;
// Rotate 90 degrees on the X axis
{
HMM_Mat4 m = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(1, 0, 0));
HMM_Quat result = HMM_M4ToQ_RH(m);
float cosf = 0.707107f; // cos(90/2 degrees)
float sinf = 0.707107f; // sin(90/2 degrees)
EXPECT_NEAR(result.X, sinf, abs_error);
EXPECT_NEAR(result.Y, 0.0f, abs_error);
EXPECT_NEAR(result.Z, 0.0f, abs_error);
EXPECT_NEAR(result.W, cosf, abs_error);
}
// Rotate 90 degrees on the Y axis (axis not normalized, just for fun)
{
HMM_Mat4 m = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(0, 2, 0));
HMM_Quat result = HMM_M4ToQ_RH(m);
float cosf = 0.707107f; // cos(90/2 degrees)
float sinf = 0.707107f; // sin(90/2 degrees)
EXPECT_NEAR(result.X, 0.0f, abs_error);
EXPECT_NEAR(result.Y, sinf, abs_error);
EXPECT_NEAR(result.Z, 0.0f, abs_error);
EXPECT_NEAR(result.W, cosf, abs_error);
}
// Rotate 90 degrees on the Z axis
{
HMM_Mat4 m = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(0, 0, 1));
HMM_Quat result = HMM_M4ToQ_RH(m);
float cosf = 0.707107f; // cos(90/2 degrees)
float sinf = 0.707107f; // sin(90/2 degrees)
EXPECT_NEAR(result.X, 0.0f, abs_error);
EXPECT_NEAR(result.Y, 0.0f, abs_error);
EXPECT_NEAR(result.Z, sinf, abs_error);
EXPECT_NEAR(result.W, cosf, abs_error);
}
// Rotate 45 degrees on the X axis (this hits case 4)
{
HMM_Mat4 m = HMM_Rotate_RH(HMM_AngleDeg(45.0f), HMM_V3(1, 0, 0));
HMM_Quat result = HMM_M4ToQ_RH(m);
float cosf = 0.9238795325f; // cos(90/2 degrees)
float sinf = 0.3826834324f; // sin(90/2 degrees)
EXPECT_NEAR(result.X, sinf, abs_error);
EXPECT_NEAR(result.Y, 0.0f, abs_error);
EXPECT_NEAR(result.Z, 0.0f, abs_error);
EXPECT_NEAR(result.W, cosf, abs_error);
}
/* NOTE(lcf): Left-handed cases. Since both Rotate and M4ToQ are LH results should be
the same with no changes to input. */
// Rotate 90 degrees on the X axis
{
HMM_Mat4 m = HMM_Rotate_LH(HMM_AngleDeg(90.0f), HMM_V3(1, 0, 0));
HMM_Quat result = HMM_M4ToQ_LH(m);
float cosf = 0.707107f; // cos(90/2 degrees)
float sinf = 0.707107f; // sin(90/2 degrees)
EXPECT_NEAR(result.X, sinf, abs_error);
EXPECT_NEAR(result.Y, 0.0f, abs_error);
EXPECT_NEAR(result.Z, 0.0f, abs_error);
EXPECT_NEAR(result.W, cosf, abs_error);
}
// Rotate 90 degrees on the Y axis (axis not normalized, just for fun)
{
HMM_Mat4 m = HMM_Rotate_LH(HMM_AngleDeg(90.0f), HMM_V3(0, 2, 0));
HMM_Quat result = HMM_M4ToQ_LH(m);
float cosf = 0.707107f; // cos(90/2 degrees)
float sinf = 0.707107f; // sin(90/2 degrees)
EXPECT_NEAR(result.X, 0.0f, abs_error);
EXPECT_NEAR(result.Y, sinf, abs_error);
EXPECT_NEAR(result.Z, 0.0f, abs_error);
EXPECT_NEAR(result.W, cosf, abs_error);
}
// Rotate 90 degrees on the Z axis
{
HMM_Mat4 m = HMM_Rotate_LH(HMM_AngleDeg(90.0f), HMM_V3(0, 0, 1));
HMM_Quat result = HMM_M4ToQ_LH(m);
float cosf = 0.707107f; // cos(90/2 degrees)
float sinf = 0.707107f; // sin(90/2 degrees)
EXPECT_NEAR(result.X, 0.0f, abs_error);
EXPECT_NEAR(result.Y, 0.0f, abs_error);
EXPECT_NEAR(result.Z, sinf, abs_error);
EXPECT_NEAR(result.W, cosf, abs_error);
}
// Rotate 45 degrees on the X axis (this hits case 4)
{
HMM_Mat4 m = HMM_Rotate_LH(HMM_AngleDeg(45.0f), HMM_V3(1, 0, 0));
HMM_Quat result = HMM_M4ToQ_LH(m);
float cosf = 0.9238795325f; // cos(90/2 degrees)
float sinf = 0.3826834324f; // sin(90/2 degrees)
EXPECT_NEAR(result.X, sinf, abs_error);
EXPECT_NEAR(result.Y, 0.0f, abs_error);
EXPECT_NEAR(result.Z, 0.0f, abs_error);
EXPECT_NEAR(result.W, cosf, abs_error);
}
}
TEST(QuaternionOps, RotateVectorAxisAngle)
{
{
HMM_Vec3 axis = HMM_V3(0.0f, 1.0f, 0.0f);
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.Z, 1.0f, 0.001f);
}
{
HMM_Vec3 axis = HMM_V3(1.0f, 0.0f, 0.0f);
float angle = HMM_AngleTurn(1.0/8);
HMM_Vec3 result = HMM_RotateV3AxisAngle_RH(HMM_V3(0.0f, 0.0f, 1.0f), axis, angle);
EXPECT_NEAR(result.X, 0.0f, 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);
}
}
hmm_quaternion result = HMM_QuaternionFromAxisAngle(axis, angle);
EXPECT_NEAR(result.X, 0.707107f, FLT_EPSILON * 2);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
EXPECT_FLOAT_EQ(result.Z, 0.0f);
EXPECT_NEAR(result.W, 0.707107f, FLT_EPSILON * 2);
}

View File

@@ -4,36 +4,38 @@
TEST(SSE, LinearCombine)
{
HMM_Mat4 MatrixOne = HMM_M4D(2.0f);
HMM_Mat4 MatrixTwo = HMM_M4D(4.0f);
HMM_Mat4 Result;
Result.Columns[0] = HMM_LinearCombineV4M4(MatrixOne.Columns[0], MatrixTwo);
Result.Columns[1] = HMM_LinearCombineV4M4(MatrixOne.Columns[1], MatrixTwo);
Result.Columns[2] = HMM_LinearCombineV4M4(MatrixOne.Columns[2], MatrixTwo);
Result.Columns[3] = HMM_LinearCombineV4M4(MatrixOne.Columns[3], MatrixTwo);
hmm_mat4 MatrixOne = HMM_Mat4d(2.0f);
hmm_mat4 MatrixTwo = HMM_Mat4d(4.0f);
hmm_mat4 Result;
Result.Rows[0] = HMM_LinearCombineSSE(MatrixOne.Rows[0], MatrixTwo);
Result.Rows[1] = HMM_LinearCombineSSE(MatrixOne.Rows[1], MatrixTwo);
Result.Rows[2] = HMM_LinearCombineSSE(MatrixOne.Rows[2], MatrixTwo);
Result.Rows[3] = HMM_LinearCombineSSE(MatrixOne.Rows[3], MatrixTwo);
{
EXPECT_FLOAT_EQ(Result.Elements[0][0], 8.0f);
EXPECT_FLOAT_EQ(Result.Elements[0][1], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[0][2], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[0][3], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[1][0], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[1][1], 8.0f);
EXPECT_FLOAT_EQ(Result.Elements[1][1], 8.0f);
EXPECT_FLOAT_EQ(Result.Elements[1][2], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[1][3], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[2][0], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[2][1], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[2][1], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[2][2], 8.0f);
EXPECT_FLOAT_EQ(Result.Elements[2][3], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[3][0], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[3][1], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[3][1], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[3][2], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[3][3], 8.0f);
}
EXPECT_FLOAT_EQ(Result.Elements[3][3], 8.0f);
}
}
#endif

View File

@@ -28,26 +28,47 @@ TEST(ScalarMath, Trigonometry)
// checking that things work by default.
}
TEST(ScalarMath, ToRadians)
{
EXPECT_FLOAT_EQ(HMM_ToRadians(0.0f), 0.0f);
EXPECT_FLOAT_EQ(HMM_ToRadians(180.0f), HMM_PI32);
EXPECT_FLOAT_EQ(HMM_ToRadians(-180.0f), -HMM_PI32);
}
TEST(ScalarMath, SquareRoot)
{
EXPECT_FLOAT_EQ(HMM_SqrtF(16.0f), 4.0f);
EXPECT_FLOAT_EQ(HMM_SquareRootF(16.0f), 4.0f);
}
TEST(ScalarMath, RSquareRootF)
{
EXPECT_NEAR(HMM_InvSqrtF(10.0f), 0.31616211f, 0.0001f);
EXPECT_NEAR(HMM_RSquareRootF(10.0f), 0.31616211f, 0.0001f);
}
TEST(ScalarMath, Power)
{
EXPECT_FLOAT_EQ(HMM_Power(2.0f, 0), 1.0f);
EXPECT_FLOAT_EQ(HMM_Power(2.0f, 4), 16.0f);
EXPECT_FLOAT_EQ(HMM_Power(2.0f, -2), 0.25f);
}
TEST(ScalarMath, PowerF)
{
EXPECT_FLOAT_EQ(HMM_PowerF(2.0f, 0), 1.0f);
EXPECT_NEAR(HMM_PowerF(2.0f, 4.1), 17.148376f, 0.0001f);
EXPECT_NEAR(HMM_PowerF(2.0f, -2.5), 0.176777f, 0.0001f);
}
TEST(ScalarMath, Lerp)
{
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.0f, 2.0f), -2.0f);
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.5f, 2.0f), 0.0f);
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.0f, 2.0f), -2.0f);
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.5f, 2.0f), 0.0f);
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 1.0f, 2.0f), 2.0f);
}
TEST(ScalarMath, Clamp)
{
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, 0.0f, 2.0f), 0.0f);
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, -3.0f, 2.0f), -2.0f);
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, 0.0f, 2.0f), 0.0f);
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, -3.0f, 2.0f), -2.0f);
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, 3.0f, 2.0f), 2.0f);
}

View File

@@ -2,24 +2,22 @@
TEST(Subtraction, Vec2)
{
HMM_Vec2 v2_1 = HMM_V2(1.0f, 2.0f);
HMM_Vec2 v2_2 = HMM_V2(3.0f, 4.0f);
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 v2_2 = HMM_Vec2(3.0f, 4.0f);
{
HMM_Vec2 result = HMM_SubV2(v2_1, v2_2);
hmm_vec2 result = HMM_SubtractVec2(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, -2.0f);
EXPECT_FLOAT_EQ(result.Y, -2.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Sub(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, -2.0f);
EXPECT_FLOAT_EQ(result.Y, -2.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec2 result = v2_1 - v2_2;
hmm_vec2 result = HMM_Subtract(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, -2.0f);
EXPECT_FLOAT_EQ(result.Y, -2.0f);
}
{
hmm_vec2 result = v2_1 - v2_2;
EXPECT_FLOAT_EQ(result.X, -2.0f);
EXPECT_FLOAT_EQ(result.Y, -2.0f);
}
@@ -32,26 +30,24 @@ TEST(Subtraction, Vec2)
TEST(Subtraction, Vec3)
{
HMM_Vec3 v3_1 = HMM_V3(1.0f, 2.0f, 3.0f);
HMM_Vec3 v3_2 = HMM_V3(4.0f, 5.0f, 6.0f);
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3_2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
{
HMM_Vec3 result = HMM_SubV3(v3_1, v3_2);
hmm_vec3 result = HMM_SubtractVec3(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, -3.0f);
EXPECT_FLOAT_EQ(result.Y, -3.0f);
EXPECT_FLOAT_EQ(result.Z, -3.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Sub(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, -3.0f);
EXPECT_FLOAT_EQ(result.Y, -3.0f);
EXPECT_FLOAT_EQ(result.Z, -3.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec3 result = v3_1 - v3_2;
hmm_vec3 result = HMM_Subtract(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, -3.0f);
EXPECT_FLOAT_EQ(result.Y, -3.0f);
EXPECT_FLOAT_EQ(result.Z, -3.0f);
}
{
hmm_vec3 result = v3_1 - v3_2;
EXPECT_FLOAT_EQ(result.X, -3.0f);
EXPECT_FLOAT_EQ(result.Y, -3.0f);
EXPECT_FLOAT_EQ(result.Z, -3.0f);
@@ -66,28 +62,26 @@ TEST(Subtraction, Vec3)
TEST(Subtraction, Vec4)
{
HMM_Vec4 v4_1 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Vec4 v4_2 = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f);
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v4_2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
{
HMM_Vec4 result = HMM_SubV4(v4_1, v4_2);
hmm_vec4 result = HMM_SubtractVec4(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Sub(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec4 result = v4_1 - v4_2;
hmm_vec4 result = HMM_Subtract(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f);
}
{
hmm_vec4 result = v4_1 - v4_2;
EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f);
@@ -102,127 +96,10 @@ TEST(Subtraction, Vec4)
#endif
}
TEST(Subtraction, Mat2)
{
HMM_Mat2 a = HMM_M2();
HMM_Mat2 b = HMM_M2();
int Counter = 1;
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
a.Elements[Column][Row] = Counter++;
}
}
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
b.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat2 result = HMM_SubM2(b,a);
EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat2 result = HMM_Sub(b,a);
EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0);
}
#endif
#ifdef __cplusplus
{
HMM_Mat2 result = b - a;
EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0);
}
b -= a;
EXPECT_FLOAT_EQ(b.Elements[0][0], 4.0);
EXPECT_FLOAT_EQ(b.Elements[0][1], 4.0);
EXPECT_FLOAT_EQ(b.Elements[1][0], 4.0);
EXPECT_FLOAT_EQ(b.Elements[1][1], 4.0);
#endif
}
TEST(Subtraction, Mat3)
{
HMM_Mat3 a = HMM_M3();
HMM_Mat3 b = HMM_M3();
int Counter = 1;
for (int Column = 0; Column < 3; ++Column)
{
for (int Row = 0; Row < 3; ++Row)
{
a.Elements[Column][Row] = Counter++;
}
}
for (int Column = 0; Column < 3; ++Column)
{
for (int Row = 0; Row < 3; ++Row)
{
b.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat3 result = HMM_SubM3(b,a);
EXPECT_FLOAT_EQ(result.Elements[0][0], 9.0);
EXPECT_FLOAT_EQ(result.Elements[0][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0);
EXPECT_FLOAT_EQ(result.Elements[1][0], 9.0);
EXPECT_FLOAT_EQ(result.Elements[1][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[1][2], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][0], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][2], 9.0);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat3 result = HMM_Sub(b,a);
EXPECT_FLOAT_EQ(result.Elements[0][0], 9.0);
EXPECT_FLOAT_EQ(result.Elements[0][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0);
EXPECT_FLOAT_EQ(result.Elements[1][0], 9.0);
EXPECT_FLOAT_EQ(result.Elements[1][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[1][2], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][0], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][2], 9.0);
}
#endif
#ifdef __cplusplus
b -= a;
EXPECT_FLOAT_EQ(b.Elements[0][0], 9.0);
EXPECT_FLOAT_EQ(b.Elements[0][1], 9.0);
EXPECT_FLOAT_EQ(b.Elements[0][2], 9.0);
EXPECT_FLOAT_EQ(b.Elements[1][0], 9.0);
EXPECT_FLOAT_EQ(b.Elements[1][1], 9.0);
EXPECT_FLOAT_EQ(b.Elements[1][2], 9.0);
EXPECT_FLOAT_EQ(b.Elements[2][0], 9.0);
EXPECT_FLOAT_EQ(b.Elements[2][1], 9.0);
EXPECT_FLOAT_EQ(b.Elements[2][2], 9.0);
#endif
}
TEST(Subtraction, Mat4)
{
HMM_Mat4 m4_1 = HMM_M4(); // will have 1 - 16
HMM_Mat4 m4_2 = HMM_M4(); // will have 17 - 32
hmm_mat4 m4_1 = HMM_Mat4(); // will have 1 - 16
hmm_mat4 m4_2 = HMM_Mat4(); // will have 17 - 32
// Fill the matrices
int Counter = 1;
@@ -245,7 +122,7 @@ TEST(Subtraction, Mat4)
// Test the results
{
HMM_Mat4 result = HMM_SubM4(m4_1, m4_2);
hmm_mat4 result = HMM_SubtractMat4(m4_1, m4_2);
for (int Column = 0; Column < 4; ++Column)
{
for (int Row = 0; Row < 4; ++Row)
@@ -254,21 +131,19 @@ TEST(Subtraction, Mat4)
}
}
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat4 result = HMM_Sub(m4_1, m4_2);
for (int Column = 0; Column < 4; ++Column)
{
for (int Row = 0; Row < 4; ++Row)
{
EXPECT_FLOAT_EQ(result.Elements[Column][Row], -16.0f);
}
}
}
#endif
#ifdef __cplusplus
{
HMM_Mat4 result = m4_1 - m4_2;
hmm_mat4 result = HMM_Subtract(m4_1, m4_2);
for (int Column = 0; Column < 4; ++Column)
{
for (int Row = 0; Row < 4; ++Row)
{
EXPECT_FLOAT_EQ(result.Elements[Column][Row], -16.0f);
}
}
}
{
hmm_mat4 result = m4_1 - m4_2;
for (int Column = 0; Column < 4; ++Column)
{
for (int Row = 0; Row < 4; ++Row)
@@ -291,28 +166,26 @@ TEST(Subtraction, Mat4)
TEST(Subtraction, Quaternion)
{
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f);
{
HMM_Quat result = HMM_SubQ(q1, q2);
hmm_quaternion result = HMM_SubtractQuaternion(q1, q2);
EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Quat result = HMM_Sub(q1, q2);
EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Quat result = q1 - q2;
hmm_quaternion result = HMM_Subtract(q1, q2);
EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f);
}
{
hmm_quaternion result = q1 - q2;
EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f);
@@ -326,32 +199,3 @@ 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

View File

@@ -2,132 +2,76 @@
TEST(Transformations, Translate)
{
HMM_Mat4 translate = HMM_Translate(HMM_V3(1.0f, -3.0f, 6.0f));
hmm_mat4 translate = HMM_Translate(HMM_Vec3(1.0f, -3.0f, 6.0f));
HMM_Vec3 original = HMM_V3(1.0f, 2.0f, 3.0f);
HMM_Vec4 translated = HMM_MulM4V4(translate, HMM_V4V(original, 1));
hmm_vec3 original = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec4 translated = HMM_MultiplyMat4ByVec4(translate, HMM_Vec4v(original, 1));
EXPECT_NEAR(translated.X, 2.0f, 0.001f);
EXPECT_NEAR(translated.Y, -1.0f, 0.001f);
EXPECT_NEAR(translated.Z, 9.0f, 0.001f);
EXPECT_NEAR(translated.W, 1.0f, 0.001f);
EXPECT_FLOAT_EQ(translated.X, 2.0f);
EXPECT_FLOAT_EQ(translated.Y, -1.0f);
EXPECT_FLOAT_EQ(translated.Z, 9.0f);
EXPECT_FLOAT_EQ(translated.W, 1.0f);
}
TEST(Transformations, Rotate)
{
HMM_Vec3 original = HMM_V3(1.0f, 1.0f, 1.0f);
hmm_vec3 original = HMM_Vec3(1.0f, 1.0f, 1.0f);
HMM_Mat4 rotateX = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(1, 0, 0));
HMM_Vec4 rotatedX = HMM_MulM4V4(rotateX, HMM_V4V(original, 1));
EXPECT_NEAR(rotatedX.X, 1.0f, 0.001f);
EXPECT_NEAR(rotatedX.Y, -1.0f, 0.001f);
EXPECT_NEAR(rotatedX.Z, 1.0f, 0.001f);
EXPECT_NEAR(rotatedX.W, 1.0f, 0.001f);
hmm_mat4 rotateX = HMM_Rotate(90, HMM_Vec3(1, 0, 0));
hmm_vec4 rotatedX = HMM_MultiplyMat4ByVec4(rotateX, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(rotatedX.X, 1.0f);
EXPECT_FLOAT_EQ(rotatedX.Y, -1.0f);
EXPECT_FLOAT_EQ(rotatedX.Z, 1.0f);
EXPECT_FLOAT_EQ(rotatedX.W, 1.0f);
HMM_Mat4 rotateY = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(0, 1, 0));
HMM_Vec4 rotatedY = HMM_MulM4V4(rotateY, HMM_V4V(original, 1));
EXPECT_NEAR(rotatedY.X, 1.0f, 0.001f);
EXPECT_NEAR(rotatedY.Y, 1.0f, 0.001f);
EXPECT_NEAR(rotatedY.Z, -1.0f, 0.001f);
EXPECT_NEAR(rotatedY.W, 1.0f, 0.001f);
hmm_mat4 rotateY = HMM_Rotate(90, HMM_Vec3(0, 1, 0));
hmm_vec4 rotatedY = HMM_MultiplyMat4ByVec4(rotateY, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(rotatedY.X, 1.0f);
EXPECT_FLOAT_EQ(rotatedY.Y, 1.0f);
EXPECT_FLOAT_EQ(rotatedY.Z, -1.0f);
EXPECT_FLOAT_EQ(rotatedY.W, 1.0f);
HMM_Mat4 rotateZ = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(0, 0, 1));
HMM_Vec4 rotatedZ = HMM_MulM4V4(rotateZ, HMM_V4V(original, 1));
EXPECT_NEAR(rotatedZ.X, -1.0f, 0.001f);
EXPECT_NEAR(rotatedZ.Y, 1.0f, 0.001f);
EXPECT_NEAR(rotatedZ.Z, 1.0f, 0.001f);
EXPECT_NEAR(rotatedZ.W, 1.0f, 0.001f);
HMM_Mat4 rotateZLH = HMM_Rotate_LH(HMM_AngleDeg(90.0f), HMM_V3(0, 0, 1));
HMM_Vec4 rotatedZLH = HMM_MulM4V4(rotateZLH, HMM_V4V(original, 1));
EXPECT_NEAR(rotatedZLH.X, 1.0f, 0.001f);
EXPECT_NEAR(rotatedZLH.Y, -1.0f, 0.001f);
EXPECT_NEAR(rotatedZLH.Z, 1.0f, 0.001f);
EXPECT_NEAR(rotatedZLH.W, 1.0f, 0.001f);
hmm_mat4 rotateZ = HMM_Rotate(90, HMM_Vec3(0, 0, 1));
hmm_vec4 rotatedZ = HMM_MultiplyMat4ByVec4(rotateZ, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(rotatedZ.X, -1.0f);
EXPECT_FLOAT_EQ(rotatedZ.Y, 1.0f);
EXPECT_FLOAT_EQ(rotatedZ.Z, 1.0f);
EXPECT_FLOAT_EQ(rotatedZ.W, 1.0f);
}
TEST(Transformations, Scale)
{
HMM_Mat4 scale = HMM_Scale(HMM_V3(2.0f, -3.0f, 0.5f));
hmm_mat4 scale = HMM_Scale(HMM_Vec3(2.0f, -3.0f, 0.5f));
HMM_Vec3 original = HMM_V3(1.0f, 2.0f, 3.0f);
HMM_Vec4 scaled = HMM_MulM4V4(scale, HMM_V4V(original, 1));
hmm_vec3 original = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec4 scaled = HMM_MultiplyMat4ByVec4(scale, HMM_Vec4v(original, 1));
EXPECT_NEAR(scaled.X, 2.0f, 0.001f);
EXPECT_NEAR(scaled.Y, -6.0f, 0.001f);
EXPECT_NEAR(scaled.Z, 1.5f, 0.001f);
EXPECT_NEAR(scaled.W, 1.0f, 0.001f);
EXPECT_FLOAT_EQ(scaled.X, 2.0f);
EXPECT_FLOAT_EQ(scaled.Y, -6.0f);
EXPECT_FLOAT_EQ(scaled.Z, 1.5f);
EXPECT_FLOAT_EQ(scaled.W, 1.0f);
}
TEST(Transformations, LookAt)
{
const float abs_error = 0.001f;
const float abs_error = 0.0001f;
{
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(HMM_Vec3(1.0f, 0.0f, 0.0f), HMM_Vec3(0.0f, 2.0f, 1.0f), HMM_Vec3(2.0f, 1.0f, 1.0f));
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][2], 0.408248f, abs_error);
EXPECT_NEAR(result.Elements[0][3], 0.0f, abs_error);
EXPECT_NEAR(result.Elements[1][0], 0.507093f, abs_error);
EXPECT_NEAR(result.Elements[1][1], 0.276026f, abs_error);
EXPECT_NEAR(result.Elements[1][2], -0.816497f, abs_error);
EXPECT_NEAR(result.Elements[1][3], 0.0f, abs_error);
EXPECT_NEAR(result.Elements[2][0], -0.845154f, abs_error);
EXPECT_NEAR(result.Elements[2][1], 0.345033f, abs_error);
EXPECT_NEAR(result.Elements[2][2], -0.408248f, abs_error);
EXPECT_NEAR(result.Elements[2][3], 0.0f, abs_error);
EXPECT_NEAR(result.Elements[3][0], -0.169031f, abs_error);
EXPECT_NEAR(result.Elements[3][1], -0.897085f, abs_error);
EXPECT_NEAR(result.Elements[3][2], -0.408248f, abs_error);
EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error);
}
{
HMM_Mat4 result = HMM_LookAt_LH(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][1], 0.897085f, abs_error);
EXPECT_NEAR(result.Elements[0][2], -0.408248f, abs_error);
EXPECT_NEAR(result.Elements[0][3], 0.0f, abs_error);
EXPECT_NEAR(result.Elements[1][0], -0.507093f, abs_error);
EXPECT_NEAR(result.Elements[1][1], 0.276026f, abs_error);
EXPECT_NEAR(result.Elements[1][2], 0.816497f, abs_error);
EXPECT_NEAR(result.Elements[1][3], 0.0f, abs_error);
EXPECT_NEAR(result.Elements[2][0], 0.845154f, abs_error);
EXPECT_NEAR(result.Elements[2][1], 0.345033f, abs_error);
EXPECT_NEAR(result.Elements[2][2], 0.408248f, abs_error);
EXPECT_NEAR(result.Elements[2][3], 0.0f, abs_error);
EXPECT_NEAR(result.Elements[3][0], 0.169031f, abs_error);
EXPECT_NEAR(result.Elements[3][1], -0.897085f, abs_error);
EXPECT_NEAR(result.Elements[3][2], 0.408248f, 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);
}
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][2], 0.408248f, abs_error);
EXPECT_FLOAT_EQ(result.Elements[0][3], 0.0f);
EXPECT_NEAR(result.Elements[1][0], 0.507093f, abs_error);
EXPECT_NEAR(result.Elements[1][1], 0.276026f, abs_error);
EXPECT_NEAR(result.Elements[1][2], -0.816497f, abs_error);
EXPECT_FLOAT_EQ(result.Elements[1][3], 0.0f);
EXPECT_NEAR(result.Elements[2][0], -0.845154f, abs_error);
EXPECT_NEAR(result.Elements[2][1], 0.345033f, abs_error);
EXPECT_NEAR(result.Elements[2][2], -0.408248f, abs_error);
EXPECT_FLOAT_EQ(result.Elements[2][3], 0.0f);
EXPECT_NEAR(result.Elements[3][0], -0.169031f, abs_error);
EXPECT_NEAR(result.Elements[3][1], -0.897085f, abs_error);
EXPECT_NEAR(result.Elements[3][2], -0.408248f, abs_error);
EXPECT_FLOAT_EQ(result.Elements[3][3], 1.0f);
}

View File

@@ -2,83 +2,83 @@
TEST(VectorOps, LengthSquared)
{
HMM_Vec2 v2 = HMM_V2(1.0f, -2.0f);
HMM_Vec3 v3 = HMM_V3(1.0f, -2.0f, 3.0f);
HMM_Vec4 v4 = HMM_V4(1.0f, -2.0f, 3.0f, 1.0f);
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f);
hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f);
hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, 1.0f);
EXPECT_FLOAT_EQ(HMM_LenSqrV2(v2), 5.0f);
EXPECT_FLOAT_EQ(HMM_LenSqrV3(v3), 14.0f);
EXPECT_FLOAT_EQ(HMM_LenSqrV4(v4), 15.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec2(v2), 5.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec3(v3), 14.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec4(v4), 15.0f);
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_LenSqr(v2), 5.0f);
EXPECT_FLOAT_EQ(HMM_LenSqr(v3), 14.0f);
EXPECT_FLOAT_EQ(HMM_LenSqr(v4), 15.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(HMM_LengthSquared(v2), 5.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquared(v3), 14.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquared(v4), 15.0f);
#endif
}
TEST(VectorOps, Length)
{
HMM_Vec2 v2 = HMM_V2(1.0f, -9.0f);
HMM_Vec3 v3 = HMM_V3(2.0f, -3.0f, 6.0f);
HMM_Vec4 v4 = HMM_V4(2.0f, -3.0f, 6.0f, 12.0f);
hmm_vec2 v2 = HMM_Vec2(1.0f, -9.0f);
hmm_vec3 v3 = HMM_Vec3(2.0f, -3.0f, 6.0f);
hmm_vec4 v4 = HMM_Vec4(2.0f, -3.0f, 6.0f, 12.0f);
EXPECT_FLOAT_EQ(HMM_LenV2(v2), 9.0553856f);
EXPECT_FLOAT_EQ(HMM_LenV3(v3), 7.0f);
EXPECT_FLOAT_EQ(HMM_LenV4(v4), 13.892444f);
EXPECT_FLOAT_EQ(HMM_LengthVec2(v2), 9.0553856f);
EXPECT_FLOAT_EQ(HMM_LengthVec3(v3), 7.0f);
EXPECT_FLOAT_EQ(HMM_LengthVec4(v4), 13.892444f);
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_Len(v2), 9.0553856f);
EXPECT_FLOAT_EQ(HMM_Len(v3), 7.0f);
EXPECT_FLOAT_EQ(HMM_Len(v4), 13.892444f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(HMM_Length(v2), 9.0553856f);
EXPECT_FLOAT_EQ(HMM_Length(v3), 7.0f);
EXPECT_FLOAT_EQ(HMM_Length(v4), 13.892444f);
#endif
}
TEST(VectorOps, Normalize)
{
HMM_Vec2 v2 = HMM_V2(1.0f, -2.0f);
HMM_Vec3 v3 = HMM_V3(1.0f, -2.0f, 3.0f);
HMM_Vec4 v4 = HMM_V4(1.0f, -2.0f, 3.0f, -1.0f);
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f);
hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f);
hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, -1.0f);
{
HMM_Vec2 result = HMM_NormV2(v2);
EXPECT_NEAR(HMM_LenV2(result), 1.0f, 0.001f);
hmm_vec2 result = HMM_NormalizeVec2(v2);
EXPECT_FLOAT_EQ(HMM_LengthVec2(result), 1.0f);
EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f);
}
{
HMM_Vec3 result = HMM_NormV3(v3);
EXPECT_NEAR(HMM_LenV3(result), 1.0f, 0.001f);
hmm_vec3 result = HMM_NormalizeVec3(v3);
EXPECT_FLOAT_EQ(HMM_LengthVec3(result), 1.0f);
EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f);
EXPECT_GT(result.Z, 0.0f);
}
{
HMM_Vec4 result = HMM_NormV4(v4);
EXPECT_NEAR(HMM_LenV4(result), 1.0f, 0.001f);
hmm_vec4 result = HMM_NormalizeVec4(v4);
EXPECT_FLOAT_EQ(HMM_LengthVec4(result), 1.0f);
EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f);
EXPECT_GT(result.Z, 0.0f);
EXPECT_LT(result.W, 0.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
#ifdef __cplusplus
{
HMM_Vec2 result = HMM_Norm(v2);
EXPECT_NEAR(HMM_LenV2(result), 1.0f, 0.001f);
hmm_vec2 result = HMM_Normalize(v2);
EXPECT_FLOAT_EQ(HMM_LengthVec2(result), 1.0f);
EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f);
}
{
HMM_Vec3 result = HMM_Norm(v3);
EXPECT_NEAR(HMM_LenV3(result), 1.0f, 0.001f);
hmm_vec3 result = HMM_Normalize(v3);
EXPECT_FLOAT_EQ(HMM_LengthVec3(result), 1.0f);
EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f);
EXPECT_GT(result.Z, 0.0f);
}
{
HMM_Vec4 result = HMM_Norm(v4);
EXPECT_NEAR(HMM_LenV4(result), 1.0f, 0.001f);
hmm_vec4 result = HMM_Normalize(v4);
EXPECT_FLOAT_EQ(HMM_LengthVec4(result), 1.0f);
EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f);
EXPECT_GT(result.Z, 0.0f);
@@ -89,43 +89,43 @@ TEST(VectorOps, Normalize)
TEST(VectorOps, NormalizeZero)
{
HMM_Vec2 v2 = HMM_V2(0.0f, 0.0f);
HMM_Vec3 v3 = HMM_V3(0.0f, 0.0f, 0.0f);
HMM_Vec4 v4 = HMM_V4(0.0f, 0.0f, 0.0f, 0.0f);
hmm_vec2 v2 = HMM_Vec2(0.0f, 0.0f);
hmm_vec3 v3 = HMM_Vec3(0.0f, 0.0f, 0.0f);
hmm_vec4 v4 = HMM_Vec4(0.0f, 0.0f, 0.0f, 0.0f);
{
HMM_Vec2 result = HMM_NormV2(v2);
hmm_vec2 result = HMM_NormalizeVec2(v2);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
}
{
HMM_Vec3 result = HMM_NormV3(v3);
hmm_vec3 result = HMM_NormalizeVec3(v3);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
EXPECT_FLOAT_EQ(result.Z, 0.0f);
}
{
HMM_Vec4 result = HMM_NormV4(v4);
hmm_vec4 result = HMM_NormalizeVec4(v4);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
EXPECT_FLOAT_EQ(result.Z, 0.0f);
EXPECT_FLOAT_EQ(result.W, 0.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
#ifdef __cplusplus
{
HMM_Vec2 result = HMM_Norm(v2);
hmm_vec2 result = HMM_Normalize(v2);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
}
{
HMM_Vec3 result = HMM_Norm(v3);
hmm_vec3 result = HMM_Normalize(v3);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
EXPECT_FLOAT_EQ(result.Z, 0.0f);
}
{
HMM_Vec4 result = HMM_Norm(v4);
hmm_vec4 result = HMM_Normalize(v4);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
EXPECT_FLOAT_EQ(result.Z, 0.0f);
@@ -136,10 +136,10 @@ TEST(VectorOps, NormalizeZero)
TEST(VectorOps, Cross)
{
HMM_Vec3 v1 = HMM_V3(1.0f, 2.0f, 3.0f);
HMM_Vec3 v2 = HMM_V3(4.0f, 5.0f, 6.0f);
hmm_vec3 v1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 v2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
HMM_Vec3 result = HMM_Cross(v1, v2);
hmm_vec3 result = HMM_Cross(v1, v2);
EXPECT_FLOAT_EQ(result.X, -3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
@@ -148,107 +148,45 @@ TEST(VectorOps, Cross)
TEST(VectorOps, DotVec2)
{
HMM_Vec2 v1 = HMM_V2(1.0f, 2.0f);
HMM_Vec2 v2 = HMM_V2(3.0f, 4.0f);
hmm_vec2 v1 = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 v2 = HMM_Vec2(3.0f, 4.0f);
EXPECT_FLOAT_EQ(HMM_DotV2(v1, v2), 11.0f);
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_DotVec2(v1, v2), 11.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 11.0f);
#endif
}
TEST(VectorOps, DotVec3)
{
HMM_Vec3 v1 = HMM_V3(1.0f, 2.0f, 3.0f);
HMM_Vec3 v2 = HMM_V3(4.0f, 5.0f, 6.0f);
hmm_vec3 v1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 v2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
EXPECT_FLOAT_EQ(HMM_DotV3(v1, v2), 32.0f);
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_DotVec3(v1, v2), 32.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 32.0f);
#endif
}
TEST(VectorOps, DotVec4)
{
HMM_Vec4 v1 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Vec4 v2 = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f);
hmm_vec4 v1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
EXPECT_FLOAT_EQ(HMM_DotV4(v1, v2), 70.0f);
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_DotVec4(v1, v2), 70.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 70.0f);
#endif
}
TEST(VectorOps, LerpV2)
{
HMM_Vec2 v1 = HMM_V2(1.0f, 0.0f);
HMM_Vec2 v2 = HMM_V2(0.0f, 1.0f);
{
HMM_Vec2 result = HMM_LerpV2(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.5f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Lerp(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.5f);
}
#endif
}
TEST(VectorOps, LerpV3)
{
HMM_Vec3 v1 = HMM_V3(1.0f, 1.0f, 0.0f);
HMM_Vec3 v2 = HMM_V3(0.0f, 1.0f, 1.0f);
{
HMM_Vec3 result = HMM_LerpV3(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 0.5f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Lerp(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 0.5f);
}
#endif
}
TEST(VectorOps, LerpV4)
{
HMM_Vec4 v1 = HMM_V4(1.0f, 1.0f, 0.0f, 1.0f);
HMM_Vec4 v2 = HMM_V4(0.0f, 1.0f, 1.0f, 1.0f);
{
HMM_Vec4 result = HMM_LerpV4(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 0.5f);
EXPECT_FLOAT_EQ(result.W, 1.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Lerp(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 0.5f);
EXPECT_FLOAT_EQ(result.W, 1.0f);
}
#endif
}
/*
* MatrixOps tests
*/
TEST(MatrixOps, TransposeM4)
TEST(MatrixOps, Transpose)
{
HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
hmm_mat4 m4 = HMM_Mat4(); // will have 1 - 16
// Fill the matrix
int Counter = 1;
@@ -262,7 +200,7 @@ TEST(MatrixOps, TransposeM4)
}
// Test the matrix
HMM_Mat4 result = HMM_TransposeM4(m4);
hmm_mat4 result = HMM_Transpose(m4);
EXPECT_FLOAT_EQ(result.Elements[0][0], 1.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 5.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);

View File

@@ -1,9 +1,7 @@
#include "HandmadeTest.h"
#include "hmm_test.h"
int main()
{
int tests_failed = hmt_run_all_tests();
int coverage_failed = hmt_check_all_coverage();
return tests_failed || coverage_failed;
return hmt_run_all_tests();
}

View File

@@ -1,15 +1,11 @@
#include <float.h>
#define HANDMADE_TEST_IMPLEMENTATION
#include "HandmadeTest.h"
#undef COVERAGE // Make sure we don't double-define initializers from the header part
#include "../HandmadeMath.h"
#include "categories/ScalarMath.h"
#include "categories/Initialization.h"
#include "categories/VectorOps.h"
#include "categories/MatrixOps.h"
#include "categories/QuaternionOps.h"
#include "categories/Addition.h"
#include "categories/Subtraction.h"

View File

@@ -1,27 +0,0 @@
@echo off
if not exist "build" mkdir build
pushd build
clang-cl /std:c11 /Fehmm_test_c11.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c11 || exit /b 1
clang-cl /std:c11 /Fehmm_test_c11_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c11_no_simd || exit /b 1
clang-cl /std:c17 /Fehmm_test_c17.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c17 || exit /b 1
clang-cl /std:c++14 /Fehmm_test_cpp14.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
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

View File

@@ -1,32 +0,0 @@
@echo off
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
pushd build
cl /std:c11 /Fehmm_test_c11.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c11 || exit /b 1
cl /std:c11 /Fehmm_test_c11_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c11_no_simd || exit /b 1
cl /std:c17 /Fehmm_test_c17.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c17 || exit /b 1
cl /std:c++14 /Fehmm_test_cpp14.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
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

View File

@@ -1,24 +0,0 @@
# Handmade Math 2.0 Update Tool
Due to the large number of breaking naming changes in Handmade Math 2, we provide a small Python script to update your programs automatically. It can run on individual files or on all files in a directory (recursively).
**Warning!** This tool is not very smart! Please ensure that your work is committed and backed up, in case you have to revert this tool's changes.
```
# see usage info and options
> python3 update_hmm.py -h
usage: update_hmm [-h] [--exts .foo [.foo ...]] filename [filename ...]
...
# run on individual files
> python3 update_hmm.py MyPlatformLayer.c MyPlatformLayer.h
Updating: MyPlatformLayer.c
Updating: MyPlatformLayer.h
Updated 2 files with 0 warnings.
# run on a whole directory
> python3 update_hmm.py projects/MyCoolGame
Updating: projects/MyCoolGame/src/MyPlatformLayer.c
Updating: projects/MyCoolGame/include/MyPlatformLayer.h
...
```

View File

@@ -1,166 +0,0 @@
#!/usr/bin/env python3
import argparse
import os
import re
typeReplacements = [
('hmm_', 'HMM_'),
('vec', 'Vec'),
('mat', 'Mat'),
('quaternion', 'Quaternion'),
('bool', 'Bool'),
('.InternalElementsSSE', '.SSE'),
]
funcReplacements = [
('HMM_', 'HMM_'),
('Vec', 'V'),
('Mat', 'M'),
('Quaternion', 'Q'),
('Equals', 'Eq'),
('Subtract', 'Sub'),
('Multiply', 'Mul'),
('Divide', 'Div'),
('Inverse', 'Inv'),
('RSquareRoot', 'InvSqrt'),
('SquareRoot', 'Sqrt'),
('Squared', 'Sqr'),
('Length', 'Len'),
('Slerp', 'SLerp'),
('By', ''),
('LinearCombineSSE', 'LinearCombineV4M4'),
('Transpose', 'TransposeM4'),
('Fast', ''), # TODO(port): emit warning, lower precision
('Normalize', 'Norm'),
('ToRadians', 'ToRad')
]
handedFuncs = [
'Perspective',
'Rotate',
'Orthographic',
'LookAt',
'FromAxisAngle',
'ToQuaternion',
]
projectionFuncs = [
'Perspective',
'Orthographic',
]
numFiles = 0
numWarnings = 0
def printWarning(msg):
global numWarnings
numWarnings += 1
print('WARNING: {}'.format(msg))
def updateFile(filename):
global numFiles
print('Updating: {}'.format(filename))
numFiles += 1
result = ''
with open(filename, 'r', newline='') as f:
for lineNo, line in enumerate(f):
updatedLine = line
def printLineWarning(msg):
printWarning(' Line {}: {}'.format(lineNo + 1, msg))
def replaceName(m):
name = m.group()
if name.startswith('hmm_'):
# do type replacements
for before, after in typeReplacements:
if before not in name:
continue
name = name.replace(before, after)
else:
# do func replacements
for before, after in funcReplacements:
if before not in name:
continue
name = name.replace(before, after)
if after == 'LinearCombineV4M4':
printLineWarning('HMM_LinearCombineSSE is now HMM_LinearCombineV4M4, and will now use a fallback method when SSE is not available. You no longer need to check for the availability of SSE.')
if after == 'V' or after == 'M':
# uppercase the modifier, if any
name = re.sub(
r'[VM]\d[ivfd]?',
lambda m: m.group().upper(),
name
)
# and also nuke the integer constructors
vecIntMatch = re.search(r'(V\d)I', name)
if vecIntMatch:
name = name.replace(vecIntMatch.group(), vecIntMatch.group(1))
# add handedness / NDC modifiers
if not any(x in name for x in ['RH', 'LH', 'NO', 'ZO']):
for handedFunc in handedFuncs:
suffixed = handedFunc + '_RH'
if handedFunc in projectionFuncs:
suffixed += '_NO'
name = name.replace(handedFunc, suffixed)
return name
def wrapDegrees(m):
name = m.group('name')
arg = m.group('arg')
if '(' in arg:
# all bets are off, don't wrap the argument
printLineWarning('{} now takes radians, but we were unable to automatically wrap the first argument with HMM_AngleDeg().'.format(name))
return m.group()
return '{}(HMM_AngleDeg({}),'.format(name, arg)
updatedLine = re.sub(r'(hmm_|HMM_)\w+', replaceName, updatedLine)
updatedLine = re.sub(r'(?P<name>HMM_Perspective_RH_NO|HMM_Rotate_RH)\((?P<arg>.*?),', wrapDegrees, updatedLine)
result += updatedLine
with open(filename, 'w', newline='') as f:
f.write(result)
parser = argparse.ArgumentParser(
prog = 'update_hmm',
description = 'Updates C and C++ source code to use Handmade Math 2.0.',
)
parser.add_argument(
'filename', nargs='+',
help='A file or directory to update to HMM 2.0. If a directory, all files with extensions from --exts will be processed.',
)
parser.add_argument(
'--exts', nargs='+', default=['.c', '.cpp', '.h', '.hpp'],
help='File extensions to run the script on, when targeting a directory. Default: .c, .cpp, .h, .hpp.',
metavar='.foo',
)
args = parser.parse_args()
for path in args.filename:
filenames = []
if os.path.isfile(path):
filenames = [path]
else:
for root, dirs, files in os.walk(path):
for file in files:
if file == 'HandmadeMath.h':
printWarning('HandmadeMath.h will not be replaced by this script.')
elif file.endswith(tuple(args.exts)):
filenames.append(os.path.join(root, file))
for filename in filenames:
try:
updateFile(filename)
except UnicodeDecodeError:
pass
print('Updated {} files with {} warnings.'.format(numFiles, numWarnings))