/* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Avril 2001 */ /* Le clipping de Cohen-Sutherland en 3D */ #include #include #include #include #include #include #include "ModuleCouleurs.h" #include "ModuleManipulateur.h" #include "ModuleMenus.h" #include "ModuleReshape.h" 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 display(void) { glClearColor(0.0F,0.0F,0.0F,0.0F); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); manipulateurSouris(); manipulateurClavier(); glRotatef(30.0,1.0F,1.0F,1.0F) ; glColor4fv(couleurBlanc()) ; glPushMatrix(); glTranslatef((b.pi.x+b.pf.x)/2,(b.pi.y+b.pf.y)/2,(b.pi.z+b.pf.z)/2) ; glScalef(b.pi.x-b.pf.x,b.pi.y-b.pf.y,b.pi.z-b.pf.z) ; glutWireCube(1.0F); glPopMatrix(); glColor4fv(couleurRouge()) ; 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(); glutSwapBuffers(); } void myinit (void) { glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); } void key(unsigned char key,int x,int y) { if ( keyManipulateur(key,x,y) ) glutPostRedisplay(); else switch ( key ) { case ' ' : clip = 1-clip ; glutPostRedisplay(); break; case 'a' : b.pi.x += 0.05F ; glutPostRedisplay(); break; case 'A' : b.pi.x -= 0.1F ; glutPostRedisplay(); break; case 'q' : b.pf.x += 0.1F ; glutPostRedisplay(); break; case 'Q' : b.pf.x -= 0.1F ; glutPostRedisplay(); break; case 'z' : b.pi.y += 0.1F ; glutPostRedisplay(); break; case 'Z' : b.pi.y -= 0.1F ; glutPostRedisplay(); break; case 's' : b.pf.y += 0.1F ; glutPostRedisplay(); break; case 'S' : b.pf.y -= 0.1F ; glutPostRedisplay(); break; case 'e' : b.pi.z += 0.1F ; glutPostRedisplay(); break; case 'E' : b.pi.z -= 0.1F ; glutPostRedisplay(); break; case 'd' : b.pf.z += 0.1F ; glutPostRedisplay(); break; case 'D' : b.pf.z -= 0.1F ; glutPostRedisplay(); break; } } int main(int argc,char **argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); glutInitWindowSize(300,300); glutInitWindowPosition(50,50); glutCreateWindow("Clipping 3D"); myinit(); creationMenuBasique(); setParametresOrthoBasique(-10.0,10.0,-10.0,10.0,-500.0,500.0); setManipulateurDistance(1.0F); glutReshapeFunc(reshapeOrthoBasique); glutKeyboardFunc(key); glutSpecialFunc(specialBasique); glutMotionFunc(motionBasique); glutMouseFunc(sourisBasique); glutDisplayFunc(display); glutMainLoop(); return(0); }