rasteriver.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. #include <stdio.h>
  2. #include <CL/cl.h>
  3. #include <SDL2/SDL.h>
  4. #include "../headers/rasteriver.h"
  5. #define STB_IMAGE_IMPLEMENTATION
  6. #include "../headers/stb_image.h"
  7. #include "stdint.h"
  8. #include <math.h>
  9. RasterIver ri = {NULL};
  10. void debug(char *string, ...){
  11. va_list args;
  12. va_start(args, string);
  13. char message[500];
  14. strcpy(message, ri.prefix);
  15. strcat(message, string);
  16. vprintf(message, args);
  17. printf("\n");
  18. va_end(args);
  19. }
  20. RasterIver* RI_get_ri(){
  21. return &ri;
  22. }
  23. int RI_add_actors_to_scene(int RI_number_of_actors_to_add_to_scene, RI_actor *actors, RI_scene *scene){
  24. int previous_actor_count = scene->actor_count;
  25. scene->actor_count += RI_number_of_actors_to_add_to_scene;
  26. scene->actors = realloc(scene->actors, sizeof(RI_actor *) * scene->actor_count);
  27. for (int i = 0; i < RI_number_of_actors_to_add_to_scene; ++i){
  28. scene->actors[i + previous_actor_count] = &actors[i];
  29. }
  30. return 0;
  31. }
  32. RI_scene* RI_request_scene(){
  33. RI_scene* new_scene = malloc(sizeof(RI_scene));
  34. new_scene->actor_count = 0;
  35. new_scene->actors = NULL;
  36. return new_scene;
  37. }
  38. RI_actor* RI_request_actors(int RI_number_of_requested_actors, RI_actor_creation_data *actor_creation_data){
  39. int previous_actor_count = ri.actor_count;
  40. ri.actor_count += RI_number_of_requested_actors;
  41. ri.actors = realloc(ri.actors, sizeof(RI_actor) * ri.actor_count);
  42. for (int i = 0; i < RI_number_of_requested_actors; ++i){
  43. RI_actor new_actor = {0};
  44. new_actor.mesh_reference = actor_creation_data[i].mesh_reference;
  45. if (actor_creation_data->material_reference){
  46. new_actor.material_reference = actor_creation_data[i].material_reference;
  47. }
  48. else {
  49. new_actor.material_reference = &ri.error_material;
  50. }
  51. ri.actors[i + previous_actor_count] = new_actor;
  52. }
  53. return ri.actors;
  54. }
  55. RI_material* RI_request_materials(int RI_number_of_requested_materials){
  56. ri.material_count += RI_number_of_requested_materials;
  57. ri.materials = realloc(ri.materials, sizeof(RI_material) * ri.material_count);
  58. return ri.materials;
  59. }
  60. RI_texture* RI_request_textures(int RI_number_of_requested_textures, RI_texture_creation_data *texture_creation_data){
  61. int previous_loaded_texture_count = ri.loaded_texture_count;
  62. ri.loaded_texture_count += RI_number_of_requested_textures;
  63. ri.loaded_textures = realloc(ri.loaded_textures, sizeof(RI_texture) * ri.loaded_texture_count);
  64. for (int i = 0; i < RI_number_of_requested_textures; i++){
  65. RI_texture new_texture = {0};
  66. char *current_texture_filename = texture_creation_data[i].filename;
  67. unsigned char* temp_texture = stbi_load(current_texture_filename, &new_texture.resolution.x, &new_texture.resolution.y, NULL, 4);
  68. if(stbi_failure_reason()){
  69. new_texture = ri.error_texture;
  70. }
  71. else {
  72. new_texture.image_buffer = malloc(sizeof(uint32_t) * new_texture.resolution.x * new_texture.resolution.y);
  73. for (int i = 0; i < new_texture.resolution.x * new_texture.resolution.y; ++i){
  74. unsigned char r = temp_texture[i * 4];
  75. unsigned char g = temp_texture[i * 4 + 1];
  76. unsigned char b = temp_texture[i * 4 + 2];
  77. unsigned char a = temp_texture[i * 4 + 3];
  78. new_texture.image_buffer[i] = (a << 24 | r << 16 | g << 8 | b);
  79. }
  80. }
  81. ri.loaded_textures[previous_loaded_texture_count + i] = new_texture;
  82. stbi_image_free(temp_texture);
  83. }
  84. return ri.loaded_textures;
  85. }
  86. RI_mesh* RI_request_meshes(int RI_number_of_requested_meshes, char **filenames){
  87. int meshes_already_loaded_count = ri.loaded_mesh_count;
  88. ri.loaded_mesh_count += RI_number_of_requested_meshes;
  89. ri.loaded_meshes = realloc(ri.loaded_meshes, sizeof(RI_mesh) * ri.loaded_mesh_count);
  90. for (int i = 0; i < RI_number_of_requested_meshes; i++){
  91. RI_mesh new_mesh_data_struct = {0};
  92. FILE *file = fopen(filenames[i], "r");
  93. if (!file){
  94. debug("Error! File \"%s\" not found", filenames[i]);
  95. RI_stop(1);
  96. }
  97. char line[512];
  98. while (fgets(line, sizeof(line), file)) {
  99. if (line[0] == 'f' && line[1] == ' ') { // face
  100. new_mesh_data_struct.face_count++;
  101. }
  102. else if (line[0] == 'v' && line[1] == ' ') { // vertex
  103. new_mesh_data_struct.vertex_count++;
  104. }
  105. else if (line[0] == 'v' && line[1] == 'n') { // normal
  106. new_mesh_data_struct.normal_count++;
  107. }
  108. else if (line[0] == 'v' && line[1] == 't') { // UV
  109. new_mesh_data_struct.uv_count++;
  110. }
  111. }
  112. fclose(file);
  113. new_mesh_data_struct.faces = malloc(sizeof(RI_face) * new_mesh_data_struct.face_count);
  114. new_mesh_data_struct.vertecies = malloc(sizeof(RI_vertex) * new_mesh_data_struct.vertex_count);
  115. RI_vector_3f *normals = malloc(sizeof(RI_vector_3f) * new_mesh_data_struct.normal_count);
  116. RI_vector_2f *uvs = malloc(sizeof(RI_vector_2f) * new_mesh_data_struct.uv_count);
  117. FILE *file_again = fopen(filenames[i], "r");
  118. int current_face_index = 0;
  119. int current_vertex_index = 0;
  120. int current_normal_index = 0;
  121. int current_uv_index = 0;
  122. int has_normals, has_uvs;
  123. has_normals = has_uvs = 0;
  124. while (fgets(line, sizeof(line), file_again)) {
  125. if (line[0] == 'f' && line[1] == ' ') {
  126. 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;
  127. int matches = sscanf(line, "f %d/%d/%d %d/%d/%d %d/%d/%d/",
  128. &vertex_0_index, &uv_0_index, &normal_0_index,
  129. &vertex_1_index, &uv_1_index, &normal_1_index,
  130. &vertex_2_index, &uv_2_index, &normal_2_index);
  131. if (matches != 9){
  132. vertex_0_index = -1;
  133. vertex_1_index = -1;
  134. vertex_2_index = -1;
  135. normal_0_index = -1;
  136. normal_1_index = -1;
  137. normal_2_index = -1;
  138. uv_0_index = -1;
  139. uv_1_index = -1;
  140. uv_2_index = -1;
  141. if (strchr(line, '/')){
  142. sscanf(line, "f %d//%d %d//%d %d//%d",
  143. &vertex_0_index, &normal_0_index,
  144. &vertex_1_index, &normal_1_index,
  145. &vertex_2_index, &normal_2_index);
  146. has_normals = 1;
  147. }
  148. else {
  149. sscanf(line, "f %d %d %d",
  150. &vertex_0_index,
  151. &vertex_1_index,
  152. &vertex_2_index);
  153. }
  154. }
  155. else {
  156. has_normals = has_uvs = 1;
  157. }
  158. new_mesh_data_struct.faces[current_face_index].vertex_0 = &new_mesh_data_struct.vertecies[vertex_0_index - 1];
  159. new_mesh_data_struct.faces[current_face_index].vertex_1 = &new_mesh_data_struct.vertecies[vertex_1_index - 1];
  160. new_mesh_data_struct.faces[current_face_index].vertex_2 = &new_mesh_data_struct.vertecies[vertex_2_index - 1];
  161. new_mesh_data_struct.faces[current_face_index].vertex_0->original_normal = normals[normal_0_index - 1];
  162. new_mesh_data_struct.faces[current_face_index].vertex_1->original_normal = normals[normal_1_index - 1];
  163. new_mesh_data_struct.faces[current_face_index].vertex_2->original_normal = normals[normal_2_index - 1];
  164. new_mesh_data_struct.faces[current_face_index].vertex_0->uv = uvs[uv_0_index - 1];
  165. new_mesh_data_struct.faces[current_face_index].vertex_1->uv = uvs[uv_1_index - 1];
  166. new_mesh_data_struct.faces[current_face_index].vertex_2->uv = uvs[uv_2_index - 1];
  167. ++current_face_index;
  168. }
  169. else if (line[0] == 'v' && line[1] == ' ') {
  170. float x, y, z;
  171. sscanf(line, "v %f %f %f", &x, &y, &z);
  172. new_mesh_data_struct.vertecies[current_vertex_index].original_position.x = x;
  173. new_mesh_data_struct.vertecies[current_vertex_index].original_position.y = y;
  174. new_mesh_data_struct.vertecies[current_vertex_index].original_position.z = z;
  175. ++current_vertex_index;
  176. }
  177. else if (line[0] == 'v' && line[1] == 'n') {
  178. float x, y, z;
  179. sscanf(line, "vn %f %f %f", &x, &y, &z);
  180. normals[current_normal_index].x = x;
  181. normals[current_normal_index].y = y;
  182. normals[current_normal_index].z = z;
  183. ++current_normal_index;
  184. }
  185. else if (line[0] == 'v' && line[1] == 't') {
  186. float x, y, z;
  187. sscanf(line, "vt %f %f %f", &x, &y, &z);
  188. uvs[current_uv_index].x = x;
  189. uvs[current_uv_index].y = y;
  190. // UVS are almost always 2D so we don't need Z this (the type itself is a vector 2f, not 3f)
  191. ++current_uv_index;
  192. }
  193. }
  194. free(normals);
  195. free(uvs);
  196. char* loading_mesh_notice_string;
  197. if (has_normals && !has_uvs) loading_mesh_notice_string = "normals";
  198. else if (!has_normals && has_uvs) loading_mesh_notice_string = "UVs";
  199. else if (!has_normals && !has_uvs) loading_mesh_notice_string = "normals and UVs";
  200. if (!has_normals || !has_uvs) debug("Notice! Mesh \"%s\" is missing %s", filenames[i], loading_mesh_notice_string);
  201. // fclose(file_again);
  202. ri.loaded_meshes[meshes_already_loaded_count + i] = new_mesh_data_struct;
  203. 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);
  204. }
  205. return ri.loaded_meshes;
  206. }
  207. void quaternion_rotation(RI_vector_3f *position, RI_vector_4f rotation){
  208. return;
  209. }
  210. int RI_render(RI_scene *scene, RI_texture *target_texture){
  211. // do rendering stuff
  212. if (ri.running){
  213. float horizontal_fov_factor = target_texture->resolution.x / tanf(0.5 * ri.FOV);
  214. float vertical_fov_factor = target_texture->resolution.y / tanf(0.5 * ri.FOV);
  215. for (int actor_index = 0; actor_index < scene->actor_count; ++actor_index){
  216. RI_actor *current_actor = scene->actors[actor_index];
  217. for (int polygon_index = 0; polygon_index < current_actor->mesh_reference->face_count; ++polygon_index){
  218. current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position = current_actor->mesh_reference->faces[polygon_index].vertex_0->original_position;
  219. current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position = current_actor->mesh_reference->faces[polygon_index].vertex_1->original_position;
  220. current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position = current_actor->mesh_reference->faces[polygon_index].vertex_2->original_position;
  221. quaternion_rotation(&current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position, current_actor->transform.rotation);
  222. quaternion_rotation(&current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position, current_actor->transform.rotation);
  223. quaternion_rotation(&current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position, current_actor->transform.rotation);
  224. vector_3f_hadamard(&current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position, current_actor->transform.scale);
  225. vector_3f_hadamard(&current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position, current_actor->transform.scale);
  226. vector_3f_hadamard(&current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position, current_actor->transform.scale);
  227. vector_3f_element_wise_add(&current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position, current_actor->transform.position);
  228. vector_3f_element_wise_add(&current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position, current_actor->transform.position);
  229. vector_3f_element_wise_add(&current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position, current_actor->transform.position);
  230. 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;
  231. 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;
  232. 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;
  233. 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;
  234. 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;
  235. 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;
  236. }
  237. }
  238. for (int pixel_index = 0; pixel_index < target_texture->resolution.x * target_texture->resolution.y; ++pixel_index){
  239. target_texture->image_buffer[pixel_index] = 0x0;
  240. ri.z_buffer[pixel_index] = 99999;
  241. }
  242. for (int pixel_y_index = -target_texture->resolution.y / 2; pixel_y_index < target_texture->resolution.y / 2; ++pixel_y_index){
  243. for (int pixel_x_index = -target_texture->resolution.x / 2; pixel_x_index < target_texture->resolution.x / 2; ++pixel_x_index){
  244. for (int actor_index = 0; actor_index < scene->actor_count; ++actor_index){
  245. RI_actor *current_actor = scene->actors[actor_index];
  246. for (int polygon_index = 0; polygon_index < current_actor->mesh_reference->face_count; ++polygon_index){
  247. RI_vector_3f *pos_0 = &current_actor->mesh_reference->faces[polygon_index].vertex_0->transformed_position;
  248. RI_vector_3f *pos_1 = &current_actor->mesh_reference->faces[polygon_index].vertex_1->transformed_position;
  249. RI_vector_3f *pos_2 = &current_actor->mesh_reference->faces[polygon_index].vertex_2->transformed_position;
  250. RI_material *mat = current_actor->material_reference;
  251. RI_vector_2f *uv_0;
  252. RI_vector_2f *uv_1;
  253. RI_vector_2f *uv_2;
  254. if (mat == NULL){
  255. mat = &ri.error_material;
  256. }
  257. if(mat->flags & RI_MATERIAL_HAS_TEXTURE && mat->texture_reference == NULL){
  258. mat->texture_reference = &ri.error_texture;
  259. }
  260. if(mat->flags & RI_MATERIAL_HAS_BUMP_MAP && mat->bump_map_reference == NULL){
  261. mat->bump_map_reference = &ri.error_bump_map;
  262. }
  263. if(mat->flags & RI_MATERIAL_HAS_NORMAL_MAP && mat->normal_map_reference == NULL){
  264. mat->normal_map_reference = &ri.error_normal_map;
  265. }
  266. 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;
  267. 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;
  268. 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;
  269. if (vertex_0_out_of_bounds && vertex_1_out_of_bounds && vertex_2_out_of_bounds){
  270. // continue;
  271. }
  272. float denominator, w0, w1, w2;
  273. 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);
  274. 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;
  275. 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;
  276. w2 = 1.0 - w0 - w1;
  277. float w_over_z = (w0 / pos_0->z + w1 / pos_1->z + w2 / pos_2->z);
  278. float interpolated_z = 1.0 / w_over_z;
  279. if (!(w0 >= 0 && w1 >= 0 && w2 >= 0) || (mat->flags & RI_MATERIAL_WIREFRAME && (w0 >= mat->wireframe_width && w1 >= mat->wireframe_width && w2 >= mat->wireframe_width))){
  280. continue;
  281. }
  282. if (!(mat->flags & RI_MATERIAL_DONT_DEPTH_TEST) && interpolated_z >= ri.z_buffer[(pixel_x_index + target_texture->resolution.y / 2) * target_texture->resolution.x + (pixel_y_index + target_texture->resolution.x / 2)]){
  283. continue;
  284. }
  285. if (!(mat->flags & RI_MATERIAL_DONT_DEPTH_WRITE)){
  286. ri.z_buffer[(pixel_x_index + target_texture->resolution.y / 2) * target_texture->resolution.x + (pixel_y_index + target_texture->resolution.x / 2)] = interpolated_z;
  287. }
  288. uint32_t pixel_color = 0xFF000000;
  289. if (mat->flags & RI_MATERIAL_HAS_TEXTURE){
  290. uv_0 = &current_actor->mesh_reference->faces[polygon_index].vertex_0->uv;
  291. uv_1 = &current_actor->mesh_reference->faces[polygon_index].vertex_1->uv;
  292. uv_2 = &current_actor->mesh_reference->faces[polygon_index].vertex_2->uv;
  293. 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;
  294. 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;
  295. RI_vector_2 texel_position = {mat->texture_reference->resolution.x * ux, mat->texture_reference->resolution.y * uy};
  296. pixel_color = mat->texture_reference->image_buffer[texel_position.y * mat->texture_reference->resolution.x + texel_position.x];
  297. }
  298. int y = pixel_x_index;
  299. int x = pixel_y_index;
  300. x += target_texture->resolution.x / 2;
  301. y += target_texture->resolution.y / 2;
  302. if (x >= 0 && y >= 0 && x < target_texture->resolution.x && y < target_texture->resolution.y){
  303. target_texture->image_buffer[x * target_texture->resolution.y + y] = pixel_color;
  304. }
  305. }
  306. }
  307. }
  308. }
  309. SDL_UpdateTexture(ri.texture, NULL, ri.frame_buffer->image_buffer, ri.window_width * sizeof(uint32_t));
  310. SDL_RenderClear(ri.renderer);
  311. SDL_RenderCopy(ri.renderer, ri.texture, NULL, NULL);
  312. SDL_RenderPresent(ri.renderer);
  313. }
  314. else{
  315. RI_stop(0);
  316. }
  317. // handle SDL events
  318. while (SDL_PollEvent(&ri.event)){
  319. switch (ri.event.type){
  320. case SDL_QUIT:
  321. ri.running = 0;
  322. }
  323. }
  324. ++ri.frame;
  325. return 0;
  326. }
  327. int opencl_init(){
  328. return 0;
  329. }
  330. int sdl_init(int RI_window_width, int RI_window_height, char *RI_window_title){
  331. ri.window_width = RI_window_width;
  332. ri.window_height = RI_window_height;
  333. ri.window_title = RI_window_title;
  334. ri.frame_buffer = malloc(sizeof(RI_texture));
  335. ri.frame_buffer->image_buffer = malloc(sizeof(uint32_t) * ri.window_width * ri.window_height);
  336. ri.frame_buffer->resolution = (RI_vector_2){ri.window_width, ri.window_height};
  337. ri.z_buffer = malloc(sizeof(float) * ri.window_width * ri.window_height);
  338. SDL_Init(SDL_INIT_VIDEO);
  339. ri.window = SDL_CreateWindow(RI_window_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, ri.window_width, ri.window_height, SDL_WINDOW_OPENGL);
  340. ri.renderer = SDL_CreateRenderer(ri.window, -1, SDL_RENDERER_ACCELERATED);
  341. ri.texture = SDL_CreateTexture(ri.renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, ri.window_width, ri.window_height);
  342. return 0;
  343. }
  344. int RI_init(int RI_window_width, int RI_window_height, char *RI_window_title){
  345. ri.running = 1;
  346. opencl_init();
  347. sdl_init(RI_window_width, RI_window_height, RI_window_title);
  348. ri.loaded_mesh_count = 0;
  349. ri.loaded_texture_count = 0;
  350. ri.actor_count = 0;
  351. ri.prefix = "[RasterIver] ";
  352. ri.error_texture.image_buffer = malloc(sizeof(uint32_t));
  353. ri.error_texture.image_buffer[0] = 0xFFFF00FF;
  354. ri.error_texture.resolution = (RI_vector_2){1, 1};
  355. ri.error_material.texture_reference = &ri.error_texture;
  356. ri.error_material.albedo = 0xFF5522CC;
  357. ri.error_material.flags = RI_MATERIAL_UNLIT | RI_MATERIAL_DONT_DEPTH_TEST | RI_MATERIAL_DONT_RECEIVE_SHADOW | RI_MATERIAL_HAS_TEXTURE | RI_MATERIAL_DOUBLE_SIDED;
  358. return 0;
  359. }
  360. int RI_stop(int result){
  361. debug("Stopping...");
  362. for (int mesh_index = 0; mesh_index < ri.loaded_mesh_count; ++mesh_index){
  363. free(ri.loaded_meshes[mesh_index].faces); // free face array
  364. free(ri.loaded_meshes[mesh_index].vertecies); // free vertex array
  365. }
  366. for (int texture_index = 0; texture_index < ri.loaded_texture_count; ++texture_index){
  367. free(ri.loaded_textures[texture_index].image_buffer);
  368. }
  369. exit(result);
  370. return 0;
  371. }