CoordonneesHomogenes.h - CoordonneesHomogenes.cpp - Position3D.h - Position3D.cpp
ModuleAffichageChaineDeCarateres.h - ModuleAffichageChaineDeCarateres.cpp
/* Mathematiques de l'informatique graphique */
/* Direction en 3D */
/* */
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Novembre 2011 */
#ifndef ____DIRECTION3D____
#define ____DIRECTION3D____
class Position3D;
#include "CoordonneesHomogenes.h"
class Direction3D : public CoordonneesHomogenes {
public :
/* Constructeurs */
Direction3D(void);
Direction3D(double x,double y,double z);
Direction3D(Direction3D *c);
Direction3D(Position3D *p1,Position3D *p2);
/* Destructeur */
~Direction3D(void);
/* Methode de calcul de la norme */
double norme(void);
/* Methode de normalisation */
double normalisation(void);
/* Methode de calcul du produit scalaire */
/* de deux directions */
double produitScalaire(Direction3D *d);
/* Methode de calcul du produit vectoriel */
/* de deux directions */
void produitVectoriel(Direction3D *d1,Direction3D *d2);
/* Methode de calcul du produit vectoriel */
/* de deux directions */
Direction3D *produitVectoriel(Direction3D *d);
/* Methode de calcul de la direction */
/* du rayon reflechi au niveau d'une interface */
bool reflechi(Direction3D *i,Direction3D *n);
/* Methode de calcul de la direction */
/* du rayon transmis au niveau d'une interface */
bool transmis(Direction3D *i,Direction3D *n,double rp);
};
#endif
/* Mathematiques de l'informatique graphique */
/* Direction en 3D */
/* */
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Octobre 2011 */
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "CoordonneesHomogenes.h"
#include "Direction3D.h"
#include "Position3D.h"
/* Constructeurs */
Direction3D::Direction3D(void):CoordonneesHomogenes(0.0,0.0,0.0,0.0) {
}
Direction3D::Direction3D(double x,double y,double z):CoordonneesHomogenes(x,y,z,0.0) {
}
Direction3D::Direction3D(Direction3D *p):CoordonneesHomogenes(p) {
}
Direction3D::Direction3D(Position3D *p1,Position3D *p2):CoordonneesHomogenes() {
c[0] = p2->c[0]-p1->c[0];
c[1] = p2->c[1]-p1->c[1];
c[2] = p2->c[2]-p1->c[2];
c[3] = 0.0;
}
/* Destructeur */
Direction3D::~Direction3D(void) {
}
/* Methode de calcul de la norme */
double Direction3D::norme(void) {
return(sqrt(c[0]*c[0]+c[1]*c[1]+c[2]*c[2]));
}
/* Methode de normalisation */
double Direction3D::normalisation(void) {
double d = norme();
if ( d != 0.0 ) {
c[0] /= d;
c[1] /= d;
c[2] /= d; }
return(d);
}
/* Methode de calcul du produit scalaire */
/* de deux directions */
double Direction3D::produitScalaire(Direction3D *d) {
return(c[0]*d->c[0]+c[1]*d->c[1]+c[2]*d->c[2]);
}
/* Methode de calcul du produit vectoriel */
/* de deux directions */
void Direction3D::produitVectoriel(Direction3D *d1,Direction3D *d2) {
double x = d1->c[1]*d2->c[2] - d1->c[2]*d2->c[1];
double y = d1->c[2]*d2->c[0] - d1->c[0]*d2->c[2];
double z = d1->c[0]*d2->c[1] - d1->c[1]*d2->c[0];
c[0] = x;
c[1] = y;
c[2] = z;
c[3] = 0.0;
}
/* Methode de calcul du produit vectoriel */
/* de deux directions */
Direction3D *Direction3D::produitVectoriel(Direction3D *d) {
return(new Direction3D(c[1]*d->c[2] - c[2]*d->c[1],
c[2]*d->c[0] - c[0]*d->c[2],
c[0]*d->c[1] - c[1]*d->c[0]));
}
bool Direction3D::reflechi(Direction3D *i,Direction3D *n) {
double ps = i->produitScalaire(n);
if ( ps < 0.0 )
return(false);
c[0] = 2.0*ps*n->c[0]-i->c[0];
c[1] = 2.0*ps*n->c[1]-i->c[1];
c[2] = 2.0*ps*n->c[2]-i->c[2];
c[3] = 0.0;
return(true);
}
bool Direction3D::transmis(Direction3D *i,Direction3D *n,double rp) {
double ps = i->produitScalaire(n);
double fact = 1.0-rp*rp*(1.0-ps*ps);
if ( fact < 0.0 )
return(false);
fact = rp*ps-sqrt(fact);
c[0] = fact*n->c[0]-rp*i->c[0];
c[1] = fact*n->c[1]-rp*i->c[1];
c[2] = fact*n->c[2]-rp*i->c[2];
c[3] = 0.0;
return(true);
}
/* Mathematiques de l'informatique graphique */
/* Sphere */
/* */
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Novembre 2011 */
#ifndef ____SPHERE____
#define ____SPHERE____
class Position3D;
class Rayon;
class Sphere {
public :
Position3D *centre;
double rayon;
public :
/* Constructeurs */
Sphere(void);
Sphere(double cx,double cy,double cz,double rayon);
Sphere(Position3D *c,double rayon);
/* Destructeur */
~Sphere(void);
/* Methode de test de l'intersection */
/* entre une sphere et un rayon */
bool intersection(Rayon *r);
/* Methode de test de l'intersection */
/* entre une sphere et un rayon */
/* t rendu a la distance a l'intersection */
bool intersection(Rayon *r,double *t);
};
#endif
/* Mathematiques de l'informatique graphique */
/* Sphere */
/* */
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Novembre 2011 */
#include <math.h>
#include <stdio.h>
#include "Sphere.h"
#include "Position3D.h"
#include "Direction3D.h"
#include "Rayon.h"
Sphere::Sphere(void) {
centre = new Position3D();
rayon = 1.0;
}
Sphere::Sphere(double cx,double cy,double cz,double rayon) {
centre = new Position3D(cx,cy,cz);
this->rayon = rayon;
}
Sphere::Sphere(Position3D *c,double rayon) {
centre = new Position3D(c);
this->rayon = rayon;
}
Sphere::~Sphere(void) {
delete(centre);
}
bool Sphere::intersection(Rayon *r) {
double dpx = centre->c[0]-r->pos->c[0];
double dpy = centre->c[1]-r->pos->c[1];
double dpz = centre->c[2]-r->pos->c[2];
double a = r->dir->c[0]*r->dir->c[0]+
r->dir->c[1]*r->dir->c[1]+
r->dir->c[2]*r->dir->c[2];
double b = -2.0*(r->dir->c[0]*dpx+
r->dir->c[1]*dpy+
r->dir->c[2]*dpz);
double c = dpx*dpx+dpy*dpy+dpz*dpz-rayon*rayon;
double delta = b*b-4.0*a*c;
if ( delta < 0.0 )
return(false);
if ( delta == 0.0 ) {
double t = -b/(2.0*a);
return(t > 0.0); }
double t1 = (-b-sqrt(delta))/(2.0*a);
if ( t1 > 0.0 )
return(true);
double t2 = (-b+sqrt(delta))/(2.0*a);
return(t2 > 0.0);
}
bool Sphere::intersection(Rayon *r,double *tt) {
double dpx = centre->c[0]-r->pos->c[0];
double dpy = centre->c[1]-r->pos->c[1];
double dpz = centre->c[2]-r->pos->c[2];
double a = r->dir->c[0]*r->dir->c[0]+
r->dir->c[1]*r->dir->c[1]+
r->dir->c[2]*r->dir->c[2];
double b = -2.0*(r->dir->c[0]*dpx+
r->dir->c[1]*dpy+
r->dir->c[2]*dpz);
double c = dpx*dpx+dpy*dpy+dpz*dpz-rayon*rayon;
double delta = b*b-4.0*a*c;
if ( delta < 0.0 )
return(false);
if ( delta == 0.0 ) {
double t = -b/(2.0*a);
if ( t > 0.0 ) {
*tt = t;
return(true); }
else
return(false); }
double t1 = (-b-sqrt(delta))/(2.0*a);
double t2 = (-b+sqrt(delta))/(2.0*a);
double min = ( t1 < t2 ) ? t1 : t2;
double max = ( t1 > t2 ) ? t1 : t2;
if ( ( t1 <= 0.0 ) && ( t2 <= 0.0 ) )
return(false);
if ( t1 <= 0.0 )
*tt = t2;
else
*tt = t1;
return(true);
}
/* Mathematiques de l'informatique graphique */
/* Rayon lumineux */
/* */
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Novembre 2011 */
#ifndef ____RAYON____
#define ____RAYON____
class Position3D;
class Direction3D;
class Sphere;
class Rayon {
public :
Position3D *pos;
Direction3D *dir;
public :
/* Constructeurs */
Rayon(void);
Rayon(double px,double py,double pz,
double dx,double dy,double dz);
Rayon(Position3D *c,Direction3D *d);
/* Destructeur */
~Rayon(void);
/* Methode de test de l'intersection */
/* entre un rayon et une sphere */
bool intersection(Sphere *s);
};
#endif
/* Mathematiques de l'informatique graphique */
/* Rayon lumineux */
/* */
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Novembre 2011 */
#include "Rayon.h"
#include "Position3D.h"
#include "Direction3D.h"
#include "Sphere.h"
Rayon::Rayon(void) {
pos = new Position3D();
dir = new Direction3D();
}
Rayon::Rayon(double px,double py,double pz,
double dx,double dy,double dz){
pos = new Position3D(px,py,pz);
dir = new Direction3D(dx,dy,dz);
}
Rayon::Rayon(Position3D *c,Direction3D *d) {
pos = new Position3D(c);
dir = new Direction3D(d);
}
Rayon::~Rayon(void) {
delete(pos);
delete(dir);
}
bool Rayon::intersection(Sphere *s) {
return(s->intersection(this));
}
Le source : MathematiquesLancerDeRayons.cpp
/* Implantation mathematique */
/* d'operations utilisees */
/* en lancer de rayons */
/* */
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Novembre 2011 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "ModuleAffichageChaineDeCarateres.h"
#include "Position3D.h"
#include "Direction3D.h"
#include "Sphere.h"
#include "Rayon.h"
/* Variables et constantes globales */
/* pour les angles et les couleurs utilises */
static int f1;
static int aff = 1;
static float rx = -20.0F;
static float ry = 0.0F;
static float rz = 0.0F;
static float px = -0.1F;
static float py = 0.1F;
static float pz = 0.2F;
static float rp = 1.0F;
static void postRedisplay(void) {
glutPostWindowRedisplay(f1);
}
/* Fonction executee lors d'un changement */
/* de la taille de la fenetre (1) */
void reshape(int w,int h) {
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0F,1.0,(float) -h/w,(float) h/w,-50.0,50.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
/* Fonction executee lors d'un rafraichissement */
/* de la fenetre de dessin (1) */
static void drawDirection(Direction3D *d) {
glBegin(GL_LINES);
glVertex3f(0.0F,0.0F,0.0F);
glVertex3d(d->c[0],d->c[1],d->c[2]);
glEnd();
}
void displayReflexionEtTransmission() {
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
glPushMatrix();
glRotatef(rz,0.0F,0.0F,1.0F);
glRotatef(ry,0.0F,1.0F,0.0F);
glRotatef(rx,1.0F,0.0F,0.0F);
glLineWidth(2.0F);
glDisable(GL_CULL_FACE);
glDisable(GL_LIGHTING);
Direction3D *n = new Direction3D(0.3,0.6,sqrt(1.0-0.6*0.6-0.3*0.3));
Direction3D *i = new Direction3D(-0.3,0.7,sqrt(1.0-0.7*0.7-0.3*0.3));
Direction3D *a1 = new Direction3D();
a1->produitVectoriel(n,i);
Direction3D *a2 = new Direction3D();
a2->produitVectoriel(n,a1);
Direction3D *r = new Direction3D();
bool rr;
if ( rr = r->reflechi(i,n) ) {
glColor4f(1.0F,0.0F,0.0F,1.0F);
drawDirection(r); }
Direction3D *t = new Direction3D();
bool rt;
if ( rt = t->transmis(i,n,rp) ) {
glColor4f(0.0F,1.0F,0.0F,1.0F);
drawDirection(t); }
glColor4f(1.0F,1.0F,0.0,1.0F);
drawDirection(i);
glColor4f(1.0F,0.0F,1.0F,1.0F);
drawDirection(n);
glColor4f(0.5F,0.5F,0.5F,0.5F);
glBegin(GL_QUADS);
glVertex3f(a1->c[0]*2.0F,a1->c[1]*2.0F,a1->c[2]*2.0F);
glVertex3f(a2->c[0]*2.0F,a2->c[1]*2.0F,a2->c[2]*2.0F);
glVertex3f(-a1->c[0]*2.0F,-a1->c[1]*2.0F,-a1->c[2]*2.0F);
glVertex3f(-a2->c[0]*2.0F,-a2->c[1]*2.0F,-a2->c[2]*2.0F);
glEnd();
drawString(10,20,"I : %6.3lf %6.3lf %6.3lf",i->c[0],i->c[1],i->c[2]);
drawString(10,40,"N : %6.3lf %6.3lf %6.3lf",n->c[0],n->c[1],n->c[2]);
drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-50,"Rapport ni/nt : %7.4lf",rp);
if ( rr )
drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-30,
"R : %6.3lf %6.3lf %6.3lf",r->c[0],r->c[1],r->c[2]);
else
drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-30,"R : inexistant");
if ( rt )
drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-10,
"T : %6.3lf %6.3lf %6.3lf",t->c[0],t->c[1],t->c[2]);
else
drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-10,"T : inexistant");
delete(t);
delete(r);
delete(i);
delete(n);
delete(a1);
delete(a2);
glPopMatrix();
glutSwapBuffers();
int error = glGetError();
if ( error != GL_NO_ERROR )
printf("Erreur OpenGL: %d\n",error);
}
void drawPoint(double ix,double iy,double iz) {
glDisable(GL_DEPTH_TEST);
glPushMatrix();
glPointSize(5.0F);
glColor4f(0.0F,1.0F,0.0,1.0F);
glBegin(GL_POINTS);
glVertex3d(ix,iy,iz);
glEnd();
glPopMatrix();
glEnable(GL_DEPTH_TEST);
}
void drawSphere(Sphere *s) {
glPushMatrix();
glTranslated(s->centre->c[0],s->centre->c[1],s->centre->c[2]);
glutSolidSphere(s->rayon,72,72);
glPopMatrix();
}
void drawRayon(Rayon *r) {
glLineWidth(2.0F);
glPointSize(5.0F);
glColor4f(1.0F,0.0F,0.0,1.0F);
glPushMatrix();
glTranslated(r->pos->c[0],r->pos->c[1],r->pos->c[2]);
glBegin(GL_POINTS);
glVertex3d(0.0,0.0,0.0);
glEnd();
glBegin(GL_LINES);
glVertex3d(0.0,0.0,0.0);
glVertex3dv((double *) r->dir);
glEnd();
glPopMatrix();
}
void displayIntersection() {
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
glPushMatrix();
const GLfloat light0_position[] = { 1.0,1.0,1.0,0.0 };
const GLfloat light1_position[] = { -1.0,1.0,1.0,0.0 };
glLightfv(GL_LIGHT0,GL_POSITION,light0_position);
glLightfv(GL_LIGHT1,GL_POSITION,light1_position);
glRotatef(rz,0.0F,0.0F,1.0F);
glRotatef(ry,0.0F,1.0F,0.0F);
glRotatef(rx,1.0F,0.0F,0.0F);
Rayon *r = new Rayon(px,py,pz,0.5,0.6,-sqrt(1.0-0.25-0.36));
drawRayon(r);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
Sphere *s = new Sphere(0.2,0.1,-0.3,0.5);
drawSphere(s);
glDisable(GL_CULL_FACE);
glDisable(GL_LIGHTING);
drawString(10,20,"Rp = %7.4lf %7.4lf %7.4lf",
r->pos->c[0],r->pos->c[1],r->pos->c[2]);
drawString(10,40,"Rd = %7.4lf %7.4lf %7.4lf",
r->dir->c[0],r->dir->c[1],r->dir->c[2]);
drawString(10,65,"Sp = %7.4lf %7.4lf %7.4lf",
s->centre->c[0],s->centre->c[1],s->centre->c[2]);
drawString(10,85,"Sr = %7.4lf",s->rayon);
if ( s->intersection(r) ) {
double t;
s->intersection(r,&t);
double ix = r->pos->c[0] + t*r->dir->c[0];
double iy = r->pos->c[1] + t*r->dir->c[1];
double iz = r->pos->c[2] + t*r->dir->c[2];
drawPoint(ix,iy,iz);
drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-50,"Intersection");
drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-30,"t = %lf",t);
drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-10,
"pos = %7.4lf %7.4lf %7.4lf",ix,iy,iz); }
else {
drawString(10,glutGet(GLUT_WINDOW_HEIGHT)-10,"Pas d'intersection"); }
delete(r);
delete(s);
glPopMatrix();
glutSwapBuffers();
int error = glGetError();
if ( error != GL_NO_ERROR )
printf("Erreur OpenGL: %d\n",error);
}
void myinit(void) {
const GLfloat gris[] = { 0.8F,0.8F,0.8F,1.0F };
const GLfloat blanc[] = { 1.0F,1.0F,1.0F,0.5F };
const GLfloat mat_shininess[] = { 50.0 };
glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
glMaterialfv(GL_FRONT,GL_SPECULAR,blanc);
glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
glLightfv(GL_LIGHT0,GL_DIFFUSE,gris);
glLightfv(GL_LIGHT1,GL_DIFFUSE,gris);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
}
/* Fonction executee lors de la frappe */
/* d'une touche special du clavier: */
/* - touches de curseur */
/* - touches de fonction */
/* - ... */
void special(int code,int x,int y) {
switch ( code ) {
case GLUT_KEY_UP :
rx += 1.0F;
postRedisplay();
break;
case GLUT_KEY_DOWN :
rx -= 1.0F;
postRedisplay();
break;
case GLUT_KEY_RIGHT :
ry += 1.0F;
postRedisplay();
break;
case GLUT_KEY_LEFT :
ry -= 1.0F;
postRedisplay();
break;
case GLUT_KEY_PAGE_UP :
rz += 1.0F;
postRedisplay();
break;
case GLUT_KEY_PAGE_DOWN :
rz -= 1.0F;
postRedisplay();
break; }
}
/* Fonction executee lorsqu'aucun evenement */
/* n'est en file d'attente */
void idle(void) {
rx += 0.03355F;
ry += 0.06117F;
rz += 0.04174F;
postRedisplay();
}
/* Fonction executee lors de l'appui */
/* d'une touche alphanumerique du clavier */
void keyboard(unsigned char key,int x,int y) {
switch (key) {
case 43 :
rp *= 0.99F;
postRedisplay();
break;
case 45 :
rp /= 0.99F;
postRedisplay();
break;
case 'x' :
px -= 0.02F;
postRedisplay();
break;
case 'X' :
px += 0.02F;
postRedisplay();
break;
case 'y' :
py -= 0.02F;
postRedisplay();
break;
case 'Y' :
py += 0.02F;
postRedisplay();
break;
case 'z' :
pz -= 0.02F;
postRedisplay();
break;
case 'Z' :
px += 0.02F;
postRedisplay();
break;
case 'r' :
rx = 0.0F;
ry = 0.0F;
rz = 0.0F;
postRedisplay();
break;
case 0x20 :
aff = (aff+1)%2;
if ( aff )
glutDisplayFunc(displayReflexionEtTransmission);
else
glutDisplayFunc(displayIntersection);
postRedisplay();
break;
case 0x0D :
{ static int anim = 0;
anim = !anim;
glutIdleFunc(( anim ) ? idle : NULL); }
break;
case 0x1B :
exit(0);
break; }
}
int main(int argc,char **argv) {
glutInit(&argc,argv);
glutInitWindowSize(310,380);
glutInitWindowPosition(50,50);
glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
f1 = glutCreateWindow("Mathematiques pour le ray tracing");
myinit();
glutDisplayFunc(displayReflexionEtTransmission);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutSpecialFunc(special);
glutMainLoop();
return(0);
}