Initial Commit

This commit is contained in:
klein panic
2024-09-27 19:32:14 -04:00
commit 53610a8c1c
21 changed files with 1340 additions and 0 deletions

3
render/README.md Normal file
View File

@@ -0,0 +1,3 @@
# render Project
This is a C project generated with the setup tool.

26
render/build/Makefile Normal file
View File

@@ -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

BIN
render/build/cube_render Executable file

Binary file not shown.

BIN
render/obj/main.o Normal file

Binary file not shown.

189
render/src/cube.c.bak Normal file
View File

@@ -0,0 +1,189 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <math.h>
#include <stdint.h>
// 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;
}

196
render/src/main.c Normal file
View File

@@ -0,0 +1,196 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <math.h>
#include <stdint.h>
#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;
}

114
render/src/pixeltest.c.bak Normal file
View File

@@ -0,0 +1,114 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <math.h>
#include <stdint.h>
// 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;
}

189
render/src/slow_cube.c.bak Normal file
View File

@@ -0,0 +1,189 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <math.h>
#include <stdint.h>
#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;
}