Compare commits

...

34 Commits

Author SHA1 Message Date
Ben Visness
f106a0f5f3 Style and docs pass for release
Remove V2I, V3I, V4I (and style changes)

Totally useless.

Add update tool, update docs

Tweak docs

Create ci.yml

Big style pass

Maybe fix CI on Windows

Report coverage errors

Fix a missing coverage case

Try setting up MSVC another way

Update readmes

Fix remaining use of the name UpdateTool
2023-01-22 21:46:22 -06:00
Logan Forman
c24e4ff873 HMM2.0 (#149)
These changes were all made by @dev-dwarf. Many thanks for his work on this!

* Renaming

* First Pass on 2.0UpdateTool

* Another pass on UpdateTool, changed name

* Another pass on UpdateTool, changed name

* Do Renaming

* Working on Angles Consistency

* Passing Coverage

* Remove unused arc-tangent functions

* Change macro defaults

By default if user is overriding trig functions assume their input and internal units are the same.

* wrap in AngleDeg instead of AngleRad

* Remove HMM_PREFIX configuration

* Fix for Slerp

https://discord.com/channels/239737791225790464/489148972305350656/1055167647274246265

Justified by most implementations of Slerp. EX: http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/

* Handedness Changes

* More renaming. C11 _Generics

Generics enable by default when available (see lines 97-104). User can also force them by defining HANDMADE_MATH_C11_GENERICS

Also fixed some missed things w.r.t renaming. My old tool didn't catch cases like HMM_MultiplyVec3f needing to be HMM_MulV3F instead of HMM_MulV3f.

* Reuse more SSE codepaths for Quaternions

Also improved quaternion tests. More work could be done here, see discussion here about optimizing slerp: https://discord.com/channels/239737791225790464/489148972305350656/1055167647274246265

* Just saving these alternate versions of SLerp

* Reduce V4/M4 Linear Comb. codepaths

* Simple implementation of 2x2 and 3x3 basic matrix operations.

Also renamed Transpose to TransposeM4, so that we can have TransposeM2,M3

* Norm is dead! Long live Norm!

As can be seen from the tests, precision has declined quite a bit from using the FastNorm implementations for various things. We can only guarantee about 0.001f precision for anything where a norm happens now. If this is undesired we can change back easily.

* Started work on Matrix Inverses

TODO: Tests for simple 4x4 Inverses

* Matrix Inverses + Tests

* Generics for Matrices and Rename MXd/f functions

* Fixes + Better Output for UpdateTool

* I think I count as a contributor : )

* Ported UpdateTool, Inlined my library code.

* Moved tool to different repo

https://github.com/dev-dwarf/HMM2.0UpdateTool

* Remove small test change

* Found some more references to atan functions

* Standardize angle function names, use short names

* Remove other slerp comments

* woops that wasnt meant to be commited.

* Finish changing ToRadians to ToRad

* Fix [] overloads

per https://discord.com/channels/239737791225790464/600063880533770251/1051600188302692402

* Tests for 2x2, 3x3 Matrices and Other Matrix Ops

* Add an option to use Z: [0, 1] range for projection matrices.

This will make HMM more convenient to use with other graphics APIs such as Direct3d and Metal.

* Update test imports

* #if should've been #ifdef!

* Implement requested changes
2023-01-22 17:34:50 -06:00
Zak Strange
ba5405ac0f Update README.md 2021-08-31 17:11:42 -07:00
Zak Strange
d69a859d73 Fully inlined HandmadeMath.h (#139)
* Fully inlined HandmadeMath.h, renamed test.bat to run_test_msvc.bat, and introduced run_test_clang.bat

* General Cleanup
2021-08-31 17:10:46 -07:00
strangezak
8c18186b3b Removed Unnecessary Square Root from InverseQuaternion. Closes #136 2021-08-31 09:28:02 -07:00
Tim Gates
5f816bf9b3 docs: fix simple typo, percision -> precision (#137)
There is a small typo in README.md.

Should read `precision` rather than `percision`.
2021-08-31 09:22:29 -07:00
Jørgen P. Tjernø
c5bc802042 Suppress two warnings on clang 12 (#138)
Building with clang 12 with -Wextra, the following two warnings are
generated:

```
HandmadeMath.h:1167:25: warning: missing field 'Y' initializer [-Wmissing-field-initializers]
    hmm_vec2 Result = {0};
                        ^
HandmadeMath.h:1167:24: warning: suggest braces around initialization of subobject [-Wmissing-braces]
```

This expands the `-Wmissing-braces` ignore to also target clang, and adds an
ignore for `-Wmissing-field-initializers`
2021-08-31 09:37:54 -05:00
Ben Visness
43afc87fa7 Remove non-functioning issue link 2021-03-24 10:04:17 -05:00
Ben Visness
5bbac2167e Update version and changelog 2021-03-24 10:02:08 -05:00
Wayde Reitsma
655c662528 Add brackets around HMM_MIN, HMM_MAX, and HMM_MOD (#133)
* Add brackets around HMM_MIN and HMM_MAX

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

* Update README.md

Co-authored-by: zak <zak@DESKTOP-V1AQ0IT>
2021-03-06 18:39:17 -06:00
Zak Strange
2fa0b36715 Add HMM_STATIC option to statically link instead of extern (#127)
Co-authored-by: zak <zak@DESKTOP-V1AQ0IT>
2021-02-17 19:36:05 -08:00
Ben Visness
ad169e649c Make HMM_Clamp branchless in optimized builds (#122) 2020-12-22 11:19:58 -06:00
Zak Strange
1900cc9275 Updated email in HandmadeMath.h 2020-07-09 18:22:22 -07:00
Ben Visness
ddb9971e71 Update README 2020-07-09 08:51:53 -05:00
GsxCasper
341a376a17 Added HMM_PREFIX macro to function implementations (#120) 2020-07-08 16:32:29 -05:00
Ben Visness
c825fe48cf Update version and release notes 2020-04-06 10:02:16 -05:00
Ben Visness
15bef820db Add ability to customize HMM_ prefix (#114)
* Add prefix macro and use it everywhere

* Add lightweight test for prefix

* Add a little doc blurb
2020-04-06 09:57:10 -05:00
Ben Visness
fe32f081f2 Suppress float equality warnings (#113)
* Add a macro to help with deprecations

* Suppress warnings about float equality
2020-04-06 09:55:40 -05:00
Zak Strange
785f19d4a7 Removed use of stdint.h (#110) 2020-01-11 17:13:09 -08:00
Ben Visness
a9b08b9147 Run tests on Linux, macOS, and Windows (#105)
* Try running tests on all three operating systems

* Try adding an MSVC build

* Make tests work on Windows

* Try reconfiguring Travis for this

* Maybe it's because we're in git bash

* Try explicitly doing something else for travis

* Remove a part I think is unnecessary

* Run the test EXEs as they compile
2019-07-31 17:22:33 -05:00
Ben Visness
f376f2a2a7 Add test coverage macros (#104)
* Add coverage features and add it, laboriously, to everything

* Fix easy tests

* Add tests for != operators

* Clean up test framework a little

* Add documentation of coverage macros

* Fix tests for mat4 to quaternion

* Slightly improve formatting of coverage output

* Trailing whitespace must die
2019-07-31 16:43:56 -05:00
Ben Visness
78e6feea82 Add HMM_Mat4ToQuaternion (#103)
* Add mat4 to quaternion method

* Capitalize variables
2019-07-31 16:38:03 -05:00
Zak Strange
21aa828a08 Fixed issue related to unsigned/signed-ness of HMM_Power (#102)
* Fixed issue related to unsigned/signed-ness of HMM_Power

* Fixes missing braces around initializer warning with -Weverything with GCC.
2019-07-17 14:48:59 -07:00
Ben Visness
93e56be543 Use vertical instead of horizontal FOV in HMM_Perspective (#101)
* Use vertical instead of horizontal FOV

* Update readme

* Fix tests
2019-07-10 11:29:51 -05:00
Ben Visness
45c91702a9 Added SSE support for Quaternion operations (#97) (#98)
* Added SSE support for Quaternion operations (#97)

* Added SSE support for Quaternion operations

O2
| Function    |     SSE         |      NO SSE      |
====================================================
| Inverse     |     163 (0.89s) |      165 (1.89s) |
| NLerp       |     330 (1.70s) |      330 (1.75s) |
| Normalize   |     169 (1.03s) |      169 (1.06s) |
| Dot         |     22  (1.15s) |      23  (1.14s) |
| DivF        |     23  (0.72s) |      23  (0.82s) |
| MulF        |     22  (0.75s) |      22  (0.79s) |
| Mul         |     24  (1.14s) |      23  (1.24s) |
| Sub         |     23  (1.17s) |      37  (1.20s) |
| Add         |     23  (1.20s) |      24  (1.19s) |



O0
| Function    |     SSE         |      NO SSE      |
====================================================
| Inverse     |     394 (1.62s) |      430 (3.05s) |
| NLerp       |     694 (2.71s) |      1035(4.81s) |
| Normalize   |     374 (1.58s) |      412 (2.95s) |
| Dot         |     81  (1.83s) |      23  (2.50s) |
| DivF        |     61  (1.12s) |      25  (2.37s) |
| MulF        |     58  (1.09s) |      23  (2.31s) |
| Mul         |     94  (1.97s) |      42  (2.88s) |
| Sub         |     75  (1.83s) |      23  (2.82s) |
| Add         |     75  (1.81s) |      23  (2.81s) |

* Fixed quaternion multiplication

Old quaternion multiplication had a bug, this is a different approach.

* Added release notes and version for 1.9.0
2019-03-11 13:12:48 -05:00
Ben Visness
f7c8e1f7d1 Add fast vector normalization (#94)
* Add fast normalization routines

* Update readme and remove version history from main file

* Update version at top of file
2018-11-29 22:02:41 -08:00
Ben Visness
5ca1d58b36 Improve grammar/spelling 2018-11-29 13:21:05 -06:00
Zak Strange
5bf727dbd5 Removed copy in operator[] (#93)
* Removed copy in operator[]

* Updated version info
2018-11-29 09:32:12 -08:00
Ben Visness
295f6c476f Rename Rows to Columns on hmm_mat4 (#91) 2018-08-17 11:02:44 -07:00
Ben Visness
e095aefaf7 Bump file version 2018-06-10 15:32:12 -04:00
Ben Visness
4e2f47db55 Add array subscript operators for all types (#88)
* Add array subscript operators for all types

* Taking the parameter for the operator[] as a reference. This should allow it to be inlined

* I guess you can't do that.

* Update version and readme
2018-06-10 15:26:48 -04:00
Ben Visness
bee0e0c569 WIP: Properly initialize all elements of LookAt matrix (#84)
* Properly initialize all elements of LookAt matrix

* Update version and readme

* Add a test for LookAt

good enough
2018-06-03 18:42:09 -05:00
31 changed files with 5990 additions and 2441 deletions

34
.github/workflows/ci.yml vendored Normal file
View 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'

0
.gitmodules vendored
View File

View File

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

View File

@@ -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.

File diff suppressed because it is too large Load Diff

View File

@@ -1,39 +1,25 @@
# Handmade Math
[![Build Status](https://travis-ci.org/HandmadeMath/Handmade-Math.svg?branch=master)](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.

View File

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

View File

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

View File

@@ -1,13 +1,18 @@
BUILD_DIR=build
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 -rf $(BUILD_DIR)
c: HandmadeMath.c test_impl
c: build_c
$(BUILD_DIR)/hmm_test_c
build_c: HandmadeMath.c test_impl
@echo "\nCompiling in C mode"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR)\
@@ -16,7 +21,10 @@ c: HandmadeMath.c test_impl
-lm \
&& $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
c_no_sse: 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)"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
@@ -26,7 +34,10 @@ c_no_sse: HandmadeMath.c test_impl
-lm \
&& $(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm
cpp: HandmadeMath.cpp test_impl
cpp: build_cpp
$(BUILD_DIR)/hmm_test_cpp
build_cpp: HandmadeMath.cpp test_impl
@echo "\nCompiling in C++ mode"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
@@ -34,7 +45,10 @@ cpp: HandmadeMath.cpp test_impl
-DHANDMADE_MATH_CPP_MODE \
../HandmadeMath.cpp ../hmm_test.cpp
cpp_no_sse: 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)"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
@@ -43,3 +57,22 @@ cpp_no_sse: HandmadeMath.cpp test_impl
../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

View File

@@ -4,8 +4,13 @@ You can compile and run the tests yourself by running:
```
make
build/hmm_test_c
build/hmm_test_c_no_sse
build/hmm_test_cpp
build/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
```

View File

@@ -2,22 +2,22 @@
TEST(Addition, Vec2)
{
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 v2_2 = HMM_Vec2(3.0f, 4.0f);
HMM_Vec2 v2_1 = HMM_V2(1.0f, 2.0f);
HMM_Vec2 v2_2 = HMM_V2(3.0f, 4.0f);
{
hmm_vec2 result = HMM_AddVec2(v2_1, v2_2);
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);
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;
HMM_Vec2 result = v2_1 + v2_2;
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
@@ -30,24 +30,24 @@ TEST(Addition, Vec2)
TEST(Addition, Vec3)
{
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3_2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
HMM_Vec3 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_AddVec3(v3_1, v3_2);
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);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
#ifdef __cplusplus
{
hmm_vec3 result = HMM_Add(v3_1, v3_2);
HMM_Vec3 result = HMM_Add(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 7.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
{
hmm_vec3 result = v3_1 + v3_2;
HMM_Vec3 result = v3_1 + v3_2;
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 7.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
@@ -62,11 +62,11 @@ TEST(Addition, Vec3)
TEST(Addition, Vec4)
{
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v4_2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
HMM_Vec4 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_AddVec4(v4_1, v4_2);
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);
@@ -74,14 +74,14 @@ TEST(Addition, Vec4)
}
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Add(v4_1, v4_2);
HMM_Vec4 result = HMM_Add(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
{
hmm_vec4 result = v4_1 + v4_2;
HMM_Vec4 result = v4_1 + v4_2;
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
@@ -96,10 +96,134 @@ TEST(Addition, Vec4)
#endif
}
TEST(Addition, Mat2)
{
HMM_Mat2 a = HMM_M2();
HMM_Mat2 b = HMM_M2();
int Counter = 1;
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
a.Elements[Column][Row] = Counter++;
}
}
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
b.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat2 result = HMM_AddM2(a, b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 8.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 12.0f);
}
#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_Mat4(); // will have 1 - 16
hmm_mat4 m4_2 = HMM_Mat4(); // will have 17 - 32
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;
@@ -122,7 +246,7 @@ TEST(Addition, Mat4)
// Test the results
{
hmm_mat4 result = HMM_AddMat4(m4_1, m4_2);
HMM_Mat4 result = HMM_AddM4(m4_1, m4_2);
float Expected = 18.0f;
for (int Column = 0; Column < 4; ++Column)
{
@@ -135,7 +259,7 @@ TEST(Addition, Mat4)
}
#ifdef __cplusplus
{
hmm_mat4 result = HMM_Add(m4_1, m4_2);
HMM_Mat4 result = HMM_Add(m4_1, m4_2);
float Expected = 18.0f;
for (int Column = 0; Column < 4; ++Column)
{
@@ -147,7 +271,7 @@ TEST(Addition, Mat4)
}
}
{
hmm_mat4 result = m4_1 + m4_2;
HMM_Mat4 result = m4_1 + m4_2;
float Expected = 18.0f;
for (int Column = 0; Column < 4; ++Column)
{
@@ -174,11 +298,11 @@ TEST(Addition, Mat4)
TEST(Addition, Quaternion)
{
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f);
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
{
hmm_quaternion result = HMM_AddQuaternion(q1, q2);
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);
@@ -186,14 +310,14 @@ TEST(Addition, Quaternion)
}
#ifdef __cplusplus
{
hmm_quaternion result = HMM_Add(q1, q2);
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_quaternion result = q1 + q2;
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);

View File

@@ -2,22 +2,22 @@
TEST(Division, Vec2Vec2)
{
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 3.0f);
hmm_vec2 v2_2 = HMM_Vec2(2.0f, 4.0f);
HMM_Vec2 v2_1 = HMM_V2(1.0f, 3.0f);
HMM_Vec2 v2_2 = HMM_V2(2.0f, 4.0f);
{
hmm_vec2 result = HMM_DivideVec2(v2_1, v2_2);
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_Divide(v2_1, v2_2);
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;
HMM_Vec2 result = v2_1 / v2_2;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
}
@@ -30,22 +30,22 @@ TEST(Division, Vec2Vec2)
TEST(Division, Vec2Scalar)
{
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f);
HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
float s = 2;
{
hmm_vec2 result = HMM_DivideVec2f(v2, s);
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_Divide(v2, s);
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;
HMM_Vec2 result = v2 / s;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
}
@@ -58,24 +58,24 @@ TEST(Division, Vec2Scalar)
TEST(Division, Vec3Vec3)
{
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 3.0f, 5.0f);
hmm_vec3 v3_2 = HMM_Vec3(2.0f, 4.0f, 0.5f);
HMM_Vec3 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_DivideVec3(v3_1, v3_2);
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_Divide(v3_1, v3_2);
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;
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);
@@ -90,24 +90,24 @@ TEST(Division, Vec3Vec3)
TEST(Division, Vec3Scalar)
{
hmm_vec3 v3 = HMM_Vec3(1.0f, 2.0f, 3.0f);
HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
float s = 2;
{
hmm_vec3 result = HMM_DivideVec3f(v3, s);
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_Divide(v3, s);
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;
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);
@@ -122,11 +122,11 @@ TEST(Division, Vec3Scalar)
TEST(Division, Vec4Vec4)
{
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 3.0f, 5.0f, 1.0f);
hmm_vec4 v4_2 = HMM_Vec4(2.0f, 4.0f, 0.5f, 4.0f);
HMM_Vec4 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_DivideVec4(v4_1, v4_2);
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);
@@ -134,14 +134,14 @@ TEST(Division, Vec4Vec4)
}
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Divide(v4_1, v4_2);
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;
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);
@@ -158,11 +158,11 @@ TEST(Division, Vec4Vec4)
TEST(Division, Vec4Scalar)
{
hmm_vec4 v4 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
float s = 2;
{
hmm_vec4 result = HMM_DivideVec4f(v4, s);
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);
@@ -170,14 +170,14 @@ TEST(Division, Vec4Scalar)
}
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Divide(v4, s);
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;
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);
@@ -192,9 +192,103 @@ TEST(Division, Vec4Scalar)
#endif
}
TEST(Division, Mat2Scalar)
{
HMM_Mat2 m = HMM_M2();
float s = 0.5f;
int Counter = 1;
for (int Column = 0; Column < 2; ++Column) {
for (int Row = 0; Row < 2; ++Row) {
m.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat2 result = HMM_DivM2F(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f);
}
#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_Mat4(); // will have 1 - 16
HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
float s = 2;
// Fill the matrix
@@ -210,7 +304,7 @@ TEST(Division, Mat4Scalar)
// Test the results
{
hmm_mat4 result = HMM_DivideMat4f(m4, s);
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);
@@ -230,7 +324,7 @@ TEST(Division, Mat4Scalar)
}
#ifdef __cplusplus
{
hmm_mat4 result = HMM_Divide(m4, s);
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);
@@ -249,7 +343,7 @@ TEST(Division, Mat4Scalar)
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
}
{
hmm_mat4 result = m4 / s;
HMM_Mat4 result = m4 / s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
@@ -290,11 +384,11 @@ TEST(Division, Mat4Scalar)
TEST(Division, QuaternionScalar)
{
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
float f = 2.0f;
{
hmm_quaternion result = HMM_DivideQuaternionF(q, f);
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);
@@ -302,14 +396,14 @@ TEST(Division, QuaternionScalar)
}
#ifdef __cplusplus
{
hmm_quaternion result = HMM_Divide(q, f);
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_quaternion result = q / f;
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);

View File

@@ -2,54 +2,63 @@
TEST(Equality, Vec2)
{
hmm_vec2 a = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 b = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 c = HMM_Vec2(3.0f, 4.0f);
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_EqualsVec2(a, b));
EXPECT_FALSE(HMM_EqualsVec2(a, c));
EXPECT_TRUE(HMM_EqV2(a, b));
EXPECT_FALSE(HMM_EqV2(a, c));
#ifdef __cplusplus
EXPECT_TRUE(HMM_Equals(a, b));
EXPECT_FALSE(HMM_Equals(a, c));
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_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 b = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 c = HMM_Vec3(4.0f, 5.0f, 6.0f);
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_EqualsVec3(a, b));
EXPECT_FALSE(HMM_EqualsVec3(a, c));
EXPECT_TRUE(HMM_EqV3(a, b));
EXPECT_FALSE(HMM_EqV3(a, c));
#ifdef __cplusplus
EXPECT_TRUE(HMM_Equals(a, b));
EXPECT_FALSE(HMM_Equals(a, c));
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_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 b = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 c = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
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_EqualsVec4(a, b));
EXPECT_FALSE(HMM_EqualsVec4(a, c));
EXPECT_TRUE(HMM_EqV4(a, b));
EXPECT_FALSE(HMM_EqV4(a, c));
#ifdef __cplusplus
EXPECT_TRUE(HMM_Equals(a, b));
EXPECT_FALSE(HMM_Equals(a, c));
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
}

View File

@@ -4,9 +4,8 @@ TEST(Initialization, Vectors)
{
//
// Test vec2
//
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 v2i = HMM_Vec2(1, 2);
//
HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
EXPECT_FLOAT_EQ(v2.X, 1.0f);
EXPECT_FLOAT_EQ(v2.Y, 2.0f);
@@ -18,23 +17,15 @@ TEST(Initialization, Vectors)
EXPECT_FLOAT_EQ(v2.Height, 2.0f);
EXPECT_FLOAT_EQ(v2.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v2.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v2i.X, 1.0f);
EXPECT_FLOAT_EQ(v2i.Y, 2.0f);
EXPECT_FLOAT_EQ(v2i.U, 1.0f);
EXPECT_FLOAT_EQ(v2i.V, 2.0f);
EXPECT_FLOAT_EQ(v2i.Left, 1.0f);
EXPECT_FLOAT_EQ(v2i.Right, 2.0f);
EXPECT_FLOAT_EQ(v2i.Width, 1.0f);
EXPECT_FLOAT_EQ(v2i.Height, 2.0f);
EXPECT_FLOAT_EQ(v2i.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v2i.Elements[1], 2.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(v2[0], 1.0f);
EXPECT_FLOAT_EQ(v2[1], 2.0f);
#endif
//
// Test vec3
//
hmm_vec3 v3 = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3i = HMM_Vec3i(1, 2, 3);
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);
@@ -56,34 +47,17 @@ TEST(Initialization, Vectors)
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);
EXPECT_FLOAT_EQ(v3i.X, 1.0f);
EXPECT_FLOAT_EQ(v3i.Y, 2.0f);
EXPECT_FLOAT_EQ(v3i.Z, 3.0f);
EXPECT_FLOAT_EQ(v3i.U, 1.0f);
EXPECT_FLOAT_EQ(v3i.V, 2.0f);
EXPECT_FLOAT_EQ(v3i.W, 3.0f);
EXPECT_FLOAT_EQ(v3i.R, 1.0f);
EXPECT_FLOAT_EQ(v3i.G, 2.0f);
EXPECT_FLOAT_EQ(v3i.B, 3.0f);
EXPECT_FLOAT_EQ(v3i.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v3i.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v3i.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(v3i.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v3i.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v3i.YZ.Elements[0], 2.0f);
EXPECT_FLOAT_EQ(v3i.YZ.Elements[1], 3.0f);
EXPECT_FLOAT_EQ(v3i.UV.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v3i.UV.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v3i.VW.Elements[0], 2.0f);
EXPECT_FLOAT_EQ(v3i.VW.Elements[1], 3.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(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_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v4i = HMM_Vec4i(1, 2, 3, 4);
hmm_vec4 v4v = HMM_Vec4v(v3, 4.0f);
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);
@@ -107,29 +81,12 @@ TEST(Initialization, Vectors)
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);
EXPECT_FLOAT_EQ(v4i.X, 1.0f);
EXPECT_FLOAT_EQ(v4i.Y, 2.0f);
EXPECT_FLOAT_EQ(v4i.Z, 3.0f);
EXPECT_FLOAT_EQ(v4i.W, 4.0f);
EXPECT_FLOAT_EQ(v4i.R, 1.0f);
EXPECT_FLOAT_EQ(v4i.G, 2.0f);
EXPECT_FLOAT_EQ(v4i.B, 3.0f);
EXPECT_FLOAT_EQ(v4i.A, 4.0f);
EXPECT_FLOAT_EQ(v4i.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4i.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4i.YZ.Elements[0], 2.0f);
EXPECT_FLOAT_EQ(v4i.YZ.Elements[1], 3.0f);
EXPECT_FLOAT_EQ(v4i.ZW.Elements[0], 3.0f);
EXPECT_FLOAT_EQ(v4i.ZW.Elements[1], 4.0f);
EXPECT_FLOAT_EQ(v4i.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4i.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4i.XYZ.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4i.XYZ.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4i.XYZ.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(v4i.RGB.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4i.RGB.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4i.RGB.Elements[2], 3.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(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);
@@ -153,23 +110,100 @@ TEST(Initialization, Vectors)
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)
{
hmm_mat4 m4 = HMM_Mat4();
//
// 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)
{
hmm_mat4 m4d = HMM_Mat4d(1.0f);
//
// 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)
@@ -185,7 +219,7 @@ TEST(Initialization, MatrixDiagonal)
TEST(Initialization, Quaternion)
{
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
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);
@@ -197,11 +231,91 @@ TEST(Initialization, Quaternion)
EXPECT_FLOAT_EQ(q.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(q.Elements[3], 4.0f);
hmm_vec4 v = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion qv = HMM_QuaternionV4(v);
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
View 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]);
}
}

View File

@@ -2,22 +2,22 @@
TEST(Multiplication, Vec2Vec2)
{
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 v2_2 = HMM_Vec2(3.0f, 4.0f);
HMM_Vec2 v2_1 = HMM_V2(1.0f, 2.0f);
HMM_Vec2 v2_2 = HMM_V2(3.0f, 4.0f);
{
hmm_vec2 result = HMM_MultiplyVec2(v2_1, v2_2);
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_Multiply(v2_1, v2_2);
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;
HMM_Vec2 result = v2_1 * v2_2;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
}
@@ -30,27 +30,27 @@ TEST(Multiplication, Vec2Vec2)
TEST(Multiplication, Vec2Scalar)
{
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f);
HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
float s = 3.0f;
{
hmm_vec2 result = HMM_MultiplyVec2f(v2, s);
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_Multiply(v2, s);
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;
HMM_Vec2 result = v2 * s;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
{
hmm_vec2 result = s * v2;
HMM_Vec2 result = s * v2;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
@@ -63,24 +63,24 @@ TEST(Multiplication, Vec2Scalar)
TEST(Multiplication, Vec3Vec3)
{
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3_2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
HMM_Vec3 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_MultiplyVec3(v3_1, v3_2);
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_Multiply(v3_1, v3_2);
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;
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);
@@ -95,30 +95,30 @@ TEST(Multiplication, Vec3Vec3)
TEST(Multiplication, Vec3Scalar)
{
hmm_vec3 v3 = HMM_Vec3(1.0f, 2.0f, 3.0f);
HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
float s = 3.0f;
{
hmm_vec3 result = HMM_MultiplyVec3f(v3, s);
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_Multiply(v3, s);
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;
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;
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);
@@ -133,11 +133,11 @@ TEST(Multiplication, Vec3Scalar)
TEST(Multiplication, Vec4Vec4)
{
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v4_2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
HMM_Vec4 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_MultiplyVec4(v4_1, v4_2);
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);
@@ -145,14 +145,14 @@ TEST(Multiplication, Vec4Vec4)
}
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Multiply(v4_1, v4_2);
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;
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);
@@ -169,11 +169,11 @@ TEST(Multiplication, Vec4Vec4)
TEST(Multiplication, Vec4Scalar)
{
hmm_vec4 v4 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
float s = 3.0f;
{
hmm_vec4 result = HMM_MultiplyVec4f(v4, s);
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);
@@ -181,21 +181,21 @@ TEST(Multiplication, Vec4Scalar)
}
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Multiply(v4, s);
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;
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;
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);
@@ -209,10 +209,309 @@ TEST(Multiplication, Vec4Scalar)
#endif
}
TEST(Multiplication, Mat2Mat2) {
HMM_Mat2 a = HMM_M2();
HMM_Mat2 b = HMM_M2();
int counter = 1;
for (int Column = 0; Column < 2; Column++) {
for (int Row = 0; Row < 2; Row++) {
a.Elements[Column][Row] = counter++;
}
}
for (int Column = 0; Column < 2; Column++) {
for (int Row = 0; Row < 2; Row++) {
b.Elements[Column][Row] = counter++;
}
}
{
HMM_Mat2 result = HMM_MulM2(a,b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 34.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 31.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 46.0f);
}
#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_Mat4(); // will have 1 - 16
hmm_mat4 m4_2 = HMM_Mat4(); // will have 17 - 32
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;
@@ -235,7 +534,7 @@ TEST(Multiplication, Mat4Mat4)
// Test the results
{
hmm_mat4 result = HMM_MultiplyMat4(m4_1, m4_2);
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);
@@ -255,7 +554,7 @@ TEST(Multiplication, Mat4Mat4)
}
#ifdef __cplusplus
{
hmm_mat4 result = HMM_Multiply(m4_1, m4_2);
HMM_Mat4 result = HMM_Mul(m4_1, m4_2);
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
@@ -274,7 +573,7 @@ TEST(Multiplication, Mat4Mat4)
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
}
{
hmm_mat4 result = m4_1 * m4_2;
HMM_Mat4 result = m4_1 * m4_2;
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
@@ -301,7 +600,7 @@ TEST(Multiplication, Mat4Mat4)
TEST(Multiplication, Mat4Scalar)
{
hmm_mat4 m4 = HMM_Mat4(); // will have 1 - 16
HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
float s = 3;
// Fill the matrix
@@ -317,7 +616,7 @@ TEST(Multiplication, Mat4Scalar)
// Test the results
{
hmm_mat4 result = HMM_MultiplyMat4f(m4, s);
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);
@@ -337,7 +636,7 @@ TEST(Multiplication, Mat4Scalar)
}
#ifdef __cplusplus
{
hmm_mat4 result = HMM_Multiply(m4, s);
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);
@@ -356,7 +655,7 @@ TEST(Multiplication, Mat4Scalar)
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
}
{
hmm_mat4 result = m4 * s;
HMM_Mat4 result = m4 * s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
@@ -375,7 +674,7 @@ TEST(Multiplication, Mat4Scalar)
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
}
{
hmm_mat4 result = s * m4;
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);
@@ -416,8 +715,8 @@ TEST(Multiplication, Mat4Scalar)
TEST(Multiplication, Mat4Vec4)
{
hmm_mat4 m4 = HMM_Mat4(); // will have 1 - 16
hmm_vec4 v4 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
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;
@@ -432,7 +731,7 @@ TEST(Multiplication, Mat4Vec4)
// Test the results
{
hmm_vec4 result = HMM_MultiplyMat4ByVec4(m4, v4);
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);
@@ -440,14 +739,14 @@ TEST(Multiplication, Mat4Vec4)
}
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Multiply(m4, v4);
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;
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);
@@ -460,11 +759,11 @@ TEST(Multiplication, Mat4Vec4)
TEST(Multiplication, QuaternionQuaternion)
{
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f);
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
{
hmm_quaternion result = HMM_MultiplyQuaternion(q1, q2);
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);
@@ -472,14 +771,14 @@ TEST(Multiplication, QuaternionQuaternion)
}
#ifdef __cplusplus
{
hmm_quaternion result = HMM_Multiply(q1, q2);
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_quaternion result = q1 * q2;
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);
@@ -494,11 +793,11 @@ TEST(Multiplication, QuaternionQuaternion)
TEST(Multiplication, QuaternionScalar)
{
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
float f = 2.0f;
{
hmm_quaternion result = HMM_MultiplyQuaternionF(q, f);
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);
@@ -506,21 +805,21 @@ TEST(Multiplication, QuaternionScalar)
}
#ifdef __cplusplus
{
hmm_quaternion result = HMM_Multiply(q, f);
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_quaternion result = q * f;
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_quaternion result = f * q;
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);

View File

@@ -2,35 +2,48 @@
TEST(Projection, Orthographic)
{
hmm_mat4 projection = HMM_Orthographic(-10.0f, 10.0f, -5.0f, 5.0f, 0.0f, -10.0f);
{
HMM_Mat4 projection = HMM_Orthographic_RH(-10.0f, 10.0f, -5.0f, 5.0f, 0.0f, -10.0f);
hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -5.0f);
hmm_vec4 projected = HMM_MultiplyMat4ByVec4(projection, HMM_Vec4v(original, 1));
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);
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(90.0f, 2.0f, 5.0f, 15.0f);
{
hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -15.0f);
hmm_vec4 projected = HMM_MultiplyMat4ByVec4(projection, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(projected.X, 5.0f);
EXPECT_FLOAT_EQ(projected.Y, 10.0f);
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_vec3 original = HMM_Vec3(5.0f, 5.0f, -5.0f);
hmm_vec4 projected = HMM_MultiplyMat4ByVec4(projection, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(projected.X, 5.0f);
EXPECT_FLOAT_EQ(projected.Y, 10.0f);
EXPECT_FLOAT_EQ(projected.Z, -5.0f);
EXPECT_FLOAT_EQ(projected.W, 5.0f);
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);
}
}

View File

@@ -2,10 +2,10 @@
TEST(QuaternionOps, Inverse)
{
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion inverse = HMM_InverseQuaternion(q1);
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Quat inverse = HMM_InvQ(q1);
hmm_quaternion result = HMM_MultiplyQuaternion(q1, inverse);
HMM_Quat result = HMM_MulQ(q1, inverse);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
@@ -15,11 +15,11 @@ TEST(QuaternionOps, Inverse)
TEST(QuaternionOps, Dot)
{
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f);
HMM_Quat 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_DotQuaternion(q1, q2);
float result = HMM_DotQ(q1, q2);
EXPECT_FLOAT_EQ(result, 70.0f);
}
#ifdef __cplusplus
@@ -32,57 +32,87 @@ TEST(QuaternionOps, Dot)
TEST(QuaternionOps, Normalize)
{
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
{
hmm_quaternion result = HMM_NormalizeQuaternion(q);
EXPECT_FLOAT_EQ(result.X, 0.1825741858f);
EXPECT_FLOAT_EQ(result.Y, 0.3651483717f);
EXPECT_FLOAT_EQ(result.Z, 0.5477225575f);
EXPECT_FLOAT_EQ(result.W, 0.7302967433f);
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_quaternion result = HMM_Normalize(q);
EXPECT_FLOAT_EQ(result.X, 0.1825741858f);
EXPECT_FLOAT_EQ(result.Y, 0.3651483717f);
EXPECT_FLOAT_EQ(result.Z, 0.5477225575f);
EXPECT_FLOAT_EQ(result.W, 0.7302967433f);
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_quaternion from = HMM_Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
hmm_quaternion to = HMM_Quaternion(0.5f, 0.5f, -0.5f, 0.5f);
HMM_Quat from = HMM_Q(0.0f, 0.0f, 0.0f, 1.0f);
HMM_Quat to = HMM_Q(0.5f, 0.5f, -0.5f, 0.5f);
hmm_quaternion result = HMM_NLerp(from, 0.5f, to);
EXPECT_FLOAT_EQ(result.X, 0.28867513f);
EXPECT_FLOAT_EQ(result.Y, 0.28867513f);
EXPECT_FLOAT_EQ(result.Z, -0.28867513f);
EXPECT_FLOAT_EQ(result.W, 0.86602540f);
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)
TEST(QuaternionOps, SLerp)
{
hmm_quaternion from = HMM_Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
hmm_quaternion to = HMM_Quaternion(0.5f, 0.5f, -0.5f, 0.5f);
HMM_Quat from = HMM_Q(0.0f, 0.0f, 0.0f, 1.0f);
HMM_Quat to = HMM_Q(0.5f, 0.5f, -0.5f, 0.5f);
hmm_quaternion result = HMM_Slerp(from, 0.5f, to);
EXPECT_FLOAT_EQ(result.X, 0.28867513f);
EXPECT_FLOAT_EQ(result.Y, 0.28867513f);
EXPECT_FLOAT_EQ(result.Z, -0.28867513f);
EXPECT_FLOAT_EQ(result.W, 0.86602540f);
{
HMM_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, ToMat4)
TEST(QuaternionOps, QuatToMat4)
{
const float abs_error = 0.0001f;
const float abs_error = 0.001f;
hmm_quaternion rot = HMM_Quaternion(0.707107f, 0.0f, 0.0f, 0.707107f);
HMM_Quat rot = HMM_Q(0.707107f, 0.0f, 0.0f, 0.707107f);
hmm_mat4 result = HMM_QuaternionToMat4(rot);
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);
@@ -105,14 +135,142 @@ TEST(QuaternionOps, ToMat4)
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_Vec3(1.0f, 0.0f, 0.0f);
HMM_Vec3 axis = HMM_V3(1.0f, 0.0f, 0.0f);
float angle = HMM_PI32 / 2.0f;
hmm_quaternion result = HMM_QuaternionFromAxisAngle(axis, angle);
EXPECT_NEAR(result.X, 0.707107f, FLT_EPSILON * 2);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
EXPECT_FLOAT_EQ(result.Z, 0.0f);
EXPECT_NEAR(result.W, 0.707107f, FLT_EPSILON * 2);
}
{
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);
}
}

View File

@@ -4,38 +4,36 @@
TEST(SSE, LinearCombine)
{
hmm_mat4 MatrixOne = HMM_Mat4d(2.0f);
hmm_mat4 MatrixTwo = HMM_Mat4d(4.0f);
hmm_mat4 Result;
Result.Rows[0] = HMM_LinearCombineSSE(MatrixOne.Rows[0], MatrixTwo);
Result.Rows[1] = HMM_LinearCombineSSE(MatrixOne.Rows[1], MatrixTwo);
Result.Rows[2] = HMM_LinearCombineSSE(MatrixOne.Rows[2], MatrixTwo);
Result.Rows[3] = HMM_LinearCombineSSE(MatrixOne.Rows[3], MatrixTwo);
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][1], 8.0f);
EXPECT_FLOAT_EQ(Result.Elements[1][2], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[1][3], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[2][0], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[2][1], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[2][1], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[2][2], 8.0f);
EXPECT_FLOAT_EQ(Result.Elements[2][3], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[3][0], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[3][1], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[3][1], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[3][2], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[3][3], 8.0f);
}
EXPECT_FLOAT_EQ(Result.Elements[3][3], 8.0f);
}
}
#endif

View File

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

View File

@@ -2,22 +2,22 @@
TEST(Subtraction, Vec2)
{
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 v2_2 = HMM_Vec2(3.0f, 4.0f);
HMM_Vec2 v2_1 = HMM_V2(1.0f, 2.0f);
HMM_Vec2 v2_2 = HMM_V2(3.0f, 4.0f);
{
hmm_vec2 result = HMM_SubtractVec2(v2_1, v2_2);
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_Subtract(v2_1, v2_2);
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;
HMM_Vec2 result = v2_1 - v2_2;
EXPECT_FLOAT_EQ(result.X, -2.0f);
EXPECT_FLOAT_EQ(result.Y, -2.0f);
}
@@ -30,24 +30,24 @@ TEST(Subtraction, Vec2)
TEST(Subtraction, Vec3)
{
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3_2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
HMM_Vec3 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_SubtractVec3(v3_1, v3_2);
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_Subtract(v3_1, v3_2);
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;
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);
@@ -62,11 +62,11 @@ TEST(Subtraction, Vec3)
TEST(Subtraction, Vec4)
{
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v4_2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
HMM_Vec4 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_SubtractVec4(v4_1, v4_2);
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);
@@ -74,14 +74,14 @@ TEST(Subtraction, Vec4)
}
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Subtract(v4_1, v4_2);
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;
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);
@@ -96,10 +96,124 @@ TEST(Subtraction, Vec4)
#endif
}
TEST(Subtraction, Mat2)
{
HMM_Mat2 a = HMM_M2();
HMM_Mat2 b = HMM_M2();
int Counter = 1;
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
a.Elements[Column][Row] = Counter++;
}
}
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
b.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat2 result = HMM_SubM2(b,a);
EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0);
}
#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_Mat4(); // will have 1 - 16
hmm_mat4 m4_2 = HMM_Mat4(); // will have 17 - 32
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;
@@ -122,7 +236,7 @@ TEST(Subtraction, Mat4)
// Test the results
{
hmm_mat4 result = HMM_SubtractMat4(m4_1, m4_2);
HMM_Mat4 result = HMM_SubM4(m4_1, m4_2);
for (int Column = 0; Column < 4; ++Column)
{
for (int Row = 0; Row < 4; ++Row)
@@ -133,7 +247,7 @@ TEST(Subtraction, Mat4)
}
#ifdef __cplusplus
{
hmm_mat4 result = HMM_Subtract(m4_1, m4_2);
HMM_Mat4 result = HMM_Sub(m4_1, m4_2);
for (int Column = 0; Column < 4; ++Column)
{
for (int Row = 0; Row < 4; ++Row)
@@ -143,7 +257,7 @@ TEST(Subtraction, Mat4)
}
}
{
hmm_mat4 result = m4_1 - m4_2;
HMM_Mat4 result = m4_1 - m4_2;
for (int Column = 0; Column < 4; ++Column)
{
for (int Row = 0; Row < 4; ++Row)
@@ -166,11 +280,11 @@ TEST(Subtraction, Mat4)
TEST(Subtraction, Quaternion)
{
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f);
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
{
hmm_quaternion result = HMM_SubtractQuaternion(q1, q2);
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);
@@ -178,14 +292,14 @@ TEST(Subtraction, Quaternion)
}
#ifdef __cplusplus
{
hmm_quaternion result = HMM_Subtract(q1, q2);
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_quaternion result = q1 - q2;
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);
@@ -199,3 +313,32 @@ TEST(Subtraction, Quaternion)
EXPECT_FLOAT_EQ(q1.W, -4.0f);
#endif
}
#ifdef __cplusplus
TEST(UnaryMinus, Vec2)
{
HMM_Vec2 VectorOne = {1.0f, 2.0f};
HMM_Vec2 Result = -VectorOne;
EXPECT_FLOAT_EQ(Result.X, -1.0f);
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
}
TEST(UnaryMinus, Vec3)
{
HMM_Vec3 VectorOne = {1.0f, 2.0f, 3.0f};
HMM_Vec3 Result = -VectorOne;
EXPECT_FLOAT_EQ(Result.X, -1.0f);
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
EXPECT_FLOAT_EQ(Result.Z, -3.0f);
}
TEST(UnaryMinus, Vec4)
{
HMM_Vec4 VectorOne = {1.0f, 2.0f, 3.0f, 4.0f};
HMM_Vec4 Result = -VectorOne;
EXPECT_FLOAT_EQ(Result.X, -1.0f);
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
EXPECT_FLOAT_EQ(Result.Z, -3.0f);
EXPECT_FLOAT_EQ(Result.W, -4.0f);
}
#endif

View File

@@ -2,52 +2,104 @@
TEST(Transformations, Translate)
{
hmm_mat4 translate = HMM_Translate(HMM_Vec3(1.0f, -3.0f, 6.0f));
HMM_Mat4 translate = HMM_Translate(HMM_V3(1.0f, -3.0f, 6.0f));
hmm_vec3 original = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec4 translated = HMM_MultiplyMat4ByVec4(translate, HMM_Vec4v(original, 1));
HMM_Vec3 original = HMM_V3(1.0f, 2.0f, 3.0f);
HMM_Vec4 translated = HMM_MulM4V4(translate, HMM_V4V(original, 1));
EXPECT_FLOAT_EQ(translated.X, 2.0f);
EXPECT_FLOAT_EQ(translated.Y, -1.0f);
EXPECT_FLOAT_EQ(translated.Z, 9.0f);
EXPECT_FLOAT_EQ(translated.W, 1.0f);
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_Vec3(1.0f, 1.0f, 1.0f);
HMM_Vec3 original = HMM_V3(1.0f, 1.0f, 1.0f);
hmm_mat4 rotateX = HMM_Rotate(90, HMM_Vec3(1, 0, 0));
hmm_vec4 rotatedX = HMM_MultiplyMat4ByVec4(rotateX, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(rotatedX.X, 1.0f);
EXPECT_FLOAT_EQ(rotatedX.Y, -1.0f);
EXPECT_FLOAT_EQ(rotatedX.Z, 1.0f);
EXPECT_FLOAT_EQ(rotatedX.W, 1.0f);
HMM_Mat4 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(90, HMM_Vec3(0, 1, 0));
hmm_vec4 rotatedY = HMM_MultiplyMat4ByVec4(rotateY, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(rotatedY.X, 1.0f);
EXPECT_FLOAT_EQ(rotatedY.Y, 1.0f);
EXPECT_FLOAT_EQ(rotatedY.Z, -1.0f);
EXPECT_FLOAT_EQ(rotatedY.W, 1.0f);
HMM_Mat4 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(90, HMM_Vec3(0, 0, 1));
hmm_vec4 rotatedZ = HMM_MultiplyMat4ByVec4(rotateZ, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(rotatedZ.X, -1.0f);
EXPECT_FLOAT_EQ(rotatedZ.Y, 1.0f);
EXPECT_FLOAT_EQ(rotatedZ.Z, 1.0f);
EXPECT_FLOAT_EQ(rotatedZ.W, 1.0f);
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_Vec3(2.0f, -3.0f, 0.5f));
HMM_Mat4 scale = HMM_Scale(HMM_V3(2.0f, -3.0f, 0.5f));
hmm_vec3 original = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec4 scaled = HMM_MultiplyMat4ByVec4(scale, HMM_Vec4v(original, 1));
HMM_Vec3 original = HMM_V3(1.0f, 2.0f, 3.0f);
HMM_Vec4 scaled = HMM_MulM4V4(scale, HMM_V4V(original, 1));
EXPECT_FLOAT_EQ(scaled.X, 2.0f);
EXPECT_FLOAT_EQ(scaled.Y, -6.0f);
EXPECT_FLOAT_EQ(scaled.Z, 1.5f);
EXPECT_FLOAT_EQ(scaled.W, 1.0f);
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);
}
}

View File

@@ -2,60 +2,60 @@
TEST(VectorOps, LengthSquared)
{
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f);
hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f);
hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, 1.0f);
HMM_Vec2 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_LengthSquaredVec2(v2), 5.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec3(v3), 14.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec4(v4), 15.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_LengthSquared(v2), 5.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquared(v3), 14.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquared(v4), 15.0f);
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_Vec2(1.0f, -9.0f);
hmm_vec3 v3 = HMM_Vec3(2.0f, -3.0f, 6.0f);
hmm_vec4 v4 = HMM_Vec4(2.0f, -3.0f, 6.0f, 12.0f);
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_LengthVec2(v2), 9.0553856f);
EXPECT_FLOAT_EQ(HMM_LengthVec3(v3), 7.0f);
EXPECT_FLOAT_EQ(HMM_LengthVec4(v4), 13.892444f);
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_Length(v2), 9.0553856f);
EXPECT_FLOAT_EQ(HMM_Length(v3), 7.0f);
EXPECT_FLOAT_EQ(HMM_Length(v4), 13.892444f);
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_Vec2(1.0f, -2.0f);
hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f);
hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, -1.0f);
HMM_Vec2 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_NormalizeVec2(v2);
EXPECT_FLOAT_EQ(HMM_LengthVec2(result), 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_NormalizeVec3(v3);
EXPECT_FLOAT_EQ(HMM_LengthVec3(result), 1.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_NormalizeVec4(v4);
EXPECT_FLOAT_EQ(HMM_LengthVec4(result), 1.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);
@@ -64,21 +64,21 @@ TEST(VectorOps, Normalize)
#ifdef __cplusplus
{
hmm_vec2 result = HMM_Normalize(v2);
EXPECT_FLOAT_EQ(HMM_LengthVec2(result), 1.0f);
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_Normalize(v3);
EXPECT_FLOAT_EQ(HMM_LengthVec3(result), 1.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_Normalize(v4);
EXPECT_FLOAT_EQ(HMM_LengthVec4(result), 1.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);
@@ -89,23 +89,23 @@ TEST(VectorOps, Normalize)
TEST(VectorOps, NormalizeZero)
{
hmm_vec2 v2 = HMM_Vec2(0.0f, 0.0f);
hmm_vec3 v3 = HMM_Vec3(0.0f, 0.0f, 0.0f);
hmm_vec4 v4 = HMM_Vec4(0.0f, 0.0f, 0.0f, 0.0f);
HMM_Vec2 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_NormalizeVec2(v2);
HMM_Vec2 result = HMM_NormV2(v2);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
}
{
hmm_vec3 result = HMM_NormalizeVec3(v3);
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_NormalizeVec4(v4);
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);
@@ -114,18 +114,18 @@ TEST(VectorOps, NormalizeZero)
#ifdef __cplusplus
{
hmm_vec2 result = HMM_Normalize(v2);
HMM_Vec2 result = HMM_Norm(v2);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
}
{
hmm_vec3 result = HMM_Normalize(v3);
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_Normalize(v4);
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);
@@ -136,10 +136,10 @@ TEST(VectorOps, NormalizeZero)
TEST(VectorOps, Cross)
{
hmm_vec3 v1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 v2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
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);
HMM_Vec3 result = HMM_Cross(v1, v2);
EXPECT_FLOAT_EQ(result.X, -3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
@@ -148,10 +148,10 @@ TEST(VectorOps, Cross)
TEST(VectorOps, DotVec2)
{
hmm_vec2 v1 = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 v2 = HMM_Vec2(3.0f, 4.0f);
HMM_Vec2 v1 = HMM_V2(1.0f, 2.0f);
HMM_Vec2 v2 = HMM_V2(3.0f, 4.0f);
EXPECT_FLOAT_EQ(HMM_DotVec2(v1, v2), 11.0f);
EXPECT_FLOAT_EQ(HMM_DotV2(v1, v2), 11.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 11.0f);
#endif
@@ -159,10 +159,10 @@ TEST(VectorOps, DotVec2)
TEST(VectorOps, DotVec3)
{
hmm_vec3 v1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 v2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
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_DotVec3(v1, v2), 32.0f);
EXPECT_FLOAT_EQ(HMM_DotV3(v1, v2), 32.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 32.0f);
#endif
@@ -170,23 +170,85 @@ TEST(VectorOps, DotVec3)
TEST(VectorOps, DotVec4)
{
hmm_vec4 v1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
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_DotVec4(v1, v2), 70.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, Transpose)
TEST(MatrixOps, TransposeM4)
{
hmm_mat4 m4 = HMM_Mat4(); // will have 1 - 16
HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
// Fill the matrix
int Counter = 1;
@@ -200,7 +262,7 @@ TEST(MatrixOps, Transpose)
}
// Test the matrix
hmm_mat4 result = HMM_Transpose(m4);
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);

View File

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

View File

@@ -1,11 +1,15 @@
#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"

18
test/run_test_clang.bat Normal file
View 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
View 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
View 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
View 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
View 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
View 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