/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Avril 2001 */
/* Le clipping de Cohen-Sutherland en 3D */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#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);
}