diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..99c1a8d --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +array.h is a fork from zauonlok's (github.com/zauonlok) darray.h file with +small syntax changes. + +------------------------------------------------------------------------------ + +darray.h is under the following license: + +MIT License + +Copyright (c) 2020 Zhou Le + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/assets/cube.obj b/assets/cube.obj new file mode 100644 index 0000000..c6d5f12 --- /dev/null +++ b/assets/cube.obj @@ -0,0 +1,46 @@ +# Blender v2.76 (sub 0) OBJ File: '' +# www.blender.org +mtllib cube.mtl +o Cube + +v -1.000000 -1.000000 1.000000 +v 1.000000 -1.000000 1.000000 +v -1.000000 1.000000 1.000000 +v 1.000000 1.000000 1.000000 +v -1.000000 1.000000 -1.000000 +v 1.000000 1.000000 -1.000000 +v -1.000000 -1.000000 -1.000000 +v 1.000000 -1.000000 -1.000000 + +vt 1.000000 0.000000 +vt 0.000000 0.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 + +vn 0.000000 0.000000 1.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 -1.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn -1.000000 0.000000 0.000000 + +g cube +usemtl cube +s 1 +f 1/1/1 2/2/1 3/3/1 +f 3/3/3 2/2/1 4/4/1 +s 2 +f 3/1/2 4/2/2 5/3/2 +f 5/3/2 4/2/2 6/4/2 +s 3 +f 5/4/3 6/3/3 7/2/3 +f 7/2/3 6/3/3 8/1/3 +s 4 +f 7/1/4 8/1/4 1/3/4 +f 1/3/4 8/2/4 2/4/4 +s 5 +f 2/1/5 8/2/5 4/3/5 +f 4/3/5 8/2/5 6/4/5 +s 6 +f 7/1/6 1/2/6 5/3/6 +f 5/3/6 1/2/6 3/4/6 \ No newline at end of file diff --git a/src/array.c b/src/array.c new file mode 100644 index 0000000..8d05d07 --- /dev/null +++ b/src/array.c @@ -0,0 +1,40 @@ +#include +#include +#include "array.h" + +#define ARRAY_RAW_DATA(array) ((int*)(array) - 2) +#define ARRAY_CAPACITY(array) (ARRAY_RAW_DATA(array)[0]) +#define ARRAY_OCCUPIED(array) (ARRAY_RAW_DATA(array)[1]) + +void* array_hold(void* array, int count, int item_size) { + if (array == NULL) { + int raw_size = (sizeof(int) * 2) + (item_size * count); + int* base = (int*)malloc(raw_size); + base[0] = count; // capacity + base[1] = count; // occupied + return base + 2; + } else if (ARRAY_OCCUPIED(array) + count <= ARRAY_CAPACITY(array)) { + ARRAY_OCCUPIED(array) += count; + return array; + } else { + int needed_size = ARRAY_OCCUPIED(array) + count; + int double_curr = ARRAY_CAPACITY(array) * 2; + int capacity = needed_size > double_curr ? needed_size : double_curr; + int occupied = needed_size; + int raw_size = sizeof(int) * 2 + item_size * capacity; + int* base = (int*)realloc(ARRAY_RAW_DATA(array), raw_size); + base[0] = capacity; + base[1] = occupied; + return base + 2; + } +} + +int array_length(void* array) { + return (array != NULL) ? ARRAY_OCCUPIED(array) : 0; +} + +void array_free(void* array) { + if (array != NULL) { + free(ARRAY_RAW_DATA(array)); + } +} \ No newline at end of file diff --git a/src/array.h b/src/array.h new file mode 100644 index 0000000..4b44afb --- /dev/null +++ b/src/array.h @@ -0,0 +1,14 @@ +#ifndef ARRAY_H +#define ARRAY_H + +#define array_push(array, value) \ + do { \ + (array) = array_hold((array), 1, sizeof(*(array))); \ + (array)[array_length(array) - 1] = (value); \ + } while (0); + +void* array_hold(void* array, int count, int item_size); +int array_length(void* array); +void array_free(void* array); + +#endif \ No newline at end of file diff --git a/src/display.c b/src/display.c index 57fd941..1f0f1dd 100644 --- a/src/display.c +++ b/src/display.c @@ -98,7 +98,6 @@ void draw_rect(int x, int y, int width, int height, uint32_t color) { } void destroy_window(void) { - free(color_buffer); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_DestroyTexture(color_buffer_texture); diff --git a/src/main.c b/src/main.c index c255487..fd4fa98 100644 --- a/src/main.c +++ b/src/main.c @@ -4,15 +4,18 @@ #include "display.h" #include "vector.h" #include "mesh.h" +#include "array.h" + +triangle_t* triangles_to_render = NULL; vec3_t camera_position = {0, 0, -5}; -vec3_t cube_rotation = {.x = 0, .y = 0, .z = 0}; -triangle_t triangles_to_render[N_MESH_FACES]; float fov_factor = 640; bool is_running = false; uint32_t previous_frame_time = 0; +void free_resources(); + void setup(void) { // Allocate the required memory in bytes to hold color buffer color_buffer = (uint32_t *) malloc(sizeof(uint32_t) * window_width * window_height); @@ -25,6 +28,9 @@ void setup(void) { window_width, window_height ); + + // load cube vertices into mesh data + load_cube_mesh_data(); } void process_input(void) { @@ -62,23 +68,27 @@ void update(void) { } previous_frame_time = SDL_GetTicks(); - cube_rotation.y += 0.01f; - cube_rotation.z += 0.01f; - cube_rotation.x += 0.01f; + //initialize array of triangles + triangles_to_render = NULL; - for (int i = 0; i < N_MESH_FACES; i++) { - face_t mesh_face = mesh_faces[i]; + mesh.rotation.y += 0.01f; + mesh.rotation.z += 0.01f; + mesh.rotation.x += 0.01f; + + int num_faces = array_length(mesh.faces); + for (int i = 0; i < num_faces; i++) { + face_t mesh_face = mesh.faces[i]; vec3_t face_vertices[3]; - face_vertices[0] = mesh_vertices[mesh_face.a - 1]; - face_vertices[1] = mesh_vertices[mesh_face.b - 1]; - face_vertices[2] = mesh_vertices[mesh_face.c - 1]; + face_vertices[0] = mesh.vertices[mesh_face.a - 1]; + face_vertices[1] = mesh.vertices[mesh_face.b - 1]; + face_vertices[2] = mesh.vertices[mesh_face.c - 1]; //loop all three vertices triangle_t projected_triangle; for (int j = 0; j < 3; j++) { vec3_t transformed_vertex = face_vertices[j]; - transformed_vertex = vec3_rotate_y(transformed_vertex, cube_rotation.y); - transformed_vertex = vec3_rotate_x(transformed_vertex, cube_rotation.x); - transformed_vertex = vec3_rotate_z(transformed_vertex, cube_rotation.z); + transformed_vertex = vec3_rotate_y(transformed_vertex, mesh.rotation.y); + transformed_vertex = vec3_rotate_x(transformed_vertex, mesh.rotation.x); + transformed_vertex = vec3_rotate_z(transformed_vertex, mesh.rotation.z); transformed_vertex.z -= camera_position.z; vec2_t projected_point = project(transformed_vertex); @@ -88,16 +98,18 @@ void update(void) { projected_triangle.points[j] = projected_point; } // save projected triangle in array of triangles to render - triangles_to_render[i] = projected_triangle; + array_push(triangles_to_render, projected_triangle); } } void render(void) { - draw_grid(); +// draw_grid(); - for (int i = 0; i < N_MESH_FACES; i++) { + //triangle array size + int num_triangles = array_length(triangles_to_render); + for (int i = 0; i < num_triangles; i++) { triangle_t triangle = triangles_to_render[i]; uint32_t color = 0xFFFFFF00; for (int j = 0; j < 3; j++) { @@ -117,6 +129,13 @@ void render(void) { } +void free_resources() { + array_free(triangles_to_render); + array_free(mesh.vertices); + array_free(mesh.faces); + free(color_buffer); +} + int main(void) { is_running = initialize_window(); setup(); @@ -127,5 +146,7 @@ int main(void) { render(); } destroy_window(); + free_resources(); return 0; } + diff --git a/src/mesh.c b/src/mesh.c index 01846d0..e9db202 100644 --- a/src/mesh.c +++ b/src/mesh.c @@ -1,6 +1,14 @@ +#include #include "mesh.h" +#include "array.h" -vec3_t mesh_vertices[N_MESH_VERTICES] = { +mesh_t mesh = { + .vertices = NULL, + .faces = NULL, + .rotation = {0,0,0} +}; + +vec3_t cube_vertices[N_CUBE_VERTICES] = { {.x = -1, .y = -1, .z = -1}, {.x = -1, .y = 1, .z = -1}, {.x = 1, .y = 1, .z = -1}, @@ -11,7 +19,7 @@ vec3_t mesh_vertices[N_MESH_VERTICES] = { {.x = -1, .y = -1, .z = 1}, }; -face_t mesh_faces[N_MESH_FACES] = { +face_t cube_faces[N_CUBE_FACES] = { // Front {.a = 1, .b = 2, .c = 3}, {.a = 1, .b = 3, .c = 4}, @@ -30,4 +38,15 @@ face_t mesh_faces[N_MESH_FACES] = { // bottom {.a = 6, .b = 8, .c = 1}, {.a = 6, .b = 1, .c = 4}, -}; \ No newline at end of file +}; + +void load_cube_mesh_data(void) { + for (int i = 0; i < N_CUBE_VERTICES; i++){ + vec3_t cube_vertex = cube_vertices[i]; + array_push(mesh.vertices, cube_vertex); + } + for (int i = 0; i < N_CUBE_FACES; i++){ + face_t cube_face = cube_faces[i]; + array_push(mesh.faces, cube_face); + } +} \ No newline at end of file diff --git a/src/mesh.h b/src/mesh.h index 396cd7e..460473c 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -2,10 +2,19 @@ #define RENDERER_MESH_H #include "vector.h" #include "triangle.h" -#define N_MESH_VERTICES 8 -#define N_MESH_FACES (6 * 2 ) +#define N_CUBE_VERTICES 8 +#define N_CUBE_FACES (6 * 2) -extern vec3_t mesh_vertices[N_MESH_VERTICES]; -extern face_t mesh_faces[N_MESH_FACES]; +extern vec3_t cube_vertices[N_CUBE_VERTICES]; +extern face_t cube_faces[N_CUBE_FACES]; + +typedef struct { + vec3_t* vertices; + face_t* faces; + vec3_t rotation; +} mesh_t; + +extern mesh_t mesh; +void load_cube_mesh_data(void); #endif //RENDERER_MESH_H \ No newline at end of file