diff options
author | vimene <vincent.menegaux@gmail.com> | 2023-11-26 06:49:51 +0100 |
---|---|---|
committer | vimene <vincent.menegaux@gmail.com> | 2023-11-26 06:49:51 +0100 |
commit | f63febed2a769d0c55192e192a20b8e39f162932 (patch) | |
tree | f12fef4643e03e93363f902e35d06ef92dd8350d | |
parent | 97f4e5c80483255912b177e6a2557344da499a3e (diff) | |
download | engine-f63febed2a769d0c55192e192a20b8e39f162932.tar.gz |
improved matrices, cube building and command parsing
-rw-r--r-- | src/engine.cpp | 217 | ||||
-rw-r--r-- | src/math/mat4.cpp | 39 | ||||
-rw-r--r-- | src/math/mat4.h | 6 | ||||
-rw-r--r-- | src/o3d/obj3d.cpp | 23 | ||||
-rw-r--r-- | src/o3d/obj3d.h | 2 |
5 files changed, 124 insertions, 163 deletions
diff --git a/src/engine.cpp b/src/engine.cpp index 4740046..69b2f43 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -9,6 +9,7 @@ #include <vector> #include <functional> #include <utility> +#include <iterator> #include <SDL.h> #ifdef ENABLE_NCURSES @@ -49,158 +50,30 @@ template <class FB> void scene_main(FB& fb, std::function<bool()> update_frame) { MathVector3 a{0.f, 0.f, 0.f}; float dist = 4.f; + float rad = 5.f; bool cont = true; + std::array<Object3D, 2> objs{{ Object3D::cube(), Object3D::cube() }}; + auto scale_mat = Mat4::scale(rad); while (cont) { a.x += .0050f; a.y += .0065f; a.z += .0080f; - float rad = 5.f; - auto [e4_x, e4_y, e4_z, e4_w] = (Mat4::rot_x(a.x) * Mat4::rot_y(a.y) * Mat4::rot_z(a.z)).to_vecs(); - auto e_x = e4_x.xyz(); - auto e_y = e4_y.xyz(); - auto e_z = e4_z.xyz(); - - std::array<Object3D, 2> objs{{ - { - { - { - rad * (-e_x + -e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (+e_x + -e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (-e_x + +e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (+e_x + +e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (-e_x + -e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (+e_x + -e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (-e_x + +e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (+e_x + +e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - } - }, - { - // face 1 - { 0, 2, 3 }, - { 0, 3, 1 }, - - // face 2 - { 0, 4, 6 }, - { 0, 6, 2 }, - - // face 3 - { 0, 1, 5 }, - { 0, 5, 4 }, - - // face 4 - { 7, 6, 4 }, - { 7, 4, 5 }, - - // face 5 - { 7, 3, 2 }, - { 7, 2, 6 }, - - // face 6 - { 7, 5, 1 }, - { 7, 1, 3 }, - } - }, - { - { - { - rad * (-e_x + -e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (+e_x + -e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (-e_x + +e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (+e_x + +e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (-e_x + -e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (+e_x + -e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (-e_x + +e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - }, - { - rad * (+e_x + +e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, - {} - } - }, - { - // face 1 - { 0, 2, 3 }, - { 0, 3, 1 }, - - // face 2 - { 0, 4, 6 }, - { 0, 6, 2 }, - - // face 3 - { 0, 1, 5 }, - { 0, 5, 4 }, - - // face 4 - { 7, 6, 4 }, - { 7, 4, 5 }, - - // face 5 - { 7, 3, 2 }, - { 7, 2, 6 }, - - // face 6 - { 7, 5, 1 }, - { 7, 1, 3 }, - } - } - }}; fb.clear(); - float min_z = 2.f, max_z = 50.f; - float fac_for_aspect_ratio = static_cast<float>(fb.height()) / static_cast<float>(fb.width()); - Mat4 mat{{ - fac_for_aspect_ratio, 0.f, 0.f, 0.f, - 0.f, -1.f, 0.f, 0.f, - 0.f, 0.f, -2.f / (max_z - min_z), -(max_z + min_z) / (max_z - min_z), - 0.f, 0.f, -1.f, 0.f, + auto transform_mat = Mat4::translate(MathVector3{0.f, 0.f, -rad * dist}) * Mat4::rot_z(a.z) * Mat4::rot_y(a.y) * Mat4::rot_x(a.x); + std::array<Mat4, 2> mats{{ + transform_mat * Mat4::translate(MathVector3{-.5f * rad, -.5f * rad, -.5f * rad}) * scale_mat, + transform_mat * Mat4::translate(MathVector3{+.5f * rad, +.5f * rad, +.5f * rad}) * scale_mat, }}; - for (auto obj : objs) { - for (auto triangle : obj) { + auto projection_mat = Mat4::projection(static_cast<float>(fb.height()) / static_cast<float>(fb.width()), 2.f, 50.f); + for (int i = 0; i < 2; i++) { + auto final_mat = projection_mat * mats[i]; + for (auto triangle : objs[i]) { TriangleVertex4 t{triangle}; - t.vertex1.point = mat * t.vertex1.point; - t.vertex2.point = mat * t.vertex2.point; - t.vertex3.point = mat * t.vertex3.point; + t.vertex1.point = final_mat * t.vertex1.point; + t.vertex2.point = final_mat * t.vertex2.point; + t.vertex3.point = final_mat * t.vertex3.point; fb.draw_triangle(t); } @@ -285,13 +158,14 @@ int main_graphical() { SDL_Renderer* renderer = NULL; SDL_Texture* texture = NULL; + // init if (SDL_Init(SDL_INIT_VIDEO) < 0) { - fprintf(stderr, "Error: SDL_Init error: %s\n", SDL_GetError()); + std::cerr << "Error: SDL_Init error: " << SDL_GetError() << std::endl; return EXIT_FAILURE; } window = SDL_CreateWindow("Engine", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (window == NULL) { - fprintf(stderr, "Error: SDL_CreateWindow error: %s\n", SDL_GetError()); + std::cerr << "Error: SDL_CreateWindow error: " << SDL_GetError() << std::endl; return EXIT_FAILURE; } renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); @@ -307,14 +181,17 @@ int main_graphical() { SDL_RenderPresent(renderer); SDL_UpdateWindowSurface(window); bool cont = true; - while (SDL_WaitEventTimeout(&e, 10)) { - if (e.type == SDL_QUIT) { - cont = false; - } + if (SDL_WaitEventTimeout(&e, 10)) { + do { + if (e.type == SDL_QUIT) { + cont = false; + } + } while (SDL_PollEvent(&e)); } return cont; }); + // terminate SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); @@ -323,29 +200,38 @@ int main_graphical() { return EXIT_SUCCESS; } -int main(int argc, char *argv[]) { - int mode = MODE_GRAPHICAL; - for (int i = 1; i < argc; i++) { - if (argv[i][0] == '-') { - if (argv[i][1] == '-') { - if (strcmp(&argv[i][2], "help") == 0) { +std::vector<std::string_view> convert_args(int argc, char *argv[]) { + std::vector<std::string_view> args(argc); + for (int i = 0; i < argc; i++) + args[i] = argv[i]; + return args; +} + +void parse_args(const std::vector<std::string_view>& args, int& mode) { + for (auto args_iter = std::next(args.begin()); args_iter != args.end(); args_iter++) { + const auto& arg = *args_iter; + if (arg.size() >= 1 && arg[0] == '-') { + if (arg.size() >= 2 && arg[1] == '-') { + auto long_opt = arg.substr(2); + if (long_opt == "help") { mode = MODE_HELP; - } else if (strcmp(&argv[i][2], "term") == 0) { + } else if (long_opt == "term") { mode = MODE_TERM; - } else if (strcmp(&argv[i][2], "graphical") == 0) { + } else if (long_opt == "graphical") { mode = MODE_GRAPHICAL; } else { - std::cerr << "Error: Unexpected option `--" << &argv[i][2] << "'." << std::endl; + std::cerr << "Error: Unexpected option `--" << long_opt << "'." << std::endl; usage_error_exit(); } } else { - if (!argv[i][1]) { + std::size_t arg_len = arg.size(); + if (arg_len == 1) { std::cerr << "Error: Unexpected argument `-'." << std::endl; usage_error_exit(); } - std::size_t arg_len = strlen(&argv[i][1]); - for (int j = 0; j < arg_len; j++) { - switch (argv[i][1 + j]) { + for (auto arg_iter = std::next(arg.begin()); arg_iter != arg.end(); arg_iter++) { + const auto& opt = *arg_iter; + switch (opt) { case 'h': mode = MODE_HELP; break; @@ -356,16 +242,21 @@ int main(int argc, char *argv[]) { mode = MODE_GRAPHICAL; break; default: - std::cerr << "Error: Unexpected option `-" << argv[i][1] << "'." << std::endl; + std::cerr << "Error: Unexpected option `-" << opt << "'." << std::endl; usage_error_exit(); } } } } else { - std::cerr << "Error: Unexpected argument `" << argv[i] << "'." << std::endl; + std::cerr << "Error: Unexpected argument `" << arg << "'." << std::endl; usage_error_exit(); } } +} + +int main(int argc, char *argv[]) { + int mode = MODE_GRAPHICAL; + parse_args(convert_args(argc, argv), mode); switch (mode) { case MODE_HELP: print_usage(std::cout); diff --git a/src/math/mat4.cpp b/src/math/mat4.cpp index 0342fdf..ece42d8 100644 --- a/src/math/mat4.cpp +++ b/src/math/mat4.cpp @@ -12,6 +12,23 @@ Mat4 Mat4::idty() { }; } +Mat4 Mat4::translate(MathVector3 v) { + return { + 1.f, 0.f, 0.f, v.x, + 0.f, 1.f, 0.f, v.y, + 0.f, 0.f, 1.f, v.z, + 0.f, 0.f, 0.f, 1.f, + }; +} +Mat4 Mat4::scale(float fac) { + return { + fac, 0.f, 0.f, 0.f, + 0.f, fac, 0.f, 0.f, + 0.f, 0.f, fac, 0.f, + 0.f, 0.f, 0.f, 1.f, + }; +} + Mat4 Mat4::rot_x(float a) { float c = std::cos(a); float s = std::sin(a); @@ -45,6 +62,19 @@ Mat4 Mat4::rot_z(float a) { }; } +Mat4 Mat4::projection(float aspect_ratio, float min_z, float max_z) { + return {{ + aspect_ratio, 0.f, 0.f, 0.f, + 0.f, -1.f, 0.f, 0.f, + 0.f, 0.f, -2.f / (max_z - min_z), -(max_z + min_z) / (max_z - min_z), + 0.f, 0.f, -1.f, 0.f, + }}; +} + +Mat4 Mat4::operator+() { + return *this; +} + Mat4 Mat4::operator-() { return { -values[ 0], -values[ 1], -values[ 2], -values[ 3], @@ -96,3 +126,12 @@ std::array<MathVector4, 4> Mat4::to_vecs() { { values[ 3], values[ 7], values[11], values[15] }, }}; } + +Mat4 operator*(float fac, Mat4 m) { + return { + fac * m.values[ 0], fac * m.values[ 1], fac * m.values[ 2], fac * m.values[ 3], + fac * m.values[ 4], fac * m.values[ 5], fac * m.values[ 6], fac * m.values[ 7], + fac * m.values[ 8], fac * m.values[ 9], fac * m.values[10], fac * m.values[11], + fac * m.values[12], fac * m.values[13], fac * m.values[14], fac * m.values[15], + }; +} diff --git a/src/math/mat4.h b/src/math/mat4.h index d81da63..6df9d49 100644 --- a/src/math/mat4.h +++ b/src/math/mat4.h @@ -7,12 +7,16 @@ class Mat4 { public: static Mat4 idty(); + static Mat4 translate(MathVector3 v); + static Mat4 scale(float fac); static Mat4 rot_x(float a); static Mat4 rot_y(float a); static Mat4 rot_z(float a); + static Mat4 projection(float aspect_ratio, float min_z, float max_z); std::array<float, 16> values; + Mat4 operator+(); Mat4 operator-(); Mat4 operator+(Mat4 m); Mat4 operator-(Mat4 m); @@ -21,4 +25,6 @@ class Mat4 { std::array<MathVector4, 4> to_vecs(); }; +Mat4 operator*(float fac, Mat4 m); + #endif // MATH_MAT4_H diff --git a/src/o3d/obj3d.cpp b/src/o3d/obj3d.cpp index 46f4db6..584e304 100644 --- a/src/o3d/obj3d.cpp +++ b/src/o3d/obj3d.cpp @@ -34,6 +34,29 @@ Object3D::TriangleVertex3Iterator::reference Object3D::TriangleVertex3Iterator:: }; } +Object3D Object3D::cube() { + return { + { + { MathVector3(-1.f, -1.f, -1.f), {} }, + { MathVector3(+1.f, -1.f, -1.f), {} }, + { MathVector3(-1.f, +1.f, -1.f), {} }, + { MathVector3(+1.f, +1.f, -1.f), {} }, + { MathVector3(-1.f, -1.f, +1.f), {} }, + { MathVector3(+1.f, -1.f, +1.f), {} }, + { MathVector3(-1.f, +1.f, +1.f), {} }, + { MathVector3(+1.f, +1.f, +1.f), {} }, + }, + { + { 0, 2, 3 }, { 0, 3, 1 }, // face 1 + { 0, 4, 6 }, { 0, 6, 2 }, // face 2 + { 0, 1, 5 }, { 0, 5, 4 }, // face 3 + { 7, 6, 4 }, { 7, 4, 5 }, // face 4 + { 7, 3, 2 }, { 7, 2, 6 }, // face 5 + { 7, 5, 1 }, { 7, 1, 3 }, // face 6 + } + }; +} + Object3D::Object3D(std::vector<Vertex3> pts, std::vector<std::array<int, 3>> faces) : pts{pts}, faces{faces} { } diff --git a/src/o3d/obj3d.h b/src/o3d/obj3d.h index 559ed63..c65a06b 100644 --- a/src/o3d/obj3d.h +++ b/src/o3d/obj3d.h @@ -30,6 +30,8 @@ class Object3D { }; + static Object3D cube(); // this function should not be in this file + Object3D(std::vector<Vertex3> pts, std::vector<std::array<int, 3>> faces); TriangleVertex3Iterator begin(); TriangleVertex3Iterator end(); |