mirror of
https://github.com/HandmadeMath/HandmadeMath.git
synced 2025-12-28 15:44:33 +00:00
Compare commits
34 Commits
v1.1.3
...
mat4toquat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05a474eb76 | ||
|
|
3a5a5320c1 | ||
|
|
bb6b315c37 | ||
|
|
e095aefaf7 | ||
|
|
4e2f47db55 | ||
|
|
bee0e0c569 | ||
|
|
f8b3a84cec | ||
|
|
77914405c3 | ||
|
|
eb5c659148 | ||
|
|
52fd5cceb4 | ||
|
|
8e67482295 | ||
|
|
c508ce342b | ||
|
|
250c38e845 | ||
|
|
4981d5ab89 | ||
|
|
5f173e0176 | ||
|
|
575fcb767d | ||
|
|
a08262b2d9 | ||
|
|
53bc939d8e | ||
|
|
7eb4ae1846 | ||
|
|
48bd24b05e | ||
|
|
064baeb5b9 | ||
|
|
afd726ab0b | ||
|
|
98fffbd7cc | ||
|
|
efd9f2f4b7 | ||
|
|
c8ada18370 | ||
|
|
70ac2b7e5b | ||
|
|
924ee43923 | ||
|
|
440b885d59 | ||
|
|
98f535aeec | ||
|
|
09524f72ed | ||
|
|
be30046a5a | ||
|
|
ff4513ff33 | ||
|
|
364569abe9 | ||
|
|
a9972e71da |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -31,5 +31,4 @@
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
hmm_test
|
||||
hmm_test*
|
||||
test/build
|
||||
|
||||
@@ -6,5 +6,7 @@ install:
|
||||
- cd test
|
||||
- make
|
||||
script:
|
||||
- ./hmm_test_c
|
||||
- ./hmm_test_cpp
|
||||
- build/hmm_test_c
|
||||
- build/hmm_test_c_no_sse
|
||||
- build/hmm_test_cpp
|
||||
- build/hmm_test_cpp_no_sse
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
# 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
|
||||
@@ -13,23 +19,6 @@
|
||||
1.f
|
||||
.0f
|
||||
```
|
||||
* Put macros and return types on a separate line from the function definition:
|
||||
```cpp
|
||||
HINLINE float
|
||||
HMM_MyFunction()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
* Explicitly initialize variables to zero:
|
||||
```cpp
|
||||
HINLINE float
|
||||
HMM_MyFunction()
|
||||
{
|
||||
float MyFloat = 0.0f;
|
||||
hmm_vec3 MyVector = {0};
|
||||
}
|
||||
```
|
||||
* Put parentheses around the returned value:
|
||||
```cpp
|
||||
HINLINE float
|
||||
@@ -40,7 +29,7 @@
|
||||
```
|
||||
|
||||
|
||||
# Other notes
|
||||
## 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)`.
|
||||
|
||||
@@ -49,3 +38,6 @@
|
||||
* 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.
|
||||
|
||||
3843
HandmadeMath.h
3843
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/>
|
||||
25
README.md
25
README.md
@@ -1,17 +1,23 @@
|
||||
# Handmade-Math
|
||||
------
|
||||
# Handmade Math
|
||||
|
||||
[](https://travis-ci.org/StrangeZak/Handmade-Math)
|
||||
[](https://travis-ci.org/StrangeZak/Handmade-Math)
|
||||
|
||||
Single-file cross-platform public domain game math library for C/C++
|
||||
A single-file, cross-platform, public domain game math library for C/C++.
|
||||
|
||||
_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._
|
||||
To get started, go download [the latest release](https://github.com/HandmadeMath/Handmade-Math/releases).
|
||||
|
||||
[](http://www.patreon.com/strangezak) [](https://www.paypal.me/zakarystrange)
|
||||
-----
|
||||
|
||||
|
||||
Version | Changes |
|
||||
Version | Changes |
|
||||
----------------|----------------|
|
||||
**1.6.0** | Added array subscript operators for vector and matrix types in C++. This is provided as a convenience, but be aware that it may incur an extra function call in unoptimized builds.
|
||||
**1.5.1** | Fixed a bug with uninitialized elements in HMM_LookAt.
|
||||
**1.5.0** | Changed internal structure for better performance and inlining. As a result, `HANDMADE_MATH_NO_INLINE` has been removed and no longer has any effect.
|
||||
**1.4.0** | Fixed bug when using C mode. SSE'd all vec4 operations. Removed zeroing for better performance.
|
||||
**1.3.0** | Removed need to `#define HANDMADE_MATH_CPP_MODE`. C++ definitions are now included automatically in C++ environments.
|
||||
**1.2.0** | Added equality functions for `HMM_Vec2`, `HMM_Vec3`, and `HMM_Vec4`, and SSE'd `HMM_MultiplyMat4` and `HMM_Transpose`.
|
||||
**1.1.5** | Added `Width` and `Height` to `HMM_Vec2`, and made it so you can supply your own `SqrtF`.
|
||||
**1.1.4** | Fixed SSE being included on platforms that don't support it, and fixed divide-by-zero errors when normalizing zero vectors.
|
||||
**1.1.3** | Fixed compile error in C mode
|
||||
**1.1.2** | Fixed invalid HMMDEF's in the function definitions
|
||||
**1.1.1** | Resolved compiler warnings on gcc and g++
|
||||
@@ -30,7 +36,6 @@ Version | Changes |
|
||||
**0.1** | Initial Version |
|
||||
|
||||
-----
|
||||
_This library is free and will stay free, but if you would like to support development, or you are a company using HandmadeMath, please consider financial support._
|
||||
|
||||
## FAQ
|
||||
|
||||
@@ -40,4 +45,4 @@ This library is in the public domain. You can do whatever you want with it.
|
||||
|
||||
**Where can I contact you to ask questions?**
|
||||
|
||||
You can email me at: Zak@Handmade.Network
|
||||
Feel free to make Github issues for any questions, concerns, or problems you encounter.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
#define HANDMADE_MATH_IMPLEMENTATION
|
||||
#define HANDMADE_MATH_NO_INLINE
|
||||
#include "../HandmadeMath.h"
|
||||
|
||||
@@ -1,5 +1,2 @@
|
||||
|
||||
#define HANDMADE_MATH_IMPLEMENTATION
|
||||
#define HANDMADE_MATH_CPP_MODE
|
||||
#define HANDMADE_MATH_NO_INLINE
|
||||
#include "../HandmadeMath.h"
|
||||
#include "HandmadeMath.c"
|
||||
// C++ compilers complain when compiling a .c file...
|
||||
|
||||
@@ -1,80 +1,263 @@
|
||||
/*
|
||||
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.
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
The main function of your test code should then call hmt_run_all_tests and
|
||||
return the result:
|
||||
|
||||
int main() {
|
||||
return hmt_run_all_tests();
|
||||
}
|
||||
|
||||
=============================================================================
|
||||
|
||||
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_INITIAL_ARRAY_SIZE 1024
|
||||
|
||||
typedef struct hmt_testresult_struct {
|
||||
int count_cases;
|
||||
int count_failures;
|
||||
} hmt_testresult;
|
||||
|
||||
typedef void (*hmt_test_func)(hmt_testresult*);
|
||||
|
||||
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;
|
||||
int tests_capacity;
|
||||
hmt_test* tests;
|
||||
} hmt_category;
|
||||
|
||||
int hmt_num_categories = 0;
|
||||
int hmt_category_capacity = HMT_INITIAL_ARRAY_SIZE;
|
||||
hmt_category* categories = 0;
|
||||
|
||||
hmt_category _hmt_new_category(const char* name) {
|
||||
hmt_category cat = {
|
||||
.name = name,
|
||||
.num_tests = 0,
|
||||
.tests_capacity = HMT_INITIAL_ARRAY_SIZE,
|
||||
.tests = (hmt_test*) malloc(HMT_INITIAL_ARRAY_SIZE * sizeof(hmt_test))
|
||||
};
|
||||
|
||||
return cat;
|
||||
}
|
||||
|
||||
#define TEST_BEGIN(name) { \
|
||||
int count_testfailures = 0; \
|
||||
count_categorytests++; \
|
||||
printf(" " #name ":");
|
||||
#define TEST_END() \
|
||||
count_categoryfailures += count_testfailures; \
|
||||
if (count_testfailures > 0) { \
|
||||
count_categoryfailedtests++; \
|
||||
printf("\n"); \
|
||||
} else { \
|
||||
printf(GREEN " [PASS]\n" RESET); \
|
||||
} \
|
||||
hmt_test _hmt_new_test(const char* name, hmt_test_func func) {
|
||||
hmt_test test = {
|
||||
.name = name,
|
||||
.func = func
|
||||
};
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
#define CASE_FAIL() \
|
||||
count_testfailures++; \
|
||||
printf("\n - " RED "[FAIL] (%d) " RESET, __LINE__)
|
||||
int hmt_register_test(const char* category, const char* name, hmt_test_func func) {
|
||||
// initialize categories array if not initialized
|
||||
if (!categories) {
|
||||
categories = (hmt_category*) malloc(hmt_category_capacity * sizeof(hmt_category));
|
||||
}
|
||||
|
||||
// Find the matching category, if possible
|
||||
int cat_index;
|
||||
for (cat_index = 0; cat_index < hmt_num_categories; cat_index++) {
|
||||
if (strcmp(categories[cat_index].name, category) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Expand the array of categories if necessary
|
||||
if (cat_index >= hmt_category_capacity) {
|
||||
// TODO: If/when we ever split HandmadeTest off into its own package,
|
||||
// we should start with a smaller initial capacity and dynamically expand.
|
||||
}
|
||||
|
||||
// Add a new category if necessary
|
||||
if (cat_index >= hmt_num_categories) {
|
||||
categories[cat_index] = _hmt_new_category(category);
|
||||
hmt_num_categories++;
|
||||
}
|
||||
|
||||
hmt_category* cat = &categories[cat_index];
|
||||
|
||||
// Add the test to the category
|
||||
if (cat->num_tests >= cat->tests_capacity) {
|
||||
// TODO: If/when we ever split HandmadeTest off into its own package,
|
||||
// we should start with a smaller initial capacity and dynamically expand.
|
||||
}
|
||||
cat->tests[cat->num_tests] = _hmt_new_test(name, func);
|
||||
cat->num_tests++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hmt_run_all_tests() {
|
||||
int count_alltests = 0;
|
||||
int count_allfailedtests = 0; // failed test cases
|
||||
int count_allfailures = 0; // failed asserts
|
||||
|
||||
for (int i = 0; i < hmt_num_categories; i++) {
|
||||
hmt_category cat = categories[i];
|
||||
int count_catfailedtests = 0;
|
||||
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 = {
|
||||
.count_cases = 0,
|
||||
.count_failures = 0
|
||||
};
|
||||
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);
|
||||
}
|
||||
|
||||
#define _HMT_TEST_FUNCNAME(category, name) category ## _ ## name
|
||||
#define _HMT_TEST_FUNCNAME_INIT(category, name) category ## _ ## 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] (%d) " HMT_RESET, __LINE__);
|
||||
|
||||
/*
|
||||
* Asserts and expects
|
||||
*/
|
||||
#define EXPECT_FLOAT_EQ(_actual, _expected) do { \
|
||||
#define HMT_EXPECT_TRUE(_actual) do { \
|
||||
_HMT_CASE_START(); \
|
||||
if (!(_actual)) { \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected true but got something false"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define HMT_EXPECT_FALSE(_actual) do { \
|
||||
_HMT_CASE_START(); \
|
||||
if (_actual) { \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected false but got something true"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define HMT_EXPECT_FLOAT_EQ(_actual, _expected) do { \
|
||||
_HMT_CASE_START(); \
|
||||
float actual = (_actual); \
|
||||
float diff = actual - (_expected); \
|
||||
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
|
||||
CASE_FAIL(); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected %f, got %f", (_expected), actual); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define EXPECT_NEAR(_actual, _expected, _epsilon) do { \
|
||||
#define HMT_EXPECT_NEAR(_actual, _expected, _epsilon) do { \
|
||||
_HMT_CASE_START(); \
|
||||
float actual = (_actual); \
|
||||
float diff = actual - (_expected); \
|
||||
if (diff < -(_epsilon) || (_epsilon) < diff) { \
|
||||
CASE_FAIL(); \
|
||||
_HMT_CASE_FAIL(); \
|
||||
printf("Expected %f, got %f", (_expected), actual); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define EXPECT_LT(_actual, _expected) do { \
|
||||
#define HMT_EXPECT_LT(_actual, _expected) do { \
|
||||
_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 { \
|
||||
#define HMT_EXPECT_GT(_actual, _expected) do { \
|
||||
_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 EXPECT_TRUE(_actual) HMT_EXPECT_TRUE(_actual)
|
||||
#define EXPECT_FALSE(_actual) HMT_EXPECT_FALSE(_actual)
|
||||
#define EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ(_actual, _expected)
|
||||
#define EXPECT_NEAR(_actual, _expected, _epsilon) HMT_EXPECT_NEAR(_actual, _expected, _epsilon)
|
||||
#define EXPECT_LT(_actual, _expected) HMT_EXPECT_LT(_actual, _expected)
|
||||
#define EXPECT_GT(_actual, _expected) HMT_EXPECT_GT(_actual, _expected)
|
||||
#endif // HMT_SAFE_MACROS
|
||||
|
||||
#endif // HANDMADETEST_H
|
||||
|
||||
@@ -1,17 +1,45 @@
|
||||
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
|
||||
|
||||
all: c cpp
|
||||
all: c c_no_sse cpp cpp_no_sse
|
||||
|
||||
clean:
|
||||
rm -f hmm_test_c hmm_test_cpp *.o
|
||||
rm -rf $(BUILD_DIR)
|
||||
|
||||
c: $(ROOT_DIR)/test/HandmadeMath.c test_impl
|
||||
$(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
|
||||
c: HandmadeMath.c test_impl
|
||||
@echo "\nCompiling in C mode"
|
||||
mkdir -p $(BUILD_DIR)
|
||||
cd $(BUILD_DIR)\
|
||||
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
|
||||
-c ../HandmadeMath.c ../hmm_test.c \
|
||||
-lm \
|
||||
&& $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
|
||||
|
||||
cpp: $(ROOT_DIR)/test/HandmadeMath.cpp test_impl
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp $(ROOT_DIR)/test/HandmadeMath.cpp $(ROOT_DIR)/test/hmm_test.cpp
|
||||
c_no_sse: HandmadeMath.c test_impl
|
||||
@echo "\nCompiling in C mode (no SSE)"
|
||||
mkdir -p $(BUILD_DIR)
|
||||
cd $(BUILD_DIR) \
|
||||
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
|
||||
-DHANDMADE_MATH_NO_SSE \
|
||||
-c ../HandmadeMath.c ../hmm_test.c \
|
||||
-lm \
|
||||
&& $(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm
|
||||
|
||||
test_impl: $(ROOT_DIR)/test/hmm_test.cpp $(ROOT_DIR)/test/hmm_test.c
|
||||
cpp: HandmadeMath.cpp test_impl
|
||||
@echo "\nCompiling in C++ mode"
|
||||
mkdir -p $(BUILD_DIR)
|
||||
cd $(BUILD_DIR) \
|
||||
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp \
|
||||
-DHANDMADE_MATH_CPP_MODE \
|
||||
../HandmadeMath.cpp ../hmm_test.cpp
|
||||
|
||||
cpp_no_sse: HandmadeMath.cpp test_impl
|
||||
@echo "\nCompiling in C++ mode (no SSE)"
|
||||
mkdir -p $(BUILD_DIR)
|
||||
cd $(BUILD_DIR) \
|
||||
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse \
|
||||
-DHANDMADE_MATH_CPP_MODE -DHANDMADE_MATH_NO_SSE \
|
||||
../HandmadeMath.cpp ../hmm_test.cpp
|
||||
|
||||
test_impl: hmm_test.cpp hmm_test.c
|
||||
|
||||
11
test/README.md
Normal file
11
test/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Testing
|
||||
|
||||
You can compile and run the tests yourself by running:
|
||||
|
||||
```
|
||||
make
|
||||
build/hmm_test_c
|
||||
build/hmm_test_c_no_sse
|
||||
build/hmm_test_cpp
|
||||
build/hmm_test_cpp_no_sse
|
||||
```
|
||||
209
test/categories/Addition.h
Normal file
209
test/categories/Addition.h
Normal file
@@ -0,0 +1,209 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(Addition, Vec2)
|
||||
{
|
||||
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 2.0f);
|
||||
hmm_vec2 v2_2 = HMM_Vec2(3.0f, 4.0f);
|
||||
|
||||
{
|
||||
hmm_vec2 result = HMM_AddVec2(v2_1, v2_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec2 result = HMM_Add(v2_1, v2_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec2 result = v2_1 + v2_2;
|
||||
EXPECT_FLOAT_EQ(result.X, 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
}
|
||||
|
||||
v2_1 += v2_2;
|
||||
EXPECT_FLOAT_EQ(v2_1.X, 4.0f);
|
||||
EXPECT_FLOAT_EQ(v2_1.Y, 6.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Addition, Vec3)
|
||||
{
|
||||
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
|
||||
hmm_vec3 v3_2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
|
||||
|
||||
{
|
||||
hmm_vec3 result = HMM_AddVec3(v3_1, v3_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 7.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec3 result = HMM_Add(v3_1, v3_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 7.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec3 result = v3_1 + v3_2;
|
||||
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 7.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||
}
|
||||
|
||||
v3_1 += v3_2;
|
||||
EXPECT_FLOAT_EQ(v3_1.X, 5.0f);
|
||||
EXPECT_FLOAT_EQ(v3_1.Y, 7.0f);
|
||||
EXPECT_FLOAT_EQ(v3_1.Z, 9.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Addition, Vec4)
|
||||
{
|
||||
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
hmm_vec4 v4_2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
|
||||
|
||||
{
|
||||
hmm_vec4 result = HMM_AddVec4(v4_1, v4_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec4 result = HMM_Add(v4_1, v4_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec4 result = v4_1 + v4_2;
|
||||
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||
}
|
||||
|
||||
v4_1 += v4_2;
|
||||
EXPECT_FLOAT_EQ(v4_1.X, 6.0f);
|
||||
EXPECT_FLOAT_EQ(v4_1.Y, 8.0f);
|
||||
EXPECT_FLOAT_EQ(v4_1.Z, 10.0f);
|
||||
EXPECT_FLOAT_EQ(v4_1.W, 12.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Addition, Mat4)
|
||||
{
|
||||
hmm_mat4 m4_1 = HMM_Mat4(); // will have 1 - 16
|
||||
hmm_mat4 m4_2 = HMM_Mat4(); // will have 17 - 32
|
||||
|
||||
// Fill the matrices
|
||||
int Counter = 1;
|
||||
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_AddMat4(m4_1, m4_2);
|
||||
float Expected = 18.0f;
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected);
|
||||
Expected += 2.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_mat4 result = HMM_Add(m4_1, m4_2);
|
||||
float Expected = 18.0f;
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected);
|
||||
Expected += 2.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
hmm_mat4 result = m4_1 + m4_2;
|
||||
float Expected = 18.0f;
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected);
|
||||
Expected += 2.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m4_1 += m4_2;
|
||||
float Expected = 18.0f;
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(m4_1.Elements[Column][Row], Expected);
|
||||
Expected += 2.0f;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Addition, Quaternion)
|
||||
{
|
||||
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f);
|
||||
|
||||
{
|
||||
hmm_quaternion result = HMM_AddQuaternion(q1, q2);
|
||||
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_quaternion result = HMM_Add(q1, q2);
|
||||
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||
}
|
||||
{
|
||||
hmm_quaternion result = q1 + q2;
|
||||
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||
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
|
||||
}
|
||||
325
test/categories/Division.h
Normal file
325
test/categories/Division.h
Normal file
@@ -0,0 +1,325 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(Division, Vec2Vec2)
|
||||
{
|
||||
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 3.0f);
|
||||
hmm_vec2 v2_2 = HMM_Vec2(2.0f, 4.0f);
|
||||
|
||||
{
|
||||
hmm_vec2 result = HMM_DivideVec2(v2_1, v2_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec2 result = HMM_Divide(v2_1, v2_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||
}
|
||||
{
|
||||
hmm_vec2 result = v2_1 / v2_2;
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||
}
|
||||
|
||||
v2_1 /= v2_2;
|
||||
EXPECT_FLOAT_EQ(v2_1.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(v2_1.Y, 0.75f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Division, Vec2Scalar)
|
||||
{
|
||||
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f);
|
||||
float s = 2;
|
||||
|
||||
{
|
||||
hmm_vec2 result = HMM_DivideVec2f(v2, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec2 result = HMM_Divide(v2, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec2 result = v2 / s;
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
}
|
||||
|
||||
v2 /= s;
|
||||
EXPECT_FLOAT_EQ(v2.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(v2.Y, 1.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Division, Vec3Vec3)
|
||||
{
|
||||
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 3.0f, 5.0f);
|
||||
hmm_vec3 v3_2 = HMM_Vec3(2.0f, 4.0f, 0.5f);
|
||||
|
||||
{
|
||||
hmm_vec3 result = HMM_DivideVec3(v3_1, v3_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec3 result = HMM_Divide(v3_1, v3_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec3 result = v3_1 / v3_2;
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||
}
|
||||
|
||||
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_Vec3(1.0f, 2.0f, 3.0f);
|
||||
float s = 2;
|
||||
|
||||
{
|
||||
hmm_vec3 result = HMM_DivideVec3f(v3, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec3 result = HMM_Divide(v3, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||
}
|
||||
{
|
||||
hmm_vec3 result = v3 / s;
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||
}
|
||||
|
||||
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_Vec4(1.0f, 3.0f, 5.0f, 1.0f);
|
||||
hmm_vec4 v4_2 = HMM_Vec4(2.0f, 4.0f, 0.5f, 4.0f);
|
||||
|
||||
{
|
||||
hmm_vec4 result = HMM_DivideVec4(v4_1, v4_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 0.25f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec4 result = HMM_Divide(v4_1, v4_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 0.25f);
|
||||
}
|
||||
{
|
||||
hmm_vec4 result = v4_1 / v4_2;
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.75f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 10.0f);
|
||||
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_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
float s = 2;
|
||||
|
||||
{
|
||||
hmm_vec4 result = HMM_DivideVec4f(v4, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||
EXPECT_FLOAT_EQ(result.W, 2.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec4 result = HMM_Divide(v4, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||
EXPECT_FLOAT_EQ(result.W, 2.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec4 result = v4 / s;
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||
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, Mat4Scalar)
|
||||
{
|
||||
hmm_mat4 m4 = HMM_Mat4(); // 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_DivideMat4f(m4, s);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][3], 2.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][0], 2.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][1], 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][2], 3.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][3], 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][0], 4.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][1], 5.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][2], 5.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][3], 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][0], 6.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][1], 7.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_mat4 result = HMM_Divide(m4, s);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][3], 2.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][0], 2.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][1], 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][2], 3.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][3], 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][0], 4.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][1], 5.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][2], 5.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][3], 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][0], 6.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][1], 7.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
|
||||
}
|
||||
{
|
||||
hmm_mat4 result = m4 / s;
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
|
||||
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_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
float f = 2.0f;
|
||||
|
||||
{
|
||||
hmm_quaternion result = HMM_DivideQuaternionF(q, f);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||
EXPECT_FLOAT_EQ(result.W, 2.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_quaternion result = HMM_Divide(q, f);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||
EXPECT_FLOAT_EQ(result.W, 2.0f);
|
||||
}
|
||||
{
|
||||
hmm_quaternion result = q / f;
|
||||
EXPECT_FLOAT_EQ(result.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 1.5f);
|
||||
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
|
||||
}
|
||||
55
test/categories/Equality.h
Normal file
55
test/categories/Equality.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(Equality, Vec2)
|
||||
{
|
||||
hmm_vec2 a = HMM_Vec2(1.0f, 2.0f);
|
||||
hmm_vec2 b = HMM_Vec2(1.0f, 2.0f);
|
||||
hmm_vec2 c = HMM_Vec2(3.0f, 4.0f);
|
||||
|
||||
EXPECT_TRUE(HMM_EqualsVec2(a, b));
|
||||
EXPECT_FALSE(HMM_EqualsVec2(a, c));
|
||||
|
||||
#ifdef __cplusplus
|
||||
EXPECT_TRUE(HMM_Equals(a, b));
|
||||
EXPECT_FALSE(HMM_Equals(a, c));
|
||||
|
||||
EXPECT_TRUE(a == b);
|
||||
EXPECT_FALSE(a == c);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Equality, Vec3)
|
||||
{
|
||||
hmm_vec3 a = HMM_Vec3(1.0f, 2.0f, 3.0f);
|
||||
hmm_vec3 b = HMM_Vec3(1.0f, 2.0f, 3.0f);
|
||||
hmm_vec3 c = HMM_Vec3(4.0f, 5.0f, 6.0f);
|
||||
|
||||
EXPECT_TRUE(HMM_EqualsVec3(a, b));
|
||||
EXPECT_FALSE(HMM_EqualsVec3(a, c));
|
||||
|
||||
#ifdef __cplusplus
|
||||
EXPECT_TRUE(HMM_Equals(a, b));
|
||||
EXPECT_FALSE(HMM_Equals(a, c));
|
||||
|
||||
EXPECT_TRUE(a == b);
|
||||
EXPECT_FALSE(a == c);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Equality, Vec4)
|
||||
{
|
||||
hmm_vec4 a = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
hmm_vec4 b = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
hmm_vec4 c = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
|
||||
|
||||
EXPECT_TRUE(HMM_EqualsVec4(a, b));
|
||||
EXPECT_FALSE(HMM_EqualsVec4(a, c));
|
||||
|
||||
#ifdef __cplusplus
|
||||
EXPECT_TRUE(HMM_Equals(a, b));
|
||||
EXPECT_FALSE(HMM_Equals(a, c));
|
||||
|
||||
EXPECT_TRUE(a == b);
|
||||
EXPECT_FALSE(a == c);
|
||||
#endif
|
||||
}
|
||||
246
test/categories/Initialization.h
Normal file
246
test/categories/Initialization.h
Normal file
@@ -0,0 +1,246 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(Initialization, Vectors)
|
||||
{
|
||||
//
|
||||
// Test vec2
|
||||
//
|
||||
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f);
|
||||
hmm_vec2 v2i = HMM_Vec2(1, 2);
|
||||
|
||||
EXPECT_FLOAT_EQ(v2.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v2.Y, 2.0f);
|
||||
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
|
||||
|
||||
EXPECT_FLOAT_EQ(v2i.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v2i.Y, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v2i.U, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v2i.V, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v2i.Left, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v2i.Right, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v2i.Width, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v2i.Height, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v2i.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v2i.Elements[1], 2.0f);
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(v2i[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v2i[1], 2.0f);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Test vec3
|
||||
//
|
||||
hmm_vec3 v3 = HMM_Vec3(1.0f, 2.0f, 3.0f);
|
||||
hmm_vec3 v3i = HMM_Vec3i(1, 2, 3);
|
||||
|
||||
EXPECT_FLOAT_EQ(v3.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3.Y, 2.0f);
|
||||
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
|
||||
|
||||
EXPECT_FLOAT_EQ(v3i.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.Y, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.Z, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.U, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.V, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.W, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.R, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.G, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.B, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.Elements[2], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.XY.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.XY.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.YZ.Elements[0], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.YZ.Elements[1], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.UV.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.UV.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.VW.Elements[0], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3i.VW.Elements[1], 3.0f);
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(v3i[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v3i[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v3i[2], 3.0f);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Test vec4
|
||||
//
|
||||
hmm_vec4 v4 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
hmm_vec4 v4i = HMM_Vec4i(1, 2, 3, 4);
|
||||
hmm_vec4 v4v = HMM_Vec4v(v3, 4.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(v4.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4.Y, 2.0f);
|
||||
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(v4i.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.Y, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.Z, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.W, 4.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.R, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.G, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.B, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.A, 4.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.XY.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.XY.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.YZ.Elements[0], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.YZ.Elements[1], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.ZW.Elements[0], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.ZW.Elements[1], 4.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.XY.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.XY.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.XYZ.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.XYZ.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.XYZ.Elements[2], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.RGB.Elements[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.RGB.Elements[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4i.RGB.Elements[2], 3.0f);
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(v4i[0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4i[1], 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4i[2], 3.0f);
|
||||
EXPECT_FLOAT_EQ(v4i[3], 4.0f);
|
||||
#endif
|
||||
|
||||
EXPECT_FLOAT_EQ(v4v.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.Y, 2.0f);
|
||||
EXPECT_FLOAT_EQ(v4v.Z, 3.0f);
|
||||
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)
|
||||
{
|
||||
hmm_mat4 m4 = HMM_Mat4();
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(m4.Elements[Column][Row], 0.0f);
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(m4[Column][Row], 0.0f);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Initialization, MatrixDiagonal)
|
||||
{
|
||||
hmm_mat4 m4d = HMM_Mat4d(1.0f);
|
||||
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_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(q.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(q.Y, 2.0f);
|
||||
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_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
hmm_quaternion qv = HMM_QuaternionV4(v);
|
||||
|
||||
EXPECT_FLOAT_EQ(qv.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(qv.Y, 2.0f);
|
||||
EXPECT_FLOAT_EQ(qv.Z, 3.0f);
|
||||
EXPECT_FLOAT_EQ(qv.W, 4.0f);
|
||||
}
|
||||
154
test/categories/MatrixOps.h
Normal file
154
test/categories/MatrixOps.h
Normal file
@@ -0,0 +1,154 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
void printQuat(hmm_quaternion quat) {
|
||||
printf("\n%f %f %f %f", quat.X, quat.Y, quat.Z, quat.W);
|
||||
}
|
||||
|
||||
TEST(MatrixOps, Transpose)
|
||||
{
|
||||
hmm_mat4 m4 = HMM_Mat4(); // 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_Transpose(m4);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][0], 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][1], 5.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
|
||||
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);
|
||||
}
|
||||
|
||||
TEST(MatrixOps, ToQuaternion)
|
||||
{
|
||||
{ // Test 90 degree rotation about X axis
|
||||
hmm_mat4 rot = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f, // first column (X)
|
||||
0.0f, 0.0f, 1.0f, 0.0f, // second column (Y)
|
||||
0.0f, -1.0f, 0.0f, 0.0f, // third column (Z)
|
||||
0.0f, 0.0f, 0.0f, 0.0f
|
||||
};
|
||||
|
||||
hmm_quaternion expected = HMM_QuaternionFromAxisAngle(HMM_Vec3(1.0f, 0.0f, 0.0f), HMM_ToRadians(90.0f));
|
||||
hmm_quaternion actualResult = HMM_Mat4ToQuaternion(rot);
|
||||
|
||||
EXPECT_FLOAT_EQ(actualResult.X, expected.X);
|
||||
EXPECT_FLOAT_EQ(actualResult.Y, expected.Y);
|
||||
EXPECT_FLOAT_EQ(actualResult.Z, expected.Z);
|
||||
EXPECT_FLOAT_EQ(actualResult.W, expected.W);
|
||||
}
|
||||
|
||||
{ // Test 90 degree rotation about Y axis
|
||||
hmm_mat4 rot = {
|
||||
0.0f, 0.0f, -1.0f, 0.0f, // first column (X)
|
||||
0.0f, 1.0f, 0.0f, 0.0f, // second column (Y)
|
||||
1.0f, 0.0f, 0.0f, 0.0f, // third column (Z)
|
||||
0.0f, 0.0f, 0.0f, 0.0f
|
||||
};
|
||||
|
||||
hmm_quaternion expected = HMM_QuaternionFromAxisAngle(HMM_Vec3(0.0f, 1.0f, 0.0f), HMM_ToRadians(90.0f));
|
||||
hmm_quaternion actualResult = HMM_Mat4ToQuaternion(rot);
|
||||
|
||||
EXPECT_FLOAT_EQ(actualResult.X, expected.X);
|
||||
EXPECT_FLOAT_EQ(actualResult.Y, expected.Y);
|
||||
EXPECT_FLOAT_EQ(actualResult.Z, expected.Z);
|
||||
EXPECT_FLOAT_EQ(actualResult.W, expected.W);
|
||||
}
|
||||
|
||||
{ // Test 90 degree rotation about Z axis
|
||||
hmm_mat4 rot = {
|
||||
0.0f, 1.0f, 0.0f, 0.0f, // first column (X)
|
||||
-1.0f, 0.0f, 0.0f, 0.0f, // second column (Y)
|
||||
0.0f, 0.0f, 1.0f, 0.0f, // third column (Z)
|
||||
0.0f, 0.0f, 0.0f, 0.0f
|
||||
};
|
||||
|
||||
hmm_quaternion expected = HMM_QuaternionFromAxisAngle(HMM_Vec3(0.0f, 0.0f, 1.0f), HMM_ToRadians(90.0f));
|
||||
hmm_quaternion actualResult = HMM_Mat4ToQuaternion(rot);
|
||||
|
||||
EXPECT_FLOAT_EQ(actualResult.X, expected.X);
|
||||
EXPECT_FLOAT_EQ(actualResult.Y, expected.Y);
|
||||
EXPECT_FLOAT_EQ(actualResult.Z, expected.Z);
|
||||
EXPECT_FLOAT_EQ(actualResult.W, expected.W);
|
||||
}
|
||||
|
||||
{ // Test 180 degree rotation about X axis
|
||||
hmm_mat4 rot = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f, // first column (X)
|
||||
0.0f, -1.0f, 1.0f, 0.0f, // second column (Y)
|
||||
0.0f, 0.0f, -1.0f, 0.0f, // third column (Z)
|
||||
0.0f, 0.0f, 0.0f, 0.0f
|
||||
};
|
||||
|
||||
hmm_quaternion expected = HMM_QuaternionFromAxisAngle(HMM_Vec3(1.0f, 0.0f, 0.0f), HMM_ToRadians(180.0f));
|
||||
hmm_quaternion actualResult = HMM_Mat4ToQuaternion(rot);
|
||||
|
||||
printQuat(expected);
|
||||
printQuat(actualResult);
|
||||
|
||||
EXPECT_FLOAT_EQ(actualResult.X, expected.X);
|
||||
EXPECT_FLOAT_EQ(actualResult.Y, expected.Y);
|
||||
EXPECT_FLOAT_EQ(actualResult.Z, expected.Z);
|
||||
EXPECT_FLOAT_EQ(actualResult.W, expected.W);
|
||||
}
|
||||
|
||||
{ // Test 180 degree rotation about Y axis
|
||||
hmm_mat4 rot = {
|
||||
-1.0f, 0.0f, 0.0f, 0.0f, // first column (X)
|
||||
0.0f, 1.0f, 1.0f, 0.0f, // second column (Y)
|
||||
0.0f, 0.0f, -1.0f, 0.0f, // third column (Z)
|
||||
0.0f, 0.0f, 0.0f, 0.0f
|
||||
};
|
||||
|
||||
hmm_quaternion expected = HMM_QuaternionFromAxisAngle(HMM_Vec3(0.0f, 1.0f, 0.0f), HMM_ToRadians(180.0f));
|
||||
hmm_quaternion actualResult = HMM_Mat4ToQuaternion(rot);
|
||||
|
||||
printQuat(expected);
|
||||
printQuat(actualResult);
|
||||
|
||||
EXPECT_FLOAT_EQ(actualResult.X, expected.X);
|
||||
EXPECT_FLOAT_EQ(actualResult.Y, expected.Y);
|
||||
EXPECT_FLOAT_EQ(actualResult.Z, expected.Z);
|
||||
EXPECT_FLOAT_EQ(actualResult.W, expected.W);
|
||||
}
|
||||
|
||||
{ // Test 180 degree rotation about Z axis
|
||||
hmm_mat4 rot = {
|
||||
-1.0f, 0.0f, 0.0f, 0.0f, // first column (X)
|
||||
0.0f, -1.0f, 1.0f, 0.0f, // second column (Y)
|
||||
0.0f, 0.0f, 1.0f, 0.0f, // third column (Z)
|
||||
0.0f, 0.0f, 0.0f, 0.0f
|
||||
};
|
||||
|
||||
hmm_quaternion expected = HMM_QuaternionFromAxisAngle(HMM_Vec3(0.0f, 0.0f, 1.0f), HMM_ToRadians(180.0f));
|
||||
hmm_quaternion actualResult = HMM_Mat4ToQuaternion(rot);
|
||||
|
||||
printQuat(expected);
|
||||
printQuat(actualResult);
|
||||
|
||||
EXPECT_FLOAT_EQ(actualResult.X, expected.X);
|
||||
EXPECT_FLOAT_EQ(actualResult.Y, expected.Y);
|
||||
EXPECT_FLOAT_EQ(actualResult.Z, expected.Z);
|
||||
EXPECT_FLOAT_EQ(actualResult.W, expected.W);
|
||||
}
|
||||
}
|
||||
536
test/categories/Multiplication.h
Normal file
536
test/categories/Multiplication.h
Normal file
@@ -0,0 +1,536 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(Multiplication, Vec2Vec2)
|
||||
{
|
||||
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 2.0f);
|
||||
hmm_vec2 v2_2 = HMM_Vec2(3.0f, 4.0f);
|
||||
|
||||
{
|
||||
hmm_vec2 result = HMM_MultiplyVec2(v2_1, v2_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec2 result = HMM_Multiply(v2_1, v2_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec2 result = v2_1 * v2_2;
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 8.0f);
|
||||
}
|
||||
|
||||
v2_1 *= v2_2;
|
||||
EXPECT_FLOAT_EQ(v2_1.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v2_1.Y, 8.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Multiplication, Vec2Scalar)
|
||||
{
|
||||
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f);
|
||||
float s = 3.0f;
|
||||
|
||||
{
|
||||
hmm_vec2 result = HMM_MultiplyVec2f(v2, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec2 result = HMM_Multiply(v2, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec2 result = v2 * s;
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec2 result = s * v2;
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
}
|
||||
|
||||
v2 *= s;
|
||||
EXPECT_FLOAT_EQ(v2.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(v2.Y, 6.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Multiplication, Vec3Vec3)
|
||||
{
|
||||
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
|
||||
hmm_vec3 v3_2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
|
||||
|
||||
{
|
||||
hmm_vec3 result = HMM_MultiplyVec3(v3_1, v3_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 10.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 18.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec3 result = HMM_Multiply(v3_1, v3_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 10.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 18.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec3 result = v3_1 * v3_2;
|
||||
EXPECT_FLOAT_EQ(result.X, 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 10.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 18.0f);
|
||||
}
|
||||
|
||||
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_Vec3(1.0f, 2.0f, 3.0f);
|
||||
float s = 3.0f;
|
||||
|
||||
{
|
||||
hmm_vec3 result = HMM_MultiplyVec3f(v3, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec3 result = HMM_Multiply(v3, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec3 result = 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_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
hmm_vec4 v4_2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
|
||||
|
||||
{
|
||||
hmm_vec4 result = HMM_MultiplyVec4(v4_1, v4_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 12.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 21.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 32.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec4 result = HMM_Multiply(v4_1, v4_2);
|
||||
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 12.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 21.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 32.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec4 result = v4_1 * v4_2;
|
||||
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 12.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 21.0f);
|
||||
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_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
float s = 3.0f;
|
||||
|
||||
{
|
||||
hmm_vec4 result = HMM_MultiplyVec4f(v4, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec4 result = HMM_Multiply(v4, s);
|
||||
EXPECT_FLOAT_EQ(result.X, 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 12.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec4 result = 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, Mat4Mat4)
|
||||
{
|
||||
hmm_mat4 m4_1 = HMM_Mat4(); // will have 1 - 16
|
||||
hmm_mat4 m4_2 = HMM_Mat4(); // will have 17 - 32
|
||||
|
||||
// Fill the matrices
|
||||
int Counter = 1;
|
||||
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_MultiplyMat4(m4_1, m4_2);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][3], 760.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][0], 650.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][1], 740.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][2], 830.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][3], 920.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][0], 762.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][1], 868.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][2], 974.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][3], 1080.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][0], 874.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][1], 996.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_mat4 result = HMM_Multiply(m4_1, m4_2);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][3], 760.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][0], 650.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][1], 740.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][2], 830.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][3], 920.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][0], 762.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][1], 868.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][2], 974.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][3], 1080.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][0], 874.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][1], 996.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
|
||||
}
|
||||
{
|
||||
hmm_mat4 result = m4_1 * m4_2;
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
|
||||
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_Mat4(); // 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_MultiplyMat4f(m4, s);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][3], 12.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][0], 15.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][1], 18.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][3], 24.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][0], 27.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][1], 30.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][2], 33.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][3], 36.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][0], 39.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][1], 42.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_mat4 result = HMM_Multiply(m4, s);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][3], 12.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][0], 15.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][1], 18.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][3], 24.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][0], 27.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][1], 30.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][2], 33.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][3], 36.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][0], 39.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][1], 42.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
|
||||
}
|
||||
{
|
||||
hmm_mat4 result = m4 * s;
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][3], 12.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][0], 15.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][1], 18.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][3], 24.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][0], 27.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][1], 30.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][2], 33.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][3], 36.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][0], 39.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][1], 42.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
|
||||
}
|
||||
{
|
||||
hmm_mat4 result = s * m4;
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][3], 12.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][0], 15.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][1], 18.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][3], 24.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][0], 27.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][1], 30.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][2], 33.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][3], 36.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][0], 39.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][1], 42.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
|
||||
}
|
||||
|
||||
m4 *= s;
|
||||
EXPECT_FLOAT_EQ(m4.Elements[0][0], 3.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[0][1], 6.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[0][2], 9.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[0][3], 12.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[1][0], 15.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[1][1], 18.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[1][2], 21.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[1][3], 24.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[2][0], 27.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[2][1], 30.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[2][2], 33.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[2][3], 36.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[3][0], 39.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[3][1], 42.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[3][2], 45.0f);
|
||||
EXPECT_FLOAT_EQ(m4.Elements[3][3], 48.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Multiplication, Mat4Vec4)
|
||||
{
|
||||
hmm_mat4 m4 = HMM_Mat4(); // will have 1 - 16
|
||||
hmm_vec4 v4 = HMM_Vec4(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_MultiplyMat4ByVec4(m4, v4);
|
||||
EXPECT_FLOAT_EQ(result.X, 90.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 100.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 110.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 120.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec4 result = HMM_Multiply(m4, v4);
|
||||
EXPECT_FLOAT_EQ(result.X, 90.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 100.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 110.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 120.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec4 result = m4 * v4;
|
||||
EXPECT_FLOAT_EQ(result.X, 90.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 100.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 110.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 120.0f);
|
||||
}
|
||||
|
||||
// *= makes no sense for this particular case.
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Multiplication, QuaternionQuaternion)
|
||||
{
|
||||
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f);
|
||||
|
||||
{
|
||||
hmm_quaternion result = HMM_MultiplyQuaternion(q1, q2);
|
||||
EXPECT_FLOAT_EQ(result.X, 24.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 48.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 48.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, -6.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_quaternion result = HMM_Multiply(q1, q2);
|
||||
EXPECT_FLOAT_EQ(result.X, 24.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 48.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 48.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, -6.0f);
|
||||
}
|
||||
{
|
||||
hmm_quaternion result = q1 * q2;
|
||||
EXPECT_FLOAT_EQ(result.X, 24.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 48.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 48.0f);
|
||||
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_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
float f = 2.0f;
|
||||
|
||||
{
|
||||
hmm_quaternion result = HMM_MultiplyQuaternionF(q, f);
|
||||
EXPECT_FLOAT_EQ(result.X, 2.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 8.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_quaternion result = HMM_Multiply(q, f);
|
||||
EXPECT_FLOAT_EQ(result.X, 2.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 8.0f);
|
||||
}
|
||||
{
|
||||
hmm_quaternion result = q * f;
|
||||
EXPECT_FLOAT_EQ(result.X, 2.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 6.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 8.0f);
|
||||
}
|
||||
{
|
||||
hmm_quaternion result = f * q;
|
||||
EXPECT_FLOAT_EQ(result.X, 2.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 6.0f);
|
||||
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
|
||||
}
|
||||
36
test/categories/Projection.h
Normal file
36
test/categories/Projection.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(Projection, Orthographic)
|
||||
{
|
||||
hmm_mat4 projection = HMM_Orthographic(-10.0f, 10.0f, -5.0f, 5.0f, 0.0f, -10.0f);
|
||||
|
||||
hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -5.0f);
|
||||
hmm_vec4 projected = HMM_MultiplyMat4ByVec4(projection, HMM_Vec4v(original, 1));
|
||||
|
||||
EXPECT_FLOAT_EQ(projected.X, 0.5f);
|
||||
EXPECT_FLOAT_EQ(projected.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(projected.Z, -2.0f);
|
||||
EXPECT_FLOAT_EQ(projected.W, 1.0f);
|
||||
}
|
||||
|
||||
TEST(Projection, Perspective)
|
||||
{
|
||||
hmm_mat4 projection = HMM_Perspective(90.0f, 2.0f, 5.0f, 15.0f);
|
||||
|
||||
{
|
||||
hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -15.0f);
|
||||
hmm_vec4 projected = HMM_MultiplyMat4ByVec4(projection, HMM_Vec4v(original, 1));
|
||||
EXPECT_FLOAT_EQ(projected.X, 5.0f);
|
||||
EXPECT_FLOAT_EQ(projected.Y, 10.0f);
|
||||
EXPECT_FLOAT_EQ(projected.Z, 15.0f);
|
||||
EXPECT_FLOAT_EQ(projected.W, 15.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -5.0f);
|
||||
hmm_vec4 projected = HMM_MultiplyMat4ByVec4(projection, HMM_Vec4v(original, 1));
|
||||
EXPECT_FLOAT_EQ(projected.X, 5.0f);
|
||||
EXPECT_FLOAT_EQ(projected.Y, 10.0f);
|
||||
EXPECT_FLOAT_EQ(projected.Z, -5.0f);
|
||||
EXPECT_FLOAT_EQ(projected.W, 5.0f);
|
||||
}
|
||||
}
|
||||
118
test/categories/QuaternionOps.h
Normal file
118
test/categories/QuaternionOps.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(QuaternionOps, Inverse)
|
||||
{
|
||||
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
hmm_quaternion inverse = HMM_InverseQuaternion(q1);
|
||||
|
||||
hmm_quaternion result = HMM_MultiplyQuaternion(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_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f);
|
||||
|
||||
{
|
||||
float result = HMM_DotQuaternion(q1, q2);
|
||||
EXPECT_FLOAT_EQ(result, 70.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
float result = HMM_Dot(q1, q2);
|
||||
EXPECT_FLOAT_EQ(result, 70.0f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(QuaternionOps, Normalize)
|
||||
{
|
||||
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
|
||||
{
|
||||
hmm_quaternion result = HMM_NormalizeQuaternion(q);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.1825741858f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.3651483717f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 0.5477225575f);
|
||||
EXPECT_FLOAT_EQ(result.W, 0.7302967433f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_quaternion result = HMM_Normalize(q);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.1825741858f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.3651483717f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 0.5477225575f);
|
||||
EXPECT_FLOAT_EQ(result.W, 0.7302967433f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(QuaternionOps, NLerp)
|
||||
{
|
||||
hmm_quaternion from = HMM_Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
hmm_quaternion to = HMM_Quaternion(0.5f, 0.5f, -0.5f, 0.5f);
|
||||
|
||||
hmm_quaternion result = HMM_NLerp(from, 0.5f, to);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.28867513f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.28867513f);
|
||||
EXPECT_FLOAT_EQ(result.Z, -0.28867513f);
|
||||
EXPECT_FLOAT_EQ(result.W, 0.86602540f);
|
||||
}
|
||||
|
||||
TEST(QuaternionOps, Slerp)
|
||||
{
|
||||
hmm_quaternion from = HMM_Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
hmm_quaternion to = HMM_Quaternion(0.5f, 0.5f, -0.5f, 0.5f);
|
||||
|
||||
hmm_quaternion result = HMM_Slerp(from, 0.5f, to);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.28867513f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.28867513f);
|
||||
EXPECT_FLOAT_EQ(result.Z, -0.28867513f);
|
||||
EXPECT_FLOAT_EQ(result.W, 0.86602540f);
|
||||
}
|
||||
|
||||
TEST(QuaternionOps, ToMat4)
|
||||
{
|
||||
const float abs_error = 0.0001f;
|
||||
|
||||
hmm_quaternion rot = HMM_Quaternion(0.707107f, 0.0f, 0.0f, 0.707107f);
|
||||
|
||||
hmm_mat4 result = HMM_QuaternionToMat4(rot);
|
||||
|
||||
EXPECT_NEAR(result.Elements[0][0], 1.0f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[0][1], 0.0f, abs_error);
|
||||
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, FromAxisAngle)
|
||||
{
|
||||
hmm_vec3 axis = HMM_Vec3(1.0f, 0.0f, 0.0f);
|
||||
float angle = HMM_PI32 / 2.0f;
|
||||
|
||||
hmm_quaternion result = HMM_QuaternionFromAxisAngle(axis, angle);
|
||||
EXPECT_NEAR(result.X, 0.707107f, FLT_EPSILON * 2);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 0.0f);
|
||||
EXPECT_NEAR(result.W, 0.707107f, FLT_EPSILON * 2);
|
||||
}
|
||||
41
test/categories/SSE.h
Normal file
41
test/categories/SSE.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
#ifdef HANDMADE_MATH__USE_SSE
|
||||
|
||||
TEST(SSE, LinearCombine)
|
||||
{
|
||||
hmm_mat4 MatrixOne = HMM_Mat4d(2.0f);
|
||||
hmm_mat4 MatrixTwo = HMM_Mat4d(4.0f);
|
||||
hmm_mat4 Result;
|
||||
|
||||
Result.Rows[0] = HMM_LinearCombineSSE(MatrixOne.Rows[0], MatrixTwo);
|
||||
Result.Rows[1] = HMM_LinearCombineSSE(MatrixOne.Rows[1], MatrixTwo);
|
||||
Result.Rows[2] = HMM_LinearCombineSSE(MatrixOne.Rows[2], MatrixTwo);
|
||||
Result.Rows[3] = HMM_LinearCombineSSE(MatrixOne.Rows[3], MatrixTwo);
|
||||
|
||||
{
|
||||
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
|
||||
74
test/categories/ScalarMath.h
Normal file
74
test/categories/ScalarMath.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#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, ToRadians)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(HMM_ToRadians(0.0f), 0.0f);
|
||||
EXPECT_FLOAT_EQ(HMM_ToRadians(180.0f), HMM_PI32);
|
||||
EXPECT_FLOAT_EQ(HMM_ToRadians(-180.0f), -HMM_PI32);
|
||||
}
|
||||
|
||||
TEST(ScalarMath, SquareRoot)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(HMM_SquareRootF(16.0f), 4.0f);
|
||||
}
|
||||
|
||||
TEST(ScalarMath, RSquareRootF)
|
||||
{
|
||||
EXPECT_NEAR(HMM_RSquareRootF(10.0f), 0.31616211f, 0.0001f);
|
||||
}
|
||||
|
||||
TEST(ScalarMath, Power)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(HMM_Power(2.0f, 0), 1.0f);
|
||||
EXPECT_FLOAT_EQ(HMM_Power(2.0f, 4), 16.0f);
|
||||
EXPECT_FLOAT_EQ(HMM_Power(2.0f, -2), 0.25f);
|
||||
}
|
||||
|
||||
TEST(ScalarMath, PowerF)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(HMM_PowerF(2.0f, 0), 1.0f);
|
||||
EXPECT_NEAR(HMM_PowerF(2.0f, 4.1), 17.148376f, 0.0001f);
|
||||
EXPECT_NEAR(HMM_PowerF(2.0f, -2.5), 0.176777f, 0.0001f);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
201
test/categories/Subtraction.h
Normal file
201
test/categories/Subtraction.h
Normal file
@@ -0,0 +1,201 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(Subtraction, Vec2)
|
||||
{
|
||||
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 2.0f);
|
||||
hmm_vec2 v2_2 = HMM_Vec2(3.0f, 4.0f);
|
||||
|
||||
{
|
||||
hmm_vec2 result = HMM_SubtractVec2(v2_1, v2_2);
|
||||
EXPECT_FLOAT_EQ(result.X, -2.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, -2.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec2 result = HMM_Subtract(v2_1, v2_2);
|
||||
EXPECT_FLOAT_EQ(result.X, -2.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, -2.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec2 result = v2_1 - v2_2;
|
||||
EXPECT_FLOAT_EQ(result.X, -2.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, -2.0f);
|
||||
}
|
||||
|
||||
v2_1 -= v2_2;
|
||||
EXPECT_FLOAT_EQ(v2_1.X, -2.0f);
|
||||
EXPECT_FLOAT_EQ(v2_1.Y, -2.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Subtraction, Vec3)
|
||||
{
|
||||
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
|
||||
hmm_vec3 v3_2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
|
||||
|
||||
{
|
||||
hmm_vec3 result = HMM_SubtractVec3(v3_1, v3_2);
|
||||
EXPECT_FLOAT_EQ(result.X, -3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, -3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, -3.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec3 result = HMM_Subtract(v3_1, v3_2);
|
||||
EXPECT_FLOAT_EQ(result.X, -3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, -3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, -3.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec3 result = v3_1 - v3_2;
|
||||
EXPECT_FLOAT_EQ(result.X, -3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, -3.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, -3.0f);
|
||||
}
|
||||
|
||||
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_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
hmm_vec4 v4_2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
|
||||
|
||||
{
|
||||
hmm_vec4 result = HMM_SubtractVec4(v4_1, v4_2);
|
||||
EXPECT_FLOAT_EQ(result.X, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, -4.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec4 result = HMM_Subtract(v4_1, v4_2);
|
||||
EXPECT_FLOAT_EQ(result.X, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, -4.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec4 result = v4_1 - v4_2;
|
||||
EXPECT_FLOAT_EQ(result.X, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, -4.0f);
|
||||
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, Mat4)
|
||||
{
|
||||
hmm_mat4 m4_1 = HMM_Mat4(); // will have 1 - 16
|
||||
hmm_mat4 m4_2 = HMM_Mat4(); // will have 17 - 32
|
||||
|
||||
// Fill the matrices
|
||||
int Counter = 1;
|
||||
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_SubtractMat4(m4_1, m4_2);
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(result.Elements[Column][Row], -16.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_mat4 result = HMM_Subtract(m4_1, m4_2);
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(result.Elements[Column][Row], -16.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
hmm_mat4 result = m4_1 - m4_2;
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
for (int Row = 0; Row < 4; ++Row)
|
||||
{
|
||||
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_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f);
|
||||
|
||||
{
|
||||
hmm_quaternion result = HMM_SubtractQuaternion(q1, q2);
|
||||
EXPECT_FLOAT_EQ(result.X, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, -4.0f);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_quaternion result = HMM_Subtract(q1, q2);
|
||||
EXPECT_FLOAT_EQ(result.X, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, -4.0f);
|
||||
}
|
||||
{
|
||||
hmm_quaternion result = q1 - q2;
|
||||
EXPECT_FLOAT_EQ(result.X, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, -4.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, -4.0f);
|
||||
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
|
||||
}
|
||||
77
test/categories/Transformation.h
Normal file
77
test/categories/Transformation.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(Transformations, Translate)
|
||||
{
|
||||
hmm_mat4 translate = HMM_Translate(HMM_Vec3(1.0f, -3.0f, 6.0f));
|
||||
|
||||
hmm_vec3 original = HMM_Vec3(1.0f, 2.0f, 3.0f);
|
||||
hmm_vec4 translated = HMM_MultiplyMat4ByVec4(translate, HMM_Vec4v(original, 1));
|
||||
|
||||
EXPECT_FLOAT_EQ(translated.X, 2.0f);
|
||||
EXPECT_FLOAT_EQ(translated.Y, -1.0f);
|
||||
EXPECT_FLOAT_EQ(translated.Z, 9.0f);
|
||||
EXPECT_FLOAT_EQ(translated.W, 1.0f);
|
||||
}
|
||||
|
||||
TEST(Transformations, Rotate)
|
||||
{
|
||||
hmm_vec3 original = HMM_Vec3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
hmm_mat4 rotateX = HMM_Rotate(90, HMM_Vec3(1, 0, 0));
|
||||
hmm_vec4 rotatedX = HMM_MultiplyMat4ByVec4(rotateX, HMM_Vec4v(original, 1));
|
||||
EXPECT_FLOAT_EQ(rotatedX.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(rotatedX.Y, -1.0f);
|
||||
EXPECT_FLOAT_EQ(rotatedX.Z, 1.0f);
|
||||
EXPECT_FLOAT_EQ(rotatedX.W, 1.0f);
|
||||
|
||||
hmm_mat4 rotateY = HMM_Rotate(90, HMM_Vec3(0, 1, 0));
|
||||
hmm_vec4 rotatedY = HMM_MultiplyMat4ByVec4(rotateY, HMM_Vec4v(original, 1));
|
||||
EXPECT_FLOAT_EQ(rotatedY.X, 1.0f);
|
||||
EXPECT_FLOAT_EQ(rotatedY.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(rotatedY.Z, -1.0f);
|
||||
EXPECT_FLOAT_EQ(rotatedY.W, 1.0f);
|
||||
|
||||
hmm_mat4 rotateZ = HMM_Rotate(90, HMM_Vec3(0, 0, 1));
|
||||
hmm_vec4 rotatedZ = HMM_MultiplyMat4ByVec4(rotateZ, HMM_Vec4v(original, 1));
|
||||
EXPECT_FLOAT_EQ(rotatedZ.X, -1.0f);
|
||||
EXPECT_FLOAT_EQ(rotatedZ.Y, 1.0f);
|
||||
EXPECT_FLOAT_EQ(rotatedZ.Z, 1.0f);
|
||||
EXPECT_FLOAT_EQ(rotatedZ.W, 1.0f);
|
||||
}
|
||||
|
||||
TEST(Transformations, Scale)
|
||||
{
|
||||
hmm_mat4 scale = HMM_Scale(HMM_Vec3(2.0f, -3.0f, 0.5f));
|
||||
|
||||
hmm_vec3 original = HMM_Vec3(1.0f, 2.0f, 3.0f);
|
||||
hmm_vec4 scaled = HMM_MultiplyMat4ByVec4(scale, HMM_Vec4v(original, 1));
|
||||
|
||||
EXPECT_FLOAT_EQ(scaled.X, 2.0f);
|
||||
EXPECT_FLOAT_EQ(scaled.Y, -6.0f);
|
||||
EXPECT_FLOAT_EQ(scaled.Z, 1.5f);
|
||||
EXPECT_FLOAT_EQ(scaled.W, 1.0f);
|
||||
}
|
||||
|
||||
TEST(Transformations, LookAt)
|
||||
{
|
||||
const float abs_error = 0.0001f;
|
||||
|
||||
hmm_mat4 result = HMM_LookAt(HMM_Vec3(1.0f, 0.0f, 0.0f), HMM_Vec3(0.0f, 2.0f, 1.0f), HMM_Vec3(2.0f, 1.0f, 1.0f));
|
||||
|
||||
EXPECT_NEAR(result.Elements[0][0], 0.169031f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[0][1], 0.897085f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[0][2], 0.408248f, abs_error);
|
||||
EXPECT_FLOAT_EQ(result.Elements[0][3], 0.0f);
|
||||
EXPECT_NEAR(result.Elements[1][0], 0.507093f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[1][1], 0.276026f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[1][2], -0.816497f, abs_error);
|
||||
EXPECT_FLOAT_EQ(result.Elements[1][3], 0.0f);
|
||||
EXPECT_NEAR(result.Elements[2][0], -0.845154f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[2][1], 0.345033f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[2][2], -0.408248f, abs_error);
|
||||
EXPECT_FLOAT_EQ(result.Elements[2][3], 0.0f);
|
||||
EXPECT_NEAR(result.Elements[3][0], -0.169031f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[3][1], -0.897085f, abs_error);
|
||||
EXPECT_NEAR(result.Elements[3][2], -0.408248f, abs_error);
|
||||
EXPECT_FLOAT_EQ(result.Elements[3][3], 1.0f);
|
||||
}
|
||||
180
test/categories/VectorOps.h
Normal file
180
test/categories/VectorOps.h
Normal file
@@ -0,0 +1,180 @@
|
||||
#include "../HandmadeTest.h"
|
||||
|
||||
TEST(VectorOps, LengthSquared)
|
||||
{
|
||||
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f);
|
||||
hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f);
|
||||
hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, 1.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec2(v2), 5.0f);
|
||||
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec3(v3), 14.0f);
|
||||
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec4(v4), 15.0f);
|
||||
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(HMM_LengthSquared(v2), 5.0f);
|
||||
EXPECT_FLOAT_EQ(HMM_LengthSquared(v3), 14.0f);
|
||||
EXPECT_FLOAT_EQ(HMM_LengthSquared(v4), 15.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(VectorOps, Length)
|
||||
{
|
||||
hmm_vec2 v2 = HMM_Vec2(1.0f, -9.0f);
|
||||
hmm_vec3 v3 = HMM_Vec3(2.0f, -3.0f, 6.0f);
|
||||
hmm_vec4 v4 = HMM_Vec4(2.0f, -3.0f, 6.0f, 12.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(HMM_LengthVec2(v2), 9.0553856f);
|
||||
EXPECT_FLOAT_EQ(HMM_LengthVec3(v3), 7.0f);
|
||||
EXPECT_FLOAT_EQ(HMM_LengthVec4(v4), 13.892444f);
|
||||
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(HMM_Length(v2), 9.0553856f);
|
||||
EXPECT_FLOAT_EQ(HMM_Length(v3), 7.0f);
|
||||
EXPECT_FLOAT_EQ(HMM_Length(v4), 13.892444f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(VectorOps, Normalize)
|
||||
{
|
||||
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f);
|
||||
hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f);
|
||||
hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, -1.0f);
|
||||
|
||||
{
|
||||
hmm_vec2 result = HMM_NormalizeVec2(v2);
|
||||
EXPECT_FLOAT_EQ(HMM_LengthVec2(result), 1.0f);
|
||||
EXPECT_GT(result.X, 0.0f);
|
||||
EXPECT_LT(result.Y, 0.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec3 result = HMM_NormalizeVec3(v3);
|
||||
EXPECT_FLOAT_EQ(HMM_LengthVec3(result), 1.0f);
|
||||
EXPECT_GT(result.X, 0.0f);
|
||||
EXPECT_LT(result.Y, 0.0f);
|
||||
EXPECT_GT(result.Z, 0.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec4 result = HMM_NormalizeVec4(v4);
|
||||
EXPECT_FLOAT_EQ(HMM_LengthVec4(result), 1.0f);
|
||||
EXPECT_GT(result.X, 0.0f);
|
||||
EXPECT_LT(result.Y, 0.0f);
|
||||
EXPECT_GT(result.Z, 0.0f);
|
||||
EXPECT_LT(result.W, 0.0f);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec2 result = HMM_Normalize(v2);
|
||||
EXPECT_FLOAT_EQ(HMM_LengthVec2(result), 1.0f);
|
||||
EXPECT_GT(result.X, 0.0f);
|
||||
EXPECT_LT(result.Y, 0.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec3 result = HMM_Normalize(v3);
|
||||
EXPECT_FLOAT_EQ(HMM_LengthVec3(result), 1.0f);
|
||||
EXPECT_GT(result.X, 0.0f);
|
||||
EXPECT_LT(result.Y, 0.0f);
|
||||
EXPECT_GT(result.Z, 0.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec4 result = HMM_Normalize(v4);
|
||||
EXPECT_FLOAT_EQ(HMM_LengthVec4(result), 1.0f);
|
||||
EXPECT_GT(result.X, 0.0f);
|
||||
EXPECT_LT(result.Y, 0.0f);
|
||||
EXPECT_GT(result.Z, 0.0f);
|
||||
EXPECT_LT(result.W, 0.0f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(VectorOps, NormalizeZero)
|
||||
{
|
||||
hmm_vec2 v2 = HMM_Vec2(0.0f, 0.0f);
|
||||
hmm_vec3 v3 = HMM_Vec3(0.0f, 0.0f, 0.0f);
|
||||
hmm_vec4 v4 = HMM_Vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
{
|
||||
hmm_vec2 result = HMM_NormalizeVec2(v2);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec3 result = HMM_NormalizeVec3(v3);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 0.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec4 result = HMM_NormalizeVec4(v4);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 0.0f);
|
||||
EXPECT_FLOAT_EQ(result.W, 0.0f);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
{
|
||||
hmm_vec2 result = HMM_Normalize(v2);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec3 result = HMM_Normalize(v3);
|
||||
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
||||
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||
EXPECT_FLOAT_EQ(result.Z, 0.0f);
|
||||
}
|
||||
{
|
||||
hmm_vec4 result = HMM_Normalize(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_Vec3(1.0f, 2.0f, 3.0f);
|
||||
hmm_vec3 v2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
|
||||
|
||||
hmm_vec3 result = HMM_Cross(v1, v2);
|
||||
|
||||
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_Vec2(1.0f, 2.0f);
|
||||
hmm_vec2 v2 = HMM_Vec2(3.0f, 4.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(HMM_DotVec2(v1, v2), 11.0f);
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 11.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(VectorOps, DotVec3)
|
||||
{
|
||||
hmm_vec3 v1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
|
||||
hmm_vec3 v2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(HMM_DotVec3(v1, v2), 32.0f);
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 32.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(VectorOps, DotVec4)
|
||||
{
|
||||
hmm_vec4 v1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
hmm_vec4 v2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(HMM_DotVec4(v1, v2), 70.0f);
|
||||
#ifdef __cplusplus
|
||||
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 70.0f);
|
||||
#endif
|
||||
}
|
||||
1942
test/hmm_test.c
1942
test/hmm_test.c
File diff suppressed because it is too large
Load Diff
18
test/hmm_test.h
Normal file
18
test/hmm_test.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <float.h>
|
||||
|
||||
#include "HandmadeTest.h"
|
||||
#include "../HandmadeMath.h"
|
||||
|
||||
#include "categories/Addition.h"
|
||||
#include "categories/Division.h"
|
||||
#include "categories/Equality.h"
|
||||
#include "categories/Initialization.h"
|
||||
#include "categories/MatrixOps.h"
|
||||
#include "categories/Multiplication.h"
|
||||
#include "categories/Projection.h"
|
||||
#include "categories/QuaternionOps.h"
|
||||
#include "categories/ScalarMath.h"
|
||||
#include "categories/SSE.h"
|
||||
#include "categories/Subtraction.h"
|
||||
#include "categories/Transformation.h"
|
||||
#include "categories/VectorOps.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
|
||||
Reference in New Issue
Block a user