/* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Avril 2001 */ /* Illustration de la propagation */ /* des rayons secondaires dans le cadre */ /* d'un algorithme de lancer de rayons */ #include #include #include #include #include #include "ModuleCouleurs.h" #include "ModuleFont.h" #include "ModuleManipulateur.h" #include "ModuleMenus.h" static float oz = 1.0F ; static float oy = 0.4F ; static int aff = 0 ; static float ratio ; static float alpha = 0.0F ; static float n = 1.2F ; int intersection(float px,float py,float pz,float dx,float dy,float dz,float *d1,float *d2) { float c = px*px+py*py+pz*pz - 9 ; float b = 2*(px*dx+py*dy+pz*dz) ; float a = dx*dx+dy*dy+dz*dz ; float delta = b*b - 4*a*c ; if ( delta < 0 ) return(0) ; if ( delta == 0.0F ) { *d1 = -b/2/a ; if ( *d1 >= 0.00001F ) return(1) ; else return(0) ; } *d2 = (-b-(float) sqrt(delta))/2/a ; *d1 = (-b+(float) sqrt(delta))/2/a ; if ( ( *d1 <= 0.0001F ) && ( *d2 <= 0.00001F ) ) return(0) ; if ( *d2 <= 0.0001F ) return(1) ; return(2) ; } void myinit(void) { GLfloat light_position0[] = { 0.0F,0.0F,1.0F,0.0F }; glLightfv(GL_LIGHT0,GL_AMBIENT,couleurNoir()); glLightfv(GL_LIGHT0,GL_DIFFUSE,couleurBlanc()); glLightfv(GL_LIGHT0,GL_SPECULAR,couleurNoir()); glLightfv(GL_LIGHT0,GL_POSITION,light_position0); glEnable(GL_LIGHT0); glEnable(GL_AUTO_NORMAL); glEnable(GL_NORMALIZE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_ALPHA_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); } void rayonOmbre(float x,float y,float z,float px,float py,float pz) { glColor4fv(couleurJaune()) ; glBegin(GL_LINES); glVertex3f(px,py,pz); if ( ( aff != 0 ) && ( alpha > 1.0F ) ) if ( alpha <= 2.0 ) glVertex3f(px+(alpha-1.0F)*(x-px),py+(alpha-1.0F)*(y-py),pz+(alpha-1.0F)*(z-pz)); else glVertex3f(x,y,z); if ( aff == 0 ) glVertex3f(x,y,z); glEnd(); glEnable(GL_LIGHTING); glMaterialfv(GL_FRONT,GL_DIFFUSE,couleurJaune()) ; if ( aff != 0 ) { if ( ( alpha > 1.0 ) && ( alpha <= 2.0 ) ) { glPushMatrix(); glTranslatef(px+(alpha-1.0F)*(x-px),py+(alpha-1.0F)*(y-py),pz+(alpha-1.0F)*(z-pz)) ; glutSolidSphere(0.1,36,36) ; glPopMatrix(); } } glPushMatrix(); glTranslatef(x,y,z) ; glutSolidSphere(0.1,36,36) ; glPopMatrix(); glDisable(GL_LIGHTING); } void rayonIncident(int n,float d) { glPushMatrix(); glColor4fv(couleurBlanc()); glBegin(GL_LINES); glVertex3f(-8.0F,oy,oz); if ( n ) { if ( aff == 0 ) glVertex3f(-8.0F+d,oy,oz); else if ( alpha <= 1.0 ) glVertex3f(-8.0F+alpha*d,oy,oz); else glVertex3f(-8.0F+d,oy,oz); } else { glVertex3f(8.0F,oy,oz); } glEnd(); glPopMatrix(); glEnable(GL_LIGHTING); if ( alpha <= 1.0 ) { glMaterialfv(GL_FRONT,GL_DIFFUSE,couleurBlanc()) ; glPushMatrix(); glTranslatef(-8.0F+d*alpha,oy,oz) ; glutSolidSphere(0.1,36,36) ; glPopMatrix(); } glDisable(GL_LIGHTING); } void rayonReflechi(float px,float py,float pz) { float nx = px/3.0F ; float ny = py/3.0F ; float nz = pz/3.0F ; float ix = -1.0F ; float iy = 0.0F ; float iz = 0.0F ; float scal = nx*ix ; float rx = 2*nx*scal-ix ; float ry = 2*ny*scal-iy ; float rz = 2*nz*scal-iz ; glPushMatrix(); glColor4fv(couleurRouge(0.5F)); glBegin(GL_LINES); glVertex3f(px,py,pz); if ( aff == 0 ) glVertex3f(px+5*rx,py+5*ry,pz+5*rz); else if ( alpha > 1.0F ) if ( alpha <= 2.0F ) glVertex3f(px+(alpha-1)*5*rx,py+(alpha-1)*5*ry,pz+(alpha-1)*5*rz); else glVertex3f(px+5*rx,py+5*ry,pz+5*rz); glEnd(); glPopMatrix(); glEnable(GL_LIGHTING); if ( alpha > 1.0 ) { glMaterialfv(GL_FRONT,GL_DIFFUSE,couleurRouge(0.5F)) ; glPushMatrix(); if ( alpha <= 2.0F ) glTranslatef(px+(alpha-1)*5*rx,py+(alpha-1)*5*ry,pz+(alpha-1)*5*rz) ; else glTranslatef(px+5*rx,py+5*ry,pz+5*rz) ; glutSolidSphere(0.1,36,36) ; glPopMatrix(); } glDisable(GL_LIGHTING); } void transmis(float nx,float ny,float nz,float ix,float iy,float iz,float n,float *tx,float *ty,float *tz) { float scal = nx*ix ; float t = n*scal-(float) sqrt(1.0F-n*n*(1-scal*scal)) ; *tx = t*nx-n*ix ; *ty = t*ny-n*iy ; *tz = t*nz-n*iz ; } void rayonTransmis(float px,float py,float pz) { float nx = px/3.0F ; float ny = py/3.0F ; float nz = pz/3.0F ; float ix = -1.0F ; float iy = 0.0F ; float iz = 0.0F ; float tx ; float ty ; float tz ; transmis(nx,ny,nz,ix,iy,iz,n,&tx,&ty,&tz); float d1 ; float d2 ; int ni = intersection(px,py,pz,tx,ty,tz,&d1,&d2) ; float pix = px+tx*d1 ; float piy = py+ty*d1 ; float piz = pz+tz*d1 ; float nix = pix / 3.0F ; float niy = piy / 3.0F ; float niz = piz / 3.0F ; float tix ; float tiy ; float tiz ; transmis(-nix,-niy,-niz,-tx,-ty,-tz,n,&tix,&tiy,&tiz); glPushMatrix(); glColor4fv(couleurBleu()); glBegin(GL_LINES); glVertex3f(px,py,pz); if ( aff == 0 ) glVertex3f(px+d1*tx,py+d1*ty,pz+d1*tz); else if ( alpha > 1.0 ) if ( alpha <=2.0 ) glVertex3f(px+(alpha-1)*d1*tx,py+(alpha-1)*d1*ty,pz+(alpha-1)*d1*tz); else glVertex3f(px+d1*tx,py+d1*ty,pz+d1*tz); glEnd(); glPopMatrix(); glPushMatrix(); glColor4fv(couleurMagenta()); glBegin(GL_LINES); glVertex3f(pix,piy,piz); if ( aff == 0 ) glVertex3f(pix+4*tix,piy+4*tiy,piz+4*tiz); else if ( alpha > 2.0 ) glVertex3f(pix+(alpha-2.0F)*4*tix,piy+(alpha-2.0F)*4*tiy,piz+(alpha-2.0F)*4*tiz); glEnd(); glPopMatrix(); glEnable(GL_LIGHTING); if ( alpha > 1.0 ) { glMaterialfv(GL_FRONT,GL_DIFFUSE,couleurBleu()) ; glPushMatrix(); if ( alpha <= 2.0 ) glTranslatef(px+(alpha-1)*d1*tx,py+(alpha-1)*d1*ty,pz+(alpha-1)*d1*tz) ; else glTranslatef(px+d1*tx,py+d1*ty,pz+d1*tz) ; glutSolidSphere(0.1,36,36) ; glPopMatrix(); } if ( alpha > 2.0 ) { glMaterialfv(GL_FRONT,GL_DIFFUSE,couleurMagenta()) ; glPushMatrix(); glTranslatef(pix+(alpha-2.0F)*4*tix,piy+(alpha-2.0F)*4*tiy,piz+(alpha-2.0F)*4*tiz); glutSolidSphere(0.1,36,36) ; glPopMatrix(); } glDisable(GL_LIGHTING); } void displayObjets(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); manipulateurSouris(); manipulateurClavier(); glTranslatef(1.0F,0.0F,0.0F); float d1 ; float d2 ; int n = intersection(-8.0F,oy,oz,1.0F,0.0F,0.0F,&d1,&d2) ; float px = -8.0F+d2 ; rayonIncident(n,d2) ; if ( n ) { switch ( aff ) { case 0 : case 1 : rayonOmbre(-4.0F,3.0F,4.0F,px,oy,oz) ; rayonOmbre(5.0F,-5.0F,-5.0F,px,oy,oz) ; rayonOmbre(-5.0F,-1.0F,5.0F,px,oy,oz) ; rayonReflechi(px,oy,oz) ; rayonTransmis(px,oy,oz) ; break ; case 2 : rayonOmbre(-4.0F,3.0F,4.0F,px,oy,oz) ; rayonOmbre(5.0F,-5.0F,-5.0F,px,oy,oz) ; rayonOmbre(-5.0F,-1.0F,5.0F,px,oy,oz) ; break ; case 3 : rayonReflechi(px,oy,oz) ; break ; case 4 : rayonTransmis(px,oy,oz) ; break ; } } glEnable(GL_LIGHTING); glPushMatrix(); glMaterialfv(GL_FRONT,GL_DIFFUSE,couleurVert(0.5F)) ; glutSolidSphere(3.0,36,36) ; glPopMatrix(); glDisable(GL_LIGHTING); glPopMatrix(); } void display(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); float xmin; float ymin; if ( ratio > 1.0F ) { xmin = -8.0F ; ymin = ratio*xmin; glOrtho(-8.0,8.0,-ratio*8.0,ratio*8.0,-150.0,150.0); } else { ymin = -8.0F ; xmin = ymin/ratio; glOrtho(-8.0/ratio,8.0/ratio,-8.0,8.0,-150.0,150.0); } setManipulateurDistance(1.0F); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPushMatrix() ; glEnable(GL_DEPTH_TEST); displayObjets() ; glDisable(GL_DEPTH_TEST); glColor4fv(couleurBlanc()); placeFontCursor(xmin+1.0F,ymin+1.0F,0.0F); simpleBitmapOutput("n = %f",n); glPopMatrix() ; glFlush(); glutSwapBuffers(); } void reshape(int w,int h) { glViewport(0,0,w,h); ratio =(float) h/w ; } void key(unsigned char key,int x,int y) { if ( keyManipulateur(key,x,y) ) glutPostRedisplay(); else switch ( key ) { case '2' : oy += 0.1F; glutPostRedisplay(); break; case '8' : oy -= 0.1F; glutPostRedisplay(); break; case '4' : oz += 0.1F; glutPostRedisplay(); break; case '6' : oz -= 0.1F; glutPostRedisplay(); break; case 0x0D : alpha = 0.0F ; aff = (aff+1)%5 ; glutPostRedisplay(); break; case 43 : n *= 1.02F; glutPostRedisplay(); break; case 45 : n /= 1.02F; glutPostRedisplay(); break; } } void idle(void) { if ( aff == 0 ) { alpha += 0.02F ; if ( alpha > 1.0F ) alpha = 0.0F ; } if ( aff != 0 ) { alpha += 0.02F ; if ( alpha > 3.0F ) alpha = 0.0F ; } glutPostRedisplay() ; } int main(int argc,char **argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); glutInitWindowSize(300,300); glutInitWindowPosition(50,50); glutCreateWindow("Rayons secondaires"); myinit(); creationMenuBasique(); glutKeyboardFunc(key); glutSpecialFunc(specialBasique); glutMotionFunc(motionBasique); glutMouseFunc(sourisBasique); glutIdleFunc(idle); glutReshapeFunc(reshape); glutDisplayFunc(display); glutMainLoop(); return(0); }