Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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;
- 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;
- }
- /* 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);
- /* ukazatel na studentsky renderer */
- S_StudentRenderer * renderer;
- renderer = (S_StudentRenderer *)pRenderer;
- /* index pixelu */
- int pixelIndex = x + y * pRenderer->frame_w;
- /* hodnota pixelu na danem indexu */
- int pixelValue = ivecGet(renderer->buffer1, pixelIndex);
- /* pokud je hodnota pixelu -1, tak vytvorim fragment a nenastavuji naslednika
- a nasledne index vytvoreneho fragmentu ulozim do HEAD_POINT_BUFFERU
- */
- if (pixelValue == -1)
- {
- S_Frag fragment = makeFrag((S_RGBA){ color.red, color.green, color.blue, color.alpha }, z, -1);
- int nextIndex = fragvecPushBack(renderer->buffer2, fragment);
- ivecSet(renderer->buffer1, pixelIndex, nextIndex);
- }
- /* pokud je hodnota jina nez -1 tak vytvorim fragment a jako naslednika dam nasledujici pixel
- nasledne ulozim index vytvoreneho fragmentu do HEAD_POINT_BUFFERU
- */
- else
- {
- int pixelValue = ivecGet(renderer->buffer1, pixelIndex);
- S_Frag fragment = makeFrag((S_RGBA){ color.red, color.green, color.blue, color.alpha }, z, pixelValue);
- int nextIndex = fragvecPushBack(renderer->buffer2, fragment);
- ivecSet(renderer->buffer1, pixelIndex, nextIndex);
- }
- }
- /* hranova fce o pixel vedle */
- e1 += a1;
- e2 += a2;
- e3 += a3;
- }
- }
- }
- void studrenProjectTriangle(S_Renderer *pRenderer, S_Model *pModel, int i)
- {
- /* zaklad fce zkopirujte z render.c */
- /* ??? */
- S_Coords aa, bb, cc; /* souradnice vrcholu po transformaci */
- S_Coords naa, nbb, ncc; /* normaly ve vrcholech po transformaci */
- S_Coords nn; /* normala trojuhelniku po transformaci */
- int u1, v1, u2, v2, u3, v3; /* souradnice vrcholu po projekci do roviny obrazovky */
- S_Triangle * triangle;
- IZG_ASSERT(pRenderer && pModel && i >= 0 && i < trivecSize(pModel->triangles));
- /* z modelu si vytahneme trojuhelnik */
- triangle = trivecGetPtr(pModel->triangles, i);
- /* transformace vrcholu matici model */
- trTransformVertex(&aa, cvecGetPtr(pModel->vertices, triangle->v[0]));
- trTransformVertex(&bb, cvecGetPtr(pModel->vertices, triangle->v[1]));
- trTransformVertex(&cc, cvecGetPtr(pModel->vertices, triangle->v[2]));
- /* promitneme vrcholy trojuhelniku na obrazovku */
- trProjectVertex(&u1, &v1, &aa);
- trProjectVertex(&u2, &v2, &bb);
- trProjectVertex(&u3, &v3, &cc);
- /* pro osvetlovaci model transformujeme take normaly ve vrcholech */
- trTransformVector(&naa, cvecGetPtr(pModel->normals, triangle->v[0]));
- trTransformVector(&nbb, cvecGetPtr(pModel->normals, triangle->v[1]));
- trTransformVector(&ncc, cvecGetPtr(pModel->normals, triangle->v[2]));
- /* normalizace normal */
- coordsNormalize(&naa);
- coordsNormalize(&nbb);
- coordsNormalize(&ncc);
- /* transformace normaly trojuhelniku matici model */
- trTransformVector(&nn, cvecGetPtr(pModel->trinormals, triangle->n));
- /* normalizace normaly */
- coordsNormalize(&nn);
- /* rasterizace trojuhelniku - zavolam svou funci*/
- studrenDrawTriangle(pRenderer,
- &aa, &bb, &cc,
- &naa, &nbb, &ncc,
- u1, v1, u2, v2, u3, v3
- );
- }
- void renderStudentScene(S_Renderer *pRenderer, S_Model *pModel)
- {
- S_Matrix backup;
- /*####################################################################
- ######################################################################
- cerveny kralik
- ######################################################################
- ####################################################################*/
- /* test existence frame bufferu a modelu */
- IZG_ASSERT(pModel && pRenderer);
- /* nastavit projekcni matici */
- trProjectionPerspective(pRenderer->camera_dist, pRenderer->frame_w, pRenderer->frame_h);
- /* vycistit model matici */
- trLoadIdentity();
- trGetMatrix(&backup);
- /* nejprve nastavime posuv cele sceny od/ke kamere */
- trTranslate(0.0, 0.0, pRenderer->scene_move_z);
- /* nejprve nastavime posuv cele sceny v rovine XY */
- trTranslate(pRenderer->scene_move_x, pRenderer->scene_move_y, 0.0);
- /* natoceni cele sceny - jen ve dvou smerech - mys je jen 2D... :( */
- trRotateX(pRenderer->scene_rot_x);
- trRotateY(pRenderer->scene_rot_y);
- trTranslate(pRenderer->scene_move_x - 1.3, 0.0, 0.0);
- /* nastavime material */
- renMatAmbient(pRenderer, &MAT_RED_AMBIENT);
- renMatDiffuse(pRenderer, &MAT_RED_DIFFUSE);
- renMatSpecular(pRenderer, &MAT_RED_SPECULAR);
- /* a vykreslime nas model */
- renderModel(pRenderer, pModel);
- /*####################################################################
- ######################################################################
- zeleny kralik
- ######################################################################
- ####################################################################*/
- /* nejprve nastavime posuv cele sceny od/ke kamere */
- trSetMatrix(&backup);
- trTranslate(0.0, 0.0, pRenderer->scene_move_z);
- /* nejprve nastavime posuv cele sceny v rovine XY */
- trTranslate(pRenderer->scene_move_x, pRenderer->scene_move_y, 0.0);
- /* natoceni cele sceny - jen ve dvou smerech - mys je jen 2D... :( */
- trRotateX(pRenderer->scene_rot_x);
- trRotateY(pRenderer->scene_rot_y);
- trTranslate(pRenderer->scene_move_x + 1.3, 0.0, 0.0);
- /* nastavime material */
- renMatAmbient(pRenderer, &MAT_STUD_AMBIENT);
- renMatDiffuse(pRenderer, &MAT_STUD_DIFFUSE);
- renMatSpecular(pRenderer, &MAT_STUD_SPECULAR);
- /* a vykreslime nas model */
- renderModel(pRenderer, pModel);
- S_StudentRenderer * renderer;
- renderer = (S_StudentRenderer *)pRenderer;
- S_RGBA dst;
- dst.red = 0;
- dst.green = 0;
- dst.blue = 0;
- dst.alpha = 0;
- for (int i = 0; i < fragvecSize(renderer->buffer1); i++){
- S_RGBA src = fragvecGetPtr(renderer->buffer1, i)->color;
- float Asrc = src.alpha / 255.0;
- dst.red += src.alpha*src.red;
- dst.green += src.alpha*src.green;
- dst.blue += src.alpha*src.blue;
- dst.alpha *= 1 - Asrc;
- }
- renderModel(renderer, pModel);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement