--- /dev/null
+#include "screen_trunner.h"
+
+// standard library includes
+#include <raylib.h>
+
+#include <cassert>
+#include <cmath>
+
+// local includes
+#include "3d_helpers.h"
+
+TRunnerScreen::TRunnerScreen(std::weak_ptr<ScreenStack> stack)
+ : Screen(stack),
+ camera{Vector3{0.0F, 0.0F, 0.0F}, Vector3{0.0F, 0.0F, -1.0F},
+ Vector3{0.0F, 1.0F, 0.0F}, 80.0F, CAMERA_PERSPECTIVE},
+ flags(),
+ TEMP_cube(GenMeshCube(2.0F, 2.0F, 2.0F)),
+ TEMP_default_material(LoadMaterialDefault()),
+ TEMP_matrix(get_identity_matrix()),
+ TEMP_offset_matrix(translate_matrix_z(-4.0F)),
+ grid_spacing(1.0F),
+ grid_spacing_modifier(0.0F) {}
+
+TRunnerScreen::~TRunnerScreen() {
+ UnloadMesh(TEMP_cube);
+ UnloadMaterial(TEMP_default_material);
+}
+
+bool TRunnerScreen::update(float dt) {
+ // grid_spacing_modifier += dt * GRID_SPACING_RATE;
+ // if (grid_spacing_modifier > 2.0F * PI) {
+ // grid_spacing_modifier -= 2.0F * PI;
+ // }
+ // grid_spacing = std::sin(grid_spacing_modifier) + GRID_SPACING_OFFSET;
+ TEMP_matrix = get_rotation_matrix_about_z(dt) *
+ get_rotation_matrix_about_y(dt * 1.2F) *
+ get_rotation_matrix_about_x(dt * 1.4F) * TEMP_matrix;
+ return false;
+}
+
+bool TRunnerScreen::draw() {
+ BeginDrawing();
+ ClearBackground(PixelToColor(Pixel::PIXEL_SKY));
+ BeginMode3D(camera);
+
+ 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();
+ EndDrawing();
+
+ return false;
+}
+
+Color TRunnerScreen::PixelToColor(Pixel p) {
+ switch (p) {
+ case PIXEL_BLANK:
+ return Color{0, 0, 0, 0};
+ case PIXEL_BLACK:
+ return Color{0, 0, 0, 255};
+ case PIXEL_RED:
+ return Color{255, 50, 50, 255};
+ case PIXEL_GREEN:
+ return Color{50, 255, 50, 255};
+ case PIXEL_BLUE:
+ return Color{50, 50, 255, 255};
+ case PIXEL_YELLOW:
+ return Color{255, 255, 0, 255};
+ case PIXEL_CYAN:
+ return Color{0, 255, 255, 255};
+ case PIXEL_MAGENTA:
+ return Color{255, 0, 255, 255};
+ case PIXEL_ORANGE:
+ return Color{255, 200, 0, 255};
+ case PIXEL_BROWN:
+ return Color{180, 130, 0, 255};
+ case PIXEL_TURQUOISE:
+ return Color{0, 255, 200, 255};
+ case PIXEL_SKY:
+ return Color{168, 178, 255, 255};
+ case PIXEL_WHITE:
+ return Color{255, 255, 255, 255};
+ default:
+ assert(!"unreachable");
+ return Color{0, 0, 0, 255};
+ }
+}
--- /dev/null
+// standard library includes
+#include <iostream>
+
+// local includes
+#include "../3d_helpers.h"
+
+#define ASSERT_TRUE(v) \
+ if (!(v)) { \
+ std::cerr << "False in ASSERT_TRUE at line " << __LINE__ << "!\n"; \
+ }
+
+#define ASSERT_FALSE(v) \
+ if (v) { \
+ std::cerr << "True in ASSERT_FALSE at line " << __LINE__ << "!\n"; \
+ }
+
+#define ASSERT_FLOAT_EQUALS(f, v) \
+ 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"; \
+ }
+
+
+int main() {
+ std::cout << "Testing 3d_helpers...\n";
+ {
+ auto identity = get_identity_matrix();
+ ASSERT_TRUE(identity.m0 == 1.0F);
+ ASSERT_TRUE(identity.m1 == 0.0F);
+ ASSERT_TRUE(identity.m2 == 0.0F);
+ ASSERT_TRUE(identity.m3 == 0.0F);
+
+ ASSERT_TRUE(identity.m4 == 0.0F);
+ ASSERT_TRUE(identity.m5 == 1.0F);
+ ASSERT_TRUE(identity.m6 == 0.0F);
+ ASSERT_TRUE(identity.m7 == 0.0F);
+
+ ASSERT_TRUE(identity.m8 == 0.0F);
+ ASSERT_TRUE(identity.m9 == 0.0F);
+ ASSERT_TRUE(identity.m10 == 1.0F);
+ ASSERT_TRUE(identity.m11 == 0.0F);
+
+ ASSERT_TRUE(identity.m12 == 0.0F);
+ ASSERT_TRUE(identity.m13 == 0.0F);
+ ASSERT_TRUE(identity.m14 == 0.0F);
+ ASSERT_TRUE(identity.m15 == 1.0F);
+
+ identity = identity * get_identity_matrix();
+ ASSERT_FLOAT_EQUALS(identity.m0, 1.0F);
+ ASSERT_FLOAT_EQUALS(identity.m1, 0.0F);
+ ASSERT_FLOAT_EQUALS(identity.m2, 0.0F);
+ ASSERT_FLOAT_EQUALS(identity.m3, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(identity.m4, 0.0F);
+ ASSERT_FLOAT_EQUALS(identity.m5, 1.0F);
+ ASSERT_FLOAT_EQUALS(identity.m6, 0.0F);
+ ASSERT_FLOAT_EQUALS(identity.m7, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(identity.m8, 0.0F);
+ ASSERT_FLOAT_EQUALS(identity.m9, 0.0F);
+ ASSERT_FLOAT_EQUALS(identity.m10, 1.0F);
+ ASSERT_FLOAT_EQUALS(identity.m11, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(identity.m12, 0.0F);
+ ASSERT_FLOAT_EQUALS(identity.m13, 0.0F);
+ ASSERT_FLOAT_EQUALS(identity.m14, 0.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.
+ auto m = get_rotation_matrix_about_z(PI / 2.0F) * get_identity_matrix();
+ ASSERT_FLOAT_EQUALS(m.m0, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m1, -1.0F);
+ ASSERT_FLOAT_EQUALS(m.m2, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m3, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m4, 1.0F);
+ ASSERT_FLOAT_EQUALS(m.m5, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m6, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m7, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m8, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m9, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m10, 1.0F);
+ ASSERT_FLOAT_EQUALS(m.m11, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m12, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m13, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m14, 0.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.
+ 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.m1, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m2, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m3, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m4, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m5, -1.0F);
+ ASSERT_FLOAT_EQUALS(m.m6, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m7, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m8, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m9, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m10, 1.0F);
+ ASSERT_FLOAT_EQUALS(m.m11, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m12, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m13, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m14, 0.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.
+ m = get_rotation_matrix_about_z(-PI/2.0F) * m;
+ ASSERT_FLOAT_EQUALS(m.m0, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m1, -1.0F);
+ ASSERT_FLOAT_EQUALS(m.m2, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m3, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m4, 1.0F);
+ ASSERT_FLOAT_EQUALS(m.m5, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m6, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m7, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m8, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m9, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m10, 1.0F);
+ ASSERT_FLOAT_EQUALS(m.m11, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m12, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m13, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m14, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m15, 1.0F);
+ }
+ {
+ // Rotate about y-axis 90 degrees.
+ auto m = get_rotation_matrix_about_y(PI/2.0F);
+ ASSERT_FLOAT_EQUALS(m.m0, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m1, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m2, 1.0F);
+ ASSERT_FLOAT_EQUALS(m.m3, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m4, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m5, 1.0F);
+ ASSERT_FLOAT_EQUALS(m.m6, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m7, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m8, -1.0F);
+ ASSERT_FLOAT_EQUALS(m.m9, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m10, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m11, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m12, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m13, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m14, 0.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.
+ m = get_rotation_matrix_about_y(PI/2.0F) * m;
+ ASSERT_FLOAT_EQUALS(m.m0, -1.0F);
+ ASSERT_FLOAT_EQUALS(m.m1, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m2, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m3, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m4, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m5, 1.0F);
+ ASSERT_FLOAT_EQUALS(m.m6, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m7, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m8, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m9, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m10, -1.0F);
+ ASSERT_FLOAT_EQUALS(m.m11, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m12, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m13, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m14, 0.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.
+ auto m = get_rotation_matrix_about_x(PI/2.0F);
+ ASSERT_FLOAT_EQUALS(m.m0, 1.0F);
+ ASSERT_FLOAT_EQUALS(m.m1, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m2, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m3, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m4, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m5, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m6, -1.0F);
+ ASSERT_FLOAT_EQUALS(m.m7, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m8, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m9, 1.0F);
+ ASSERT_FLOAT_EQUALS(m.m10, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m11, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m12, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m13, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m14, 0.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.
+ m = get_rotation_matrix_about_x(PI/2.0F) * m;
+ ASSERT_FLOAT_EQUALS(m.m0, 1.0F);
+ ASSERT_FLOAT_EQUALS(m.m1, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m2, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m3, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m4, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m5, -1.0F);
+ ASSERT_FLOAT_EQUALS(m.m6, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m7, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m8, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m9, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m10, -1.0F);
+ ASSERT_FLOAT_EQUALS(m.m11, 0.0F);
+
+ ASSERT_FLOAT_EQUALS(m.m12, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m13, 0.0F);
+ ASSERT_FLOAT_EQUALS(m.m14, 0.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";
+ return 0;
+}