#include #include #include #include #include "display.h" #include "mesh.h" #include "vector.h" #include "array.h" #define STEP 0.075 triangle_t* triangles_to_render = NULL; //[N_MESH_FACES]; vec3_t camera_position = { .x = 0, .y = 0, .z = -5 }; float fov_factor = 640; bool is_running = false; uint32_t previous_frame_time = 0; void setup(void) { // Allocate the required memory in bytes to hold the color buffer color_buffer = (uint32_t*) malloc(sizeof(uint32_t) * window_width * window_height); // Creating a SDL texture that is used to display the color buffer color_buffer_texture = SDL_CreateTexture( renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, window_width, window_height ); // load cube mesh data load_file(); } void process_input(void) { SDL_Event event; SDL_PollEvent(&event); switch (event.type) { case SDL_QUIT: is_running = false; break; case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) is_running = false; //break; if (event.key.keysym.sym == SDLK_UP) mesh.rotation.z += STEP; if (event.key.keysym.sym == SDLK_LEFT) mesh.rotation.x += STEP; if (event.key.keysym.sym == SDLK_RIGHT) mesh.rotation.y += STEP; break; } } //////////////////////////////////////////////////////////////////////////////// // Function that receives a 3D vector and returns a projected 2D point //////////////////////////////////////////////////////////////////////////////// vec2_t project(vec3_t point) { vec2_t projected_point = { .x = (fov_factor * point.x) / point.z, .y = (fov_factor * point.y) / point.z, }; return projected_point; } void update(void) { //while (!SDL_TICKS_PASSED(SDL_GetTicks(), previous_frame_time + FRAME_TARGET_TIME)); int time_to_wait = FRAME_TARGET_TIME - (SDL_GetTicks() - previous_frame_time); // only delay execution if we are running too fast if (time_to_wait > 0 && time_to_wait <= FRAME_TARGET_TIME) { SDL_Delay(time_to_wait); } previous_frame_time = SDL_GetTicks(); //mesh.rotation.y += 0.01; mesh.rotation.x -= 0.01; //mesh.rotation.z += 0.01; triangles_to_render = NULL; 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_verticies[3]; face_verticies[0] = mesh.vertices[mesh_face.a - 1]; face_verticies[1] = mesh.vertices[mesh_face.b - 1]; face_verticies[2] = mesh.vertices[mesh_face.c - 1]; triangle_t projected_triangle; for (int j = 0; j < 3; j++) { vec3_t transformed_vertex = face_verticies[j]; transformed_vertex = vec3_rotate_x(transformed_vertex, mesh.rotation.x); transformed_vertex = vec3_rotate_y(transformed_vertex, mesh.rotation.y); transformed_vertex = vec3_rotate_z(transformed_vertex, mesh.rotation.z); // translate away from camera in z transformed_vertex.z -= camera_position.z; // project the current vertex vec2_t projected_point = project(transformed_vertex); // scale and translate the projected points to the center of the screen projected_point.x += (window_width / 2); projected_point.y += (window_height / 2); projected_triangle.points[j] = projected_point; } // save the projected triangle in the array of triangles array_push(triangles_to_render, projected_triangle); } } void render(void) { draw_grid(); // Loop all projected points and render them for (int i = 0; i < array_length(triangles_to_render); i++) { triangle_t triangle = triangles_to_render[i]; draw_triangle(triangle, 0xFF00FF00); draw_rect(triangle.points[0].x, triangle.points[0].y, 3, 3, 0xFFFFFF00); draw_rect(triangle.points[1].x, triangle.points[1].y, 3, 3, 0xFFFFFF00); draw_rect(triangle.points[2].x, triangle.points[2].y, 3, 3, 0xFFFFFF00); } //draw_line(10, 10, 500, 500, 0x00FF00); array_free(triangles_to_render); render_color_buffer(); clear_color_buffer(0xFF000000); SDL_RenderPresent(renderer); } void free_resources(void) { free(color_buffer); array_free(mesh.faces); array_free(mesh.vertices); } int main(int argc, char *argv[]) { is_running = initialize_window(); setup(); while (is_running) { process_input(); update(); render(); } destroy_window(); free_resources(); return 0; }