mirror of
https://github.com/StepanovPlaton/C3DGraphicEngine.git
synced 2026-04-03 12:20:42 +04:00
Unix build
This commit is contained in:
16
src/Makefile
16
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);
|
||||
rm -f $(WIN_OBJECTS) $(UNIX_OBJECTS) $(ELF) $(MICRO_OBJECTS);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
#endif
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
#endif
|
||||
|
||||
@@ -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); }
|
||||
void destroy() { free(render_matrix); }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
141
src/platforms/unix/unix.c
Normal file
141
src/platforms/unix/unix.c
Normal file
@@ -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;
|
||||
}
|
||||
13
src/platforms/unix/unix.h
Normal file
13
src/platforms/unix/unix.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef UNIX_H
|
||||
#define UNIX_H
|
||||
|
||||
#include "../platform.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#endif
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user