#include "triangle.h" #include #include #include "display.h" // TODO: Create implementation for triangle.h functions int compare_vec2_t(const void* a, const void* b) { const int_vec2_t* arg1 = (const int_vec2_t*)a; const int_vec2_t* arg2 = (const int_vec2_t*)b; if (arg1->y < arg2->y) return -1; if (arg1->y > arg2->y) return 1; return 0; } #define FUNC (int)ceilf #define FUNC2 (int)floorf uint32_t invert_rgb(uint32_t color) { uint32_t a = color & 0xFF000000; // Alpha channel uint32_t rgb = color & 0x00FFFFFF; // RGB channels rgb = ~rgb & 0x00FFFFFF; // Invert RGB only return a | rgb; } /////////////////////////////////////////////////////////////////////////////// // Draw a filled a triangle with a flat bottom /////////////////////////////////////////////////////////////////////////////// // // (x0,y0) // / \ // / \ // / \ // / \ // / \ // (x1,y1)------(x2,y2) // /////////////////////////////////////////////////////////////////////////////// void fill_flat_bottom_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color) { // Find the two slopes (two triangle legs) float inv_slope_1 = (float)(x1 - x0) / (y1 - y0); float inv_slope_2 = (float)(x2 - x0) / (y2 - y0); // Start x_start and x_end from the top vertex (x0,y0) float x_start = x0; float x_end = x0; // Loop all the scanlines from top to bottom for (int y = y0; y <= y2; y++) { draw_line(x_start, y, x_end, y, color); x_start += inv_slope_1; x_end += inv_slope_2; } } /////////////////////////////////////////////////////////////////////////////// // Draw a filled a triangle with a flat top /////////////////////////////////////////////////////////////////////////////// // // (x0,y0)------(x1,y1) // \ / // \ / // \ / // \ / // \ / // (x2,y2) // /////////////////////////////////////////////////////////////////////////////// void fill_flat_top_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color) { // Find the two slopes (two triangle legs) float inv_slope_1 = (float)(x2 - x0) / (y2 - y0); float inv_slope_2 = (float)(x2 - x1) / (y2 - y1); // Start x_start and x_end from the bottom vertex (x2,y2) float x_start = x2; float x_end = x2; // Loop all the scanlines from bottom to top for (int y = y2; y >= y0; y--) { draw_line(x_start, y, x_end, y, color); x_start -= inv_slope_1; x_end -= inv_slope_2; } } /////////////////////////////////////////////////////////////////////////////// // Draw a filled triangle with the flat-top/flat-bottom method // We split the original triangle in two, half flat-bottom and half flat-top /////////////////////////////////////////////////////////////////////////////// // // (x0,y0) // / \ // / \ // / \ // / \ // / \ // (x1,y1)------(Mx,My) // \_ \ // \_ \ // \_ \ // \_ \ // \ \ // \_ \ // \_\ // \ // (x2,y2) // /////////////////////////////////////////////////////////////////////////////// void draw_filled_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color) { // We need to sort the vertices by y-coordinate ascending (y0 < y1 < y2) if (y0 > y1) { int_swap(&y0, &y1); int_swap(&x0, &x1); } if (y1 > y2) { int_swap(&y1, &y2); int_swap(&x1, &x2); } if (y0 > y1) { int_swap(&y0, &y1); int_swap(&x0, &x1); } if (y1 == y2) { // Draw flat-bottom triangle fill_flat_bottom_triangle(x0, y0, x1, y1, x2, y2, color); } else if (y0 == y1) { // Draw flat-top triangle fill_flat_top_triangle(x0, y0, x1, y1, x2, y2, color); } else { // Calculate the new vertex (Mx,My) using triangle similarity int My = y1; int Mx = (((x2 - x0) * (y1 - y0)) / (y2 - y0)) + x0; // Draw flat-bottom triangle fill_flat_bottom_triangle(x0, y0, x1, y1, Mx, My, color); // Draw flat-top triangle fill_flat_top_triangle(x1, y1, Mx, My, x2, y2, color); } } void draw_textured_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t* texture) { // sort by y int temp = 0, min_idx = 0, mid_idx = 1, max_idx = 2; // We need to sort the vertices by y-coordinate ascending (y0 < y1 < y2) if (y0 > y1) { int_swap(&y0, &y1); int_swap(&x0, &x1); } if (y1 > y2) { int_swap(&y1, &y2); int_swap(&x1, &x2); } if (y0 > y1) { int_swap(&y0, &y1); int_swap(&x0, &x1); } float inv_slope_1 = 0; float inv_slope_2 = 0; /*if (triangle.points[mid_idx].y - triangle.points[min_idx].y != 0) { inv_slope_1 = (float)(triangle.points[mid_idx].x - triangle.points[min_idx].x) / fabsf(triangle.points[mid_idx].y - triangle.points[min_idx].y); } if (triangle.points[max_idx].y - triangle.points[min_idx].y != 0) { inv_slope_2 = (float)(triangle.points[max_idx].x - triangle.points[min_idx].x) / fabsf(triangle.points[max_idx].y - triangle.points[min_idx].y); } for (int y = triangle.points[min_idx].y; y <= triangle.points[mid_idx].y; y++) { //float x_start = triangle } */ }