/* Un programme OpenGL de rasterisation */ /* d'un triangle */ /* */ /* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Novembre 2009 */ #include #include #include #include #include typedef struct position2D { int x; int y; int w; } position2D; typedef struct triangle { position2D p1; position2D p2; position2D p3; } triangle; static int scn = 0; static triangle t1 = { { -20, 110 }, { -100, -10 }, { 90, -90 } }; static triangle t2 = { { -20, 110 }, { -100, -90 }, { 90, -30 } }; static triangle t = t1; /* Scene dessinee */ void ligne(position2D *pi,position2D *pf) { int i,cumul; int x = pi->x; int y = pi->y; int dx = pf->x - pi->x; int dy = pf->y - pi->y; int xinc = ( dx > 0 ) ? 1 : -1; int yinc = ( dy > 0 ) ? 1 : -1; dx = abs(dx); dy = abs(dy); glBegin(GL_POINTS); glVertex2i(x,y); if ( dx > dy ) { cumul = dx>>1; for ( i = 1 ; i <= dx ; i++ ) { x += xinc; cumul += dy; if (cumul >= dx) { cumul -= dx; y += yinc; } glVertex2i(x,y); } } else { cumul = dy / 2; for ( i = 1 ; i <= dy ; i++ ) { y += yinc; cumul += dx; if ( cumul >= dy ) { cumul -= dy; x += xinc; } glVertex2i(x,y); } } glEnd(); } void scene1(void) { glPushMatrix(); glColor3f(1.0F,0.0F,0.0F); ligne(&t.p1,&t.p2); glColor3f(0.0F,1.0F,0.0F); ligne(&t.p2,&t.p3); glColor3f(0.0F,0.0F,1.0F); ligne(&t.p3,&t.p1); glPopMatrix(); } void tourneSensMontre(triangle *t) { position2D p = t->p1; t->p1 = t->p2; t->p2 = t->p3; t->p3 = p; } void tourneInverseSensMontre(triangle *t) { position2D p = t->p1; t->p1 = t->p3; t->p3 = t->p2; t->p2 = p; } void ordonne(triangle *t) { if ( ( t->p1.y <= t->p2.y ) && ( t->p1.y <= t->p3.y ) ) return; if ( t->p2.y <= t->p3.y ) tourneSensMontre(t); else tourneInverseSensMontre(t); } void bord(int *tx,int ymin,position2D *pi,position2D *pf) { int i,cumul; int x = pi->x; int y = pi->y; int dx = pf->x - pi->x; int dy = pf->y - pi->y; int xinc = ( dx > 0 ) ? 1 : -1; int yinc = ( dy > 0 ) ? 1 : -1; dx = abs(dx); dy = abs(dy); tx[y-ymin] = x; if ( dx > dy ) { cumul = dx>>1; for ( i = 1 ; i <= dx ; i++ ) { x += xinc; cumul += dy; if (cumul >= dx) { cumul -= dx; y += yinc; } tx[y-ymin] = x; } } else { cumul = dy / 2; for ( i = 1 ; i <= dy ; i++ ) { y += yinc; cumul += dx; if ( cumul >= dy ) { cumul -= dy; x += xinc; } tx[y-ymin] = x; } } } void triangle(triangle *t) { ordonne(t); int ymin = t->p1.y; int ymax; int type; if ( t->p2.y > t->p3.y ) { ymax = t->p2.y; type = 0; } else { ymax = t->p3.y; type = 1; } int ydim = ymax-ymin+1; //printf("%d %d\n",t->p1.x,t->p1.y); //printf("%d %d\n",t->p2.x,t->p2.y); //printf("%d %d\n",t->p3.x,t->p3.y); //printf("%d\n",ymin); //printf("%d\n",ymax); //printf("%d\n",type); int *bd =(int *) calloc(ydim,sizeof(int)); int *bg =(int *) calloc(ydim,sizeof(int)); switch (type) { case 0 : bord(bd,ymin,&t->p1,&t->p2); bord(bg,ymin,&t->p2,&t->p3); bord(bg,ymin,&t->p3,&t->p1); break; case 1 : bord(bd,ymin,&t->p1,&t->p2); bord(bd,ymin,&t->p2,&t->p3); bord(bg,ymin,&t->p3,&t->p1); break; } //for ( int i = 0 ; i < ydim ; i++ ) // printf("%4d %4d %4d\n",i,bg[i],bd[i]); glBegin(GL_LINES); for ( int y = ymin ; y <= ymax ; y++ ) { glVertex2i(bg[y-ymin],y); glVertex2i(bd[y-ymin],y); } glEnd(); free(bg); free(bd); } void scene2(void) { glPushMatrix(); glColor3f(0.5F,0.5F,0.5F); triangle(&t); glPopMatrix(); } /* Fonction executee lors d'un rafraichissement */ /* de la fenetre de dessin */ void display(void) { glClearColor(1.0F,1.0F,1.0F,1.0F); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); if ( scn == 0 ) scene1(); else scene2(); glPopMatrix(); glFlush(); glutSwapBuffers(); } /* Fonction executee lors d'un changement */ /* de la taille de la fenetre OpenGL */ void reshape(int x,int y) { glViewport(0,0,x,y); glMatrixMode(GL_PROJECTION) ; glLoadIdentity() ; glOrtho(-x/2,-x/2+x,-y/2,-y/2+y,-300.0,300.0) ; glMatrixMode(GL_MODELVIEW) ; glLoadIdentity() ; } /* Fonction executee lors de l'appui */ /* d'une touche alphanumerique du clavier */ void keyboard(unsigned char key,int x,int y) { switch (key) { case 0x20 : { static int tr = 0; tr = (tr+1)%2; if ( tr == 1 ) t = t2; else t = t1; } glutPostRedisplay(); break; case 0x0D : scn = !scn; glutPostRedisplay(); break; case 0x1B : exit(0); break; } } /* Fonction principale */ int main(int argc,char **argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); glutInitWindowSize(240,240); glutInitWindowPosition(50,50); glutCreateWindow("Rasterisation d'un triangle"); glutKeyboardFunc(keyboard); glutReshapeFunc(reshape); glutDisplayFunc(display); glutMainLoop(); return(0); }