Browse Source

added quaternion rotation, new example scene, fixed shared meshes also sharing transformations

IverMartinson 5 months ago
parent
commit
2238db889c

BIN
build/librasteriver.so


BIN
build/main.bin


+ 0 - 0
objects/cube.obj → objects/unit_cube.obj


+ 270 - 0
objects/unit_ico_sphere.obj

@@ -0,0 +1,270 @@
+# Blender 4.4.3
+# www.blender.org
+mtllib unit_ico_sphere.mtl
+o Icosphere
+v 0.000000 -1.000000 0.000000
+v 0.723607 -0.447220 0.525725
+v -0.276388 -0.447220 0.850649
+v -0.894426 -0.447216 0.000000
+v -0.276388 -0.447220 -0.850649
+v 0.723607 -0.447220 -0.525725
+v 0.276388 0.447220 0.850649
+v -0.723607 0.447220 0.525725
+v -0.723607 0.447220 -0.525725
+v 0.276388 0.447220 -0.850649
+v 0.894426 0.447216 0.000000
+v 0.000000 1.000000 0.000000
+v -0.162456 -0.850654 0.499995
+v 0.425323 -0.850654 0.309011
+v 0.262869 -0.525738 0.809012
+v 0.850648 -0.525736 0.000000
+v 0.425323 -0.850654 -0.309011
+v -0.525730 -0.850652 0.000000
+v -0.688189 -0.525736 0.499997
+v -0.162456 -0.850654 -0.499995
+v -0.688189 -0.525736 -0.499997
+v 0.262869 -0.525738 -0.809012
+v 0.951058 0.000000 0.309013
+v 0.951058 0.000000 -0.309013
+v 0.000000 0.000000 1.000000
+v 0.587786 0.000000 0.809017
+v -0.951058 0.000000 0.309013
+v -0.587786 0.000000 0.809017
+v -0.587786 0.000000 -0.809017
+v -0.951058 0.000000 -0.309013
+v 0.587786 0.000000 -0.809017
+v 0.000000 0.000000 -1.000000
+v 0.688189 0.525736 0.499997
+v -0.262869 0.525738 0.809012
+v -0.850648 0.525736 0.000000
+v -0.262869 0.525738 -0.809012
+v 0.688189 0.525736 -0.499997
+v 0.162456 0.850654 0.499995
+v 0.525730 0.850652 0.000000
+v -0.425323 0.850654 0.309011
+v -0.425323 0.850654 -0.309011
+v 0.162456 0.850654 -0.499995
+vn 0.1024 -0.9435 0.3151
+vn 0.7002 -0.6617 0.2680
+vn -0.2680 -0.9435 0.1947
+vn -0.2680 -0.9435 -0.1947
+vn 0.1024 -0.9435 -0.3151
+vn 0.9050 -0.3304 0.2680
+vn 0.0247 -0.3304 0.9435
+vn -0.8897 -0.3304 0.3151
+vn -0.5746 -0.3304 -0.7488
+vn 0.5346 -0.3304 -0.7779
+vn 0.8026 -0.1256 0.5831
+vn -0.3066 -0.1256 0.9435
+vn -0.9921 -0.1256 -0.0000
+vn -0.3066 -0.1256 -0.9435
+vn 0.8026 -0.1256 -0.5831
+vn 0.4089 0.6617 0.6284
+vn -0.4713 0.6617 0.5831
+vn -0.7002 0.6617 -0.2680
+vn 0.0385 0.6617 -0.7488
+vn 0.7240 0.6617 -0.1947
+vn 0.2680 0.9435 -0.1947
+vn 0.4911 0.7947 -0.3568
+vn 0.4089 0.6617 -0.6284
+vn -0.1024 0.9435 -0.3151
+vn -0.1876 0.7947 -0.5773
+vn -0.4713 0.6617 -0.5831
+vn -0.3313 0.9435 -0.0000
+vn -0.6071 0.7947 -0.0000
+vn -0.7002 0.6617 0.2680
+vn -0.1024 0.9435 0.3151
+vn -0.1876 0.7947 0.5773
+vn 0.0385 0.6617 0.7488
+vn 0.2680 0.9435 0.1947
+vn 0.4911 0.7947 0.3568
+vn 0.7240 0.6617 0.1947
+vn 0.8897 0.3304 -0.3151
+vn 0.7947 0.1876 -0.5773
+vn 0.5746 0.3304 -0.7488
+vn -0.0247 0.3304 -0.9435
+vn -0.3035 0.1876 -0.9342
+vn -0.5346 0.3304 -0.7779
+vn -0.9050 0.3304 -0.2680
+vn -0.9822 0.1876 -0.0000
+vn -0.9050 0.3304 0.2680
+vn -0.5346 0.3304 0.7779
+vn -0.3035 0.1876 0.9342
+vn -0.0247 0.3304 0.9435
+vn 0.5746 0.3304 0.7488
+vn 0.7947 0.1876 0.5773
+vn 0.8897 0.3304 0.3151
+vn 0.3066 0.1256 -0.9435
+vn 0.3035 -0.1876 -0.9342
+vn 0.0247 -0.3304 -0.9435
+vn -0.8026 0.1256 -0.5831
+vn -0.7947 -0.1876 -0.5773
+vn -0.8897 -0.3304 -0.3151
+vn -0.8026 0.1256 0.5831
+vn -0.7947 -0.1876 0.5773
+vn -0.5746 -0.3304 0.7488
+vn 0.3066 0.1256 0.9435
+vn 0.3035 -0.1876 0.9342
+vn 0.5346 -0.3304 0.7779
+vn 0.9921 0.1256 -0.0000
+vn 0.9822 -0.1876 -0.0000
+vn 0.9050 -0.3304 -0.2680
+vn 0.4713 -0.6617 -0.5831
+vn 0.1876 -0.7947 -0.5773
+vn -0.0385 -0.6617 -0.7488
+vn -0.4089 -0.6617 -0.6284
+vn -0.4911 -0.7947 -0.3568
+vn -0.7240 -0.6617 -0.1947
+vn -0.7240 -0.6617 0.1947
+vn -0.4911 -0.7947 0.3568
+vn -0.4089 -0.6617 0.6284
+vn 0.7002 -0.6617 -0.2680
+vn 0.6071 -0.7947 -0.0000
+vn 0.3313 -0.9435 -0.0000
+vn -0.0385 -0.6617 0.7488
+vn 0.1876 -0.7947 0.5773
+vn 0.4713 -0.6617 0.5831
+vt 0.181819 0.000000
+vt 0.227273 0.078731
+vt 0.136365 0.078731
+vt 0.272728 0.157461
+vt 0.318182 0.078731
+vt 0.363637 0.157461
+vt 0.909091 0.000000
+vt 0.954545 0.078731
+vt 0.863636 0.078731
+vt 0.727273 0.000000
+vt 0.772727 0.078731
+vt 0.681818 0.078731
+vt 0.545455 0.000000
+vt 0.590909 0.078731
+vt 0.500000 0.078731
+vt 0.318182 0.236191
+vt 0.090910 0.157461
+vt 0.181819 0.157461
+vt 0.136365 0.236191
+vt 0.818182 0.157461
+vt 0.909091 0.157461
+vt 0.863636 0.236191
+vt 0.636364 0.157461
+vt 0.727273 0.157461
+vt 0.681818 0.236191
+vt 0.454546 0.157461
+vt 0.545455 0.157461
+vt 0.500000 0.236191
+vt 0.227273 0.236191
+vt 0.045455 0.236191
+vt 0.772727 0.236191
+vt 0.590909 0.236191
+vt 0.409092 0.236191
+vt 0.181819 0.314921
+vt 0.272728 0.314921
+vt 0.227273 0.393651
+vt 0.000000 0.314921
+vt 0.090910 0.314921
+vt 0.045455 0.393651
+vt 0.727273 0.314921
+vt 0.818182 0.314921
+vt 0.772727 0.393651
+vt 0.545455 0.314921
+vt 0.636364 0.314921
+vt 0.590909 0.393651
+vt 0.363637 0.314921
+vt 0.454546 0.314921
+vt 0.409092 0.393651
+vt 0.500000 0.393651
+vt 0.454546 0.472382
+vt 0.681818 0.393651
+vt 0.636364 0.472382
+vt 0.863636 0.393651
+vt 0.818182 0.472382
+vt 0.909091 0.314921
+vt 0.136365 0.393651
+vt 0.090910 0.472382
+vt 0.318182 0.393651
+vt 0.272728 0.472382
+vt 0.954545 0.236191
+vt 1.000000 0.157461
+vt 0.409092 0.078731
+vt 0.363637 0.000000
+s 0
+f 1/1/1 14/2/1 13/3/1
+f 2/4/2 14/5/2 16/6/2
+f 1/7/3 13/8/3 18/9/3
+f 1/10/4 18/11/4 20/12/4
+f 1/13/5 20/14/5 17/15/5
+f 2/4/6 16/6/6 23/16/6
+f 3/17/7 15/18/7 25/19/7
+f 4/20/8 19/21/8 27/22/8
+f 5/23/9 21/24/9 29/25/9
+f 6/26/10 22/27/10 31/28/10
+f 2/4/11 23/16/11 26/29/11
+f 3/17/12 25/19/12 28/30/12
+f 4/20/13 27/22/13 30/31/13
+f 5/23/14 29/25/14 32/32/14
+f 6/26/15 31/28/15 24/33/15
+f 7/34/16 33/35/16 38/36/16
+f 8/37/17 34/38/17 40/39/17
+f 9/40/18 35/41/18 41/42/18
+f 10/43/19 36/44/19 42/45/19
+f 11/46/20 37/47/20 39/48/20
+f 39/48/21 42/49/21 12/50/21
+f 39/48/22 37/47/22 42/49/22
+f 37/47/23 10/43/23 42/49/23
+f 42/45/24 41/51/24 12/52/24
+f 42/45/25 36/44/25 41/51/25
+f 36/44/26 9/40/26 41/51/26
+f 41/42/27 40/53/27 12/54/27
+f 41/42/28 35/41/28 40/53/28
+f 35/41/29 8/55/29 40/53/29
+f 40/39/30 38/56/30 12/57/30
+f 40/39/31 34/38/31 38/56/31
+f 34/38/32 7/34/32 38/56/32
+f 38/36/33 39/58/33 12/59/33
+f 38/36/34 33/35/34 39/58/34
+f 33/35/35 11/46/35 39/58/35
+f 24/33/36 37/47/36 11/46/36
+f 24/33/37 31/28/37 37/47/37
+f 31/28/38 10/43/38 37/47/38
+f 32/32/39 36/44/39 10/43/39
+f 32/32/40 29/25/40 36/44/40
+f 29/25/41 9/40/41 36/44/41
+f 30/31/42 35/41/42 9/40/42
+f 30/31/43 27/22/43 35/41/43
+f 27/22/44 8/55/44 35/41/44
+f 28/30/45 34/38/45 8/37/45
+f 28/30/46 25/19/46 34/38/46
+f 25/19/47 7/34/47 34/38/47
+f 26/29/48 33/35/48 7/34/48
+f 26/29/49 23/16/49 33/35/49
+f 23/16/50 11/46/50 33/35/50
+f 31/28/51 32/32/51 10/43/51
+f 31/28/52 22/27/52 32/32/52
+f 22/27/53 5/23/53 32/32/53
+f 29/25/54 30/31/54 9/40/54
+f 29/25/55 21/24/55 30/31/55
+f 21/24/56 4/20/56 30/31/56
+f 27/22/57 28/60/57 8/55/57
+f 27/22/58 19/21/58 28/60/58
+f 19/21/59 3/61/59 28/60/59
+f 25/19/60 26/29/60 7/34/60
+f 25/19/61 15/18/61 26/29/61
+f 15/18/62 2/4/62 26/29/62
+f 23/16/63 24/33/63 11/46/63
+f 23/16/64 16/6/64 24/33/64
+f 16/6/65 6/26/65 24/33/65
+f 17/15/66 22/27/66 6/26/66
+f 17/15/67 20/14/67 22/27/67
+f 20/14/68 5/23/68 22/27/68
+f 20/12/69 21/24/69 5/23/69
+f 20/12/70 18/11/70 21/24/70
+f 18/11/71 4/20/71 21/24/71
+f 18/9/72 19/21/72 4/20/72
+f 18/9/73 13/8/73 19/21/73
+f 13/8/74 3/61/74 19/21/74
+f 16/6/75 17/62/75 6/26/75
+f 16/6/76 14/5/76 17/62/76
+f 14/5/77 1/63/77 17/62/77
+f 13/3/78 15/18/78 3/17/78
+f 13/3/79 14/2/79 15/18/79
+f 14/2/80 2/4/80 15/18/80

+ 16 - 0
objects/unit_plane.obj

@@ -0,0 +1,16 @@
+# Blender 4.4.3
+# www.blender.org
+mtllib unit_plane.mtl
+o Plane
+v -1.000000 0.000000 1.000000
+v 1.000000 0.000000 1.000000
+v -1.000000 0.000000 -1.000000
+v 1.000000 0.000000 -1.000000
+vn -0.0000 1.0000 -0.0000
+vt 1.000000 0.000000
+vt 0.000000 1.000000
+vt 0.000000 0.000000
+vt 1.000000 1.000000
+s 0
+f 2/1/1 3/2/1 1/3/1
+f 2/1/1 4/4/1 3/2/1

+ 8 - 7
src/headers/custom_types.h

@@ -5,17 +5,15 @@
 
 // ----- Meshes -----
 typedef struct {
-    RI_vector_3f original_position;
-    RI_vector_3f transformed_position;
-    RI_vector_3f original_normal;
-    RI_vector_3f transformed_normal;
+    RI_vector_3f position;
+    RI_vector_3f normal;
     RI_vector_2f uv;
 } RI_vertex;
 
 typedef struct {
-    RI_vertex *vertex_0;
-    RI_vertex *vertex_1;
-    RI_vertex *vertex_2;
+    int vertex_0_index;
+    int vertex_1_index;
+    int vertex_2_index;
 } RI_face;
 
 typedef struct { // A loaded mesh file (NOT an actor; doesn't store transformations or textures, ONLY mesh file data)
@@ -71,6 +69,7 @@ typedef struct {
 typedef struct { // An entity that has an mesh, transform, materials, etc
     RI_mesh *mesh_reference;
     RI_material *material_reference;
+    RI_vertex *transformed_verticies;
     RI_transform transform;
 } RI_actor;
 
@@ -83,6 +82,8 @@ typedef struct {
 typedef struct {
     RI_actor **actors;
     int actor_count;
+    RI_vector_3f camera_position;
+    RI_vector_4f camera_rotation;
 } RI_scene;
 
 #endif

+ 2 - 2
src/headers/functions.h

@@ -3,8 +3,8 @@
 
 #include "custom_types.h"
 
-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_mesh* RI_request_meshes(int RI_number_of_requested_objects, char **filenames, int RI_request_just_mesh); // Load object file(s)
+RI_actor* RI_request_actors(int RI_number_of_requested_actors); // Load texture file(s)
 RI_material* RI_request_materials(int RI_number_of_requested_materials); // Create materials
 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();

+ 24 - 0
src/headers/math.h

@@ -44,10 +44,34 @@ void vector_3f_element_wise_add(RI_vector_3f *addend_a, RI_vector_3f addend_b){
     addend_a->z += addend_b.z;
 }
 
+void vector_3f_element_wise_subtract(RI_vector_3f *minuend, RI_vector_3f subtrahend){
+    minuend->x -= subtrahend.x;
+    minuend->y -= subtrahend.y;
+    minuend->z -= subtrahend.z;
+}
+
 void vector_3f_divide_float(RI_vector_3f *dividend, float divisor){
     dividend->x /= divisor;
     dividend->y /= divisor;
     dividend->z /= divisor;
 }
 
+void quaternion_conjugate(RI_vector_4f* quaternion){
+    quaternion->x *= -1;
+    quaternion->y *= -1;
+    quaternion->z *= -1;
+}
+
+void quaternion_multiply(RI_vector_4f* a, RI_vector_4f b){
+    float w1 = a->w; float x1 = a->x; float y1 = a->y; float z1 = a->z;
+    float w2 = b.w; float x2 = b.x; float y2 = b.y; float z2 = b.z;
+
+    float w = w1*w2 - x1*x2 - y1*y2 - z1*z2;
+    float x = w1*x2 + x1*w2 + y1*z2 - z1*y2;
+    float y = w1*y2 - x1*z2 + y1*w2 + z1*x2;
+    float z = w1*z2 + x1*y2 - y1*x2 + z1*w2;
+
+    *a = (RI_vector_4f){w, x, y, z};
+}
+
 #endif

+ 1 - 0
src/headers/rasteriver.h

@@ -43,6 +43,7 @@ typedef struct {
     RI_texture error_bump_map;
     RI_texture error_normal_map;
     RI_material error_material;
+    RI_mesh error_mesh;
 
     // miscellaneous
     int loaded_mesh_count;

+ 63 - 19
src/launch_program/main.c

@@ -1,42 +1,86 @@
 #include "../headers/rasteriver.h"
 
 int main(){
-    RI_init(300, 300, "This is RasterIver 2.0!!");
+    RI_init(400, 400, "This is RasterIver 2.0!!");
 
     int running = 1;
 
-    char *filenames[] = {"objects/cube.obj", "objects/test_guy.obj"};
-    RI_mesh* meshes = RI_request_meshes(2, filenames);
+    // get RasterIver context
+    RasterIver *ri = RI_get_ri();
 
+    // data for loading files
+    char *filenames[] = {"objects/unit_cube.obj", "objects/test_guy.obj", "objects/unit_plane.obj"};
     RI_texture_creation_data texture_creation_info[2] = {{"textures/bill_mcdinner.png", {0, 0}}, {"textures/test_guy_texture.png", {0, 0}}};
+    
+    // requesting assets
+    RI_mesh* meshes = RI_request_meshes(3, filenames, 0);
     RI_texture* textures = RI_request_textures(2, texture_creation_info);
+    RI_material* materials = RI_request_materials(4);
+    RI_actor* actors = RI_request_actors(4);
+    RI_scene* scene = RI_request_scene();
 
-    RI_material* materials = RI_request_materials(2);
+    // meshes
+    RI_mesh* unit_plane_mesh = &meshes[2];
+    RI_mesh* unit_cube_mesh = &meshes[0];
 
-    materials[0].flags = RI_MATERIAL_HAS_TEXTURE;
-    materials[0].texture_reference = &textures[0];
-    materials[1].flags = RI_MATERIAL_HAS_TEXTURE;
-    materials[1].texture_reference = &textures[1];
+    // textures
+    RI_texture* bill_cube_texture = &textures[0];
 
-    RI_actor_creation_data actor_creation_info[2] = {{&meshes[0], &materials[0]}, {&meshes[1], &materials[1]}};
-    RI_actor* actors = RI_request_actors(2, actor_creation_info);
+    // materials
+    RI_material* floor_material = &materials[0];
+    floor_material->flags = 0;
+    floor_material->albedo = 0xFF77FF77;
+    
+    RI_material* wall_material = &materials[1];
+    wall_material->flags = 0;
+    wall_material->albedo = 0xFF7777FF;
 
-    RI_scene* scene = RI_request_scene();
+    RI_material* bill_cube_material = &materials[2];
+    bill_cube_material->flags = RI_MATERIAL_HAS_TEXTURE;
+    bill_cube_material->texture_reference = bill_cube_texture;
 
-    RI_add_actors_to_scene(2, actors, scene);
+    RI_material* screen_material = &materials[3];
+    screen_material->flags = RI_MATERIAL_HAS_TEXTURE;
+    screen_material->texture_reference = ri->frame_buffer;
 
-    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};
+    // actors
+    RI_actor* floor = &actors[0];
+    floor->material_reference = floor_material;
+    floor->mesh_reference = unit_plane_mesh;
+    floor->transform.scale = (RI_vector_3f){100, 100, 100};
+    floor->transform.position = (RI_vector_3f){0, -100, 200};
+    floor->transform.rotation = (RI_vector_4f){0, 1, 0, 0};
 
-    RasterIver *ri = RI_get_ri();
-    ri->FOV = 60;
+    RI_actor* wall = &actors[1];
+    wall->material_reference = wall_material;
+    wall->mesh_reference = unit_plane_mesh;
+    wall->transform.scale = (RI_vector_3f){100, 100, 100};
+    wall->transform.position = (RI_vector_3f){0, 0, 300};
+    wall->transform.rotation = (RI_vector_4f){0.70710678, 0.70710678, 0, 0};
 
-    materials[0].texture_reference = ri->frame_buffer;
+    RI_actor* bill_cube = &actors[2];
+    bill_cube->material_reference = bill_cube_material;
+    bill_cube->mesh_reference = unit_cube_mesh;
+    bill_cube->transform.scale = (RI_vector_3f){50, 50, 50};
+    bill_cube->transform.position = (RI_vector_3f){-50, 100, 100};
+    bill_cube->transform.rotation = (RI_vector_4f){0, 1, 0, 0};
+
+    RI_actor* screen = &actors[3];
+    screen->material_reference = screen_material;
+    screen->mesh_reference = unit_plane_mesh;
+    screen->transform.scale = (RI_vector_3f){50, 50, 50};
+    screen->transform.position = (RI_vector_3f){0, 0, 250};
+    screen->transform.rotation = (RI_vector_4f){0.70710678, 0.70710678};
+
+    RI_add_actors_to_scene(4, actors, scene);
+
+    ri->FOV = 1.5; // 90 degrees in radians
 
     while (running){
-        actors[1].transform.position = (RI_vector_3f){0, 0, sin(ri->frame * 0.1) * 50 + 200};
+        bill_cube->transform.position = (RI_vector_3f){sin(ri->frame * 0.1) * 50 - 100, sin(ri->frame * 0.2 + 0.4) * 50, sin(ri->frame * 0.1) * 10 + 200};
         
+        scene->camera_position = (RI_vector_3f){cos(ri->frame * 0.07) * 50 * sin(ri->frame * 0.2), sin(ri->frame * 0.07) * 50 * sin(ri->frame * 0.2), -150};
+
         RI_render(scene, ri->frame_buffer);
     }
 }

+ 106 - 59
src/library/rasteriver.c

@@ -52,7 +52,7 @@ RI_scene* RI_request_scene(){
     return new_scene;
 }
 
-RI_actor* RI_request_actors(int RI_number_of_requested_actors, RI_actor_creation_data *actor_creation_data){
+RI_actor* RI_request_actors(int RI_number_of_requested_actors){
     int previous_actor_count = ri.actor_count;
     ri.actor_count += RI_number_of_requested_actors;
     
@@ -61,14 +61,8 @@ RI_actor* RI_request_actors(int RI_number_of_requested_actors, RI_actor_creation
     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.error_material;
-        }
+        new_actor.mesh_reference = NULL;
+        new_actor.material_reference = NULL;
 
         ri.actors[i + previous_actor_count] = new_actor;
     }
@@ -122,12 +116,19 @@ RI_texture* RI_request_textures(int RI_number_of_requested_textures, RI_texture_
     return ri.loaded_textures;
 }
 
-RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
+RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames, int RI_return_just_mesh){
     int meshes_already_loaded_count = ri.loaded_mesh_count;
     
-    ri.loaded_mesh_count += RI_number_of_requested_meshes;
+    RI_mesh* mesh;
+    
+    if (!RI_return_just_mesh) {
+        ri.loaded_mesh_count += RI_number_of_requested_meshes;
 
-    ri.loaded_meshes = realloc(ri.loaded_meshes, sizeof(RI_mesh) * ri.loaded_mesh_count);
+        ri.loaded_meshes = realloc(ri.loaded_meshes, sizeof(RI_mesh) * ri.loaded_mesh_count);
+    }
+    else {
+        mesh = malloc(sizeof(RI_mesh));
+    }
 
     for (int i = 0; i < RI_number_of_requested_meshes; i++){
         RI_mesh new_mesh_data_struct = {0};
@@ -215,17 +216,17 @@ RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
                     has_normals = has_uvs = 1;
                 }
 
-                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_index = vertex_0_index - 1;
+                new_mesh_data_struct.faces[current_face_index].vertex_1_index = vertex_1_index - 1;
+                new_mesh_data_struct.faces[current_face_index].vertex_2_index = 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.vertecies[vertex_0_index - 1].normal = normals[normal_0_index - 1];
+                new_mesh_data_struct.vertecies[vertex_1_index - 1].normal = normals[normal_1_index - 1];
+                new_mesh_data_struct.vertecies[vertex_2_index - 1].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];
+                new_mesh_data_struct.vertecies[vertex_0_index - 1].uv = uvs[uv_0_index - 1];
+                new_mesh_data_struct.vertecies[vertex_1_index - 1].uv = uvs[uv_1_index - 1];
+                new_mesh_data_struct.vertecies[vertex_2_index - 1].uv = uvs[uv_2_index - 1];
 
                 ++current_face_index;
             }
@@ -234,9 +235,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].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;
+                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;
 
                 ++current_vertex_index;
             } 
@@ -258,7 +259,7 @@ RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
 
                 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) 
+                // UVS are almost always 2D so we don't need Z (the type itself is a vector 2f, not 3f) 
 
                 ++current_uv_index;
             } 
@@ -277,16 +278,31 @@ RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
         
         // fclose(file_again);
 
-        ri.loaded_meshes[meshes_already_loaded_count + i] = new_mesh_data_struct;   
+        if (!RI_return_just_mesh) {
+            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); 
+            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); 
+        }
+        else {
+            *mesh = new_mesh_data_struct;
+        }
     }
 
-    return ri.loaded_meshes;
+    if (!RI_return_just_mesh) return ri.loaded_meshes;
+    else return mesh;
 }
 
 void quaternion_rotation(RI_vector_3f *position, RI_vector_4f rotation){
-    return;
+    RI_vector_4f pos_quat = {0, position->x, position->y, position->z};
+
+    RI_vector_4f rotation_conjugation = rotation;
+    quaternion_conjugate(&rotation_conjugation);
+
+    quaternion_multiply(&rotation, pos_quat);
+
+    quaternion_multiply(&rotation, rotation_conjugation);
+
+    *position = (RI_vector_3f){rotation.x, rotation.y, rotation.z};
 }
 
 int RI_render(RI_scene *scene, RI_texture *target_texture){
@@ -298,31 +314,45 @@ int RI_render(RI_scene *scene, RI_texture *target_texture){
         for (int actor_index = 0; actor_index < scene->actor_count; ++actor_index){
             RI_actor *current_actor = scene->actors[actor_index];
 
+            if (!current_actor->transformed_verticies){
+                current_actor->transformed_verticies = malloc(sizeof(RI_vertex) * current_actor->mesh_reference->vertex_count);
+            }
+
             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;
+                current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].position = current_actor->mesh_reference->vertecies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].position;
+                current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].uv = current_actor->mesh_reference->vertecies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].uv;
+
+                current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].position = current_actor->mesh_reference->vertecies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].position;
+                current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].uv = current_actor->mesh_reference->vertecies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].uv;
+
+                current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].position = current_actor->mesh_reference->vertecies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].position;
+                current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].uv = current_actor->mesh_reference->vertecies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].uv;
+
 
-                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);
+                quaternion_rotation(&current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].position, current_actor->transform.rotation);
+                quaternion_rotation(&current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].position, current_actor->transform.rotation);
+                quaternion_rotation(&current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].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_hadamard(&current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].position, current_actor->transform.scale);
+                vector_3f_hadamard(&current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].position, current_actor->transform.scale);
+                vector_3f_hadamard(&current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].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);
+                vector_3f_element_wise_add(&current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].position, current_actor->transform.position);
+                vector_3f_element_wise_add(&current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].position, current_actor->transform.position);
+                vector_3f_element_wise_add(&current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].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;
+                vector_3f_element_wise_subtract(&current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].position, scene->camera_position);
+                vector_3f_element_wise_subtract(&current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].position, scene->camera_position);
+                vector_3f_element_wise_subtract(&current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].position, scene->camera_position);
+
+                current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].position.x = current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].position.x / current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].position.z * horizontal_fov_factor;
+                current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].position.y = current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].position.y / current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].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->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].position.x = current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].position.x / current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].position.z * horizontal_fov_factor;
+                current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].position.y = current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].position.y / current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].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;
+                current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].position.x = current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].position.x / current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].position.z * horizontal_fov_factor;
+                current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].position.y = current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].position.y / current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].position.z * vertical_fov_factor;
             }
         }
 
@@ -337,9 +367,9 @@ int RI_render(RI_scene *scene, RI_texture *target_texture){
                     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;
+                        RI_vector_3f *pos_0 = &current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].position;
+                        RI_vector_3f *pos_1 = &current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].position;
+                        RI_vector_3f *pos_2 = &current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].position;
                         
                         RI_material *mat = current_actor->material_reference;
 
@@ -394,28 +424,35 @@ int RI_render(RI_scene *scene, RI_texture *target_texture){
                         }
                         
                         uint32_t pixel_color = 0xFF000000;
-
+                        
                         if (mat->flags & RI_MATERIAL_HAS_TEXTURE){
-                            uv_0 = &current_actor->mesh_reference->faces[polygon_index].vertex_0->uv;
-                            uv_1 = &current_actor->mesh_reference->faces[polygon_index].vertex_1->uv;
-                            uv_2 = &current_actor->mesh_reference->faces[polygon_index].vertex_2->uv;
+                            uv_0 = &current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_0_index].uv;
+                            uv_1 = &current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_1_index].uv;
+                            uv_2 = &current_actor->transformed_verticies[current_actor->mesh_reference->faces[polygon_index].vertex_2_index].uv;
 
                             double ux = (w0 * (uv_0->x / pos_0->z) + w1 * (uv_1->x / pos_1->z) + w2 * (uv_2->x / pos_2->z)) / w_over_z;
                             double uy = (w0 * (uv_0->y / pos_0->z) + w1 * (uv_1->y / pos_1->z) + w2 * (uv_2->y / pos_2->z)) / w_over_z;                
                         
                             RI_vector_2 texel_position = {mat->texture_reference->resolution.x * ux, mat->texture_reference->resolution.y * uy};
-                        
+                            
                             pixel_color = mat->texture_reference->image_buffer[texel_position.y * mat->texture_reference->resolution.x + texel_position.x];
                         }
+                        else { // must be only an albedo
+                            if (mat->albedo) pixel_color = mat->albedo;
+                            else pixel_color = 0xFFFF77FF;
+                        }
 
-                        int y = pixel_x_index;
-                        int x = pixel_y_index;
+                        int x = pixel_x_index;
+                        int y = pixel_y_index;
                         
                         x += target_texture->resolution.x / 2;
                         y += target_texture->resolution.y / 2;
 
+                        // x = target_texture->resolution.x - 1 - x;
+                        // y = target_texture->resolution.y - 1 - y;
+
                         if (x >= 0 && y >= 0 && x < target_texture->resolution.x && y < target_texture->resolution.y){
-                            target_texture->image_buffer[x * target_texture->resolution.y + y] = pixel_color;
+                            target_texture->image_buffer[y * target_texture->resolution.y + x] = pixel_color;
                         }   
                     }
                 }
@@ -425,7 +462,7 @@ int RI_render(RI_scene *scene, RI_texture *target_texture){
         SDL_UpdateTexture(ri.texture, NULL, ri.frame_buffer->image_buffer, ri.window_width * sizeof(uint32_t));
 
         SDL_RenderClear(ri.renderer);
-        SDL_RenderCopy(ri.renderer, ri.texture, NULL, NULL);
+        SDL_RenderCopyEx(ri.renderer, ri.texture, NULL, NULL, 0, NULL, SDL_FLIP_VERTICAL);
     
         SDL_RenderPresent(ri.renderer);
     }
@@ -486,6 +523,16 @@ int RI_init(int RI_window_width, int RI_window_height, char *RI_window_title){
 
     ri.prefix = "[RasterIver] ";
 
+    char **error_cube_file = malloc(sizeof(char *));
+    error_cube_file[0] = "objects/unit_cube.obj";
+
+    RI_mesh* error_mesh = RI_request_meshes(1, error_cube_file, 1);
+
+    ri.error_mesh = *error_mesh;
+
+    free(error_mesh);
+    free(error_cube_file);
+
     ri.error_texture.image_buffer = malloc(sizeof(uint32_t));
 
     ri.error_texture.image_buffer[0] = 0xFFFF00FF;