aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvimene <vincent.menegaux@gmail.com>2023-11-23 05:57:39 +0100
committervimene <vincent.menegaux@gmail.com>2023-11-23 05:57:39 +0100
commit918e9c083b36acdfc3c61d86e5b54cd118caa591 (patch)
treef27e5fe294f0d0e7a90aa94d4835315486499209
parent6570a75b1d75f0c3b5a7307096efffb4f973e856 (diff)
downloadengine-918e9c083b36acdfc3c61d86e5b54cd118caa591.tar.gz
add options to choose render mode
-rw-r--r--Makefile.am10
-rw-r--r--configure.ac24
-rw-r--r--src/engine.cpp421
-rw-r--r--src/fb/chfb.cpp6
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();