Le source : Exam-TD2-2004-2005-Exo2b.cpp
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Decembre 2004 */
/* Calcul d'une surface parametrique bicubique */
/* avec affichage de sa normale */
#include <math.h>
#include <stdio.h>
#include <stdlib.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"
#include "ModuleFleche.h"
#include "ModuleFont.h"
struct coord_3D {
GLfloat x,y,z,t ; } ;
typedef float matrice[4][4] ;
typedef float vecteur[4] ;
static int f1;
static int f2;
static coord_3D pts[16] = {
{-1.5F,-1.5F,-0.5F,1.0F},{-0.5F,-1.5F, 1.5F,1.0F},{0.5F,-1.5F, 2.0F,1.0F},{1.5F,-1.5F,-1.5F,1.0F},
{-1.5F,-0.5F, 2.5F,1.0F},{-0.5F,-0.5F, 2.0F,1.0F},{0.5F,-0.5F,-1.5F,1.0F},{1.5F,-0.5F, 0.5F,1.0F},
{-1.5F, 0.5F,-0.5F,1.0F},{-0.5F, 0.5F,-0.5F,1.0F},{0.5F, 0.5F, 1.5F,1.0F},{1.5F, 0.5F,-1.5F,1.0F},
{-1.5F, 1.5F,-2.0F,1.0F},{-0.5F, 1.5F, 2.5F,1.0F},{0.5F, 1.5F, 2.5F,1.0F},{1.5F, 1.5F, 0.5F,1.0F} } ;
static coord_3D *points = pts ;
static int aff = 0 ;
static int point = 0 ;
static int maille = 8 ;
static int norm = 1 ;
static int md = 1 ;
static float s = 0.5F ;
static float t = 0.5F ;
static coord_3D pt;
static coord_3D nm;
static matrice nrubs =
{ -0.1666666F, 0.5F, -0.5F, 0.1666666F,
0.5F ,-1.0F, 0.5F, 0.0F,
-0.5F , 0.0F, 0.5F, 0.0F,
0.1666666F, 0.6666666F, 0.1666666F,0.0F } ;
static matrice cr =
{ -0.5F, 1.5F,-1.5F, 0.5F,
1.0F,-2.5F, 2.0F,-0.5F,
-0.5F, 0.0F, 0.5F, 0.0F,
0.0F, 1.0F, 0.0F, 0.0F } ;
static matrice bezier =
{ -1.0F, 3.0F,-3.0F, 1.0F,
3.0F,-6.0F, 3.0F, 0.0F,
-3.0F, 3.0F, 0.0F, 0.0F,
1.0F, 0.0F, 0.0F, 0.0F } ;
void pixel(float x,float y,float z) {
glVertex3f(x,y,z);
}
void vectoriel(struct coord_3D *v1,struct coord_3D *v2,struct coord_3D *v) {
v->x = v1->y*v2->z - v1->z*v2->y;
v->y = v1->z*v2->x - v1->x*v2->z;
v->z = v1->x*v2->y - v1->y*v2->x;
}
void normalize(struct coord_3D *n) {
float d =(float) sqrt(n->x*n->x+n->y*n->y+n->z*n->z);
if ( d != 0.0F) {
n->x /= d;
n->y /= d;
n->z /= d;}
}
void pixel(struct coord_3D *p,struct coord_3D *n) {
glNormal3f(n->x,n->y,n->z);
glVertex3f(p->x,p->y,p->z);
}
void transposition(matrice m,matrice t) {
for ( int i = 0 ; i < 4 ; i++ )
for ( int j = 0 ; j < 4 ; j++ )
t[i][j] = m[j][i];
}
void produitMatriceMatrice(matrice m1,matrice m2,matrice m) {
matrice mt;
int i;
for ( i = 0 ; i < 4 ; i++ )
for ( int j = 0 ; j < 4 ; j++ ) {
mt[i][j] = 0 ;
for ( int k = 0 ; k < 4 ; k++ )
mt[i][j] += m1[i][k]*m2[k][j]; }
for ( i = 0 ; i < 4 ; i++ )
for ( int j = 0 ; j < 4 ; j++ ) {
m[i][j] = mt[i][j]; }
}
void produitMatriceVecteur(matrice m,vecteur v,vecteur r) {
vecteur vt;
int i;
for ( i = 0 ; i < 4 ; i++ ) {
vt[i] = 0 ;
for ( int j = 0 ; j < 4 ; j++ )
vt[i] += m[i][j]*v[j]; }
for ( i = 0 ; i < 4 ; i++ ) {
r[i] = vt[i]; }
}
void produitVecteurMatrice(vecteur v,matrice m,vecteur r) {
vecteur vt;
int i;
for ( i = 0 ; i < 4 ; i++ ) {
vt[i] = 0 ;
for ( int j = 0 ; j < 4 ; j++ )
vt[i] += v[j]*m[j][i]; }
for ( i = 0 ; i < 4 ; i++ ) {
r[i] = vt[i]; }
}
float produitVecteurVecteur(vecteur v1,vecteur v2) {
float r = 0 ;
for ( int i = 0 ; i < 4 ; i++ )
r += v1[i]*v2[i];
return(r) ;
}
void trouvePosition(vecteur s,vecteur t,matrice m,matrice mprime,coord_3D *p,coord_3D *coord) {
matrice trans ;
transposition(mprime,trans) ;
matrice mx ;
matrice my ;
matrice mz ;
for ( int i = 0 ; i < 4 ; i++ )
for ( int j = 0 ; j < 4 ; j++ ) {
mx[i][j] = p[i*4+j].x ;
my[i][j] = p[i*4+j].y ;
mz[i][j] = p[i*4+j].z ; }
produitMatriceMatrice(m,mx,mx) ;
produitMatriceMatrice(m,my,my) ;
produitMatriceMatrice(m,mz,mz) ;
produitMatriceMatrice(mx,trans,mx) ;
produitMatriceMatrice(my,trans,my) ;
produitMatriceMatrice(mz,trans,mz) ;
vecteur d;
produitVecteurMatrice(s,mx,d) ;
coord->x = produitVecteurVecteur(d,t) ;
produitVecteurMatrice(s,my,d) ;
coord->y = produitVecteurVecteur(d,t) ;
produitVecteurMatrice(s,mz,d) ;
coord->z = produitVecteurVecteur(d,t) ;
}
void dessinePatchBicubique(int n,matrice m,matrice mprime,coord_3D *p) {
int i;
struct coord_3D **pts =(struct coord_3D **) malloc(n*sizeof(struct coord_3D *));
struct coord_3D **nms =(struct coord_3D **) malloc(n*sizeof(struct coord_3D *));
for ( i = 0 ; i < n ; i++ ) {
pts[i] =(struct coord_3D *) malloc(n*sizeof(struct coord_3D));
nms[i] =(struct coord_3D *) malloc(n*sizeof(struct coord_3D)); }
for ( i = 0 ; i < n ; i++ ) {
float s =(float) i/(float) (n-1) ;
vecteur S = { s*s*s,s*s,s,1.0F } ;
vecteur dS = { 3*s*s,2*s,1.0F,0.0F } ;
for ( int j = 0 ; j < n ; j++ ) {
float t =(float) j/(float) (n-1) ;
vecteur T = { t*t*t,t*t,t,1.0F } ;
vecteur dT = { 3*t*t,2*t,1.0F,0.0F } ;
trouvePosition(S,T,m,mprime,p,&pts[i][j]);
coord_3D ds,dt;
trouvePosition(dS,T,m,mprime,p,&ds);
normalize(&ds);
trouvePosition(S,dT,m,mprime,p,&dt);
normalize(&dt);
vectoriel(&dt,&ds,&nms[i][j]); } }
if ( !md )
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_QUADS);
for ( i = 0 ; i < n-1 ; i++ )
for ( int j = 0 ; j < n-1 ; j++ ) {
pixel(&pts[i][j],&nms[i][j]);
pixel(&pts[i+1][j],&nms[i+1][j]);
pixel(&pts[i+1][j+1],&nms[i+1][j+1]);
pixel(&pts[i][j+1],&nms[i][j+1]); }
glEnd();
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHT2);
glMaterialfv(GL_FRONT,GL_DIFFUSE,couleurRougeFonce());
if ( norm )
for ( i = 0 ; i < n ; i++ )
for ( int j = 0 ; j < n ; j++ ) {
glPushMatrix();
glTranslatef(pts[i][j].x,pts[i][j].y,pts[i][j].z);
flecheEnVolume(nms[i][j].x,nms[i][j].y,nms[i][j].z,0.04F,0.3F,0.01F) ;
glPopMatrix(); }
else {
vecteur S = { s*s*s,s*s,s,1.0F } ;
vecteur T = { t*t*t,t*t,t,1.0F } ;
vecteur dS = { 3*s*s,2*s,1.0F,0.0F } ;
vecteur dT = { 3*t*t,2*t,1.0F,0.0F } ;
trouvePosition(S,T,m,mprime,p,&pt);
coord_3D ds,dt;
trouvePosition(dS,T,m,mprime,p,&ds);
trouvePosition(S,dT,m,mprime,p,&dt);
vectoriel(&dt,&ds,&nm);
normalize(&nm);
glPushMatrix();
glTranslatef(pt.x,pt.y,pt.z);
flecheEnVolume(nm.x,nm.y,nm.z,0.04F,0.3F,0.01F) ;
glPopMatrix(); }
glMaterialfv(GL_FRONT,GL_DIFFUSE,couleurGrisClair());
glDisable(GL_LIGHT1);
glDisable(GL_LIGHT2);
for ( i = 0 ; i < n ; i++ ) {
free(pts[i]);
free(nms[i]); }
free(pts);
free(nms);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
manipulateurSouris();
manipulateurClavier();
glEnable(GL_DEPTH_TEST);
glPointSize(5.0);
glBegin(GL_POINTS);
for ( int i = 0 ; i < 16 ; i++ ) {
if ( i != point )
glColor4fv(couleurJaune());
else
glColor4fv(couleurVert());
glVertex3fv((float *) &pts[i]); }
glEnd();
glColor4fv(couleurCyan());
glEnable(GL_LIGHTING);
glPointSize(1.0);
switch ( aff ) {
case 0 : dessinePatchBicubique(maille,bezier,bezier,points);
break ;
case 1 : dessinePatchBicubique(maille,bezier,cr,points);
break ;
case 2 : dessinePatchBicubique(maille,cr,bezier,points);
break ;
case 3 : dessinePatchBicubique(maille,cr,cr,points);
break ;
case 4 : dessinePatchBicubique(maille,nrubs,nrubs,points);
break ;
case 5 : dessinePatchBicubique(maille,nrubs,cr,points);
break ;
case 6 : dessinePatchBicubique(maille,cr,nrubs,points);
break ; }
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glPopMatrix();
glFlush();
glutSwapBuffers();
glutPostWindowRedisplay(f2);
}
void myinit(void) {
glClearColor(0.75,0.75,0.75,1.0);
glShadeModel(GL_SMOOTH);
glDepthFunc(GL_LESS);
GLfloat shinines[] = { 50.0 };
GLfloat l_pos0[] = { 1.0,1.0,1.0,0.0 };
GLfloat l_pos1[] = { -1.0,0.0,1.0,0.0 };
GLfloat l_pos2[] = { -1.0,0.0,1.0,0.0 };
glMaterialfv(GL_FRONT,GL_DIFFUSE,couleurGrisClair());
glMaterialfv(GL_FRONT,GL_SPECULAR,couleurBlanc());
glMaterialfv(GL_FRONT,GL_SHININESS,shinines);
glLightfv(GL_LIGHT0,GL_POSITION,l_pos0);
glLightfv(GL_LIGHT1,GL_POSITION,l_pos1);
glLightfv(GL_LIGHT1,GL_POSITION,l_pos2);
glLightfv(GL_LIGHT1,GL_DIFFUSE,couleurBlanc());
glLightfv(GL_LIGHT2,GL_DIFFUSE,couleurBlanc());
glEnable(GL_LIGHT0);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
}
void redisplay(void) {
glutPostWindowRedisplay(f1);
}
void key(unsigned char key,int x,int y) {
if ( keyManipulateur(key,x,y) )
glutPostRedisplay();
else
switch ( key ) {
case 32 : norm = !norm;
redisplay();
break;
case 45 : maille-- ;
if ( maille < 5 )
maille = 5 ;
redisplay();
break;
case 43 : maille++ ;
redisplay();
break;
case 's' : s += 0.01F ;
if ( s > 1.0F )
s = 1.0F;
redisplay();
break;
case 'S' : s -= 0.01F ;
if ( s < 0.0F )
s = 0.0F;
redisplay();
break;
case 't' : t += 0.01F ;
if ( t > 1.0F )
t = 1.0F;
redisplay();
break;
case 'T' : t -= 0.01F ;
if ( t < 0.0F )
t = 0.0F;
redisplay();
break;
case 'm' :
case 'M' : md = !md;
redisplay();
break;
case 0x0D : aff =(aff+1)%7 ;
redisplay();
break;
case 'p' :
case 'P' : point = (point+1)%16 ;
redisplay();
break; }
}
void special(int k, int x, int y) {
switch (k) {
case GLUT_KEY_LEFT : points[point].x -= 0.1F;
redisplay();
break;
case GLUT_KEY_RIGHT : points[point].x += 0.1F;
redisplay();
break;
case GLUT_KEY_UP : points[point].y += 0.1F;
redisplay();
break;
case GLUT_KEY_DOWN : points[point].y -= 0.1F;
redisplay();
break;
case GLUT_KEY_PAGE_UP : points[point].z += 0.1F ;
redisplay();
break;
case GLUT_KEY_PAGE_DOWN : points[point].z += 0.1F ;
redisplay();
break; }
}
void select1(int selection) {
switch (selection) {
case 1 : norm = 1;
redisplay();
break;
case 2 : norm = 0;
redisplay();
break; }
}
void select2(int selection) {
switch (selection) {
case 0 :
case 1 :
case 2 :
case 3 :
case 4 :
case 5 :
case 6 : aff = selection ;
redisplay();
break; }
}
void select3(int selection) {
switch (selection) {
case 10 : maille = 5;
redisplay();
break;
case 11 : maille = 10;
redisplay();
break;
case 12 : maille = 25;
redisplay();
break;
case 13 : maille = 50;
redisplay();
break;
case 14 : maille = 100;
redisplay();
break;
case 6 : maille++;
redisplay();
break;
case 7 : maille--;
if ( maille < 3 )
maille = 3;
redisplay();
break; }
}
void select(int selection) {
switch (selection) {
case 1 : point = (point+1)%4;
redisplay();
break;
case 0 : exit(0); }
}
void creationMenu(void) {
int menu1 = glutCreateMenu(select1);
glutAddMenuEntry("Toutes",1);
glutAddMenuEntry("Une",2);
int menu2 = glutCreateMenu(select2);
glutAddMenuEntry("Bezier x Bezier",0);
glutAddMenuEntry("Bezier x Catmull Rom",1);
glutAddMenuEntry("Catmull Rom x Bezier",2);
glutAddMenuEntry("Catmull Rom x Catmull Rom",3);
glutAddMenuEntry("NRUBS x NRUBS",4);
glutAddMenuEntry("NRUBS x Catmull Rom",5);
glutAddMenuEntry("Catmull Rom x NRUBS",6);
int menu3 = glutCreateMenu(select3);
glutAddMenuEntry("5",10);
glutAddMenuEntry("10",11);
glutAddMenuEntry("25",12);
glutAddMenuEntry("50",13);
glutAddMenuEntry("100",14);
glutAddMenuEntry("Augmenter",6);
glutAddMenuEntry("Reduire",7);
glutCreateMenu(select);
glutAddSubMenu("Affichage",menu2);
glutAddSubMenu("Discretisation",menu3);
glutAddSubMenu("Tangentes",menu1);
glutAddMenuEntry("Changer point",1);
glutAddMenuEntry("Quitter",0);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
void reshape2(int w,int h) {
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,w,-h,0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void display2() {
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
glClearColor(0.0F,0.0F,0.0F,1.0F) ;
glPushMatrix();
glColor4fv(couleurBlanc());
float pos = 1.0F;
placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
switch ( aff ) {
case 0 :
case 1 : simpleBitmapOutput(1,REGULAR8x13,"Bezier en s") ;
break ;
case 2 :
case 3 :
case 6 : simpleBitmapOutput(1,REGULAR8x13,"Catmull Rom en s") ;
break ;
case 4 :
case 5 : simpleBitmapOutput(1,REGULAR8x13,"Non Uniforme Rationel en s") ;
break ; }
pos += 1.0F;
placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
switch ( aff ) {
case 0 :
case 2 : simpleBitmapOutput(1,REGULAR8x13,"Bezier en t") ;
break ;
case 1 :
case 3 :
case 5 : simpleBitmapOutput(1,REGULAR8x13,"Catmull Rom en t") ;
break ;
case 4 :
case 6 : simpleBitmapOutput(1,REGULAR8x13,"Non Uniforme Rationel en t") ;
break ; }
if ( !norm ) {
pos += 1.0F;
placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR8x13,"s :%7.3f",s) ;
pos += 1.0F;
placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR8x13,"t :%7.3f",t) ;
pos += 1.0F;
placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR8x13,"Position :%7.3f%7.3f%7.3f",pt.x,pt.y,pt.z) ;
pos += 1.0F;
placeFontCursor(5.0F,-pos*20.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR8x13,"Normale :%7.3f%7.3f%7.3f",nm.x,nm.y,nm.z) ; }
glPopMatrix();
glutSwapBuffers();
}
int main(int argc,char **argv) {
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
glutInitWindowSize(270,270);
glutInitWindowPosition(50,50);
f1 = glutCreateWindow("Surface bicubique avec normales");
myinit();
creationMenu();
setParametresOrthoBasique(-2.5,2.5,-2.5,2.5,-10.0,10.0);
setManipulateurDistance(1.0F);
glutReshapeFunc(reshapeOrthoBasique);
glutKeyboardFunc(key);
glutSpecialFunc(special);
glutMotionFunc(motionBasique);
glutMouseFunc(sourisBasique);
setIdleWindow(f1);
glutIdleFunc(idleBasique);
glutDisplayFunc(display);
glutInitWindowSize(320,130);
glutInitWindowPosition(60,380);
glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
f2 = glutCreateWindow("Valeurs");
creationMenuBasique();
glutDisplayFunc(display2);
glutReshapeFunc(reshape2);
glutKeyboardFunc(key);
glutSpecialFunc(special);
glutMainLoop();
return(0);
}