From 947ad09430125dade70ae8220f49c106c0a2b8ca Mon Sep 17 00:00:00 2001 From: StepanovPlaton Date: Mon, 22 Dec 2025 16:07:05 +0400 Subject: [PATCH] Unix build --- src/Makefile | 16 ++-- src/engine/object.c | 4 +- src/engine/object.h | 4 +- src/engine/point.c | 5 +- src/engine/point.h | 5 +- src/main.c | 4 +- src/platforms/micro/micro.cpp | 4 +- src/platforms/platform.h | 11 ++- src/platforms/unix/unix.c | 141 ++++++++++++++++++++++++++++++++++ src/platforms/unix/unix.h | 13 ++++ src/platforms/win/win.c | 5 +- src/utils/screen.h | 6 +- 12 files changed, 195 insertions(+), 23 deletions(-) create mode 100644 src/platforms/unix/unix.c create mode 100644 src/platforms/unix/unix.h diff --git a/src/Makefile b/src/Makefile index 9f51a53..981907c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,8 @@ CC = gcc CFLAGS = -std=gnu23 -Wall -Wextra -O2 CXXFLAGS = -std=gnu++17 -Wall -Wextra -O2 -fno-exceptions -fno-rtti -LIBS = -lgdi32 +WIN_LIBS = -lgdi32 +UNIX_LIBS = -lX11 -lm # Micro options MCU = atmega328p @@ -25,7 +26,7 @@ WIN_SOURCES = $(BASE_SOURCES) platforms/win/win.c WIN_OBJECTS = $(WIN_SOURCES:.c=.wo) WIN_TARGET = $(TARGET).exe -UNIX_SOURCES = $(BASE_SOURCES) platforms/unix.c +UNIX_SOURCES = $(BASE_SOURCES) platforms/unix/unix.c UNIX_OBJECTS = $(UNIX_SOURCES:.c=.uo) UNIX_TARGET = $(TARGET) @@ -39,7 +40,12 @@ HEX = $(TARGET).hex win: $(WIN_TARGET) $(WIN_TARGET): $(WIN_OBJECTS) - $(CC) -o $@ $^ $(LIBS) + $(CC) -o $@ $^ $(WIN_LIBS) + +unix: $(UNIX_TARGET) + +$(UNIX_TARGET): $(UNIX_OBJECTS) + $(CC) -o $@ $^ $(UNIX_LIBS) micro: $(HEX) @@ -68,7 +74,7 @@ run_win: $(WIN_TARGET) .\$(WIN_TARGET) run_unix: $(UNIX_TARGET) - .\$(UNIX_TARGET) + ./$(UNIX_TARGET) upload_micro: $(HEX) $(AVRDUDE) -p $(MCU) -c $(PROGRAMMER) -P $(PORT) -b 57600 -U flash:w:$(HEX):i @@ -77,4 +83,4 @@ clean: rm -f $(WIN_TARGET) $(WIN_OBJECTS) $(UNIX_TARGET) $(UNIX_OBJECTS) $(HEX) $(ELF) $(MICRO_OBJECTS); clean_objects: - rm -f $(WIN_OBJECTS) $(UNIX_OBJECTS) $(ELF) $(MICRO_OBJECTS); \ No newline at end of file + rm -f $(WIN_OBJECTS) $(UNIX_OBJECTS) $(ELF) $(MICRO_OBJECTS); diff --git a/src/engine/object.c b/src/engine/object.c index 11aaf01..adc278a 100644 --- a/src/engine/object.c +++ b/src/engine/object.c @@ -27,7 +27,7 @@ Point object_get_centroid(const Object *const object) { return centroid; } -void object_draw(const Object *object, const Screen *const screen, +void object_draw(const Object *object, const EngineScreen *const screen, const float *render_matrix, const Camera *const camera, const Color *const color) { // Массив для отслеживания, какие рёбра нужно нарисовать @@ -108,4 +108,4 @@ void object_draw(const Object *object, const Screen *const screen, screen->draw_line(&p1, &p2, color); } } -} \ No newline at end of file +} diff --git a/src/engine/object.h b/src/engine/object.h index f002e2b..13ed372 100644 --- a/src/engine/object.h +++ b/src/engine/object.h @@ -20,8 +20,8 @@ typedef struct Object { void object_transform(Object *const object, int size, float *translate_matrix); Point object_get_centroid(const Object *const object); -void object_draw(const Object *object, const Screen *const screen, +void object_draw(const Object *object, const EngineScreen *const screen, const float *render_matrix, const Camera *const camera, const Color *const color); -#endif \ No newline at end of file +#endif diff --git a/src/engine/point.c b/src/engine/point.c index 7b59729..6899ec0 100644 --- a/src/engine/point.c +++ b/src/engine/point.c @@ -39,7 +39,8 @@ void point_create_translate_matrix(const Point *const position, } } -ScreenPoint point_to_screen_point(Point *point, const Screen *const screen, +ScreenPoint point_to_screen_point(Point *point, + const EngineScreen *const screen, const float *render_matrix) { float tmp[] = {point->coordinates[0], point->coordinates[1], point->coordinates[2], 1.0f}; @@ -57,4 +58,4 @@ ScreenPoint point_to_screen_point(Point *point, const Screen *const screen, ((perspective_coordinates[1] + 1.0f) / 2.0f) * (float)screen->height}}; return spoint; -} \ No newline at end of file +} diff --git a/src/engine/point.h b/src/engine/point.h index 66fa262..0e7f0cf 100644 --- a/src/engine/point.h +++ b/src/engine/point.h @@ -14,7 +14,8 @@ void point_transform(Point *const point, int size, const float *translate_matrix); void point_create_translate_matrix(const Point *const position, float *translate_matrix, int k); -ScreenPoint point_to_screen_point(Point *point, const Screen *const screen, +ScreenPoint point_to_screen_point(Point *point, + const EngineScreen *const screen, const float *render_matrix); -#endif \ No newline at end of file +#endif diff --git a/src/main.c b/src/main.c index 371c7b9..3594aa5 100644 --- a/src/main.c +++ b/src/main.c @@ -45,7 +45,7 @@ void init_engine() { logff(BLUE BOLD UNDERLINE, "Engine init complete!"); } -void render(const Screen *const screen, const Color *const color) { +void render(const EngineScreen *const screen, const Color *const color) { for (int i = 0; i < number_of_objects; i++) { object_draw(&(objects[i]), screen, render_matrix, &camera, color); } @@ -80,4 +80,4 @@ void tic() { } } -void destroy() { free(render_matrix); } \ No newline at end of file +void destroy() { free(render_matrix); } diff --git a/src/platforms/micro/micro.cpp b/src/platforms/micro/micro.cpp index 5157667..2a25820 100644 --- a/src/platforms/micro/micro.cpp +++ b/src/platforms/micro/micro.cpp @@ -13,7 +13,7 @@ void draw_line(const ScreenPoint *const sp1, const ScreenPoint *const sp2, TV.drawLine(sp1->coordinates[0], sp1->coordinates[1], sp2->coordinates[0], sp2->coordinates[1], 1); } -Screen screen = {.width = 128, .height = 64, .draw_line = &draw_line}; +EngineScreen screen = {.width = 128, .height = 64, .draw_line = &draw_line}; Color white = {.red = (char)255, .green = (char)255, .blue = (char)255}; float gx, gy, gz; @@ -36,4 +36,4 @@ int main(void) { // _delay_ms(1000 / FPS); } return 0; -} \ No newline at end of file +} diff --git a/src/platforms/platform.h b/src/platforms/platform.h index 1968aef..327407b 100644 --- a/src/platforms/platform.h +++ b/src/platforms/platform.h @@ -11,7 +11,7 @@ #endif EXTERNC void init_engine(); -EXTERNC void render(const Screen *const screen, const Color *const color); +EXTERNC void render(const EngineScreen *const screen, const Color *const color); EXTERNC void tic(); EXTERNC void rotate(const float angles_speed[3]); EXTERNC void destroy(); @@ -27,6 +27,15 @@ EXTERNC void destroy(); #endif // WIN +#ifdef UNIX +#include "unix/unix.h" + +#define FPS 25 +#define WINDOW_WIDTH 800 +#define WINDOW_HEIGHT 600 + +#endif // WIN + #ifdef MICRO #define FPS 20 diff --git a/src/platforms/unix/unix.c b/src/platforms/unix/unix.c new file mode 100644 index 0000000..ab50054 --- /dev/null +++ b/src/platforms/unix/unix.c @@ -0,0 +1,141 @@ +#include "../platform.h" + +#include "unix.h" + +const Color white = {255, 255, 255}; +const Color black = {0, 0, 0}; + +Display *display = NULL; +Window window; +GC gc; +int screen_num; +int running = 1; + +void draw_line_x11(const ScreenPoint *sp1, const ScreenPoint *sp2, + const Color *const color) { + if (!display || !gc) + return; + + XSetForeground(display, gc, + (color->red << 16) | (color->green << 8) | color->blue); + XDrawLine(display, window, gc, sp1->coordinates[0], sp1->coordinates[1], + sp2->coordinates[0], sp2->coordinates[1]); +} + +void redraw_window(void) { + if (!display || !window) + return; + + XWindowAttributes window_attrs; + XGetWindowAttributes(display, window, &window_attrs); + + XSetForeground(display, gc, + (black.red << 16) | (black.green << 8) | black.blue); + XFillRectangle(display, window, gc, 0, 0, window_attrs.width, + window_attrs.height); + + EngineScreen screen = {.width = window_attrs.width, + .height = window_attrs.height, + .draw_line = &draw_line_x11}; + + render(&screen, &white); + XFlush(display); +} + +int main() { + struct timeval last_time, current_time; + long frame_delay = 1000000 / FPS; // микросекунды на кадр + + display = XOpenDisplay(NULL); + if (display == NULL) { + fprintf(stderr, "Cannot open display\n"); + return 1; + } + + screen_num = DefaultScreen(display); + + window = XCreateSimpleWindow(display, RootWindow(display, screen_num), 0, 0, + WINDOW_WIDTH, WINDOW_HEIGHT, 1, + BlackPixel(display, screen_num), + BlackPixel(display, screen_num)); + + XStoreName(display, window, "C3DGraphicEngine"); + + XSelectInput(display, window, + ExposureMask | KeyPressMask | StructureNotifyMask | + KeyReleaseMask); + + Atom wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False); + XSetWMProtocols(display, window, &wm_delete_window, 1); + + gc = XCreateGC(display, window, 0, NULL); + + XSetGraphicsExposures(display, gc, False); + + XMapWindow(display, window); + XFlush(display); + + XEvent ev; + do { + XNextEvent(display, &ev); + } while (ev.type != Expose); + + init_engine(); + + redraw_window(); + + gettimeofday(&last_time, NULL); + + while (running) { + while (XPending(display) > 0) { + XNextEvent(display, &ev); + + switch (ev.type) { + case Expose: + if (ev.xexpose.count == 0) { + redraw_window(); + } + break; + + case ConfigureNotify: + redraw_window(); + break; + + case KeyPress: + if (XLookupKeysym(&ev.xkey, 0) == XK_Escape) { + running = 0; + } + break; + + case ClientMessage: + if (ev.xclient.message_type == + XInternAtom(display, "WM_PROTOCOLS", True) && + (Atom)ev.xclient.data.l[0] == + XInternAtom(display, "WM_DELETE_WINDOW", False)) { + running = 0; + } + break; + } + } + + gettimeofday(¤t_time, NULL); + long elapsed = (current_time.tv_sec - last_time.tv_sec) * 1000000 + + (current_time.tv_usec - last_time.tv_usec); + + if (elapsed >= frame_delay) { + tic(); + + redraw_window(); + + last_time = current_time; + } else { + usleep(1000); + } + } + + XFreeGC(display, gc); + XDestroyWindow(display, window); + XCloseDisplay(display); + + return 0; +} diff --git a/src/platforms/unix/unix.h b/src/platforms/unix/unix.h new file mode 100644 index 0000000..2b24259 --- /dev/null +++ b/src/platforms/unix/unix.h @@ -0,0 +1,13 @@ +#ifndef UNIX_H +#define UNIX_H + +#include "../platform.h" +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/src/platforms/win/win.c b/src/platforms/win/win.c index d5e60fd..fff504c 100644 --- a/src/platforms/win/win.c +++ b/src/platforms/win/win.c @@ -32,7 +32,8 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, DeleteObject(hPen); }; - Screen screen = {.width = width, .height = height, .draw_line = &draw_line}; + EngineScreen screen = { + .width = width, .height = height, .draw_line = &draw_line}; render(&screen, &white); @@ -86,4 +87,4 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, } return 0; -} \ No newline at end of file +} diff --git a/src/utils/screen.h b/src/utils/screen.h index 2a5dc93..0acdc4d 100644 --- a/src/utils/screen.h +++ b/src/utils/screen.h @@ -11,11 +11,11 @@ typedef struct Color { char blue; } Color; -typedef struct Screen { +typedef struct EngineScreen { int width; int height; void (*draw_line)(const ScreenPoint *sp1, const ScreenPoint *sp2, const Color *const color); -} Screen; +} EngineScreen; -#endif \ No newline at end of file +#endif