/* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Novembre 2007 */ /* Rasterisation de segments de droites */ /* trois dimensions et de facettes */ /* deux dimensions */ #include #include #include #include #include #include /* Variables globales de definition de couleurs */ static float noir[] = { 0.0F,0.0F,0.0F,1.0F }; static float rouge[] = { 1.0F,0.0F,0.0F,1.0F }; static float bleu[] = { 0.0F,0.0F,1.0F,1.0F }; static float jaune[] = { 1.0F,1.0F,0.0F,1.0F }; static float vertFonce[] = { 0.0F,0.5F,0.0F,1.0F }; /* Variables globales de gestion */ /* de l'interactivite clavier et souris */ static int clic = 0; static int mx; static int my; static float rx = 0.0F; static float ry = 0.0F; static float zoom = 1.0F; struct coordonnees { int x; int y; int z; int t; }; struct segment { coordonnees pi; coordonnees pf; }; struct facette { coordonnees p1; coordonnees p2; coordonnees p3; }; static int aff = 0; static int mode = 0; static segment seg1 = { { -9, 2, 3,1 }, { 8, 8, -4,1 } }; static segment seg2 = { { 3, -9, -6,1 }, { 9, 6, 5,1 } }; static segment seg3 = { { -8, -2,-10,1 }, { -1, -7, 9,1 } }; static facette f = { { -9, 2, 0,1 }, { 9, 6, 0,1 }, { 6, -8, 0,1 } }; void pixel(int x,int y,float *c) { glColor4fv(c); glBegin(GL_QUADS); glVertex2i(x,y); glVertex2i(x+1,y); glVertex2i(x+1,y+1); glVertex2i(x,y+1); glEnd(); glColor4fv(noir); glBegin(GL_LINE_LOOP); glVertex2i(x,y); glVertex2i(x+1,y); glVertex2i(x+1,y+1); glVertex2i(x,y+1); glEnd(); } void pixel(int x,int y,int z,float *c) { glColor4fv(c); glPushMatrix(); glTranslatef(x+0.5F,y+0.5F,z+0.5F); glutWireCube(1.0); glPopMatrix(); } void lignePixels(int xi,int yi,int xf,int yf,float *c) { int i,cumul; int x = xi; int y = yi; int dx = xf - xi; int dy = yf - yi; int xinc = ( dx > 0 ) ? 1 : -1; int yinc = ( dy > 0 ) ? 1 : -1; dx = abs(dx); dy = abs(dy); pixel(x,y,c); if ( dx > dy ) { cumul = dx / 2; for ( i = 1 ; i <= dx ; i++ ) { x += xinc; cumul += dy; if (cumul >= dx) { cumul -= dx; y += yinc; } pixel(x,y,c); } } else { cumul = dy / 2; for ( i = 1 ; i <= dy ; i++ ) { y += yinc; cumul += dx; if ( cumul >= dy ) { cumul -= dy; x += xinc; } pixel(x,y,c); } } } void lignePixels(int xi,int yi,int zi,int xf,int yf,int zf,float *c) { int i; int x = xi; int y = yi; int z = zi; int dx = xf - xi; int dy = yf - yi; int dz = zf - zi; int xinc = ( dx > 0 ) ? 1 : -1; int yinc = ( dy > 0 ) ? 1 : -1; int zinc = ( dz > 0 ) ? 1 : -1; dx = abs(dx); dy = abs(dy); dz = abs(dz); pixel(x,y,z,c); if ( ( dx >= dy ) && ( dx >= dz ) ) { int cumuly = dx / 2; int cumulz = dx / 2; for ( i = 1 ; i <= dx ; i++ ) { x += xinc; cumuly += dy; cumulz += dz; if (cumuly >= dx) { cumuly -= dx; y += yinc; } if (cumulz >= dx) { cumulz -= dx; z += zinc; } pixel(x,y,z,c); } } else if ( dy > dz ) { int cumulx = dy / 2; int cumulz = dy / 2; for ( i = 1 ; i <= dy ; i++ ) { y += yinc; cumulx += dx; cumulz += dz; if ( cumulx >= dy ) { cumulx -= dy; x += xinc; } if ( cumulz >= dy ) { cumulz -= dy; z += zinc; } pixel(x,y,z,c); } } else { int cumulx = dz / 2; int cumuly = dz / 2; for ( i = 1 ; i <= dz ; i++ ) { z += zinc; cumulx += dx; cumuly += dy; if ( cumulx >= dz ) { cumulx -= dz; x += xinc; } if ( cumuly >= dz ) { cumuly -= dz; y += yinc; } pixel(x,y,z,c); } } } void dessineSegment(float *c,coordonnees *pi,coordonnees *pf) { glColor4fv(c); glLineWidth(3.0); glBegin(GL_LINES); glVertex3d(pi->x+0.5,pi->y+0.5,0.5); glVertex3d(pf->x+0.5,pf->y+0.5,0.5); glEnd(); glLineWidth(1.0); } void dessineSegment(float *c,segment *s) { dessineSegment(c,&s->pi,&s->pf); } void dessineQuadrillage(float *c,int n) { int i; glColor4fv(c); glBegin(GL_LINES); for ( i = -n ; i <= n ; i++ ) { glVertex2d(-n,i); glVertex2d(n,i); } for ( i = -n ; i <= n ; i++ ) { glVertex2d(i,-n); glVertex2d(i,n); } glEnd(); } void display1() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); switch (aff) { case 0 : dessineSegment(rouge,&seg1); dessineSegment(rouge,&seg2); dessineSegment(rouge,&seg3); break; case 1 : dessineQuadrillage(bleu,11); dessineSegment(rouge,&seg1); dessineSegment(rouge,&seg2); dessineSegment(rouge,&seg3); break; case 2 : dessineQuadrillage(bleu,11); lignePixels(seg1.pi.x,seg1.pi.y, seg1.pf.x,seg1.pf.y, vertFonce); lignePixels(seg2.pi.x,seg2.pi.y, seg2.pf.x,seg2.pf.y, vertFonce); lignePixels(seg3.pi.x,seg3.pi.y, seg3.pf.x,seg3.pf.y, vertFonce); dessineSegment(rouge,&seg1); dessineSegment(rouge,&seg2); dessineSegment(rouge,&seg3); break; } glPopMatrix(); glFlush(); glutSwapBuffers(); } void dessineSegment3D(float *c,coordonnees *pi,coordonnees *pf) { glColor4fv(c); glLineWidth(3.0); glBegin(GL_LINES); glVertex3d(pi->x+0.5,pi->y+0.5,pi->z+0.5); glVertex3d(pf->x+0.5,pf->y+0.5,pf->z+0.5); glEnd(); glLineWidth(1.0); } void dessineSegment3D(float *c,segment *s) { dessineSegment3D(c,&s->pi,&s->pf); } void dessineQuadrillage3D(float *c,int n) { glColor4fv(c); glPushMatrix(); glutWireCube(2*n); glPopMatrix(); } void display2() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(rx,1.0F,0.0F,0.0F); glRotatef(ry,0.0F,1.0F,0.0F); glScalef(zoom,zoom,zoom); switch (aff) { case 0 : dessineSegment3D(rouge,&seg1); dessineSegment3D(rouge,&seg2); dessineSegment3D(rouge,&seg3); break; case 1 : dessineQuadrillage3D(bleu,11); dessineSegment3D(rouge,&seg1); dessineSegment3D(rouge,&seg2); dessineSegment3D(rouge,&seg3); break; case 2 : dessineQuadrillage3D(bleu,11); lignePixels(seg1.pi.x,seg1.pi.y,seg1.pi.z, seg1.pf.x,seg1.pf.y,seg1.pf.z, vertFonce); lignePixels(seg2.pi.x,seg2.pi.y,seg2.pi.z, seg2.pf.x,seg2.pf.y,seg2.pf.z, vertFonce); lignePixels(seg3.pi.x,seg3.pi.y,seg3.pi.z, seg3.pf.x,seg3.pf.y,seg3.pf.z, vertFonce); dessineSegment3D(rouge,&seg1); dessineSegment3D(rouge,&seg2); dessineSegment3D(rouge,&seg3); break; } glPopMatrix(); glFlush(); glutSwapBuffers(); } void pixel(int x,int y,int *tx) { tx[y] = x; } void calculBordure(int xi,int yi,int xf,int yf,int *tx) { int i,cumul; int x = xi; int y = yi; int dx = xf - xi; int dy = yf - yi; int xinc = ( dx > 0 ) ? 1 : -1; int yinc = ( dy > 0 ) ? 1 : -1; dx = abs(dx); dy = abs(dy); pixel(x,y,tx); if ( dx > dy ) { cumul = dx / 2; for ( i = 1 ; i <= dx ; i++ ) { x += xinc; cumul += dy; if (cumul >= dx) { cumul -= dx; y += yinc; } pixel(x,y,tx); } } else { cumul = dy / 2; for ( i = 1 ; i <= dy ; i++ ) { y += yinc; cumul += dx; if ( cumul >= dy ) { cumul -= dy; x += xinc; } pixel(x,y,tx); } } } void permute(coordonnees *c1,coordonnees *c2) { coordonnees c = *c1; *c1 = *c2; *c2 = c; } void traceFacette(facette *f,float *c) { facette fc = *f; if ( fc.p3.y < fc.p2.y ) permute(&fc.p3,&fc.p2); if ( fc.p2.y < fc.p1.y ) permute(&fc.p2,&fc.p1); if ( fc.p3.y < fc.p2.y ) permute(&fc.p3,&fc.p2); int xmin = min(fc.p1.x,min(fc.p2.x,fc.p3.x)); int ymin = fc.p1.y; int ymax = fc.p3.y; int dy = ymax-ymin+1; int *x1 =(int *) calloc(dy,sizeof(int)); int *x2 =(int *) malloc(dy*sizeof(int)); int i; calculBordure(fc.p1.x-xmin+1,fc.p1.y-ymin,fc.p2.x-xmin+1,fc.p2.y-ymin,x2); calculBordure(fc.p2.x-xmin+1,fc.p2.y-ymin,fc.p3.x-xmin+1,fc.p3.y-ymin,x2); calculBordure(fc.p3.x-xmin+1,fc.p3.y-ymin,fc.p1.x-xmin+1,fc.p1.y-ymin,x1); for ( i = 0 ; i < dy ; i++ ) { int dx = abs(x1[i]-x2[i])+1; int x = min(x1[i],x2[i])+xmin-1; for ( int j = 0 ; j < dx ; j++ ) { pixel(x,i+ymin,c); x++; } } free(x1); free(x2); } void traceFacette3D(facette *f,float *c) { facette fc = *f; if ( fc.p3.y < fc.p2.y ) permute(&fc.p3,&fc.p2); if ( fc.p2.y < fc.p1.y ) permute(&fc.p2,&fc.p1); if ( fc.p3.y < fc.p2.y ) permute(&fc.p3,&fc.p2); int xmin = min(fc.p1.x,min(fc.p2.x,fc.p3.x)); int ymin = fc.p1.y; int ymax = fc.p3.y; int dy = ymax-ymin+1; int *x1 =(int *) calloc(dy,sizeof(int)); int *x2 =(int *) malloc(dy*sizeof(int)); int i; calculBordure(fc.p1.x-xmin+1,fc.p1.y-ymin,fc.p2.x-xmin+1,fc.p2.y-ymin,x2); calculBordure(fc.p2.x-xmin+1,fc.p2.y-ymin,fc.p3.x-xmin+1,fc.p3.y-ymin,x2); calculBordure(fc.p3.x-xmin+1,fc.p3.y-ymin,fc.p1.x-xmin+1,fc.p1.y-ymin,x1); for ( i = 0 ; i < dy ; i++ ) { int dx = abs(x1[i]-x2[i])+1; int x = min(x1[i],x2[i])+xmin-1; for ( int j = 0 ; j < dx ; j++ ) { pixel(x,i+ymin,0,c); x++; } } free(x1); free(x2); } void display3() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); switch (aff) { case 0 : dessineSegment(rouge,&f.p1,&f.p2); dessineSegment(rouge,&f.p2,&f.p3); dessineSegment(rouge,&f.p3,&f.p1); break; case 1 : dessineQuadrillage(bleu,11); dessineSegment(rouge,&f.p1,&f.p2); dessineSegment(rouge,&f.p2,&f.p3); dessineSegment(rouge,&f.p3,&f.p1); break; case 2 : dessineQuadrillage(bleu,11); lignePixels(f.p1.x,f.p1.y, f.p2.x,f.p2.y, vertFonce); lignePixels(f.p2.x,f.p2.y, f.p3.x,f.p3.y, vertFonce); lignePixels(f.p3.x,f.p3.y, f.p1.x,f.p1.y, vertFonce); dessineSegment(rouge,&f.p1,&f.p2); dessineSegment(rouge,&f.p2,&f.p3); dessineSegment(rouge,&f.p3,&f.p1); break; case 3 : dessineQuadrillage(bleu,11); traceFacette(&f,jaune); lignePixels(f.p1.x,f.p1.y, f.p2.x,f.p2.y, vertFonce); lignePixels(f.p2.x,f.p2.y, f.p3.x,f.p3.y, vertFonce); lignePixels(f.p3.x,f.p3.y, f.p1.x,f.p1.y, vertFonce); dessineSegment(rouge,&f.p1,&f.p2); dessineSegment(rouge,&f.p2,&f.p3); dessineSegment(rouge,&f.p3,&f.p1); break; } glPopMatrix(); glFlush(); glutSwapBuffers(); } void display4() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(rx,1.0F,0.0F,0.0F); glRotatef(ry,0.0F,1.0F,0.0F); glScalef(zoom,zoom,zoom); switch (aff) { case 0 : dessineSegment3D(rouge,&f.p1,&f.p2); dessineSegment3D(rouge,&f.p2,&f.p3); dessineSegment3D(rouge,&f.p3,&f.p1); break; case 1 : dessineQuadrillage3D(bleu,11); dessineSegment3D(rouge,&f.p1,&f.p2); dessineSegment3D(rouge,&f.p2,&f.p3); dessineSegment3D(rouge,&f.p3,&f.p1); break; case 2 : dessineQuadrillage3D(bleu,11); lignePixels(f.p1.x,f.p1.y,f.p1.z, f.p2.x,f.p2.y,f.p2.z, vertFonce); lignePixels(f.p2.x,f.p2.y,f.p2.z, f.p3.x,f.p3.y,f.p3.z, vertFonce); lignePixels(f.p3.x,f.p3.y,f.p3.z, f.p1.x,f.p1.y,f.p1.z, vertFonce); dessineSegment3D(rouge,&f.p1,&f.p2); dessineSegment3D(rouge,&f.p2,&f.p3); dessineSegment3D(rouge,&f.p3,&f.p1); break; case 3 : dessineQuadrillage3D(bleu,11); traceFacette3D(&f,jaune); lignePixels(f.p1.x,f.p1.y,f.p1.z, f.p2.x,f.p2.y,f.p2.z, vertFonce); lignePixels(f.p2.x,f.p2.y,f.p2.z, f.p3.x,f.p3.y,f.p3.z, vertFonce); lignePixels(f.p3.x,f.p3.y,f.p3.z, f.p1.x,f.p1.y,f.p1.z, vertFonce); dessineSegment3D(rouge,&f.p1,&f.p2); dessineSegment3D(rouge,&f.p2,&f.p3); dessineSegment3D(rouge,&f.p3,&f.p1); break; } glPopMatrix(); glFlush(); glutSwapBuffers(); } void myinit() { glClearColor(0.8F,0.8F,0.8F,1.0F); } /* Fonction executee lors d'un changement */ /* de la taille de la fenetre OpenGL */ /* Configuration d'une camera de visualisation */ /* en projection parallele */ void reshape(int tx,int ty) { glViewport(0,0,tx,ty); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho((-12.0*tx)/ty,(12.0*tx)/ty,-12.0,12.0,-20.0,20.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } /* Fonction executee lors d'un clic de souris */ /* dans la fenetre */ void mouse(int bouton,int etat,int x,int y) { if ( bouton == GLUT_LEFT_BUTTON ) { if ( etat == GLUT_DOWN ) { clic = 1; mx = x; my = y; } if ( etat == GLUT_UP ) { clic = 0; } } } /* Fonction executee lors d'un deplacement */ /* de la souris sur la fenetre */ /* avec un bouton appuye */ void motion(int x,int y) { if ( clic ) { ry += (x-mx); rx += (y-my); mx = x; my = y; glutPostRedisplay(); } } /* Fonction executee lors de la frappe */ /* d'une touche alphanumerique du clavier */ void key(unsigned char key,int x,int y) { switch ( key ) { case 43 : zoom *= 1.01F; glutPostRedisplay(); break; case 45 : zoom /= 1.01F; glutPostRedisplay(); break; case 0x1B : exit(0); break; case 0x20 : mode = (mode+1)%4; switch (mode) { case 0 : glutDisplayFunc(display1); glutMouseFunc(NULL); glutMotionFunc(NULL); aff = 0; break; case 1 : glutDisplayFunc(display2); glutMouseFunc(mouse); glutMotionFunc(motion); aff = 0; break; case 2 : glutDisplayFunc(display3); glutMouseFunc(NULL); glutMotionFunc(NULL); aff = 0; break; case 3 : glutDisplayFunc(display4); glutMouseFunc(mouse); glutMotionFunc(motion); aff = 0; break; } glutPostRedisplay(); break; case 0x0D : aff = (aff+1)%4; glutPostRedisplay(); break; } } /* Fonction principale */ int main(int argc,char **argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); glutInitWindowSize(350,350); glutInitWindowPosition(50,50); glutCreateWindow("Rasterisation selon Bresenham"); myinit(); glutReshapeFunc(reshape); glutKeyboardFunc(key); glutMouseFunc(mouse); glutMotionFunc(motion); glutDisplayFunc(display1); glutMainLoop(); return(0); }