#include "config.h" #include #ifdef ENABLE_NCURSES #include #endif #include #include #include #include #include "fb/chfb.h" #include "fb/pixfb.h" #include "o3d/obj3d.h" #include "o3d/vertex.h" #include "o3d/vertex_data.h" #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); int w, h; getmaxyx(stdscr, h, w); CharacterFrameBuffer cfb{static_cast(w), static_cast(h)}; 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; } a.x += .0050f; a.y += .0065f; a.z += .0080f; getmaxyx(stdscr, h, w); cfb.resize(static_cast(w), static_cast(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)}; std::array rot_x = {{ { 1.f, 0.f, 0.f }, { 0.f, ca.x, sa.x }, { 0.f, -sa.x, ca.x }, }}; std::array rot_y = {{ { ca.y, 0.f, -sa.y }, { 0.f, 1.f, 0.f }, { sa.y, 0.f, ca.y }, }}; std::array 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 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 }, } } }}; cfb.clear(); float min_z = 2.f, max_z = 50.f; float fac_for_aspect_ratio = 2.f * static_cast(cfb.height()) / static_cast(cfb.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; cfb.draw_triangle(t); } } mvaddnstr(0, 0, cfb.chars(), cfb.width() * cfb.height()); } // terminate endwin(); } #endif #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 void main_SDL() { 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; } 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; } 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 rot_x = {{ { 1.f, 0.f, 0.f }, { 0.f, ca.x, sa.x }, { 0.f, -sa.x, ca.x }, }}; std::array rot_y = {{ { ca.y, 0.f, -sa.y }, { 0.f, 1.f, 0.f }, { sa.y, 0.f, ca.y }, }}; std::array 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 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(pfb.height()) / static_cast(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); } } SDL_UpdateTexture(texture, NULL, pfb.pixels(), SCREEN_WIDTH * 4); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); SDL_UpdateWindowSurface(window); while (SDL_WaitEventTimeout(&e, 10)) { if (e.type == SDL_QUIT) { quit = true; } } } SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); } int main(int argc, char *argv[]) { (void) argc; (void) argv; // main_term(); main_SDL(); return EXIT_SUCCESS; }