Here is the implementation of a 3D rasterizer in pure C. I want you to update the code such that, a distance buffer is computed not from the camera, but from a light source. Implement a whole light system this way, by separating the camera from the light origin.
Current C code:
```c
/* 
   Simple 3D Rasterizer in Pure C
   - Renders triangles in the terminal using ASCII characters.
   - Supports perspective projection with a field of view (FOV) of 90 degrees.
   - Allows global and local transformations (translation, rotation, scaling) for triangles.
   - Includes camera transformations (translation and rotation).
   - Continuously rotates the first triangle around its Z-axis in a loop.

   Compile with:
       gcc -o rasterizer rasterizer.c -lm
*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <unistd.h>   // For usleep()

/* Screen dimensions */
#define WIDTH 120*4
#define HEIGHT 60*4

/* Depth range */
#define ZNEAR_CLIP 0.1f     // Near clipping plane
#define ZFAR_CLIP 1000.0f   // Far clipping plane
#define ZNEAR 0.1f
#define ZFAR 10.0f

/* Field of view in degrees */
#define FOV 90.0f

/* Aspect ratio correction (characters are taller than they are wide) */
#define ASPECT_RATIO_CORRECTION 1.2f

/* Precompute FOV scaling factor */
#define FOV_RAD (FOV * (M_PI / 180.0f))
#define F_SCALE (1.0f / tanf(FOV_RAD / 2.0f))

/* Type Definitions */
typedef unsigned char u8_t;
typedef float f32_t;
typedef int i32_t;
typedef unsigned int u32_t;

typedef struct { u8_t r, g, b; } col_t;
typedef struct { f32_t x, y, z; } vec3_t;
typedef struct { f32_t x, y, z, w; } vec4_t;
typedef struct { f32_t m[4][4]; } mat4x4_t;

typedef struct { vec3_t p; col_t c; } vert_t;
typedef struct { vert_t a, b, c; } tri_t;
typedef struct { i32_t x, y; f32_t z; } screen_vert_t;
typedef struct { screen_vert_t a, b, c; } screen_tri_t;

/* Camera Structure */
typedef struct {
    vec3_t position;
    f32_t pitch; // Rotation around X-axis (in radians)
    f32_t yaw;   // Rotation around Y-axis (in radians)
    f32_t roll;  // Rotation around Z-axis (in radians)
} camera_t;

/* Function Prototypes */

/* Matrix Operations */
void mat4x4_identity(mat4x4_t *mat);
void mat4x4_multiply(mat4x4_t *result, const mat4x4_t *a, const mat4x4_t *b);
void mat4x4_translate(mat4x4_t *mat, const vec3_t *t);
void mat4x4_rotate_x(mat4x4_t *mat, f32_t angle);
void mat4x4_rotate_y(mat4x4_t *mat, f32_t angle);
void mat4x4_rotate_z(mat4x4_t *mat, f32_t angle);
void mat4x4_scale(mat4x4_t *mat, const vec3_t *s);
vec3_t mat4x4_multiply_vec3(const mat4x4_t *mat, const vec3_t *v);

/* Transformation Functions for Triangles */
void translate_triangle(tri_t *tri, vec3_t t);
void translate_triangle_local_along_normal(tri_t *tri, float distance);
void rotate_triangle(tri_t *tri, f32_t angle_x, f32_t angle_y, f32_t angle_z);
void rotate_triangle_deg(tri_t *tri, f32_t angle_x_deg, f32_t angle_y_deg, f32_t angle_z_deg);
void scale_triangle(tri_t *tri, const vec3_t s);
void scale_triangle_local(tri_t *tri, const vec3_t s);
void scale_triangle_local_uniform(tri_t *tri, f32_t scale_factor);
void rotate_triangle_local(tri_t *tri, f32_t angle_x, f32_t angle_y, f32_t angle_z);
void rotate_triangle_local_deg(tri_t *tri, f32_t angle_x_deg, f32_t angle_y_deg, f32_t angle_z_deg);
vec3_t compute_centroid(const tri_t *tri);

/* Camera Transformation Functions */
void translate_camera(camera_t *cam, const vec3_t *t);
void rotate_camera(camera_t *cam, f32_t angle_x, f32_t angle_y, f32_t angle_z);
void rotate_camera_deg(camera_t *cam, f32_t angle_x_deg, f32_t angle_y_deg, f32_t angle_z_deg);

/* Rendering Functions */
void set_color(col_t c);
void next_line();
void clear_screen();
void clear_fb(col_t fb[HEIGHT][WIDTH], f32_t zb_buffer[HEIGHT][WIDTH], f32_t distance_buffer[HEIGHT][WIDTH]);
void render_fb_distance(const col_t fb[HEIGHT][WIDTH], const f32_t distance_buffer[HEIGHT][WIDTH]);

/* Projection and Rasterization */
vec3_t apply_camera_transform(const camera_t *cam, const vec3_t *p);
screen_vert_t project_vertex(const camera_t *cam, const vec3_t *p_world);
void compute_barycentric(int px, int py, screen_tri_t tri, f32_t *u, f32_t *v, f32_t *w);
void rasterize_triangle(const tri_t *tri, const camera_t *cam, col_t fb[HEIGHT][WIDTH], f32_t zb_buffer[HEIGHT][WIDTH], f32_t distance_buffer[HEIGHT][WIDTH]);

/* Helper Functions */
f32_t deg_to_rad(f32_t degrees);

/* Function Implementations */

/* Helper function to convert degrees to radians */
f32_t deg_to_rad(f32_t degrees) {
    return degrees * (M_PI / 180.0f);
}

/* Matrix Operations Implementations */

void mat4x4_identity(mat4x4_t *mat) {
    memset(mat, 0, sizeof(mat4x4_t));
    for(int i = 0; i < 4; i++) {
        mat->m[i][i] = 1.0f;
    }
}

void mat4x4_multiply(mat4x4_t *result, const mat4x4_t *a, const mat4x4_t *b) {
    mat4x4_t temp;
    for(int i = 0; i < 4; i++) {
        for(int j = 0; j < 4; j++) {
            temp.m[i][j] = 0.0f;
            for(int k = 0; k < 4; k++) {
                temp.m[i][j] += a->m[i][k] * b->m[k][j];
            }
        }
    }
    *result = temp;
}

void mat4x4_translate(mat4x4_t *mat, const vec3_t *t) {
    mat4x4_identity(mat);
    mat->m[0][3] = t->x;
    mat->m[1][3] = t->y;
    mat->m[2][3] = t->z;
}

void mat4x4_rotate_x(mat4x4_t *mat, f32_t angle) {
    mat4x4_identity(mat);
    f32_t c = cosf(angle);
    f32_t s = sinf(angle);
    mat->m[1][1] = c;
    mat->m[1][2] = -s;
    mat->m[2][1] = s;
    mat->m[2][2] = c;
}

void mat4x4_rotate_y(mat4x4_t *mat, f32_t angle) {
    mat4x4_identity(mat);
    f32_t c = cosf(angle);
    f32_t s = sinf(angle);
    mat->m[0][0] = c;
    mat->m[0][2] = s;
    mat->m[2][0] = -s;
    mat->m[2][2] = c;
}

void mat4x4_rotate_z(mat4x4_t *mat, f32_t angle) {
    mat4x4_identity(mat);
    f32_t c = cosf(angle);
    f32_t s = sinf(angle);
    mat->m[0][0] = c;
    mat->m[0][1] = -s;
    mat->m[1][0] = s;
    mat->m[1][1] = c;
}

void mat4x4_scale(mat4x4_t *mat, const vec3_t *s) {
    mat4x4_identity(mat);
    mat->m[0][0] = s->x;
    mat->m[1][1] = s->y;
    mat->m[2][2] = s->z;
}

vec3_t mat4x4_multiply_vec3(const mat4x4_t *mat, const vec3_t *v) {
    vec4_t result;
    result.x = mat->m[0][0]*v->x + mat->m[0][1]*v->y + mat->m[0][2]*v->z + mat->m[0][3]*1.0f;
    result.y = mat->m[1][0]*v->x + mat->m[1][1]*v->y + mat->m[1][2]*v->z + mat->m[1][3]*1.0f;
    result.z = mat->m[2][0]*v->x + mat->m[2][1]*v->y + mat->m[2][2]*v->z + mat->m[2][3]*1.0f;
    result.w = mat->m[3][0]*v->x + mat->m[3][1]*v->y + mat->m[3][2]*v->z + mat->m[3][3]*1.0f;
    
    // Perform perspective divide if w is not 1
    if(result.w != 0.0f && result.w != 1.0f) {
        result.x /= result.w;
        result.y /= result.w;
        result.z /= result.w;
    }
    
    vec3_t final = { result.x, result.y, result.z };
    return final;
}

/* Transformation Functions for Triangles */

/* Function to translate a triangle globally */
void translate_triangle(tri_t *tri, vec3_t t) {
    tri->a.p.x += t.x;
    tri->a.p.y += t.y;
    tri->a.p.z += t.z;

    tri->b.p.x += t.x;
    tri->b.p.y += t.y;
    tri->b.p.z += t.z;

    tri->c.p.x += t.x;
    tri->c.p.y += t.y;
    tri->c.p.z += t.z;
}

/* Function to compute the normal vector of a triangle */
vec3_t compute_normal(const tri_t *tri) {
    // Calculate vectors AB and AC
    vec3_t ab = { tri->b.p.x - tri->a.p.x, tri->b.p.y - tri->a.p.y, tri->b.p.z - tri->a.p.z };
    vec3_t ac = { tri->c.p.x - tri->a.p.x, tri->c.p.y - tri->a.p.y, tri->c.p.z - tri->a.p.z };

    // Cross product AB x AC
    vec3_t cross = {
        ab.y * ac.z - ab.z * ac.y,
        ab.z * ac.x - ab.x * ac.z,
        ab.x * ac.y - ab.y * ac.x
    };

    // Normalize the vector
    f32_t length = sqrtf(cross.x * cross.x + cross.y * cross.y + cross.z * cross.z);
    if(length == 0.0f) return (vec3_t){0.0f, 0.0f, 0.0f};
    cross.x /= length;
    cross.y /= length;
    cross.z /= length;

    return cross;
}

/* Function to translate a triangle locally along its normal vector */
void translate_triangle_local_along_normal(tri_t *tri, float distance) {
    // Step 1: Compute the centroid
    vec3_t centroid = compute_centroid(tri);
    
    // Step 2: Compute the normal vector
    vec3_t normal = compute_normal(tri);
    
    // Step 3: Create translation vector along the normal
    vec3_t translation = { normal.x * distance, normal.y * distance, normal.z * distance };
    
    // Step 4: Translate the triangle by the translation vector
    translate_triangle(tri, translation);
}

/* Function to rotate a triangle globally using radians */
void rotate_triangle(tri_t *tri, f32_t angle_x, f32_t angle_y, f32_t angle_z) {
    mat4x4_t rot_x, rot_y, rot_z, temp, rot_total;

    /* Rotate around X-axis */
    mat4x4_rotate_x(&rot_x, angle_x);
    
    /* Rotate around Y-axis */
    mat4x4_rotate_y(&rot_y, angle_y);
    
    /* Rotate around Z-axis */
    mat4x4_rotate_z(&rot_z, angle_z);
    
    /* Combine rotations: Rz * Ry * Rx */
    mat4x4_multiply(&temp, &rot_y, &rot_x);
    mat4x4_multiply(&rot_total, &rot_z, &temp);
    
    /* Apply rotation to each vertex */
    tri->a.p = mat4x4_multiply_vec3(&rot_total, &tri->a.p);
    tri->b.p = mat4x4_multiply_vec3(&rot_total, &tri->b.p);
    tri->c.p = mat4x4_multiply_vec3(&rot_total, &tri->c.p);
}

/* Function to rotate a triangle globally using degrees */
void rotate_triangle_deg(tri_t *tri, f32_t angle_x_deg, f32_t angle_y_deg, f32_t angle_z_deg) {
    f32_t angle_x_rad = deg_to_rad(angle_x_deg);
    f32_t angle_y_rad = deg_to_rad(angle_y_deg);
    f32_t angle_z_rad = deg_to_rad(angle_z_deg);
    rotate_triangle(tri, angle_x_rad, angle_y_rad, angle_z_rad);
}

/* Function to scale a triangle globally */
void scale_triangle(tri_t *tri, const vec3_t s) {
    tri->a.p.x *= s.x;
    tri->a.p.y *= s.y;
    tri->a.p.z *= s.z;

    tri->b.p.x *= s.x;
    tri->b.p.y *= s.y;
    tri->b.p.z *= s.z;

    tri->c.p.x *= s.x;
    tri->c.p.y *= s.y;
    tri->c.p.z *= s.z;
}

/* Function to compute the centroid of a triangle */
vec3_t compute_centroid(const tri_t *tri) {
    vec3_t centroid;
    centroid.x = (tri->a.p.x + tri->b.p.x + tri->c.p.x) / 3.0f;
    centroid.y = (tri->a.p.y + tri->b.p.y + tri->c.p.y) / 3.0f;
    centroid.z = (tri->a.p.z + tri->b.p.z + tri->c.p.z) / 3.0f;
    return centroid;
}



/* Function to rotate a triangle around its centroid using radians */
void rotate_triangle_local(tri_t *tri, f32_t angle_x, f32_t angle_y, f32_t angle_z) {
    // Step 1: Compute the centroid
    vec3_t centroid = compute_centroid(tri);
    
    // Step 2: Translate the triangle so that the centroid is at the origin
    translate_triangle(tri, (vec3_t){ -centroid.x, -centroid.y, -centroid.z });
    
    // Step 3: Apply rotation
    rotate_triangle(tri, angle_x, angle_y, angle_z);
    
    // Step 4: Translate the triangle back to its original position
    translate_triangle(tri, centroid);
}

/* Function to rotate a triangle around its centroid using degrees */
void rotate_triangle_local_deg(tri_t *tri, f32_t angle_x_deg, f32_t angle_y_deg, f32_t angle_z_deg) {
    f32_t angle_x_rad = deg_to_rad(angle_x_deg);
    f32_t angle_y_rad = deg_to_rad(angle_y_deg);
    f32_t angle_z_rad = deg_to_rad(angle_z_deg);
    rotate_triangle_local(tri, angle_x_rad, angle_y_rad, angle_z_rad);
}

/* Function to scale a triangle relative to its centroid using scaling factors */
void scale_triangle_local(tri_t *tri, const vec3_t s) {
    // Step 1: Compute the centroid
    vec3_t centroid = compute_centroid(tri);
    
    // Step 2: Translate the triangle so that the centroid is at the origin
    translate_triangle(tri, (vec3_t){ -centroid.x, -centroid.y, -centroid.z });
    
    // Step 3: Apply scaling
    scale_triangle(tri, s);
    
    // Step 4: Translate the triangle back to its original position
    translate_triangle(tri, centroid);
}

/* Function to scale a triangle uniformly relative to its centroid */
void scale_triangle_local_uniform(tri_t *tri, f32_t scale_factor) {
    vec3_t scale = { scale_factor, scale_factor, scale_factor };
    scale_triangle_local(tri, scale);
}

/* Camera Transformation Functions */

/* Function to translate the camera */
void translate_camera(camera_t *cam, const vec3_t *t) {
    cam->position.x += t->x;
    cam->position.y += t->y;
    cam->position.z += t->z;
}

/* Function to rotate the camera using radians */
void rotate_camera(camera_t *cam, f32_t angle_x, f32_t angle_y, f32_t angle_z) {
    cam->pitch += angle_x;
    cam->yaw   += angle_y;
    cam->roll  += angle_z;
}

/* Function to rotate the camera using degrees */
void rotate_camera_deg(camera_t *cam, f32_t angle_x_deg, f32_t angle_y_deg, f32_t angle_z_deg) {
    f32_t angle_x_rad = deg_to_rad(angle_x_deg);
    f32_t angle_y_rad = deg_to_rad(angle_y_deg);
    f32_t angle_z_rad = deg_to_rad(angle_z_deg);
    rotate_camera(cam, angle_x_rad, angle_y_rad, angle_z_rad);
}

/* Function to apply camera transformation to a point (world space to camera space) */
vec3_t apply_camera_transform(const camera_t *cam, const vec3_t *p) {
    // Translate
    vec3_t translated = {
        p->x - cam->position.x,
        p->y - cam->position.y,
        p->z - cam->position.z
    };

    // Apply inverse rotations (pitch, yaw, roll)
    // Rotation order: Roll -> Pitch -> Yaw
    // Inverse rotations: Negate the angles

    // Rotate around Z-axis (Roll)
    f32_t cos_z = cosf(-cam->roll);
    f32_t sin_z = sinf(-cam->roll);
    f32_t x1 = translated.x * cos_z - translated.y * sin_z;
    f32_t y1 = translated.x * sin_z + translated.y * cos_z;
    f32_t z1 = translated.z;

    // Rotate around X-axis (Pitch)
    f32_t cos_x = cosf(-cam->pitch);
    f32_t sin_x = sinf(-cam->pitch);
    f32_t x2 = x1;
    f32_t y2 = y1 * cos_x - z1 * sin_x;
    f32_t z2 = y1 * sin_x + z1 * cos_x;

    // Rotate around Y-axis (Yaw)
    f32_t cos_y = cosf(-cam->yaw);
    f32_t sin_y = sinf(-cam->yaw);
    f32_t x3 = x2 * cos_y + z2 * sin_y;
    f32_t y3 = y2;
    f32_t z3 = -x2 * sin_y + z2 * cos_y;

    vec3_t final = { x3, y3, z3 };
    return final;
}

/* Projection Function: Project a 3D point to 2D screen space using perspective projection and camera transform */
screen_vert_t project_vertex(const camera_t *cam, const vec3_t *p_world) {
    screen_vert_t sv;
    
    // Transform the point to camera space
    vec3_t p_cam = apply_camera_transform(cam, p_world);
    
    // Prevent division by zero and handle points behind the camera
    if (p_cam.z <= ZNEAR_CLIP) {
        p_cam.z = ZNEAR_CLIP;
    }

    // Apply perspective projection
    f32_t x_proj = (p_cam.x * F_SCALE) / p_cam.z;
    f32_t y_proj = (p_cam.y * F_SCALE) / p_cam.z;

    // Adjust for aspect ratio correction
    y_proj /= ASPECT_RATIO_CORRECTION;

    // Map normalized device coordinates [-1, 1] to screen coordinates [0, WIDTH] and [0, HEIGHT]
    sv.x = (int)((x_proj + 1.0f) * 0.5f * WIDTH);
    sv.y = (int)((1.0f - (y_proj + 1.0f) * 0.5f) * HEIGHT);
    sv.z = p_cam.z;

    return sv;
}

/* Function to compute barycentric coordinates */
void compute_barycentric(int px, int py, screen_tri_t tri, f32_t *u, f32_t *v, f32_t *w) {
    f32_t denom = (f32_t)((tri.b.y - tri.c.y)*(tri.a.x - tri.c.x) + (tri.c.x - tri.b.x)*(tri.a.y - tri.c.y));
    if (fabsf(denom) < 1e-6f) { // Degenerate triangle
        *u = *v = *w = -1.0f;
        return;
    }
    *u = ((tri.b.y - tri.c.y)*(px - tri.c.x) + (tri.c.x - tri.b.x)*(py - tri.c.y)) / denom;
    *v = ((tri.c.y - tri.a.y)*(px - tri.c.x) + (tri.a.x - tri.c.x)*(py - tri.c.y)) / denom;
    *w = 1.0f - (*u) - (*v);
}

/* Function to rasterize a single triangle */
void rasterize_triangle(const tri_t *tri, const camera_t *cam, col_t fb[HEIGHT][WIDTH], f32_t zb_buffer[HEIGHT][WIDTH], f32_t distance_buffer[HEIGHT][WIDTH]) {
    // Project vertices to screen space
    screen_tri_t st = {
        .a = project_vertex(cam, &tri->a.p),
        .b = project_vertex(cam, &tri->b.p),
        .c = project_vertex(cam, &tri->c.p)
    };

    // Compute bounding box
    i32_t minX = st.a.x < st.b.x ? (st.a.x < st.c.x ? st.a.x : st.c.x) : (st.b.x < st.c.x ? st.b.x : st.c.x);
    i32_t maxX = st.a.x > st.b.x ? (st.a.x > st.c.x ? st.a.x : st.c.x) : (st.b.x > st.c.x ? st.b.x : st.c.x);
    i32_t minY = st.a.y < st.b.y ? (st.a.y < st.c.y ? st.a.y : st.c.y) : (st.b.y < st.c.y ? st.b.y : st.c.y);
    i32_t maxY = st.a.y > st.b.y ? (st.a.y > st.c.y ? st.a.y : st.c.y) : (st.b.y > st.c.y ? st.b.y : st.c.y);

    // Clamp to screen dimensions
    if(minX < 0) minX = 0;
    if(maxX >= WIDTH) maxX = WIDTH -1;
    if(minY < 0) minY = 0;
    if(maxY >= HEIGHT) maxY = HEIGHT -1;

    // Iterate over the bounding box
    for(int y = minY; y <= maxY; y++) {
        for(int x = minX; x <= maxX; x++) {
            f32_t u, v, w;
            compute_barycentric(x + 0.5f, y + 0.5f, st, &u, &v, &w);

            // Check if inside the triangle
            if(u >= 0.0f && v >= 0.0f && w >= 0.0f) {
                // Interpolate depth (z)
                f32_t depth = u * st.a.z + v * st.b.z + w * st.c.z;

                // Z-buffer test
                if(depth < zb_buffer[y][x]) {
                    zb_buffer[y][x] = depth;

                    // Interpolate 3D position in camera space
                    vec3_t pos_a = apply_camera_transform(cam, &tri->a.p);
                    vec3_t pos_b = apply_camera_transform(cam, &tri->b.p);
                    vec3_t pos_c = apply_camera_transform(cam, &tri->c.p);

                    vec3_t pos = {
                        u * pos_a.x + v * pos_b.x + w * pos_c.x,
                        u * pos_a.y + v * pos_b.y + w * pos_c.y,
                        u * pos_a.z + v * pos_b.z + w * pos_c.z
                    };

                    // Compute distance from camera (origin)
                    f32_t distance = sqrtf(pos.x * pos.x + pos.y * pos.y + pos.z * pos.z);
                    distance_buffer[y][x] = distance;

                    // Interpolate color
                    col_t color = {
                        .r = (u * tri->a.c.r) + (v * tri->b.c.r) + (w * tri->c.c.r),
                        .g = (u * tri->a.c.g) + (v * tri->b.c.g) + (w * tri->c.c.g),
                        .b = (u * tri->a.c.b) + (v * tri->b.c.b) + (w * tri->c.c.b),
                    };
                    fb[y][x] = color;
                }
            }
        }
    }
}

/* Rendering Functions */
/* Set the terminal color using ANSI escape codes */
void set_color(col_t c) {
    printf("\x1b[38;2;%d;%d;%dm", c.r, c.g, c.b);
}

/* Move to the next line and reset color */
void next_line() {
    printf("\x1b[0m\n");
}

/* Clear the terminal screen and move the cursor to home position */
void clear_screen(){
    printf("\x1b[2J"); // Clear screen
    printf("\x1b[H");  // Move cursor to home position
}

/* Clear the frame buffer, Z-buffer, and Distance buffer */
void clear_fb(col_t fb[HEIGHT][WIDTH], f32_t zb_buffer[HEIGHT][WIDTH], f32_t distance_buffer[HEIGHT][WIDTH]) {
    for(u32_t i = 0; i < HEIGHT * WIDTH; i++) {
        ((col_t*)fb)[i] = (col_t){0, 0, 0}; // Black background with zero alpha
        ((f32_t*)zb_buffer)[i] = ZFAR_CLIP;    // Initialize Z-buffer to farthest depth
        ((f32_t*)distance_buffer)[i] = ZFAR;   // Initialize Distance buffer to farthest distance
    }
}

/* Render the frame buffer with distance-based shading */
void render_fb_distance(const col_t fb[HEIGHT][WIDTH], const f32_t distance_buffer[HEIGHT][WIDTH]) {
    for(int y = 0; y < HEIGHT; y++) {
        for(int x = 0; x < WIDTH; x++) {
            f32_t distance = distance_buffer[y][x];

            // Normalize distance between ZNEAR and ZFAR
            f32_t normalized = (distance - ZNEAR) / (ZFAR - ZNEAR);

            // Clamp the normalized value between 0 and 1
            if(normalized < 0.0f) normalized = 0.0f;
            if(normalized > 1.0f) normalized = 1.0f;

            // Invert the normalized distance for brightness (closer objects are brighter)
            f32_t brightness = 1.0f - normalized;


            // Get the color from the frame buffer
            col_t color = fb[y][x];
            //color.a = (u8_t)(brightness * 255); // Alpha based on brightness

            color.r *= brightness;
            color.g *= brightness;
            color.b *= brightness;

            // Set the color and print the character
            set_color(color);
            printf("%s", "█");
        }
        next_line();
    }

    // Reset terminal color at the end
    printf("\x1b[0m");
}

/* Main Function */
int main() {
    /* Initialize frame buffer, Z-buffer, and Distance buffer */
    col_t fb[HEIGHT][WIDTH];              // Frame buffer
    f32_t zb_buffer[HEIGHT][WIDTH];       // Z-buffer
    f32_t distance_buffer[HEIGHT][WIDTH]; // Distance buffer

    /* Example Triangles */
    tri_t t1 = {
        .a = { .p = { -1.0f, -1.0f, 2.0f }, .c = { 255, 0, 0 } },   // Red
        .b = { .p = {  1.0f, -1.0f, 2.0f }, .c = { 0, 255, 0 } },   // Green
        .c = { .p = {  0.0f,  1.0f, 2.0f }, .c = { 0, 0, 255 } }    // Blue
    };

    tri_t t2 = {
        .a = { .p = { -0.5f, -0.5f, 2.0f }, .c = { 255, 255, 0 } }, // Yellow
        .b = { .p = {  0.5f, -0.5f, 2.0f }, .c = { 0, 255, 255 } }, // Cyan
        .c = { .p = {  0.0f,  0.5f, 2.0f }, .c = { 255, 0, 255 } }  // Magenta
    };

    /* Initialize Camera */
    camera_t camera = {
        .position = {0.0f, 0.0f, 0.0f},
        .pitch = 0.0f,
        .yaw = 0.0f,
        .roll = 0.0f
    };

    /* Apply Initial Transformations (Optional) */
    // You can apply initial transformations here if desired

    /* Main Rendering Loop */
    while(1) {
        /* Clear the screen and buffers */
        clear_screen();
        clear_fb(fb, zb_buffer, distance_buffer);

        /* Apply Local Transformation: Rotate Triangle t1 around its centroid by 1 degree around Z-axis */
        rotate_triangle_local_deg(&t1, 2.0f, 2.0f, 2.0f); // Rotate 1 degree around Z-axis

        /* Rasterize the triangles */
        rasterize_triangle(&t1, &camera, fb, zb_buffer, distance_buffer);
        rasterize_triangle(&t2, &camera, fb, zb_buffer, distance_buffer);

        //translate_triangle(&t1, (vec3_t){ 0.0f, 0.0f, 0.02f });
        //translate_triangle_local_along_normal(&t1, 0.02f);
        //scale_triangle_local(&t1, (vec3_t){ 1.02f, 1.02f, 1.02f });


        /* Render the frame buffer to the terminal */
        render_fb_distance(fb, distance_buffer);

        /* Control Frame Rate: Sleep for 50,000 microseconds (50 ms) */
        usleep(50000); // Adjust as needed for smoother/faster animation
    }

    return 0;
}
```