mirror of
https://github.com/HandmadeMath/HandmadeMath.git
synced 2025-12-28 15:44:33 +00:00
Compare commits
71 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 |
34
.github/workflows/ci.yml
vendored
Normal file
34
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: TheMrMilchmann/setup-msvc-dev@v2
|
||||
with:
|
||||
arch: x64
|
||||
if: matrix.os == 'windows-latest'
|
||||
- name: Test (Windows, MSVC)
|
||||
run: ./run_test_msvc.bat
|
||||
working-directory: ./test
|
||||
if: matrix.os == 'windows-latest'
|
||||
- name: Test (Windows, clang)
|
||||
run: ./run_test_clang.bat
|
||||
working-directory: ./test
|
||||
if: matrix.os == 'windows-latest'
|
||||
- name: Test (${{ matrix.os }})
|
||||
run: make all
|
||||
working-directory: ./test
|
||||
if: matrix.os != 'windows-latest'
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -31,5 +31,4 @@
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
hmm_test
|
||||
hmm_test*
|
||||
test/build
|
||||
|
||||
0
.gitmodules
vendored
0
.gitmodules
vendored
12
.travis.yml
12
.travis.yml
@@ -1,12 +0,0 @@
|
||||
language: cpp
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
install:
|
||||
- cd test
|
||||
- make
|
||||
script:
|
||||
- ./hmm_test_c
|
||||
- ./hmm_test_c_no_sse
|
||||
- ./hmm_test_cpp
|
||||
- ./hmm_test_cpp_no_sse
|
||||
@@ -1,43 +0,0 @@
|
||||
# Understanding the structure of Handmade Math
|
||||
|
||||
Most of the functions in Handmade Math are very short, and are the kind of functions you want to have inlined. Because of this, most functions in Handmade Math are defined with `HINLINE`, which is defined as `static inline`.
|
||||
|
||||
The exceptions are functions like `HMM_Rotate`, which are long enough that it doesn't make sense to inline them. These functions are defined with an `HEXTERN` prototype, and implemented in the `#ifdef HANDMADE_MATH_IMPLEMENTATION` block.
|
||||
|
||||
# Quick style guide
|
||||
|
||||
* Put braces on a new line
|
||||
* Float literals should have digits both before and after the decimal.
|
||||
```cpp
|
||||
// Good
|
||||
0.0f;
|
||||
0.5f;
|
||||
1.0f;
|
||||
3.14159f;
|
||||
|
||||
// Bad
|
||||
1.f
|
||||
.0f
|
||||
```
|
||||
* Put parentheses around the returned value:
|
||||
```cpp
|
||||
HINLINE float
|
||||
HMM_MyFunction()
|
||||
{
|
||||
return (1.0f);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Other style notes
|
||||
|
||||
* If a new function is defined with different names for different datatypes, also add C++ overloaded versions of the functions. For example, if you have `HMM_LengthVec2(hmm_vec2)` and `HMM_LengthVec3(hmm_vec3)`, also provide `HMM_Length(hmm_vec2)` and `HMM_Length(hmm_vec3)`.
|
||||
|
||||
It is fine for the overloaded versions to call the C versions.
|
||||
* Only use operator overloading for analogous operators in C. That means `+` for vector addition is fine, but no using `^` for cross product or `|` for dot product.
|
||||
* Try to define functions in the same order as the prototypes.
|
||||
* Don't forget that Handmade Math uses column-major order for matrices!
|
||||
|
||||
# Versioning
|
||||
|
||||
We use [semantic versioning](http://semver.org/) because it's reasonable.
|
||||
5004
HandmadeMath.h
5004
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/>
|
||||
60
README.md
60
README.md
@@ -1,51 +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.
|
||||
|
||||
A single-file, cross-platform, public domain game math library for C/C++.
|
||||
To get started, go download [the latest release](https://github.com/HandmadeMath/HandmadeMath/releases).
|
||||
|
||||
To get started, go download [the latest release](https://github.com/HandmadeMath/Handmade-Math/releases).
|
||||
> If you are upgrading to Handmade Math 2.0, save yourself some time and use our [automatic update tool](./update).
|
||||
|
||||
_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._
|
||||
Here's what sets Handmade Math apart:
|
||||
|
||||
[](http://www.patreon.com/strangezak) [](https://www.paypal.me/zakarystrange)
|
||||
- **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 |
|
||||
----------------|----------------|
|
||||
**1.5.0** | Changed internal structure for better performance and inlining. As a result, `HANDMADE_MATH_NO_INLINE` has been removed and no longer has any effect.
|
||||
**1.4.0** | Fixed bug when using C mode. SSE'd all vec4 operations. Removed zeroing for better performance.
|
||||
**1.3.0** | Removed need to `#define HANDMADE_MATH_CPP_MODE`. C++ definitions are now included automatically in C++ environments.
|
||||
**1.2.0** | Added equality functions for `HMM_Vec2`, `HMM_Vec3`, and `HMM_Vec4`, and SSE'd `HMM_MultiplyMat4` and `HMM_Transpose`.
|
||||
**1.1.5** | Added `Width` and `Height` to `HMM_Vec2`, and made it so you can supply your own `SqrtF`.
|
||||
**1.1.4** | Fixed SSE being included on platforms that don't support it, and fixed divide-by-zero errors when normalizing zero vectors.
|
||||
**1.1.3** | Fixed compile error in C mode
|
||||
**1.1.2** | Fixed invalid HMMDEF's in the function definitions
|
||||
**1.1.1** | Resolved compiler warnings on gcc and g++
|
||||
**1.1** | Quaternions! |
|
||||
**1.0** | Lots of testing |
|
||||
**0.7** | Added HMM_Vec2, and HMM_Vec4 versions of HMM_LengthSquared, HMM_Length, and HMM_Normalize. |
|
||||
**0.6** | Made HMM_Power faster, Fixed possible efficiency problem with HMM_Normalize, RENAMED HMM_LengthSquareRoot to HMM_LengthSquared, RENAMED HMM_RSqrtF to HMM_RSquareRootF, RENAMED HMM_SqrtF to HMM_SquareRootF, REMOVED Inner function (user should use Dot now), REMOVED HMM_FastInverseSquareRoot function declaration |
|
||||
**0.5.2** | Fixed SSE code in HMM_SqrtF and HMM_RSqrtF |
|
||||
**0.5.1** | Fixed HMM_Translate producing row-major matrices, ensured column-major order for matrices throughout |
|
||||
**0.5** | Added scalar operations on vectors and matrices, added += and -= for hmm_mat4, reconciled headers and implementations, tidied up in general |
|
||||
**0.4** | Added SSE Optimized HMM_SqrtF, HMM_RSqrtF, Removed use of C Runtime |
|
||||
**0.3** | Added +=,-=, *=, /= for hmm_vec2, hmm_vec3, hmm_vec4 |
|
||||
**0.2b** | Disabled warning C4201 on MSVC, Added 64bit percision on HMM_PI |
|
||||
**0.2a** | Prefixed Macros |
|
||||
**0.2** | Updated Documentation, Fixed C Compliance, Prefixed all functions, and added better operator overloading |
|
||||
**0.1** | Initial Version |
|
||||
## Usage
|
||||
|
||||
Simply `#include "HandmadeMath.h"`. All functions are `static inline`, so there is no need for an "implementation" file as with some other single-header libraries.
|
||||
|
||||
A few config options are available. See the header comment in [the source](./HandmadeMath.h) for details.
|
||||
|
||||
-----
|
||||
_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
|
||||
|
||||
**What conventions does HMM use, e.g. row vs. column major, handedness, etc.?**
|
||||
|
||||
Handmade Math's matrices are column-major, i.e. data is stored by columns, then rows. It also assumes column vectors, i.e. vectors are written vertically and matrix-vector multiplication is `M * V` instead of `V * M`. For more information, see [this issue](https://github.com/HandmadeMath/HandmadeMath/issues/124#issuecomment-775737253).
|
||||
|
||||
For other properties, we provide variants for each common convention. Functions that care about handedness have left-handed (`LH`) and right-handed (`RH`) variants. Projection functions have zero-to-one (`ZO`) and negative-one-to-one (`NO`) variants for different NDC conventions.
|
||||
|
||||
**What if I don't want the `HMM_` prefix?**
|
||||
|
||||
Do a find and replace in the library source.
|
||||
|
||||
**What's the license?**
|
||||
|
||||
This library is in the public domain. You can do whatever you want with it.
|
||||
|
||||
**Where can I contact you to ask questions?**
|
||||
|
||||
Feel free to make Github issues for any questions, concerns, or problems you encounter.
|
||||
Feel free to make GitHub issues for any questions, concerns, or problems you encounter.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define HANDMADE_MATH_IMPLEMENTATION
|
||||
#define HANDMADE_MATH_NO_INLINE
|
||||
#ifndef WITHOUT_COVERAGE
|
||||
#include "HandmadeTest.h"
|
||||
#endif
|
||||
|
||||
#include "../HandmadeMath.h"
|
||||
|
||||
@@ -1,104 +1,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
|
||||
#define HANDMADETEST_H
|
||||
|
||||
#include <float.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int hmt_count_tests = 0;
|
||||
int hmt_count_failedtests = 0;
|
||||
int hmt_count_failures = 0;
|
||||
#include "initializer.h"
|
||||
|
||||
#define RESET "\033[0m"
|
||||
#define RED "\033[31m"
|
||||
#define GREEN "\033[32m"
|
||||
#define HMT_RESET "\033[0m"
|
||||
#define HMT_RED "\033[31m"
|
||||
#define HMT_GREEN "\033[32m"
|
||||
|
||||
#define CATEGORY_BEGIN(name) { \
|
||||
int count_categorytests = 0; \
|
||||
int count_categoryfailedtests = 0; \
|
||||
int count_categoryfailures = 0; \
|
||||
printf("\n" #name ":\n");
|
||||
#define CATEGORY_END(name) \
|
||||
hmt_count_tests += count_categorytests; \
|
||||
hmt_count_failedtests += count_categoryfailedtests; \
|
||||
hmt_count_failures += count_categoryfailures; \
|
||||
printf("%d/%d tests passed, %d failures\n", count_categorytests - count_categoryfailedtests, count_categorytests, count_categoryfailures); \
|
||||
}
|
||||
#define HMT_ARRAY_SIZE 1024
|
||||
|
||||
#define TEST_BEGIN(name) { \
|
||||
int count_testcases = 0, count_testfailures = 0; \
|
||||
count_categorytests++; \
|
||||
printf(" " #name ":");
|
||||
#define TEST_END() \
|
||||
count_categoryfailures += count_testfailures; \
|
||||
if (count_testfailures > 0) { \
|
||||
count_categoryfailedtests++; \
|
||||
printf("\n " RED "(%d/%d passed)" RESET, count_testcases - count_testfailures, count_testcases); \
|
||||
printf("\n"); \
|
||||
} else { \
|
||||
printf(GREEN " [PASS] (%d/%d passed) \n" RESET, count_testcases - count_testfailures, count_testcases); \
|
||||
} \
|
||||
}
|
||||
typedef struct hmt_testresult_struct {
|
||||
int count_cases;
|
||||
int count_failures;
|
||||
} hmt_testresult;
|
||||
|
||||
#define CASE_START() \
|
||||
count_testcases++;
|
||||
typedef void (*hmt_test_func)(hmt_testresult*);
|
||||
|
||||
#define CASE_FAIL() \
|
||||
count_testfailures++; \
|
||||
printf("\n - " RED "[FAIL] (%d) " RESET, __LINE__);
|
||||
typedef struct hmt_test_struct {
|
||||
const char* name;
|
||||
hmt_test_func func;
|
||||
} hmt_test;
|
||||
|
||||
typedef struct hmt_category_struct {
|
||||
const char* name;
|
||||
int num_tests;
|
||||
hmt_test* tests;
|
||||
} hmt_category;
|
||||
|
||||
typedef struct hmt_covercase_struct {
|
||||
const char* name;
|
||||
int expected_asserts;
|
||||
int actual_asserts;
|
||||
int* asserted_lines;
|
||||
} hmt_covercase;
|
||||
|
||||
hmt_category _hmt_new_category(const char* name);
|
||||
hmt_test _hmt_new_test(const char* name, hmt_test_func func);
|
||||
hmt_covercase _hmt_new_covercase(const char* name, int expected);
|
||||
void _hmt_register_test(const char* category, const char* name, hmt_test_func func);
|
||||
void _hmt_register_covercase(const char* name, const char* expected_asserts);
|
||||
void _hmt_count_cover(const char* name, int line);
|
||||
|
||||
#define _HMT_TEST_FUNCNAME(category, name) _hmt_test_ ## category ## _ ## name
|
||||
#define _HMT_TEST_FUNCNAME_INIT(category, name) _hmt_test_ ## category ## _ ## name ## _init
|
||||
#define _HMT_COVERCASE_FUNCNAME_INIT(name) _hmt_covercase_ ## name ## _init
|
||||
|
||||
#define HMT_TEST(category, name) \
|
||||
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result); \
|
||||
INITIALIZER(_HMT_TEST_FUNCNAME_INIT(category, name)) { \
|
||||
_hmt_register_test(#category, #name, _HMT_TEST_FUNCNAME(category, name)); \
|
||||
} \
|
||||
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result)
|
||||
|
||||
#define _HMT_CASE_START() \
|
||||
_result->count_cases++;
|
||||
|
||||
#define _HMT_CASE_FAIL() \
|
||||
_result->count_failures++; \
|
||||
printf("\n - " HMT_RED "[FAIL] (line %d) " HMT_RESET, __LINE__);
|
||||
|
||||
#define HMT_COVERAGE(name, num_asserts) \
|
||||
INITIALIZER(_HMT_COVERCASE_FUNCNAME_INIT(name)) { \
|
||||
_hmt_register_covercase(#name, #num_asserts); \
|
||||
} \
|
||||
|
||||
#define HMT_ASSERT_COVERED(name) \
|
||||
{ \
|
||||
_hmt_count_cover(#name, __LINE__); \
|
||||
} \
|
||||
|
||||
/*
|
||||
* Asserts and expects
|
||||
*/
|
||||
#define EXPECT_TRUE(_actual) do { \
|
||||
CASE_START(); \
|
||||
#define HMT_EXPECT_TRUE(_actual) { \
|
||||
_HMT_CASE_START(); \
|
||||
if (!(_actual)) { \
|
||||
CASE_FAIL(); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected true but got something false"); \
|
||||
} \
|
||||
} while (0)
|
||||
} \
|
||||
|
||||
#define EXPECT_FALSE(_actual) do { \
|
||||
CASE_START(); \
|
||||
#define HMT_EXPECT_FALSE(_actual) { \
|
||||
_HMT_CASE_START(); \
|
||||
if (_actual) { \
|
||||
CASE_FAIL(); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected false but got something true"); \
|
||||
} \
|
||||
} while (0)
|
||||
} \
|
||||
|
||||
#define EXPECT_FLOAT_EQ(_actual, _expected) do { \
|
||||
CASE_START(); \
|
||||
#define HMT_EXPECT_FLOAT_EQ_MSG(_actual, _expected, _msg) { \
|
||||
_HMT_CASE_START(); \
|
||||
float actual = (_actual); \
|
||||
float diff = actual - (_expected); \
|
||||
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
|
||||
CASE_FAIL(); \
|
||||
printf("Expected %f, got %f", (_expected), actual); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
if ((_msg)[0] == 0) { \
|
||||
printf("Expected %f, got %f (error: %.9g)", (_expected), actual, diff); \
|
||||
} else { \
|
||||
printf("%s: Expected %f, got %f (error: %.9g)", (_msg), (_expected), actual, diff); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
}
|
||||
#define HMT_EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ_MSG(_actual, _expected, "");
|
||||
|
||||
#define EXPECT_NEAR(_actual, _expected, _epsilon) do { \
|
||||
CASE_START(); \
|
||||
#define HMT_EXPECT_NEAR_MSG(_actual, _expected, _epsilon, _msg) { \
|
||||
_HMT_CASE_START(); \
|
||||
float actual = (_actual); \
|
||||
float diff = actual - (_expected); \
|
||||
if (diff < -(_epsilon) || (_epsilon) < diff) { \
|
||||
CASE_FAIL(); \
|
||||
printf("Expected %f, got %f", (_expected), actual); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
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 { \
|
||||
CASE_START(); \
|
||||
#define HMT_EXPECT_LT(_actual, _expected) { \
|
||||
_HMT_CASE_START(); \
|
||||
if ((_actual) >= (_expected)) { \
|
||||
CASE_FAIL(); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected %f to be less than %f", (_actual), (_expected)); \
|
||||
} \
|
||||
} while (0)
|
||||
} \
|
||||
|
||||
#define EXPECT_GT(_actual, _expected) do { \
|
||||
CASE_START(); \
|
||||
#define HMT_EXPECT_GT(_actual, _expected) { \
|
||||
_HMT_CASE_START(); \
|
||||
if ((_actual) <= (_expected)) { \
|
||||
CASE_FAIL(); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected %f to be greater than %f", (_actual), (_expected)); \
|
||||
} \
|
||||
} while (0)
|
||||
} \
|
||||
|
||||
#endif
|
||||
#ifndef HMT_SAFE_MACROS
|
||||
// Friendly defines
|
||||
#define TEST(category, name) HMT_TEST(category, name)
|
||||
#define COVERAGE(name, expected_asserts) HMT_COVERAGE(name, expected_asserts)
|
||||
#define ASSERT_COVERED(name) HMT_ASSERT_COVERED(name)
|
||||
#define EXPECT_TRUE(_actual) HMT_EXPECT_TRUE(_actual)
|
||||
#define EXPECT_FALSE(_actual) HMT_EXPECT_FALSE(_actual)
|
||||
#define EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ(_actual, _expected)
|
||||
#define EXPECT_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
|
||||
|
||||
143
test/Makefile
143
test/Makefile
@@ -1,37 +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 c_no_sse cpp cpp_no_sse
|
||||
.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:
|
||||
rm -f hmm_test_c hmm_test_cpp hmm_test_c_no_sse hmm_test_cpp_no_sse *.o
|
||||
rm -rf $(BUILD_DIR)
|
||||
|
||||
c: $(ROOT_DIR)/test/HandmadeMath.c test_impl
|
||||
@echo "\nCompiling in C mode"
|
||||
$(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
|
||||
-c $(ROOT_DIR)/test/HandmadeMath.c $(ROOT_DIR)/test/hmm_test.c \
|
||||
-lm
|
||||
$(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
|
||||
.PHONY: c99
|
||||
c99:
|
||||
@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
|
||||
|
||||
c_no_sse: $(ROOT_DIR)/test/HandmadeMath.c test_impl
|
||||
@echo "\nCompiling in C mode (no SSE)"
|
||||
$(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
|
||||
-DHANDMADE_MATH_NO_SSE \
|
||||
-c $(ROOT_DIR)/test/HandmadeMath.c $(ROOT_DIR)/test/hmm_test.c \
|
||||
-lm
|
||||
$(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm
|
||||
.PHONY: c99_no_simd
|
||||
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
|
||||
|
||||
cpp: $(ROOT_DIR)/test/HandmadeMath.cpp test_impl
|
||||
@echo "\nCompiling in C++ mode"
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp \
|
||||
-DHANDMADE_MATH_CPP_MODE \
|
||||
$(ROOT_DIR)/test/HandmadeMath.cpp $(ROOT_DIR)/test/hmm_test.cpp
|
||||
.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
|
||||
|
||||
cpp_no_sse: $(ROOT_DIR)/test/HandmadeMath.cpp test_impl
|
||||
@echo "\nCompiling in C++ mode (no SSE)"
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse \
|
||||
-DHANDMADE_MATH_CPP_MODE -DHANDMADE_MATH_NO_SSE \
|
||||
$(ROOT_DIR)/test/HandmadeMath.cpp $(ROOT_DIR)/test/hmm_test.cpp
|
||||
.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
|
||||
|
||||
test_impl: $(ROOT_DIR)/test/hmm_test.cpp $(ROOT_DIR)/test/hmm_test.c
|
||||
.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
|
||||
|
||||
@@ -4,8 +4,13 @@ You can compile and run the tests yourself by running:
|
||||
|
||||
```
|
||||
make
|
||||
./hmm_test_c
|
||||
./hmm_test_c_no_sse
|
||||
./hmm_test_cpp
|
||||
./hmm_test_cpp_no_sse
|
||||
```
|
||||
|
||||
To run a specific test configuration, run one of:
|
||||
|
||||
```
|
||||
make c
|
||||
make c_no_sse
|
||||
make cpp
|
||||
make cpp_no_sse
|
||||
```
|
||||
|
||||
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);
|
||||
}
|
||||
2201
test/hmm_test.c
2201
test/hmm_test.c
File diff suppressed because it is too large
Load Diff
21
test/hmm_test.h
Normal file
21
test/hmm_test.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <float.h>
|
||||
|
||||
#define HANDMADE_TEST_IMPLEMENTATION
|
||||
#include "HandmadeTest.h"
|
||||
|
||||
#undef COVERAGE // Make sure we don't double-define initializers from the header part
|
||||
#include "../HandmadeMath.h"
|
||||
|
||||
#include "categories/ScalarMath.h"
|
||||
#include "categories/Initialization.h"
|
||||
#include "categories/VectorOps.h"
|
||||
#include "categories/MatrixOps.h"
|
||||
#include "categories/QuaternionOps.h"
|
||||
#include "categories/Addition.h"
|
||||
#include "categories/Subtraction.h"
|
||||
#include "categories/Multiplication.h"
|
||||
#include "categories/Division.h"
|
||||
#include "categories/Equality.h"
|
||||
#include "categories/Projection.h"
|
||||
#include "categories/Transformation.h"
|
||||
#include "categories/SSE.h"
|
||||
29
test/initializer.h
Normal file
29
test/initializer.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// Initializer/finalizer sample for MSVC and GCC/Clang.
|
||||
// 2010-2016 Joe Lowe. Released into the public domain.
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define _INITIALIZER_T(f) f##_t_
|
||||
#define _INITIALIZER_U(f) f##_
|
||||
#define INITIALIZER(f) \
|
||||
static void f(void); \
|
||||
struct _INITIALIZER_T(f) { _INITIALIZER_T(f)(void) { f(); } }; static _INITIALIZER_T(f) _INITIALIZER_U(f); \
|
||||
static void f(void)
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma section(".CRT$XCU",read)
|
||||
#define INITIALIZER2_(f,p) \
|
||||
static void f(void); \
|
||||
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
|
||||
__pragma(comment(linker,"/include:" p #f "_")) \
|
||||
static void f(void)
|
||||
#ifdef _WIN64
|
||||
#define INITIALIZER(f) INITIALIZER2_(f,"")
|
||||
#else
|
||||
#define INITIALIZER(f) INITIALIZER2_(f,"_")
|
||||
#endif
|
||||
#else
|
||||
#define INITIALIZER(f) \
|
||||
static void f(void) __attribute__((constructor)); \
|
||||
static void f(void)
|
||||
#endif
|
||||
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