Computação Gráfica Interativa - Gattass 2000.03.25 Rasterização de linhas e polígonos Algoritmos de rasterização de linhas Suponha Suponha ∆x ∆x>>∆y ∆y incrementa x e vê o que acontece com y ∆x = 5, ∆y =3 incrementa y e vê o que acontece com x Rasterização de Primitivas 1 Computação Gráfica Interativa - Gattass 2000.03.25 Algoritmo simples de linha (no primeiro octante) yi = m xi + b onde: m = ∆y/∆x b = y1 - m x1 void Line(int x1, int y1, int x2, int y2, int color) { float m = (y2-y1)/(x2-x1); float b = y1 - m*x1; float y; SetPixel(x1,y1, color); y = y1; while( x1 < x2 ) { x1++; y = m*x1 + b; SetPixel(x1,ROUND(y), color); } } Algoritmo de linha incremental Se xi+1 = xi + 1 então yi+1 = yi + ∆y/∆x void LineDDA(int x1, int y1, int x2, int y2, int color) { float y; float m = (y2-y1)/(x2-x1); SetPixel(x1,y1, c); y = y1; while( x1 < x2 ) { x1++; y += m; SetPixel(x1,ROUND(y), c); } } Rasterização de Primitivas 2 Computação Gráfica Interativa - Gattass 2000.03.25 Algoritmo de linha baseado no erro void BresLine0(int x1, int y1, int x2, int y2, int c) { int Dx = x2 - x2; int Dy = y2 - y1; float e= -0.5; SetPixel(x1, y1, c); erro de manter y - 0.5 0.5 while( x1 < x2 ) { x1++; e+=Dy/Dx; x if (e>=0) { y1++ ; e -= 1; } - 0.5 0.5 e = erro - 0.5 x SetPixel(x1, y1, c); } } Algoritmo de Bresenham ei = 2*Dx*e void voidBresLine0(int BresLine0(intx1, x1,int inty1, y1, int int x2, x2,int inty2, y2,int intc)c) {{ int int Dx Dx==x2 x2- -x1; x1; int int Dy Dy==y2 y2- -y1; y1; float e= -0.5; float e= -0.5; void voidBresLine1(int BresLine1(intx1, x1,int inty1, y1, int int x2, x2,int inty2, y2,int intc)c) {{ int int Dx Dx==x2 x2- -x1; x1; int int Dy Dy==y2 y2- -y1; y1; int ei = -Dx; int ei = -Dx; SetPixel(x1, SetPixel(x1,y1, y1,c); c); SetPixel(x1, SetPixel(x1,y1, y1,c); c); while( while(x1 x1<<x2 x2) ) {{ x1++; x1++; e+=Dy/Dx; e+=Dy/Dx; while( while(x1 x1<<x2 x2) ) {{ x1++; x1++; eiei+= +=2*Dy; 2*Dy; }} ifif(e>=0) (e>=0){{ y1++ y1++; ; ee-= -=1;1; }} ifif(ei>=0) (ei>=0){{ y1++ y1++; ; eiei-= -=2*Dx; 2*Dx; }} SetPixel(x1, SetPixel(x1,y1, y1,c); c); }} SetPixel(x1, SetPixel(x1,y1, y1,c); c); }} }} válidos somente quando Dx>Dy, x2 > x1 e y2 > y1 Rasterização de Primitivas 3 Computação Gráfica Interativa - Gattass 2000.03.25 Equação implícita da reta y y= F ( x, y) < 0 dy x+B dx y2 F ( x, y) > 0 y1 n = (dy x1 − dx ) x x2 F ( x , y ) = dy. x − dx. y + B. dx = 0 F ( x , y ) = a . x + b. y + c NE yp+ 1/2 M yp E xp xp+1 xp+2 Algoritmo do ponto médio - variável de decisão MNE yp+3/2 NE yp+1/2 M yp ME > 0 → escolha NE F( M) = ≤ 0 → escolha E E xp xp+1 d = F ( x p + 1, y p + xp+2 1 2) d new = F ( x p + 2 , y p + 1 E = a ( x p + 1) + b ( y p + 2) 1 = a (x p + 2) + b( y p + d new = d old + a d new = F ( x p + 2 , y p + NE Rasterização de Primitivas 3 2) 1 +c 2) +c ∆E = a = a (x p + 2) + b( y p + d n e w = d old + a + b 2) 3 2) +c ∆ NE = a + b 4 Computação Gráfica Interativa - Gattass 2000.03.25 Algoritimo do ponto médio - redução para inteiros d start = F ( x 0 + 1, y 0 + 1 2) = a ( x 0 + 1) + b ( y 0 + 1 2) +c d start = F ( x0 , y 0 ) + a + b / 2 = a + b / 2 ∆E = a ∆ NE = a + b d = 2. F ( x , y ) d start = 2. a + b ∆ E = 2a ∆ NE = 2(a + b ) Algoritimo do ponto médio - código C void MidpointLine(int x0, int y0, int x1, int y1, { int dx = x1-x0; int dy = y1-y0; int d=2*dy-dx; /* Valor inicial da var. int incrE = 2*dy; /* incremento p/ mover int incrNE = 2*(dy-dx); /* incremento p/ mover int x=x0; int y=y0; Pixel(x,y,fgcolor); /* Primeiro pixel */ int color) decisao */ E */ NE */ while (x<xl) { if (d<=0) { /* Escolha E */ d+=incrE; x++; } else { /* Escolha NE */ d+=incrNE; x++; y++; } Pixel(x,y,color); } /* while */ } /* MidpointLine */ Rasterização de Primitivas 5 Computação Gráfica Interativa - Gattass 2000.03.25 Estilos de linha void MidpointLine(int x0, int y0, int x1, int y1, { int dx = x1-x0; int dy = y1-y0; int d=2*dy-dx; /* Valor inicial da var. int incrE = 2*dy; /* incremento p/ mover int incrNE = 2*(dy-dx); /* incremento p/ mover int x=x0; int y=y0; int color) decisao */ E */ NE */ int style[8]={1,1,0,0,1,1,0,0}; int k=1; Pixel(x,y,fgcolor)} while (x<xl) { if (d<=0) { /* Escolha E */ d+=incrE; x++; } else { /* Escolha NE */ d+=incrNE; x++; y++; } if (style[(++k)%8]) Pixel(x,y,color); } /* while */ } /* MidpointLine */ Rasterização de Retas -caso geraly 1 2 2 y 1 x orientação x outros quadrantes Rasterização de Primitivas 6 Computação Gráfica Interativa - Gattass 2000.03.25 Rasterização de Cônicas y ∇F = F(x,y) = 0 ∂F ∂x ∂F ∂y x 450 y simetrias do círculo: cada ponto calculado define 8 pixels x Rasterização de Cônicas y y=raio; for (x=0; x< y; x++) { if F(M)<0 escolha E else escolha SE Pixel (E ou SE) pinte os simétricos } x E ME M SE Rasterização de Primitivas F(x,y) = 0 MSE 7 Computação Gráfica Interativa - Gattass 2000.03.25 Preenchimento de polígonos dados: dados: {x , x {x00, x11, ,xx22, ,xx3,3,xx4}4} {y {y00, ,yy11, ,yy22, ,yy3,3,yy4}4} y ymax 1 4 i1 ys i0 i4 i3 acha ey achayymax max e ymin min 0 ymin Para ∈∈ [y[ymax , ,yymin]] Paracada cadays∈ ys∈ max min Para Paracada cadaaresta aresta 2 3 0 xi1 xi0 xi4 xi3 vx= vx={x {xi1i1, ,xxi0i0, ,xxi4i4, ,xxi3i3}} calcula calculaas asinterseções interseções x ordena ordenainterseções interseções desenha desenhalinhas linhashorizontais horizontais Preenchimento de polígonos (scan passando por vértices) y 1 ys i0 0 i4 5 i3 i1 i2 3 2 4 0 x inclui incluivértices: vértices: i0-i1, i0-i1,i2-i3, i2-i3,i4-? i4-? não nãoinclui incluivértices: vértices: i0-? i0-? y y 1 ys i0 i1 i2 3 0 1 i4 i3 5 ys 3 L 2 4 4 Rasterização de Primitivas 5 L 2 0 0 i0 x 0 x 8 Computação Gráfica Interativa - Gattass 2000.03.25 Interseção nos vértices só sóinclui incluivértices vérticesde demenor menory:y: ou i0-i4 J i0-i4 só sóinclui incluivértices vérticesde demaior maiory:y: J i0-i1, i0-i1,i2-i3 i2-i3 reta retahorizontal horizontalnão nãoproduz produzinterseção interseção Algoritmo de Fill void FillPolygon (int np, int *x, int *y) { /* declarações */ . . . /* calcula y max e min dos vértices*/ . . . for(ys=ymim; ys<=ymax; ys--) /* para cada linha de scan */ { num_inters = 0; for(i=0; i<np; i++) /* para cada aresta */ { yi = y[i]; yf = y[(i+1)%np]; if (yi!=yf && ys >= MIN(yi,yf) && ys < MAX(yi,yf) ) { vxs[num_inters] = x[i] + (ys-yi)*(x[(i+1)%np]-x[i])/(yf-yi); num_inters++; } } ordena(vxs,0,num_inters-1); for (i=0;i<num_inters;i+=2) if (vxs[i]+1 <= vxs[i+1]) /* ordena as interseções */ ScanLine(vxs[i],vxs[i+1],ys); } Rasterização de Primitivas 9 Computação Gráfica Interativa - Gattass 2000.03.25 Otimizações do algoritmo de fill y ymax xx==x+dx x+dx ys+1 ys dy = 1 ymin x0 Lista de Arestas x1 x (ou z) dx = (x1-x0)/(ymax-ymin) struct edge { int y_max; int y_min; float xs; /* maior y da aresta */ /* menor y da aresta */ /* x correspondente a ys */ /* (no início é o correspondente a y_max) */ float delta_xs; /* incremento de xs entre duas linhas de scan */ }; Algoritmo de Fill de Polígonos (Parte 1-Alocação de Memória) #define Max(a,b) #define Min(a,b) (((a) > (b)) ? (a) : (b)) (((a) < (b)) ? (a) : (b)) void fill (int np, int *x, int *y) { static struct edge *aresta=NULL; /* vetor de arestas */ static int *vxs=NULL; /* vetor de interseções */ static int old_np=0; /* número de pontos da última chamada */ int int int int int ymax, ymin; num_inters; num_arestas; ys; i; /* /* /* /* limites do polígono */ num. de interseções */ num. de arestas */ ordenada da reta de scan */ /* realoca os vetores de arestas e de interseções */ if (np > old_np) { old_np=np; if (vxs) free (vxs); if (aresta) free (aresta); vxs=(int *) malloc ((np-1)*sizeof(int)); /* max num. De inters.*/ aresta=(struct edge *) malloc (np*sizeof(struct edge)); } /* CONTINUA NA PARTE 2 */ Rasterização de Primitivas 10 Computação Gráfica Interativa - Gattass 2000.03.25 Algoritmo de Fill de Polígonos (Parte 2-Lista de Arestas) /* PARTE 1*/ /* calcula y max e min e monta o vetor de arestas */ ymax = y[0]; ymin = y[0]; num_arestas = 0; for(i=0;i<np;i++) { int i1=(i+1)%np; if (y[i] != y[i1]) { aresta[num_arestas].y_max = Max(y[i],y[i1]); aresta[num_arestas].y_min = Min(y[i],y[i1]); aresta[num_arestas].delta = ((float)(x[i1]-x[i])/ (float)(y[i1]-y[i])); if (aresta[num_arestas].y_mim == y[i]) aresta[num_arestas].xs = x[i]; else aresta[num_arestas].xa = x[i1]; if (aresta[num_arestas].y_max > ymax) ymax = aresta[num_arestas].y_max; if (aresta[num_arestas].y_min < ymin) ymin = aresta[num_arestas].y_min; num_arestas++; } } /* CONTINUA NA PARTE 3 */ Algoritmo de Fill de Polígonos (Parte 3-Varredura) /* PARTES 1 E 2 */ for(ys=ymin; ys<ymax; ys++) /* para cada linha de scan */ { num_inters = 0; for(i=0; i<num_arestas; i++) { if (aresta[i].y_max < ys){ /* retira da lista de arestas */ aresta[i] = aresta[num_arestas-1]; num_arestas--; } if((ys>=aresta[i].y_min)&&(ys<aresta[i].y_max)){ /* intersepta */ vxs[num_inters] = aresta[i].xs; aresta[i].xs += aresta[i].delta; /* atualiza o xs */ num_inters++; } } /* for */ ordena(vxs,0,num_inters-1); for(i=0;i<num_inters;i+=2) if (vxs[i]+1 <= vxs[i+1]) } } /* fill */ /* ordena as interseções */ hline(vxs[i],vxs[i+1],ys,0xff); /* FIM */ Rasterização de Primitivas 11 Computação Gráfica Interativa - Gattass 2000.03.25 Ordenação no Algoritmo de Fill static void ordena(int *vxs, int left, int right) { int i,j; int a; i = left; j = right; a = vxs[(left + right)/2]; do { while (vxs[i] < a && i < right) i++; while (a < vxs[j] && j > left) j--; if (i<=j) { int b = vxs[i]; vxs[i] = vxs[j]; vxs[j] = b; i++;j--; } } while (i<=j); if (left < j) ordena(vxs,left,j); if (i < right) ordena(vxs,i,right); } Caso Particular: Triângulo y A c b B a C x Rasterização de Primitivas 12 Computação Gráfica Interativa - Gattass 2000.03.25 Stipples, patterns e imagens Stipple void SetPixel(int x,int y) { int i=(x-x0)%w; int j=(y-y0)%h; h=5 if (stipple[i][j]) { w=5 Pixel(x,y,foreground); } else { if (backopacity) Pixel(x,y,background); } } Pattern void SetPixel(int x,int y) { color = pattern[(x-x0)%w][(y-y0)%h] Pixel(x,y,color); } Rasterização de Primitivas 13