mirror of
https://github.com/HandmadeMath/HandmadeMath.git
synced 2025-12-28 15:44:33 +00:00
Compare commits
36 Commits
benchmark2
...
2.0.0-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f106a0f5f3 | ||
|
|
c24e4ff873 | ||
|
|
ba5405ac0f | ||
|
|
d69a859d73 | ||
|
|
8c18186b3b | ||
|
|
5f816bf9b3 | ||
|
|
c5bc802042 | ||
|
|
43afc87fa7 | ||
|
|
5bbac2167e | ||
|
|
655c662528 | ||
|
|
1f0c6ba493 | ||
|
|
1d82b4f0bc | ||
|
|
2fa0b36715 | ||
|
|
ad169e649c | ||
|
|
1900cc9275 | ||
|
|
ddb9971e71 | ||
|
|
341a376a17 | ||
|
|
c825fe48cf | ||
|
|
15bef820db | ||
|
|
fe32f081f2 | ||
|
|
785f19d4a7 | ||
|
|
a9b08b9147 | ||
|
|
f376f2a2a7 | ||
|
|
78e6feea82 | ||
|
|
21aa828a08 | ||
|
|
93e56be543 | ||
|
|
45c91702a9 | ||
|
|
f7c8e1f7d1 | ||
|
|
5ca1d58b36 | ||
|
|
5bf727dbd5 | ||
|
|
295f6c476f | ||
|
|
e095aefaf7 | ||
|
|
4e2f47db55 | ||
|
|
bee0e0c569 | ||
|
|
f8b3a84cec | ||
|
|
77914405c3 |
34
.github/workflows/ci.yml
vendored
Normal file
34
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
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'
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -31,5 +31,4 @@
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
hmm_test
|
||||
hmm_test*
|
||||
test/build
|
||||
|
||||
0
.gitmodules
vendored
0
.gitmodules
vendored
12
.travis.yml
12
.travis.yml
@@ -1,12 +0,0 @@
|
||||
language: cpp
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
install:
|
||||
- cd test
|
||||
- make
|
||||
script:
|
||||
- ./hmm_test_c
|
||||
- ./hmm_test_c_no_sse
|
||||
- ./hmm_test_cpp
|
||||
- ./hmm_test_cpp_no_sse
|
||||
@@ -1,43 +0,0 @@
|
||||
# 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.
|
||||
4856
HandmadeMath.h
4856
HandmadeMath.h
File diff suppressed because it is too large
Load Diff
48
README.md
48
README.md
@@ -1,39 +1,25 @@
|
||||
# Handmade Math
|
||||
|
||||
[](https://travis-ci.org/StrangeZak/Handmade-Math)
|
||||
A single-file, cross-platform, public domain game math library for both C and C++. Supports vectors, matrices, quaternions, and all the utilities you'd expect.
|
||||
|
||||
A single-file, cross-platform, public domain game math library for C/C++.
|
||||
To get started, go download [the latest release](https://github.com/HandmadeMath/HandmadeMath/releases).
|
||||
|
||||
To get started, go download [the latest release](https://github.com/HandmadeMath/Handmade-Math/releases).
|
||||
> If you are upgrading to version 2 of Handmade Math, save yourself some time and use our [automatic update tool](./update).
|
||||
|
||||
-----
|
||||
Here's what sets Handmade Math apart:
|
||||
|
||||
Version | Changes |
|
||||
----------------|----------------|
|
||||
**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 |
|
||||
- **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.
|
||||
- **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 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.
|
||||
|
||||
-----
|
||||
|
||||
## FAQ
|
||||
|
||||
@@ -44,3 +30,7 @@ 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.
|
||||
|
||||
**What if I don't want the `HMM_` prefix?**
|
||||
|
||||
Do a find and replace in the library source.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define HANDMADE_MATH_IMPLEMENTATION
|
||||
#define HANDMADE_MATH_NO_INLINE
|
||||
#ifndef WITHOUT_COVERAGE
|
||||
#include "HandmadeTest.h"
|
||||
#endif
|
||||
|
||||
#include "../HandmadeMath.h"
|
||||
|
||||
@@ -1,104 +1,406 @@
|
||||
/*
|
||||
HandmadeTest.h
|
||||
|
||||
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 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:
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
=============================================================================
|
||||
|
||||
If Handmade Test's macros are conflicting with existing macros in your
|
||||
project, you may define HMT_SAFE_MACROS before you include HandmadeTest.h.
|
||||
You may then prefix each macro with HMT_. For example, you may use HMT_TEST
|
||||
instead of TEST and HMT_EXPECT_TRUE instead of EXPECT_TRUE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef HANDMADETEST_H
|
||||
#define HANDMADETEST_H
|
||||
|
||||
#include <float.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int hmt_count_tests = 0;
|
||||
int hmt_count_failedtests = 0;
|
||||
int hmt_count_failures = 0;
|
||||
#include "initializer.h"
|
||||
|
||||
#define RESET "\033[0m"
|
||||
#define RED "\033[31m"
|
||||
#define GREEN "\033[32m"
|
||||
#define HMT_RESET "\033[0m"
|
||||
#define HMT_RED "\033[31m"
|
||||
#define HMT_GREEN "\033[32m"
|
||||
|
||||
#define CATEGORY_BEGIN(name) { \
|
||||
int count_categorytests = 0; \
|
||||
int count_categoryfailedtests = 0; \
|
||||
int count_categoryfailures = 0; \
|
||||
printf("\n" #name ":\n");
|
||||
#define CATEGORY_END(name) \
|
||||
hmt_count_tests += count_categorytests; \
|
||||
hmt_count_failedtests += count_categoryfailedtests; \
|
||||
hmt_count_failures += count_categoryfailures; \
|
||||
printf("%d/%d tests passed, %d failures\n", count_categorytests - count_categoryfailedtests, count_categorytests, count_categoryfailures); \
|
||||
}
|
||||
#define HMT_ARRAY_SIZE 1024
|
||||
|
||||
#define TEST_BEGIN(name) { \
|
||||
int count_testcases = 0, count_testfailures = 0; \
|
||||
count_categorytests++; \
|
||||
printf(" " #name ":");
|
||||
#define TEST_END() \
|
||||
count_categoryfailures += count_testfailures; \
|
||||
if (count_testfailures > 0) { \
|
||||
count_categoryfailedtests++; \
|
||||
printf("\n " RED "(%d/%d passed)" RESET, count_testcases - count_testfailures, count_testcases); \
|
||||
printf("\n"); \
|
||||
} else { \
|
||||
printf(GREEN " [PASS] (%d/%d passed) \n" RESET, count_testcases - count_testfailures, count_testcases); \
|
||||
} \
|
||||
}
|
||||
typedef struct hmt_testresult_struct {
|
||||
int count_cases;
|
||||
int count_failures;
|
||||
} hmt_testresult;
|
||||
|
||||
#define CASE_START() \
|
||||
count_testcases++;
|
||||
typedef void (*hmt_test_func)(hmt_testresult*);
|
||||
|
||||
#define CASE_FAIL() \
|
||||
count_testfailures++; \
|
||||
printf("\n - " RED "[FAIL] (%d) " RESET, __LINE__);
|
||||
typedef struct hmt_test_struct {
|
||||
const char* name;
|
||||
hmt_test_func func;
|
||||
} hmt_test;
|
||||
|
||||
typedef struct hmt_category_struct {
|
||||
const char* name;
|
||||
int num_tests;
|
||||
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 EXPECT_TRUE(_actual) do { \
|
||||
CASE_START(); \
|
||||
#define HMT_EXPECT_TRUE(_actual) { \
|
||||
_HMT_CASE_START(); \
|
||||
if (!(_actual)) { \
|
||||
CASE_FAIL(); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected true but got something false"); \
|
||||
} \
|
||||
} while (0)
|
||||
} \
|
||||
|
||||
#define EXPECT_FALSE(_actual) do { \
|
||||
CASE_START(); \
|
||||
#define HMT_EXPECT_FALSE(_actual) { \
|
||||
_HMT_CASE_START(); \
|
||||
if (_actual) { \
|
||||
CASE_FAIL(); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected false but got something true"); \
|
||||
} \
|
||||
} while (0)
|
||||
} \
|
||||
|
||||
#define EXPECT_FLOAT_EQ(_actual, _expected) do { \
|
||||
CASE_START(); \
|
||||
#define HMT_EXPECT_FLOAT_EQ(_actual, _expected) { \
|
||||
_HMT_CASE_START(); \
|
||||
float actual = (_actual); \
|
||||
float diff = actual - (_expected); \
|
||||
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
|
||||
CASE_FAIL(); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected %f, got %f", (_expected), actual); \
|
||||
} \
|
||||
} while (0)
|
||||
} \
|
||||
|
||||
#define EXPECT_NEAR(_actual, _expected, _epsilon) do { \
|
||||
CASE_START(); \
|
||||
#define HMT_EXPECT_NEAR(_actual, _expected, _epsilon) { \
|
||||
_HMT_CASE_START(); \
|
||||
float actual = (_actual); \
|
||||
float diff = actual - (_expected); \
|
||||
if (diff < -(_epsilon) || (_epsilon) < diff) { \
|
||||
CASE_FAIL(); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected %f, got %f", (_expected), actual); \
|
||||
} \
|
||||
} while (0)
|
||||
} \
|
||||
|
||||
#define EXPECT_LT(_actual, _expected) do { \
|
||||
CASE_START(); \
|
||||
#define HMT_EXPECT_LT(_actual, _expected) { \
|
||||
_HMT_CASE_START(); \
|
||||
if ((_actual) >= (_expected)) { \
|
||||
CASE_FAIL(); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected %f to be less than %f", (_actual), (_expected)); \
|
||||
} \
|
||||
} while (0)
|
||||
} \
|
||||
|
||||
#define EXPECT_GT(_actual, _expected) do { \
|
||||
CASE_START(); \
|
||||
#define HMT_EXPECT_GT(_actual, _expected) { \
|
||||
_HMT_CASE_START(); \
|
||||
if ((_actual) <= (_expected)) { \
|
||||
CASE_FAIL(); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected %f to be greater than %f", (_actual), (_expected)); \
|
||||
} \
|
||||
} while (0)
|
||||
} \
|
||||
|
||||
#endif
|
||||
#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_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
|
||||
|
||||
#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;
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
return cat;
|
||||
}
|
||||
|
||||
hmt_test _hmt_new_test(const char* name, hmt_test_func func) {
|
||||
hmt_test test = {
|
||||
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) {
|
||||
// initialize categories array if not initialized
|
||||
if (!_hmt_categories) {
|
||||
_hmt_categories = (hmt_category*) malloc(HMT_ARRAY_SIZE * 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) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new category if necessary
|
||||
if (cat_index >= _hmt_num_categories) {
|
||||
_hmt_categories[cat_index] = _hmt_new_category(category);
|
||||
_hmt_num_categories++;
|
||||
}
|
||||
|
||||
hmt_category* cat = &_hmt_categories[cat_index];
|
||||
|
||||
// Add the test to the category
|
||||
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;
|
||||
int count_catfailures = 0;
|
||||
|
||||
printf("\n%s:\n", cat.name);
|
||||
|
||||
for (int j = 0; j < cat.num_tests; j++) {
|
||||
hmt_test test = cat.tests[j];
|
||||
|
||||
printf(" %s:", test.name);
|
||||
|
||||
hmt_testresult result = {
|
||||
0, // count_cases
|
||||
0, // count_failures
|
||||
};
|
||||
test.func(&result);
|
||||
|
||||
count_catfailures += result.count_failures;
|
||||
|
||||
if (result.count_failures > 0) {
|
||||
count_catfailedtests++;
|
||||
printf("\n " HMT_RED "(%d/%d passed)" HMT_RESET, result.count_cases - result.count_failures, result.count_cases);
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(HMT_GREEN " [PASS] (%d/%d passed) \n" HMT_RESET, result.count_cases - result.count_failures, result.count_cases);
|
||||
}
|
||||
}
|
||||
|
||||
count_alltests += cat.num_tests;
|
||||
count_allfailedtests += count_catfailedtests;
|
||||
count_allfailures += count_catfailures;
|
||||
|
||||
printf("%d/%d tests passed, %d failures\n", cat.num_tests - count_catfailedtests, cat.num_tests, count_catfailures);
|
||||
}
|
||||
|
||||
if (count_allfailedtests > 0) {
|
||||
printf(HMT_RED);
|
||||
} else {
|
||||
printf(HMT_GREEN);
|
||||
}
|
||||
printf("\n%d/%d tests passed overall, %d failures\n" HMT_RESET, count_alltests - count_allfailedtests, count_alltests, count_allfailures);
|
||||
|
||||
printf("\n");
|
||||
|
||||
return (count_allfailedtests > 0);
|
||||
}
|
||||
|
||||
int hmt_check_all_coverage() {
|
||||
printf("Coverage:\n");
|
||||
|
||||
int count_failures = 0;
|
||||
|
||||
for (int i = 0; i < _hmt_num_covercases; i++) {
|
||||
hmt_covercase covercase = _hmt_covercases[i];
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
printf("\n");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return (count_failures > 0);
|
||||
}
|
||||
|
||||
#endif // HANDMADE_TEST_IMPLEMENTATION_GUARD
|
||||
#endif // HANDMADE_TEST_IMPLEMENTATION
|
||||
|
||||
@@ -1,37 +1,78 @@
|
||||
ROOT_DIR=..
|
||||
BUILD_DIR=./build
|
||||
|
||||
CXXFLAGS+=-g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers
|
||||
CXXFLAGS+=-g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers -Wfloat-equal
|
||||
|
||||
all: c c_no_sse cpp cpp_no_sse
|
||||
all: c c_no_sse cpp cpp_no_sse build_c_without_coverage build_cpp_without_coverage
|
||||
|
||||
build_all: build_c build_c_no_sse build_cpp build_cpp_no_sse
|
||||
|
||||
clean:
|
||||
rm -f hmm_test_c hmm_test_cpp hmm_test_c_no_sse hmm_test_cpp_no_sse *.o
|
||||
rm -rf $(BUILD_DIR)
|
||||
|
||||
c: $(ROOT_DIR)/test/HandmadeMath.c test_impl
|
||||
c: build_c
|
||||
$(BUILD_DIR)/hmm_test_c
|
||||
|
||||
build_c: HandmadeMath.c test_impl
|
||||
@echo "\nCompiling in C mode"
|
||||
$(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
|
||||
-c $(ROOT_DIR)/test/HandmadeMath.c $(ROOT_DIR)/test/hmm_test.c \
|
||||
-lm
|
||||
$(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
|
||||
mkdir -p $(BUILD_DIR)
|
||||
cd $(BUILD_DIR)\
|
||||
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
|
||||
-c ../HandmadeMath.c ../hmm_test.c \
|
||||
-lm \
|
||||
&& $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
|
||||
|
||||
c_no_sse: $(ROOT_DIR)/test/HandmadeMath.c test_impl
|
||||
c_no_sse: build_c_no_sse
|
||||
$(BUILD_DIR)/hmm_test_c_no_sse
|
||||
|
||||
build_c_no_sse: HandmadeMath.c test_impl
|
||||
@echo "\nCompiling in C mode (no SSE)"
|
||||
$(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
|
||||
-DHANDMADE_MATH_NO_SSE \
|
||||
-c $(ROOT_DIR)/test/HandmadeMath.c $(ROOT_DIR)/test/hmm_test.c \
|
||||
-lm
|
||||
$(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm
|
||||
mkdir -p $(BUILD_DIR)
|
||||
cd $(BUILD_DIR) \
|
||||
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
|
||||
-DHANDMADE_MATH_NO_SSE \
|
||||
-c ../HandmadeMath.c ../hmm_test.c \
|
||||
-lm \
|
||||
&& $(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm
|
||||
|
||||
cpp: $(ROOT_DIR)/test/HandmadeMath.cpp test_impl
|
||||
cpp: build_cpp
|
||||
$(BUILD_DIR)/hmm_test_cpp
|
||||
|
||||
build_cpp: HandmadeMath.cpp test_impl
|
||||
@echo "\nCompiling in C++ mode"
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp \
|
||||
-DHANDMADE_MATH_CPP_MODE \
|
||||
$(ROOT_DIR)/test/HandmadeMath.cpp $(ROOT_DIR)/test/hmm_test.cpp
|
||||
mkdir -p $(BUILD_DIR)
|
||||
cd $(BUILD_DIR) \
|
||||
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp \
|
||||
-DHANDMADE_MATH_CPP_MODE \
|
||||
../HandmadeMath.cpp ../hmm_test.cpp
|
||||
|
||||
cpp_no_sse: $(ROOT_DIR)/test/HandmadeMath.cpp test_impl
|
||||
cpp_no_sse: build_cpp_no_sse
|
||||
$(BUILD_DIR)/hmm_test_cpp_no_sse
|
||||
|
||||
build_cpp_no_sse: HandmadeMath.cpp test_impl
|
||||
@echo "\nCompiling in C++ mode (no SSE)"
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse \
|
||||
-DHANDMADE_MATH_CPP_MODE -DHANDMADE_MATH_NO_SSE \
|
||||
$(ROOT_DIR)/test/HandmadeMath.cpp $(ROOT_DIR)/test/hmm_test.cpp
|
||||
mkdir -p $(BUILD_DIR)
|
||||
cd $(BUILD_DIR) \
|
||||
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse \
|
||||
-DHANDMADE_MATH_CPP_MODE -DHANDMADE_MATH_NO_SSE \
|
||||
../HandmadeMath.cpp ../hmm_test.cpp
|
||||
|
||||
test_impl: hmm_test.cpp hmm_test.c
|
||||
|
||||
build_c_without_coverage: HandmadeMath.c test_impl
|
||||
@echo "\nCompiling in C mode"
|
||||
mkdir -p $(BUILD_DIR)
|
||||
cd $(BUILD_DIR)\
|
||||
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
|
||||
-DWITHOUT_COVERAGE \
|
||||
-c ../HandmadeMath.c ../hmm_test.c \
|
||||
-lm \
|
||||
&& $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
|
||||
|
||||
build_cpp_without_coverage: HandmadeMath.cpp test_impl
|
||||
@echo "\nCompiling in C++ mode (no SSE)"
|
||||
mkdir -p $(BUILD_DIR)
|
||||
cd $(BUILD_DIR) \
|
||||
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse \
|
||||
-DHANDMADE_MATH_CPP_MODE -DWITHOUT_COVERAGE \
|
||||
../HandmadeMath.cpp ../hmm_test.cpp
|
||||
|
||||
test_impl: $(ROOT_DIR)/test/hmm_test.cpp $(ROOT_DIR)/test/hmm_test.c
|
||||
|
||||
@@ -4,8 +4,13 @@ You can compile and run the tests yourself by running:
|
||||
|
||||
```
|
||||
make
|
||||
./hmm_test_c
|
||||
./hmm_test_c_no_sse
|
||||
./hmm_test_cpp
|
||||
./hmm_test_cpp_no_sse
|
||||
```
|
||||
|
||||
To run a specific test configuration, run one of:
|
||||
|
||||
```
|
||||
make c
|
||||
make c_no_sse
|
||||
make cpp
|
||||
make cpp_no_sse
|
||||
```
|
||||
|
||||
333
test/categories/Addition.h
Normal file
333
test/categories/Addition.h
Normal file
@@ -0,0 +1,333 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
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 result = HMM_AddV2(v2_1, v2_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
v2_1 += v2_2;
|
||||
EXPECT_FLOAT_EQ(v2_1.X, 4.0f);
|
||||
EXPECT_FLOAT_EQ(v2_1.Y, 6.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 result = HMM_AddV3(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
v3_1 += v3_2;
|
||||
EXPECT_FLOAT_EQ(v3_1.X, 5.0f);
|
||||
EXPECT_FLOAT_EQ(v3_1.Y, 7.0f);
|
||||
EXPECT_FLOAT_EQ(v3_1.Z, 9.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 result = HMM_AddV4(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||
}
|
||||
|
||||
v4_1 += v4_2;
|
||||
EXPECT_FLOAT_EQ(v4_1.X, 6.0f);
|
||||
EXPECT_FLOAT_EQ(v4_1.Y, 8.0f);
|
||||
EXPECT_FLOAT_EQ(v4_1.Z, 10.0f);
|
||||
EXPECT_FLOAT_EQ(v4_1.W, 12.0f);
|
||||
#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);
|
||||
}
|
||||
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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
|
||||
|
||||
// Fill the matrices
|
||||
int Counter = 1;
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
m4_1.Elements[Column][Row] = Counter;
|
||||
++Counter;
|
||||
}
|
||||
}
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
m4_2.Elements[Column][Row] = Counter;
|
||||
++Counter;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the results
|
||||
{
|
||||
HMM_Mat4 result = HMM_AddM4(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef __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;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
HMM_Mat4 result = 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(m4_1.Elements[Column][Row], Expected);
|
||||
Expected += 2.0f;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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_Quat result = HMM_AddQ(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
HMM_Quat result = 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);
|
||||
}
|
||||
|
||||
q1 += q2;
|
||||
EXPECT_FLOAT_EQ(q1.X, 6.0f);
|
||||
EXPECT_FLOAT_EQ(q1.Y, 8.0f);
|
||||
EXPECT_FLOAT_EQ(q1.Z, 10.0f);
|
||||
EXPECT_FLOAT_EQ(q1.W, 12.0f);
|
||||
#endif
|
||||
}
|
||||
419
test/categories/Division.h
Normal file
419
test/categories/Division.h
Normal file
@@ -0,0 +1,419 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
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 result = HMM_DivV2(v2_1, v2_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
HMM_Vec2 result = HMM_Div(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);
|
||||
}
|
||||
|
||||
v2_1 /= v2_2;
|
||||
EXPECT_FLOAT_EQ(v2_1.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(v2_1.Y, 0.75f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Division, Vec2Scalar)
|
||||
{
|
||||
HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
|
||||
float s = 2;
|
||||
|
||||
{
|
||||
HMM_Vec2 result = HMM_DivV2F(v2, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
HMM_Vec2 result = HMM_Div(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);
|
||||
}
|
||||
|
||||
v2 /= s;
|
||||
EXPECT_FLOAT_EQ(v2.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(v2.Y, 1.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 result = HMM_DivV3(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
v3_1 /= v3_2;
|
||||
EXPECT_FLOAT_EQ(v3_1.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(v3_1.Y, 0.75f);
|
||||
EXPECT_FLOAT_EQ(v3_1.Z, 10.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Division, Vec3Scalar)
|
||||
{
|
||||
HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||
float s = 2;
|
||||
|
||||
{
|
||||
HMM_Vec3 result = HMM_DivV3F(v3, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
v3 /= s;
|
||||
EXPECT_FLOAT_EQ(v3.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(v3.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3.Z, 1.5f);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 result = HMM_DivV4(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
EXPECT_FLOAT_EQ(result.W, 0.25f);
|
||||
}
|
||||
|
||||
v4_1 /= v4_2;
|
||||
EXPECT_FLOAT_EQ(v4_1.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(v4_1.Y, 0.75f);
|
||||
EXPECT_FLOAT_EQ(v4_1.Z, 10.0f);
|
||||
EXPECT_FLOAT_EQ(v4_1.W, 0.25f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Division, Vec4Scalar)
|
||||
{
|
||||
HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
float s = 2;
|
||||
|
||||
{
|
||||
HMM_Vec4 result = HMM_DivV4F(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
EXPECT_FLOAT_EQ(result.W, 2.0f);
|
||||
}
|
||||
|
||||
v4 /= s;
|
||||
EXPECT_FLOAT_EQ(v4.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(v4.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4.Z, 1.5f);
|
||||
EXPECT_FLOAT_EQ(v4.W, 2.0f);
|
||||
#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);
|
||||
}
|
||||
|
||||
#ifdef __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);
|
||||
}
|
||||
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef __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);
|
||||
}
|
||||
|
||||
{
|
||||
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
|
||||
float s = 2;
|
||||
|
||||
// Fill the matrix
|
||||
int Counter = 1;
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
m4.Elements[Column][Row] = Counter;
|
||||
++Counter;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the results
|
||||
{
|
||||
HMM_Mat4 result = HMM_DivM4F(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
m4 /= s;
|
||||
EXPECT_FLOAT_EQ(m4.Elements[0][0], 0.5f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[0][1], 1.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[0][2], 1.5f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[0][3], 2.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[1][0], 2.5f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[1][1], 3.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[1][2], 3.5f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[1][3], 4.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[2][0], 4.5f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[2][1], 5.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[2][2], 5.5f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[2][3], 6.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[3][0], 6.5f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[3][1], 7.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[3][2], 7.5f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[3][3], 8.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Division, QuaternionScalar)
|
||||
{
|
||||
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
float f = 2.0f;
|
||||
|
||||
{
|
||||
HMM_Quat result = HMM_DivQF(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
HMM_Quat result = 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);
|
||||
}
|
||||
|
||||
q /= f;
|
||||
EXPECT_FLOAT_EQ(q.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(q.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(q.Z, 1.5f);
|
||||
EXPECT_FLOAT_EQ(q.W, 2.0f);
|
||||
#endif
|
||||
}
|
||||
64
test/categories/Equality.h
Normal file
64
test/categories/Equality.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
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);
|
||||
|
||||
EXPECT_TRUE(HMM_EqV2(a, b));
|
||||
EXPECT_FALSE(HMM_EqV2(a, c));
|
||||
|
||||
#ifdef __cplusplus
|
||||
EXPECT_TRUE(HMM_Eq(a, b));
|
||||
EXPECT_FALSE(HMM_Eq(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);
|
||||
|
||||
EXPECT_TRUE(HMM_EqV3(a, b));
|
||||
EXPECT_FALSE(HMM_EqV3(a, c));
|
||||
|
||||
#ifdef __cplusplus
|
||||
EXPECT_TRUE(HMM_Eq(a, b));
|
||||
EXPECT_FALSE(HMM_Eq(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);
|
||||
|
||||
EXPECT_TRUE(HMM_EqV4(a, b));
|
||||
EXPECT_FALSE(HMM_EqV4(a, c));
|
||||
|
||||
#ifdef __cplusplus
|
||||
EXPECT_TRUE(HMM_Eq(a, b));
|
||||
EXPECT_FALSE(HMM_Eq(a, c));
|
||||
|
||||
EXPECT_TRUE(a == b);
|
||||
EXPECT_FALSE(a == c);
|
||||
|
||||
EXPECT_FALSE(a != b);
|
||||
EXPECT_TRUE(a != c);
|
||||
#endif
|
||||
}
|
||||
321
test/categories/Initialization.h
Normal file
321
test/categories/Initialization.h
Normal file
@@ -0,0 +1,321 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(Initialization, Vectors)
|
||||
{
|
||||
//
|
||||
// Test vec2
|
||||
//
|
||||
HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(v2.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v2.Y, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v2.U, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v2.V, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v2.Left, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v2.Right, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v2.Width, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v2.Height, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v2.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v2.Elements[1], 2.0f);
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(v2[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v2[1], 2.0f);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Test vec3
|
||||
//
|
||||
HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(v3.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3.Y, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3.Z, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v3.U, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3.V, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3.W, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v3.R, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3.G, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3.B, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v3.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3.Elements[2], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v3.XY.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3.XY.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3.YZ.Elements[0], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3.YZ.Elements[1], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v3.UV.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3.UV.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3.VW.Elements[0], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3.VW.Elements[1], 3.0f);
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(v3[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3[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);
|
||||
|
||||
EXPECT_FLOAT_EQ(v4.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4.Y, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4.Z, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4.W, 4.0f);
|
||||
EXPECT_FLOAT_EQ(v4.R, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4.G, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4.B, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4.A, 4.0f);
|
||||
EXPECT_FLOAT_EQ(v4.XY.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4.XY.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4.YZ.Elements[0], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4.YZ.Elements[1], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4.ZW.Elements[0], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4.ZW.Elements[1], 4.0f);
|
||||
EXPECT_FLOAT_EQ(v4.XY.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4.XY.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4.XYZ.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4.XYZ.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4.XYZ.Elements[2], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4.RGB.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4.RGB.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4.RGB.Elements[2], 3.0f);
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(v4[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4[2], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4[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);
|
||||
EXPECT_FLOAT_EQ(v4v.W, 4.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.R, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.G, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.B, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.A, 4.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.XY.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.XY.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.YZ.Elements[0], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.YZ.Elements[1], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.ZW.Elements[0], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.ZW.Elements[1], 4.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.XY.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.XY.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.XYZ.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.XYZ.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.XYZ.Elements[2], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.RGB.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.RGB.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.RGB.Elements[2], 3.0f);
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(v4v[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4v[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4v[2], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4v[3], 4.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
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();
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(m4.Elements[Column][Row], 0.0f);
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(m4[Column][Row], 0.0f);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
if (Column == Row) {
|
||||
EXPECT_FLOAT_EQ(m4d.Elements[Column][Row], 1.0f);
|
||||
} else {
|
||||
EXPECT_FLOAT_EQ(m4d.Elements[Column][Row], 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Initialization, Quaternion)
|
||||
{
|
||||
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(q.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(q.Y, 2.0f);
|
||||
EXPECT_FLOAT_EQ(q.Z, 3.0f);
|
||||
EXPECT_FLOAT_EQ(q.W, 4.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(q.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(q.Elements[1], 2.0f);
|
||||
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);
|
||||
|
||||
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
|
||||
413
test/categories/MatrixOps.h
Normal file
413
test/categories/MatrixOps.h
Normal file
@@ -0,0 +1,413 @@
|
||||
#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]);
|
||||
}
|
||||
#ifdef __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]);
|
||||
}
|
||||
#ifdef __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]);
|
||||
}
|
||||
#ifdef __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_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][3], Expect.Elements[0][3]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][3], Expect.Elements[1][3]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][3], Expect.Elements[2][3]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][0], Expect.Elements[3][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][1], Expect.Elements[3][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][2], Expect.Elements[3][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][3], Expect.Elements[3][3]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
Inverse = HMM_InvGeneral(Matrix);
|
||||
Result = HMM_Mul(Matrix, Inverse);
|
||||
|
||||
Det = HMM_Determinant(Matrix);
|
||||
EXPECT_FLOAT_EQ(Det, -80.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][3], Expect.Elements[0][3]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][3], Expect.Elements[1][3]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][3], Expect.Elements[2][3]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][0], Expect.Elements[3][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][1], Expect.Elements[3][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][2], Expect.Elements[3][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][3], Expect.Elements[3][3]);
|
||||
#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, Mat4Inverses)
|
||||
{
|
||||
{
|
||||
HMM_Mat4 Matrix = HMM_Orthographic_RH(-160+100, 160+100, -90+200, 90+200, 10, 10000);
|
||||
HMM_Mat4 Expect = HMM_M4D(1.0f);
|
||||
HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix);
|
||||
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][3], Expect.Elements[0][3]);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][3], Expect.Elements[1][3]);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][3], Expect.Elements[2][3]);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][0], Expect.Elements[3][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][1], Expect.Elements[3][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][2], Expect.Elements[3][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][3], Expect.Elements[3][3]);
|
||||
}
|
||||
{
|
||||
HMM_Mat4 Matrix = HMM_Perspective_RH(HMM_AngleDeg(120), 16.0/9.0, 10, 10000);
|
||||
HMM_Mat4 Expect = HMM_M4D(1.0f);
|
||||
HMM_Mat4 Inverse = HMM_InvPerspective(Matrix);
|
||||
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][3], Expect.Elements[0][3]);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][3], Expect.Elements[1][3]);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][3], Expect.Elements[2][3]);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][0], Expect.Elements[3][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][1], Expect.Elements[3][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][2], Expect.Elements[3][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][3], Expect.Elements[3][3]);
|
||||
}
|
||||
{
|
||||
HMM_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_NEAR(Result.Elements[0][0], Expect.Elements[0][0], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[0][1], Expect.Elements[0][1], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[0][2], Expect.Elements[0][2], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[0][3], Expect.Elements[0][3], 0.001f);
|
||||
|
||||
EXPECT_NEAR(Result.Elements[1][0], Expect.Elements[1][0], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[1][1], Expect.Elements[1][1], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[1][2], Expect.Elements[1][2], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[1][3], Expect.Elements[1][3], 0.001f);
|
||||
|
||||
EXPECT_NEAR(Result.Elements[2][0], Expect.Elements[2][0], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[2][1], Expect.Elements[2][1], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[2][2], Expect.Elements[2][2], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[2][3], Expect.Elements[2][3], 0.001f);
|
||||
|
||||
EXPECT_NEAR(Result.Elements[3][0], Expect.Elements[3][0], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[3][1], Expect.Elements[3][1], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[3][2], Expect.Elements[3][2], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[3][3], Expect.Elements[3][3], 0.001f);
|
||||
}
|
||||
{
|
||||
HMM_Vec3 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_NEAR(Result.Elements[0][0], Expect.Elements[0][0], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[0][1], Expect.Elements[0][1], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[0][2], Expect.Elements[0][2], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[0][3], Expect.Elements[0][3], 0.001f);
|
||||
|
||||
EXPECT_NEAR(Result.Elements[1][0], Expect.Elements[1][0], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[1][1], Expect.Elements[1][1], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[1][2], Expect.Elements[1][2], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[1][3], Expect.Elements[1][3], 0.001f);
|
||||
|
||||
EXPECT_NEAR(Result.Elements[2][0], Expect.Elements[2][0], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[2][1], Expect.Elements[2][1], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[2][2], Expect.Elements[2][2], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[2][3], Expect.Elements[2][3], 0.001f);
|
||||
|
||||
EXPECT_NEAR(Result.Elements[3][0], Expect.Elements[3][0], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[3][1], Expect.Elements[3][1], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[3][2], Expect.Elements[3][2], 0.001f);
|
||||
EXPECT_NEAR(Result.Elements[3][3], Expect.Elements[3][3], 0.001f);
|
||||
}
|
||||
{
|
||||
HMM_Vec3 Scale = {1.0f, -1.0f, 0.5f};
|
||||
HMM_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_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][3], Expect.Elements[0][3]);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][3], Expect.Elements[1][3]);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][3], Expect.Elements[2][3]);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][0], Expect.Elements[3][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][1], Expect.Elements[3][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][2], Expect.Elements[3][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][3], Expect.Elements[3][3]);
|
||||
}
|
||||
{
|
||||
HMM_Vec3 Move = {1.0f, -1.0f, 0.5f};
|
||||
HMM_Mat4 Matrix = HMM_Translate(Move);
|
||||
HMM_Mat4 Expect = HMM_M4D(1.0f);
|
||||
HMM_Mat4 Inverse = HMM_InvTranslate(Matrix);
|
||||
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[0][3], Expect.Elements[0][3]);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[1][3], Expect.Elements[1][3]);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[2][3], Expect.Elements[2][3]);
|
||||
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][0], Expect.Elements[3][0]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][1], Expect.Elements[3][1]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][2], Expect.Elements[3][2]);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][3], Expect.Elements[3][3]);
|
||||
}
|
||||
}
|
||||
835
test/categories/Multiplication.h
Normal file
835
test/categories/Multiplication.h
Normal file
@@ -0,0 +1,835 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
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 result = HMM_MulV2(v2_1, v2_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
HMM_Vec2 result = HMM_Mul(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);
|
||||
}
|
||||
|
||||
v2_1 *= v2_2;
|
||||
EXPECT_FLOAT_EQ(v2_1.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v2_1.Y, 8.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Multiplication, Vec2Scalar)
|
||||
{
|
||||
HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
|
||||
float s = 3.0f;
|
||||
|
||||
{
|
||||
HMM_Vec2 result = HMM_MulV2F(v2, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
HMM_Vec2 result = HMM_Mul(v2, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
v2 *= s;
|
||||
EXPECT_FLOAT_EQ(v2.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v2.Y, 6.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 result = HMM_MulV3(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
v3_1 *= v3_2;
|
||||
EXPECT_FLOAT_EQ(v3_1.X, 4.0f);
|
||||
EXPECT_FLOAT_EQ(v3_1.Y, 10.0f);
|
||||
EXPECT_FLOAT_EQ(v3_1.Z, 18.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Multiplication, Vec3Scalar)
|
||||
{
|
||||
HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||
float s = 3.0f;
|
||||
|
||||
{
|
||||
HMM_Vec3 result = HMM_MulV3F(v3, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
v3 *= s;
|
||||
EXPECT_FLOAT_EQ(v3.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v3.Y, 6.0f);
|
||||
EXPECT_FLOAT_EQ(v3.Z, 9.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 result = HMM_MulV4(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
EXPECT_FLOAT_EQ(result.W, 32.0f);
|
||||
}
|
||||
|
||||
v4_1 *= v4_2;
|
||||
EXPECT_FLOAT_EQ(v4_1.X, 5.0f);
|
||||
EXPECT_FLOAT_EQ(v4_1.Y, 12.0f);
|
||||
EXPECT_FLOAT_EQ(v4_1.Z, 21.0f);
|
||||
EXPECT_FLOAT_EQ(v4_1.W, 32.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Multiplication, Vec4Scalar)
|
||||
{
|
||||
HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
float s = 3.0f;
|
||||
|
||||
{
|
||||
HMM_Vec4 result = HMM_MulV4F(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||
}
|
||||
|
||||
v4 *= s;
|
||||
EXPECT_FLOAT_EQ(v4.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4.Y, 6.0f);
|
||||
EXPECT_FLOAT_EQ(v4.Z, 9.0f);
|
||||
#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);
|
||||
}
|
||||
|
||||
#ifdef __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);
|
||||
}
|
||||
|
||||
{
|
||||
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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
HMM_Vec2 result = HMM_Mul(m, v);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0], 23.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1], 34.0f);
|
||||
}
|
||||
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef __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);
|
||||
}
|
||||
|
||||
{
|
||||
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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
|
||||
{
|
||||
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
|
||||
|
||||
// Fill the matrices
|
||||
int Counter = 1;
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
m4_1.Elements[Column][Row] = Counter;
|
||||
++Counter;
|
||||
}
|
||||
}
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
m4_2.Elements[Column][Row] = Counter;
|
||||
++Counter;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the results
|
||||
{
|
||||
HMM_Mat4 result = HMM_MulM4(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
// At the time I wrote this, I intentionally omitted
|
||||
// the *= operator for matrices because matrix
|
||||
// multiplication is not commutative. (bvisness)
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Multiplication, Mat4Scalar)
|
||||
{
|
||||
HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
|
||||
float s = 3;
|
||||
|
||||
// Fill the matrix
|
||||
int Counter = 1;
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
m4.Elements[Column][Row] = Counter;
|
||||
++Counter;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the results
|
||||
{
|
||||
HMM_Mat4 result = HMM_MulM4F(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
m4 *= s;
|
||||
EXPECT_FLOAT_EQ(m4.Elements[0][0], 3.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[0][1], 6.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[0][2], 9.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[0][3], 12.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[1][0], 15.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[1][1], 18.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[1][2], 21.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[1][3], 24.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[2][0], 27.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[2][1], 30.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[2][2], 33.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[2][3], 36.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[3][0], 39.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[3][1], 42.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[3][2], 45.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[3][3], 48.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// Fill the matrix
|
||||
int Counter = 1;
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
m4.Elements[Column][Row] = Counter;
|
||||
++Counter;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the results
|
||||
{
|
||||
HMM_Vec4 result = HMM_MulM4V4(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
EXPECT_FLOAT_EQ(result.W, 120.0f);
|
||||
}
|
||||
|
||||
// *= makes no sense for this particular case.
|
||||
#endif
|
||||
}
|
||||
|
||||
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_Quat result = HMM_MulQ(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
HMM_Quat result = 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);
|
||||
}
|
||||
|
||||
// Like with matrices, we're not implementing the *=
|
||||
// operator for quaternions because quaternion multiplication
|
||||
// is not commutative.
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Multiplication, QuaternionScalar)
|
||||
{
|
||||
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
float f = 2.0f;
|
||||
|
||||
{
|
||||
HMM_Quat result = HMM_MulQF(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
HMM_Quat 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_Quat result = f * q;
|
||||
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);
|
||||
}
|
||||
|
||||
q *= f;
|
||||
EXPECT_FLOAT_EQ(q.X, 2.0f);
|
||||
EXPECT_FLOAT_EQ(q.Y, 4.0f);
|
||||
EXPECT_FLOAT_EQ(q.Z, 6.0f);
|
||||
EXPECT_FLOAT_EQ(q.W, 8.0f);
|
||||
#endif
|
||||
}
|
||||
49
test/categories/Projection.h
Normal file
49
test/categories/Projection.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(Projection, Orthographic)
|
||||
{
|
||||
{
|
||||
HMM_Mat4 projection = HMM_Orthographic_RH(-10.0f, 10.0f, -5.0f, 5.0f, 0.0f, -10.0f);
|
||||
|
||||
HMM_Vec3 original = HMM_V3(5.0f, 5.0f, -5.0f);
|
||||
HMM_Vec4 projected = HMM_MulM4V4(projection, HMM_V4V(original, 1));
|
||||
|
||||
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);
|
||||
}
|
||||
{
|
||||
HMM_Mat4 projection = HMM_Orthographic_LH(-10.0f, 10.0f, -5.0f, 5.0f, 0.0f, 10.0f);
|
||||
|
||||
HMM_Vec3 original = HMM_V3(5.0f, 5.0f, -5.0f);
|
||||
HMM_Vec4 projected = HMM_MulM4V4(projection, HMM_V4V(original, 1));
|
||||
|
||||
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)
|
||||
{
|
||||
{
|
||||
HMM_Mat4 projection = HMM_Perspective_RH(HMM_AngleDeg(90.0f), 2.0f, 5.0f, 15.0f);
|
||||
HMM_Vec3 original = HMM_V3(5.0f, 5.0f, -15.0f);
|
||||
HMM_Vec4 projected = HMM_MulM4V4(projection, HMM_V4V(original, 1));
|
||||
EXPECT_FLOAT_EQ(projected.X, 2.5f);
|
||||
EXPECT_FLOAT_EQ(projected.Y, 5.0f);
|
||||
EXPECT_FLOAT_EQ(projected.Z, 15.0f);
|
||||
EXPECT_FLOAT_EQ(projected.W, 15.0f);
|
||||
}
|
||||
{
|
||||
HMM_Mat4 projection = HMM_Perspective_LH(HMM_AngleDeg(90.0f), 2.0f, 5.0f, 15.0f);
|
||||
HMM_Vec3 original = HMM_V3(5.0f, 5.0f, -15.0f);
|
||||
HMM_Vec4 projected = HMM_MulM4V4(projection, HMM_V4V(original, 1));
|
||||
EXPECT_FLOAT_EQ(projected.X, 2.5f);
|
||||
EXPECT_FLOAT_EQ(projected.Y, 5.0f);
|
||||
EXPECT_FLOAT_EQ(projected.Z, 15.0f);
|
||||
EXPECT_FLOAT_EQ(projected.W, -15.0f);
|
||||
}
|
||||
}
|
||||
276
test/categories/QuaternionOps.h
Normal file
276
test/categories/QuaternionOps.h
Normal file
@@ -0,0 +1,276 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(QuaternionOps, Inverse)
|
||||
{
|
||||
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
HMM_Quat inverse = HMM_InvQ(q1);
|
||||
|
||||
HMM_Quat result = HMM_MulQ(q1, inverse);
|
||||
|
||||
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, 1.0f);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
{
|
||||
float result = HMM_DotQ(q1, q2);
|
||||
EXPECT_FLOAT_EQ(result, 70.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
float result = HMM_Dot(q1, q2);
|
||||
EXPECT_FLOAT_EQ(result, 70.0f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(QuaternionOps, Normalize)
|
||||
{
|
||||
HMM_Quat q = HMM_Q(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);
|
||||
}
|
||||
#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);
|
||||
}
|
||||
#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_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);
|
||||
}
|
||||
|
||||
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_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);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(QuaternionOps, QuatToMat4)
|
||||
{
|
||||
const float abs_error = 0.001f;
|
||||
|
||||
HMM_Quat rot = HMM_Q(0.707107f, 0.0f, 0.0f, 0.707107f);
|
||||
|
||||
HMM_Mat4 result = HMM_QToM4(rot);
|
||||
|
||||
EXPECT_NEAR(result.Elements[0][0], 1.0f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[0][1], 0.0f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[0][2], 0.0f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[0][3], 0.0f, abs_error);
|
||||
|
||||
EXPECT_NEAR(result.Elements[1][0], 0.0f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[1][1], 0.0f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[1][2], 1.0f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[1][3], 0.0f, abs_error);
|
||||
|
||||
EXPECT_NEAR(result.Elements[2][0], 0.0f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[2][1], -1.0f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[2][2], 0.0f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[2][3], 0.0f, abs_error);
|
||||
|
||||
EXPECT_NEAR(result.Elements[3][0], 0.0f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[3][1], 0.0f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[3][2], 0.0f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error);
|
||||
}
|
||||
|
||||
TEST(QuaternionOps, Mat4ToQuat)
|
||||
{
|
||||
const float abs_error = 0.0001f;
|
||||
|
||||
// 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, FromAxisAngle)
|
||||
{
|
||||
HMM_Vec3 axis = HMM_V3(1.0f, 0.0f, 0.0f);
|
||||
float angle = HMM_PI32 / 2.0f;
|
||||
|
||||
{
|
||||
HMM_Quat result = HMM_QFromAxisAngle_RH(axis, angle);
|
||||
EXPECT_NEAR(result.X, 0.707107f, 0.001f);
|
||||
EXPECT_NEAR(result.Y, 0.0f, 0.001f);
|
||||
EXPECT_NEAR(result.Z, 0.0f, 0.001f);
|
||||
EXPECT_NEAR(result.W, 0.707107f, 0.001f);
|
||||
}
|
||||
{
|
||||
HMM_Quat result = HMM_QFromAxisAngle_LH(axis, angle);
|
||||
EXPECT_NEAR(result.X, -0.707107f, 0.001f);
|
||||
EXPECT_NEAR(result.Y, 0.0f, 0.001f);
|
||||
EXPECT_NEAR(result.Z, 0.0f, 0.001f);
|
||||
EXPECT_NEAR(result.W, 0.707107f, 0.001f);
|
||||
}
|
||||
}
|
||||
39
test/categories/SSE.h
Normal file
39
test/categories/SSE.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
#ifdef HANDMADE_MATH__USE_SSE
|
||||
|
||||
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);
|
||||
|
||||
{
|
||||
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][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][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][2], 0.0f);
|
||||
EXPECT_FLOAT_EQ(Result.Elements[3][3], 8.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
53
test/categories/ScalarMath.h
Normal file
53
test/categories/ScalarMath.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(ScalarMath, Trigonometry)
|
||||
{
|
||||
// We have to be a little looser with our equality constraint
|
||||
// because of floating-point precision issues.
|
||||
const float trigAbsError = 0.0001f;
|
||||
|
||||
EXPECT_NEAR(HMM_SinF(0.0f), 0.0f, trigAbsError);
|
||||
EXPECT_NEAR(HMM_SinF(HMM_PI32 / 2), 1.0f, trigAbsError);
|
||||
EXPECT_NEAR(HMM_SinF(HMM_PI32), 0.0f, trigAbsError);
|
||||
EXPECT_NEAR(HMM_SinF(3 * HMM_PI32 / 2), -1.0f, trigAbsError);
|
||||
EXPECT_NEAR(HMM_SinF(-HMM_PI32 / 2), -1.0f, trigAbsError);
|
||||
|
||||
EXPECT_NEAR(HMM_CosF(0.0f), 1.0f, trigAbsError);
|
||||
EXPECT_NEAR(HMM_CosF(HMM_PI32 / 2), 0.0f, trigAbsError);
|
||||
EXPECT_NEAR(HMM_CosF(HMM_PI32), -1.0f, trigAbsError);
|
||||
EXPECT_NEAR(HMM_CosF(3 * HMM_PI32 / 2), 0.0f, trigAbsError);
|
||||
EXPECT_NEAR(HMM_CosF(-HMM_PI32), -1.0f, trigAbsError);
|
||||
|
||||
EXPECT_NEAR(HMM_TanF(0.0f), 0.0f, trigAbsError);
|
||||
EXPECT_NEAR(HMM_TanF(HMM_PI32 / 4), 1.0f, trigAbsError);
|
||||
EXPECT_NEAR(HMM_TanF(3 * HMM_PI32 / 4), -1.0f, trigAbsError);
|
||||
EXPECT_NEAR(HMM_TanF(HMM_PI32), 0.0f, trigAbsError);
|
||||
EXPECT_NEAR(HMM_TanF(-HMM_PI32 / 4), -1.0f, trigAbsError);
|
||||
|
||||
// This isn't the most rigorous because we're really just sanity-
|
||||
// checking that things work by default.
|
||||
}
|
||||
|
||||
TEST(ScalarMath, SquareRoot)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(HMM_SqrtF(16.0f), 4.0f);
|
||||
}
|
||||
|
||||
TEST(ScalarMath, RSquareRootF)
|
||||
{
|
||||
EXPECT_NEAR(HMM_InvSqrtF(10.0f), 0.31616211f, 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, 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, 3.0f, 2.0f), 2.0f);
|
||||
}
|
||||
344
test/categories/Subtraction.h
Normal file
344
test/categories/Subtraction.h
Normal file
@@ -0,0 +1,344 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
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 result = HMM_SubV2(v2_1, v2_2);
|
||||
EXPECT_FLOAT_EQ(result.X, -2.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, -2.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
HMM_Vec2 result = HMM_Sub(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);
|
||||
}
|
||||
|
||||
v2_1 -= v2_2;
|
||||
EXPECT_FLOAT_EQ(v2_1.X, -2.0f);
|
||||
EXPECT_FLOAT_EQ(v2_1.Y, -2.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 result = HMM_SubV3(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
v3_1 -= v3_2;
|
||||
EXPECT_FLOAT_EQ(v3_1.X, -3.0f);
|
||||
EXPECT_FLOAT_EQ(v3_1.Y, -3.0f);
|
||||
EXPECT_FLOAT_EQ(v3_1.Z, -3.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 result = HMM_SubV4(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
EXPECT_FLOAT_EQ(result.W, -4.0f);
|
||||
}
|
||||
|
||||
v4_1 -= v4_2;
|
||||
EXPECT_FLOAT_EQ(v4_1.X, -4.0f);
|
||||
EXPECT_FLOAT_EQ(v4_1.Y, -4.0f);
|
||||
EXPECT_FLOAT_EQ(v4_1.Z, -4.0f);
|
||||
EXPECT_FLOAT_EQ(v4_1.W, -4.0f);
|
||||
#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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
|
||||
{
|
||||
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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// Fill the matrices
|
||||
int Counter = 1;
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
m4_1.Elements[Column][Row] = Counter;
|
||||
++Counter;
|
||||
}
|
||||
}
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
m4_2.Elements[Column][Row] = Counter;
|
||||
++Counter;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the results
|
||||
{
|
||||
HMM_Mat4 result = HMM_SubM4(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
HMM_Mat4 result = 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m4_1 -= m4_2;
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(m4_1.Elements[Column][Row], -16.0f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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_Quat result = HMM_SubQ(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
{
|
||||
HMM_Quat result = 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);
|
||||
}
|
||||
|
||||
q1 -= q2;
|
||||
EXPECT_FLOAT_EQ(q1.X, -4.0f);
|
||||
EXPECT_FLOAT_EQ(q1.Y, -4.0f);
|
||||
EXPECT_FLOAT_EQ(q1.Z, -4.0f);
|
||||
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
|
||||
105
test/categories/Transformation.h
Normal file
105
test/categories/Transformation.h
Normal file
@@ -0,0 +1,105 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(Transformations, Translate)
|
||||
{
|
||||
HMM_Mat4 translate = HMM_Translate(HMM_V3(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));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
TEST(Transformations, Rotate)
|
||||
{
|
||||
HMM_Vec3 original = HMM_V3(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 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 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);
|
||||
}
|
||||
|
||||
TEST(Transformations, Scale)
|
||||
{
|
||||
HMM_Mat4 scale = HMM_Scale(HMM_V3(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));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
TEST(Transformations, LookAt)
|
||||
{
|
||||
const float abs_error = 0.001f;
|
||||
|
||||
{ HMM_Mat4 result = HMM_LookAt_RH(HMM_V3(1.0f, 0.0f, 0.0f), HMM_V3(0.0f, 2.0f, 1.0f), HMM_V3(2.0f, 1.0f, 1.0f));
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
282
test/categories/VectorOps.h
Normal file
282
test/categories/VectorOps.h
Normal file
@@ -0,0 +1,282 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
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);
|
||||
|
||||
EXPECT_FLOAT_EQ(HMM_LenSqrV2(v2), 5.0f);
|
||||
EXPECT_FLOAT_EQ(HMM_LenSqrV3(v3), 14.0f);
|
||||
EXPECT_FLOAT_EQ(HMM_LenSqrV4(v4), 15.0f);
|
||||
|
||||
#ifdef __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);
|
||||
#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);
|
||||
|
||||
EXPECT_FLOAT_EQ(HMM_LenV2(v2), 9.0553856f);
|
||||
EXPECT_FLOAT_EQ(HMM_LenV3(v3), 7.0f);
|
||||
EXPECT_FLOAT_EQ(HMM_LenV4(v4), 13.892444f);
|
||||
|
||||
#ifdef __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);
|
||||
#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 result = HMM_NormV2(v2);
|
||||
EXPECT_NEAR(HMM_LenV2(result), 1.0f, 0.001f);
|
||||
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);
|
||||
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);
|
||||
EXPECT_GT(result.X, 0.0f);
|
||||
EXPECT_LT(result.Y, 0.0f);
|
||||
EXPECT_GT(result.Z, 0.0f);
|
||||
EXPECT_LT(result.W, 0.0f);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
HMM_Vec2 result = HMM_Norm(v2);
|
||||
EXPECT_NEAR(HMM_LenV2(result), 1.0f, 0.001f);
|
||||
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);
|
||||
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);
|
||||
EXPECT_GT(result.X, 0.0f);
|
||||
EXPECT_LT(result.Y, 0.0f);
|
||||
EXPECT_GT(result.Z, 0.0f);
|
||||
EXPECT_LT(result.W, 0.0f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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 result = HMM_NormV2(v2);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||
}
|
||||
{
|
||||
HMM_Vec3 result = HMM_NormV3(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);
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
HMM_Vec2 result = HMM_Norm(v2);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||
}
|
||||
{
|
||||
HMM_Vec3 result = HMM_Norm(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);
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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 result = HMM_Cross(v1, v2);
|
||||
|
||||
EXPECT_FLOAT_EQ(result.X, -3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, -3.0f);
|
||||
}
|
||||
|
||||
TEST(VectorOps, DotVec2)
|
||||
{
|
||||
HMM_Vec2 v1 = HMM_V2(1.0f, 2.0f);
|
||||
HMM_Vec2 v2 = HMM_V2(3.0f, 4.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(HMM_DotV2(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);
|
||||
|
||||
EXPECT_FLOAT_EQ(HMM_DotV3(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);
|
||||
|
||||
EXPECT_FLOAT_EQ(HMM_DotV4(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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
#ifdef __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);
|
||||
}
|
||||
#ifdef __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)
|
||||
{
|
||||
HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
|
||||
|
||||
// Fill the matrix
|
||||
int Counter = 1;
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
m4.Elements[Column][Row] = Counter;
|
||||
++Counter;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the matrix
|
||||
HMM_Mat4 result = HMM_TransposeM4(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);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][3], 13.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][0], 2.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][1], 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][2], 10.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][3], 14.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][0], 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][1], 7.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][2], 11.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][3], 15.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][0], 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][1], 8.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][2], 12.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][3], 16.0f);
|
||||
}
|
||||
2201
test/hmm_test.c
2201
test/hmm_test.c
File diff suppressed because it is too large
Load Diff
21
test/hmm_test.h
Normal file
21
test/hmm_test.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#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"
|
||||
#include "categories/Multiplication.h"
|
||||
#include "categories/Division.h"
|
||||
#include "categories/Equality.h"
|
||||
#include "categories/Projection.h"
|
||||
#include "categories/Transformation.h"
|
||||
#include "categories/SSE.h"
|
||||
29
test/initializer.h
Normal file
29
test/initializer.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// Initializer/finalizer sample for MSVC and GCC/Clang.
|
||||
// 2010-2016 Joe Lowe. Released into the public domain.
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define _INITIALIZER_T(f) f##_t_
|
||||
#define _INITIALIZER_U(f) f##_
|
||||
#define INITIALIZER(f) \
|
||||
static void f(void); \
|
||||
struct _INITIALIZER_T(f) { _INITIALIZER_T(f)(void) { f(); } }; static _INITIALIZER_T(f) _INITIALIZER_U(f); \
|
||||
static void f(void)
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma section(".CRT$XCU",read)
|
||||
#define INITIALIZER2_(f,p) \
|
||||
static void f(void); \
|
||||
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
|
||||
__pragma(comment(linker,"/include:" p #f "_")) \
|
||||
static void f(void)
|
||||
#ifdef _WIN64
|
||||
#define INITIALIZER(f) INITIALIZER2_(f,"")
|
||||
#else
|
||||
#define INITIALIZER(f) INITIALIZER2_(f,"_")
|
||||
#endif
|
||||
#else
|
||||
#define INITIALIZER(f) \
|
||||
static void f(void) __attribute__((constructor)); \
|
||||
static void f(void)
|
||||
#endif
|
||||
18
test/run_test_clang.bat
Normal file
18
test/run_test_clang.bat
Normal file
@@ -0,0 +1,18 @@
|
||||
@echo off
|
||||
|
||||
if not exist "build" mkdir build
|
||||
pushd build
|
||||
|
||||
clang-cl /Fehmm_test_c.exe ..\HandmadeMath.c ..\hmm_test.c
|
||||
hmm_test_c
|
||||
|
||||
clang-cl /Fehmm_test_c_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.c ..\hmm_test.c
|
||||
hmm_test_c_no_sse
|
||||
|
||||
clang-cl /Fehmm_test_cpp.exe ..\HandmadeMath.cpp ..\hmm_test.cpp
|
||||
hmm_test_cpp
|
||||
|
||||
clang-cl /Fehmm_test_cpp_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.cpp ..\hmm_test.cpp
|
||||
hmm_test_cpp_no_sse
|
||||
|
||||
popd
|
||||
27
test/run_test_msvc.bat
Normal file
27
test/run_test_msvc.bat
Normal file
@@ -0,0 +1,27 @@
|
||||
@echo off
|
||||
|
||||
if "%1%"=="travis" (
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools\VsDevCmd.bat" -host_arch=amd64 -arch=amd64
|
||||
) else (
|
||||
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 /Fehmm_test_c.exe ..\HandmadeMath.c ..\hmm_test.c
|
||||
hmm_test_c
|
||||
|
||||
cl /Fehmm_test_c_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.c ..\hmm_test.c
|
||||
hmm_test_c_no_sse
|
||||
|
||||
cl /Fehmm_test_cpp.exe ..\HandmadeMath.cpp ..\hmm_test.cpp
|
||||
hmm_test_cpp
|
||||
|
||||
cl /Fehmm_test_cpp_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.cpp ..\hmm_test.cpp
|
||||
hmm_test_cpp_no_sse
|
||||
|
||||
popd
|
||||
36
update/README.md
Normal file
36
update/README.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Handmade Math 2.0 Update Tool
|
||||
|
||||
Due to the large number of breaking naming changes in Handmade Math 2, we provide a small tool to update your programs automatically. It's a C program that takes a list of files and updates their text, along with some scripts to recursively run the program on all code in a directory.
|
||||
|
||||
You can compile the tool yourself with any C/C++ compiler:
|
||||
|
||||
```bash
|
||||
# MSVC (Windows)
|
||||
cl update_hmm.c
|
||||
|
||||
# gcc
|
||||
gcc update_hmm.c -o update_hmm
|
||||
|
||||
# clang
|
||||
clang update_hmm.c -o update_hmm
|
||||
```
|
||||
|
||||
Once built, the tool can be run on any C or C++ files:
|
||||
|
||||
```bash
|
||||
# Windows
|
||||
update_hmm.exe MyGame.cpp MyPlatformLayer.cpp
|
||||
|
||||
# Other platforms
|
||||
update_hmm MyGame.cpp MyPlatformLayer.cpp
|
||||
```
|
||||
|
||||
Or, update all C/C++ files in a directory by running one of the provided shell scripts:
|
||||
|
||||
```bash
|
||||
# Windows
|
||||
update_hmm_all.bat "path\to\project"
|
||||
|
||||
# Other platforms
|
||||
update_hmm_all.sh path/to/project
|
||||
```
|
||||
562
update/update_hmm.c
Normal file
562
update/update_hmm.c
Normal file
@@ -0,0 +1,562 @@
|
||||
/* Compile:
|
||||
Windows (MSVC): cl update_hmm.c
|
||||
Linux (GCC): gcc update_hmm.c -o update_hmm
|
||||
*/
|
||||
|
||||
/** LCF stuff **/
|
||||
/* I used my personally library when writing this so I am dumping the necessary things here
|
||||
so that it's all in one file. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
/* Types */
|
||||
#define global static
|
||||
#define internal static
|
||||
typedef int32_t s32; global s32 s32_MAX = 0x7FFFFFFF; global s32 s32_MIN = -1 - 0x7FFFFFFF;
|
||||
typedef int64_t s64; global s64 s64_MAX = 0x7FFFFFFFFFFFFFFF; global s64 s64_MIN = -1 - 0x7FFFFFFFFFFFFFFF;
|
||||
typedef uint32_t u32; global u32 u32_MAX = 0xFFFFFFFF; global u32 u32_MIN = 0;
|
||||
typedef uint64_t u64; global u64 u64_MAX = 0xFFFFFFFFFFFFFFFF; global u64 u64_MIN = 0;
|
||||
typedef u32 b32;
|
||||
typedef u64 b64;
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#define CLAMPTOP(a,b) MIN(a,b)
|
||||
|
||||
/* Memory */
|
||||
struct lcf_Arena {
|
||||
u64 pos;
|
||||
u64 size;
|
||||
u64 alignment;
|
||||
u64 commited_pos;
|
||||
};
|
||||
typedef struct lcf_Arena Arena;
|
||||
#define KB(x) ((x) << 10)
|
||||
#define GB(x) ((x) << 30)
|
||||
Arena* Arena_create(u64 size);
|
||||
void* Arena_take(Arena *a, u64 size);
|
||||
void* Arena_take_custom(Arena *a, u64 size, u64 alignment);
|
||||
#define Arena_take_array(a, type, count) ((type*) Arena_take(a, sizeof(type)*count))
|
||||
void Arena_reset_all(Arena *a);
|
||||
|
||||
#define LCF_MEMORY_PROVIDE_MEMORY "stdlib"
|
||||
#define LCF_MEMORY_RESERVE_MEMORY(name) void* name(u64 size)
|
||||
#define LCF_MEMORY_COMMIT_MEMORY(name) b32 name(void* memory, u64 size)
|
||||
#define LCF_MEMORY_DECOMMIT_MEMORY(name) void name(void* memory, u64 size)
|
||||
#define LCF_MEMORY_FREE_MEMORY(name) void name(void* memory, u64 size)
|
||||
/* This implementation of an arena doesn't take advantage of virtual memory at all.
|
||||
It's just convenient to have something portable so I can use the Arena API I'm used to. */
|
||||
internal LCF_MEMORY_RESERVE_MEMORY(_lcf_memory_default_reserve) {
|
||||
return malloc(size);
|
||||
}
|
||||
internal LCF_MEMORY_COMMIT_MEMORY(_lcf_memory_default_commit) {
|
||||
(void) size, memory;
|
||||
return 1; /* malloc commits memory automatically */
|
||||
}
|
||||
internal LCF_MEMORY_DECOMMIT_MEMORY(_lcf_memory_default_decommit) {
|
||||
(void) size, memory;
|
||||
return;
|
||||
}
|
||||
internal LCF_MEMORY_FREE_MEMORY(_lcf_memory_default_free) {
|
||||
(void) size;
|
||||
free(memory);
|
||||
}
|
||||
#define LCF_MEMORY_reserve _lcf_memory_default_reserve
|
||||
#define LCF_MEMORY_commit _lcf_memory_default_commit
|
||||
#define LCF_MEMORY_decommit _lcf_memory_default_decommit
|
||||
#define LCF_MEMORY_free _lcf_memory_default_free
|
||||
#define LCF_MEMORY_RESERVE_SIZE GB(1)
|
||||
#define LCF_MEMORY_COMMIT_SIZE KB(4)
|
||||
#define LCF_MEMORY_ALIGNMENT (sizeof(void*))
|
||||
|
||||
Arena* Arena_create(u64 size) {
|
||||
Arena* a = (Arena*) LCF_MEMORY_reserve(size);
|
||||
LCF_MEMORY_commit(a, LCF_MEMORY_COMMIT_SIZE);
|
||||
a->size = size;
|
||||
a->pos = sizeof(Arena);
|
||||
a->commited_pos = LCF_MEMORY_COMMIT_SIZE;
|
||||
a->alignment = LCF_MEMORY_ALIGNMENT;
|
||||
return a;
|
||||
}
|
||||
#define B_PTR(p) (u8*)(p)
|
||||
|
||||
internal b32 is_power_of_2(u64 x) {
|
||||
return ((x & (x-1)) == 0);
|
||||
}
|
||||
internal u64 next_alignment(u64 ptr, u64 alignment) {
|
||||
/* Fast replacement for mod because alignment is power of 2 */
|
||||
u64 modulo = ptr & (alignment-1);
|
||||
|
||||
if (modulo != 0) {
|
||||
ptr += alignment - modulo;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
void* Arena_take_custom(Arena *a, u64 size, u64 alignment) {
|
||||
void* result = 0;
|
||||
|
||||
/* Align pos pointer to check if "size" can fit */
|
||||
u64 mem = (u64) a;
|
||||
u64 aligned_pos = next_alignment(mem + a->pos, alignment) - mem;
|
||||
u64 new_pos = aligned_pos + size;
|
||||
|
||||
/* Check that there is space */
|
||||
if (new_pos < a->size) {
|
||||
u64 commited_pos = a->commited_pos;
|
||||
|
||||
/* Commit memory if needed */
|
||||
if (new_pos > commited_pos) {
|
||||
u64 new_commited_pos = next_alignment(mem + new_pos, LCF_MEMORY_COMMIT_SIZE)-mem;
|
||||
if (LCF_MEMORY_commit(a, new_commited_pos)) {
|
||||
a->commited_pos = commited_pos = new_commited_pos;
|
||||
}
|
||||
}
|
||||
|
||||
/* If enough memory is commited, set result and pos. */
|
||||
if (new_pos <= commited_pos) {
|
||||
result = (void*)(mem + aligned_pos);
|
||||
a->pos = new_pos;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
void* Arena_take(Arena *a, u64 size) {
|
||||
return Arena_take_custom(a, size, LCF_MEMORY_ALIGNMENT);
|
||||
}
|
||||
void Arena_reset_all(Arena *a) {
|
||||
a->pos = 0;
|
||||
}
|
||||
|
||||
/* String */
|
||||
typedef char chr8;
|
||||
struct str8 {
|
||||
u64 len;
|
||||
chr8 *str;
|
||||
};
|
||||
typedef struct str8 str8;
|
||||
#define str8_PRINTF_ARGS(s) (int)(s).len, (s).str
|
||||
#define str8_lit(s) str8_from((chr8*)(s),(u64)sizeof(s)-1) /* -1 to exclude null character */
|
||||
#define str8_is_empty(s) ((b32)((s).len == 0))
|
||||
#define LCF_STRING_NO_MATCH 0x8000000000000000
|
||||
#define str8_iter_custom(s, i, c) \
|
||||
s64 i = 0; \
|
||||
chr8 c = s.str[i]; \
|
||||
for (; (i < (s64) s.len); i++, c = s.str[i])
|
||||
|
||||
#define str8_iter(s) str8_iter_custom(s, i, c)
|
||||
|
||||
str8 str8_from(chr8* s, u64 len);
|
||||
str8 str8_from_cstring(chr8 *cstr);
|
||||
str8 str8_first(str8 s, u64 len);
|
||||
str8 str8_skip(str8 s, u64 len);
|
||||
b32 chr8_is_whitespace(chr8 c);
|
||||
b32 str8_contains_char(str8 s, chr8 c);
|
||||
u64 str8_char_location(str8 s, chr8 c);
|
||||
|
||||
#define RET_STR8(s,l) \
|
||||
str8 _str8; \
|
||||
_str8.str = (s); \
|
||||
_str8.len = (l); \
|
||||
return _str8
|
||||
str8 str8_from(chr8* s, u64 len) {
|
||||
RET_STR8(s, len);
|
||||
}
|
||||
str8 str8_from_cstring(chr8 *cstr) {
|
||||
chr8* p2 = cstr;
|
||||
while(*p2 != 0)
|
||||
p2++;
|
||||
RET_STR8(cstr, (u64)(p2 - cstr));
|
||||
}
|
||||
str8 str8_first(str8 s, u64 len) {
|
||||
u64 len_clamped = CLAMPTOP(len, s.len);
|
||||
RET_STR8(s.str, len_clamped);
|
||||
}
|
||||
str8 str8_skip(str8 s, u64 len) {
|
||||
u64 len_clamped = CLAMPTOP(len, s.len);
|
||||
RET_STR8(s.str + len_clamped, s.len - len_clamped);
|
||||
}
|
||||
b32 chr8_is_whitespace(chr8 c) {
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\n':
|
||||
case '\t':
|
||||
case '\r':
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
b32 str8_contains_char(str8 s, chr8 find) {
|
||||
return str8_char_location(s,find) != LCF_STRING_NO_MATCH;
|
||||
}
|
||||
u64 str8_char_location(str8 s, chr8 find) {
|
||||
str8_iter(s) {
|
||||
if (c == find) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return LCF_STRING_NO_MATCH;
|
||||
}
|
||||
#undef RET_STR8
|
||||
|
||||
struct Str8Node {
|
||||
struct Str8Node *next;
|
||||
struct str8 str;
|
||||
};
|
||||
struct Str8List {
|
||||
struct Str8Node *first;
|
||||
struct Str8Node *last;
|
||||
u64 count;
|
||||
u64 total_len;
|
||||
};
|
||||
typedef struct Str8Node Str8Node;
|
||||
typedef struct Str8List Str8List;
|
||||
|
||||
void Str8List_add_node(Str8List *list, Str8Node *n);
|
||||
void Str8List_add(Arena *arena, Str8List *list, str8 str);
|
||||
void Str8List_add_node(Str8List *list, Str8Node *n) {
|
||||
if (list->last) {
|
||||
list->last->next = n;
|
||||
} else {
|
||||
list->first = n;
|
||||
}
|
||||
list->last = n;
|
||||
list->count++;
|
||||
list->total_len += n->str.len;
|
||||
}
|
||||
void Str8List_add(Arena *arena, Str8List *list, str8 str) {
|
||||
Str8Node *n = Arena_take_array(arena, Str8Node, 1);
|
||||
n->str = str;
|
||||
n->next = 0;
|
||||
Str8List_add_node(list, n);
|
||||
}
|
||||
|
||||
/* CRT - stdio */
|
||||
str8 stdio_load_entire_file(Arena *arena, str8 filepath);
|
||||
b32 stdio_write_file(str8 filepath, Str8List text);
|
||||
|
||||
str8 stdio_load_entire_file(Arena *arena, str8 filepath) {
|
||||
str8 file_content = {0};
|
||||
|
||||
FILE *file = fopen(filepath.str, "rb");
|
||||
if (file != 0) {
|
||||
fseek(file, 0, SEEK_END);
|
||||
u64 file_len = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
file_content.str = (chr8*) Arena_take(arena, file_len+1);
|
||||
if (file_content.str != 0) {
|
||||
file_content.len = file_len;
|
||||
fread(file_content.str, 1, file_len, file);
|
||||
file_content.str[file_content.len] = 0;
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
return file_content;
|
||||
}
|
||||
b32 stdio_write_file(str8 filepath, Str8List text) {
|
||||
u64 bytes_written = 0;
|
||||
FILE *file = fopen(filepath.str, "wb");
|
||||
if (file != 0) {
|
||||
Str8Node* n = text.first;
|
||||
for (s64 i = 0; i < text.count; i++, n = n->next) {
|
||||
if (!fwrite(n->str.str, n->str.len, 1, file)) {
|
||||
break;
|
||||
}
|
||||
bytes_written += n->str.len;
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
return bytes_written == text.total_len;
|
||||
}
|
||||
|
||||
/** HMM2.0 Update Tool **/
|
||||
enum Targets {
|
||||
/* hmm_ and HMM_ prefixes */
|
||||
PREFIX_TYPE, PREFIX_FUNCTION,
|
||||
PREFIXES_Size,
|
||||
/* Struct/Union types */
|
||||
TYPE_VEC, TYPE_MAT, TYPE_QUATERNION, TYPE_BOOL,
|
||||
TYPE_INTERNAL_ELEMENTS_SSE,
|
||||
TYPES_Size,
|
||||
/* Types in Function Names */
|
||||
FUN_VEC, FUN_MAT, FUN_QUATERNION,
|
||||
/* Function Names for Common Operations */
|
||||
FUN_EQUALS, FUN_SUBTRACT, FUN_MULTIPLY, FUN_DIVIDE,
|
||||
FUN_INVERSE, FUN_R_SQUARE_ROOT, FUN_SQUARE_ROOT,
|
||||
FUN_LENGTH_SQUARED, FUN_LENGTH, FUN_FAST_NORM, FUN_NORM,
|
||||
FUN_SLERP, FUN_BY,
|
||||
FUN_LINEAR_COMBINE_SSE, FUN_TRANSPOSE,
|
||||
FUNCTIONS_Size,
|
||||
/* Handedness */
|
||||
HAND_PERSPECTIVE, HAND_ROTATE,
|
||||
HAND_ORTHO, HAND_LOOK_AT, HAND_QUAT_AXIS_ANGLE, HAND_MAT_TO_QUAT,
|
||||
HAND_Size,
|
||||
};
|
||||
|
||||
Str8List update_file_content(Arena* arena, str8 file_content) {
|
||||
Str8List out = {0};
|
||||
|
||||
str8 Find[HAND_Size];
|
||||
str8 Repl[HAND_Size];
|
||||
{ /* NOTE: Initialization */
|
||||
Find[PREFIX_TYPE] = str8_lit("hmm_");
|
||||
Find[PREFIX_FUNCTION] = str8_lit("HMM_");
|
||||
Repl[PREFIX_TYPE] = Find[PREFIX_FUNCTION];
|
||||
|
||||
Find[TYPE_VEC] = str8_lit("vec");
|
||||
Repl[TYPE_VEC] = str8_lit("Vec");
|
||||
Find[TYPE_MAT] = str8_lit("mat");
|
||||
Repl[TYPE_MAT] = str8_lit("Mat");
|
||||
Find[TYPE_QUATERNION] = str8_lit("quaternion");
|
||||
Repl[TYPE_QUATERNION] = str8_lit("Quat");
|
||||
Find[TYPE_BOOL] = str8_lit("bool");
|
||||
Repl[TYPE_BOOL] = str8_lit("Bool");
|
||||
Find[TYPE_INTERNAL_ELEMENTS_SSE] = str8_lit(".InternalElementsSSE");
|
||||
Repl[TYPE_INTERNAL_ELEMENTS_SSE] = str8_lit(".SSE");
|
||||
|
||||
Find[FUN_VEC] = str8_lit("Vec");
|
||||
Repl[FUN_VEC] = str8_lit("V");
|
||||
Find[FUN_MAT] = str8_lit("Mat");
|
||||
Repl[FUN_MAT] = str8_lit("M");
|
||||
Find[FUN_QUATERNION] = str8_lit("Quaternion");
|
||||
Repl[FUN_QUATERNION] = str8_lit("Q");
|
||||
Find[FUN_EQUALS] = str8_lit("Equals");
|
||||
Repl[FUN_EQUALS] = str8_lit("Eq");
|
||||
Find[FUN_SUBTRACT] = str8_lit("Subtract");
|
||||
Repl[FUN_SUBTRACT] = str8_lit("Sub");
|
||||
Find[FUN_MULTIPLY] = str8_lit("Multiply");
|
||||
Repl[FUN_MULTIPLY] = str8_lit("Mul");
|
||||
Find[FUN_DIVIDE] = str8_lit("Divide");
|
||||
Repl[FUN_DIVIDE] = str8_lit("Div");
|
||||
Find[FUN_INVERSE] = str8_lit("Inverse");
|
||||
Repl[FUN_INVERSE] = str8_lit("Inv");
|
||||
Find[FUN_R_SQUARE_ROOT] = str8_lit("RSquareRoot");
|
||||
Repl[FUN_R_SQUARE_ROOT] = str8_lit("InvSqrt");
|
||||
Find[FUN_SQUARE_ROOT] = str8_lit("SquareRoot");
|
||||
Repl[FUN_SQUARE_ROOT] = str8_lit("Sqrt");
|
||||
Find[FUN_LENGTH_SQUARED] = str8_lit("Squared");
|
||||
Repl[FUN_LENGTH_SQUARED] = str8_lit("Sqr"); /* FIXME: not working for some reason */
|
||||
Find[FUN_LENGTH] = str8_lit("Length");
|
||||
Repl[FUN_LENGTH] = str8_lit("Len");
|
||||
|
||||
Find[FUN_SLERP] = str8_lit("Slerp");
|
||||
Repl[FUN_SLERP] = str8_lit("SLerp");
|
||||
Find[FUN_BY] = str8_lit("By");
|
||||
Repl[FUN_BY] = str8_lit("");
|
||||
Find[FUN_LINEAR_COMBINE_SSE] = str8_lit("LinearCombineSSE"); /* TODO: emit warning */
|
||||
Repl[FUN_LINEAR_COMBINE_SSE] = str8_lit("LinearCombineV4M4");
|
||||
Find[FUN_TRANSPOSE] = str8_lit("Transpose");
|
||||
Repl[FUN_TRANSPOSE] = str8_lit("TransposeM4");
|
||||
Find[FUN_FAST_NORM] = str8_lit("Fast"); /* TODO: emit warning, lower precision. */
|
||||
Repl[FUN_FAST_NORM] = str8_lit("");
|
||||
Find[FUN_NORM] = str8_lit("Normalize");
|
||||
Repl[FUN_NORM] = str8_lit("Norm");
|
||||
|
||||
Find[HAND_PERSPECTIVE] = str8_lit("Perspective");
|
||||
Find[HAND_ROTATE] = str8_lit("Rotate");
|
||||
Find[HAND_ORTHO] = str8_lit("Orthographic");
|
||||
Find[HAND_LOOK_AT] = str8_lit("LookAt");
|
||||
Find[HAND_QUAT_AXIS_ANGLE] = str8_lit("FromAxisAngle");
|
||||
Find[HAND_MAT_TO_QUAT] = str8_lit("ToQuaternion");
|
||||
}
|
||||
|
||||
/* Match with a bunch of sliding windows, skipping when there can't be a match */
|
||||
u64 MatchProgress[HAND_Size] = {0};
|
||||
b32 FoundTypePrefix = 0;
|
||||
b32 FoundFunctionPrefix = 0;
|
||||
u32 Line = 1;
|
||||
str8_iter(file_content) {
|
||||
if (c == '\n') {
|
||||
Line++;
|
||||
}
|
||||
if (FoundTypePrefix || FoundFunctionPrefix) {
|
||||
if (chr8_is_whitespace(c)
|
||||
|| str8_contains_char(str8_lit("(){}[]:;,.<>~?!@#$%^&+-*/'\""), c)) {
|
||||
FoundTypePrefix = 0;
|
||||
FoundFunctionPrefix = 0;
|
||||
}
|
||||
}
|
||||
for (u32 t = 0; t < PREFIXES_Size; t++) {
|
||||
if (c == Find[t].str[MatchProgress[t]]) {
|
||||
MatchProgress[t]++;
|
||||
if (MatchProgress[t] == Find[t].len) {
|
||||
if (t == PREFIX_TYPE) {
|
||||
FoundTypePrefix = 1;
|
||||
} else if (t == PREFIX_FUNCTION) {
|
||||
FoundFunctionPrefix = 1;
|
||||
}
|
||||
MatchProgress[t] = 0;
|
||||
}
|
||||
} else {
|
||||
MatchProgress[t] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace hmm_ types */
|
||||
if (FoundTypePrefix) {
|
||||
for (u32 t = PREFIXES_Size+1; t < TYPES_Size; t++) {
|
||||
if (c == Find[t].str[MatchProgress[t]]) {
|
||||
MatchProgress[t]++;
|
||||
if (MatchProgress[t] == Find[t].len) {
|
||||
MatchProgress[t] = 0;
|
||||
printf("\t[%u]: Find: %.*s, Repl: %.*s.\n", Line, str8_PRINTF_ARGS(Find[t]), str8_PRINTF_ARGS(Repl[t]));
|
||||
Str8List_add(arena, &out,
|
||||
str8_first(file_content,
|
||||
i + 1 - (Find[t].len + Find[PREFIX_TYPE].len)));
|
||||
Str8List_add(arena, &out, Repl[PREFIX_TYPE]);
|
||||
Str8List_add(arena, &out, Repl[t]);
|
||||
file_content = str8_skip(file_content, i+1);
|
||||
i = -1;
|
||||
}
|
||||
} else {
|
||||
MatchProgress[t] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If in a HMM_ function, do function name replacements */
|
||||
if (FoundFunctionPrefix) {
|
||||
for (u32 t = TYPES_Size+1; t < FUNCTIONS_Size; t++) {
|
||||
if (c == Find[t].str[MatchProgress[t]]) {
|
||||
MatchProgress[t]++;
|
||||
if (MatchProgress[t] == Find[t].len) {
|
||||
MatchProgress[t] = 0;
|
||||
printf("\t[%u]: Find: %.*s, Repl: %.*s.\n", Line, str8_PRINTF_ARGS(Find[t]), str8_PRINTF_ARGS(Repl[t]));
|
||||
Str8List_add(arena, &out, str8_first(file_content, i + 1 - Find[t].len));
|
||||
Str8List_add(arena, &out, Repl[t]);
|
||||
file_content = str8_skip(file_content, i+1);
|
||||
i = -1;
|
||||
|
||||
/* NOTE(lcf): Special case because Find[] overlaps here */
|
||||
if (t == FUN_R_SQUARE_ROOT) {
|
||||
MatchProgress[FUN_SQUARE_ROOT] = 0;
|
||||
}
|
||||
|
||||
if (t == FUN_LINEAR_COMBINE_SSE) {
|
||||
printf("\t[%u]: HMM_LinearCombineSSE is now HMM_LinearCombineV4M4, and will now use a fallback method when SSE is not available. \n\tYou no longer need to check for the availability of SSE.\n", Line);
|
||||
}
|
||||
|
||||
if (t == FUN_VEC) {
|
||||
/* NOTE(lcf): if pattern is Vec2i, this is now i */
|
||||
c = file_content.str[1];
|
||||
if (c == 'i') {
|
||||
Str8List_add(arena, &out, str8_first(file_content, 1));
|
||||
Str8List_add(arena, &out, str8_lit("I"));
|
||||
file_content = str8_skip(file_content, 2);
|
||||
} else if (c == 'v') {
|
||||
Str8List_add(arena, &out, str8_first(file_content, 1));
|
||||
Str8List_add(arena, &out, str8_lit("V"));
|
||||
file_content = str8_skip(file_content, 2);
|
||||
} else if (c == 'f') {
|
||||
Str8List_add(arena, &out, str8_first(file_content, 1));
|
||||
Str8List_add(arena, &out, str8_lit("F"));
|
||||
file_content = str8_skip(file_content, 2);
|
||||
}
|
||||
} else if (t == FUN_MAT) {
|
||||
/* if pattern is Mat4d, this is now d */
|
||||
c = file_content.str[1];
|
||||
if (c == 'd') {
|
||||
Str8List_add(arena, &out, str8_first(file_content, 1));
|
||||
Str8List_add(arena, &out, str8_lit("D"));
|
||||
file_content = str8_skip(file_content, 2);
|
||||
} else if (c == 'f') {
|
||||
Str8List_add(arena, &out, str8_first(file_content, 1));
|
||||
Str8List_add(arena, &out, str8_lit("F"));
|
||||
file_content = str8_skip(file_content, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MatchProgress[t] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Handedness cases. */
|
||||
if (FoundFunctionPrefix) {
|
||||
for (u32 t = FUNCTIONS_Size+1; t < HAND_Size; t++) {
|
||||
if (c == Find[t].str[MatchProgress[t]]) {
|
||||
MatchProgress[t]++;
|
||||
if (MatchProgress[t] == Find[t].len) {
|
||||
MatchProgress[t] = 0;
|
||||
|
||||
chr8 check = file_content.str[i+1];
|
||||
if (check == '(') {
|
||||
printf("\t[%u]: Find: %.*s, Appending: _RH for old default handedness.\n", Line, str8_PRINTF_ARGS(Find[t]));
|
||||
Str8List_add(arena, &out, str8_first(file_content, i + 1));
|
||||
Str8List_add(arena, &out, str8_lit("_RH("));
|
||||
file_content = str8_skip(file_content, i+2);
|
||||
i = -1;
|
||||
|
||||
if (t == HAND_PERSPECTIVE || t == HAND_ROTATE) {
|
||||
printf("\t[%u]: ", Line);
|
||||
if (t == HAND_PERSPECTIVE) {
|
||||
printf("HMM_Perspective_RH()");
|
||||
} else {
|
||||
printf("HMM_Rotate_RH()");
|
||||
}
|
||||
printf(" now takes Radians. Wrapping Degrees with HMM_AngleDeg()\n");
|
||||
u64 end_arg = str8_char_location(file_content, ',');
|
||||
if (end_arg != LCF_STRING_NO_MATCH) {
|
||||
Str8List_add(arena, &out, str8_lit("HMM_AngleDeg("));
|
||||
Str8List_add(arena, &out, str8_first(file_content, end_arg));
|
||||
Str8List_add(arena, &out, str8_lit(")"));
|
||||
file_content = str8_skip(file_content, end_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MatchProgress[t] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Str8List_add(arena, &out, file_content);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void print_usage() {
|
||||
printf("Updates C and C++ source code to use Handmade Math version 2.\n");
|
||||
#ifdef _WIN32
|
||||
printf("Usage: update_hmm.exe <filename> [<filename>...]\n");
|
||||
#else
|
||||
printf("Usage: update_hmm <filename> [<filename>...]\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
Arena *tempa = Arena_create(GB(1));
|
||||
|
||||
if (argc == 1) {
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
s32 argi = 1;
|
||||
str8 arg = str8_from_cstring(argv[argi]);
|
||||
|
||||
if (arg.len == 2 && (arg.str[1] == 'h' || arg.str[1] == '?')) {
|
||||
print_usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (; argi < argc; argi++) {
|
||||
arg = str8_from_cstring(argv[argi]);
|
||||
str8 file_content = stdio_load_entire_file(tempa, arg);
|
||||
if (str8_is_empty(file_content)) {
|
||||
printf("X - Invalid file name: %.*s\n\n", str8_PRINTF_ARGS(arg));
|
||||
continue;
|
||||
}
|
||||
printf("O - Updating file: %.*s -------------------\n", str8_PRINTF_ARGS(arg));
|
||||
Str8List result = update_file_content(tempa, file_content);
|
||||
printf("\n");
|
||||
stdio_write_file(arg, result);
|
||||
|
||||
Arena_reset_all(tempa);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
12
update/update_hmm_all.bat
Normal file
12
update/update_hmm_all.bat
Normal file
@@ -0,0 +1,12 @@
|
||||
@REM Batch script to run update_hmm.exe on all your code files.
|
||||
@REM Example:
|
||||
@REM "update_hmm_all.bat Code\Project\" -> Recursively update all files/folders in .\Code\Project\
|
||||
|
||||
for /r %1 %%v in (*.c) do update_hmm.exe "%%v"
|
||||
for /r %1 %%v in (*.h) do update_hmm.exe "%%v"
|
||||
for /r %1 %%v in (*.cpp) do update_hmm.exe "%%v"
|
||||
for /r %1 %%v in (*.hpp) do update_hmm.exe "%%v"
|
||||
|
||||
@REM @REM Uncomment for sokol-samples
|
||||
@REM for /r %1 %%v in (*.glsl) do update_hmm.exe "%%v"
|
||||
@REM for /r %1 %%v in (*.hlsl) do update_hmm.exe "%%v"
|
||||
12
update/update_hmm_all.sh
Normal file
12
update/update_hmm_all.sh
Normal file
@@ -0,0 +1,12 @@
|
||||
# Bash script to run update_hmm on all your code files.
|
||||
# Example:
|
||||
# "update_hmm_all Code/Project/" -> Recursively update all files/folders in ./Code/Project/
|
||||
echo $1
|
||||
for file in "$1"/*.{c,h,cpp,hpp} "$1"/**/*.{c,h,cpp,hpp} ; do
|
||||
./update_hmm "$file"
|
||||
done
|
||||
|
||||
# # Uncomment for sokol-samples
|
||||
# for file in "$1"/*.{glsl,hlsl} "$1"/**/*.{glsl,hlsl} ; do
|
||||
# ./update_hmm "$file"
|
||||
# done
|
||||
Reference in New Issue
Block a user