Trois solutions sont proposées:
- Parcours simple du bord (problème possible au cas où l'onsouhaite dessiner deux facettes ayant un coté commun:
pixels non tracé)
- Parcours du bord de manière que chaque coté soit toujours parcouru dans le même sens (recollage possible de deux
facettes ayant un bord en commun)
- Prétraitement pour déterminer et extraire les bords gauche et droit (dessin de tous les pixels obtenus par traçage
des cotés de la facette)
Solution 1: Le bord n'est pas entièrement recouvert.
Solution 1: Des trous peuvent apparaître entre facettes adjacentes.
Solution 2: Plus de trou entre facettes adjacentes
Solution 3: Les cotés sont entièrement recouverts.
Solution 3: Les cotés sont entièrement recouverts.
Fichier source : RemplissageTriangle.cpp
/* Remplissage 2D d'un triangle */
/* Solution imparfaite car presentant */
/* des problemes lors du collage */
/* deux facettes adjacentes: */
/* Apparition possible de trous car des pixels */
/* peuvent ne pas etre allumes a la limite */
/* entre les deux facettes car allumes */
/* pour aucune des deux facettes */
static void bord(int *px,Position3D *pi,Position3D *pf) {
int xi = pi->c[0];
int yi = pi->c[1];
int xf = pf->c[0];
int yf = pf->c[1];
int dx,dy,i,xinc,yinc,cumul,x,y;
x = xi;
y = yi;
dx = xf - xi;
dy = yf - yi;
xinc = ( dx > 0 ) ? 1 : -1;
yinc = ( dy > 0 ) ? 1 : -1;
dx = abs(dx);
dy = abs(dy);
px[y] = x;
if ( dx > dy ) {
cumul = dx / 2;
for ( i = 1 ; i <= dx ; i++ ) {
x += xinc;
cumul += dy;
if ( cumul >= dx ) {
cumul -= dx;
y += yinc; }
px[y] = x; } }
else {
cumul = dy / 2;
for ( i = 1 ; i <= dy ; i++ ) {
y += yinc;
cumul += dx;
if ( cumul >= dy ) {
cumul -= dy;
x += xinc; }
px[y] = x; } }
}
static void remplissageTriangle1(Position3D *p1,Position3D *p2,Position3D *p3) {
int yi =(int) min(p1->c[1],min(p2->c[1],p3->c[1]));
int yf =(int) max(p1->c[1],max(p2->c[1],p3->c[1]));
int x1[4096];
int x2[4096];
if ( ( ( p1->c[1] == yi ) && ( p2->c[1] == yf ) ) ||
( ( p1->c[1] == yf ) && ( p2->c[1] == yi ) ) ) {
bord(x1,p1,p2);
bord(x2,p1,p3);
bord(x2,p2,p3); }
else
if ( ( ( p1->c[1] == yi ) && ( p3->c[1] == yf ) ) ||
( ( p1->c[1] == yf ) && ( p3->c[1] == yi ) ) ) {
bord(x1,p1,p3);
bord(x2,p1,p2);
bord(x2,p2,p3); }
else {
bord(x1,p2,p3);
bord(x2,p1,p2);
bord(x2,p1,p3); }
glPointSize(9.0F);
glBegin(GL_POINTS);
for ( int y = yi ; y <= yf ; y++ ) {
int xi = min(x1[y],x2[y]);
int xf = max(x1[y],x2[y]);
for ( int x = xi ; x <= xf ; x++ ) {
glVertex2i(x*11+4,y*11+4); } }
glEnd();
glPointSize(1.0F);
}
/* Remplissage 2D d'un triangle */
/* Resolution du probleme de collage */
/* de facettes adjacentes */
/* Determination de chaque bord de maniere */
/* que leurs extremites soient toujours */
/* considerees dans le meme ordre */
static void bordTri(int *px,Position3D *pi,Position3D *pf) {
if ( pi->c[0] > pf->c[0] ) {
Position3D *aux = pi;
pi = pf;
pf = aux; }
if ( ( pi->c[0] == pf->c[0] ) && ( pi->c[1] > pf->c[1] ) ) {
Position3D *aux = pi;
pi = pf;
pf = aux; }
int xi = pi->c[0];
int yi = pi->c[1];
int xf = pf->c[0];
int yf = pf->c[1];
int dx,dy,i,xinc,yinc,cumul,x,y;
x = xi;
y = yi;
dx = xf - xi;
dy = yf - yi;
xinc = ( dx > 0 ) ? 1 : -1;
yinc = ( dy > 0 ) ? 1 : -1;
dx = abs(dx);
dy = abs(dy);
px[y] = x;
if ( dx > dy ) {
cumul = dx / 2;
for ( i = 1 ; i <= dx ; i++ ) {
x += xinc;
cumul += dy;
if ( cumul >= dx ) {
cumul -= dx;
y += yinc; }
px[y] = x; } }
else {
cumul = dy / 2;
for ( i = 1 ; i <= dy ; i++ ) {
y += yinc;
cumul += dx;
if ( cumul >= dy ) {
cumul -= dy;
x += xinc; }
px[y] = x; } }
}
static void remplissageTriangle2(Position3D *p1,Position3D *p2,Position3D *p3) {
int yi =(int) min(p1->c[1],min(p2->c[1],p3->c[1]));
int yf =(int) max(p1->c[1],max(p2->c[1],p3->c[1]));
int x1[4096];
int x2[4096];
if ( ( ( p1->c[1] == yi ) && ( p2->c[1] == yf ) ) ||
( ( p1->c[1] == yf ) && ( p2->c[1] == yi ) ) ) {
bordTri(x1,p1,p2);
bordTri(x2,p1,p3);
bordTri(x2,p2,p3); }
else
if ( ( ( p1->c[1] == yi ) && ( p3->c[1] == yf ) ) ||
( ( p1->c[1] == yf ) && ( p3->c[1] == yi ) ) ) {
bordTri(x1,p1,p3);
bordTri(x2,p1,p2);
bordTri(x2,p2,p3); }
else {
bordTri(x1,p2,p3);
bordTri(x2,p1,p2);
bordTri(x2,p1,p3); }
glPointSize(9.0F);
glBegin(GL_POINTS);
for ( int y = yi ; y <= yf ; y++ ) {
int xi = min(x1[y],x2[y]);
int xf = max(x1[y],x2[y]);
for ( int x = xi ; x <= xf ; x++ ) {
glVertex2i(x*11+4,y*11+4); } }
glEnd();
glPointSize(1.0F);
}
/* Remplissage 2D d'un triangle */
/* Recouvrement avec les pixels du bord */
/* traces par l'algorithme de Bresenham */
/* Determination effective des bords */
/* droit et gauche */
static void bordDroit(int *px,Position3D *pi,Position3D *pf) {
int xi = pi->c[0];
int yi = pi->c[1];
int xf = pf->c[0];
int yf = pf->c[1];
int dx,dy,i,xinc,yinc,cumul,x,y;
x = xi;
y = yi;
dx = xf - xi;
dy = yf - yi;
xinc = ( dx > 0 ) ? 1 : -1;
yinc = ( dy > 0 ) ? 1 : -1;
dx = abs(dx);
dy = abs(dy);
px[y] = x;
if ( dx > dy ) {
cumul = dx / 2;
for ( i = 1 ; i <= dx ; i++ ) {
x += xinc;
cumul += dy;
if ( cumul >= dx ) {
cumul -= dx;
y += yinc; }
if ( x > px[y] )
px[y] = x; } }
else {
cumul = dy / 2;
for ( i = 1 ; i <= dy ; i++ ) {
y += yinc;
cumul += dx;
if ( cumul >= dy ) {
cumul -= dy;
x += xinc; }
if ( x > px[y] )
px[y] = x; } }
}
static void bordGauche(int *px,Position3D *pi,Position3D *pf) {
int xi = pi->c[0];
int yi = pi->c[1];
int xf = pf->c[0];
int yf = pf->c[1];
int dx,dy,i,xinc,yinc,cumul,x,y;
x = xi;
y = yi;
dx = xf - xi;
dy = yf - yi;
xinc = ( dx > 0 ) ? 1 : -1;
yinc = ( dy > 0 ) ? 1 : -1;
dx = abs(dx);
dy = abs(dy);
px[y] = x;
if ( dx > dy ) {
cumul = dx / 2;
for ( i = 1 ; i <= dx ; i++ ) {
x += xinc;
cumul += dy;
if ( cumul >= dx ) {
cumul -= dx;
y += yinc; }
if ( x < px[y] )
px[y] = x; } }
else {
cumul = dy / 2;
for ( i = 1 ; i <= dy ; i++ ) {
y += yinc;
cumul += dx;
if ( cumul >= dy ) {
cumul -= dy;
x += xinc; }
if ( x < px[y] )
px[y] = x; } }
}
static void remplissageTriangle3(Position3D *p1,Position3D *p2,Position3D *p3) {
Position3D *c1;
Position3D *c2;
Position3D *c3;
if ( ( p1->c[1] <= p2->c[1] ) && ( p1->c[1] <= p3->c[1] ) ) {
c1 = p1;
if ( p2->c[1] < p3->c[1] ) {
c2 = p2;
c3 = p3; }
else {
c2 = p3;
c3 = p2; } }
else {
if ( p2->c[1] < p3->c[1] ) {
c1 = p2;
if ( p1->c[1] < p3->c[1] ) {
c2 = p1;
c3 = p3; }
else {
c2 = p3;
c3 = p1; } }
else {
c1 = p3;
if ( p1->c[1] < p2->c[1] ) {
c2 = p1;
c3 = p2; }
else {
c2 = p2;
c3 = p1; } } }
Direction3D *d1 = new Direction3D(c1,c3);
Direction3D *d2 = new Direction3D(c1,c2);
double z = d1->c[0]*d2->c[1]-d2->c[0]*d1->c[1];
delete(d1);
delete(d2);
int t = (z < 0.0);
int xi[4096];
int xf[4096];
for ( int y = c1->c[1] ; y <= c3->c[1] ; y++ ) {
xi[y] = 4096;
xf[y] = 0; }
if ( t ) {
bordGauche(xi,c1,c3);
bordDroit(xf,c1,c2);
bordDroit(xf,c2,c3); }
else {
bordGauche(xi,c1,c2);
bordGauche(xi,c2,c3);
bordDroit(xf,c1,c3); }
glPointSize(9.0F);
glBegin(GL_POINTS);
for ( int y = c1->c[1] ; y <= c3->c[1] ; y++ ) {
for ( int x = xi[y] ; x <= xf[y] ; x++ ) {
glVertex2i(x*11+4,y*11+4); } }
glEnd();
glPointSize(1.0F);
}