commit 53610a8c1c700c72127d7b9abcb4f0efdc477231 Author: klein panic Date: Fri Sep 27 19:32:14 2024 -0400 Initial Commit diff --git a/clock/README.md b/clock/README.md new file mode 100644 index 0000000..7653c0e --- /dev/null +++ b/clock/README.md @@ -0,0 +1,3 @@ +# clock Project + +This is a C project generated with the setup tool. diff --git a/clock/build/Makefile b/clock/build/Makefile new file mode 100644 index 0000000..f0e7f35 --- /dev/null +++ b/clock/build/Makefile @@ -0,0 +1,24 @@ +# build/Makefile +CC = gcc +CFLAGS = -Wall -I../include +SRCDIR = ../src +OBJDIR = ../obj +BINDIR = ../build +TARGET = clock + +# Gather all source files in src directory +SOURCES = $(wildcard $(SRCDIR)/*.c) +OBJECTS = $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SOURCES)) + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(CFLAGS) -o $(BINDIR)/$(TARGET) $(OBJECTS) -lm + +$(OBJDIR)/%.o: $(SRCDIR)/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJDIR)/*.o $(BINDIR)/$(TARGET) + +.PHONY: all clean diff --git a/clock/build/clock b/clock/build/clock new file mode 100755 index 0000000..2355aae Binary files /dev/null and b/clock/build/clock differ diff --git a/clock/include/clock.h b/clock/include/clock.h new file mode 100644 index 0000000..bbc8ad7 --- /dev/null +++ b/clock/include/clock.h @@ -0,0 +1,37 @@ +// include/clock.h +#ifndef CLOCK_H +#define CLOCK_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SCREEN_WIDTH 800 +#define SCREEN_HEIGHT 600 +#define CENTER_X (SCREEN_WIDTH / 2) +#define CENTER_Y (SCREEN_HEIGHT / 2) +#define RADIUS 200 +#define HOUR_HAND_LENGTH 100 +#define MINUTE_HAND_LENGTH 150 + +typedef struct { + int x; + int y; +} Point; + +void draw_circle(int *framebuffer, struct fb_var_screeninfo vinfo); +void draw_hand(int *framebuffer, struct fb_var_screeninfo vinfo, float angle, int length, int color); +void draw_clock_face(int *framebuffer, struct fb_var_screeninfo vinfo); +void update_time(int *framebuffer, struct fb_var_screeninfo vinfo); +void draw_text(int *framebuffer, struct fb_var_screeninfo vinfo, const char *text, int x, int y, int size, int color); + +#endif diff --git a/clock/obj/clock.o b/clock/obj/clock.o new file mode 100644 index 0000000..b3ab4ad Binary files /dev/null and b/clock/obj/clock.o differ diff --git a/clock/src/clock.c b/clock/src/clock.c new file mode 100644 index 0000000..118ec73 --- /dev/null +++ b/clock/src/clock.c @@ -0,0 +1,168 @@ +// src/clock.c +#include "../include/clock.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Set a pixel at (x, y) with color in the framebuffer +void set_pixel(int *framebuffer, struct fb_var_screeninfo vinfo, int x, int y, int color) { + if (x >= 0 && x < vinfo.xres_virtual && y >= 0 && y < vinfo.yres_virtual) { + framebuffer[y * vinfo.xres_virtual + x] = color; + } +} + +// Bresenham's line algorithm for drawing lines +void draw_line(int *framebuffer, struct fb_var_screeninfo vinfo, int x0, int y0, int x1, int y1, int color) { + int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1; + int err = dx + dy, e2; + + while (1) { + set_pixel(framebuffer, vinfo, x0, y0, color); + if (x0 == x1 && y0 == y1) break; + e2 = 2 * err; + if (e2 >= dy) { err += dy; x0 += sx; } + if (e2 <= dx) { err += dx; y0 += sy; } + } +} + +// Draw a simple filled rectangle to represent text characters +void draw_char(int *framebuffer, struct fb_var_screeninfo vinfo, char c, int x, int y, int size, int color) { + static const char font[10][5][3] = { + { "111", "101", "101", "101", "111" }, // '0' + { "110", "010", "010", "010", "111" }, // '1' + { "111", "001", "111", "100", "111" }, // '2' + { "111", "001", "111", "001", "111" }, // '3' + { "101", "101", "111", "001", "001" }, // '4' + { "111", "100", "111", "001", "111" }, // '5' + { "111", "100", "111", "101", "111" }, // '6' + { "111", "001", "001", "001", "001" }, // '7' + { "111", "101", "111", "101", "111" }, // '8' + { "111", "101", "111", "001", "111" } // '9' + }; + + if (c >= '0' && c <= '9') { + int index = c - '0'; + for (int row = 0; row < 5; ++row) { + for (int col = 0; col < 3; ++col) { + if (font[index][row][col] == '1') { + for (int i = 0; i < size; ++i) { + for (int j = 0; j < size; ++j) { + set_pixel(framebuffer, vinfo, x + col * size + i, y + row * size + j, color); + } + } + } + } + } + } +} + +// Draw a string of characters +void draw_text(int *framebuffer, struct fb_var_screeninfo vinfo, const char *text, int x, int y, int size, int color) { + for (const char *p = text; *p; ++p) { + draw_char(framebuffer, vinfo, *p, x, y, size, color); + x += size * 4; // Move to the next character position + } +} + +// Draw numbers around the clock face +void draw_circle(int *framebuffer, struct fb_var_screeninfo vinfo) { + for (int i = 1; i <= 12; ++i) { + float angle = (i * 30 - 90) * M_PI / 180.0; + int x = CENTER_X + (int)(RADIUS * cos(angle)); + int y = CENTER_Y + (int)(RADIUS * sin(angle)); + + char buffer[3]; + sprintf(buffer, "%d", i); + draw_text(framebuffer, vinfo, buffer, x - 10, y - 10, 3, 0xFFFFFF); // Increased the size to '3' for visibility + } +} + +// Draw clock hands +void draw_hand(int *framebuffer, struct fb_var_screeninfo vinfo, float angle, int length, int color) { + int x_end = CENTER_X + length * cos(angle); + int y_end = CENTER_Y - length * sin(angle); + draw_line(framebuffer, vinfo, CENTER_X, CENTER_Y, x_end, y_end, color); +} + +// Draw the clock face with numbers +void draw_clock_face(int *framebuffer, struct fb_var_screeninfo vinfo) { + memset(framebuffer, 0, vinfo.yres_virtual * vinfo.xres_virtual * sizeof(int)); // Clear screen + draw_circle(framebuffer, vinfo); // Draw the numbers +} + +// Update the clock hands and date/time display +void update_time(int *framebuffer, struct fb_var_screeninfo vinfo) { + time_t rawtime; + struct tm *timeinfo; + char date_buffer[80]; + char time_buffer[80]; + + time(&rawtime); + timeinfo = localtime(&rawtime); + + // Calculate the angle for the hour hand + float hour_angle_degrees = (30 * timeinfo->tm_hour) + (timeinfo->tm_min * 0.5); + float hour_angle = - hour_angle_degrees * M_PI / 180.0 + M_PI / 2; // Convert to radians and adjust to 12 o'clock start + + // Calculate the angle for the minute hand + float minute_angle_degrees = 6 * timeinfo->tm_min; + float minute_angle = - minute_angle_degrees * M_PI / 180.0 + M_PI / 2; // Convert to radians and adjust to 12 o'clock start + + // Draw both hands in white (0xFFFFFF) + draw_hand(framebuffer, vinfo, hour_angle, HOUR_HAND_LENGTH, 0xFFFFFF); // Hour hand is shorter + draw_hand(framebuffer, vinfo, minute_angle, MINUTE_HAND_LENGTH, 0xFFFFFF); // Minute hand is longer + + // Display the date + strftime(date_buffer, sizeof(date_buffer), "%Y-%m-%d", timeinfo); + draw_text(framebuffer, vinfo, date_buffer, CENTER_X - 100, CENTER_Y + 300, 3, 0xFFFFFF); // Moved lower and increased size + + // Display the time + strftime(time_buffer, sizeof(time_buffer), "%H:%M:%S", timeinfo); + draw_text(framebuffer, vinfo, time_buffer, CENTER_X - 80, CENTER_Y + 350, 3, 0xFFFFFF); // Moved lower and increased size +} + +int main() { + // Open the framebuffer device + int fbfd = open("/dev/fb0", O_RDWR); + if (fbfd == -1) { + perror("Error: cannot open framebuffer device"); + exit(1); + } + + // Get variable screen information + struct fb_var_screeninfo vinfo; + if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) { + perror("Error reading variable information"); + close(fbfd); + exit(2); + } + + // Map the framebuffer to user memory + size_t screensize = vinfo.yres_virtual * vinfo.xres_virtual * vinfo.bits_per_pixel / 8; + int *framebuffer = (int *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); + if (framebuffer == MAP_FAILED) { + perror("Error mapping framebuffer device to memory"); + close(fbfd); + exit(3); + } + + // Continuously update the clock + while (1) { + draw_clock_face(framebuffer, vinfo); + update_time(framebuffer, vinfo); + sleep(1); // Sleep for 1 second to update the clock every second + } + + // Cleanup + munmap(framebuffer, screensize); + close(fbfd); + + return 0; +} diff --git a/clock/src/clock.c.bak b/clock/src/clock.c.bak new file mode 100644 index 0000000..63481b4 --- /dev/null +++ b/clock/src/clock.c.bak @@ -0,0 +1,165 @@ +// src/clock.c +#include "../include/clock.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Set a pixel at (x, y) with color in the framebuffer +void set_pixel(int *framebuffer, struct fb_var_screeninfo vinfo, int x, int y, int color) { + if (x >= 0 && x < vinfo.xres_virtual && y >= 0 && y < vinfo.yres_virtual) { + framebuffer[y * vinfo.xres_virtual + x] = color; + } +} + +// Bresenham's line algorithm for drawing lines +void draw_line(int *framebuffer, struct fb_var_screeninfo vinfo, int x0, int y0, int x1, int y1, int color) { + int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1; + int err = dx + dy, e2; + + while (1) { + set_pixel(framebuffer, vinfo, x0, y0, color); + if (x0 == x1 && y0 == y1) break; + e2 = 2 * err; + if (e2 >= dy) { err += dy; x0 += sx; } + if (e2 <= dx) { err += dx; y0 += sy; } + } +} + +// Draw a simple filled rectangle to represent text characters +void draw_char(int *framebuffer, struct fb_var_screeninfo vinfo, char c, int x, int y, int size, int color) { + static const char font[10][5][3] = { + { "111", "101", "101", "101", "111" }, // '0' + { "110", "010", "010", "010", "111" }, // '1' + { "111", "001", "111", "100", "111" }, // '2' + { "111", "001", "111", "001", "111" }, // '3' + { "101", "101", "111", "001", "001" }, // '4' + { "111", "100", "111", "001", "111" }, // '5' + { "111", "100", "111", "101", "111" }, // '6' + { "111", "001", "001", "001", "001" }, // '7' + { "111", "101", "111", "101", "111" }, // '8' + { "111", "101", "111", "001", "111" } // '9' + }; + + if (c >= '0' && c <= '9') { + int index = c - '0'; + for (int row = 0; row < 5; ++row) { + for (int col = 0; col < 3; ++col) { + if (font[index][row][col] == '1') { + for (int i = 0; i < size; ++i) { + for (int j = 0; j < size; ++j) { + set_pixel(framebuffer, vinfo, x + col * size + i, y + row * size + j, color); + } + } + } + } + } + } +} + +// Draw a string of characters +void draw_text(int *framebuffer, struct fb_var_screeninfo vinfo, const char *text, int x, int y, int size, int color) { + for (const char *p = text; *p; ++p) { + draw_char(framebuffer, vinfo, *p, x, y, size, color); + x += size * 4; // Move to the next character position + } +} + +// Draw numbers around the clock face +void draw_circle(int *framebuffer, struct fb_var_screeninfo vinfo) { + for (int i = 1; i <= 12; ++i) { + float angle = (i * 30 - 90) * M_PI / 180.0; + int x = CENTER_X + (int)(RADIUS * cos(angle)); + int y = CENTER_Y + (int)(RADIUS * sin(angle)); + + char buffer[3]; + sprintf(buffer, "%d", i); + draw_text(framebuffer, vinfo, buffer, x - 10, y - 10, 3, 0xFFFFFF); // Increased the size to '3' for visibility + } +} + +// Draw clock hands +void draw_hand(int *framebuffer, struct fb_var_screeninfo vinfo, float angle, int length, int color) { + int x_end = CENTER_X + length * cos(angle); + int y_end = CENTER_Y - length * sin(angle); + draw_line(framebuffer, vinfo, CENTER_X, CENTER_Y, x_end, y_end, color); +} + +// Draw the clock face with numbers +void draw_clock_face(int *framebuffer, struct fb_var_screeninfo vinfo) { + memset(framebuffer, 0, vinfo.yres_virtual * vinfo.xres_virtual * sizeof(int)); // Clear screen + draw_circle(framebuffer, vinfo); // Draw the numbers +} + +// Update the clock hands and date/time display +void update_time(int *framebuffer, struct fb_var_screeninfo vinfo) { + time_t rawtime; + struct tm *timeinfo; + char date_buffer[80]; + char time_buffer[80]; + + time(&rawtime); + timeinfo = localtime(&rawtime); + + // Correcting hour and minute hand angles + float hour_angle = ((timeinfo->tm_hour % 12) * 30 + timeinfo->tm_min * 0.5) * (M_PI / 180.0) - M_PI / 2; + float minute_angle = (timeinfo->tm_min * 6 + timeinfo->tm_sec * 0.1) * (M_PI / 180.0) - M_PI / 2; + + // Draw both hands in black color + draw_hand(framebuffer, vinfo, hour_angle, HOUR_HAND_LENGTH, 0x000000); // Hour hand in black + draw_hand(framebuffer, vinfo, minute_angle, MINUTE_HAND_LENGTH, 0x000000); // Minute hand in black + + // Display the date + strftime(date_buffer, sizeof(date_buffer), "%Y-%m-%d", timeinfo); + draw_text(framebuffer, vinfo, date_buffer, CENTER_X - 100, CENTER_Y + 300, 3, 0xFFFFFF); // Moved lower and increased size + + // Display the time + strftime(time_buffer, sizeof(time_buffer), "%H:%M:%S", timeinfo); + draw_text(framebuffer, vinfo, time_buffer, CENTER_X - 80, CENTER_Y + 350, 3, 0xFFFFFF); // Moved lower and increased size +} + +// Main function +int main() { + // Open the framebuffer device + int fbfd = open("/dev/fb0", O_RDWR); + if (fbfd == -1) { + perror("Error: cannot open framebuffer device"); + exit(1); + } + + // Get variable screen information + struct fb_var_screeninfo vinfo; + if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) { + perror("Error reading variable information"); + close(fbfd); + exit(2); + } + + // Map the framebuffer to user memory + size_t screensize = vinfo.yres_virtual * vinfo.xres_virtual * vinfo.bits_per_pixel / 8; + int *framebuffer = (int *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); + if (framebuffer == MAP_FAILED) { + perror("Error mapping framebuffer device to memory"); + close(fbfd); + exit(3); + } + + // Continuously update the clock + while (1) { + draw_clock_face(framebuffer, vinfo); + update_time(framebuffer, vinfo); + sleep(1); // Sleep for 1 second to update the clock every second + } + + // Cleanup + munmap(framebuffer, screensize); + close(fbfd); + + return 0; +} diff --git a/render/README.md b/render/README.md new file mode 100644 index 0000000..76ba9e5 --- /dev/null +++ b/render/README.md @@ -0,0 +1,3 @@ +# render Project + +This is a C project generated with the setup tool. diff --git a/render/build/Makefile b/render/build/Makefile new file mode 100644 index 0000000..a052d2e --- /dev/null +++ b/render/build/Makefile @@ -0,0 +1,26 @@ +CC = gcc +CFLAGS = -Wall -O2 + +SRC_DIR = ../src +OBJ_DIR = ../obj +BUILD_DIR = . + +TARGET = $(BUILD_DIR)/cube_render + +SRCS = $(wildcard $(SRC_DIR)/*.c) +OBJS = $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) $(CFLAGS) -o $@ $^ -lm + +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c + @mkdir -p $(OBJ_DIR) + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -rf $(OBJ_DIR)/*.o $(TARGET) + +rebuild: clean all + diff --git a/render/build/cube_render b/render/build/cube_render new file mode 100755 index 0000000..ccf50d7 Binary files /dev/null and b/render/build/cube_render differ diff --git a/render/obj/main.o b/render/obj/main.o new file mode 100644 index 0000000..db05e4b Binary files /dev/null and b/render/obj/main.o differ diff --git a/render/src/cube.c.bak b/render/src/cube.c.bak new file mode 100644 index 0000000..e815f31 --- /dev/null +++ b/render/src/cube.c.bak @@ -0,0 +1,189 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +// Cube parameters +#define CUBE_SIZE 200.0 +#define COLOR 0xFFFFFF // White for 32-bit or RGB565 for 16-bit +#define FRAME_DELAY 16000 // Microseconds (about 60fps) +#define ROTATION_SPEED 0.02 + +// Structure for framebuffer info +struct framebuffer_info { + int fb_fd; + uint8_t* fb_ptr; + struct fb_var_screeninfo vinfo; + struct fb_fix_screeninfo finfo; + long int screensize; +}; + +// Structure for 3D point +typedef struct { + float x, y, z; +} Point3D; + +// Cube vertices +Point3D cube[8] = { + {-CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, + { CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, + { CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, + {-CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, + {-CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, + { CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, + { CUBE_SIZE, CUBE_SIZE, CUBE_SIZE}, + {-CUBE_SIZE, CUBE_SIZE, CUBE_SIZE} +}; + +// Cube edges +int edges[12][2] = { + {0, 1}, {1, 2}, {2, 3}, {3, 0}, // Bottom face + {4, 5}, {5, 6}, {6, 7}, {7, 4}, // Top face + {0, 4}, {1, 5}, {2, 6}, {3, 7} // Connecting edges +}; + +// Function to initialize framebuffer +struct framebuffer_info init_framebuffer(const char* fb_path) { + struct framebuffer_info fb_info; + + fb_info.fb_fd = open(fb_path, O_RDWR); + if (fb_info.fb_fd == -1) { + perror("Error opening framebuffer device"); + exit(1); + } + + // Get fixed screen information + if (ioctl(fb_info.fb_fd, FBIOGET_FSCREENINFO, &fb_info.finfo)) { + perror("Error reading fixed information"); + exit(1); + } + + // Get variable screen information + if (ioctl(fb_info.fb_fd, FBIOGET_VSCREENINFO, &fb_info.vinfo)) { + perror("Error reading variable information"); + exit(1); + } + + // Calculate the screen size in bytes + fb_info.screensize = fb_info.vinfo.yres_virtual * fb_info.finfo.line_length; + + // Map framebuffer to memory + fb_info.fb_ptr = (uint8_t*)mmap(0, fb_info.screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_info.fb_fd, 0); + if ((intptr_t)fb_info.fb_ptr == -1) { + perror("Error mapping framebuffer to memory"); + exit(1); + } + + return fb_info; +} + +// Function to clear the screen +void clear_screen(struct framebuffer_info* fb_info) { + for (int i = 0; i < fb_info->screensize; i++) { + fb_info->fb_ptr[i] = 0; // Set each pixel to black + } +} + +// Function to set a pixel in the framebuffer +void set_pixel(struct framebuffer_info* fb_info, int x, int y, uint32_t color) { + if (x >= 0 && x < fb_info->vinfo.xres && y >= 0 && y < fb_info->vinfo.yres) { + long location = (x + fb_info->vinfo.xoffset) * (fb_info->vinfo.bits_per_pixel / 8) + + (y + fb_info->vinfo.yoffset) * fb_info->finfo.line_length; + + // Handle different bits per pixel + if (fb_info->vinfo.bits_per_pixel == 32) { + *((uint32_t*)(fb_info->fb_ptr + location)) = color; + } else if (fb_info->vinfo.bits_per_pixel == 16) { + uint16_t rgb565 = ((color & 0xF80000) >> 8) | ((color & 0x00FC00) >> 5) | ((color & 0x0000F8) >> 3); + *((uint16_t*)(fb_info->fb_ptr + location)) = rgb565; + } else { + printf("Unsupported bits per pixel: %d\n", fb_info->vinfo.bits_per_pixel); + } + } +} + +// Bresenham's Line Algorithm +void draw_line(struct framebuffer_info* fb_info, int x0, int y0, int x1, int y1, uint32_t color) { + int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1; + int err = dx + dy, e2; + + while (1) { + set_pixel(fb_info, x0, y0, color); + if (x0 == x1 && y0 == y1) break; + e2 = 2 * err; + if (e2 >= dy) { err += dy; x0 += sx; } + if (e2 <= dx) { err += dx; y0 += sy; } + } +} + +// Function to rotate 3D point +void rotate(Point3D* p, float angleX, float angleY, float angleZ) { + // Rotation around X-axis + float y = p->y * cos(angleX) - p->z * sin(angleX); + float z = p->y * sin(angleX) + p->z * cos(angleX); + p->y = y; + p->z = z; + + // Rotation around Y-axis + float x = p->x * cos(angleY) + p->z * sin(angleY); + z = -p->x * sin(angleY) + p->z * cos(angleY); + p->x = x; + p->z = z; + + // Rotation around Z-axis + x = p->x * cos(angleZ) - p->y * sin(angleZ); + y = p->x * sin(angleZ) + p->y * cos(angleZ); + p->x = x; + p->y = y; +} + +// Function to project 3D point onto 2D screen +void project(Point3D p, int* x2D, int* y2D, int screenWidth, int screenHeight, float dist) { + *x2D = (int)(screenWidth / 2 + p.x * (dist / (p.z + dist))); + *y2D = (int)(screenHeight / 2 + p.y * (dist / (p.z + dist))); +} + +// Main function +int main() { + struct framebuffer_info fb_info = init_framebuffer("/dev/fb0"); + + float angleX = 0, angleY = 0, angleZ = 0; + float dist = 400.0f; + + while (1) { + clear_screen(&fb_info); + + Point3D transformed[8]; + int projected[8][2]; + + // Rotate and project each vertex + for (int i = 0; i < 8; i++) { + transformed[i] = cube[i]; + rotate(&transformed[i], angleX, angleY, angleZ); + project(transformed[i], &projected[i][0], &projected[i][1], fb_info.vinfo.xres, fb_info.vinfo.yres, dist); + } + + // Draw the cube edges + for (int i = 0; i < 12; i++) { + draw_line(&fb_info, projected[edges[i][0]][0], projected[edges[i][0]][1], + projected[edges[i][1]][0], projected[edges[i][1]][1], COLOR); + } + + // Increment angles for rotation + angleX += ROTATION_SPEED; + angleY += ROTATION_SPEED * 0.5; + angleZ += ROTATION_SPEED * 0.25; + + usleep(FRAME_DELAY); // Sleep for ~60fps + } + + munmap(fb_info.fb_ptr, fb_info.screensize); + close(fb_info.fb_fd); + return 0; +} + diff --git a/render/src/main.c b/render/src/main.c new file mode 100644 index 0000000..fb2c3ad --- /dev/null +++ b/render/src/main.c @@ -0,0 +1,196 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define CUBE_SIZE 200.0 +#define COLOR 0xFFFFFF // White for 32-bit or RGB565 for 16-bit +#define FRAME_DELAY 50000 // Slower: Microseconds (~20fps) +#define ROTATION_SPEED 0.003 // Slower rotation speed + +// Structure for framebuffer info +struct framebuffer_info { + int fb_fd; + uint8_t* fb_ptr; + struct fb_var_screeninfo vinfo; + struct fb_fix_screeninfo finfo; + long int screensize; +}; + +// Structure for 3D point +typedef struct { + float x, y, z; +} Point3D; + +// Cube vertices +Point3D cube[8] = { + {-CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, + { CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, + { CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, + {-CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, + {-CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, + { CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, + { CUBE_SIZE, CUBE_SIZE, CUBE_SIZE}, + {-CUBE_SIZE, CUBE_SIZE, CUBE_SIZE} +}; + +// Cube edges +int edges[12][2] = { + {0, 1}, {1, 2}, {2, 3}, {3, 0}, // Bottom face + {4, 5}, {5, 6}, {6, 7}, {7, 4}, // Top face + {0, 4}, {1, 5}, {2, 6}, {3, 7} // Connecting edges +}; + +// Function to initialize framebuffer +struct framebuffer_info init_framebuffer(const char* fb_path) { + struct framebuffer_info fb_info; + + fb_info.fb_fd = open(fb_path, O_RDWR); + if (fb_info.fb_fd == -1) { + perror("Error opening framebuffer device"); + exit(1); + } + + // Get fixed screen information + if (ioctl(fb_info.fb_fd, FBIOGET_FSCREENINFO, &fb_info.finfo)) { + perror("Error reading fixed information"); + exit(1); + } + + // Get variable screen information + if (ioctl(fb_info.fb_fd, FBIOGET_VSCREENINFO, &fb_info.vinfo)) { + perror("Error reading variable information"); + exit(1); + } + + // Calculate the screen size in bytes + fb_info.screensize = fb_info.vinfo.yres_virtual * fb_info.finfo.line_length; + + // Map framebuffer to memory + fb_info.fb_ptr = (uint8_t*)mmap(0, fb_info.screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_info.fb_fd, 0); + if ((intptr_t)fb_info.fb_ptr == -1) { + perror("Error mapping framebuffer to memory"); + exit(1); + } + + return fb_info; +} + +// Function to clear the screen +void clear_screen(struct framebuffer_info* fb_info) { + for (int i = 0; i < fb_info->screensize; i++) { + fb_info->fb_ptr[i] = 0; // Set each pixel to black + } +} + +// Function to set a pixel in the framebuffer +void set_pixel(struct framebuffer_info* fb_info, int x, int y, uint32_t color) { + if (x >= 0 && x < fb_info->vinfo.xres && y >= 0 && y < fb_info->vinfo.yres) { + long location = (x + fb_info->vinfo.xoffset) * (fb_info->vinfo.bits_per_pixel / 8) + + (y + fb_info->vinfo.yoffset) * fb_info->finfo.line_length; + + // Handle different bits per pixel + if (fb_info->vinfo.bits_per_pixel == 32) { + *((uint32_t*)(fb_info->fb_ptr + location)) = color; + } else if (fb_info->vinfo.bits_per_pixel == 16) { + uint16_t rgb565 = ((color & 0xF80000) >> 8) | ((color & 0x00FC00) >> 5) | ((color & 0x0000F8) >> 3); + *((uint16_t*)(fb_info->fb_ptr + location)) = rgb565; + } else { + printf("Unsupported bits per pixel: %d\n", fb_info->vinfo.bits_per_pixel); + } + } +} + +// Improved Bresenham's Line Algorithm with edge cases handling +void draw_line(struct framebuffer_info* fb_info, int x0, int y0, int x1, int y1, uint32_t color) { + int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1; + int err = dx + dy, e2; + + while (1) { + set_pixel(fb_info, x0, y0, color); + if (x0 == x1 && y0 == y1) break; + + e2 = 2 * err; + if (e2 >= dy) { err += dy; x0 += sx; } + if (e2 <= dx) { err += dx; y0 += sy; } + } +} + +// Function to rotate 3D point +void rotate(Point3D* p, float angleX, float angleY, float angleZ) { + // Rotation around X-axis + float y = p->y * cos(angleX) - p->z * sin(angleX); + float z = p->y * sin(angleX) + p->z * cos(angleX); + p->y = y; + p->z = z; + + // Rotation around Y-axis + float x = p->x * cos(angleY) + p->z * sin(angleY); + z = -p->x * sin(angleY) + p->z * cos(angleY); + p->x = x; + p->z = z; + + // Rotation around Z-axis + x = p->x * cos(angleZ) - p->y * sin(angleZ); + y = p->x * sin(angleZ) + p->y * cos(angleZ); + p->x = x; + p->y = y; +} + +// Function to project 3D point onto 2D screen +void project(Point3D p, int* x2D, int* y2D, int screenWidth, int screenHeight, float dist) { + float scale = dist / (p.z + dist); // Perspective scaling + *x2D = (int)(screenWidth / 2 + p.x * scale); + *y2D = (int)(screenHeight / 2 + p.y * scale); + + // Ensure the projected point remains within screen bounds + if (*x2D < 0) *x2D = 0; + if (*x2D >= screenWidth) *x2D = screenWidth - 1; + if (*y2D < 0) *y2D = 0; + if (*y2D >= screenHeight) *y2D = screenHeight - 1; +} + +// Main function +int main() { + struct framebuffer_info fb_info = init_framebuffer("/dev/fb0"); + + float angleX = 0, angleY = 0, angleZ = 0; + float dist = 400.0f; + + while (1) { + clear_screen(&fb_info); + + Point3D transformed[8]; + int projected[8][2]; + + // Rotate and project each vertex + for (int i = 0; i < 8; i++) { + transformed[i] = cube[i]; + rotate(&transformed[i], angleX, angleY, angleZ); + project(transformed[i], &projected[i][0], &projected[i][1], fb_info.vinfo.xres, fb_info.vinfo.yres, dist); + } + + // Draw the cube edges + for (int i = 0; i < 12; i++) { + draw_line(&fb_info, projected[edges[i][0]][0], projected[edges[i][0]][1], + projected[edges[i][1]][0], projected[edges[i][1]][1], COLOR); + } + + // Increment angles for slower rotation + angleX += ROTATION_SPEED; + angleY += ROTATION_SPEED * 0.5; + angleZ += ROTATION_SPEED * 0.25; + + usleep(FRAME_DELAY); // Slower frame rate for smoother rotation + } + + munmap(fb_info.fb_ptr, fb_info.screensize); + close(fb_info.fb_fd); + return 0; +} + diff --git a/render/src/pixeltest.c.bak b/render/src/pixeltest.c.bak new file mode 100644 index 0000000..c83e7c8 --- /dev/null +++ b/render/src/pixeltest.c.bak @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +// Cube parameters +#define COLOR 0xFFFFFF // White for 32-bit or RGB565 for 16-bit + +// Structure for framebuffer info +struct framebuffer_info { + int fb_fd; + uint8_t* fb_ptr; + struct fb_var_screeninfo vinfo; + struct fb_fix_screeninfo finfo; + long int screensize; +}; + +// Function to initialize framebuffer +struct framebuffer_info init_framebuffer(const char* fb_path) { + struct framebuffer_info fb_info; + + fb_info.fb_fd = open(fb_path, O_RDWR); + if (fb_info.fb_fd == -1) { + perror("Error opening framebuffer device"); + exit(1); + } + + // Get fixed screen information + if (ioctl(fb_info.fb_fd, FBIOGET_FSCREENINFO, &fb_info.finfo)) { + perror("Error reading fixed information"); + exit(1); + } + + // Get variable screen information + if (ioctl(fb_info.fb_fd, FBIOGET_VSCREENINFO, &fb_info.vinfo)) { + perror("Error reading variable information"); + exit(1); + } + + // Calculate the screen size in bytes + fb_info.screensize = fb_info.vinfo.yres_virtual * fb_info.finfo.line_length; + + // Map framebuffer to memory + fb_info.fb_ptr = (uint8_t*)mmap(0, fb_info.screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_info.fb_fd, 0); + if ((intptr_t)fb_info.fb_ptr == -1) { + perror("Error mapping framebuffer to memory"); + exit(1); + } + + // Debugging: print framebuffer info + printf("Framebuffer resolution: %dx%d, %d bpp\n", fb_info.vinfo.xres, fb_info.vinfo.yres, fb_info.vinfo.bits_per_pixel); + printf("Framebuffer screensize: %ld bytes\n", fb_info.screensize); + + return fb_info; +} + +// Function to clear the screen +void clear_screen(struct framebuffer_info* fb_info) { + for (int i = 0; i < fb_info->screensize; i++) { + fb_info->fb_ptr[i] = 0; // Set each pixel to black + } +} + +// Function to set a pixel in the framebuffer +void set_pixel(struct framebuffer_info* fb_info, int x, int y, uint32_t color) { + if (x >= 0 && x < fb_info->vinfo.xres && y >= 0 && y < fb_info->vinfo.yres) { + long location = (x + fb_info->vinfo.xoffset) * (fb_info->vinfo.bits_per_pixel / 8) + + (y + fb_info->vinfo.yoffset) * fb_info->finfo.line_length; + + // Handle different bits per pixel + if (fb_info->vinfo.bits_per_pixel == 32) { + // 32-bit color (ARGB or XRGB) + *((uint32_t*)(fb_info->fb_ptr + location)) = color; + } else if (fb_info->vinfo.bits_per_pixel == 16) { + // 16-bit color (RGB565) + uint16_t rgb565 = ((color & 0xF80000) >> 8) | ((color & 0x00FC00) >> 5) | ((color & 0x0000F8) >> 3); + *((uint16_t*)(fb_info->fb_ptr + location)) = rgb565; + } else { + printf("Unsupported bits per pixel: %d\n", fb_info->vinfo.bits_per_pixel); + } + } +} + +// Main function +int main() { + // Initialize framebuffer + struct framebuffer_info fb_info = init_framebuffer("/dev/fb0"); + + // Clear the screen first + clear_screen(&fb_info); + + // Draw a pixel at the center of the screen to test framebuffer access + int center_x = fb_info.vinfo.xres / 2; + int center_y = fb_info.vinfo.yres / 2; + printf("Drawing pixel at center: (%d, %d)\n", center_x, center_y); + + // Use appropriate color depth + set_pixel(&fb_info, center_x, center_y, COLOR); // Draw white pixel at the center + + // Hold for a while to inspect + printf("Framebuffer test complete. Pixel drawn at the center.\n"); + sleep(10); // Wait for 10 seconds to allow visual inspection + + // Unmap and close the framebuffer + munmap(fb_info.fb_ptr, fb_info.screensize); + close(fb_info.fb_fd); + + return 0; +} + diff --git a/render/src/slow_cube.c.bak b/render/src/slow_cube.c.bak new file mode 100644 index 0000000..42ec6f8 --- /dev/null +++ b/render/src/slow_cube.c.bak @@ -0,0 +1,189 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define CUBE_SIZE 200.0 +#define COLOR 0xFFFFFF // White for 32-bit or RGB565 for 16-bit +#define FRAME_DELAY 50000 // Slower: Microseconds (~20fps) +#define ROTATION_SPEED 0.005 // Slower rotation speed + +// Structure for framebuffer info +struct framebuffer_info { + int fb_fd; + uint8_t* fb_ptr; + struct fb_var_screeninfo vinfo; + struct fb_fix_screeninfo finfo; + long int screensize; +}; + +// Structure for 3D point +typedef struct { + float x, y, z; +} Point3D; + +// Cube vertices +Point3D cube[8] = { + {-CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, + { CUBE_SIZE, -CUBE_SIZE, -CUBE_SIZE}, + { CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, + {-CUBE_SIZE, CUBE_SIZE, -CUBE_SIZE}, + {-CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, + { CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE}, + { CUBE_SIZE, CUBE_SIZE, CUBE_SIZE}, + {-CUBE_SIZE, CUBE_SIZE, CUBE_SIZE} +}; + +// Cube edges +int edges[12][2] = { + {0, 1}, {1, 2}, {2, 3}, {3, 0}, // Bottom face + {4, 5}, {5, 6}, {6, 7}, {7, 4}, // Top face + {0, 4}, {1, 5}, {2, 6}, {3, 7} // Connecting edges +}; + +// Function to initialize framebuffer +struct framebuffer_info init_framebuffer(const char* fb_path) { + struct framebuffer_info fb_info; + + fb_info.fb_fd = open(fb_path, O_RDWR); + if (fb_info.fb_fd == -1) { + perror("Error opening framebuffer device"); + exit(1); + } + + // Get fixed screen information + if (ioctl(fb_info.fb_fd, FBIOGET_FSCREENINFO, &fb_info.finfo)) { + perror("Error reading fixed information"); + exit(1); + } + + // Get variable screen information + if (ioctl(fb_info.fb_fd, FBIOGET_VSCREENINFO, &fb_info.vinfo)) { + perror("Error reading variable information"); + exit(1); + } + + // Calculate the screen size in bytes + fb_info.screensize = fb_info.vinfo.yres_virtual * fb_info.finfo.line_length; + + // Map framebuffer to memory + fb_info.fb_ptr = (uint8_t*)mmap(0, fb_info.screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_info.fb_fd, 0); + if ((intptr_t)fb_info.fb_ptr == -1) { + perror("Error mapping framebuffer to memory"); + exit(1); + } + + return fb_info; +} + +// Function to clear the screen +void clear_screen(struct framebuffer_info* fb_info) { + for (int i = 0; i < fb_info->screensize; i++) { + fb_info->fb_ptr[i] = 0; // Set each pixel to black + } +} + +// Function to set a pixel in the framebuffer +void set_pixel(struct framebuffer_info* fb_info, int x, int y, uint32_t color) { + if (x >= 0 && x < fb_info->vinfo.xres && y >= 0 && y < fb_info->vinfo.yres) { + long location = (x + fb_info->vinfo.xoffset) * (fb_info->vinfo.bits_per_pixel / 8) + + (y + fb_info->vinfo.yoffset) * fb_info->finfo.line_length; + + // Handle different bits per pixel + if (fb_info->vinfo.bits_per_pixel == 32) { + *((uint32_t*)(fb_info->fb_ptr + location)) = color; + } else if (fb_info->vinfo.bits_per_pixel == 16) { + uint16_t rgb565 = ((color & 0xF80000) >> 8) | ((color & 0x00FC00) >> 5) | ((color & 0x0000F8) >> 3); + *((uint16_t*)(fb_info->fb_ptr + location)) = rgb565; + } else { + printf("Unsupported bits per pixel: %d\n", fb_info->vinfo.bits_per_pixel); + } + } +} + +// Improved Bresenham's Line Algorithm with edge cases handling +void draw_line(struct framebuffer_info* fb_info, int x0, int y0, int x1, int y1, uint32_t color) { + int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1; + int err = (dx > dy ? dx : -dy) / 2, e2; + + for (;;) { + set_pixel(fb_info, x0, y0, color); + if (x0 == x1 && y0 == y1) break; + e2 = err; + if (e2 > -dx) { err -= dy; x0 += sx; } + if (e2 < dy) { err += dx; y0 += sy; } + } +} + +// Function to rotate 3D point +void rotate(Point3D* p, float angleX, float angleY, float angleZ) { + // Rotation around X-axis + float y = p->y * cos(angleX) - p->z * sin(angleX); + float z = p->y * sin(angleX) + p->z * cos(angleX); + p->y = y; + p->z = z; + + // Rotation around Y-axis + float x = p->x * cos(angleY) + p->z * sin(angleY); + z = -p->x * sin(angleY) + p->z * cos(angleY); + p->x = x; + p->z = z; + + // Rotation around Z-axis + x = p->x * cos(angleZ) - p->y * sin(angleZ); + y = p->x * sin(angleZ) + p->y * cos(angleZ); + p->x = x; + p->y = y; +} + +// Function to project 3D point onto 2D screen +void project(Point3D p, int* x2D, int* y2D, int screenWidth, int screenHeight, float dist) { + float scale = dist / (p.z + dist); // Perspective scaling + *x2D = (int)(screenWidth / 2 + p.x * scale); + *y2D = (int)(screenHeight / 2 + p.y * scale); +} + +// Main function +int main() { + struct framebuffer_info fb_info = init_framebuffer("/dev/fb0"); + + float angleX = 0, angleY = 0, angleZ = 0; + float dist = 400.0f; + + while (1) { + clear_screen(&fb_info); + + Point3D transformed[8]; + int projected[8][2]; + + // Rotate and project each vertex + for (int i = 0; i < 8; i++) { + transformed[i] = cube[i]; + rotate(&transformed[i], angleX, angleY, angleZ); + project(transformed[i], &projected[i][0], &projected[i][1], fb_info.vinfo.xres, fb_info.vinfo.yres, dist); + } + + // Draw the cube edges + for (int i = 0; i < 12; i++) { + draw_line(&fb_info, projected[edges[i][0]][0], projected[edges[i][0]][1], + projected[edges[i][1]][0], projected[edges[i][1]][1], COLOR); + } + + // Increment angles for slower rotation + angleX += ROTATION_SPEED; + angleY += ROTATION_SPEED * 0.5; + angleZ += ROTATION_SPEED * 0.25; + + usleep(FRAME_DELAY); // Slower frame rate for smoother rotation + } + + munmap(fb_info.fb_ptr, fb_info.screensize); + close(fb_info.fb_fd); + return 0; +} + diff --git a/riceapp/README.md b/riceapp/README.md new file mode 100644 index 0000000..27612cb --- /dev/null +++ b/riceapp/README.md @@ -0,0 +1,3 @@ +# riceapp Project + +This is a C project generated with the setup tool. diff --git a/riceapp/build/Makefile b/riceapp/build/Makefile new file mode 100644 index 0000000..a63f9fe --- /dev/null +++ b/riceapp/build/Makefile @@ -0,0 +1,24 @@ +CC = gcc +CFLAGS = -I../include -Wall -O2 +LDFLAGS = -lm +SRCDIR = ../src +OBJDIR = ../obj +BUILDDIR = ../build +TARGET = cube_app + +SOURCES = $(wildcard $(SRCDIR)/*.c) +OBJECTS = $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o) + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(OBJECTS) $(LDFLAGS) -o $(BUILDDIR)/$(TARGET) + +$(OBJDIR)/%.o: $(SRCDIR)/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJDIR)/*.o $(BUILDDIR)/$(TARGET) + +.PHONY: all clean + diff --git a/riceapp/build/cube_app b/riceapp/build/cube_app new file mode 100755 index 0000000..8a22307 Binary files /dev/null and b/riceapp/build/cube_app differ diff --git a/riceapp/include/cube.h b/riceapp/include/cube.h new file mode 100644 index 0000000..995a038 --- /dev/null +++ b/riceapp/include/cube.h @@ -0,0 +1,21 @@ +#ifndef CUBE_H +#define CUBE_H + +typedef struct { + float x, y, z; +} Vertex; + +typedef struct { + int width, height; +} Screen; + +// Function declarations +void init_framebuffer(); +void draw_cube(Vertex vertices[8], Screen *screen); +void translate(Vertex *v, float dx, float dy, float dz); +void rotate_cube(Vertex vertices[8], float angleX, float angleY); +void update_screen(Screen *screen); +void handle_collision(Vertex *v, Screen *screen); + +#endif + diff --git a/riceapp/obj/cube.o b/riceapp/obj/cube.o new file mode 100644 index 0000000..9213c2b Binary files /dev/null and b/riceapp/obj/cube.o differ diff --git a/riceapp/src/cube.c b/riceapp/src/cube.c new file mode 100644 index 0000000..1c6a0a6 --- /dev/null +++ b/riceapp/src/cube.c @@ -0,0 +1,178 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "cube.h" + +// Framebuffer and screen parameters +int fbfd = 0; +struct fb_var_screeninfo vinfo; +struct fb_fix_screeninfo finfo; +long int screensize = 0; +char *fbp = 0; + +// Cube vertex data +Vertex vertices[8] = { + {-50, -50, -50}, {50, -50, -50}, {50, 50, -50}, {-50, 50, -50}, + {-50, -50, 50}, {50, -50, 50}, {50, 50, 50}, {-50, 50, 50} +}; + +float velocityX = 2.0, velocityY = 1.5; +float rotationSpeed = 0.02; +float cubeX = 300, cubeY = 200; +Screen screen = {800, 600}; // Screen resolution + +// Initialize framebuffer +void init_framebuffer() { + fbfd = open("/dev/fb0", O_RDWR); + if (fbfd == -1) { + perror("Error opening framebuffer device"); + exit(1); + } + if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) { + perror("Error reading fixed information"); + exit(2); + } + if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) { + perror("Error reading variable information"); + exit(3); + } + screensize = vinfo.yres_virtual * finfo.line_length; + fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); + if ((int)fbp == -1) { + perror("Error mapping framebuffer device to memory"); + exit(4); + } +} + +// Clear screen +void clear_screen() { + for (int y = 0; y < screen.height; y++) { + for (int x = 0; x < screen.width; x++) { + long int location = (x + vinfo.xoffset) * (vinfo.bits_per_pixel / 8) + (y + vinfo.yoffset) * finfo.line_length; + *((unsigned int*)(fbp + location)) = 0x000000; // Black color + } + } +} + +// Put pixel on screen +void put_pixel(int x, int y, unsigned int color) { + if (x >= 0 && x < screen.width && y >= 0 && y < screen.height) { + long int location = (x + vinfo.xoffset) * (vinfo.bits_per_pixel / 8) + (y + vinfo.yoffset) * finfo.line_length; + *((unsigned int*)(fbp + location)) = color; + } +} + +// Draw line between two points (Bresenham's line algorithm) +void draw_line(int x1, int y1, int x2, int y2, unsigned int color) { + int dx = abs(x2 - x1), sx = x1 < x2 ? 1 : -1; + int dy = -abs(y2 - y1), sy = y1 < y2 ? 1 : -1; + int err = dx + dy, e2; + + while (1) { + put_pixel(x1, y1, color); + if (x1 == x2 && y1 == y2) break; + e2 = 2 * err; + if (e2 >= dy) { err += dy; x1 += sx; } + if (e2 <= dx) { err += dx; y1 += sy; } + } +} + +// Project 3D coordinates to 2D +void project(Vertex v, int *x, int *y) { + float scale = 200 / (v.z + 200); // Perspective projection scaling + *x = (int)(v.x * scale + cubeX); + *y = (int)(v.y * scale + cubeY); +} + +// Draw the 3D cube +void draw_cube(Vertex vertices[8]) { + int projectedX[8], projectedY[8]; + for (int i = 0; i < 8; i++) { + project(vertices[i], &projectedX[i], &projectedY[i]); + } + + // Draw front face + for (int i = 0; i < 4; i++) { + draw_line(projectedX[i], projectedY[i], projectedX[(i+1)%4], projectedY[(i+1)%4], 0xFFFFFF); + } + + // Draw back face + for (int i = 4; i < 8; i++) { + draw_line(projectedX[i], projectedY[i], projectedX[((i+1)%4)+4], projectedY[((i+1)%4)+4], 0x00FF00); + } + + // Draw edges between front and back faces + for (int i = 0; i < 4; i++) { + draw_line(projectedX[i], projectedY[i], projectedX[i+4], projectedY[i+4], 0xFF0000); + } +} + +// Translate vertices +void translate(Vertex *v, float dx, float dy, float dz) { + v->x += dx; + v->y += dy; + v->z += dz; +} + +// Rotate cube vertices around X and Y axes +void rotate_cube(Vertex vertices[8], float angleX, float angleY) { + float cosX = cos(angleX), sinX = sin(angleX); + float cosY = cos(angleY), sinY = sin(angleY); + + for (int i = 0; i < 8; i++) { + float x = vertices[i].x, y = vertices[i].y, z = vertices[i].z; + + // Rotation around X-axis + vertices[i].y = y * cosX - z * sinX; + vertices[i].z = y * sinX + z * cosX; + + // Rotation around Y-axis + vertices[i].x = x * cosY - z * sinY; + vertices[i].z = x * sinY + z * cosY; + } +} + +// Handle screen edge collision +void handle_collision() { + if (cubeX >= screen.width - 100 || cubeX <= 100) velocityX = -velocityX; + if (cubeY >= screen.height - 100 || cubeY <= 100) velocityY = -velocityY; +} + +int main() { + init_framebuffer(); + + float angleX = 0.0, angleY = 0.0; + + while (1) { + // Clear the screen + clear_screen(); + + // Translate the cube across the screen + cubeX += velocityX; + cubeY += velocityY; + handle_collision(); + + // Rotate the cube + rotate_cube(vertices, angleX, angleY); + + // Draw the cube on the screen + draw_cube(vertices); + + // Update rotation angles for the next iteration + angleX += rotationSpeed; + angleY += rotationSpeed; + + // Add delay to control frame rate (~60 FPS) + usleep(16000); + } + + munmap(fbp, screensize); + close(fbfd); + return 0; +} +