#include "triangle.h" #include "texture.h" #include "space.h" #include "zbuffer.h" #ifdef USE_LIBPROF #include #endif #include #include #ifdef USE_LIBPROF static uint32_t frame_interval_min=1000000; static uint32_t frame_interval_max=1; #endif void fe_render_update(const uint32_t libprof_channel) { dupdate(); #ifdef USE_LIBPROF // gestion du temps avec libprof if (prof_elapsed) { prof_leave(libprof_channel); uint32_t frame_interval = prof_time(libprof_channel); //sleep_us(0, MINIMUM_FRAME_DELAY-frame_interval); if (frame_intervalframe_interval_max) frame_interval_max = frame_interval; } else { prof_init(libprof_channel+1, 0); } //dupdate(); prof_clear(libprof_channel); prof_enter(libprof_channel); #endif fe_zbuffer_clear(); ///fe_set(dh, dv, roulis, camera); dclear(C_WHITE); } /** * @brief Orientation of the face * * @param face The face * * @return if it is true the it is clockwised else it isn't clockwised */ static bool is_colckwised(fe_triangle const * face) { int32_t area = 0; area += face->s1->x * face->s2->y; area -= face->s2->x * face->s1->y; area += face->s2->x * face->s3->y; area -= face->s3->x * face->s2->y; area += face->s3->x * face->s1->y; area -= face->s1->x * face->s3->y; return (area < 0); } // gestion locale des arètes typedef struct line line; struct line { int32_t x,y,z; int32_t dx,dy,dz; int32_t no_line; // si les deux points sont confondus (se comporte comme un bool) }; /** * @brief Sets up a line with 2 points * * @param l The line * @param s1 The s 1 * @param s2 The s 2 */ static void line_set(line* l,fe_ipoint const * s1, fe_ipoint const * s2) { l->x = s1->x; l->y = s1->y; l->z = s1->z; l->dx = s2->x - s1->x; l->dy = s2->y - s1->y; l->dz = s2->z - s1->z; l->no_line = (l->dx==0 && l->dy==0); } static int32_t max(int32_t x, int32_t y) { return (x>y ? x : y); } static int32_t min(int32_t x, int32_t y) { return (xy; if (y < 0 && l->dy > 0) return false; if (y > 0 && l->dy < 0) return false; if (abs(y) > abs(l->dy)) return false; if (l->dy != 0) *x = l->x + (y * l->dx) / l->dy; else if (y==0) *x = l->x + l->dx; else return false; return true; } void fe_display_triangle(const fe_triangle * face) { // backface culling if (is_colckwised(face) != face->clockwised) return; // incomplete clipping if (face->s1->x < 0 && face->s2->x < 0 && face->s3->x < 0) return; if (face->s1->x >= fe_width && face->s2->x >= fe_width && face->s3->x >= fe_width) return; if (face->s1->y < 0 && face->s2->y < 0 && face->s3->y < 0) return; if (face->s1->y >= fe_height && face->s2->y >= fe_height && face->s3->y >= fe_height) return; if (face->s1->z <= 0 && face->s2->z <= 0 && face->s3->z <= 0) return; line cotes[3]; line_set(&cotes[0], face->s1, face->s2); line_set(&cotes[1], face->s1, face->s3); line_set(&cotes[2], face->s2, face->s3); if (cotes[0].no_line || cotes[1].no_line || cotes[2].no_line) return; const int32_t ymin = max(min(face->s1->y, min(face->s2->y, face->s3->y)), 0); const int32_t ymax = min(max(face->s1->y, max(face->s2->y, face->s3->y)), 63); const int32_t xAB = face->s2->x - face->s1->x, yAB = face->s2->y - face->s1->y, zAB=face->s2->z-face->s1->z; const int32_t xAC = face->s3->x - face->s1->x, yAC = face->s3->y - face->s1->y, zAC=face->s3->z-face->s1->z; const int32_t diviseur_commun = (xAB * yAC - yAB * xAC); const int32_t fact_1= (32768 * yAC) / diviseur_commun, fact_2 = (32768 * xAC) / diviseur_commun; const int32_t fact_3= (32768 * xAB) / diviseur_commun, fact_4 = (32768 * yAB) / diviseur_commun; for (int32_t y = ymin; y <= ymax; y++) { // xmin and xmax determination int32_t tx1,tx2; for (int t=0;t<3;t++) { if (line_get_x(y,&cotes[t],&tx1)) break; } for (int32_t t=0;t<3;t++) { if (line_get_x(y,&cotes[t],&tx2) && tx1!=tx2) break; } const int32_t txmin=max(min(tx1,tx2),0), txmax=min(max(tx1,tx2),127); for (int32_t x=txmin; x<=txmax; x++) { int32_t vx, vy, z; const int32_t xcalc = x - face->s1->x, ycalc = y - face->s1->y; // calcul de vx, vy vx = (xcalc*fact_1 - ycalc*fact_2); vy = (ycalc*fact_3 - xcalc*fact_4); z = face->s1->z + (vx * zAB + vy * zAC)/32768; int32_t vx2= ( vx*face->texture->size_px_x/face->s2->z ) / ((32768-vx)/face->s1->z + vx/face->s2->z); int32_t vy2= ( vy*face->texture->size_px_y/face->s3->z ) / ((32768-vy)/face->s1->z + vy/face->s3->z); /* Perspective correction vx /= (double) face->s2->z / ((1 - vx) / face->s1->z + vx / (double) face->s2->z); vy /= (double) face->s3->z / ((1 - vy) / face->s1->z + vy / (double) face->s3->z); */ // Affichage du point const uint8_t color = fe_texture_get_pixel_r(face->texture, vx2, vy2); if (color >> 1) { //dpixel(x,y, C_BLACK); if (fe_zbuffer_set_px(x,y,z)) dpixel(x, y, 3 * (color % 2)); // 3* means cast to black and white, and vx,and vy casted between 0 and 7 } } } }