/* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Avril 2003 */ /* Clipping de Cohen-Sutherland */ #include #include #include #include #include #include #include "ModuleCouleurs.h" #include "ModuleMenus.h" #include "ModuleReshape.h" struct point { int x ; int y ; } ; struct segment { point pi ; point pf ; } ; struct rectangle { point ig ; point sd ; } ; struct code { int c1 ; int c2 ; int c3 ; int c4 ; } ; static int aff = 0 ; static segment s1 = { { 2,10 }, { 27,19 } } ; static segment s2 = { { 5,9 }, { 28,4 } } ; void pixel(int x,int y,float *c) { glColor4fv(c) ; glBegin(GL_QUADS) ; glVertex2f(x-1.0F,y-1.0F) ; glVertex2f(x-1.0F,y) ; glVertex2f(x,y) ; glVertex2f(x,y-1.0F) ; glEnd() ; } void line(point *pi,point *pf,float *c) { int dx,dy,i,xinc,yinc,cumul,x,y ; x = pi->x ; y = pi->y ; dx = pf->x - pi->x ; dy = pf->y - pi->y ; xinc = ( dx > 0 ) ? 1 : -1 ; 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 traceRectangle(rectangle *r,float *c) { point id = { r->sd.x,r->ig.y }; point sg = { r->ig.x,r->sd.y }; line(&id,&r->ig,c) ; line(&id,&r->sd,c) ; line(&sg,&r->ig,c) ; line(&sg,&r->sd,c) ; } void getCode(point *p,rectangle *r,code *c) { c->c1 = p->x < r->ig.x; c->c2 = p->x > r->sd.x; c->c3 = p->y < r->ig.y; c->c4 = p->y > r->sd.y; } void affichageCode(code *c) { printf("%d%d%d%d\n",c->c1,c->c2,c->c3,c->c4); } int codeNul(code *c) { return(!(c->c1 || c->c2 || c->c3 || c->c4)) ; } int pas1commun(code *c1,code *c2) { if ( c1->c1 && c2->c1 ) return(0); if ( c1->c2 && c2->c2 ) return(0); if ( c1->c3 && c2->c3 ) return(0); if ( c1->c4 && c2->c4 ) return(0); return(1) ; } int code0(code *c) { return(c->c1) ; } int code1(code *c) { return(c->c2) ; } int code2(code *c) { return(c->c3) ; } int code3(code *c) { return(c->c4) ; } int intersection(int ai,int bi,int af,int bf,int val) { int res = 0 ; if ( af-ai != 0 ) res =(int) (0.499 + bi +(double) (val-ai) / (af-ai) * (bf-bi)) ; else res = 32767 ; return(res) ; } void clipperSegment(rectangle *r,segment *s,float *c) { segment se = *s ; code c1,c2 ; point p ; getCode(&s->pi,r,&c1) ; getCode(&s->pf,r,&c2) ; while ( ( !codeNul(&c1) || !codeNul(&c2) ) && ( pas1commun(&c1,&c2) ) ) { if ( codeNul(&c1) ) { p = s->pi ; s->pi = s->pf ; s->pf = p ; c1 = c2 ; } if ( code0(&c1) ) { s->pi.y = intersection(s->pi.x,s->pi.y,s->pf.x,s->pf.y,r->ig.x) ; s->pi.x = r->ig.x ; } else if ( code1(&c1) ) { s->pi.y = intersection(s->pi.x,s->pi.y,s->pf.x,s->pf.y,r->sd.x) ; s->pi.x = r->sd.x ; } else if ( code2(&c1) ) { s->pi.x = intersection(s->pi.y,s->pi.x,s->pf.y,s->pf.x,r->ig.y) ; s->pi.y = r->ig.y ; } else if ( code3(&c1) ) { s->pi.x = intersection(s->pi.y,s->pi.x,s->pf.y,s->pf.x,r->sd.y) ; s->pi.y = r->sd.y ; } getCode(&s->pi,r,&c1) ; getCode(&s->pf,r,&c2) ; } if ( codeNul(&c1) && codeNul(&c2) ) line(&s->pi,&s->pf,c) ; *s = se ; } void dessineQuadrillage(void) { float i; glColor4fv(couleurGrisMoyen()) ; glBegin(GL_LINES); for ( i = 0 ; i <= 30 ; i++ ) { glVertex3d(i,0,-10.0); glVertex3d(i,20,-10.0); } for ( i = 0 ; i <= 20 ; i++ ) { glVertex3d(0,i,-10.0); glVertex3d(30,i,-10.0); } glEnd() ; } void display() { rectangle r = { 6,5,26,15 } ; glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); dessineQuadrillage(); traceRectangle(&r,couleurRouge(0.6F)); switch ( aff) { case 1 : line(&s1.pi, &s1.pf, couleurBleu(0.5)); line(&s2.pi, &s2.pf, couleurVertFonce(0.5)); break ; case 2 : line(&s1.pi, &s1.pf, couleurBleu(0.3)); line(&s2.pi, &s2.pf, couleurVertFonce(0.3)); clipperSegment(&r, &s1, couleurBleu(0.8)); clipperSegment(&r, &s2, couleurVertFonce(0.8)); break ; case 3 : clipperSegment(&r, &s1, couleurBleu(0.8)); clipperSegment(&r, &s2, couleurVertFonce(0.8)); break ; } glPopMatrix(); glFlush(); glutSwapBuffers() ; } void special(int key,int x,int y) { } void key(unsigned char key,int x,int y) { switch ( key ) { case 0x0D : aff = (aff+1)%4 ; glutPostRedisplay(); break; case 0x1B : exit(0); break; } } void myinit() { glEnable(GL_ALPHA_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glClearColor(0.8F,0.8F,0.8F,1.0F); } int main(int argc,char **argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); glutInitWindowSize(375,252); glutInitWindowPosition(50,50); glutCreateWindow("Clipping Cohen-Sutherland"); myinit(); creationMenuBasique(); setParametresOrthoBasique(-0.5,20.5,-0.5,20.5,-50.0,50.0); glutReshapeFunc(reshapeOrthoBasique); glutSpecialFunc(special); glutKeyboardFunc(key); glutDisplayFunc(display); glutMainLoop(); return(0); }