mirror of
https://github.com/HandmadeMath/HandmadeMath.git
synced 2025-12-28 15:44:33 +00:00
Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
142ba3cd9d | ||
|
|
8c2ac269ba | ||
|
|
736ebaaf23 | ||
|
|
bdc7dd2a51 | ||
|
|
b4ce44823b | ||
|
|
2901e70ca3 | ||
|
|
21b4a0d209 | ||
|
|
43836aa3a6 | ||
|
|
bdc04881de | ||
|
|
322826bcee | ||
|
|
4e1e97522d | ||
|
|
6603c796cc | ||
|
|
623215b228 | ||
|
|
fcc510f767 | ||
|
|
133a595b6f | ||
|
|
5f20d693c9 | ||
|
|
e210d8729b | ||
|
|
a1c84320f9 | ||
|
|
8df5da57f5 | ||
|
|
149c18d449 | ||
|
|
98748f702c | ||
|
|
6cf6226c57 | ||
|
|
aaa767bf0b | ||
|
|
422bc588e9 | ||
|
|
beb837a3c6 | ||
|
|
50ab55b3bc | ||
|
|
22d743ce3d | ||
|
|
d4918a514e | ||
|
|
37aa3fa6a0 | ||
|
|
7e493a5481 | ||
|
|
f106a0f5f3 | ||
|
|
c24e4ff873 | ||
|
|
ba5405ac0f | ||
|
|
d69a859d73 | ||
|
|
8c18186b3b | ||
|
|
5f816bf9b3 | ||
|
|
c5bc802042 | ||
|
|
43afc87fa7 | ||
|
|
5bbac2167e | ||
|
|
655c662528 | ||
|
|
1f0c6ba493 | ||
|
|
1d82b4f0bc | ||
|
|
2fa0b36715 | ||
|
|
ad169e649c | ||
|
|
1900cc9275 | ||
|
|
ddb9971e71 | ||
|
|
341a376a17 | ||
|
|
c825fe48cf | ||
|
|
15bef820db | ||
|
|
fe32f081f2 | ||
|
|
785f19d4a7 | ||
|
|
a9b08b9147 | ||
|
|
f376f2a2a7 | ||
|
|
78e6feea82 | ||
|
|
21aa828a08 | ||
|
|
93e56be543 | ||
|
|
45c91702a9 | ||
|
|
f7c8e1f7d1 | ||
|
|
5ca1d58b36 | ||
|
|
5bf727dbd5 | ||
|
|
295f6c476f | ||
|
|
e095aefaf7 | ||
|
|
4e2f47db55 | ||
|
|
bee0e0c569 | ||
|
|
f8b3a84cec | ||
|
|
77914405c3 | ||
|
|
eb5c659148 | ||
|
|
52fd5cceb4 | ||
|
|
8e67482295 | ||
|
|
c508ce342b | ||
|
|
250c38e845 | ||
|
|
4981d5ab89 | ||
|
|
5f173e0176 | ||
|
|
575fcb767d | ||
|
|
a08262b2d9 | ||
|
|
53bc939d8e | ||
|
|
7eb4ae1846 | ||
|
|
48bd24b05e | ||
|
|
064baeb5b9 | ||
|
|
afd726ab0b | ||
|
|
98fffbd7cc | ||
|
|
efd9f2f4b7 | ||
|
|
c8ada18370 | ||
|
|
70ac2b7e5b | ||
|
|
924ee43923 | ||
|
|
440b885d59 | ||
|
|
98f535aeec | ||
|
|
09524f72ed | ||
|
|
be30046a5a | ||
|
|
ff4513ff33 | ||
|
|
364569abe9 | ||
|
|
a9972e71da |
34
.github/workflows/ci.yml
vendored
Normal file
34
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "master" ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Test on ${{ matrix.os }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: TheMrMilchmann/setup-msvc-dev@v2
|
||||||
|
with:
|
||||||
|
arch: x64
|
||||||
|
if: matrix.os == 'windows-latest'
|
||||||
|
- name: Test (Windows, MSVC)
|
||||||
|
run: ./run_test_msvc.bat
|
||||||
|
working-directory: ./test
|
||||||
|
if: matrix.os == 'windows-latest'
|
||||||
|
- name: Test (Windows, clang)
|
||||||
|
run: ./run_test_clang.bat
|
||||||
|
working-directory: ./test
|
||||||
|
if: matrix.os == 'windows-latest'
|
||||||
|
- name: Test (${{ matrix.os }})
|
||||||
|
run: make all
|
||||||
|
working-directory: ./test
|
||||||
|
if: matrix.os != 'windows-latest'
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -31,5 +31,4 @@
|
|||||||
*.exe
|
*.exe
|
||||||
*.out
|
*.out
|
||||||
*.app
|
*.app
|
||||||
hmm_test
|
test/build
|
||||||
hmm_test*
|
|
||||||
|
|||||||
0
.gitmodules
vendored
0
.gitmodules
vendored
10
.travis.yml
10
.travis.yml
@@ -1,10 +0,0 @@
|
|||||||
language: cpp
|
|
||||||
compiler:
|
|
||||||
- clang
|
|
||||||
- gcc
|
|
||||||
install:
|
|
||||||
- cd test
|
|
||||||
- make
|
|
||||||
script:
|
|
||||||
- ./hmm_test_c
|
|
||||||
- ./hmm_test_cpp
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
# 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 macros and return types on a separate line from the function definition:
|
|
||||||
```cpp
|
|
||||||
HINLINE float
|
|
||||||
HMM_MyFunction()
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
* Explicitly initialize variables to zero:
|
|
||||||
```cpp
|
|
||||||
HINLINE float
|
|
||||||
HMM_MyFunction()
|
|
||||||
{
|
|
||||||
float MyFloat = 0.0f;
|
|
||||||
hmm_vec3 MyVector = {0};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
* Put parentheses around the returned value:
|
|
||||||
```cpp
|
|
||||||
HINLINE float
|
|
||||||
HMM_MyFunction()
|
|
||||||
{
|
|
||||||
return (1.0f);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
# Other 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!
|
|
||||||
|
|
||||||
4695
HandmadeMath.h
4695
HandmadeMath.h
File diff suppressed because it is too large
Load Diff
116
LICENSE
Normal file
116
LICENSE
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
CC0 1.0 Universal
|
||||||
|
|
||||||
|
Statement of Purpose
|
||||||
|
|
||||||
|
The laws of most jurisdictions throughout the world automatically confer
|
||||||
|
exclusive Copyright and Related Rights (defined below) upon the creator and
|
||||||
|
subsequent owner(s) (each and all, an "owner") of an original work of
|
||||||
|
authorship and/or a database (each, a "Work").
|
||||||
|
|
||||||
|
Certain owners wish to permanently relinquish those rights to a Work for the
|
||||||
|
purpose of contributing to a commons of creative, cultural and scientific
|
||||||
|
works ("Commons") that the public can reliably and without fear of later
|
||||||
|
claims of infringement build upon, modify, incorporate in other works, reuse
|
||||||
|
and redistribute as freely as possible in any form whatsoever and for any
|
||||||
|
purposes, including without limitation commercial purposes. These owners may
|
||||||
|
contribute to the Commons to promote the ideal of a free culture and the
|
||||||
|
further production of creative, cultural and scientific works, or to gain
|
||||||
|
reputation or greater distribution for their Work in part through the use and
|
||||||
|
efforts of others.
|
||||||
|
|
||||||
|
For these and/or other purposes and motivations, and without any expectation
|
||||||
|
of additional consideration or compensation, the person associating CC0 with a
|
||||||
|
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
|
||||||
|
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
|
||||||
|
and publicly distribute the Work under its terms, with knowledge of his or her
|
||||||
|
Copyright and Related Rights in the Work and the meaning and intended legal
|
||||||
|
effect of CC0 on those rights.
|
||||||
|
|
||||||
|
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||||
|
protected by copyright and related or neighboring rights ("Copyright and
|
||||||
|
Related Rights"). Copyright and Related Rights include, but are not limited
|
||||||
|
to, the following:
|
||||||
|
|
||||||
|
i. the right to reproduce, adapt, distribute, perform, display, communicate,
|
||||||
|
and translate a Work;
|
||||||
|
|
||||||
|
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||||
|
|
||||||
|
iii. publicity and privacy rights pertaining to a person's image or likeness
|
||||||
|
depicted in a Work;
|
||||||
|
|
||||||
|
iv. rights protecting against unfair competition in regards to a Work,
|
||||||
|
subject to the limitations in paragraph 4(a), below;
|
||||||
|
|
||||||
|
v. rights protecting the extraction, dissemination, use and reuse of data in
|
||||||
|
a Work;
|
||||||
|
|
||||||
|
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||||
|
European Parliament and of the Council of 11 March 1996 on the legal
|
||||||
|
protection of databases, and under any national implementation thereof,
|
||||||
|
including any amended or successor version of such directive); and
|
||||||
|
|
||||||
|
vii. other similar, equivalent or corresponding rights throughout the world
|
||||||
|
based on applicable law or treaty, and any national implementations thereof.
|
||||||
|
|
||||||
|
2. Waiver. To the greatest extent permitted by, but not in contravention of,
|
||||||
|
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
|
||||||
|
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
|
||||||
|
and Related Rights and associated claims and causes of action, whether now
|
||||||
|
known or unknown (including existing as well as future claims and causes of
|
||||||
|
action), in the Work (i) in all territories worldwide, (ii) for the maximum
|
||||||
|
duration provided by applicable law or treaty (including future time
|
||||||
|
extensions), (iii) in any current or future medium and for any number of
|
||||||
|
copies, and (iv) for any purpose whatsoever, including without limitation
|
||||||
|
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
|
||||||
|
the Waiver for the benefit of each member of the public at large and to the
|
||||||
|
detriment of Affirmer's heirs and successors, fully intending that such Waiver
|
||||||
|
shall not be subject to revocation, rescission, cancellation, termination, or
|
||||||
|
any other legal or equitable action to disrupt the quiet enjoyment of the Work
|
||||||
|
by the public as contemplated by Affirmer's express Statement of Purpose.
|
||||||
|
|
||||||
|
3. Public License Fallback. Should any part of the Waiver for any reason be
|
||||||
|
judged legally invalid or ineffective under applicable law, then the Waiver
|
||||||
|
shall be preserved to the maximum extent permitted taking into account
|
||||||
|
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
|
||||||
|
is so judged Affirmer hereby grants to each affected person a royalty-free,
|
||||||
|
non transferable, non sublicensable, non exclusive, irrevocable and
|
||||||
|
unconditional license to exercise Affirmer's Copyright and Related Rights in
|
||||||
|
the Work (i) in all territories worldwide, (ii) for the maximum duration
|
||||||
|
provided by applicable law or treaty (including future time extensions), (iii)
|
||||||
|
in any current or future medium and for any number of copies, and (iv) for any
|
||||||
|
purpose whatsoever, including without limitation commercial, advertising or
|
||||||
|
promotional purposes (the "License"). The License shall be deemed effective as
|
||||||
|
of the date CC0 was applied by Affirmer to the Work. Should any part of the
|
||||||
|
License for any reason be judged legally invalid or ineffective under
|
||||||
|
applicable law, such partial invalidity or ineffectiveness shall not
|
||||||
|
invalidate the remainder of the License, and in such case Affirmer hereby
|
||||||
|
affirms that he or she will not (i) exercise any of his or her remaining
|
||||||
|
Copyright and Related Rights in the Work or (ii) assert any associated claims
|
||||||
|
and causes of action with respect to the Work, in either case contrary to
|
||||||
|
Affirmer's express Statement of Purpose.
|
||||||
|
|
||||||
|
4. Limitations and Disclaimers.
|
||||||
|
|
||||||
|
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||||
|
surrendered, licensed or otherwise affected by this document.
|
||||||
|
|
||||||
|
b. Affirmer offers the Work as-is and makes no representations or warranties
|
||||||
|
of any kind concerning the Work, express, implied, statutory or otherwise,
|
||||||
|
including without limitation warranties of title, merchantability, fitness
|
||||||
|
for a particular purpose, non infringement, or the absence of latent or
|
||||||
|
other defects, accuracy, or the present or absence of errors, whether or not
|
||||||
|
discoverable, all to the greatest extent permissible under applicable law.
|
||||||
|
|
||||||
|
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||||
|
that may apply to the Work or any use thereof, including without limitation
|
||||||
|
any person's Copyright and Related Rights in the Work. Further, Affirmer
|
||||||
|
disclaims responsibility for obtaining any necessary consents, permissions
|
||||||
|
or other rights required for any use of the Work.
|
||||||
|
|
||||||
|
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||||
|
party to this document and has no duty or obligation with respect to this
|
||||||
|
CC0 or use of the Work.
|
||||||
|
|
||||||
|
For more information, please see
|
||||||
|
<http://creativecommons.org/publicdomain/zero/1.0/>
|
||||||
54
README.md
54
README.md
@@ -1,43 +1,43 @@
|
|||||||
# Handmade-Math
|
# Handmade Math
|
||||||
------
|
|
||||||
|
|
||||||
[](https://travis-ci.org/StrangeZak/Handmade-Math)
|
A single-file, cross-platform, public domain graphics math library for both C and C++. Supports vectors, matrices, quaternions, and all the utilities you'd expect.
|
||||||
|
|
||||||
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).
|
||||||
|
|
||||||
_This library is free and will stay free, but if you would like to support development, or you are a company using HandmadeMath, please consider financial support._
|
> If you are upgrading to Handmade Math 2.0, save yourself some time and use our [automatic update tool](./update).
|
||||||
|
|
||||||
[](http://www.patreon.com/strangezak) [](https://www.paypal.me/zakarystrange)
|
Here's what sets Handmade Math apart:
|
||||||
|
|
||||||
|
- **A simple single-header library.** Just `#include "HandmadeMath.h"`.
|
||||||
|
- **Supports both C and C++.** While libraries like GLM only support C++, Handmade Math supports both C and C++, with convenient overloads wherever possible. For example, C++ codebases get operator overloading, and C11 codebases get `_Generic` versions of common operations.
|
||||||
|
- **Supports all graphics APIs.** Handmade Math has left- and right-handed versions of each operation, as well as support for zero-to-one and negative-one-to-one NDC conventions.
|
||||||
|
- **Swizzling, sort of.** Handmade Math's vector types use unions to provide several ways of accessing the same underlying data. For example, the components of an `HMM_Vec3` can be accessed as `XYZ`, `RGB`, or `UVW` - or subsets can be accessed like `.XY` and `.YZ`.
|
||||||
|
- **Your choice of angle unit.** While Handmade Math uses radians by default, you can configure it to use degrees or [turns](https://www.computerenhance.com/p/turns-are-better-than-radians) instead.
|
||||||
|
|
||||||
|
|
||||||
Version | Changes |
|
## Usage
|
||||||
----------------|----------------|
|
|
||||||
**1.1.3** | Fixed compile error in C mode
|
Simply `#include "HandmadeMath.h"`. All functions are `static inline`, so there is no need for an "implementation" file as with some other single-header libraries.
|
||||||
**1.1.2** | Fixed invalid HMMDEF's in the function definitions
|
|
||||||
**1.1.1** | Resolved compiler warnings on gcc and g++
|
A few config options are available. See the header comment in [the source](./HandmadeMath.h) for details.
|
||||||
**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 |
|
|
||||||
|
|
||||||
-----
|
|
||||||
_This library is free and will stay free, but if you would like to support development, or you are a company using HandmadeMath, please consider financial support._
|
|
||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
|
**What conventions does HMM use, e.g. row vs. column major, handedness, etc.?**
|
||||||
|
|
||||||
|
Handmade Math's matrices are column-major, i.e. data is stored by columns, then rows. It also assumes column vectors, i.e. vectors are written vertically and matrix-vector multiplication is `M * V` instead of `V * M`. For more information, see [this issue](https://github.com/HandmadeMath/HandmadeMath/issues/124#issuecomment-775737253).
|
||||||
|
|
||||||
|
For other properties, we provide variants for each common convention. Functions that care about handedness have left-handed (`LH`) and right-handed (`RH`) variants. Projection functions have zero-to-one (`ZO`) and negative-one-to-one (`NO`) variants for different NDC conventions.
|
||||||
|
|
||||||
|
**What if I don't want the `HMM_` prefix?**
|
||||||
|
|
||||||
|
Do a find and replace in the library source.
|
||||||
|
|
||||||
**What's the license?**
|
**What's the license?**
|
||||||
|
|
||||||
This library is in the public domain. You can do whatever you want with it.
|
This library is in the public domain. You can do whatever you want with it.
|
||||||
|
|
||||||
**Where can I contact you to ask questions?**
|
**Where can I contact you to ask questions?**
|
||||||
|
|
||||||
You can email me at: Zak@Handmade.Network
|
Feel free to make GitHub issues for any questions, concerns, or problems you encounter.
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
|
#ifndef WITHOUT_COVERAGE
|
||||||
|
#include "HandmadeTest.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define HANDMADE_MATH_IMPLEMENTATION
|
|
||||||
#define HANDMADE_MATH_NO_INLINE
|
|
||||||
#include "../HandmadeMath.h"
|
#include "../HandmadeMath.h"
|
||||||
|
|||||||
@@ -1,5 +1,2 @@
|
|||||||
|
#include "HandmadeMath.c"
|
||||||
#define HANDMADE_MATH_IMPLEMENTATION
|
// C++ compilers complain when compiling a .c file...
|
||||||
#define HANDMADE_MATH_CPP_MODE
|
|
||||||
#define HANDMADE_MATH_NO_INLINE
|
|
||||||
#include "../HandmadeMath.h"
|
|
||||||
|
|||||||
@@ -1,80 +1,455 @@
|
|||||||
|
/*
|
||||||
|
HandmadeTest.h
|
||||||
|
|
||||||
|
This is Handmade Math's test framework. It is fully compatible with both C
|
||||||
|
and C++, although it requires some compiler-specific features.
|
||||||
|
|
||||||
|
To use Handmade Test, you must #define HANDMADE_TEST_IMPLEMENTATION in
|
||||||
|
exactly one C or C++ file that includes the header, like this:
|
||||||
|
|
||||||
|
#define HANDMADE_TEST_IMPLEMENTATION
|
||||||
|
#include "HandmadeTest.h"
|
||||||
|
|
||||||
|
The basic way of creating a test is using the TEST macro, which registers a
|
||||||
|
single test to be run:
|
||||||
|
|
||||||
|
TEST(MyCategory, MyTestName) {
|
||||||
|
// test code, including asserts/expects
|
||||||
|
}
|
||||||
|
|
||||||
|
Handmade Test also provides macros you can use to check the coverage of
|
||||||
|
important parts of your code. Define a coverage case by using the COVERAGE
|
||||||
|
macro outside the function you wish to test, providing both a name and the
|
||||||
|
number of asserts you expect to see covered over the course of your test.
|
||||||
|
Then use the ASSERT_COVERED macro in every part of the function you wish to
|
||||||
|
check coverage on. For example:
|
||||||
|
|
||||||
|
COVERAGE(MyCoverageCase, 3)
|
||||||
|
void MyFunction(int a, int b) {
|
||||||
|
if (a > b) {
|
||||||
|
ASSERT_COVERED(MyCoverageCase);
|
||||||
|
return 10;
|
||||||
|
} else if (a < b) {
|
||||||
|
ASSERT_COVERED(MyCoverageCase);
|
||||||
|
return -10;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_COVERED(MyCoverageCase);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
The main function of your test code should then call hmt_run_all_tests (and
|
||||||
|
optionally hmt_check_all_coverage) and return the result:
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return hmt_run_all_tests() || hmt_check_all_coverage();
|
||||||
|
}
|
||||||
|
|
||||||
|
=============================================================================
|
||||||
|
|
||||||
|
If Handmade Test's macros are conflicting with existing macros in your
|
||||||
|
project, you may define HMT_SAFE_MACROS before you include HandmadeTest.h.
|
||||||
|
You may then prefix each macro with HMT_. For example, you may use HMT_TEST
|
||||||
|
instead of TEST and HMT_EXPECT_TRUE instead of EXPECT_TRUE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef HANDMADETEST_H
|
#ifndef HANDMADETEST_H
|
||||||
#define HANDMADETEST_H
|
#define HANDMADETEST_H
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
int hmt_count_tests = 0;
|
#include "initializer.h"
|
||||||
int hmt_count_failedtests = 0;
|
|
||||||
int hmt_count_failures = 0;
|
|
||||||
|
|
||||||
#define RESET "\033[0m"
|
#define HMT_RESET "\033[0m"
|
||||||
#define RED "\033[31m"
|
#define HMT_RED "\033[31m"
|
||||||
#define GREEN "\033[32m"
|
#define HMT_GREEN "\033[32m"
|
||||||
|
|
||||||
#define CATEGORY_BEGIN(name) { \
|
#define HMT_ARRAY_SIZE 1024
|
||||||
int count_categorytests = 0; \
|
|
||||||
int count_categoryfailedtests = 0; \
|
|
||||||
int count_categoryfailures = 0; \
|
|
||||||
printf("\n" #name ":\n");
|
|
||||||
#define CATEGORY_END(name) \
|
|
||||||
hmt_count_tests += count_categorytests; \
|
|
||||||
hmt_count_failedtests += count_categoryfailedtests; \
|
|
||||||
hmt_count_failures += count_categoryfailures; \
|
|
||||||
printf("%d/%d tests passed, %d failures\n", count_categorytests - count_categoryfailedtests, count_categorytests, count_categoryfailures); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define TEST_BEGIN(name) { \
|
typedef struct hmt_testresult_struct {
|
||||||
int count_testfailures = 0; \
|
int count_cases;
|
||||||
count_categorytests++; \
|
int count_failures;
|
||||||
printf(" " #name ":");
|
} hmt_testresult;
|
||||||
#define TEST_END() \
|
|
||||||
count_categoryfailures += count_testfailures; \
|
|
||||||
if (count_testfailures > 0) { \
|
|
||||||
count_categoryfailedtests++; \
|
|
||||||
printf("\n"); \
|
|
||||||
} else { \
|
|
||||||
printf(GREEN " [PASS]\n" RESET); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CASE_FAIL() \
|
typedef void (*hmt_test_func)(hmt_testresult*);
|
||||||
count_testfailures++; \
|
|
||||||
printf("\n - " RED "[FAIL] (%d) " RESET, __LINE__)
|
typedef struct hmt_test_struct {
|
||||||
|
const char* name;
|
||||||
|
hmt_test_func func;
|
||||||
|
} hmt_test;
|
||||||
|
|
||||||
|
typedef struct hmt_category_struct {
|
||||||
|
const char* name;
|
||||||
|
int num_tests;
|
||||||
|
hmt_test* tests;
|
||||||
|
} hmt_category;
|
||||||
|
|
||||||
|
typedef struct hmt_covercase_struct {
|
||||||
|
const char* name;
|
||||||
|
int expected_asserts;
|
||||||
|
int actual_asserts;
|
||||||
|
int* asserted_lines;
|
||||||
|
} hmt_covercase;
|
||||||
|
|
||||||
|
hmt_category _hmt_new_category(const char* name);
|
||||||
|
hmt_test _hmt_new_test(const char* name, hmt_test_func func);
|
||||||
|
hmt_covercase _hmt_new_covercase(const char* name, int expected);
|
||||||
|
void _hmt_register_test(const char* category, const char* name, hmt_test_func func);
|
||||||
|
void _hmt_register_covercase(const char* name, const char* expected_asserts);
|
||||||
|
void _hmt_count_cover(const char* name, int line);
|
||||||
|
|
||||||
|
#define _HMT_TEST_FUNCNAME(category, name) _hmt_test_ ## category ## _ ## name
|
||||||
|
#define _HMT_TEST_FUNCNAME_INIT(category, name) _hmt_test_ ## category ## _ ## name ## _init
|
||||||
|
#define _HMT_COVERCASE_FUNCNAME_INIT(name) _hmt_covercase_ ## name ## _init
|
||||||
|
|
||||||
|
#define HMT_TEST(category, name) \
|
||||||
|
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result); \
|
||||||
|
INITIALIZER(_HMT_TEST_FUNCNAME_INIT(category, name)) { \
|
||||||
|
_hmt_register_test(#category, #name, _HMT_TEST_FUNCNAME(category, name)); \
|
||||||
|
} \
|
||||||
|
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result)
|
||||||
|
|
||||||
|
#define _HMT_CASE_START() \
|
||||||
|
_result->count_cases++;
|
||||||
|
|
||||||
|
#define _HMT_CASE_FAIL() \
|
||||||
|
_result->count_failures++; \
|
||||||
|
printf("\n - " HMT_RED "[FAIL] (line %d) " HMT_RESET, __LINE__);
|
||||||
|
|
||||||
|
#define HMT_COVERAGE(name, num_asserts) \
|
||||||
|
INITIALIZER(_HMT_COVERCASE_FUNCNAME_INIT(name)) { \
|
||||||
|
_hmt_register_covercase(#name, #num_asserts); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define HMT_ASSERT_COVERED(name) \
|
||||||
|
{ \
|
||||||
|
_hmt_count_cover(#name, __LINE__); \
|
||||||
|
} \
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Asserts and expects
|
* Asserts and expects
|
||||||
*/
|
*/
|
||||||
#define EXPECT_FLOAT_EQ(_actual, _expected) do { \
|
#define HMT_EXPECT_TRUE(_actual) { \
|
||||||
|
_HMT_CASE_START(); \
|
||||||
|
if (!(_actual)) { \
|
||||||
|
_HMT_CASE_FAIL(); \
|
||||||
|
printf("Expected true but got something false"); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define HMT_EXPECT_FALSE(_actual) { \
|
||||||
|
_HMT_CASE_START(); \
|
||||||
|
if (_actual) { \
|
||||||
|
_HMT_CASE_FAIL(); \
|
||||||
|
printf("Expected false but got something true"); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define HMT_EXPECT_FLOAT_EQ_MSG(_actual, _expected, _msg) { \
|
||||||
|
_HMT_CASE_START(); \
|
||||||
float actual = (_actual); \
|
float actual = (_actual); \
|
||||||
float diff = actual - (_expected); \
|
float diff = actual - (_expected); \
|
||||||
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
|
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
|
||||||
CASE_FAIL(); \
|
_HMT_CASE_FAIL(); \
|
||||||
printf("Expected %f, got %f", (_expected), actual); \
|
if ((_msg)[0] == 0) { \
|
||||||
|
printf("Expected %f, got %f (error: %.9g)", (_expected), actual, diff); \
|
||||||
|
} else { \
|
||||||
|
printf("%s: Expected %f, got %f (error: %.9g)", (_msg), (_expected), actual, diff); \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
}
|
||||||
|
#define HMT_EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ_MSG(_actual, _expected, "");
|
||||||
|
|
||||||
#define EXPECT_NEAR(_actual, _expected, _epsilon) do { \
|
#define HMT_EXPECT_NEAR_MSG(_actual, _expected, _epsilon, _msg) { \
|
||||||
|
_HMT_CASE_START(); \
|
||||||
float actual = (_actual); \
|
float actual = (_actual); \
|
||||||
float diff = actual - (_expected); \
|
float diff = actual - (_expected); \
|
||||||
if (diff < -(_epsilon) || (_epsilon) < diff) { \
|
if (diff < -(_epsilon) || (_epsilon) < diff) { \
|
||||||
CASE_FAIL(); \
|
_HMT_CASE_FAIL(); \
|
||||||
printf("Expected %f, got %f", (_expected), actual); \
|
if ((_msg)[0] == 0) { \
|
||||||
|
printf("Expected %f, got %f", (_expected), actual); \
|
||||||
|
} else { \
|
||||||
|
printf("%s: Expected %f, got %f", (_msg), (_expected), actual); \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
}
|
||||||
|
#define HMT_EXPECT_NEAR(_actual, _expected, _epsilon) HMT_EXPECT_NEAR_MSG(_actual, _expected, _epsilon, "");
|
||||||
|
|
||||||
#define EXPECT_LT(_actual, _expected) do { \
|
#define HMT_EXPECT_LT(_actual, _expected) { \
|
||||||
|
_HMT_CASE_START(); \
|
||||||
if ((_actual) >= (_expected)) { \
|
if ((_actual) >= (_expected)) { \
|
||||||
CASE_FAIL(); \
|
_HMT_CASE_FAIL(); \
|
||||||
printf("Expected %f to be less than %f", (_actual), (_expected)); \
|
printf("Expected %f to be less than %f", (_actual), (_expected)); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} \
|
||||||
|
|
||||||
#define EXPECT_GT(_actual, _expected) do { \
|
#define HMT_EXPECT_GT(_actual, _expected) { \
|
||||||
|
_HMT_CASE_START(); \
|
||||||
if ((_actual) <= (_expected)) { \
|
if ((_actual) <= (_expected)) { \
|
||||||
CASE_FAIL(); \
|
_HMT_CASE_FAIL(); \
|
||||||
printf("Expected %f to be greater than %f", (_actual), (_expected)); \
|
printf("Expected %f to be greater than %f", (_actual), (_expected)); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} \
|
||||||
|
|
||||||
#endif
|
#ifndef HMT_SAFE_MACROS
|
||||||
|
// Friendly defines
|
||||||
|
#define TEST(category, name) HMT_TEST(category, name)
|
||||||
|
#define COVERAGE(name, expected_asserts) HMT_COVERAGE(name, expected_asserts)
|
||||||
|
#define ASSERT_COVERED(name) HMT_ASSERT_COVERED(name)
|
||||||
|
#define EXPECT_TRUE(_actual) HMT_EXPECT_TRUE(_actual)
|
||||||
|
#define EXPECT_FALSE(_actual) HMT_EXPECT_FALSE(_actual)
|
||||||
|
#define EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ(_actual, _expected)
|
||||||
|
#define EXPECT_V4_EQ(_actual, _expected) \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.X, _expected.X, "incorrect X"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Y, _expected.Y, "incorrect Y"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Z, _expected.Z, "incorrect Z"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.W, _expected.W, "incorrect W");
|
||||||
|
#define EXPECT_M4_EQ(_actual, _expected) \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[0][0], _expected.Elements[0][0], "incorrect [0][0]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[0][1], _expected.Elements[0][1], "incorrect [0][1]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[0][2], _expected.Elements[0][2], "incorrect [0][2]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[0][3], _expected.Elements[0][3], "incorrect [0][3]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[1][0], _expected.Elements[1][0], "incorrect [1][0]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[1][1], _expected.Elements[1][1], "incorrect [1][1]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[1][2], _expected.Elements[1][2], "incorrect [1][2]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[1][3], _expected.Elements[1][3], "incorrect [1][3]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[2][0], _expected.Elements[2][0], "incorrect [2][0]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[2][1], _expected.Elements[2][1], "incorrect [2][1]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[2][2], _expected.Elements[2][2], "incorrect [2][2]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[2][3], _expected.Elements[2][3], "incorrect [2][3]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[3][0], _expected.Elements[3][0], "incorrect [3][0]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[3][1], _expected.Elements[3][1], "incorrect [3][1]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[3][2], _expected.Elements[3][2], "incorrect [3][2]"); \
|
||||||
|
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[3][3], _expected.Elements[3][3], "incorrect [3][3]");
|
||||||
|
#define EXPECT_NEAR(_actual, _expected, _epsilon) HMT_EXPECT_NEAR(_actual, _expected, _epsilon)
|
||||||
|
#define EXPECT_M4_NEAR(_actual, _expected, _epsilon) \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[0][0], _expected.Elements[0][0], _epsilon, "incorrect [0][0]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[0][1], _expected.Elements[0][1], _epsilon, "incorrect [0][1]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[0][2], _expected.Elements[0][2], _epsilon, "incorrect [0][2]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[0][3], _expected.Elements[0][3], _epsilon, "incorrect [0][3]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[1][0], _expected.Elements[1][0], _epsilon, "incorrect [1][0]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[1][1], _expected.Elements[1][1], _epsilon, "incorrect [1][1]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[1][2], _expected.Elements[1][2], _epsilon, "incorrect [1][2]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[1][3], _expected.Elements[1][3], _epsilon, "incorrect [1][3]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[2][0], _expected.Elements[2][0], _epsilon, "incorrect [2][0]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[2][1], _expected.Elements[2][1], _epsilon, "incorrect [2][1]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[2][2], _expected.Elements[2][2], _epsilon, "incorrect [2][2]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[2][3], _expected.Elements[2][3], _epsilon, "incorrect [2][3]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[3][0], _expected.Elements[3][0], _epsilon, "incorrect [3][0]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[3][1], _expected.Elements[3][1], _epsilon, "incorrect [3][1]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[3][2], _expected.Elements[3][2], _epsilon, "incorrect [3][2]"); \
|
||||||
|
HMT_EXPECT_NEAR_MSG(_actual.Elements[3][3], _expected.Elements[3][3], _epsilon, "incorrect [3][3]");
|
||||||
|
#define EXPECT_LT(_actual, _expected) HMT_EXPECT_LT(_actual, _expected)
|
||||||
|
#define EXPECT_GT(_actual, _expected) HMT_EXPECT_GT(_actual, _expected)
|
||||||
|
#endif // HMT_SAFE_MACROS
|
||||||
|
|
||||||
|
#endif // HANDMADETEST_H
|
||||||
|
|
||||||
|
#ifdef HANDMADE_TEST_IMPLEMENTATION
|
||||||
|
|
||||||
|
#ifndef HANDMADE_TEST_IMPLEMENTATION_GUARD
|
||||||
|
#define HANDMADE_TEST_IMPLEMENTATION_GUARD
|
||||||
|
|
||||||
|
int _hmt_num_categories = 0;
|
||||||
|
hmt_category* _hmt_categories = 0;
|
||||||
|
|
||||||
|
int _hmt_num_covercases = 0;
|
||||||
|
hmt_covercase* _hmt_covercases = 0;
|
||||||
|
|
||||||
|
int _hmt_num_covererrors = 0;
|
||||||
|
|
||||||
|
hmt_category _hmt_new_category(const char* name) {
|
||||||
|
hmt_category cat = {
|
||||||
|
name, // name
|
||||||
|
0, // num_tests
|
||||||
|
(hmt_test*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_test)), // tests
|
||||||
|
};
|
||||||
|
|
||||||
|
return cat;
|
||||||
|
}
|
||||||
|
|
||||||
|
hmt_test _hmt_new_test(const char* name, hmt_test_func func) {
|
||||||
|
hmt_test test = {
|
||||||
|
name, // name
|
||||||
|
func, // func
|
||||||
|
};
|
||||||
|
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
|
hmt_covercase _hmt_new_covercase(const char* name, int expected) {
|
||||||
|
hmt_covercase covercase = {
|
||||||
|
name, // name
|
||||||
|
expected, // expected_asserts
|
||||||
|
0, // actual_asserts
|
||||||
|
(int*) malloc(HMT_ARRAY_SIZE * sizeof(int)), // asserted_lines
|
||||||
|
};
|
||||||
|
|
||||||
|
return covercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _hmt_register_test(const char* category, const char* name, hmt_test_func func) {
|
||||||
|
// initialize categories array if not initialized
|
||||||
|
if (!_hmt_categories) {
|
||||||
|
_hmt_categories = (hmt_category*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_category));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the matching category, if possible
|
||||||
|
int cat_index;
|
||||||
|
for (cat_index = 0; cat_index < _hmt_num_categories; cat_index++) {
|
||||||
|
if (strcmp(_hmt_categories[cat_index].name, category) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new category if necessary
|
||||||
|
if (cat_index >= _hmt_num_categories) {
|
||||||
|
_hmt_categories[cat_index] = _hmt_new_category(category);
|
||||||
|
_hmt_num_categories++;
|
||||||
|
}
|
||||||
|
|
||||||
|
hmt_category* cat = &_hmt_categories[cat_index];
|
||||||
|
|
||||||
|
// Add the test to the category
|
||||||
|
cat->tests[cat->num_tests] = _hmt_new_test(name, func);
|
||||||
|
cat->num_tests++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _hmt_register_covercase(const char* name, const char* expected_asserts) {
|
||||||
|
// initialize cases array if not initialized
|
||||||
|
if (!_hmt_covercases) {
|
||||||
|
_hmt_covercases = (hmt_covercase*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_covercase));
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for existing case with that name, because the macro can run multiple
|
||||||
|
// times in different translation units
|
||||||
|
for (int i = 0; i < _hmt_num_covercases; i++) {
|
||||||
|
if (strcmp(_hmt_covercases[i].name, name) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_hmt_covercases[_hmt_num_covercases] = _hmt_new_covercase(name, atoi(expected_asserts));
|
||||||
|
_hmt_num_covercases++;
|
||||||
|
}
|
||||||
|
|
||||||
|
hmt_covercase* _hmt_find_covercase(const char* name) {
|
||||||
|
for (int i = 0; i < _hmt_num_covercases; i++) {
|
||||||
|
if (strcmp(_hmt_covercases[i].name, name) == 0) {
|
||||||
|
return &_hmt_covercases[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _hmt_count_cover(const char* name, int line) {
|
||||||
|
hmt_covercase* covercase = _hmt_find_covercase(name);
|
||||||
|
if (covercase == 0) {
|
||||||
|
printf(HMT_RED "ERROR (line %d): Could not find coverage case with name \"%s\".\n" HMT_RESET, line, name);
|
||||||
|
_hmt_num_covererrors++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if this line has already been covered
|
||||||
|
for (int i = 0; i < covercase->actual_asserts; i++) {
|
||||||
|
if (covercase->asserted_lines[i] == line) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
covercase->asserted_lines[covercase->actual_asserts] = line;
|
||||||
|
covercase->actual_asserts++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hmt_run_all_tests() {
|
||||||
|
int count_alltests = 0;
|
||||||
|
int count_allfailedtests = 0; // failed test cases
|
||||||
|
int count_allfailures = 0; // failed asserts
|
||||||
|
|
||||||
|
for (int i = 0; i < _hmt_num_categories; i++) {
|
||||||
|
hmt_category cat = _hmt_categories[i];
|
||||||
|
int count_catfailedtests = 0;
|
||||||
|
int count_catfailures = 0;
|
||||||
|
|
||||||
|
printf("\n%s:\n", cat.name);
|
||||||
|
|
||||||
|
for (int j = 0; j < cat.num_tests; j++) {
|
||||||
|
hmt_test test = cat.tests[j];
|
||||||
|
|
||||||
|
printf(" %s:", test.name);
|
||||||
|
|
||||||
|
hmt_testresult result = {
|
||||||
|
0, // count_cases
|
||||||
|
0, // count_failures
|
||||||
|
};
|
||||||
|
test.func(&result);
|
||||||
|
|
||||||
|
count_catfailures += result.count_failures;
|
||||||
|
|
||||||
|
if (result.count_failures > 0) {
|
||||||
|
count_catfailedtests++;
|
||||||
|
printf("\n " HMT_RED "(%d/%d passed)" HMT_RESET, result.count_cases - result.count_failures, result.count_cases);
|
||||||
|
printf("\n");
|
||||||
|
} else {
|
||||||
|
printf(HMT_GREEN " [PASS] (%d/%d passed) \n" HMT_RESET, result.count_cases - result.count_failures, result.count_cases);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count_alltests += cat.num_tests;
|
||||||
|
count_allfailedtests += count_catfailedtests;
|
||||||
|
count_allfailures += count_catfailures;
|
||||||
|
|
||||||
|
printf("%d/%d tests passed, %d failures\n", cat.num_tests - count_catfailedtests, cat.num_tests, count_catfailures);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count_allfailedtests > 0) {
|
||||||
|
printf(HMT_RED);
|
||||||
|
} else {
|
||||||
|
printf(HMT_GREEN);
|
||||||
|
}
|
||||||
|
printf("\n%d/%d tests passed overall, %d failures\n" HMT_RESET, count_alltests - count_allfailedtests, count_alltests, count_allfailures);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return (count_allfailedtests > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hmt_check_all_coverage() {
|
||||||
|
printf("Coverage:\n");
|
||||||
|
|
||||||
|
int count_failures = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < _hmt_num_covercases; i++) {
|
||||||
|
hmt_covercase covercase = _hmt_covercases[i];
|
||||||
|
|
||||||
|
if (covercase.expected_asserts != covercase.actual_asserts) {
|
||||||
|
count_failures++;
|
||||||
|
printf("%s: " HMT_RED "FAIL (expected %d asserts, got %d)\n" HMT_RESET, covercase.name, covercase.expected_asserts, covercase.actual_asserts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count_failures > 0) {
|
||||||
|
printf("\n");
|
||||||
|
printf(HMT_RED);
|
||||||
|
} else {
|
||||||
|
printf(HMT_GREEN);
|
||||||
|
}
|
||||||
|
printf("%d coverage cases tested, %d failures\n", _hmt_num_covercases, count_failures);
|
||||||
|
printf(HMT_RESET);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
if (_hmt_num_covererrors > 0) {
|
||||||
|
printf(HMT_RED "There were %d other coverage errors; scroll up to see them.\n", _hmt_num_covererrors);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (count_failures > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HANDMADE_TEST_IMPLEMENTATION_GUARD
|
||||||
|
#endif // HANDMADE_TEST_IMPLEMENTATION
|
||||||
|
|||||||
127
test/Makefile
127
test/Makefile
@@ -1,17 +1,124 @@
|
|||||||
ROOT_DIR = ..
|
BUILD_DIR=./build
|
||||||
|
|
||||||
CXXFLAGS += -g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers
|
CXXFLAGS+=-g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers -Wfloat-equal
|
||||||
|
|
||||||
all: c cpp
|
.PHONY: all all_c all_cpp
|
||||||
|
all: all_c all_cpp
|
||||||
|
all_c: c99 c99_no_simd c11 c17
|
||||||
|
all_cpp: cpp98 cpp98_no_simd cpp03 cpp11 cpp14 cpp17 cpp20
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -f hmm_test_c hmm_test_cpp *.o
|
rm -rf $(BUILD_DIR)
|
||||||
|
|
||||||
c: $(ROOT_DIR)/test/HandmadeMath.c test_impl
|
.PHONY: c99
|
||||||
$(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 -c $(ROOT_DIR)/test/HandmadeMath.c $(ROOT_DIR)/test/hmm_test.c -lm
|
c99:
|
||||||
$(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
|
@echo "\nCompiling as C99"
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR)\
|
||||||
|
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
|
||||||
|
../HandmadeMath.c ../hmm_test.c \
|
||||||
|
-lm -o hmm_test_c99 \
|
||||||
|
&& ./hmm_test_c99
|
||||||
|
|
||||||
cpp: $(ROOT_DIR)/test/HandmadeMath.cpp test_impl
|
.PHONY: c99_no_simd
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp $(ROOT_DIR)/test/HandmadeMath.cpp $(ROOT_DIR)/test/hmm_test.cpp
|
c99_no_simd:
|
||||||
|
@echo "\nCompiling as C99 (no SIMD)"
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR) \
|
||||||
|
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
|
||||||
|
-DHANDMADE_MATH_NO_SIMD \
|
||||||
|
../HandmadeMath.c ../hmm_test.c \
|
||||||
|
-lm -o hmm_test_c99_no_simd \
|
||||||
|
&& ./hmm_test_c99_no_simd
|
||||||
|
|
||||||
test_impl: $(ROOT_DIR)/test/hmm_test.cpp $(ROOT_DIR)/test/hmm_test.c
|
.PHONY: c11
|
||||||
|
c11:
|
||||||
|
@echo "\nCompiling as C11"
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR)\
|
||||||
|
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c11 \
|
||||||
|
../HandmadeMath.c ../hmm_test.c \
|
||||||
|
-lm -o hmm_test_c11 \
|
||||||
|
&& ./hmm_test_c11
|
||||||
|
|
||||||
|
.PHONY: c17
|
||||||
|
c17:
|
||||||
|
@echo "\nCompiling as C17"
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR)\
|
||||||
|
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c17 \
|
||||||
|
../HandmadeMath.c ../hmm_test.c \
|
||||||
|
-lm -o hmm_test_c17 \
|
||||||
|
&& ./hmm_test_c17
|
||||||
|
|
||||||
|
.PHONY: cpp98
|
||||||
|
cpp98:
|
||||||
|
@echo "\nCompiling as C++98"
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR) \
|
||||||
|
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++98 \
|
||||||
|
../HandmadeMath.cpp ../hmm_test.cpp \
|
||||||
|
-lm -o hmm_test_cpp98 \
|
||||||
|
&& ./hmm_test_cpp98
|
||||||
|
|
||||||
|
.PHONY: cpp98_no_simd
|
||||||
|
cpp98_no_simd:
|
||||||
|
@echo "\nCompiling as C++98 (no SIMD)"
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR) \
|
||||||
|
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++98 \
|
||||||
|
-DHANDMADE_MATH_NO_SIMD \
|
||||||
|
../HandmadeMath.cpp ../hmm_test.cpp \
|
||||||
|
-lm -o hmm_test_cpp98 \
|
||||||
|
&& ./hmm_test_cpp98
|
||||||
|
|
||||||
|
.PHONY: cpp03
|
||||||
|
cpp03:
|
||||||
|
@echo "\nCompiling as C++03"
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR) \
|
||||||
|
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++03 \
|
||||||
|
../HandmadeMath.cpp ../hmm_test.cpp \
|
||||||
|
-lm -o hmm_test_cpp03 \
|
||||||
|
&& ./hmm_test_cpp03
|
||||||
|
|
||||||
|
.PHONY: cpp11
|
||||||
|
cpp11:
|
||||||
|
@echo "\nCompiling as C++11"
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR) \
|
||||||
|
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++11 \
|
||||||
|
../HandmadeMath.cpp ../hmm_test.cpp \
|
||||||
|
-lm -o hmm_test_cpp11 \
|
||||||
|
&& ./hmm_test_cpp11
|
||||||
|
|
||||||
|
.PHONY: cpp14
|
||||||
|
cpp14:
|
||||||
|
@echo "\nCompiling as C++14"
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR) \
|
||||||
|
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++14 \
|
||||||
|
../HandmadeMath.cpp ../hmm_test.cpp \
|
||||||
|
-lm -o hmm_test_cpp14 \
|
||||||
|
&& ./hmm_test_cpp14
|
||||||
|
|
||||||
|
.PHONY: cpp17
|
||||||
|
cpp17:
|
||||||
|
@echo "\nCompiling as C++17"
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR) \
|
||||||
|
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++17 \
|
||||||
|
../HandmadeMath.cpp ../hmm_test.cpp \
|
||||||
|
-lm -o hmm_test_cpp17 \
|
||||||
|
&& ./hmm_test_cpp17
|
||||||
|
|
||||||
|
.PHONY: cpp20
|
||||||
|
cpp20:
|
||||||
|
@echo "\nCompiling as C++20"
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR) \
|
||||||
|
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++20 \
|
||||||
|
../HandmadeMath.cpp ../hmm_test.cpp \
|
||||||
|
-lm -o hmm_test_cpp20 \
|
||||||
|
&& ./hmm_test_cpp20
|
||||||
|
|||||||
16
test/README.md
Normal file
16
test/README.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Testing
|
||||||
|
|
||||||
|
You can compile and run the tests yourself by running:
|
||||||
|
|
||||||
|
```
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a specific test configuration, run one of:
|
||||||
|
|
||||||
|
```
|
||||||
|
make c
|
||||||
|
make c_no_sse
|
||||||
|
make cpp
|
||||||
|
make cpp_no_sse
|
||||||
|
```
|
||||||
347
test/categories/Addition.h
Normal file
347
test/categories/Addition.h
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
#include "../HandmadeTest.h"
|
||||||
|
|
||||||
|
TEST(Addition, Vec2)
|
||||||
|
{
|
||||||
|
HMM_Vec2 v2_1 = HMM_V2(1.0f, 2.0f);
|
||||||
|
HMM_Vec2 v2_2 = HMM_V2(3.0f, 4.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_AddV2(v2_1, v2_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_Add(v2_1, v2_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = v2_1 + v2_2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v2_1 += v2_2;
|
||||||
|
EXPECT_FLOAT_EQ(v2_1.X, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2_1.Y, 6.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Addition, Vec3)
|
||||||
|
{
|
||||||
|
HMM_Vec3 v3_1 = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||||
|
HMM_Vec3 v3_2 = HMM_V3(4.0f, 5.0f, 6.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_AddV3(v3_1, v3_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 7.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_Add(v3_1, v3_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 7.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = v3_1 + v3_2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 7.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3_1 += v3_2;
|
||||||
|
EXPECT_FLOAT_EQ(v3_1.X, 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3_1.Y, 7.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3_1.Z, 9.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Addition, Vec4)
|
||||||
|
{
|
||||||
|
HMM_Vec4 v4_1 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
HMM_Vec4 v4_2 = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_AddV4(v4_1, v4_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_Add(v4_1, v4_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = v4_1 + v4_2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v4_1 += v4_2;
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.X, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.Y, 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.Z, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.W, 12.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Addition, Mat2)
|
||||||
|
{
|
||||||
|
HMM_Mat2 a = HMM_M2();
|
||||||
|
HMM_Mat2 b = HMM_M2();
|
||||||
|
|
||||||
|
int Counter = 1;
|
||||||
|
for (int Column = 0; Column < 2; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 2; ++Row)
|
||||||
|
{
|
||||||
|
a.Elements[Column][Row] = Counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int Column = 0; Column < 2; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 2; ++Row)
|
||||||
|
{
|
||||||
|
b.Elements[Column][Row] = Counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = HMM_AddM2(a, b);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 12.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = HMM_Add(a, b);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 12.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = a + b;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 12.0f);
|
||||||
|
}
|
||||||
|
a += b;
|
||||||
|
EXPECT_FLOAT_EQ(a.Elements[0][0], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(a.Elements[0][1], 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(a.Elements[1][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(a.Elements[1][1], 12.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Addition, Mat3)
|
||||||
|
{
|
||||||
|
HMM_Mat3 a = HMM_M3();
|
||||||
|
HMM_Mat3 b = HMM_M3();
|
||||||
|
|
||||||
|
int Counter = 1;
|
||||||
|
for (int Column = 0; Column < 3; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 3; ++Row)
|
||||||
|
{
|
||||||
|
a.Elements[Column][Row] = Counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int Column = 0; Column < 3; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 3; ++Row)
|
||||||
|
{
|
||||||
|
b.Elements[Column][Row] = Counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = HMM_AddM3(a, b);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 11.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 13.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 15.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 17.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 19.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 23.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 25.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 27.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = HMM_Add(a, b);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 11.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 13.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 15.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 17.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 19.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 23.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 25.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 27.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = a + b;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 11.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 13.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 15.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 17.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 19.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 23.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 25.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 27.0f);
|
||||||
|
}
|
||||||
|
a += b;
|
||||||
|
EXPECT_FLOAT_EQ(a.Elements[0][0], 11.0f);
|
||||||
|
EXPECT_FLOAT_EQ(a.Elements[0][1], 13.0f);
|
||||||
|
EXPECT_FLOAT_EQ(a.Elements[0][2], 15.0f);
|
||||||
|
EXPECT_FLOAT_EQ(a.Elements[1][0], 17.0f);
|
||||||
|
EXPECT_FLOAT_EQ(a.Elements[1][1], 19.0f);
|
||||||
|
EXPECT_FLOAT_EQ(a.Elements[1][2], 21.0f);
|
||||||
|
EXPECT_FLOAT_EQ(a.Elements[2][0], 23.0f);
|
||||||
|
EXPECT_FLOAT_EQ(a.Elements[2][1], 25.0f);
|
||||||
|
EXPECT_FLOAT_EQ(a.Elements[2][2], 27.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Addition, Mat4)
|
||||||
|
{
|
||||||
|
HMM_Mat4 m4_1 = HMM_M4(); // will have 1 - 16
|
||||||
|
HMM_Mat4 m4_2 = HMM_M4(); // will have 17 - 32
|
||||||
|
|
||||||
|
// Fill the matrices
|
||||||
|
int Counter = 1;
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
m4_1.Elements[Column][Row] = Counter;
|
||||||
|
++Counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
m4_2.Elements[Column][Row] = Counter;
|
||||||
|
++Counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the results
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_AddM4(m4_1, m4_2);
|
||||||
|
float Expected = 18.0f;
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected);
|
||||||
|
Expected += 2.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_Add(m4_1, m4_2);
|
||||||
|
float Expected = 18.0f;
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected);
|
||||||
|
Expected += 2.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = m4_1 + m4_2;
|
||||||
|
float Expected = 18.0f;
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected);
|
||||||
|
Expected += 2.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m4_1 += m4_2;
|
||||||
|
float Expected = 18.0f;
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(m4_1.Elements[Column][Row], Expected);
|
||||||
|
Expected += 2.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Addition, Quaternion)
|
||||||
|
{
|
||||||
|
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_AddQ(q1, q2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_Add(q1, q2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Quat result = q1 + q2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
q1 += q2;
|
||||||
|
EXPECT_FLOAT_EQ(q1.X, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q1.Y, 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q1.Z, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q1.W, 12.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
439
test/categories/Division.h
Normal file
439
test/categories/Division.h
Normal file
@@ -0,0 +1,439 @@
|
|||||||
|
#include "../HandmadeTest.h"
|
||||||
|
|
||||||
|
TEST(Division, Vec2Vec2)
|
||||||
|
{
|
||||||
|
HMM_Vec2 v2_1 = HMM_V2(1.0f, 3.0f);
|
||||||
|
HMM_Vec2 v2_2 = HMM_V2(2.0f, 4.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_DivV2(v2_1, v2_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_Div(v2_1, v2_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = v2_1 / v2_2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v2_1 /= v2_2;
|
||||||
|
EXPECT_FLOAT_EQ(v2_1.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(v2_1.Y, 0.75f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Division, Vec2Scalar)
|
||||||
|
{
|
||||||
|
HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
|
||||||
|
float s = 2;
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_DivV2F(v2, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_Div(v2, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = v2 / s;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v2 /= s;
|
||||||
|
EXPECT_FLOAT_EQ(v2.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(v2.Y, 1.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Division, Vec3Vec3)
|
||||||
|
{
|
||||||
|
HMM_Vec3 v3_1 = HMM_V3(1.0f, 3.0f, 5.0f);
|
||||||
|
HMM_Vec3 v3_2 = HMM_V3(2.0f, 4.0f, 0.5f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_DivV3(v3_1, v3_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_Div(v3_1, v3_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = v3_1 / v3_2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3_1 /= v3_2;
|
||||||
|
EXPECT_FLOAT_EQ(v3_1.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(v3_1.Y, 0.75f);
|
||||||
|
EXPECT_FLOAT_EQ(v3_1.Z, 10.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Division, Vec3Scalar)
|
||||||
|
{
|
||||||
|
HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||||
|
float s = 2;
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_DivV3F(v3, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_Div(v3, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = v3 / s;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3 /= s;
|
||||||
|
EXPECT_FLOAT_EQ(v3.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.Z, 1.5f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Division, Vec4Vec4)
|
||||||
|
{
|
||||||
|
HMM_Vec4 v4_1 = HMM_V4(1.0f, 3.0f, 5.0f, 1.0f);
|
||||||
|
HMM_Vec4 v4_2 = HMM_V4(2.0f, 4.0f, 0.5f, 4.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_DivV4(v4_1, v4_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 0.25f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_Div(v4_1, v4_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 0.25f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = v4_1 / v4_2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 0.25f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v4_1 /= v4_2;
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.Y, 0.75f);
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.Z, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.W, 0.25f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Division, Vec4Scalar)
|
||||||
|
{
|
||||||
|
HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
float s = 2;
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_DivV4F(v4, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 2.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_Div(v4, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 2.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = v4 / s;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v4 /= s;
|
||||||
|
EXPECT_FLOAT_EQ(v4.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.Z, 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.W, 2.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Division, Mat2Scalar)
|
||||||
|
{
|
||||||
|
HMM_Mat2 m = HMM_M2();
|
||||||
|
float s = 0.5f;
|
||||||
|
|
||||||
|
int Counter = 1;
|
||||||
|
for (int Column = 0; Column < 2; ++Column) {
|
||||||
|
for (int Row = 0; Row < 2; ++Row) {
|
||||||
|
m.Elements[Column][Row] = Counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = HMM_DivM2F(m, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = HMM_Div(m, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = m / s;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Division, Mat3Scalar)
|
||||||
|
{
|
||||||
|
HMM_Mat3 m = HMM_M3();
|
||||||
|
float s = 0.5f;
|
||||||
|
|
||||||
|
int Counter = 1;
|
||||||
|
for (int Column = 0; Column < 3; ++Column) {
|
||||||
|
for (int Row = 0; Row < 3; ++Row) {
|
||||||
|
m.Elements[Column][Row] = Counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = HMM_DivM3F(m, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 14.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 16.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 18.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = HMM_Div(m, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 14.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 16.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 18.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = m / s;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 14.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 16.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 18.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Division, Mat4Scalar)
|
||||||
|
{
|
||||||
|
HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
|
||||||
|
float s = 2;
|
||||||
|
|
||||||
|
// Fill the matrix
|
||||||
|
int Counter = 1;
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
m4.Elements[Column][Row] = Counter;
|
||||||
|
++Counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the results
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_DivM4F(m4, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][3], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 2.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 3.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][3], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 4.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 5.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][3], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][0], 6.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][1], 7.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_Div(m4, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][3], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 2.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 3.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][3], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 4.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 5.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][3], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][0], 6.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][1], 7.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = m4 / s;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][3], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 2.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 3.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][3], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 4.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 5.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][3], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][0], 6.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][1], 7.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
m4 /= s;
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[0][0], 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[0][1], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[0][2], 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[0][3], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[1][0], 2.5f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[1][1], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[1][2], 3.5f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[1][3], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[2][0], 4.5f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[2][1], 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[2][2], 5.5f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[2][3], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[3][0], 6.5f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[3][1], 7.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[3][2], 7.5f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[3][3], 8.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Division, QuaternionScalar)
|
||||||
|
{
|
||||||
|
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
float f = 2.0f;
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_DivQF(q, f);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 2.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_Div(q, f);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 2.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Quat result = q / f;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
q /= f;
|
||||||
|
EXPECT_FLOAT_EQ(q.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(q.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q.Z, 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(q.W, 2.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
70
test/categories/Equality.h
Normal file
70
test/categories/Equality.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#include "../HandmadeTest.h"
|
||||||
|
|
||||||
|
TEST(Equality, Vec2)
|
||||||
|
{
|
||||||
|
HMM_Vec2 a = HMM_V2(1.0f, 2.0f);
|
||||||
|
HMM_Vec2 b = HMM_V2(1.0f, 2.0f);
|
||||||
|
HMM_Vec2 c = HMM_V2(3.0f, 4.0f);
|
||||||
|
|
||||||
|
EXPECT_TRUE(HMM_EqV2(a, b));
|
||||||
|
EXPECT_FALSE(HMM_EqV2(a, c));
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
EXPECT_TRUE(HMM_Eq(a, b));
|
||||||
|
EXPECT_FALSE(HMM_Eq(a, c));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
EXPECT_TRUE(a == b);
|
||||||
|
EXPECT_FALSE(a == c);
|
||||||
|
|
||||||
|
EXPECT_FALSE(a != b);
|
||||||
|
EXPECT_TRUE(a != c);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Equality, Vec3)
|
||||||
|
{
|
||||||
|
HMM_Vec3 a = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||||
|
HMM_Vec3 b = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||||
|
HMM_Vec3 c = HMM_V3(4.0f, 5.0f, 6.0f);
|
||||||
|
|
||||||
|
EXPECT_TRUE(HMM_EqV3(a, b));
|
||||||
|
EXPECT_FALSE(HMM_EqV3(a, c));
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
EXPECT_TRUE(HMM_Eq(a, b));
|
||||||
|
EXPECT_FALSE(HMM_Eq(a, c));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
EXPECT_TRUE(a == b);
|
||||||
|
EXPECT_FALSE(a == c);
|
||||||
|
|
||||||
|
EXPECT_FALSE(a != b);
|
||||||
|
EXPECT_TRUE(a != c);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Equality, Vec4)
|
||||||
|
{
|
||||||
|
HMM_Vec4 a = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
HMM_Vec4 b = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
HMM_Vec4 c = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f);
|
||||||
|
|
||||||
|
EXPECT_TRUE(HMM_EqV4(a, b));
|
||||||
|
EXPECT_FALSE(HMM_EqV4(a, c));
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
EXPECT_TRUE(HMM_Eq(a, b));
|
||||||
|
EXPECT_FALSE(HMM_Eq(a, c));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
EXPECT_TRUE(a == b);
|
||||||
|
EXPECT_FALSE(a == c);
|
||||||
|
|
||||||
|
EXPECT_FALSE(a != b);
|
||||||
|
EXPECT_TRUE(a != c);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
321
test/categories/Initialization.h
Normal file
321
test/categories/Initialization.h
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
#include "../HandmadeTest.h"
|
||||||
|
|
||||||
|
TEST(Initialization, Vectors)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Test vec2
|
||||||
|
//
|
||||||
|
HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(v2.X, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2.Y, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2.U, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2.V, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2.Left, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2.Right, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2.Width, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2.Height, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2.Elements[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2.Elements[1], 2.0f);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
EXPECT_FLOAT_EQ(v2[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2[1], 2.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test vec3
|
||||||
|
//
|
||||||
|
HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(v3.X, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.Y, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.Z, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.U, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.V, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.W, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.R, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.G, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.B, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.Elements[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.Elements[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.Elements[2], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.XY.Elements[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.XY.Elements[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.YZ.Elements[0], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.YZ.Elements[1], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.UV.Elements[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.UV.Elements[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.VW.Elements[0], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.VW.Elements[1], 3.0f);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
EXPECT_FLOAT_EQ(v3[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3[2], 3.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test vec4
|
||||||
|
//
|
||||||
|
HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
HMM_Vec4 v4v = HMM_V4V(v3, 4.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(v4.X, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.Y, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.Z, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.W, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.R, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.G, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.B, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.A, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.XY.Elements[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.XY.Elements[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.YZ.Elements[0], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.YZ.Elements[1], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.ZW.Elements[0], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.ZW.Elements[1], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.XY.Elements[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.XY.Elements[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.XYZ.Elements[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.XYZ.Elements[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.XYZ.Elements[2], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.RGB.Elements[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.RGB.Elements[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.RGB.Elements[2], 3.0f);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
EXPECT_FLOAT_EQ(v4[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4[2], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4[3], 4.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(v4v.X, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.Y, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.Z, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.W, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.R, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.G, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.B, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.A, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.XY.Elements[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.XY.Elements[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.YZ.Elements[0], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.YZ.Elements[1], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.ZW.Elements[0], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.ZW.Elements[1], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.XY.Elements[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.XY.Elements[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.XYZ.Elements[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.XYZ.Elements[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.XYZ.Elements[2], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.RGB.Elements[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.RGB.Elements[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v.RGB.Elements[2], 3.0f);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
EXPECT_FLOAT_EQ(v4v[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v[2], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4v[3], 4.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Initialization, MatrixEmpty)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Test mat2
|
||||||
|
//
|
||||||
|
HMM_Mat2 m2 = HMM_M2();
|
||||||
|
for (int Column = 0; Column < 2; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 2; ++Row)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(m2.Elements[Column][Row], 0.0f);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
EXPECT_FLOAT_EQ(m2[Column][Row], 0.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test mat3
|
||||||
|
//
|
||||||
|
HMM_Mat3 m3 = HMM_M3();
|
||||||
|
for (int Column = 0; Column < 3; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 3; ++Row)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(m3.Elements[Column][Row], 0.0f);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
EXPECT_FLOAT_EQ(m3[Column][Row], 0.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test mat4
|
||||||
|
//
|
||||||
|
HMM_Mat4 m4 = HMM_M4();
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[Column][Row], 0.0f);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
EXPECT_FLOAT_EQ(m4[Column][Row], 0.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Initialization, MatrixDiagonal)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Test mat2
|
||||||
|
//
|
||||||
|
HMM_Mat2 m2d = HMM_M2D(1.0f);
|
||||||
|
for (int Column = 0; Column < 2; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 2; ++Row)
|
||||||
|
{
|
||||||
|
if (Column == Row) {
|
||||||
|
EXPECT_FLOAT_EQ(m2d.Elements[Column][Row], 1.0f);
|
||||||
|
} else {
|
||||||
|
EXPECT_FLOAT_EQ(m2d.Elements[Column][Row], 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test mat3
|
||||||
|
//
|
||||||
|
HMM_Mat3 m3d = HMM_M3D(1.0f);
|
||||||
|
for (int Column = 0; Column < 3; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 3; ++Row)
|
||||||
|
{
|
||||||
|
if (Column == Row) {
|
||||||
|
EXPECT_FLOAT_EQ(m3d.Elements[Column][Row], 1.0f);
|
||||||
|
} else {
|
||||||
|
EXPECT_FLOAT_EQ(m3d.Elements[Column][Row], 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test mat4
|
||||||
|
//
|
||||||
|
HMM_Mat4 m4d = HMM_M4D(1.0f);
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
if (Column == Row) {
|
||||||
|
EXPECT_FLOAT_EQ(m4d.Elements[Column][Row], 1.0f);
|
||||||
|
} else {
|
||||||
|
EXPECT_FLOAT_EQ(m4d.Elements[Column][Row], 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Initialization, Quaternion)
|
||||||
|
{
|
||||||
|
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(q.X, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q.Y, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q.Z, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q.W, 4.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(q.Elements[0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q.Elements[1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q.Elements[2], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q.Elements[3], 4.0f);
|
||||||
|
|
||||||
|
HMM_Vec4 v = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
HMM_Quat qv = HMM_QV4(v);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(qv.X, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(qv.Y, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(qv.Z, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(qv.W, 4.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
TEST(Initialization, MatrixOverloads)
|
||||||
|
{
|
||||||
|
// Operator overloads for matrix columns must allow mutation.
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test mat2
|
||||||
|
//
|
||||||
|
HMM_Mat2 m2 = {0};
|
||||||
|
m2[0][0] = 1.0f;
|
||||||
|
m2[0][1] = 2.0f;
|
||||||
|
m2[1][0] = 3.0f;
|
||||||
|
m2[1][1] = 4.0f;
|
||||||
|
EXPECT_FLOAT_EQ(m2.Elements[0][0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m2.Elements[0][1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m2.Elements[1][0], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m2.Elements[1][1], 4.0f);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test mat3
|
||||||
|
//
|
||||||
|
HMM_Mat3 m3 = {0};
|
||||||
|
m3[0][0] = 1.0f;
|
||||||
|
m3[0][1] = 2.0f;
|
||||||
|
m3[0][2] = 3.0f;
|
||||||
|
m3[1][0] = 4.0f;
|
||||||
|
m3[1][1] = 5.0f;
|
||||||
|
m3[1][2] = 6.0f;
|
||||||
|
m3[2][0] = 7.0f;
|
||||||
|
m3[2][1] = 8.0f;
|
||||||
|
m3[2][2] = 9.0f;
|
||||||
|
EXPECT_FLOAT_EQ(m3.Elements[0][0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m3.Elements[0][1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m3.Elements[0][2], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m3.Elements[1][0], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m3.Elements[1][1], 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m3.Elements[1][2], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m3.Elements[2][0], 7.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m3.Elements[2][1], 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m3.Elements[2][2], 9.0f);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test mat4
|
||||||
|
//
|
||||||
|
HMM_Mat4 m4 = {0};
|
||||||
|
m4[0][0] = 1.0f;
|
||||||
|
m4[0][1] = 2.0f;
|
||||||
|
m4[0][2] = 3.0f;
|
||||||
|
m4[0][3] = 4.0f;
|
||||||
|
m4[1][0] = 5.0f;
|
||||||
|
m4[1][1] = 6.0f;
|
||||||
|
m4[1][2] = 7.0f;
|
||||||
|
m4[1][3] = 8.0f;
|
||||||
|
m4[2][0] = 9.0f;
|
||||||
|
m4[2][1] = 10.0f;
|
||||||
|
m4[2][2] = 11.0f;
|
||||||
|
m4[2][3] = 12.0f;
|
||||||
|
m4[3][0] = 13.0f;
|
||||||
|
m4[3][1] = 14.0f;
|
||||||
|
m4[3][2] = 15.0f;
|
||||||
|
m4[3][3] = 16.0f;
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[0][0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[0][1], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[0][2], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[0][3], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[1][0], 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[1][1], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[1][2], 7.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[1][3], 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[2][0], 9.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[2][1], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[2][2], 11.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[2][3], 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[3][0], 13.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[3][1], 14.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[3][2], 15.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[3][3], 16.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
359
test/categories/MatrixOps.h
Normal file
359
test/categories/MatrixOps.h
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
#include "../HandmadeTest.h"
|
||||||
|
|
||||||
|
TEST(InvMatrix, Transpose)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
HMM_Mat2 Matrix = {
|
||||||
|
1.0f, 3.0f,
|
||||||
|
2.0f, 4.0f,
|
||||||
|
};
|
||||||
|
HMM_Mat2 Expect = {
|
||||||
|
1.0f, 2.0f,
|
||||||
|
3.0f, 4.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = HMM_TransposeM2(Matrix);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], Expect.Elements[0][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = HMM_Transpose(Matrix);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], Expect.Elements[0][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat3 Matrix = {
|
||||||
|
1.0f, 4.0f, 7.0f,
|
||||||
|
2.0f, 5.0f, 8.0f,
|
||||||
|
3.0f, 6.0f, 9.0f,
|
||||||
|
};
|
||||||
|
HMM_Mat3 Expect = {
|
||||||
|
1.0f, 2.0f, 3.0f,
|
||||||
|
4.0f, 5.0f, 6.0f,
|
||||||
|
7.0f, 8.0f, 9.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = HMM_TransposeM3(Matrix);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], Expect.Elements[0][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], Expect.Elements[0][2]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], Expect.Elements[1][2]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], Expect.Elements[2][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], Expect.Elements[2][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], Expect.Elements[2][2]);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = HMM_Transpose(Matrix);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], Expect.Elements[0][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], Expect.Elements[0][2]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], Expect.Elements[1][2]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], Expect.Elements[2][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], Expect.Elements[2][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], Expect.Elements[2][2]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Mat4 Matrix = {
|
||||||
|
1.0f, 5.0f, 9.0f, 13.0f,
|
||||||
|
2.0f, 6.0f, 10.0f, 14.0f,
|
||||||
|
3.0f, 7.0f, 11.0f, 15.0f,
|
||||||
|
4.0f, 8.0f, 12.0f, 16.0f
|
||||||
|
};
|
||||||
|
HMM_Mat4 Expect = {
|
||||||
|
1.0f, 2.0f, 3.0f, 4.0f,
|
||||||
|
5.0f, 6.0f, 7.0f, 8.0f,
|
||||||
|
9.0f, 10.0f, 11.0f, 12.0f,
|
||||||
|
13.0f, 14.0f, 15.0f, 16.0f,
|
||||||
|
};
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_TransposeM4(Matrix);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], Expect.Elements[0][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], Expect.Elements[0][2]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], Expect.Elements[1][2]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], Expect.Elements[2][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], Expect.Elements[2][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], Expect.Elements[2][2]);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_Transpose(Matrix);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], Expect.Elements[0][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], Expect.Elements[0][2]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], Expect.Elements[1][2]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], Expect.Elements[2][0]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], Expect.Elements[2][1]);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], Expect.Elements[2][2]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(InvMatrix, InvGeneral)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
HMM_Mat4 Matrix = {
|
||||||
|
12.0f, 2.0f, 1.0f, 1.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 1.0f,
|
||||||
|
0.0f, 1.0f, 5.0f, 1.0f,
|
||||||
|
11.0f, 1.0f, 0.0f, 10.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
HMM_Mat4 Expect = HMM_M4D(1.0);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvGeneralM4(Matrix);
|
||||||
|
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
|
||||||
|
|
||||||
|
float Det = HMM_DeterminantM4(Matrix);
|
||||||
|
EXPECT_FLOAT_EQ(Det, -80.0f);
|
||||||
|
|
||||||
|
EXPECT_NEAR(Result.Elements[0][0], Expect.Elements[0][0], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[0][1], Expect.Elements[0][1], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[0][2], Expect.Elements[0][2], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[0][3], Expect.Elements[0][3], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[1][0], Expect.Elements[1][0], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[1][1], Expect.Elements[1][1], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[1][2], Expect.Elements[1][2], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[1][3], Expect.Elements[1][3], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[2][0], Expect.Elements[2][0], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[2][1], Expect.Elements[2][1], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[2][2], Expect.Elements[2][2], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[2][3], Expect.Elements[2][3], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[3][0], Expect.Elements[3][0], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[3][1], Expect.Elements[3][1], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[3][2], Expect.Elements[3][2], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[3][3], Expect.Elements[3][3], 0.00001f);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
Inverse = HMM_InvGeneral(Matrix);
|
||||||
|
Result = HMM_Mul(Matrix, Inverse);
|
||||||
|
|
||||||
|
Det = HMM_Determinant(Matrix);
|
||||||
|
EXPECT_FLOAT_EQ(Det, -80.0f);
|
||||||
|
|
||||||
|
EXPECT_NEAR(Result.Elements[0][0], Expect.Elements[0][0], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[0][1], Expect.Elements[0][1], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[0][2], Expect.Elements[0][2], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[0][3], Expect.Elements[0][3], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[1][0], Expect.Elements[1][0], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[1][1], Expect.Elements[1][1], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[1][2], Expect.Elements[1][2], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[1][3], Expect.Elements[1][3], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[2][0], Expect.Elements[2][0], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[2][1], Expect.Elements[2][1], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[2][2], Expect.Elements[2][2], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[2][3], Expect.Elements[2][3], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[3][0], Expect.Elements[3][0], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[3][1], Expect.Elements[3][1], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[3][2], Expect.Elements[3][2], 0.00001f);
|
||||||
|
EXPECT_NEAR(Result.Elements[3][3], Expect.Elements[3][3], 0.00001f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat3 Matrix = {
|
||||||
|
12.0f, 2.0f, 1.0f,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
0.0f, 1.0f, 5.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
HMM_Mat3 Expect = HMM_M3D(1.0);
|
||||||
|
HMM_Mat3 Inverse = HMM_InvGeneralM3(Matrix);
|
||||||
|
HMM_Mat3 Result = HMM_MulM3(Matrix, Inverse);
|
||||||
|
|
||||||
|
float Det = HMM_DeterminantM3(Matrix);
|
||||||
|
EXPECT_FLOAT_EQ(Det, -12.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
Inverse = HMM_InvGeneral(Matrix);
|
||||||
|
Result = HMM_Mul(Matrix, Inverse);
|
||||||
|
Det = HMM_Determinant(Matrix);
|
||||||
|
EXPECT_FLOAT_EQ(Det, -12.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat2 Matrix = {
|
||||||
|
12.0f, 2.0f,
|
||||||
|
1.0f, 5.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
HMM_Mat2 Expect = HMM_M2D(1.0);
|
||||||
|
HMM_Mat2 Inverse = HMM_InvGeneralM2(Matrix);
|
||||||
|
HMM_Mat2 Result = HMM_MulM2(Matrix, Inverse);
|
||||||
|
|
||||||
|
float Det = HMM_DeterminantM2(Matrix);
|
||||||
|
EXPECT_FLOAT_EQ(Det, 58.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
Inverse = HMM_InvGeneral(Matrix);
|
||||||
|
Result = HMM_Mul(Matrix, Inverse);
|
||||||
|
Det = HMM_Determinant(Matrix);
|
||||||
|
EXPECT_FLOAT_EQ(Det, 58.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(InvMatrix, InvOrthographic)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
HMM_Mat4 Matrix = HMM_Orthographic_RH_NO(-160+100, 160+100, -90+200, 90+200, 10, 10000);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix);
|
||||||
|
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Mat4 Matrix = HMM_Orthographic_RH_ZO(-160+100, 160+100, -90+200, 90+200, 10, 10000);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix);
|
||||||
|
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Mat4 Matrix = HMM_Orthographic_LH_NO(-160+100, 160+100, -90+200, 90+200, 10, 10000);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix);
|
||||||
|
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Mat4 Matrix = HMM_Orthographic_LH_ZO(-160+100, 160+100, -90+200, 90+200, 10, 10000);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix);
|
||||||
|
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(InvMatrix, InvPerspective)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
HMM_Mat4 Matrix = HMM_Perspective_RH_NO(HMM_AngleDeg(120), 16.0/9.0, 10, 10000);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvPerspective_RH(Matrix);
|
||||||
|
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Mat4 Matrix = HMM_Perspective_RH_ZO(HMM_AngleDeg(120), 16.0/9.0, 10, 10000);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvPerspective_RH(Matrix);
|
||||||
|
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Mat4 Matrix = HMM_Perspective_LH_NO(HMM_AngleDeg(120), 16.0/9.0, 10, 10000);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvPerspective_LH(Matrix);
|
||||||
|
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Mat4 Matrix = HMM_Perspective_LH_ZO(HMM_AngleDeg(120), 16.0/9.0, 10, 10000);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvPerspective_LH(Matrix);
|
||||||
|
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(InvMatrix, InvLookAt)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
HMM_Vec3 Eye = {10.0f, 10.0f, 10.0f};
|
||||||
|
HMM_Vec3 Center = {100.0f, 200.0f, 30.0f};
|
||||||
|
HMM_Vec3 Up = {0.0f, 0.0f, 1.0f};
|
||||||
|
HMM_Mat4 Matrix = HMM_LookAt_RH(Eye, Center, Up);
|
||||||
|
HMM_Mat4 Expect = HMM_M4D(1.0f);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvLookAt(Matrix);
|
||||||
|
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
|
||||||
|
EXPECT_M4_NEAR(Result, Expect, 0.001f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec3 Eye = {10.0f, 10.0f, 10.0f};
|
||||||
|
HMM_Vec3 Center = {100.0f, 200.0f, 30.0f};
|
||||||
|
HMM_Vec3 Up = {0.0f, 0.0f, 1.0f};
|
||||||
|
HMM_Mat4 Matrix = HMM_LookAt_LH(Eye, Center, Up);
|
||||||
|
HMM_Mat4 Expect = HMM_M4D(1.0f);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvLookAt(Matrix);
|
||||||
|
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
|
||||||
|
EXPECT_M4_NEAR(Result, Expect, 0.001f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(InvMatrix, InvRotate)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
HMM_Vec3 Axis = {1.0f, -1.0f, 0.5f};
|
||||||
|
HMM_Mat4 Matrix = HMM_Rotate_RH(HMM_AngleDeg(30), HMM_NormV3(Axis));
|
||||||
|
HMM_Mat4 Expect = HMM_M4D(1.0f);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvRotate(Matrix);
|
||||||
|
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
|
||||||
|
EXPECT_M4_NEAR(Result, Expect, 0.001f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec3 Axis = {1.0f, -1.0f, 0.5f};
|
||||||
|
HMM_Mat4 Matrix = HMM_Rotate_LH(HMM_AngleDeg(30), HMM_NormV3(Axis));
|
||||||
|
HMM_Mat4 Expect = HMM_M4D(1.0f);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvRotate(Matrix);
|
||||||
|
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
|
||||||
|
EXPECT_M4_NEAR(Result, Expect, 0.001f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(InvMatrix, InvScale)
|
||||||
|
{
|
||||||
|
HMM_Vec3 Scale = {1.0f, -1.0f, 0.5f};
|
||||||
|
HMM_Mat4 Matrix = HMM_Scale(Scale);
|
||||||
|
HMM_Mat4 Expect = HMM_M4D(1.0f);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvScale(Matrix);
|
||||||
|
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
|
||||||
|
EXPECT_M4_EQ(Result, Expect);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(InvMatrix, InvTranslate)
|
||||||
|
{
|
||||||
|
HMM_Vec3 Move = {1.0f, -1.0f, 0.5f};
|
||||||
|
HMM_Mat4 Matrix = HMM_Translate(Move);
|
||||||
|
HMM_Mat4 Expect = HMM_M4D(1.0f);
|
||||||
|
HMM_Mat4 Inverse = HMM_InvTranslate(Matrix);
|
||||||
|
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
|
||||||
|
EXPECT_M4_EQ(Result, Expect);
|
||||||
|
}
|
||||||
868
test/categories/Multiplication.h
Normal file
868
test/categories/Multiplication.h
Normal file
@@ -0,0 +1,868 @@
|
|||||||
|
#include "../HandmadeTest.h"
|
||||||
|
|
||||||
|
TEST(Multiplication, Vec2Vec2)
|
||||||
|
{
|
||||||
|
HMM_Vec2 v2_1 = HMM_V2(1.0f, 2.0f);
|
||||||
|
HMM_Vec2 v2_2 = HMM_V2(3.0f, 4.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_MulV2(v2_1, v2_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_Mul(v2_1, v2_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = v2_1 * v2_2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v2_1 *= v2_2;
|
||||||
|
EXPECT_FLOAT_EQ(v2_1.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2_1.Y, 8.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Vec2Scalar)
|
||||||
|
{
|
||||||
|
HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
|
||||||
|
float s = 3.0f;
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_MulV2F(v2, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_Mul(v2, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = v2 * s;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = s * v2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v2 *= s;
|
||||||
|
EXPECT_FLOAT_EQ(v2.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2.Y, 6.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Vec3Vec3)
|
||||||
|
{
|
||||||
|
HMM_Vec3 v3_1 = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||||
|
HMM_Vec3 v3_2 = HMM_V3(4.0f, 5.0f, 6.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_MulV3(v3_1, v3_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 18.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_Mul(v3_1, v3_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 18.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = v3_1 * v3_2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 18.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3_1 *= v3_2;
|
||||||
|
EXPECT_FLOAT_EQ(v3_1.X, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3_1.Y, 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3_1.Z, 18.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Vec3Scalar)
|
||||||
|
{
|
||||||
|
HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||||
|
float s = 3.0f;
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_MulV3F(v3, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_Mul(v3, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = v3 * s;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = s * v3;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3 *= s;
|
||||||
|
EXPECT_FLOAT_EQ(v3.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.Y, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3.Z, 9.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Vec4Vec4)
|
||||||
|
{
|
||||||
|
HMM_Vec4 v4_1 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
HMM_Vec4 v4_2 = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_MulV4(v4_1, v4_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 21.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 32.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_Mul(v4_1, v4_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 21.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 32.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = v4_1 * v4_2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 21.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 32.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v4_1 *= v4_2;
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.X, 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.Y, 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.Z, 21.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.W, 32.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Vec4Scalar)
|
||||||
|
{
|
||||||
|
HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
float s = 3.0f;
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_MulV4F(v4, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_Mul(v4, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = v4 * s;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = s * v4;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v4 *= s;
|
||||||
|
EXPECT_FLOAT_EQ(v4.X, 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.Y, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4.Z, 9.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Mat2Mat2) {
|
||||||
|
HMM_Mat2 a = HMM_M2();
|
||||||
|
HMM_Mat2 b = HMM_M2();
|
||||||
|
|
||||||
|
int counter = 1;
|
||||||
|
for (int Column = 0; Column < 2; Column++) {
|
||||||
|
for (int Row = 0; Row < 2; Row++) {
|
||||||
|
a.Elements[Column][Row] = counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int Column = 0; Column < 2; Column++) {
|
||||||
|
for (int Row = 0; Row < 2; Row++) {
|
||||||
|
b.Elements[Column][Row] = counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = HMM_MulM2(a,b);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 23.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 34.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 31.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 46.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = HMM_Mul(a,b);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 23.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 34.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 31.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 46.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = a * b;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 23.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 34.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 31.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 46.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Mat2Scalar) {
|
||||||
|
HMM_Mat2 m = HMM_M2();
|
||||||
|
float s = 10.0f;
|
||||||
|
|
||||||
|
int counter = 1;
|
||||||
|
for (int Column = 0; Column < 2; Column++) {
|
||||||
|
for (int Row = 0; Row < 2; Row++) {
|
||||||
|
m.Elements[Column][Row] = counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = HMM_MulM2F(m, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = HMM_Mul(m, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = m * s;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = s * m;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
|
||||||
|
}
|
||||||
|
m *= s;
|
||||||
|
EXPECT_FLOAT_EQ(m.Elements[0][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m.Elements[0][1], 20.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m.Elements[1][0], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m.Elements[1][1], 40.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Mat2Vec2) {
|
||||||
|
HMM_Mat2 m = HMM_M2();
|
||||||
|
HMM_Vec2 v = HMM_V2(0.0f, 0.0f);
|
||||||
|
|
||||||
|
int counter = 1;
|
||||||
|
for (int Column = 0; Column < 2; Column++) {
|
||||||
|
for (int Row = 0; Row < 2; Row++) {
|
||||||
|
m.Elements[Column][Row] = counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int Row = 0; Row < 2; Row++) {
|
||||||
|
v.Elements[Row] = counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_MulM2V2(m, v);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0], 23.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1], 34.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_Mul(m, v);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0], 23.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1], 34.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = m * v;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0], 23.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1], 34.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Mat3Mat3)
|
||||||
|
{
|
||||||
|
HMM_Mat3 a = HMM_M3();
|
||||||
|
HMM_Mat3 b = HMM_M3();
|
||||||
|
|
||||||
|
int counter = 1;
|
||||||
|
for (int Column = 0; Column < 3; Column++) {
|
||||||
|
for (int Row = 0; Row < 3; Row++) {
|
||||||
|
a.Elements[Column][Row] = counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int Column = 0; Column < 3; Column++) {
|
||||||
|
for (int Row = 0; Row < 3; Row++) {
|
||||||
|
b.Elements[Column][Row] = counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = HMM_MulM3(a,b);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 138.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 171.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 204.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 174.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 216.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 258.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 210.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 261.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 312.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = HMM_Mul(a,b);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 138.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 171.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 204.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 174.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 216.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 258.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 210.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 261.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 312.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = a * b;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 138.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 171.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 204.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 174.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 216.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 258.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 210.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 261.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 312.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Mat3Scalar) {
|
||||||
|
HMM_Mat3 m = HMM_M3();
|
||||||
|
float s = 10.0f;
|
||||||
|
|
||||||
|
int counter = 1;
|
||||||
|
for (int Column = 0; Column < 3; Column++) {
|
||||||
|
for (int Row = 0; Row < 3; Row++) {
|
||||||
|
m.Elements[Column][Row] = counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = HMM_MulM3F(m, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 40.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 50.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 60.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 70.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = HMM_Mul(m, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 40.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 50.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 60.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 70.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = m * s;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 40.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 50.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 60.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 70.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = s * m;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 40.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 50.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 60.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 70.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
|
||||||
|
}
|
||||||
|
m *= s;
|
||||||
|
EXPECT_FLOAT_EQ(m.Elements[0][0], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m.Elements[0][1], 20.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m.Elements[0][2], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m.Elements[1][0], 40.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m.Elements[1][1], 50.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m.Elements[1][2], 60.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m.Elements[2][0], 70.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m.Elements[2][1], 80.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m.Elements[2][2], 90.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Mat3Vec3) {
|
||||||
|
HMM_Mat3 m = HMM_M3();
|
||||||
|
HMM_Vec3 v = HMM_V3(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
int counter = 1;
|
||||||
|
for (int Column = 0; Column < 3; Column++) {
|
||||||
|
for (int Row = 0; Row < 3; Row++) {
|
||||||
|
m.Elements[Column][Row] = counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int Row = 0; Row < 3; Row++) {
|
||||||
|
v.Elements[Row] = counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_MulM3V3(m, v);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0], 138.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1], 171.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2], 204.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_Mul(m, v);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0], 138.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1], 171.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2], 204.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = m * v;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0], 138.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1], 171.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2], 204.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Mat4Mat4)
|
||||||
|
{
|
||||||
|
HMM_Mat4 m4_1 = HMM_M4(); // will have 1 - 16
|
||||||
|
HMM_Mat4 m4_2 = HMM_M4(); // will have 17 - 32
|
||||||
|
|
||||||
|
// Fill the matrices
|
||||||
|
int Counter = 1;
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
m4_1.Elements[Column][Row] = Counter;
|
||||||
|
++Counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
m4_2.Elements[Column][Row] = Counter;
|
||||||
|
++Counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the results
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_MulM4(m4_1, m4_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][3], 760.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 650.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 740.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 830.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][3], 920.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 762.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 868.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 974.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][3], 1080.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][0], 874.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][1], 996.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_Mul(m4_1, m4_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][3], 760.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 650.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 740.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 830.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][3], 920.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 762.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 868.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 974.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][3], 1080.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][0], 874.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][1], 996.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = m4_1 * m4_2;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][3], 760.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 650.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 740.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 830.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][3], 920.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 762.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 868.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 974.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][3], 1080.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][0], 874.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][1], 996.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// At the time I wrote this, I intentionally omitted
|
||||||
|
// the *= operator for matrices because matrix
|
||||||
|
// multiplication is not commutative. (bvisness)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Mat4Scalar)
|
||||||
|
{
|
||||||
|
HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
|
||||||
|
float s = 3;
|
||||||
|
|
||||||
|
// Fill the matrix
|
||||||
|
int Counter = 1;
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
m4.Elements[Column][Row] = Counter;
|
||||||
|
++Counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the results
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_MulM4F(m4, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][3], 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 15.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 18.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][3], 24.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 27.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 33.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][3], 36.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][0], 39.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][1], 42.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_Mul(m4, s);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][3], 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 15.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 18.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][3], 24.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 27.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 33.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][3], 36.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][0], 39.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][1], 42.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = m4 * s;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][3], 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 15.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 18.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][3], 24.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 27.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 33.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][3], 36.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][0], 39.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][1], 42.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = s * m4;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][3], 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 15.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 18.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][3], 24.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 27.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 33.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][3], 36.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][0], 39.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][1], 42.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
m4 *= s;
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[0][0], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[0][1], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[0][2], 9.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[0][3], 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[1][0], 15.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[1][1], 18.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[1][2], 21.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[1][3], 24.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[2][0], 27.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[2][1], 30.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[2][2], 33.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[2][3], 36.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[3][0], 39.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[3][1], 42.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[3][2], 45.0f);
|
||||||
|
EXPECT_FLOAT_EQ(m4.Elements[3][3], 48.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, Mat4Vec4)
|
||||||
|
{
|
||||||
|
HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
|
||||||
|
HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
|
||||||
|
// Fill the matrix
|
||||||
|
int Counter = 1;
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
m4.Elements[Column][Row] = Counter;
|
||||||
|
++Counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the results
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_MulM4V4(m4, v4);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 90.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 100.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 110.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 120.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_Mul(m4, v4);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 90.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 100.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 110.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 120.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = m4 * v4;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 90.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 100.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 110.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 120.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// *= makes no sense for this particular case.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, QuaternionQuaternion)
|
||||||
|
{
|
||||||
|
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_MulQ(q1, q2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 24.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 48.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 48.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, -6.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_Mul(q1, q2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 24.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 48.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 48.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, -6.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Quat result = q1 * q2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 24.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 48.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 48.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, -6.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Like with matrices, we're not implementing the *=
|
||||||
|
// operator for quaternions because quaternion multiplication
|
||||||
|
// is not commutative.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Multiplication, QuaternionScalar)
|
||||||
|
{
|
||||||
|
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
float f = 2.0f;
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_MulQF(q, f);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 8.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_Mul(q, f);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 8.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Quat result = q * f;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 8.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Quat result = f * q;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 8.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
q *= f;
|
||||||
|
EXPECT_FLOAT_EQ(q.X, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q.Y, 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q.Z, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q.W, 8.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
85
test/categories/Projection.h
Normal file
85
test/categories/Projection.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#include "../HandmadeTest.h"
|
||||||
|
|
||||||
|
TEST(Projection, Orthographic)
|
||||||
|
{
|
||||||
|
#define ORTHO_BOUNDS -8.0f, 12.0f, 5.0f, 10.0f, 1.0f, 100.0f
|
||||||
|
|
||||||
|
// Right-handed
|
||||||
|
{
|
||||||
|
// Near and far distances correspond to negative Z, hence the Z coordinates here are negative.
|
||||||
|
HMM_Vec4 minCorner = HMM_V4(-8.0f, 5.0f, -1.0f, 1.0);
|
||||||
|
HMM_Vec4 maxCorner = HMM_V4(12.0f, 10.0f, -100.0f, 1.0);
|
||||||
|
|
||||||
|
// Z from -1 to 1 (GL convention)
|
||||||
|
{
|
||||||
|
HMM_Mat4 projection = HMM_Orthographic_RH_NO(ORTHO_BOUNDS);
|
||||||
|
EXPECT_V4_EQ(HMM_MulM4V4(projection, minCorner), HMM_V4(-1.0f, -1.0f, -1.0f, 1.0f));
|
||||||
|
EXPECT_V4_EQ(HMM_MulM4V4(projection, maxCorner), HMM_V4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Z from 0 to 1 (DX convention)
|
||||||
|
{
|
||||||
|
HMM_Mat4 projection = HMM_Orthographic_RH_ZO(ORTHO_BOUNDS);
|
||||||
|
EXPECT_V4_EQ(HMM_MulM4V4(projection, minCorner), HMM_V4(-1.0f, -1.0f, 0.0f, 1.0f));
|
||||||
|
EXPECT_V4_EQ(HMM_MulM4V4(projection, maxCorner), HMM_V4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Left-handed
|
||||||
|
{
|
||||||
|
// Near and far distances correspond to positive Z, hence the Z coordinates here are positive.
|
||||||
|
HMM_Vec4 minCorner = HMM_V4(-8.0f, 5.0f, 1.0f, 1.0);
|
||||||
|
HMM_Vec4 maxCorner = HMM_V4(12.0f, 10.0f, 100.0f, 1.0);
|
||||||
|
|
||||||
|
// Z from -1 to 1 (GL convention)
|
||||||
|
{
|
||||||
|
HMM_Mat4 projection = HMM_Orthographic_LH_NO(ORTHO_BOUNDS);
|
||||||
|
EXPECT_V4_EQ(HMM_MulM4V4(projection, minCorner), HMM_V4(-1.0f, -1.0f, -1.0f, 1.0f));
|
||||||
|
EXPECT_V4_EQ(HMM_MulM4V4(projection, maxCorner), HMM_V4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Z from 0 to 1 (DX convention)
|
||||||
|
{
|
||||||
|
HMM_Mat4 projection = HMM_Orthographic_LH_ZO(ORTHO_BOUNDS);
|
||||||
|
EXPECT_V4_EQ(HMM_MulM4V4(projection, minCorner), HMM_V4(-1.0f, -1.0f, 0.0f, 1.0f));
|
||||||
|
EXPECT_V4_EQ(HMM_MulM4V4(projection, maxCorner), HMM_V4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Projection, Perspective)
|
||||||
|
{
|
||||||
|
// Right-handed
|
||||||
|
{
|
||||||
|
// Z from -1 to 1 (GL convention)
|
||||||
|
{
|
||||||
|
HMM_Mat4 projection = HMM_Perspective_RH_NO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f);
|
||||||
|
HMM_Vec4 original = HMM_V4(5.0f, 5.0f, -1.0f, 1.0f);
|
||||||
|
EXPECT_V4_EQ(HMM_MulM4V4(projection, original), HMM_V4(2.5f, 5.0f, -1.0f, 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Z from 0 to 1 (DX convention)
|
||||||
|
{
|
||||||
|
HMM_Mat4 projection = HMM_Perspective_RH_ZO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f);
|
||||||
|
HMM_Vec4 original = HMM_V4(5.0f, 5.0f, -1.0f, 1.0f);
|
||||||
|
EXPECT_V4_EQ(HMM_MulM4V4(projection, original), HMM_V4(2.5f, 5.0f, 0.0f, 1.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Left-handed
|
||||||
|
{
|
||||||
|
// Z from -1 to 1 (GL convention)
|
||||||
|
{
|
||||||
|
HMM_Mat4 projection = HMM_Perspective_LH_NO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f);
|
||||||
|
HMM_Vec4 original = HMM_V4(5.0f, 5.0f, 1.0f, 1.0f);
|
||||||
|
EXPECT_V4_EQ(HMM_MulM4V4(projection, original), HMM_V4(2.5f, 5.0f, -1.0f, 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Z from 0 to 1 (DX convention)
|
||||||
|
{
|
||||||
|
HMM_Mat4 projection = HMM_Perspective_LH_ZO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f);
|
||||||
|
HMM_Vec4 original = HMM_V4(5.0f, 5.0f, 1.0f, 1.0f);
|
||||||
|
EXPECT_V4_EQ(HMM_MulM4V4(projection, original), HMM_V4(2.5f, 5.0f, 0.0f, 1.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
297
test/categories/QuaternionOps.h
Normal file
297
test/categories/QuaternionOps.h
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
#include "../HandmadeTest.h"
|
||||||
|
|
||||||
|
TEST(QuaternionOps, Inverse)
|
||||||
|
{
|
||||||
|
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
HMM_Quat inverse = HMM_InvQ(q1);
|
||||||
|
|
||||||
|
HMM_Quat result = HMM_MulQ(q1, inverse);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(QuaternionOps, Dot)
|
||||||
|
{
|
||||||
|
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
float result = HMM_DotQ(q1, q2);
|
||||||
|
EXPECT_FLOAT_EQ(result, 70.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
float result = HMM_Dot(q1, q2);
|
||||||
|
EXPECT_FLOAT_EQ(result, 70.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(QuaternionOps, Normalize)
|
||||||
|
{
|
||||||
|
HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_NormQ(q);
|
||||||
|
EXPECT_NEAR(result.X, 0.1825741858f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Y, 0.3651483717f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Z, 0.5477225575f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.W, 0.7302967433f, 0.001f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_Norm(q);
|
||||||
|
EXPECT_NEAR(result.X, 0.1825741858f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Y, 0.3651483717f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Z, 0.5477225575f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.W, 0.7302967433f, 0.001f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(QuaternionOps, NLerp)
|
||||||
|
{
|
||||||
|
HMM_Quat from = HMM_Q(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
HMM_Quat to = HMM_Q(0.5f, 0.5f, -0.5f, 0.5f);
|
||||||
|
|
||||||
|
HMM_Quat result = HMM_NLerp(from, 0.5f, to);
|
||||||
|
EXPECT_NEAR(result.X, 0.28867513f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Y, 0.28867513f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Z, -0.28867513f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.W, 0.86602540f, 0.001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(QuaternionOps, SLerp)
|
||||||
|
{
|
||||||
|
HMM_Quat from = HMM_Q(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
HMM_Quat to = HMM_Q(0.5f, 0.5f, -0.5f, 0.5f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_SLerp(from, 0.0f, to);
|
||||||
|
EXPECT_NEAR(result.X, 0.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Y, 0.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Z, 0.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.W, 1.0, 0.001f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_SLerp(from, 0.25f, to);
|
||||||
|
EXPECT_NEAR(result.X, 0.149429246f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Y, 0.149429246f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Z, -0.149429246f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.W, 0.965925812f, 0.001f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_SLerp(from, 0.5f, to);
|
||||||
|
EXPECT_NEAR(result.X, 0.28867513f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Y, 0.28867513f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Z, -0.28867513f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.W, 0.86602540f, 0.001f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_SLerp(from, 0.75f, to);
|
||||||
|
EXPECT_NEAR(result.X, 0.40824830f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Y, 0.40824830f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Z, -0.40824830f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.W, 0.70710676f, 0.001f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_SLerp(from, 1.0f, to);
|
||||||
|
EXPECT_NEAR(result.X, 0.5f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Y, 0.5f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Z, -0.5f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.W, 0.5f, 0.001f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(QuaternionOps, QuatToMat4)
|
||||||
|
{
|
||||||
|
const float abs_error = 0.001f;
|
||||||
|
|
||||||
|
HMM_Quat rot = HMM_Q(0.707107f, 0.0f, 0.0f, 0.707107f);
|
||||||
|
|
||||||
|
HMM_Mat4 result = HMM_QToM4(rot);
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.Elements[0][0], 1.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[0][1], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[0][2], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[0][3], 0.0f, abs_error);
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.Elements[1][0], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[1][1], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[1][2], 1.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[1][3], 0.0f, abs_error);
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.Elements[2][0], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[2][1], -1.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[2][2], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[2][3], 0.0f, abs_error);
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.Elements[3][0], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[3][1], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[3][2], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(QuaternionOps, Mat4ToQuat)
|
||||||
|
{
|
||||||
|
const float abs_error = 0.0001f;
|
||||||
|
|
||||||
|
// Rotate 90 degrees on the X axis
|
||||||
|
{
|
||||||
|
HMM_Mat4 m = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(1, 0, 0));
|
||||||
|
HMM_Quat result = HMM_M4ToQ_RH(m);
|
||||||
|
|
||||||
|
float cosf = 0.707107f; // cos(90/2 degrees)
|
||||||
|
float sinf = 0.707107f; // sin(90/2 degrees)
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.X, sinf, abs_error);
|
||||||
|
EXPECT_NEAR(result.Y, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Z, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate 90 degrees on the Y axis (axis not normalized, just for fun)
|
||||||
|
{
|
||||||
|
HMM_Mat4 m = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(0, 2, 0));
|
||||||
|
HMM_Quat result = HMM_M4ToQ_RH(m);
|
||||||
|
|
||||||
|
float cosf = 0.707107f; // cos(90/2 degrees)
|
||||||
|
float sinf = 0.707107f; // sin(90/2 degrees)
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.X, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Y, sinf, abs_error);
|
||||||
|
EXPECT_NEAR(result.Z, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate 90 degrees on the Z axis
|
||||||
|
{
|
||||||
|
HMM_Mat4 m = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(0, 0, 1));
|
||||||
|
HMM_Quat result = HMM_M4ToQ_RH(m);
|
||||||
|
|
||||||
|
float cosf = 0.707107f; // cos(90/2 degrees)
|
||||||
|
float sinf = 0.707107f; // sin(90/2 degrees)
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.X, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Y, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Z, sinf, abs_error);
|
||||||
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate 45 degrees on the X axis (this hits case 4)
|
||||||
|
{
|
||||||
|
HMM_Mat4 m = HMM_Rotate_RH(HMM_AngleDeg(45.0f), HMM_V3(1, 0, 0));
|
||||||
|
HMM_Quat result = HMM_M4ToQ_RH(m);
|
||||||
|
|
||||||
|
float cosf = 0.9238795325f; // cos(90/2 degrees)
|
||||||
|
float sinf = 0.3826834324f; // sin(90/2 degrees)
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.X, sinf, abs_error);
|
||||||
|
EXPECT_NEAR(result.Y, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Z, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE(lcf): Left-handed cases. Since both Rotate and M4ToQ are LH results should be
|
||||||
|
the same with no changes to input. */
|
||||||
|
// Rotate 90 degrees on the X axis
|
||||||
|
{
|
||||||
|
HMM_Mat4 m = HMM_Rotate_LH(HMM_AngleDeg(90.0f), HMM_V3(1, 0, 0));
|
||||||
|
HMM_Quat result = HMM_M4ToQ_LH(m);
|
||||||
|
|
||||||
|
float cosf = 0.707107f; // cos(90/2 degrees)
|
||||||
|
float sinf = 0.707107f; // sin(90/2 degrees)
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.X, sinf, abs_error);
|
||||||
|
EXPECT_NEAR(result.Y, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Z, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate 90 degrees on the Y axis (axis not normalized, just for fun)
|
||||||
|
{
|
||||||
|
HMM_Mat4 m = HMM_Rotate_LH(HMM_AngleDeg(90.0f), HMM_V3(0, 2, 0));
|
||||||
|
HMM_Quat result = HMM_M4ToQ_LH(m);
|
||||||
|
|
||||||
|
float cosf = 0.707107f; // cos(90/2 degrees)
|
||||||
|
float sinf = 0.707107f; // sin(90/2 degrees)
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.X, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Y, sinf, abs_error);
|
||||||
|
EXPECT_NEAR(result.Z, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate 90 degrees on the Z axis
|
||||||
|
{
|
||||||
|
HMM_Mat4 m = HMM_Rotate_LH(HMM_AngleDeg(90.0f), HMM_V3(0, 0, 1));
|
||||||
|
HMM_Quat result = HMM_M4ToQ_LH(m);
|
||||||
|
|
||||||
|
float cosf = 0.707107f; // cos(90/2 degrees)
|
||||||
|
float sinf = 0.707107f; // sin(90/2 degrees)
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.X, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Y, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Z, sinf, abs_error);
|
||||||
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate 45 degrees on the X axis (this hits case 4)
|
||||||
|
{
|
||||||
|
HMM_Mat4 m = HMM_Rotate_LH(HMM_AngleDeg(45.0f), HMM_V3(1, 0, 0));
|
||||||
|
HMM_Quat result = HMM_M4ToQ_LH(m);
|
||||||
|
|
||||||
|
float cosf = 0.9238795325f; // cos(90/2 degrees)
|
||||||
|
float sinf = 0.3826834324f; // sin(90/2 degrees)
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.X, sinf, abs_error);
|
||||||
|
EXPECT_NEAR(result.Y, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Z, 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(QuaternionOps, RotateVectorAxisAngle)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
HMM_Vec3 axis = HMM_V3(0.0f, 1.0f, 0.0f);
|
||||||
|
float angle = HMM_AngleTurn(1.0/4);
|
||||||
|
HMM_Vec3 result = HMM_RotateV3AxisAngle_LH(HMM_V3(1.0f, 0.0f, 0.0f), axis, angle);
|
||||||
|
EXPECT_NEAR(result.X, 0.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Y, 0.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Z, 1.0f, 0.001f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec3 axis = HMM_V3(1.0f, 0.0f, 0.0f);
|
||||||
|
float angle = HMM_AngleTurn(1.0/8);
|
||||||
|
HMM_Vec3 result = HMM_RotateV3AxisAngle_RH(HMM_V3(0.0f, 0.0f, 1.0f), axis, angle);
|
||||||
|
EXPECT_NEAR(result.X, 0.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Y, -0.707170f, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Z, 0.707170f, 0.001f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(QuaternionOps, QuatFromPairs)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
HMM_Vec3 n1 = HMM_V3(0.0f, 1.0f, 0.0f);
|
||||||
|
HMM_Vec3 n2 = HMM_V3(0.0f, 0.0f, 1.0f);
|
||||||
|
HMM_Quat q = HMM_QFromNormPair(n1, n2);
|
||||||
|
HMM_Vec3 result = HMM_RotateV3Q(n1, q);
|
||||||
|
EXPECT_NEAR(result.X, n2.X, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Y, n2.Y, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Z, n2.Z, 0.001f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec3 v1 = HMM_V3(2.0f, 2.0f, 2.0f);
|
||||||
|
HMM_Vec3 v2 = HMM_V3(3.0f, 0.0f, 0.0f);
|
||||||
|
HMM_Quat q = HMM_QFromVecPair(v1, v2);
|
||||||
|
HMM_Vec3 result = HMM_RotateV3Q(HMM_V3(0.0f, 1.0f, 0.0f), q);
|
||||||
|
EXPECT_NEAR(result.X, 0.577350, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Y, 0.788675, 0.001f);
|
||||||
|
EXPECT_NEAR(result.Z, -0.211325, 0.001f);
|
||||||
|
}
|
||||||
|
}
|
||||||
39
test/categories/SSE.h
Normal file
39
test/categories/SSE.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#include "../HandmadeTest.h"
|
||||||
|
|
||||||
|
#ifdef HANDMADE_MATH__USE_SSE
|
||||||
|
|
||||||
|
TEST(SSE, LinearCombine)
|
||||||
|
{
|
||||||
|
HMM_Mat4 MatrixOne = HMM_M4D(2.0f);
|
||||||
|
HMM_Mat4 MatrixTwo = HMM_M4D(4.0f);
|
||||||
|
HMM_Mat4 Result;
|
||||||
|
|
||||||
|
Result.Columns[0] = HMM_LinearCombineV4M4(MatrixOne.Columns[0], MatrixTwo);
|
||||||
|
Result.Columns[1] = HMM_LinearCombineV4M4(MatrixOne.Columns[1], MatrixTwo);
|
||||||
|
Result.Columns[2] = HMM_LinearCombineV4M4(MatrixOne.Columns[2], MatrixTwo);
|
||||||
|
Result.Columns[3] = HMM_LinearCombineV4M4(MatrixOne.Columns[3], MatrixTwo);
|
||||||
|
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][0], 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][1], 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][2], 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[0][3], 0.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][0], 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][1], 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][2], 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[1][3], 0.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[2][0], 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[2][1], 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[2][2], 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[2][3], 0.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[3][0], 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[3][1], 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[3][2], 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Elements[3][3], 8.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
53
test/categories/ScalarMath.h
Normal file
53
test/categories/ScalarMath.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#include "../HandmadeTest.h"
|
||||||
|
|
||||||
|
TEST(ScalarMath, Trigonometry)
|
||||||
|
{
|
||||||
|
// We have to be a little looser with our equality constraint
|
||||||
|
// because of floating-point precision issues.
|
||||||
|
const float trigAbsError = 0.0001f;
|
||||||
|
|
||||||
|
EXPECT_NEAR(HMM_SinF(0.0f), 0.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_SinF(HMM_PI32 / 2), 1.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_SinF(HMM_PI32), 0.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_SinF(3 * HMM_PI32 / 2), -1.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_SinF(-HMM_PI32 / 2), -1.0f, trigAbsError);
|
||||||
|
|
||||||
|
EXPECT_NEAR(HMM_CosF(0.0f), 1.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_CosF(HMM_PI32 / 2), 0.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_CosF(HMM_PI32), -1.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_CosF(3 * HMM_PI32 / 2), 0.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_CosF(-HMM_PI32), -1.0f, trigAbsError);
|
||||||
|
|
||||||
|
EXPECT_NEAR(HMM_TanF(0.0f), 0.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_TanF(HMM_PI32 / 4), 1.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_TanF(3 * HMM_PI32 / 4), -1.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_TanF(HMM_PI32), 0.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_TanF(-HMM_PI32 / 4), -1.0f, trigAbsError);
|
||||||
|
|
||||||
|
// This isn't the most rigorous because we're really just sanity-
|
||||||
|
// checking that things work by default.
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ScalarMath, SquareRoot)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(HMM_SqrtF(16.0f), 4.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ScalarMath, RSquareRootF)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(HMM_InvSqrtF(10.0f), 0.31616211f, 0.0001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ScalarMath, Lerp)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.0f, 2.0f), -2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.5f, 2.0f), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 1.0f, 2.0f), 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ScalarMath, Clamp)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, 0.0f, 2.0f), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, -3.0f, 2.0f), -2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, 3.0f, 2.0f), 2.0f);
|
||||||
|
}
|
||||||
357
test/categories/Subtraction.h
Normal file
357
test/categories/Subtraction.h
Normal file
@@ -0,0 +1,357 @@
|
|||||||
|
#include "../HandmadeTest.h"
|
||||||
|
|
||||||
|
TEST(Subtraction, Vec2)
|
||||||
|
{
|
||||||
|
HMM_Vec2 v2_1 = HMM_V2(1.0f, 2.0f);
|
||||||
|
HMM_Vec2 v2_2 = HMM_V2(3.0f, 4.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_SubV2(v2_1, v2_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, -2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, -2.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_Sub(v2_1, v2_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, -2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, -2.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = v2_1 - v2_2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, -2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, -2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v2_1 -= v2_2;
|
||||||
|
EXPECT_FLOAT_EQ(v2_1.X, -2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v2_1.Y, -2.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Subtraction, Vec3)
|
||||||
|
{
|
||||||
|
HMM_Vec3 v3_1 = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||||
|
HMM_Vec3 v3_2 = HMM_V3(4.0f, 5.0f, 6.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_SubV3(v3_1, v3_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, -3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, -3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, -3.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_Sub(v3_1, v3_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, -3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, -3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, -3.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = v3_1 - v3_2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, -3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, -3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, -3.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3_1 -= v3_2;
|
||||||
|
EXPECT_FLOAT_EQ(v3_1.X, -3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3_1.Y, -3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v3_1.Z, -3.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Subtraction, Vec4)
|
||||||
|
{
|
||||||
|
HMM_Vec4 v4_1 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
HMM_Vec4 v4_2 = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_SubV4(v4_1, v4_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, -4.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_Sub(v4_1, v4_2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, -4.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = v4_1 - v4_2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, -4.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
v4_1 -= v4_2;
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.X, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.Y, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.Z, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(v4_1.W, -4.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Subtraction, Mat2)
|
||||||
|
{
|
||||||
|
HMM_Mat2 a = HMM_M2();
|
||||||
|
HMM_Mat2 b = HMM_M2();
|
||||||
|
|
||||||
|
int Counter = 1;
|
||||||
|
for (int Column = 0; Column < 2; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 2; ++Row)
|
||||||
|
{
|
||||||
|
a.Elements[Column][Row] = Counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int Column = 0; Column < 2; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 2; ++Row)
|
||||||
|
{
|
||||||
|
b.Elements[Column][Row] = Counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = HMM_SubM2(b,a);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = HMM_Sub(b,a);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat2 result = b - a;
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
b -= a;
|
||||||
|
EXPECT_FLOAT_EQ(b.Elements[0][0], 4.0);
|
||||||
|
EXPECT_FLOAT_EQ(b.Elements[0][1], 4.0);
|
||||||
|
EXPECT_FLOAT_EQ(b.Elements[1][0], 4.0);
|
||||||
|
EXPECT_FLOAT_EQ(b.Elements[1][1], 4.0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Subtraction, Mat3)
|
||||||
|
{
|
||||||
|
HMM_Mat3 a = HMM_M3();
|
||||||
|
HMM_Mat3 b = HMM_M3();
|
||||||
|
|
||||||
|
int Counter = 1;
|
||||||
|
for (int Column = 0; Column < 3; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 3; ++Row)
|
||||||
|
{
|
||||||
|
a.Elements[Column][Row] = Counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int Column = 0; Column < 3; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 3; ++Row)
|
||||||
|
{
|
||||||
|
b.Elements[Column][Row] = Counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = HMM_SubM3(b,a);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 9.0);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat3 result = HMM_Sub(b,a);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 9.0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
b -= a;
|
||||||
|
EXPECT_FLOAT_EQ(b.Elements[0][0], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(b.Elements[0][1], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(b.Elements[0][2], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(b.Elements[1][0], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(b.Elements[1][1], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(b.Elements[1][2], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(b.Elements[2][0], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(b.Elements[2][1], 9.0);
|
||||||
|
EXPECT_FLOAT_EQ(b.Elements[2][2], 9.0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Subtraction, Mat4)
|
||||||
|
{
|
||||||
|
HMM_Mat4 m4_1 = HMM_M4(); // will have 1 - 16
|
||||||
|
HMM_Mat4 m4_2 = HMM_M4(); // will have 17 - 32
|
||||||
|
|
||||||
|
// Fill the matrices
|
||||||
|
int Counter = 1;
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
m4_1.Elements[Column][Row] = Counter;
|
||||||
|
++Counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
m4_2.Elements[Column][Row] = Counter;
|
||||||
|
++Counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the results
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_SubM4(m4_1, m4_2);
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[Column][Row], -16.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_Sub(m4_1, m4_2);
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[Column][Row], -16.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = m4_1 - m4_2;
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[Column][Row], -16.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m4_1 -= m4_2;
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
EXPECT_FLOAT_EQ(m4_1.Elements[Column][Row], -16.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Subtraction, Quaternion)
|
||||||
|
{
|
||||||
|
HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_SubQ(q1, q2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, -4.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Quat result = HMM_Sub(q1, q2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, -4.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
{
|
||||||
|
HMM_Quat result = q1 - q2;
|
||||||
|
EXPECT_FLOAT_EQ(result.X, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, -4.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
q1 -= q2;
|
||||||
|
EXPECT_FLOAT_EQ(q1.X, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q1.Y, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q1.Z, -4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(q1.W, -4.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
TEST(UnaryMinus, Vec2)
|
||||||
|
{
|
||||||
|
HMM_Vec2 VectorOne = {1.0f, 2.0f};
|
||||||
|
HMM_Vec2 Result = -VectorOne;
|
||||||
|
EXPECT_FLOAT_EQ(Result.X, -1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(UnaryMinus, Vec3)
|
||||||
|
{
|
||||||
|
HMM_Vec3 VectorOne = {1.0f, 2.0f, 3.0f};
|
||||||
|
HMM_Vec3 Result = -VectorOne;
|
||||||
|
EXPECT_FLOAT_EQ(Result.X, -1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Z, -3.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(UnaryMinus, Vec4)
|
||||||
|
{
|
||||||
|
HMM_Vec4 VectorOne = {1.0f, 2.0f, 3.0f, 4.0f};
|
||||||
|
HMM_Vec4 Result = -VectorOne;
|
||||||
|
EXPECT_FLOAT_EQ(Result.X, -1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.Z, -3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(Result.W, -4.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
133
test/categories/Transformation.h
Normal file
133
test/categories/Transformation.h
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
#include "../HandmadeTest.h"
|
||||||
|
|
||||||
|
TEST(Transformations, Translate)
|
||||||
|
{
|
||||||
|
HMM_Mat4 translate = HMM_Translate(HMM_V3(1.0f, -3.0f, 6.0f));
|
||||||
|
|
||||||
|
HMM_Vec3 original = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||||
|
HMM_Vec4 translated = HMM_MulM4V4(translate, HMM_V4V(original, 1));
|
||||||
|
|
||||||
|
EXPECT_NEAR(translated.X, 2.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(translated.Y, -1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(translated.Z, 9.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(translated.W, 1.0f, 0.001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Transformations, Rotate)
|
||||||
|
{
|
||||||
|
HMM_Vec3 original = HMM_V3(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
HMM_Mat4 rotateX = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(1, 0, 0));
|
||||||
|
HMM_Vec4 rotatedX = HMM_MulM4V4(rotateX, HMM_V4V(original, 1));
|
||||||
|
EXPECT_NEAR(rotatedX.X, 1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(rotatedX.Y, -1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(rotatedX.Z, 1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(rotatedX.W, 1.0f, 0.001f);
|
||||||
|
|
||||||
|
HMM_Mat4 rotateY = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(0, 1, 0));
|
||||||
|
HMM_Vec4 rotatedY = HMM_MulM4V4(rotateY, HMM_V4V(original, 1));
|
||||||
|
EXPECT_NEAR(rotatedY.X, 1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(rotatedY.Y, 1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(rotatedY.Z, -1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(rotatedY.W, 1.0f, 0.001f);
|
||||||
|
|
||||||
|
HMM_Mat4 rotateZ = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(0, 0, 1));
|
||||||
|
HMM_Vec4 rotatedZ = HMM_MulM4V4(rotateZ, HMM_V4V(original, 1));
|
||||||
|
EXPECT_NEAR(rotatedZ.X, -1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(rotatedZ.Y, 1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(rotatedZ.Z, 1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(rotatedZ.W, 1.0f, 0.001f);
|
||||||
|
|
||||||
|
HMM_Mat4 rotateZLH = HMM_Rotate_LH(HMM_AngleDeg(90.0f), HMM_V3(0, 0, 1));
|
||||||
|
HMM_Vec4 rotatedZLH = HMM_MulM4V4(rotateZLH, HMM_V4V(original, 1));
|
||||||
|
EXPECT_NEAR(rotatedZLH.X, 1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(rotatedZLH.Y, -1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(rotatedZLH.Z, 1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(rotatedZLH.W, 1.0f, 0.001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Transformations, Scale)
|
||||||
|
{
|
||||||
|
HMM_Mat4 scale = HMM_Scale(HMM_V3(2.0f, -3.0f, 0.5f));
|
||||||
|
|
||||||
|
HMM_Vec3 original = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||||
|
HMM_Vec4 scaled = HMM_MulM4V4(scale, HMM_V4V(original, 1));
|
||||||
|
|
||||||
|
EXPECT_NEAR(scaled.X, 2.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(scaled.Y, -6.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(scaled.Z, 1.5f, 0.001f);
|
||||||
|
EXPECT_NEAR(scaled.W, 1.0f, 0.001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Transformations, LookAt)
|
||||||
|
{
|
||||||
|
const float abs_error = 0.001f;
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_LookAt_RH(HMM_V3(1.0f, 0.0f, 0.0f), HMM_V3(0.0f, 2.0f, 1.0f), HMM_V3(2.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.Elements[0][0], 0.169031f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[0][1], 0.897085f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[0][2], 0.408248f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[0][3], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[1][0], 0.507093f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[1][1], 0.276026f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[1][2], -0.816497f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[1][3], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[2][0], -0.845154f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[2][1], 0.345033f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[2][2], -0.408248f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[2][3], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[3][0], -0.169031f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[3][1], -0.897085f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[3][2], -0.408248f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Mat4 result = HMM_LookAt_LH(HMM_V3(1.0f, 0.0f, 0.0f), HMM_V3(0.0f, 2.0f, 1.0f), HMM_V3(2.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
|
EXPECT_NEAR(result.Elements[0][0], -0.169031f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[0][1], 0.897085f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[0][2], -0.408248f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[0][3], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[1][0], -0.507093f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[1][1], 0.276026f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[1][2], 0.816497f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[1][3], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[2][0], 0.845154f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[2][1], 0.345033f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[2][2], 0.408248f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[2][3], 0.0f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[3][0], 0.169031f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[3][1], -0.897085f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[3][2], 0.408248f, abs_error);
|
||||||
|
EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Transformations, RotateV2)
|
||||||
|
{
|
||||||
|
HMM_Vec2 v2 = HMM_V2(1, 2);
|
||||||
|
|
||||||
|
float epsilon = 0.000001f;
|
||||||
|
{
|
||||||
|
HMM_Vec2 res = HMM_RotateV2(v2, HMM_AngleDeg(90));
|
||||||
|
EXPECT_NEAR(res.X, -2.0f, epsilon);
|
||||||
|
EXPECT_NEAR(res.Y, 1.0f, epsilon);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec2 res = HMM_RotateV2(v2, HMM_AngleDeg(180));
|
||||||
|
EXPECT_NEAR(res.X, -1.0f, epsilon);
|
||||||
|
EXPECT_NEAR(res.Y, -2.0f, epsilon);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec2 res = HMM_RotateV2(v2, HMM_AngleDeg(270));
|
||||||
|
EXPECT_NEAR(res.X, 2.0f, epsilon);
|
||||||
|
EXPECT_NEAR(res.Y, -1.0f, epsilon);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec2 res = HMM_RotateV2(v2, HMM_AngleDeg(360));
|
||||||
|
EXPECT_NEAR(res.X, 1.0f, epsilon);
|
||||||
|
EXPECT_NEAR(res.Y, 2.0f, epsilon);
|
||||||
|
}
|
||||||
|
}
|
||||||
282
test/categories/VectorOps.h
Normal file
282
test/categories/VectorOps.h
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
#include "../HandmadeTest.h"
|
||||||
|
|
||||||
|
TEST(VectorOps, LengthSquared)
|
||||||
|
{
|
||||||
|
HMM_Vec2 v2 = HMM_V2(1.0f, -2.0f);
|
||||||
|
HMM_Vec3 v3 = HMM_V3(1.0f, -2.0f, 3.0f);
|
||||||
|
HMM_Vec4 v4 = HMM_V4(1.0f, -2.0f, 3.0f, 1.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(HMM_LenSqrV2(v2), 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(HMM_LenSqrV3(v3), 14.0f);
|
||||||
|
EXPECT_FLOAT_EQ(HMM_LenSqrV4(v4), 15.0f);
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
EXPECT_FLOAT_EQ(HMM_LenSqr(v2), 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(HMM_LenSqr(v3), 14.0f);
|
||||||
|
EXPECT_FLOAT_EQ(HMM_LenSqr(v4), 15.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VectorOps, Length)
|
||||||
|
{
|
||||||
|
HMM_Vec2 v2 = HMM_V2(1.0f, -9.0f);
|
||||||
|
HMM_Vec3 v3 = HMM_V3(2.0f, -3.0f, 6.0f);
|
||||||
|
HMM_Vec4 v4 = HMM_V4(2.0f, -3.0f, 6.0f, 12.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(HMM_LenV2(v2), 9.0553856f);
|
||||||
|
EXPECT_FLOAT_EQ(HMM_LenV3(v3), 7.0f);
|
||||||
|
EXPECT_FLOAT_EQ(HMM_LenV4(v4), 13.892444f);
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
EXPECT_FLOAT_EQ(HMM_Len(v2), 9.0553856f);
|
||||||
|
EXPECT_FLOAT_EQ(HMM_Len(v3), 7.0f);
|
||||||
|
EXPECT_FLOAT_EQ(HMM_Len(v4), 13.892444f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VectorOps, Normalize)
|
||||||
|
{
|
||||||
|
HMM_Vec2 v2 = HMM_V2(1.0f, -2.0f);
|
||||||
|
HMM_Vec3 v3 = HMM_V3(1.0f, -2.0f, 3.0f);
|
||||||
|
HMM_Vec4 v4 = HMM_V4(1.0f, -2.0f, 3.0f, -1.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_NormV2(v2);
|
||||||
|
EXPECT_NEAR(HMM_LenV2(result), 1.0f, 0.001f);
|
||||||
|
EXPECT_GT(result.X, 0.0f);
|
||||||
|
EXPECT_LT(result.Y, 0.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_NormV3(v3);
|
||||||
|
EXPECT_NEAR(HMM_LenV3(result), 1.0f, 0.001f);
|
||||||
|
EXPECT_GT(result.X, 0.0f);
|
||||||
|
EXPECT_LT(result.Y, 0.0f);
|
||||||
|
EXPECT_GT(result.Z, 0.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_NormV4(v4);
|
||||||
|
EXPECT_NEAR(HMM_LenV4(result), 1.0f, 0.001f);
|
||||||
|
EXPECT_GT(result.X, 0.0f);
|
||||||
|
EXPECT_LT(result.Y, 0.0f);
|
||||||
|
EXPECT_GT(result.Z, 0.0f);
|
||||||
|
EXPECT_LT(result.W, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_Norm(v2);
|
||||||
|
EXPECT_NEAR(HMM_LenV2(result), 1.0f, 0.001f);
|
||||||
|
EXPECT_GT(result.X, 0.0f);
|
||||||
|
EXPECT_LT(result.Y, 0.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_Norm(v3);
|
||||||
|
EXPECT_NEAR(HMM_LenV3(result), 1.0f, 0.001f);
|
||||||
|
EXPECT_GT(result.X, 0.0f);
|
||||||
|
EXPECT_LT(result.Y, 0.0f);
|
||||||
|
EXPECT_GT(result.Z, 0.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_Norm(v4);
|
||||||
|
EXPECT_NEAR(HMM_LenV4(result), 1.0f, 0.001f);
|
||||||
|
EXPECT_GT(result.X, 0.0f);
|
||||||
|
EXPECT_LT(result.Y, 0.0f);
|
||||||
|
EXPECT_GT(result.Z, 0.0f);
|
||||||
|
EXPECT_LT(result.W, 0.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VectorOps, NormalizeZero)
|
||||||
|
{
|
||||||
|
HMM_Vec2 v2 = HMM_V2(0.0f, 0.0f);
|
||||||
|
HMM_Vec3 v3 = HMM_V3(0.0f, 0.0f, 0.0f);
|
||||||
|
HMM_Vec4 v4 = HMM_V4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_NormV2(v2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_NormV3(v3);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 0.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_NormV4(v4);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_Norm(v2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_Norm(v3);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 0.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_Norm(v4);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 0.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VectorOps, Cross)
|
||||||
|
{
|
||||||
|
HMM_Vec3 v1 = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||||
|
HMM_Vec3 v2 = HMM_V3(4.0f, 5.0f, 6.0f);
|
||||||
|
|
||||||
|
HMM_Vec3 result = HMM_Cross(v1, v2);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(result.X, -3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, -3.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VectorOps, DotVec2)
|
||||||
|
{
|
||||||
|
HMM_Vec2 v1 = HMM_V2(1.0f, 2.0f);
|
||||||
|
HMM_Vec2 v2 = HMM_V2(3.0f, 4.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(HMM_DotV2(v1, v2), 11.0f);
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 11.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VectorOps, DotVec3)
|
||||||
|
{
|
||||||
|
HMM_Vec3 v1 = HMM_V3(1.0f, 2.0f, 3.0f);
|
||||||
|
HMM_Vec3 v2 = HMM_V3(4.0f, 5.0f, 6.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(HMM_DotV3(v1, v2), 32.0f);
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 32.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VectorOps, DotVec4)
|
||||||
|
{
|
||||||
|
HMM_Vec4 v1 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
HMM_Vec4 v2 = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(HMM_DotV4(v1, v2), 70.0f);
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 70.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VectorOps, LerpV2)
|
||||||
|
{
|
||||||
|
HMM_Vec2 v1 = HMM_V2(1.0f, 0.0f);
|
||||||
|
HMM_Vec2 v2 = HMM_V2(0.0f, 1.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_LerpV2(v1, 0.5, v2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.5f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec2 result = HMM_Lerp(v1, 0.5, v2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 0.5f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VectorOps, LerpV3)
|
||||||
|
{
|
||||||
|
HMM_Vec3 v1 = HMM_V3(1.0f, 1.0f, 0.0f);
|
||||||
|
HMM_Vec3 v2 = HMM_V3(0.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_LerpV3(v1, 0.5, v2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 0.5f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec3 result = HMM_Lerp(v1, 0.5, v2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 0.5f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VectorOps, LerpV4)
|
||||||
|
{
|
||||||
|
HMM_Vec4 v1 = HMM_V4(1.0f, 1.0f, 0.0f, 1.0f);
|
||||||
|
HMM_Vec4 v2 = HMM_V4(0.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_LerpV4(v1, 0.5, v2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 1.0f);
|
||||||
|
}
|
||||||
|
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
|
||||||
|
{
|
||||||
|
HMM_Vec4 result = HMM_Lerp(v1, 0.5, v2);
|
||||||
|
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Z, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(result.W, 1.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MatrixOps tests
|
||||||
|
*/
|
||||||
|
|
||||||
|
TEST(MatrixOps, TransposeM4)
|
||||||
|
{
|
||||||
|
HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
|
||||||
|
|
||||||
|
// Fill the matrix
|
||||||
|
int Counter = 1;
|
||||||
|
for (int Column = 0; Column < 4; ++Column)
|
||||||
|
{
|
||||||
|
for (int Row = 0; Row < 4; ++Row)
|
||||||
|
{
|
||||||
|
m4.Elements[Column][Row] = Counter;
|
||||||
|
++Counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the matrix
|
||||||
|
HMM_Mat4 result = HMM_TransposeM4(m4);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][0], 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][1], 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[0][3], 13.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][0], 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][1], 6.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][2], 10.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[1][3], 14.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][0], 3.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][1], 7.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][2], 11.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[2][3], 15.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][0], 4.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][1], 8.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][2], 12.0f);
|
||||||
|
EXPECT_FLOAT_EQ(result.Elements[3][3], 16.0f);
|
||||||
|
}
|
||||||
1944
test/hmm_test.c
1944
test/hmm_test.c
File diff suppressed because it is too large
Load Diff
21
test/hmm_test.h
Normal file
21
test/hmm_test.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#include <float.h>
|
||||||
|
|
||||||
|
#define HANDMADE_TEST_IMPLEMENTATION
|
||||||
|
#include "HandmadeTest.h"
|
||||||
|
|
||||||
|
#undef COVERAGE // Make sure we don't double-define initializers from the header part
|
||||||
|
#include "../HandmadeMath.h"
|
||||||
|
|
||||||
|
#include "categories/ScalarMath.h"
|
||||||
|
#include "categories/Initialization.h"
|
||||||
|
#include "categories/VectorOps.h"
|
||||||
|
#include "categories/MatrixOps.h"
|
||||||
|
#include "categories/QuaternionOps.h"
|
||||||
|
#include "categories/Addition.h"
|
||||||
|
#include "categories/Subtraction.h"
|
||||||
|
#include "categories/Multiplication.h"
|
||||||
|
#include "categories/Division.h"
|
||||||
|
#include "categories/Equality.h"
|
||||||
|
#include "categories/Projection.h"
|
||||||
|
#include "categories/Transformation.h"
|
||||||
|
#include "categories/SSE.h"
|
||||||
29
test/initializer.h
Normal file
29
test/initializer.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// Initializer/finalizer sample for MSVC and GCC/Clang.
|
||||||
|
// 2010-2016 Joe Lowe. Released into the public domain.
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define _INITIALIZER_T(f) f##_t_
|
||||||
|
#define _INITIALIZER_U(f) f##_
|
||||||
|
#define INITIALIZER(f) \
|
||||||
|
static void f(void); \
|
||||||
|
struct _INITIALIZER_T(f) { _INITIALIZER_T(f)(void) { f(); } }; static _INITIALIZER_T(f) _INITIALIZER_U(f); \
|
||||||
|
static void f(void)
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#pragma section(".CRT$XCU",read)
|
||||||
|
#define INITIALIZER2_(f,p) \
|
||||||
|
static void f(void); \
|
||||||
|
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
|
||||||
|
__pragma(comment(linker,"/include:" p #f "_")) \
|
||||||
|
static void f(void)
|
||||||
|
#ifdef _WIN64
|
||||||
|
#define INITIALIZER(f) INITIALIZER2_(f,"")
|
||||||
|
#else
|
||||||
|
#define INITIALIZER(f) INITIALIZER2_(f,"_")
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define INITIALIZER(f) \
|
||||||
|
static void f(void) __attribute__((constructor)); \
|
||||||
|
static void f(void)
|
||||||
|
#endif
|
||||||
27
test/run_test_clang.bat
Normal file
27
test/run_test_clang.bat
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
if not exist "build" mkdir build
|
||||||
|
pushd build
|
||||||
|
|
||||||
|
clang-cl /std:c11 /Fehmm_test_c11.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
|
||||||
|
hmm_test_c11 || exit /b 1
|
||||||
|
|
||||||
|
clang-cl /std:c11 /Fehmm_test_c11_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
|
||||||
|
hmm_test_c11_no_simd || exit /b 1
|
||||||
|
|
||||||
|
clang-cl /std:c17 /Fehmm_test_c17.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
|
||||||
|
hmm_test_c17 || exit /b 1
|
||||||
|
|
||||||
|
clang-cl /std:c++14 /Fehmm_test_cpp14.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
|
||||||
|
hmm_test_cpp14 || exit /b 1
|
||||||
|
|
||||||
|
clang-cl /std:c++14 /Fehmm_test_cpp14_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
|
||||||
|
hmm_test_cpp14_no_simd || exit /b 1
|
||||||
|
|
||||||
|
clang-cl /std:c++17 /Fehmm_test_cpp17.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
|
||||||
|
hmm_test_cpp17 || exit /b 1
|
||||||
|
|
||||||
|
clang-cl /std:c++20 /Fehmm_test_cpp20.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
|
||||||
|
hmm_test_cpp20 || exit /b 1
|
||||||
|
|
||||||
|
popd
|
||||||
32
test/run_test_msvc.bat
Normal file
32
test/run_test_msvc.bat
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
where /q cl
|
||||||
|
if ERRORLEVEL 1 (
|
||||||
|
for /f "delims=" %%a in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -find VC\Auxiliary\Build\vcvarsall.bat') do (%%a x64)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not exist "build" mkdir build
|
||||||
|
pushd build
|
||||||
|
|
||||||
|
cl /std:c11 /Fehmm_test_c11.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
|
||||||
|
hmm_test_c11 || exit /b 1
|
||||||
|
|
||||||
|
cl /std:c11 /Fehmm_test_c11_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
|
||||||
|
hmm_test_c11_no_simd || exit /b 1
|
||||||
|
|
||||||
|
cl /std:c17 /Fehmm_test_c17.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
|
||||||
|
hmm_test_c17 || exit /b 1
|
||||||
|
|
||||||
|
cl /std:c++14 /Fehmm_test_cpp14.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
|
||||||
|
hmm_test_cpp14 || exit /b 1
|
||||||
|
|
||||||
|
cl /std:c++14 /Fehmm_test_cpp14_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
|
||||||
|
hmm_test_cpp14_no_simd || exit /b 1
|
||||||
|
|
||||||
|
cl /std:c++17 /Fehmm_test_cpp17.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
|
||||||
|
hmm_test_cpp17 || exit /b 1
|
||||||
|
|
||||||
|
cl /std:c++20 /Fehmm_test_cpp20.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
|
||||||
|
hmm_test_cpp20 || exit /b 1
|
||||||
|
|
||||||
|
popd
|
||||||
24
update/README.md
Normal file
24
update/README.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Handmade Math 2.0 Update Tool
|
||||||
|
|
||||||
|
Due to the large number of breaking naming changes in Handmade Math 2, we provide a small Python script to update your programs automatically. It can run on individual files or on all files in a directory (recursively).
|
||||||
|
|
||||||
|
**Warning!** This tool is not very smart! Please ensure that your work is committed and backed up, in case you have to revert this tool's changes.
|
||||||
|
|
||||||
|
```
|
||||||
|
# see usage info and options
|
||||||
|
> python3 update_hmm.py -h
|
||||||
|
usage: update_hmm [-h] [--exts .foo [.foo ...]] filename [filename ...]
|
||||||
|
...
|
||||||
|
|
||||||
|
# run on individual files
|
||||||
|
> python3 update_hmm.py MyPlatformLayer.c MyPlatformLayer.h
|
||||||
|
Updating: MyPlatformLayer.c
|
||||||
|
Updating: MyPlatformLayer.h
|
||||||
|
Updated 2 files with 0 warnings.
|
||||||
|
|
||||||
|
# run on a whole directory
|
||||||
|
> python3 update_hmm.py projects/MyCoolGame
|
||||||
|
Updating: projects/MyCoolGame/src/MyPlatformLayer.c
|
||||||
|
Updating: projects/MyCoolGame/include/MyPlatformLayer.h
|
||||||
|
...
|
||||||
|
```
|
||||||
166
update/update_hmm.py
Executable file
166
update/update_hmm.py
Executable file
@@ -0,0 +1,166 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
typeReplacements = [
|
||||||
|
('hmm_', 'HMM_'),
|
||||||
|
|
||||||
|
('vec', 'Vec'),
|
||||||
|
('mat', 'Mat'),
|
||||||
|
('quaternion', 'Quaternion'),
|
||||||
|
('bool', 'Bool'),
|
||||||
|
('.InternalElementsSSE', '.SSE'),
|
||||||
|
]
|
||||||
|
|
||||||
|
funcReplacements = [
|
||||||
|
('HMM_', 'HMM_'),
|
||||||
|
|
||||||
|
('Vec', 'V'),
|
||||||
|
('Mat', 'M'),
|
||||||
|
('Quaternion', 'Q'),
|
||||||
|
('Equals', 'Eq'),
|
||||||
|
('Subtract', 'Sub'),
|
||||||
|
('Multiply', 'Mul'),
|
||||||
|
('Divide', 'Div'),
|
||||||
|
('Inverse', 'Inv'),
|
||||||
|
('RSquareRoot', 'InvSqrt'),
|
||||||
|
('SquareRoot', 'Sqrt'),
|
||||||
|
('Squared', 'Sqr'),
|
||||||
|
('Length', 'Len'),
|
||||||
|
|
||||||
|
('Slerp', 'SLerp'),
|
||||||
|
('By', ''),
|
||||||
|
('LinearCombineSSE', 'LinearCombineV4M4'),
|
||||||
|
('Transpose', 'TransposeM4'),
|
||||||
|
('Fast', ''), # TODO(port): emit warning, lower precision
|
||||||
|
('Normalize', 'Norm'),
|
||||||
|
('ToRadians', 'ToRad')
|
||||||
|
]
|
||||||
|
|
||||||
|
handedFuncs = [
|
||||||
|
'Perspective',
|
||||||
|
'Rotate',
|
||||||
|
'Orthographic',
|
||||||
|
'LookAt',
|
||||||
|
'FromAxisAngle',
|
||||||
|
'ToQuaternion',
|
||||||
|
]
|
||||||
|
|
||||||
|
projectionFuncs = [
|
||||||
|
'Perspective',
|
||||||
|
'Orthographic',
|
||||||
|
]
|
||||||
|
|
||||||
|
numFiles = 0
|
||||||
|
numWarnings = 0
|
||||||
|
|
||||||
|
def printWarning(msg):
|
||||||
|
global numWarnings
|
||||||
|
numWarnings += 1
|
||||||
|
print('WARNING: {}'.format(msg))
|
||||||
|
|
||||||
|
def updateFile(filename):
|
||||||
|
global numFiles
|
||||||
|
print('Updating: {}'.format(filename))
|
||||||
|
numFiles += 1
|
||||||
|
result = ''
|
||||||
|
with open(filename, 'r', newline='') as f:
|
||||||
|
for lineNo, line in enumerate(f):
|
||||||
|
updatedLine = line
|
||||||
|
|
||||||
|
def printLineWarning(msg):
|
||||||
|
printWarning(' Line {}: {}'.format(lineNo + 1, msg))
|
||||||
|
|
||||||
|
def replaceName(m):
|
||||||
|
name = m.group()
|
||||||
|
if name.startswith('hmm_'):
|
||||||
|
# do type replacements
|
||||||
|
for before, after in typeReplacements:
|
||||||
|
if before not in name:
|
||||||
|
continue
|
||||||
|
name = name.replace(before, after)
|
||||||
|
else:
|
||||||
|
# do func replacements
|
||||||
|
for before, after in funcReplacements:
|
||||||
|
if before not in name:
|
||||||
|
continue
|
||||||
|
name = name.replace(before, after)
|
||||||
|
|
||||||
|
if after == 'LinearCombineV4M4':
|
||||||
|
printLineWarning('HMM_LinearCombineSSE is now HMM_LinearCombineV4M4, and will now use a fallback method when SSE is not available. You no longer need to check for the availability of SSE.')
|
||||||
|
if after == 'V' or after == 'M':
|
||||||
|
# uppercase the modifier, if any
|
||||||
|
name = re.sub(
|
||||||
|
r'[VM]\d[ivfd]?',
|
||||||
|
lambda m: m.group().upper(),
|
||||||
|
name
|
||||||
|
)
|
||||||
|
# and also nuke the integer constructors
|
||||||
|
vecIntMatch = re.search(r'(V\d)I', name)
|
||||||
|
if vecIntMatch:
|
||||||
|
name = name.replace(vecIntMatch.group(), vecIntMatch.group(1))
|
||||||
|
|
||||||
|
# add handedness / NDC modifiers
|
||||||
|
if not any(x in name for x in ['RH', 'LH', 'NO', 'ZO']):
|
||||||
|
for handedFunc in handedFuncs:
|
||||||
|
suffixed = handedFunc + '_RH'
|
||||||
|
if handedFunc in projectionFuncs:
|
||||||
|
suffixed += '_NO'
|
||||||
|
name = name.replace(handedFunc, suffixed)
|
||||||
|
return name
|
||||||
|
|
||||||
|
def wrapDegrees(m):
|
||||||
|
name = m.group('name')
|
||||||
|
arg = m.group('arg')
|
||||||
|
if '(' in arg:
|
||||||
|
# all bets are off, don't wrap the argument
|
||||||
|
printLineWarning('{} now takes radians, but we were unable to automatically wrap the first argument with HMM_AngleDeg().'.format(name))
|
||||||
|
return m.group()
|
||||||
|
return '{}(HMM_AngleDeg({}),'.format(name, arg)
|
||||||
|
|
||||||
|
updatedLine = re.sub(r'(hmm_|HMM_)\w+', replaceName, updatedLine)
|
||||||
|
updatedLine = re.sub(r'(?P<name>HMM_Perspective_RH_NO|HMM_Rotate_RH)\((?P<arg>.*?),', wrapDegrees, updatedLine)
|
||||||
|
|
||||||
|
result += updatedLine
|
||||||
|
|
||||||
|
with open(filename, 'w', newline='') as f:
|
||||||
|
f.write(result)
|
||||||
|
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
prog = 'update_hmm',
|
||||||
|
description = 'Updates C and C++ source code to use Handmade Math 2.0.',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'filename', nargs='+',
|
||||||
|
help='A file or directory to update to HMM 2.0. If a directory, all files with extensions from --exts will be processed.',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--exts', nargs='+', default=['.c', '.cpp', '.h', '.hpp'],
|
||||||
|
help='File extensions to run the script on, when targeting a directory. Default: .c, .cpp, .h, .hpp.',
|
||||||
|
metavar='.foo',
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
for path in args.filename:
|
||||||
|
filenames = []
|
||||||
|
if os.path.isfile(path):
|
||||||
|
filenames = [path]
|
||||||
|
else:
|
||||||
|
for root, dirs, files in os.walk(path):
|
||||||
|
for file in files:
|
||||||
|
if file == 'HandmadeMath.h':
|
||||||
|
printWarning('HandmadeMath.h will not be replaced by this script.')
|
||||||
|
elif file.endswith(tuple(args.exts)):
|
||||||
|
filenames.append(os.path.join(root, file))
|
||||||
|
|
||||||
|
for filename in filenames:
|
||||||
|
try:
|
||||||
|
updateFile(filename)
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
print('Updated {} files with {} warnings.'.format(numFiles, numWarnings))
|
||||||
Reference in New Issue
Block a user