Browse Source

added rendering & fixed object import bug

IverMartinson 5 months ago
parent
commit
7ff5edccc0

+ 4 - 2
.vscode/settings.json

@@ -1,7 +1,9 @@
 {
     "files.associations": {
         "functions.h": "c",
-        "sdl.h": "c"
+        "sdl.h": "c",
+        "math.h": "c"
     },
-    "OpenCL.explorer.localizedProperties": false
+    "OpenCL.explorer.localizedProperties": false,
+    "C_Cpp.default.compilerPath": "/bin/gcc"
 }

+ 2 - 2
Makefile

@@ -1,7 +1,7 @@
 COMPILER=gcc
-FLAGS_ALL=-g -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter
+FLAGS_ALL=-fsanitize=address -g -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter
 FLAGS_EXAMPLE=-Lbuild/ -lrasteriver -Wl,-rpath=build/ -lm -lSDL2
-FLAGS_LIB=-D CL_TARGET_OPENCL_VERSION=120 -fPIC -shared -lc -lSDL2 -lSDL2_ttf -lm -lOpenCL
+FLAGS_LIB=-D CL_TARGET_OPENCL_VERSION=120 -fPIC -shared -lc -lSDL2 -lm -lOpenCL
 
 main.bin: rasteriver.so
 	$(COMPILER) $(FLAGS_ALL) src/launch_program/main.c -o build/main.bin $(FLAGS_EXAMPLE) 

BIN
build/librasteriver.so


BIN
build/main.bin


+ 1 - 0
dbg

@@ -0,0 +1 @@
+gdb build/main.bin

+ 29 - 11
src/headers/custom_types.h

@@ -3,12 +3,13 @@
 
 #include "math.h"
 
-// ----- Meshs -----
-
+// ----- Meshes -----
 typedef struct {
-    RI_vector_3f position;
-    RI_vector_3f *normal;
-    RI_vector_2f *uv;
+    RI_vector_3f original_position;
+    RI_vector_3f transformed_position;
+    RI_vector_3f original_normal;
+    RI_vector_3f transformed_normal;
+    RI_vector_2f uv;
 } RI_vertex;
 
 typedef struct {
@@ -20,8 +21,6 @@ typedef struct {
 typedef struct { // A loaded mesh file (NOT an actor; doesn't store transformations or textures, ONLY mesh file data)
     RI_face *faces;
     RI_vertex *vertecies;
-    RI_vector_3f *normals;
-    RI_vector_2f *uvs;
     int face_count;
     int vertex_count;
     int normal_count;
@@ -36,17 +35,36 @@ typedef struct { // A loaded texture file
 
 typedef struct {
     char* filename;
-    RI_vector_2 resolution; // The resolution the texture will be AFTER importing (only if you want to change an image's scale. Setting NULL is equal to providing the image's actual resolution)
+    RI_vector_2 resolution; // The resolution the texture will be AFTER importing (only if you want to change an image's scale. >=0 is equal to providing the image's actual resolution)
 } RI_texture_creation_data;
 
 // ----- Actors -----
-typedef struct { // An entity that has an mesh,
-    RI_mesh *mesh_data;
+typedef struct { 
+    RI_vector_3f position;
+    RI_vector_4f rotation;
+    RI_vector_3f scale;
+} RI_transform;
+
+typedef struct {
+    RI_texture *texture_reference;
+    unsigned char albedo;
+} RI_material;
+
+typedef struct { // An entity that has an mesh, transform, materials, etc
+    RI_mesh *mesh_reference;
+    RI_material *material_reference;
+    RI_transform transform;
 } RI_actor;
 
 typedef struct {
     RI_mesh *mesh_reference;
-    RI_texture *texture_reference;
+    RI_material *material_reference;
 } RI_actor_creation_data;
 
+// ----- Scene -----
+typedef struct {
+    RI_actor **actors;
+    int actor_count;
+} RI_scene;
+
 #endif

+ 3 - 1
src/headers/functions.h

@@ -6,8 +6,10 @@
 RI_mesh* RI_request_meshes(int RI_number_of_requested_objects, char **filenames); // Load object file(s)
 RI_actor* RI_request_actors(int RI_number_of_requested_actors, RI_actor_creation_data *actor_creation_data); // Load texture file(s)
 RI_texture* RI_request_textures(int RI_number_of_requested_textures, RI_texture_creation_data *texture_creation_data); // Create new actor(s)
+RI_scene* RI_request_scene();
 int RI_init(int RI_window_width, int RI_window_height, char *RI_window_title); // Initialize RasterIver
 int RI_stop(int result); // Stop RasterIver safely and free memory
-int RI_tick(); // Tick RasterIver and render a frame
+int RI_render(RI_scene *scene); // Render a scene
+int RI_add_actors_to_scene(int RI_number_of_actors_to_add_to_scene, RI_actor *actors, RI_scene *scene);
 
 #endif

+ 31 - 0
src/headers/math.h

@@ -19,4 +19,35 @@ typedef struct {
     float z; 
 } RI_vector_3f;
 
+typedef struct {
+    float w; 
+    float x; 
+    float y; 
+    float z; 
+} RI_vector_4f;
+
+void vector_3f_times_float(RI_vector_3f *vector, float value){
+    vector->x *= value;
+    vector->y *= value;
+    vector->z *= value;
+}
+
+void vector_3f_hadamard(RI_vector_3f *multiplicand, RI_vector_3f multiplicator){
+    multiplicand->x *= multiplicator.x;
+    multiplicand->y *= multiplicator.y;
+    multiplicand->z *= multiplicator.z;
+}
+
+void vector_3f_element_wise_add(RI_vector_3f *addend_a, RI_vector_3f addend_b){
+    addend_a->x += addend_b.x;
+    addend_a->y += addend_b.y;
+    addend_a->z += addend_b.z;
+}
+
+void vector_3f_divide_float(RI_vector_3f *dividend, float divisor){
+    dividend->x /= divisor;
+    dividend->y /= divisor;
+    dividend->z /= divisor;
+}
+
 #endif

+ 10 - 1
src/headers/rasteriver.h

@@ -9,12 +9,16 @@
 
 typedef struct {
     // rendering (non SDL)
+    uint32_t *frame_buffer;
+    float *z_buffer;
+ 
     int window_width;
     int window_height;
     char *window_title;
 
+    float FOV;
+
     // SDL specific
-    uint32_t *frame_buffer;
     SDL_Window *window;
     SDL_Renderer *renderer;
     SDL_Texture *texture;
@@ -34,6 +38,9 @@ typedef struct {
     RI_texture *loaded_textures;
     RI_actor *actors;
 
+    RI_texture default_texture;
+    RI_material default_material;
+
     // miscellaneous
     int loaded_mesh_count;
     int loaded_texture_count;
@@ -43,4 +50,6 @@ typedef struct {
     char* prefix;
 } RasterIver;
 
+RasterIver* RI_get_ri();
+
 #endif

+ 16 - 3
src/launch_program/main.c

@@ -1,7 +1,7 @@
 #include "../headers/rasteriver.h"
 
 int main(){
-    RI_init(800, 800, "This is RasterIver 2.0!!");
+    RI_init(300, 300, "This is RasterIver 2.0!!");
 
     int running = 1;
 
@@ -11,10 +11,23 @@ int main(){
     RI_texture_creation_data texture_creation_info[2] = {{"textures/bill_mcdinner.png", {0, 0}}, {"textures/test_guy_texture.png", {0, 0}}};
     RI_texture* textures = RI_request_textures(2, texture_creation_info);
 
-    RI_actor_creation_data actor_creation_info[2] = {{&meshes[0], &textures[0]}, {&meshes[1], &textures[1]}};
+    RI_actor_creation_data actor_creation_info[2] = {{&meshes[1], NULL}, {&meshes[1], NULL}};
     RI_actor* actors = RI_request_actors(2, actor_creation_info);
 
+    RI_scene* scene = RI_request_scene();
+
+    RI_add_actors_to_scene(2, actors, scene);
+
+    actors[0].transform.position = (RI_vector_3f){50, 0, 130};
+    actors[0].transform.scale = (RI_vector_3f){50, 50, 50};
+    actors[1].transform.scale = (RI_vector_3f){50, 50, 50};
+
+    RasterIver *ri = RI_get_ri();
+    ri->FOV = 60;
+
     while (running){
-        RI_tick();
+        actors[1].transform.position = (RI_vector_3f){0, 0, sin(ri->frame * 0.1) * 50 + 200};
+        
+        RI_render(scene);
     }
 }

+ 190 - 35
src/library/rasteriver.c

@@ -5,6 +5,7 @@
 #define STB_IMAGE_IMPLEMENTATION
 #include "../headers/stb_image.h"
 #include "stdint.h"
+#include <math.h>
 
 RasterIver ri;
 
@@ -24,7 +25,53 @@ void debug(char *string, ...){
     va_end(args);
 }
 
+RasterIver* RI_get_ri(){
+    return &ri;
+}
+
+int RI_add_actors_to_scene(int RI_number_of_actors_to_add_to_scene, RI_actor *actors, RI_scene *scene){
+    int previous_actor_count = scene->actor_count;
+
+    scene->actor_count += RI_number_of_actors_to_add_to_scene;
+
+    scene->actors = realloc(scene->actors, sizeof(RI_actor *) * scene->actor_count);
+
+    for (int i = 0; i < RI_number_of_actors_to_add_to_scene; ++i){
+        scene->actors[i + previous_actor_count] = &actors[i];
+    }
+
+    return 0;
+}
+
+RI_scene* RI_request_scene(){
+    RI_scene* new_scene = malloc(sizeof(RI_scene));
+
+    new_scene->actor_count = 0;
+    new_scene->actors = NULL;
+    
+    return new_scene;
+}
+
 RI_actor* RI_request_actors(int RI_number_of_requested_actors, RI_actor_creation_data *actor_creation_data){
+    int previous_actor_count = ri.actor_count;
+    ri.actor_count += RI_number_of_requested_actors;
+    
+    ri.actors = realloc(ri.actors, sizeof(RI_actor) * ri.actor_count);
+
+    for (int i = 0; i < RI_number_of_requested_actors; ++i){
+        RI_actor new_actor = {0};
+
+        new_actor.mesh_reference = actor_creation_data[i].mesh_reference;
+        
+        if (actor_creation_data->material_reference){
+            new_actor.material_reference = actor_creation_data[i].material_reference;
+        }
+        else {
+            new_actor.material_reference = &ri.default_material;
+        }
+
+        ri.actors[i + previous_actor_count] = new_actor;
+    }
 
     return ri.actors;
 }
@@ -35,10 +82,10 @@ RI_texture* RI_request_textures(int RI_number_of_requested_textures, RI_texture_
     ri.loaded_texture_count += RI_number_of_requested_textures;
 
     ri.loaded_textures = realloc(ri.loaded_textures, sizeof(RI_texture) * ri.loaded_texture_count);
-
-    RI_texture new_texture;
-
+    
     for (int i = 0; i < RI_number_of_requested_textures; i++){
+        RI_texture new_texture = {0};
+        
         char *current_texture_filename = texture_creation_data[i].filename;
 
         unsigned char* temp_texture = stbi_load(current_texture_filename, &new_texture.resolution.x, &new_texture.resolution.y, NULL, 4);
@@ -76,13 +123,8 @@ RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
     ri.loaded_meshes = realloc(ri.loaded_meshes, sizeof(RI_mesh) * ri.loaded_mesh_count);
 
     for (int i = 0; i < RI_number_of_requested_meshes; i++){
-        RI_mesh new_mesh_data_struct;
+        RI_mesh new_mesh_data_struct = {0};
 
-        new_mesh_data_struct.face_count = 0;
-        new_mesh_data_struct.vertex_count = 0;
-        new_mesh_data_struct.normal_count = 0;
-        new_mesh_data_struct.uv_count = 0;
-        
         FILE *file = fopen(filenames[i], "r");
 
         if (!file){
@@ -90,7 +132,7 @@ RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
             RI_stop(1);
         }
         
-        char line[256];
+        char line[512];
         
         while (fgets(line, sizeof(line), file)) {
             if (line[0] == 'f' && line[1] == ' ') { // face
@@ -111,11 +153,12 @@ RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
         
         new_mesh_data_struct.faces = malloc(sizeof(RI_face) * new_mesh_data_struct.face_count);
         new_mesh_data_struct.vertecies = malloc(sizeof(RI_vertex) * new_mesh_data_struct.vertex_count);
-        new_mesh_data_struct.normals = malloc(sizeof(RI_vector_3f) * new_mesh_data_struct.normal_count);
-        new_mesh_data_struct.uvs = malloc(sizeof(RI_vector_2f) * new_mesh_data_struct.uv_count);
 
-        file = fopen(filenames[i], "r");
-        
+        RI_vector_3f *normals = malloc(sizeof(RI_vector_3f) * new_mesh_data_struct.normal_count);
+        RI_vector_2f *uvs = malloc(sizeof(RI_vector_2f) * new_mesh_data_struct.uv_count);
+
+        FILE *file_again = fopen(filenames[i], "r");
+
         int current_face_index = 0;
         int current_vertex_index = 0;
         int current_normal_index = 0;
@@ -124,7 +167,7 @@ RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
         int has_normals, has_uvs;
         has_normals = has_uvs = 0;
 
-        while (fgets(line, sizeof(line), file)) {
+        while (fgets(line, sizeof(line), file_again)) {
             if (line[0] == 'f' && line[1] == ' ') {
                 int vertex_0_index, vertex_1_index, vertex_2_index, normal_0_index, normal_1_index, normal_2_index, uv_0_index, uv_1_index, uv_2_index;
 
@@ -159,8 +202,6 @@ RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
                             &vertex_0_index, 
                             &vertex_1_index, 
                             &vertex_2_index);
-                        
-                        has_uvs = 1;
                     }
                 }
                 else {
@@ -170,7 +211,15 @@ RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
                 new_mesh_data_struct.faces[current_face_index].vertex_0 = &new_mesh_data_struct.vertecies[vertex_0_index - 1];
                 new_mesh_data_struct.faces[current_face_index].vertex_1 = &new_mesh_data_struct.vertecies[vertex_1_index - 1];
                 new_mesh_data_struct.faces[current_face_index].vertex_2 = &new_mesh_data_struct.vertecies[vertex_2_index - 1];
-            
+
+                new_mesh_data_struct.faces[current_face_index].vertex_0->original_normal = normals[normal_0_index - 1];
+                new_mesh_data_struct.faces[current_face_index].vertex_1->original_normal = normals[normal_1_index - 1];
+                new_mesh_data_struct.faces[current_face_index].vertex_2->original_normal = normals[normal_2_index - 1];
+
+                new_mesh_data_struct.faces[current_face_index].vertex_0->uv = uvs[uv_0_index - 1];
+                new_mesh_data_struct.faces[current_face_index].vertex_1->uv = uvs[uv_1_index - 1];
+                new_mesh_data_struct.faces[current_face_index].vertex_2->uv = uvs[uv_2_index - 1];
+
                 ++current_face_index;
             }
             else if (line[0] == 'v' && line[1] == ' ') {
@@ -178,9 +227,9 @@ RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
                 
                 sscanf(line, "v %f %f %f", &x, &y, &z);
 
-                new_mesh_data_struct.vertecies[current_vertex_index].position.x = x;
-                new_mesh_data_struct.vertecies[current_vertex_index].position.y = y;
-                new_mesh_data_struct.vertecies[current_vertex_index].position.z = z;
+                new_mesh_data_struct.vertecies[current_vertex_index].original_position.x = x;
+                new_mesh_data_struct.vertecies[current_vertex_index].original_position.y = y;
+                new_mesh_data_struct.vertecies[current_vertex_index].original_position.z = z;
 
                 ++current_vertex_index;
             } 
@@ -189,10 +238,10 @@ RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
                 
                 sscanf(line, "vn %f %f %f", &x, &y, &z);
 
-                new_mesh_data_struct.normals[current_vertex_index].x = x;
-                new_mesh_data_struct.normals[current_vertex_index].y = y;
-                new_mesh_data_struct.normals[current_vertex_index].z = z;
-             
+                normals[current_normal_index].x = x;
+                normals[current_normal_index].y = y;
+                normals[current_normal_index].z = z;
+
                 ++current_normal_index;
             }
             else if (line[0] == 'v' && line[1] == 't') {
@@ -200,14 +249,17 @@ RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
 
                 sscanf(line, "vt %f %f %f", &x, &y, &z);
 
-                new_mesh_data_struct.normals[current_vertex_index].x = x;
-                new_mesh_data_struct.normals[current_vertex_index].y = y;
-                // UVS are almost always 2D so we don't need this (the type itself is a vector 2f) -> new_mesh_data_struct.normals[current_vertex_index].z = z; 
-              
+                uvs[current_uv_index].x = x;
+                uvs[current_uv_index].y = y;
+                // UVS are almost always 2D so we don't need Z this (the type itself is a vector 2f, not 3f) 
+
                 ++current_uv_index;
             } 
         }
 
+        free(normals);
+        free(uvs);
+
         char* loading_mesh_notice_string;
 
         if (has_normals && !has_uvs) loading_mesh_notice_string = "normals";
@@ -216,19 +268,108 @@ RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
         
         if (!has_normals || !has_uvs) debug("Notice! Mesh \"%s\" is missing %s", filenames[i], loading_mesh_notice_string);
         
-        fclose(file);
+        // fclose(file_again);
+
+        ri.loaded_meshes[meshes_already_loaded_count + i] = new_mesh_data_struct;   
 
-        ri.loaded_meshes[meshes_already_loaded_count + i] = new_mesh_data_struct;    
+        debug("Loaded mesh \"%s\"! %d faces, %d verticies, %d normals, %d uvs", filenames[i], current_face_index, current_vertex_index, current_normal_index, current_uv_index); 
     }
 
     return ri.loaded_meshes;
 }
 
-int RI_tick(){
+void quaternion_rotation(RI_vector_3f *position, RI_vector_4f rotation){
+    return;
+}
+
+void color_pixel(int x, int y, uint32_t color){
+    ri.frame_buffer[(x + ri.window_height / 2) * ri.window_width + (y + ri.window_width / 2)] = color;
+}
+
+int RI_render(RI_scene *scene){
     // do rendering stuff
     if (ri.running){
-        for (int i = 0; i < ri.window_width; ++i){
-            ri.frame_buffer[(ri.frame % ri.window_height) * ri.window_width + i] = 0x0 + ri.frame + i * ri.frame;
+        float horizontal_fov_factor = ri.window_width / tanf(0.5 * ri.FOV);
+        float vertical_fov_factor = ri.window_height / tanf(0.5 * ri.FOV);
+
+        for (int actor_index = 0; actor_index < scene->actor_count; ++actor_index){
+            RI_actor *current_actor = scene->actors[actor_index];
+
+            for (int polygon_index = 0; polygon_index < current_actor->mesh_reference->face_count; ++polygon_index){
+                current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position = current_actor->mesh_reference->faces[polygon_index].vertex_0->original_position;
+                current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position = current_actor->mesh_reference->faces[polygon_index].vertex_1->original_position;
+                current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position = current_actor->mesh_reference->faces[polygon_index].vertex_2->original_position;
+
+                quaternion_rotation(&current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position, current_actor->transform.rotation);
+                quaternion_rotation(&current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position, current_actor->transform.rotation);
+                quaternion_rotation(&current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position, current_actor->transform.rotation);
+
+                vector_3f_hadamard(&current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position, current_actor->transform.scale);
+                vector_3f_hadamard(&current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position, current_actor->transform.scale);
+                vector_3f_hadamard(&current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position, current_actor->transform.scale);
+            
+                vector_3f_element_wise_add(&current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position, current_actor->transform.position);
+                vector_3f_element_wise_add(&current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position, current_actor->transform.position);
+                vector_3f_element_wise_add(&current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position, current_actor->transform.position);
+            
+                current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position.x = current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position.x / current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position.z * horizontal_fov_factor;
+                current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position.y = current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position.y / current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position.z * vertical_fov_factor;
+                
+                current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position.x = current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position.x / current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position.z * horizontal_fov_factor;
+                current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position.y = current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position.y / current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position.z * vertical_fov_factor;
+
+                current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position.x = current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position.x / current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position.z * horizontal_fov_factor;
+                current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position.y = current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position.y / current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position.z * vertical_fov_factor;
+            }
+        }
+
+        for (int pixel_index = 0; pixel_index < ri.window_width * ri.window_height; ++pixel_index){
+            ri.frame_buffer[pixel_index] = 0x0;
+            ri.z_buffer[pixel_index] = 99999;
+        }
+
+        for (int pixel_y_index = -ri.window_height / 2; pixel_y_index < ri.window_height / 2; ++pixel_y_index){
+            for (int pixel_x_index = -ri.window_width / 2; pixel_x_index < ri.window_height / 2; ++pixel_x_index){
+                for (int actor_index = 0; actor_index < scene->actor_count; ++actor_index){
+                    RI_actor *current_actor = scene->actors[actor_index];
+
+                    for (int polygon_index = 0; polygon_index < current_actor->mesh_reference->face_count; ++polygon_index){
+                        RI_vector_3f *pos_0 = &current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position;
+                        RI_vector_3f *pos_1 = &current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position;
+                        RI_vector_3f *pos_2 = &current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position;
+                        
+                        int vertex_0_out_of_bounds = pos_0->x < 0 || pos_0->x >= ri.window_width || pos_0->y < 0 || pos_0->y >= ri.window_height;
+                        int vertex_1_out_of_bounds = pos_1->x < 0 || pos_1->x >= ri.window_width || pos_1->y < 0 || pos_1->y >= ri.window_height;
+                        int vertex_2_out_of_bounds = pos_2->x < 0 || pos_2->x >= ri.window_width || pos_2->y < 0 || pos_2->y >= ri.window_height;
+                        
+                        if (vertex_0_out_of_bounds && vertex_1_out_of_bounds && vertex_2_out_of_bounds){
+                            // continue;
+                        }
+                        
+                        float denominator, w0, w1, w2;
+
+                        denominator = (pos_1->y - pos_2->y) * (pos_0->x - pos_2->x) + (pos_2->x - pos_1->x) * (pos_0->y - pos_2->y);
+                        w0 = ((pos_1->y - pos_2->y) * (pixel_x_index - pos_2->x) + (pos_2->x - pos_1->x) * (pixel_y_index - pos_2->y)) / denominator;
+                        w1 = ((pos_2->y - pos_0->y) * (pixel_x_index - pos_0->x) + (pos_0->x - pos_2->x) * (pixel_y_index - pos_0->y)) / denominator; 
+                        w2 = 1.0 - w0 - w1; 
+
+                        float w_over_z = (w0 / pos_0->z + w1 / pos_1->z + w2 / pos_2->z); 
+                        float interpolated_z = 1.0 / w_over_z;
+
+                        if (!(w0 >= 0 && w1 >= 0 && w2 >= 0)){
+                            continue;
+                        }
+                        
+                        if (interpolated_z >= ri.z_buffer[(pixel_x_index + ri.window_height / 2) * ri.window_width + (pixel_y_index + ri.window_width / 2)]){
+                            continue;
+                        }   
+
+                        ri.z_buffer[(pixel_x_index + ri.window_height / 2) * ri.window_width + (pixel_y_index + ri.window_width / 2)] = interpolated_z;
+                        
+                        color_pixel(pixel_y_index, pixel_x_index, 0x01010101 * polygon_index);
+                    }
+                }
+            }
         }
 
         SDL_UpdateTexture(ri.texture, NULL, ri.frame_buffer, ri.window_width * sizeof(uint32_t));
@@ -265,6 +406,7 @@ int sdl_init(int RI_window_width, int RI_window_height, char *RI_window_title){
     ri.window_title = RI_window_title;
 
     ri.frame_buffer = malloc(sizeof(uint32_t) * ri.window_width * ri.window_height);
+    ri.z_buffer = malloc(sizeof(float) * ri.window_width * ri.window_height);
 
     SDL_Init(SDL_INIT_VIDEO);
 
@@ -284,7 +426,11 @@ int RI_init(int RI_window_width, int RI_window_height, char *RI_window_title){
 
     sdl_init(RI_window_width, RI_window_height, RI_window_title);
 
-    ri.prefix = "[RasterIver]";
+    ri.loaded_mesh_count = 0;
+    ri.loaded_texture_count = 0;
+    ri.actor_count = 0;
+
+    ri.prefix = "[RasterIver] ";
 
     return 0;
 }
@@ -292,6 +438,15 @@ int RI_init(int RI_window_width, int RI_window_height, char *RI_window_title){
 int RI_stop(int result){
     debug("Stopping...");
     
+    for (int mesh_index = 0; mesh_index < ri.loaded_mesh_count; ++mesh_index){
+        free(ri.loaded_meshes[mesh_index].faces); // free face array
+        free(ri.loaded_meshes[mesh_index].vertecies); // free vertex array
+    }
+
+    for (int texture_index = 0; texture_index < ri.loaded_texture_count; ++texture_index){
+        free(ri.loaded_textures[texture_index].image_buffer);
+    }
+
     exit(result);
 
     return 0;