/* 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 <stdio.h>
#include <math.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#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);
}