diff options
author | vimene <vincent.menegaux@gmail.com> | 2023-11-23 05:57:39 +0100 |
---|---|---|
committer | vimene <vincent.menegaux@gmail.com> | 2023-11-23 05:57:39 +0100 |
commit | 918e9c083b36acdfc3c61d86e5b54cd118caa591 (patch) | |
tree | f27e5fe294f0d0e7a90aa94d4835315486499209 | |
parent | 6570a75b1d75f0c3b5a7307096efffb4f973e856 (diff) | |
download | engine-918e9c083b36acdfc3c61d86e5b54cd118caa591.tar.gz |
add options to choose render mode
-rw-r--r-- | Makefile.am | 10 | ||||
-rw-r--r-- | configure.ac | 24 | ||||
-rw-r--r-- | src/engine.cpp | 421 | ||||
-rw-r--r-- | src/fb/chfb.cpp | 6 |
4 files changed, 195 insertions, 266 deletions
diff --git a/Makefile.am b/Makefile.am index 0f451ca..fae27fd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,10 +3,12 @@ ACLOCAL_AMFLAGS = -Im4 --install AM_CPPFLAGS = $(DEPS_CFLAGS) bin_PROGRAMS = engine -engine_SOURCES = src/engine.cpp -engine_SOURCES += src/fb/chfb.h src/fb/chfb.cpp src/fb/pixfb.h src/fb/pixfb.cpp -engine_SOURCES += src/math/math_vector.h src/math/math_vector.cpp -engine_SOURCES += src/o3d/obj3d.h src/o3d/obj3d.cpp src/o3d/tri_vertex.h src/o3d/tri_vertex.cpp src/o3d/vertex.h src/o3d/vertex.cpp src/o3d/vertex_data.h src/o3d/vertex_data.cpp +engine_SOURCES = src/engine.cpp \ + src/fb/chfb.h src/fb/chfb.cpp src/fb/pixfb.h src/fb/pixfb.cpp \ + src/math/math_vector.h src/math/math_vector.cpp \ + src/o3d/obj3d.h src/o3d/obj3d.cpp src/o3d/tri_vertex.h \ + src/o3d/tri_vertex.cpp src/o3d/vertex.h src/o3d/vertex.cpp \ + src/o3d/vertex_data.h src/o3d/vertex_data.cpp engine_LDADD = $(DEPS_LIBS) EXTRA_DIST = m4/NOTES diff --git a/configure.ac b/configure.ac index 69ca562..13ccb1a 100644 --- a/configure.ac +++ b/configure.ac @@ -10,21 +10,31 @@ AC_CONFIG_FILES([Makefile]) SDL_VERSION=2.0 AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], sdl_prefix="$withval", sdl_prefix="") + +DEPS_CFLAGS="" +DEPS_LIBS="" + AS_IF([test "x$sdl_prefix" = x], [ - PKG_CHECK_MODULES([SDL], [sdl2 >= $SDL_VERSION], [sdl_loaded=yes]) + PKG_CHECK_MODULES([SDL], [sdl2 >= $SDL_VERSION]) ], [ sdl_config="$sdl_prefix/bin/sdl2-config" SDL_CFLAGS=`"$sdl_config" --prefix="$sdl_prefix" --cflags` SDL_LIBS=`"$sdl_config" --prefix="$sdl_prefix" --libs` - sdl_loaded=yes # TODO: check if sdl is present, check version + # TODO: check if sdl is present, check version ]) -AS_IF([test "x$sdl_loaded" != xyes], [AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])]) -DEPS_CFLAGS="$SDL_CFLAGS" -DEPS_LIBS="$SDL_LIBS" +DEPS_CFLAGS="$SDL_CFLAGS $DEPS_CFLAGS" +DEPS_LIBS="$SDL_LIBS $DEPS_LIBS" + +AC_CANONICAL_HOST +AS_IF([test "$host_os" != mingw32], [ + PKG_CHECK_MODULES([NCURSES], [ncurses]) + DEPS_CFLAGS="$NCURSES_CFLAGS $DEPS_CFLAGS" + DEPS_LIBS="$NCURSES_LIBS $DEPS_LIBS" + AC_DEFINE([ENABLE_NCURSES], [], [Enable ncurses]) +]) + AC_SUBST(DEPS_CFLAGS) AC_SUBST(DEPS_LIBS) -# AC_DEFINE([ENABLE_NCURSES], [], [Enable ncurses]) -# AC_CHECK_LIB([ncurses], [initscr]) AC_PROG_CXX AC_TYPE_UINT32_T diff --git a/src/engine.cpp b/src/engine.cpp index 94581b3..eb3b156 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -1,14 +1,20 @@ #include "config.h" #include <iostream> -#ifdef ENABLE_NCURSES -#include <ncurses.h> -#endif - #include <cmath> +#include <cstddef> #include <cstdint> +#include <cstdlib> +#include <cstring> #include <vector> +#include <functional> +#include <utility> #include <SDL.h> + +#ifdef ENABLE_NCURSES +#include <ncurses.h> +#endif + #include "fb/chfb.h" #include "fb/pixfb.h" #include "o3d/obj3d.h" @@ -17,71 +23,37 @@ #include "o3d/tri_vertex.h" #include "math/math_vector.h" -#define MKEY_Z 122 -#define MKEY_Q 113 -#define MKEY_S 115 -#define MKEY_D 100 - -#define MKEY_ESC 27 - #define FPS 60 #define PI 3.1415926535f -#ifdef ENABLE_NCURSES -void main_term() { - // init - setlocale(LC_ALL, ""); - initscr(); - cbreak(); - noecho(); - intrflush(stdscr, FALSE); - keypad(stdscr, TRUE); - set_escdelay(0); - curs_set(0); +#define MODE_HELP 0 +#define MODE_TERM 1 +#define MODE_GRAPHICAL 2 - int w, h; - getmaxyx(stdscr, h, w); - CharacterFrameBuffer cfb{static_cast<unsigned int>(w), static_cast<unsigned int>(h)}; +void print_usage(std::ostream& output_stream) { + output_stream << "Usage: ./engine [-tg] [--term] [--graphical]\n" + << " -h, --help show usage (this)\n" + << " -t, --term terminal mode\n" + << " -g, --graphical graphical mode (default)\n" + << std::flush; +} +[[noreturn]] void usage_error_exit() { + print_usage(std::cerr); + std::exit(EXIT_FAILURE); +} + +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; - while (1) { - //timeout(1000 / FPS); - timeout(10); - int c = getch(); - - if (c == MKEY_ESC) break; - switch (c) { - case KEY_UP: - // a.x += 0.1f; - dist += .1f; - break; - case KEY_DOWN: - // a.x -= 0.1f; - dist -= .1f; - break; - case KEY_LEFT: - // a.y += 0.1f; - break; - case KEY_RIGHT: - // a.y -= 0.1f; - break; - case MKEY_Q: - // a.z += 0.1f; - break; - case MKEY_D: - // a.z -= 0.1f; - break; - } - + bool cont = true; + while (cont) { a.x += .0050f; a.y += .0065f; a.z += .0080f; - getmaxyx(stdscr, h, w); - cfb.resize(static_cast<unsigned int>(w), static_cast<unsigned int>(h)); - float rad = 5.f; MathVector3 ca{std::cos(a.x), std::cos(a.y), std::cos(a.z)}; MathVector3 sa{std::sin(a.x), std::sin(a.y), std::sin(a.z)}; @@ -234,9 +206,9 @@ void main_term() { } } }}; - cfb.clear(); + fb.clear(); float min_z = 2.f, max_z = 50.f; - float fac_for_aspect_ratio = 2.f * static_cast<float>(cfb.height()) / static_cast<float>(cfb.width()); + float fac_for_aspect_ratio = static_cast<float>(fb.height()) / static_cast<float>(fb.width()); for (auto obj : objs) { for (auto triangle : obj) { TriangleVertex4 t{triangle}; @@ -255,244 +227,185 @@ void main_term() { t.vertex3.point.w = -t.vertex3.point.z; t.vertex3.point.z = 2.f * (-t.vertex3.point.z - min_z) / (max_z - min_z) - 1.f; - cfb.draw_triangle(t); + fb.draw_triangle(t); } } - mvaddnstr(0, 0, cfb.chars(), cfb.width() * cfb.height()); + cont = update_frame(); } +} + +#ifdef ENABLE_NCURSES +#define MKEY_Z 122 +#define MKEY_Q 113 +#define MKEY_S 115 +#define MKEY_D 100 + +#define MKEY_ESC 27 + +int main_term() { + // init + setlocale(LC_ALL, ""); + initscr(); + cbreak(); + noecho(); + intrflush(stdscr, FALSE); + keypad(stdscr, TRUE); + set_escdelay(0); + curs_set(0); + + int w, h; + getmaxyx(stdscr, h, w); + CharacterFrameBuffer cfb{static_cast<unsigned int>(w), static_cast<unsigned int>(h)}; + + scene_main(cfb, [&]() { + mvaddnstr(0, 0, cfb.chars(), cfb.width() * cfb.height()); + + bool cont = true; + //timeout(1000 / FPS); + timeout(10); + int c = getch(); + + if (c == MKEY_ESC) return false; + switch (c) { + case KEY_UP: + // a.x += 0.1f; + // dist += .1f; + break; + case KEY_DOWN: + // a.x -= 0.1f; + // dist -= .1f; + break; + case KEY_LEFT: + // a.y += 0.1f; + break; + case KEY_RIGHT: + // a.y -= 0.1f; + break; + case MKEY_Q: + // a.z += 0.1f; + break; + case MKEY_D: + // a.z -= 0.1f; + break; + } + + getmaxyx(stdscr, h, w); + cfb.resize(static_cast<unsigned int>(w), static_cast<unsigned int>(h)); + + return cont; + }); // terminate endwin(); + + return EXIT_SUCCESS; } #endif #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 -void main_SDL() { +int main_graphical() { SDL_Window* window = NULL; SDL_Renderer* renderer = NULL; SDL_Texture* texture = NULL; if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Error: SDL_Init error: %s\n", SDL_GetError()); - return; + 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()); - return; + return EXIT_FAILURE; } renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT); PixelFrameBuffer pfb{SCREEN_WIDTH, SCREEN_HEIGHT}; - MathVector3 a{0.f, 0.f, 0.f}; - float dist = 4.f; SDL_Event e; - bool quit = false; - while (!quit) { - a.x += .0050f; - a.y += .0065f; - a.z += .0080f; - - float rad = 5.f; - MathVector3 ca{std::cos(a.x), std::cos(a.y), std::cos(a.z)}; - MathVector3 sa{std::sin(a.x), std::sin(a.y), std::sin(a.z)}; - - std::array<MathVector3, 3> rot_x = {{ - { 1.f, 0.f, 0.f }, - { 0.f, ca.x, sa.x }, - { 0.f, -sa.x, ca.x }, - }}; - std::array<MathVector3, 3> rot_y = {{ - { ca.y, 0.f, -sa.y }, - { 0.f, 1.f, 0.f }, - { sa.y, 0.f, ca.y }, - }}; - std::array<MathVector3, 3> rot_z = {{ - { ca.z, sa.z, 0.f }, - { -sa.z, ca.z, 0.f }, - { 0.f, 0.f, 1.f }, - }}; - - auto [e_x, e_y, e_z] = rot_x; - e_x = e_x.x * rot_y[0] + e_x.y * rot_y[1] + e_x.z * rot_y[2]; - e_y = e_y.x * rot_y[0] + e_y.y * rot_y[1] + e_y.z * rot_y[2]; - e_z = e_z.x * rot_y[0] + e_z.y * rot_y[1] + e_z.z * rot_y[2]; - e_x = e_x.x * rot_z[0] + e_x.y * rot_z[1] + e_x.z * rot_z[2]; - e_y = e_y.x * rot_z[0] + e_y.y * rot_z[1] + e_y.z * rot_z[2]; - e_z = e_z.x * rot_z[0] + e_z.y * rot_z[1] + e_z.z * rot_z[2]; - - 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 }, - } - } - }}; - pfb.clear(); - float min_z = 2.f, max_z = 50.f; - float fac_for_aspect_ratio = 2.f * static_cast<float>(pfb.height()) / static_cast<float>(pfb.width()); - for (auto obj : objs) { - for (auto triangle : obj) { - TriangleVertex4 t{triangle}; - - // should be multiplied by a matrix, temporary replacement - t.vertex1.point.x *= fac_for_aspect_ratio; - t.vertex1.point.y = -t.vertex1.point.y; - t.vertex1.point.w = -t.vertex1.point.z; - t.vertex1.point.z = 2.f * (-t.vertex1.point.z - min_z) / (max_z - min_z) - 1.f; - t.vertex2.point.x *= fac_for_aspect_ratio; - t.vertex2.point.y = -t.vertex2.point.y; - t.vertex2.point.w = -t.vertex2.point.z; - t.vertex2.point.z = 2.f * (-t.vertex2.point.z - min_z) / (max_z - min_z) - 1.f; - t.vertex3.point.x *= fac_for_aspect_ratio; - t.vertex3.point.y = -t.vertex3.point.y; - t.vertex3.point.w = -t.vertex3.point.z; - t.vertex3.point.z = 2.f * (-t.vertex3.point.z - min_z) / (max_z - min_z) - 1.f; - - pfb.draw_triangle(t); - } - } + scene_main(pfb, [&]() { SDL_UpdateTexture(texture, NULL, pfb.pixels(), SCREEN_WIDTH * 4); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); SDL_UpdateWindowSurface(window); + bool cont = true; while (SDL_WaitEventTimeout(&e, 10)) { if (e.type == SDL_QUIT) { - quit = true; + cont = false; } } - } + return cont; + }); + SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); + + return EXIT_SUCCESS; } int main(int argc, char *argv[]) { - (void) argc; - (void) argv; - // main_term(); - main_SDL(); - return EXIT_SUCCESS; + 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) { + mode = MODE_HELP; + } else if (strcmp(&argv[i][2], "term") == 0) { + mode = MODE_TERM; + } else if (strcmp(&argv[i][2], "graphical") == 0) { + mode = MODE_GRAPHICAL; + } else { + std::cerr << "Error: Unexpected option `--" << &argv[i][2] << "'." << std::endl; + usage_error_exit(); + } + } else { + if (!argv[i][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]) { + case 'h': + mode = MODE_HELP; + break; + case 't': + mode = MODE_TERM; + break; + case 'g': + mode = MODE_GRAPHICAL; + break; + default: + std::cerr << "Error: Unexpected option `-" << argv[i][1] << "'." << std::endl; + usage_error_exit(); + } + } + } + } else { + std::cerr << "Error: Unexpected argument `" << argv[i] << "'." << std::endl; + usage_error_exit(); + } + } + switch (mode) { + case MODE_HELP: + print_usage(std::cout); + return EXIT_SUCCESS; + case MODE_TERM: +#ifdef ENABLE_NCURSES + return main_term(); +#else + std::cerr << "Error: ncurses was not enabled during compilation." << std::endl; + return EXIT_FAILURE; +#endif + case MODE_GRAPHICAL: + return main_graphical(); + default: + ; // unreachable + } + return EXIT_SUCCESS; // unreachable } diff --git a/src/fb/chfb.cpp b/src/fb/chfb.cpp index 7ac1626..e2355df 100644 --- a/src/fb/chfb.cpp +++ b/src/fb/chfb.cpp @@ -126,7 +126,11 @@ void CharacterFrameBuffer::_draw_cropped_triangle(TriangleVertex3 triangle) { void CharacterFrameBuffer::draw_triangle(TriangleVertex4 triangle) { face_ind++; for (auto t1 : triangle.crop_z_out(-1.f, 1.f)) { - for (auto t2 : t1.div_by_w().crop_xy_out(-1.f, 1.f, -1.f, 1.f)) { + auto t1_2 = t1.div_by_w(); + t1_2.vertex1.point.x *= 2.f; + t1_2.vertex2.point.x *= 2.f; + t1_2.vertex3.point.x *= 2.f; + for (auto t2 : t1_2.crop_xy_out(-1.f, 1.f, -1.f, 1.f)) { MathVector2 pp1 = t2.vertex1.point.xy(), pp2 = t2.vertex2.point.xy(), pp3 = t2.vertex3.point.xy(); |