Rotation Matrices should now match the "right-handled rule".

Fixes related to weirdness using the column-major ordered Matrix struct.
This commit is contained in:
Stephen Seo 2023-08-04 11:42:11 +09:00
parent c99407a474
commit f0ce6520f4
9 changed files with 2223 additions and 299 deletions

View file

@ -15,7 +15,8 @@ SOURCES = \
src/screen.cc \ src/screen.cc \
src/screen_test.cc \ src/screen_test.cc \
src/screen_trunner.cc \ src/screen_trunner.cc \
src/3d_helpers.cc src/3d_helpers.cc \
src/raymath.cc
HEADERS = \ HEADERS = \
src/game.h \ src/game.h \
@ -47,7 +48,7 @@ clean:
rm -f test rm -f test
format: format:
clang-format -i --style=google ${HEADERS} ${SOURCES} clang-format -i --style=google ${HEADERS} ${SOURCES} ${TEST_SOURCES}
.SECONDEXPANSION: .SECONDEXPANSION:

View file

@ -3,6 +3,9 @@
// standard library includes // standard library includes
#include <cmath> #include <cmath>
// third party includes
#include <raymath.h>
Matrix get_identity_matrix() { Matrix get_identity_matrix() {
return Matrix{1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, return Matrix{1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F,
0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F}; 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F};
@ -20,12 +23,12 @@ Matrix get_identity_matrix() {
// 0, 0, 0, 1 // 0, 0, 0, 1
Matrix get_rotation_matrix_about_z(float radians) { Matrix get_rotation_matrix_about_z(float radians) {
// OpenGL is column-major. // OpenGL is column-major but testing shows that not transposing works.
return Matrix{std::cos(radians), return Matrix{std::cos(radians),
std::sin(radians),
0.0F,
0.0F,
-std::sin(radians), -std::sin(radians),
0.0F,
0.0F,
std::sin(radians),
std::cos(radians), std::cos(radians),
0.0F, 0.0F,
0.0F, 0.0F,
@ -46,16 +49,16 @@ Matrix get_rotation_matrix_about_z(float radians) {
// 0, 0, 0, 1 // 0, 0, 0, 1
Matrix get_rotation_matrix_about_y(float radians) { Matrix get_rotation_matrix_about_y(float radians) {
// OpenGL is column-major. // OpenGL is column-major but testing shows that not transposing works.
return Matrix{std::cos(radians), return Matrix{std::cos(radians),
0.0F, 0.0F,
-std::sin(radians), std::sin(radians),
0.0F, 0.0F,
0.0F, 0.0F,
1.0F, 1.0F,
0.0F, 0.0F,
0.0F, 0.0F,
std::sin(radians), -std::sin(radians),
0.0F, 0.0F,
std::cos(radians), std::cos(radians),
0.0F, 0.0F,
@ -72,17 +75,17 @@ Matrix get_rotation_matrix_about_y(float radians) {
// 0, 0, 0, 1 // 0, 0, 0, 1
Matrix get_rotation_matrix_about_x(float radians) { Matrix get_rotation_matrix_about_x(float radians) {
// OpenGL is column-major. // OpenGL is column-major but testing shows that not transposing works.
return Matrix{1.0F, return Matrix{1.0F,
0.0F, 0.0F,
0.0F, 0.0F,
0.0F, 0.0F,
0.0F, 0.0F,
std::cos(radians), std::cos(radians),
std::sin(radians),
0.0F,
0.0F,
-std::sin(radians), -std::sin(radians),
0.0F,
0.0F,
std::sin(radians),
std::cos(radians), std::cos(radians),
0.0F, 0.0F,
0.0F, 0.0F,
@ -91,38 +94,29 @@ Matrix get_rotation_matrix_about_x(float radians) {
1.0F}; 1.0F};
} }
Matrix translate_matrix_x(float distance) {
// OpenGL is column-major but testing shows that not transposing works.
return Matrix{1.0F, 0.0F, 0.0F, distance, 0.0F, 1.0F, 0.0F, 0.0F,
0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F};
}
Matrix translate_matrix_y(float distance) {
// OpenGL is column-major but testing shows that not transposing works.
return Matrix{1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, distance,
0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F};
}
Matrix translate_matrix_z(float distance) { Matrix translate_matrix_z(float distance) {
// OpenGL is column-major but testing shows that not transposing works.
return Matrix{1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, return Matrix{1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F,
0.0F, 0.0F, 1.0F, distance, 0.0F, 0.0F, 0.0F, 1.0F}; 0.0F, 0.0F, 1.0F, distance, 0.0F, 0.0F, 0.0F, 1.0F};
} }
Matrix translate_matrix_xyz(float x, float y, float z) {
return Matrix{1.0F, 0.0F, 0.0F, x, 0.0F, 1.0F, 0.0F, y,
0.0F, 0.0F, 1.0F, z, 0.0F, 0.0F, 0.0F, 1.0F};
}
Matrix operator*(const Matrix &a, const Matrix &b) { Matrix operator*(const Matrix &a, const Matrix &b) {
return Matrix{a.m0 * b.m0 + a.m1 * b.m4 + a.m2 * b.m8 + a.m3 * b.m12, return MatrixMultiply(a, b);
a.m4 * b.m0 + a.m5 * b.m4 + a.m6 * b.m8 + a.m7 * b.m12,
a.m8 * b.m0 + a.m9 * b.m4 + a.m10 * b.m8 + a.m11 * b.m12,
a.m12 * b.m0 + a.m13 * b.m4 + a.m14 * b.m8 + a.m15 * b.m12,
a.m0 * b.m1 + a.m1 * b.m5 + a.m2 * b.m9 + a.m3 * b.m13,
a.m4 * b.m1 + a.m5 * b.m5 + a.m6 * b.m9 + a.m7 * b.m13,
a.m8 * b.m1 + a.m9 * b.m5 + a.m10 * b.m9 + a.m11 * b.m13,
a.m12 * b.m1 + a.m13 * b.m5 + a.m14 * b.m9 + a.m15 * b.m13,
a.m0 * b.m2 + a.m1 * b.m6 + a.m2 * b.m10 + a.m3 * b.m14,
a.m4 * b.m2 + a.m5 * b.m6 + a.m6 * b.m10 + a.m7 * b.m14,
a.m8 * b.m2 + a.m9 * b.m6 + a.m10 * b.m10 + a.m11 * b.m14,
a.m12 * b.m2 + a.m13 * b.m6 + a.m14 * b.m10 + a.m15 * b.m14,
a.m0 * b.m3 + a.m1 * b.m7 + a.m2 * b.m11 + a.m3 * b.m15,
a.m4 * b.m3 + a.m5 * b.m7 + a.m6 * b.m11 + a.m7 * b.m15,
a.m8 * b.m3 + a.m9 * b.m7 + a.m10 * b.m11 + a.m11 * b.m15,
a.m12 * b.m3 + a.m13 * b.m7 + a.m14 * b.m11 + a.m15 * b.m15};
}
Vector4 operator*(const Matrix &m, const Vector4 &v) {
return Vector4{
m.m0 * v.x + m.m1 * v.y + m.m2 * v.z + m.m3 * v.w,
m.m4 * v.x + m.m5 * v.y + m.m6 * v.z + m.m7 * v.w,
m.m8 * v.x + m.m9 * v.y + m.m10 * v.z + m.m11 * v.w,
m.m12 * v.x + m.m13 * v.y + m.m14 * v.z + m.m15 * v.w,
};
} }

View file

@ -9,9 +9,15 @@ extern Matrix get_rotation_matrix_about_z(float radians);
extern Matrix get_rotation_matrix_about_y(float radians); extern Matrix get_rotation_matrix_about_y(float radians);
extern Matrix get_rotation_matrix_about_x(float radians); extern Matrix get_rotation_matrix_about_x(float radians);
extern Matrix translate_matrix_x(float distance);
extern Matrix translate_matrix_y(float distance);
extern Matrix translate_matrix_z(float distance); extern Matrix translate_matrix_z(float distance);
extern Matrix translate_matrix_xyz(float x, float y, float z);
extern Matrix operator*(const Matrix &a, const Matrix &b); extern Matrix operator*(const Matrix &a, const Matrix &b);
extern Vector4 operator*(const Matrix &m, const Vector4 &v);
// Unimplemented as this function isn't really needed and it exposes some
// weirdness regarding column-major matrices.
// extern Vector4 operator*(const Matrix &m, const Vector4 &v);
#endif #endif

2
src/raymath.cc Normal file
View file

@ -0,0 +1,2 @@
#define RAYMATH_IMPLEMENTATION
#include <raymath.h>

View file

@ -18,8 +18,7 @@ TRunnerScreen::TRunnerScreen(std::weak_ptr<ScreenStack> stack)
TEMP_default_material(LoadMaterialDefault()), TEMP_default_material(LoadMaterialDefault()),
TEMP_matrix(get_identity_matrix()), TEMP_matrix(get_identity_matrix()),
TEMP_offset_matrix(translate_matrix_z(-4.0F)), TEMP_offset_matrix(translate_matrix_z(-4.0F)),
grid_spacing(1.0F), TEMP_value(0.0F) {}
grid_spacing_modifier(0.0F) {}
TRunnerScreen::~TRunnerScreen() { TRunnerScreen::~TRunnerScreen() {
UnloadMesh(TEMP_cube); UnloadMesh(TEMP_cube);
@ -27,14 +26,17 @@ TRunnerScreen::~TRunnerScreen() {
} }
bool TRunnerScreen::update(float dt) { bool TRunnerScreen::update(float dt) {
// grid_spacing_modifier += dt * GRID_SPACING_RATE; TEMP_value += TEMP_VALUE_INC_RATE * dt;
// if (grid_spacing_modifier > 2.0F * PI) { if (TEMP_value < PI / 2.0F) {
// grid_spacing_modifier -= 2.0F * PI; TEMP_matrix = get_rotation_matrix_about_z(TEMP_value);
// } } else if (TEMP_value < PI) {
// grid_spacing = std::sin(grid_spacing_modifier) + GRID_SPACING_OFFSET; TEMP_matrix = get_rotation_matrix_about_y(TEMP_value - PI / 2.0F);
TEMP_matrix = get_rotation_matrix_about_z(dt) * } else if (TEMP_value < PI * 3.0F / 2.0F) {
get_rotation_matrix_about_y(dt * 1.2F) * TEMP_matrix = get_rotation_matrix_about_x(TEMP_value - PI);
get_rotation_matrix_about_x(dt * 1.4F) * TEMP_matrix; } else {
TEMP_value -= PI * 3.0F / 2.0F;
TEMP_matrix = get_rotation_matrix_about_z(TEMP_value);
}
return false; return false;
} }
@ -45,39 +47,6 @@ bool TRunnerScreen::draw() {
DrawMesh(TEMP_cube, TEMP_default_material, TEMP_matrix * TEMP_offset_matrix); DrawMesh(TEMP_cube, TEMP_default_material, TEMP_matrix * TEMP_offset_matrix);
// for (unsigned int i = 11; i-- > 1;) {
// // upper
// DrawRay(Ray{Vector3{0.0F, 2.0F, -(0.5F + grid_spacing * (float)i)},
// Vector3{1.0F, 0.0F, 0.0F}},
// BLACK);
// DrawRay(Ray{Vector3{0.0F, 2.0F, -(0.5F + grid_spacing * (float)i)},
// Vector3{-1.0F, 0.0F, 0.0F}},
// BLACK);
//
// // lower
// DrawRay(Ray{Vector3{0.0F, -2.0F, -(0.5F + grid_spacing * (float)i)},
// Vector3{1.0F, 0.0F, 0.0F}},
// BLACK);
// DrawRay(Ray{Vector3{0.0F, -2.0F, -(0.5F + grid_spacing * (float)i)},
// Vector3{-1.0F, 0.0F, 0.0F}},
// BLACK);
//
// // left
// DrawRay(Ray{Vector3{-2.0F, 0.0F, -(0.5F + grid_spacing * (float)i)},
// Vector3{0.0F, 1.0F, 0.0F}},
// BLACK);
// DrawRay(Ray{Vector3{-2.0F, 0.0F, -(0.5F + grid_spacing * (float)i)},
// Vector3{0.0F, -1.0F, 0.0F}},
// BLACK);
//
// // right
// DrawRay(Ray{Vector3{2.0F, 0.0F, -(0.5F + grid_spacing * (float)i)},
// Vector3{0.0F, 1.0F, 0.0F}},
// BLACK);
// DrawRay(Ray{Vector3{2.0F, 0.0F, -(0.5F + grid_spacing * (float)i)},
// Vector3{0.0F, -1.0F, 0.0F}},
// BLACK);
// }
EndMode3D(); EndMode3D();
EndDrawing(); EndDrawing();

View file

@ -10,8 +10,7 @@
// third party includes // third party includes
#include <raylib.h> #include <raylib.h>
constexpr float GRID_SPACING_RATE = 1.0F; constexpr float TEMP_VALUE_INC_RATE = 1.0F;
constexpr float GRID_SPACING_OFFSET = 1.5F;
class TRunnerScreen : public Screen { class TRunnerScreen : public Screen {
public: public:
@ -46,8 +45,7 @@ class TRunnerScreen : public Screen {
Material TEMP_default_material; Material TEMP_default_material;
Matrix TEMP_matrix; Matrix TEMP_matrix;
Matrix TEMP_offset_matrix; Matrix TEMP_offset_matrix;
float grid_spacing; float TEMP_value;
float grid_spacing_modifier;
}; };
#endif #endif

View file

@ -4,24 +4,27 @@
// local includes // local includes
#include "../3d_helpers.h" #include "../3d_helpers.h"
#define ASSERT_TRUE(v) \ #define ASSERT_TRUE(v) \
if (!(v)) { \ if (!(v)) { \
std::cerr << "False in ASSERT_TRUE at line " << __LINE__ << "!\n"; \ std::cerr << "False in ASSERT_TRUE at line " << __LINE__ << "!\n"; \
} }
#define ASSERT_FALSE(v) \ #define ASSERT_FALSE(v) \
if (v) { \ if (v) { \
std::cerr << "True in ASSERT_FALSE at line " << __LINE__ << "!\n"; \ std::cerr << "True in ASSERT_FALSE at line " << __LINE__ << "!\n"; \
} }
#define ASSERT_FLOAT_EQUALS(f, v) \ #define ASSERT_FLOAT_EQUALS(f, v) \
if ((f) < (v) - 0.1F || (f) > (v) + 0.1F) { \ if ((f) < (v)-0.1F || (f) > (v) + 0.1F) { \
std::cerr << "ASSERT_FLOAT_EQUALS: " << (f) << " is not (roughly) equal to " << (v) << " at line " << __LINE__ << "!\n"; \ std::cerr << "ASSERT_FLOAT_EQUALS: " << (f) \
<< " is not (roughly) equal to " << (v) << " at line " \
<< __LINE__ << "!\n"; \
} }
int main() { int main() {
std::cout << "Testing 3d_helpers...\n"; std::cout << "Testing 3d_helpers...\n";
// Note that there is some weirdness regarding column-major ordering of matrix
// values.
{ {
auto identity = get_identity_matrix(); auto identity = get_identity_matrix();
ASSERT_TRUE(identity.m0 == 1.0F); ASSERT_TRUE(identity.m0 == 1.0F);
@ -64,42 +67,17 @@ int main() {
ASSERT_FLOAT_EQUALS(identity.m13, 0.0F); ASSERT_FLOAT_EQUALS(identity.m13, 0.0F);
ASSERT_FLOAT_EQUALS(identity.m14, 0.0F); ASSERT_FLOAT_EQUALS(identity.m14, 0.0F);
ASSERT_FLOAT_EQUALS(identity.m15, 1.0F); ASSERT_FLOAT_EQUALS(identity.m15, 1.0F);
{
auto v = Vector4{1.0F, 0.0F, 0.0F, 1.0F};
auto v_result = identity * v;
ASSERT_FLOAT_EQUALS(v_result.x, 1.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{0.0F, 1.0F, 0.0F, 1.0F};
auto v_result = identity * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 1.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{0.0F, 0.0F, 1.0F, 1.0F};
auto v_result = identity * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 1.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
} }
{ {
// 90 degree rotation and identity matrix. // 90 degree rotation and identity matrix.
auto m = get_rotation_matrix_about_z(PI / 2.0F) * get_identity_matrix(); auto m = get_rotation_matrix_about_z(PI / 2.0F) * get_identity_matrix();
ASSERT_FLOAT_EQUALS(m.m0, 0.0F); ASSERT_FLOAT_EQUALS(m.m0, 0.0F);
ASSERT_FLOAT_EQUALS(m.m1, -1.0F); ASSERT_FLOAT_EQUALS(m.m1, 1.0F);
ASSERT_FLOAT_EQUALS(m.m2, 0.0F); ASSERT_FLOAT_EQUALS(m.m2, 0.0F);
ASSERT_FLOAT_EQUALS(m.m3, 0.0F); ASSERT_FLOAT_EQUALS(m.m3, 0.0F);
ASSERT_FLOAT_EQUALS(m.m4, 1.0F); ASSERT_FLOAT_EQUALS(m.m4, -1.0F);
ASSERT_FLOAT_EQUALS(m.m5, 0.0F); ASSERT_FLOAT_EQUALS(m.m5, 0.0F);
ASSERT_FLOAT_EQUALS(m.m6, 0.0F); ASSERT_FLOAT_EQUALS(m.m6, 0.0F);
ASSERT_FLOAT_EQUALS(m.m7, 0.0F); ASSERT_FLOAT_EQUALS(m.m7, 0.0F);
@ -113,43 +91,11 @@ int main() {
ASSERT_FLOAT_EQUALS(m.m13, 0.0F); ASSERT_FLOAT_EQUALS(m.m13, 0.0F);
ASSERT_FLOAT_EQUALS(m.m14, 0.0F); ASSERT_FLOAT_EQUALS(m.m14, 0.0F);
ASSERT_FLOAT_EQUALS(m.m15, 1.0F); ASSERT_FLOAT_EQUALS(m.m15, 1.0F);
{
auto v = Vector4{1.0F, 0.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 1.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{0.0F, 1.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, -1.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{-1.0F, 0.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, -1.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{0.0F, -1.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 1.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
} }
{ {
// Double 90 degree rotation about z. // Double 90 degree rotation about z.
auto m = get_rotation_matrix_about_z(PI/2.0F) * get_rotation_matrix_about_z(PI/2.0F); auto m = get_rotation_matrix_about_z(PI / 2.0F) *
get_rotation_matrix_about_z(PI / 2.0F);
ASSERT_FLOAT_EQUALS(m.m0, -1.0F); ASSERT_FLOAT_EQUALS(m.m0, -1.0F);
ASSERT_FLOAT_EQUALS(m.m1, 0.0F); ASSERT_FLOAT_EQUALS(m.m1, 0.0F);
ASSERT_FLOAT_EQUALS(m.m2, 0.0F); ASSERT_FLOAT_EQUALS(m.m2, 0.0F);
@ -169,46 +115,15 @@ int main() {
ASSERT_FLOAT_EQUALS(m.m13, 0.0F); ASSERT_FLOAT_EQUALS(m.m13, 0.0F);
ASSERT_FLOAT_EQUALS(m.m14, 0.0F); ASSERT_FLOAT_EQUALS(m.m14, 0.0F);
ASSERT_FLOAT_EQUALS(m.m15, 1.0F); ASSERT_FLOAT_EQUALS(m.m15, 1.0F);
{
auto v = Vector4{1.0F, 0.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, -1.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{0.0F, 1.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, -1.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{-1.0F, 0.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 1.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{0.0F, -1.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 1.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
// Rotate back 90 degrees. // Rotate back 90 degrees.
m = get_rotation_matrix_about_z(-PI/2.0F) * m; m = get_rotation_matrix_about_z(-PI / 2.0F) * m;
ASSERT_FLOAT_EQUALS(m.m0, 0.0F); ASSERT_FLOAT_EQUALS(m.m0, 0.0F);
ASSERT_FLOAT_EQUALS(m.m1, -1.0F); ASSERT_FLOAT_EQUALS(m.m1, 1.0F);
ASSERT_FLOAT_EQUALS(m.m2, 0.0F); ASSERT_FLOAT_EQUALS(m.m2, 0.0F);
ASSERT_FLOAT_EQUALS(m.m3, 0.0F); ASSERT_FLOAT_EQUALS(m.m3, 0.0F);
ASSERT_FLOAT_EQUALS(m.m4, 1.0F); ASSERT_FLOAT_EQUALS(m.m4, -1.0F);
ASSERT_FLOAT_EQUALS(m.m5, 0.0F); ASSERT_FLOAT_EQUALS(m.m5, 0.0F);
ASSERT_FLOAT_EQUALS(m.m6, 0.0F); ASSERT_FLOAT_EQUALS(m.m6, 0.0F);
ASSERT_FLOAT_EQUALS(m.m7, 0.0F); ASSERT_FLOAT_EQUALS(m.m7, 0.0F);
@ -225,10 +140,10 @@ int main() {
} }
{ {
// Rotate about y-axis 90 degrees. // Rotate about y-axis 90 degrees.
auto m = get_rotation_matrix_about_y(PI/2.0F); auto m = get_rotation_matrix_about_y(PI / 2.0F);
ASSERT_FLOAT_EQUALS(m.m0, 0.0F); ASSERT_FLOAT_EQUALS(m.m0, 0.0F);
ASSERT_FLOAT_EQUALS(m.m1, 0.0F); ASSERT_FLOAT_EQUALS(m.m1, 0.0F);
ASSERT_FLOAT_EQUALS(m.m2, 1.0F); ASSERT_FLOAT_EQUALS(m.m2, -1.0F);
ASSERT_FLOAT_EQUALS(m.m3, 0.0F); ASSERT_FLOAT_EQUALS(m.m3, 0.0F);
ASSERT_FLOAT_EQUALS(m.m4, 0.0F); ASSERT_FLOAT_EQUALS(m.m4, 0.0F);
@ -236,7 +151,7 @@ int main() {
ASSERT_FLOAT_EQUALS(m.m6, 0.0F); ASSERT_FLOAT_EQUALS(m.m6, 0.0F);
ASSERT_FLOAT_EQUALS(m.m7, 0.0F); ASSERT_FLOAT_EQUALS(m.m7, 0.0F);
ASSERT_FLOAT_EQUALS(m.m8, -1.0F); ASSERT_FLOAT_EQUALS(m.m8, 1.0F);
ASSERT_FLOAT_EQUALS(m.m9, 0.0F); ASSERT_FLOAT_EQUALS(m.m9, 0.0F);
ASSERT_FLOAT_EQUALS(m.m10, 0.0F); ASSERT_FLOAT_EQUALS(m.m10, 0.0F);
ASSERT_FLOAT_EQUALS(m.m11, 0.0F); ASSERT_FLOAT_EQUALS(m.m11, 0.0F);
@ -246,41 +161,8 @@ int main() {
ASSERT_FLOAT_EQUALS(m.m14, 0.0F); ASSERT_FLOAT_EQUALS(m.m14, 0.0F);
ASSERT_FLOAT_EQUALS(m.m15, 1.0F); ASSERT_FLOAT_EQUALS(m.m15, 1.0F);
{
auto v = Vector4{1.0F, 0.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, -1.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{0.0F, 0.0F, -1.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, -1.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{-1.0F, 0.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 1.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{0.0F, 0.0F, 1.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 1.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
// additional 90 degrees. // additional 90 degrees.
m = get_rotation_matrix_about_y(PI/2.0F) * m; m = get_rotation_matrix_about_y(PI / 2.0F) * m;
ASSERT_FLOAT_EQUALS(m.m0, -1.0F); ASSERT_FLOAT_EQUALS(m.m0, -1.0F);
ASSERT_FLOAT_EQUALS(m.m1, 0.0F); ASSERT_FLOAT_EQUALS(m.m1, 0.0F);
ASSERT_FLOAT_EQUALS(m.m2, 0.0F); ASSERT_FLOAT_EQUALS(m.m2, 0.0F);
@ -300,27 +182,11 @@ int main() {
ASSERT_FLOAT_EQUALS(m.m13, 0.0F); ASSERT_FLOAT_EQUALS(m.m13, 0.0F);
ASSERT_FLOAT_EQUALS(m.m14, 0.0F); ASSERT_FLOAT_EQUALS(m.m14, 0.0F);
ASSERT_FLOAT_EQUALS(m.m15, 1.0F); ASSERT_FLOAT_EQUALS(m.m15, 1.0F);
{
auto v = Vector4{1.0F, 0.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, -1.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{0.0F, 0.0F, -1.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 1.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
} }
{ {
// About x-axis 90 degrees. // About x-axis 90 degrees.
auto m = get_rotation_matrix_about_x(PI/2.0F); auto m = get_rotation_matrix_about_x(PI / 2.0F);
ASSERT_FLOAT_EQUALS(m.m0, 1.0F); ASSERT_FLOAT_EQUALS(m.m0, 1.0F);
ASSERT_FLOAT_EQUALS(m.m1, 0.0F); ASSERT_FLOAT_EQUALS(m.m1, 0.0F);
ASSERT_FLOAT_EQUALS(m.m2, 0.0F); ASSERT_FLOAT_EQUALS(m.m2, 0.0F);
@ -328,11 +194,11 @@ int main() {
ASSERT_FLOAT_EQUALS(m.m4, 0.0F); ASSERT_FLOAT_EQUALS(m.m4, 0.0F);
ASSERT_FLOAT_EQUALS(m.m5, 0.0F); ASSERT_FLOAT_EQUALS(m.m5, 0.0F);
ASSERT_FLOAT_EQUALS(m.m6, -1.0F); ASSERT_FLOAT_EQUALS(m.m6, 1.0F);
ASSERT_FLOAT_EQUALS(m.m7, 0.0F); ASSERT_FLOAT_EQUALS(m.m7, 0.0F);
ASSERT_FLOAT_EQUALS(m.m8, 0.0F); ASSERT_FLOAT_EQUALS(m.m8, 0.0F);
ASSERT_FLOAT_EQUALS(m.m9, 1.0F); ASSERT_FLOAT_EQUALS(m.m9, -1.0F);
ASSERT_FLOAT_EQUALS(m.m10, 0.0F); ASSERT_FLOAT_EQUALS(m.m10, 0.0F);
ASSERT_FLOAT_EQUALS(m.m11, 0.0F); ASSERT_FLOAT_EQUALS(m.m11, 0.0F);
@ -340,40 +206,9 @@ int main() {
ASSERT_FLOAT_EQUALS(m.m13, 0.0F); ASSERT_FLOAT_EQUALS(m.m13, 0.0F);
ASSERT_FLOAT_EQUALS(m.m14, 0.0F); ASSERT_FLOAT_EQUALS(m.m14, 0.0F);
ASSERT_FLOAT_EQUALS(m.m15, 1.0F); ASSERT_FLOAT_EQUALS(m.m15, 1.0F);
{
auto v = Vector4{0.0F, 1.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 1.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{0.0F, 0.0F, 1.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, -1.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{0.0F, -1.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, -1.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{0.0F, 0.0F, -1.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 1.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
// Additional 90 degrees. // Additional 90 degrees.
m = get_rotation_matrix_about_x(PI/2.0F) * m; m = get_rotation_matrix_about_x(PI / 2.0F) * m;
ASSERT_FLOAT_EQUALS(m.m0, 1.0F); ASSERT_FLOAT_EQUALS(m.m0, 1.0F);
ASSERT_FLOAT_EQUALS(m.m1, 0.0F); ASSERT_FLOAT_EQUALS(m.m1, 0.0F);
ASSERT_FLOAT_EQUALS(m.m2, 0.0F); ASSERT_FLOAT_EQUALS(m.m2, 0.0F);
@ -393,22 +228,6 @@ int main() {
ASSERT_FLOAT_EQUALS(m.m13, 0.0F); ASSERT_FLOAT_EQUALS(m.m13, 0.0F);
ASSERT_FLOAT_EQUALS(m.m14, 0.0F); ASSERT_FLOAT_EQUALS(m.m14, 0.0F);
ASSERT_FLOAT_EQUALS(m.m15, 1.0F); ASSERT_FLOAT_EQUALS(m.m15, 1.0F);
{
auto v = Vector4{0.0F, 1.0F, 0.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, -1.0F);
ASSERT_FLOAT_EQUALS(v_result.z, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
{
auto v = Vector4{0.0F, 0.0F, 1.0F, 1.0F};
auto v_result = m * v;
ASSERT_FLOAT_EQUALS(v_result.x, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.y, 0.0F);
ASSERT_FLOAT_EQUALS(v_result.z, -1.0F);
ASSERT_FLOAT_EQUALS(v_result.w, 1.0F);
}
} }
std::cout << "Finished tests.\n"; std::cout << "Finished tests.\n";

View file

@ -11,7 +11,8 @@ SOURCES = \
../src/screen.cc \ ../src/screen.cc \
../src/screen_test.cc \ ../src/screen_test.cc \
../src/screen_trunner.cc \ ../src/screen_trunner.cc \
../src/3d_helpers.cc ../src/3d_helpers.cc \
../src/raymath.cc
HEADERS = \ HEADERS = \
../src/ems.h \ ../src/ems.h \

2134
wasm_include/raymath.h Normal file

File diff suppressed because it is too large Load diff