void studrenDrawTriangle(S_Renderer *pRenderer, S_Coords *v1, S_Coords *v2, S_Coords *v3, S_Coords *n1, S_Coords *n2, S_Coords *n3, int x1, int y1, int x2, int y2, int x3, int y3 ) { /* zaklad fce zkopirujte z render.c */ /* ??? */ int minx, miny, maxx, maxy; int a1, a2, a3, b1, b2, b3, c1, c2, c3; int /*s1,*/ s2, s3; int x, y, e1, e2, e3; double alpha, beta, w1, w2, w3, z; S_RGBA col1, col2, col3, color; S_StudentRenderer * renderer; S_Frag * tmpFrag; int next = 0; int i = 0; IZG_ASSERT(pRenderer && v1 && v2 && v3 && n1 && n2 && n3); renderer = (S_StudentRenderer *)pRenderer; /* vypocet barev ve vrcholech */ col1 = pRenderer->calcReflectanceFunc(pRenderer, v1, n1); col2 = pRenderer->calcReflectanceFunc(pRenderer, v2, n2); col3 = pRenderer->calcReflectanceFunc(pRenderer, v3, n3); /* obalka trojuhleniku */ minx = MIN(x1, MIN(x2, x3)); maxx = MAX(x1, MAX(x2, x3)); miny = MIN(y1, MIN(y2, y3)); maxy = MAX(y1, MAX(y2, y3)); /* oriznuti podle rozmeru okna */ miny = MAX(miny, 0); maxy = MIN(maxy, pRenderer->frame_h - 1); minx = MAX(minx, 0); maxx = MIN(maxx, pRenderer->frame_w - 1); /* vektory urcene vrcholy 1-2 a 1-3 */ a1 = x2 - x1; a3 = x3 - x1; b1 = y2 - y1; b3 = y3 - y1; /* overeni counterclockwise orientace troj. pomoci vektoroveho soucinu */ if( (a1 * b3 - b1 * a3) < 0 ) { /* spatna orientace -> prohodime vrcholy 2 a 3 */ SWAP(x2, x3); SWAP(y2, y3); /* a take barvy vrcholu */ SWAP(col2.red, col3.red); SWAP(col2.green, col3.green); SWAP(col2.blue, col3.blue); SWAP(col2.alpha, col3.alpha); } /* Pineduv alg. rasterizace troj. hranova fce je obecna rovnice primky Ax + By + C = 0 primku prochazejici body (x1, y1) a (x2, y2) urcime jako (y1 - y2)x + (x2 - x1)y + x1y2 - x2y1 = 0 */ /* normala primek - vektor kolmy k vektoru mezi dvema vrcholy, tedy (-dy, dx) */ a1 = y1 - y2; a2 = y2 - y3; a3 = y3 - y1; b1 = x2 - x1; b2 = x3 - x2; b3 = x1 - x3; /* koeficient C */ c1 = x1 * y2 - x2 * y1; c2 = x2 * y3 - x3 * y2; c3 = x3 * y1 - x1 * y3; /* vypocet hranove fce (vzdalenost od primky) pro protejsi body */ /*s1 = a1 * x3 + b1 * y3 + c1;*/ s2 = a2 * x1 + b2 * y1 + c2; s3 = a3 * x2 + b3 * y2 + c3; /* uprava koeficientu C pro korektni vyplnovani, viz "OpenGL top-left rule" */ /* https://books.google.cz/books?id=3ljRBQAAQBAJ&pg=PA73 */ if( (y1 == y2 && x2 > x1) || y2 < y1 ) { c1 -= 1; } if( (y2 == y3 && x3 > x2) || y3 < y2 ) { c2 -= 1; } if( (y3 == y1 && x1 > x3) || y1 < y3 ) { c3 -= 1; } /* koeficienty pro barycentricke souradnice */ alpha = 1.0 / (ABS(s2) + 1); beta = 1.0 / (ABS(s3) + 1); /* vyplnovani... */ for( y = miny; y <= maxy; ++y ) { /* inicilizace hranove fce v bode (minx, y) */ e1 = a1 * minx + b1 * y + c1; e2 = a2 * minx + b2 * y + c2; e3 = a3 * minx + b3 * y + c3; for( x = minx; x <= maxx; ++x ) { if( e1 >= 0 && e2 >= 0 && e3 >= 0 ) { /* interpolace pomoci barycentrickych souradnic e1, e2, e3 je aktualni vzdalenost bodu (x, y) od primek */ w1 = alpha * e2; w2 = beta * e3; w3 = 1.0 - w1 - w2; /* interpolace z-souradnice */ z = w1 * v1->z + w2 * v2->z + w3 * v3->z; /* interpolace barvy */ color.red = ROUND2BYTE(w1 * col1.red + w2 * col2.red + w3 * col3.red); color.green = ROUND2BYTE(w1 * col1.green + w2 * col2.green + w3 * col3.green); color.blue = ROUND2BYTE(w1 * col1.blue + w2 * col2.blue + w3 * col3.blue); color.alpha = ROUND2BYTE(w1 * col1.alpha + w2 * col2.alpha + w3 * col3.alpha); // vykresleni bodu i = y * pRenderer->frame_w + x; next = renderer->hBuffer[i]; if (next == -1) renderer->hBuffer[i] = fragvecPushBack(renderer->nBuffer, makeFrag(color, z, -1)); else if(fragvecGetPtr(renderer->nBuffer, next)->depth > z) renderer->hBuffer[i] = fragvecPushBack(renderer->nBuffer, makeFrag(color, z, next)); else { // razeni fragmetu tmpFrag = fragvecGetPtr(renderer->nBuffer, next); while (tmpFrag->depth > z) tmpFrag = fragvecGetPtr(renderer->nBuffer, tmpFrag->next); fragvecGetPtr(renderer->nBuffer, next)->next = fragvecPushBack(renderer->nBuffer, makeFrag(color, z, tmpFrag->next)); } } /* hranova fce o pixel vedle */ e1 += a1; e2 += a2; e3 += a3; } } }
void studrenDrawTriangle(S_Renderer *pRenderer, S_Coords *v1, S_Coords *v2, S_Coords *v3, S_Coords *n1, S_Coords *n2, S_Coords *n3, int x1, int y1, int x2, int y2, int x3, int y3 ) { S_StudentRenderer * renderer; /* ukazatel na studentsky renderer */ renderer = (S_StudentRenderer *)pRenderer; int minx, miny, maxx, maxy; int a1, a2, a3, b1, b2, b3, c1, c2, c3; int /*s1,*/ s2, s3; int x, y, e1, e2, e3; double alpha, beta, w1, w2, w3, z; S_RGBA col1, col2, col3, color; IZG_ASSERT(pRenderer && v1 && v2 && v3 && n1 && n2 && n3); /* vypocet barev ve vrcholech */ col1 = pRenderer->calcReflectanceFunc(pRenderer, v1, n1); col2 = pRenderer->calcReflectanceFunc(pRenderer, v2, n2); col3 = pRenderer->calcReflectanceFunc(pRenderer, v3, n3); /* obalka trojuhleniku */ minx = MIN(x1, MIN(x2, x3)); maxx = MAX(x1, MAX(x2, x3)); miny = MIN(y1, MIN(y2, y3)); maxy = MAX(y1, MAX(y2, y3)); /* oriznuti podle rozmeru okna */ miny = MAX(miny, 0); maxy = MIN(maxy, pRenderer->frame_h - 1); minx = MAX(minx, 0); maxx = MIN(maxx, pRenderer->frame_w - 1); /* vektory urcene vrcholy 1-2 a 1-3 */ a1 = x2 - x1; a3 = x3 - x1; b1 = y2 - y1; b3 = y3 - y1; /* overeni counterclockwise orientace troj. pomoci vektoroveho soucinu */ if ((a1 * b3 - b1 * a3) < 0) { /* spatna orientace -> prohodime vrcholy 2 a 3 */ SWAP(x2, x3); SWAP(y2, y3); /* a take barvy vrcholu */ SWAP(col2.red, col3.red); SWAP(col2.green, col3.green); SWAP(col2.blue, col3.blue); SWAP(col2.alpha, col3.alpha); } /* Pineduv alg. rasterizace troj. hranova fce je obecna rovnice primky Ax + By + C = 0 primku prochazejici body (x1, y1) a (x2, y2) urcime jako (y1 - y2)x + (x2 - x1)y + x1y2 - x2y1 = 0 */ /* normala primek - vektor kolmy k vektoru mezi dvema vrcholy, tedy (-dy, dx) */ a1 = y1 - y2; a2 = y2 - y3; a3 = y3 - y1; b1 = x2 - x1; b2 = x3 - x2; b3 = x1 - x3; /* koeficient C */ c1 = x1 * y2 - x2 * y1; c2 = x2 * y3 - x3 * y2; c3 = x3 * y1 - x1 * y3; /* vypocet hranove fce (vzdalenost od primky) pro protejsi body */ /*s1 = a1 * x3 + b1 * y3 + c1;*/ s2 = a2 * x1 + b2 * y1 + c2; s3 = a3 * x2 + b3 * y2 + c3; /* uprava koeficientu C pro korektni vyplnovani, viz "OpenGL top-left rule" */ /* https://books.google.cz/books?id=3ljRBQAAQBAJ&pg=PA73 */ if ((y1 == y2 && x2 > x1) || y2 < y1) { c1 -= 1; } if ((y2 == y3 && x3 > x2) || y3 < y2) { c2 -= 1; } if ((y3 == y1 && x1 > x3) || y1 < y3) { c3 -= 1; } // moje deklarace int * index; S_Frag tmp_frag; /* koeficienty pro barycentricke souradnice */ alpha = 1.0 / (ABS(s2) + 1); beta = 1.0 / (ABS(s3) + 1); /* vyplnovani... */ for (y = miny; y <= maxy; ++y) { /* inicilizace hranove fce v bode (minx, y) */ e1 = a1 * minx + b1 * y + c1; e2 = a2 * minx + b2 * y + c2; e3 = a3 * minx + b3 * y + c3; for (x = minx; x <= maxx; ++x) { if (e1 >= 0 && e2 >= 0 && e3 >= 0) { /* interpolace pomoci barycentrickych souradnic e1, e2, e3 je aktualni vzdalenost bodu (x, y) od primek */ w1 = alpha * e2; w2 = beta * e3; w3 = 1.0 - w1 - w2; /* interpolace z-souradnice */ z = w1 * v1->z + w2 * v2->z + w3 * v3->z; /* interpolace barvy */ color.red = ROUND2BYTE(w1 * col1.red + w2 * col2.red + w3 * col3.red); color.green = ROUND2BYTE(w1 * col1.green + w2 * col2.green + w3 * col3.green); color.blue = ROUND2BYTE(w1 * col1.blue + w2 * col2.blue + w3 * col3.blue); color.alpha = ROUND2BYTE(w1 * col1.alpha + w2 * col2.alpha + w3 * col3.alpha); /* vykresleni bodu */ if (z < DEPTH(pRenderer, x, y)) { /*PIXEL(pRenderer, x, y) = color; DEPTH(pRenderer, x, y) = z;*/ index = (int *)vecGetPtr(renderer->vecHeadBuff, y * renderer->base.frame_w + x); //tmp_index = *index; tmp_frag = makeFrag(color, z, *index); *index = fragvecPushBack(renderer->vecNodeBuff, tmp_frag); //printf("%d\n", fragvecGetPtr(renderer->vecNodeBuff, 0)->next); } } /* hranova fce o pixel vedle */ e1 += a1; e2 += a2; e3 += a3; } } /* Razeni a pocitani vyslednych barev */ // deklarace pro sorting int sortStart, sortIndex; int myDepth; // michani barev S_RGBA mixColor; double col_R, col_G, col_B, col_A; double aSrc; // pomocne fragmenty S_Frag * pattern; S_Frag myFragTMP; S_Frag * myFragment; // pruchod pro razeni for (y = miny; y <= maxy; ++y) { for (x = minx; x <= maxx; ++x) { // index byl deklarovan uz vyse index = (int *)(vecGetPtr(renderer->vecHeadBuff, y * renderer->base.frame_w + x)); if (*index != -1) { sortStart = *index; /* K razeni je pouzit radici algoritmus Select Sort */ while ((myFragment = fragvecGetPtr(renderer->vecNodeBuff, sortStart))->next != -1) { sortStart = myFragment->next; sortIndex = myFragment->next; // dokud se neprojde "pole" na sebe navazujicich(indexujicich) prvku while (sortIndex != -1) { pattern = fragvecGetPtr(renderer->vecNodeBuff, sortIndex); // dojde k prohozeni hodnot, najde-li se mensi hloubka if (pattern->depth < myFragment->depth) { myFragTMP.depth = myFragment->depth; myFragTMP.color = myFragment->color; myFragment->depth = pattern->depth; myFragment->color = pattern->color; pattern->depth = myFragTMP.depth; pattern->color = myFragTMP.color; } sortIndex = pattern->next; } } } } } // pruchod pro michani barev for (y = miny; y <= maxy; ++y) { for (x = minx; x <= maxx; ++x) { // index byl deklarovan uz vyse index = (int *)(vecGetPtr(renderer->vecHeadBuff, y * renderer->base.frame_w + x)); if (*index != -1) { sortStart = *index; // michani barvy myDepth = 0; col_R = 0.0; col_G = 0.0; col_B = 0.0; col_A = 1.0; while (sortStart != -1) { pattern = fragvecGetPtr(renderer->vecNodeBuff, sortStart); aSrc = pattern->color.alpha / 255.0; col_R = col_A * pattern->color.red + col_R; col_G = col_A * pattern->color.green + col_G; col_B = col_A * pattern->color.blue + col_B; col_A = (1.0 - aSrc) * col_A; sortStart = pattern->next; } mixColor.alpha = 255; mixColor.red = ROUND2BYTE(col_R); mixColor.green = ROUND2BYTE(col_G); mixColor.blue = ROUND2BYTE(col_B); PIXEL(pRenderer, x, y) = mixColor; DEPTH(pRenderer, x, y) = myDepth; } } } }