/* Auteur: Nicolas JANEY */ /* Avril 2001 */ /* Le clipping de Cohen-Sutherland en 3D */ #include #include #include #include #include #include #include struct coord_3D { float x ; float y ; float z ; } ; struct segment { struct coord_3D pi ; struct coord_3D pf ; } ; struct boite { struct coord_3D pi ; struct coord_3D pf ; } ; static float anglex = 0.0F ; static float angley = 0.0F ; static int clip = 0 ; struct segment s[5] = { {{5,5,5},{-1,-7,-8}}, {{8,-6,-4},{1,7,-2}}, {{-8,6,-7},{7,-3,8}}, {{2,6,-4},{-5,-7,4}}, {{5,2,-7},{-3,3,-1}} } ; struct boite b = { {-4,-4,-4},{4,4,4} } ; int code(coord_3D *p,boite *r) { int c ; if ( p->x < r->pi.x ) c = 1 ; else c = 0 ; if ( p->x > r->pf.x ) c += 2 ; if ( p->y < r->pi.y ) c += 4 ; if ( p->y > r->pf.y ) c += 8 ; if ( p->z < r->pi.z ) c += 16 ; if ( p->z > r->pf.z ) c += 32 ; return(c) ; } int code_nul(int c) { return(c == 0) ; } int pas1commun(int c1,int c2) { return((c1&c2) == 0) ; } int code0(int c) { return(c&1) ; } int code1(int c) { return(c&2) ; } int code2(int c) { return(c&4) ; } int code3(int c) { return(c&8) ; } int code4(int c) { return(c&16) ; } int code5(int c) { return(c&32) ; } float intersection(float px,float py,float pz,float dx,float dy,float dz,float val,int type) { float res = 0.0F ; switch ( type ) { case 0 : if ( dx != 0 ) res = (val-px)/dx ; else res = 1.0e+10 ; break ; case 1 : if ( dy != 0 ) res = (val-py)/dy ; else res = 1.0e+10 ; break ; case 2 : if ( dz != 0 ) res = (val-pz)/dz ; else res = 1.0e+10 ; break ; } return(res) ; } void clipping(struct segment *s,struct boite *b) { segment se = *s ; int c1,c2 ; coord_3D p ; c1 = code(&s->pi,b) ; c2 = code(&s->pf,b) ; float px,py,pz ; float dx,dy,dz ; px = s->pi.x ; py = s->pi.y ; pz = s->pi.z ; dx = px - s->pf.x ; dy = py - s->pf.y ; dz = pz - s->pf.z ; while ( ( !code_nul(c1) || !code_nul(c2) ) && ( pas1commun(c1,c2) ) ) { if ( code_nul(c1) ) { p = s->pi ; s->pi = s->pf ; s->pf = p ; c1 = c2 ; } if ( code0(c1) ) { float coef = intersection(px,py,pz,dx,dy,dz,b->pi.x,0) ; s->pi.y = py + coef*dy ; s->pi.z = pz + coef*dz ; s->pi.x = b->pi.x ; } else if ( code1(c1) ) { float coef = intersection(px,py,pz,dx,dy,dz,b->pf.x,0) ; s->pi.y = py + coef*dy ; s->pi.z = pz + coef*dz ; s->pi.x = b->pf.x ; } else if ( code2(c1) ) { float coef = intersection(px,py,pz,dx,dy,dz,b->pi.y,1) ; s->pi.x = px + coef*dx ; s->pi.z = pz + coef*dz ; s->pi.y = b->pi.y ; } else if ( code3(c1) ) { float coef = intersection(px,py,pz,dx,dy,dz,b->pf.y,1) ; s->pi.x = px + coef*dx ; s->pi.z = pz + coef*dz ; s->pi.y = b->pf.y ; } else if ( code4(c1) ) { float coef = intersection(px,py,pz,dx,dy,dz,b->pi.z,2) ; s->pi.x = px + coef*dx ; s->pi.y = py + coef*dy ; s->pi.z = b->pi.z ; } else if ( code5(c1) ) { float coef = intersection(px,py,pz,dx,dy,dz,b->pf.z,2) ; s->pi.x = px + coef*dx ; s->pi.y = py + coef*dy ; s->pi.z = b->pf.z ; } c1 = code(&s->pi,b) ; c2 = code(&s->pf,b) ; } if ( code_nul(c1) && code_nul(c2) ) { glBegin(GL_LINES) ; glVertex3f(s->pi.x,s->pi.y,s->pi.z) ; glVertex3f(s->pf.x,s->pf.y,s->pf.z) ; glEnd() ; } *s = se ; } void CALLBACK display(void) { glClearColor(0.0F,0.0F,0.0F,0.0F); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(angley,0.0F,1.0F,0.0F) ; glRotatef(anglex,1.0F,0.0F,0.0F) ; glColor3f(1.0F,1.0F,1.0F) ; glPushMatrix(); glTranslatef((b.pi.x+b.pf.x)/2,(b.pi.y+b.pf.y)/2,(b.pi.z+b.pf.z)/2) ; auxWireBox(b.pi.x-b.pf.x,b.pi.y-b.pf.y,b.pi.z-b.pf.z) ; glColor3f(1.0F,0.0F,0.0F) ; glPopMatrix(); for ( int i = 0 ; i < 5 ; i++ ) if ( clip ) { clipping(&s[i],&b) ; } else { glBegin(GL_LINES) ; glVertex3f(s[i].pi.x,s[i].pi.y,s[i].pi.z) ; glVertex3f(s[i].pf.x,s[i].pf.y,s[i].pf.z) ; glEnd() ; } glPopMatrix(); glFlush(); auxSwapBuffers(); } void myinit (void) { glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); } void CALLBACK myReshape(int w, int h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-10,10,-10/(double) w*h,10/(double) w*h,-10.0,10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void CALLBACK up(void) { anglex++ ; } void CALLBACK down(void) { anglex-- ; } void CALLBACK left(void) { angley++ ; } void CALLBACK right(void) { angley-- ; } void CALLBACK space(void) { clip = 1 - clip ; } void CALLBACK keya(void) { b.pi.x += 0.03F ; } void CALLBACK keyA(void) { b.pi.x -= 0.03F ; } void CALLBACK keyq(void) { b.pf.x += 0.03F ; } void CALLBACK keyQ(void) { b.pf.x -= 0.03F ; } void CALLBACK keyz(void) { b.pi.y += 0.03F ; } void CALLBACK keyZ(void) { b.pi.y -= 0.03F ; } void CALLBACK keys(void) { b.pf.y += 0.03F ; } void CALLBACK keyS(void) { b.pf.y -= 0.03F ; } void CALLBACK keye(void) { b.pi.z += 0.03F ; } void CALLBACK keyE(void) { b.pi.z -= 0.03F ; } void CALLBACK keyd(void) { b.pf.z += 0.03F ; } void CALLBACK keyD(void) { b.pf.z -= 0.03F ; } void main(void) { auxInitDisplayMode(AUX_DOUBLE|AUX_RGBA|AUX_DEPTH); auxInitPosition (0,0,300,300); auxInitWindow("Clipping 3D") ; myinit(); auxKeyFunc(AUX_a,keya) ; auxKeyFunc(AUX_A,keyA) ; auxKeyFunc(AUX_q,keyq) ; auxKeyFunc(AUX_Q,keyQ) ; auxKeyFunc(AUX_z,keyz) ; auxKeyFunc(AUX_s,keys) ; auxKeyFunc(AUX_e,keye) ; auxKeyFunc(AUX_d,keyd) ; auxKeyFunc(AUX_Z,keyZ) ; auxKeyFunc(AUX_S,keyS) ; auxKeyFunc(AUX_E,keyE) ; auxKeyFunc(AUX_D,keyD) ; auxKeyFunc(AUX_UP,up) ; auxKeyFunc(AUX_DOWN,down) ; auxKeyFunc(AUX_LEFT,left) ; auxKeyFunc(AUX_RIGHT,right) ; auxKeyFunc(AUX_SPACE,space) ; auxReshapeFunc(myReshape); auxMainLoop(display); }