Le source : BouteilleDeKlein.cpp
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Mars 2002 */
/* Une bouteille de Klein */
#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"
#define LI 64
#define LH 64
static GLubyte image[LI][LH][3];
static int npv = 20;
static int npu = 60;
static int aff = 0;
static int texture = 1;
static int light = 1;
static float **au;
static float **av;
static float **x;
static float **y;
static float **z;
static float **nx;
static float **ny;
static float **nz;
void makeImage(void) {
int i,j,c;
for( i = 0 ; i < LI ; i++ ) {
for( j = 0 ; j < LH ; j++ ) {
c =(((i&0x8)==0)^((j&0x8)==0))*255;
image[i][j][0] =(GLubyte) 255;
image[i][j][1] =(GLubyte) c;
image[i][j][2] =(GLubyte) c; } }
}
void normalize(double *x,double *y,double *z) {
double d =sqrt(*x**x+*y**y+*z**z);
*x /= d;
*y /= d;
*z /= d;
}
void bouteilleDeKlein(void) {
int i,j;
glPushMatrix();
switch ( aff ) {
case 0 : glBegin(GL_POINTS);
for ( i = 0 ; i < npu ; i++ )
for ( j = 0 ; j < npv ; j++ ) {
glTexCoord2f(au[i][j],av[i][j]);
glNormal3f(nx[i][j],ny[i][j],nz[i][j]);
glVertex3f(x[i][j],y[i][j],z[i][j]); }
glEnd();
break;
case 1 : for ( i = 0 ; i < npu ; i++ )
for ( j = 0 ; j < npv ; j++ ) {
int i2 = i+1;
int j2 = j+1;
glBegin(GL_LINE_STRIP);
glTexCoord2f(au[i2][j],av[i2][j]);
glNormal3f(nx[i2][j],ny[i2][j],nz[i2][j]);
glVertex3f(x[i2][j],y[i2][j],z[i2][j]);
glTexCoord2f(au[i][j],av[i][j]);
glNormal3f(nx[i][j],ny[i][j],nz[i][j]);
glVertex3f(x[i][j],y[i][j],z[i][j]);
glTexCoord2f(au[i][j2],av[i][j2]);
glNormal3f(nx[i][j2],ny[i][j2],nz[i][j2]);
glVertex3f(x[i][j2],y[i][j2],z[i][j2]);
glEnd(); }
break;
case 2 : glBegin(GL_QUADS);
for ( i = 0 ; i < npu ; i++ )
for ( j = 0 ; j < npv ; j++ ) {
int i2 = i+1;
int j2 = j+1;
glTexCoord2f(au[i][j],av[i][j]);
glNormal3f(nx[i][j],ny[i][j],nz[i][j]);
glVertex3f(x[i][j],y[i][j],z[i][j]);
glTexCoord2f(au[i2][j],av[i2][j]);
glNormal3f(nx[i2][j],ny[i2][j],nz[i2][j]);
glVertex3f(x[i2][j],y[i2][j],z[i2][j]);
glTexCoord2f(au[i2][j2],av[i2][j2]);
glNormal3f(nx[i2][j2],ny[i2][j2],nz[i2][j2]);
glVertex3f(x[i2][j2],y[i2][j2],z[i2][j2]);
glTexCoord2f(au[i][j2],av[i][j2]);
glNormal3f(nx[i][j2],ny[i][j2],nz[i][j2]);
glVertex3f(x[i][j2],y[i][j2],z[i][j2]); }
glEnd();
break; }
glPopMatrix();
}
void initBouteilleDeKlein(void) {
int i,j;
au =(float **) calloc(npu+1,sizeof(float *));
av =(float **) calloc(npu+1,sizeof(float *));
x =(float **) calloc(npu+1,sizeof(float *));
y =(float **) calloc(npu+1,sizeof(float *));
z =(float **) calloc(npu+1,sizeof(float *));
nx =(float **) calloc(npu+1,sizeof(float *));
ny =(float **) calloc(npu+1,sizeof(float *));
nz =(float **) calloc(npu+1,sizeof(float *));
for ( i = 0 ; i <= npu ; i++ ) {
au[i] =(float *) calloc(npv+1,sizeof(float));
av[i] =(float *) calloc(npv+1,sizeof(float));
x[i] =(float *) calloc(npv+1,sizeof(float));
y[i] =(float *) calloc(npv+1,sizeof(float));
z[i] =(float *) calloc(npv+1,sizeof(float));
nx[i] =(float *) calloc(npv+1,sizeof(float));
ny[i] =(float *) calloc(npv+1,sizeof(float));
nz[i] =(float *) calloc(npv+1,sizeof(float)); }
for ( i = 0 ; i <= npu ; i++ ) {
for ( j = 0 ; j <= npv ; j++ ) {
double angu = i * 2 * 3.14159 / npu;
double angv = j * 2 * 3.14159 / npv;
au[i][j] = i * 4.75 / npu;
av[i][j] = j * 4.75 / npv;
double csu = cos(angu);
double snu = sin(angu);
double csv = cos(angv);
double snv = sin(angv);
double r = 4.0-csu*2.0;
double dxdu;
double dydu;
double dzdu = 2.0*snv*snu;
double dxdv;
double dydv;
double dzdv = 4.0*csv-2.0*csu*csv;
if ( angu <= 3.14159 ) {
x[i][j] = 6.0*csu*(1.0+snu)+r*csu*csv;
y[i][j] = 16*snu+r*snu*csv;
dxdu = -6.0*snu*(1.0+snu)+6.0*csu*csu-4.0*snu*csv+4.0*snu*csu*csv;
dxdv = (-4.0+2.0*csu)*csu*snv;
dydu = 16*csu+2.0*snu*snu+4.0*csu*(1.0-csu/2);
dydv = -(4.0-2.0*csu)*snu*snv; }
else {
x[i][j] = 6.0*csu*(1.0+snu)-r*csv;
y[i][j] = 16*snu;
dxdu = -6.0*snu*(1.0+snu)+6.0*csu*csu+2.0*snu*csv;
dxdv = 4.0*snv-2.0*csu*snv;
dydu = 16*csu;
dydv = 0.0; }
z[i][j] = r*snv;
normalize(&dxdu,&dydu,&dzdu);
normalize(&dxdv,&dydv,&dzdv);
nx[i][j] = dydu*dzdv-dydv*dzdu;
ny[i][j] = dzdu*dxdv-dzdv*dxdu;
nz[i][j] = dxdu*dydv-dxdv*dydu; } }
}
void detruitBouteilleDeKlein(void) {
for ( int i = 0 ; i <= npu ; i++ ) {
free(au[i]);
free(av[i]);
free(x[i]);
free(y[i]);
free(z[i]);
free(nx[i]);
free(ny[i]);
free(nz[i]); }
free(au);
free(av);
free(x);
free(y);
free(z);
free(nx);
free(ny);
free(nz);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
manipulateurSouris();
manipulateurClavier();
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,couleurBlanc());
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,couleurBlanc());
glColor4fv(couleurBlanc());
glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,50.0F);
if ( texture )
glEnable(GL_TEXTURE_2D);
if ( light )
glEnable(GL_LIGHTING);
bouteilleDeKlein();
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glPopMatrix();
glFlush();
glutSwapBuffers();
}
void myinit(void) {
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
glEnable(GL_DEPTH_TEST);
makeImage();
glTexImage2D(GL_TEXTURE_2D,0,3,LI,LH,0,GL_RGB,GL_UNSIGNED_BYTE,&image[0][0][0]);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glClearColor(0.0,0.0,0.0,1.0);
glShadeModel(GL_SMOOTH);
glDepthFunc(GL_LESS);
GLfloat l_pos[] = { 1.0,1.0,1.0,0.0 };
glLightfv(GL_LIGHT0,GL_POSITION,l_pos);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
}
void key(unsigned char key,int x,int y) {
if ( keyManipulateur(key,x,y) )
glutPostRedisplay();
else
switch ( key ) {
case 'u' : detruitBouteilleDeKlein();
npu++;
initBouteilleDeKlein();
glutPostRedisplay();
break;
case 'U' : detruitBouteilleDeKlein();
npu--;
if ( npu < 6 )
npu = 6;
initBouteilleDeKlein();
glutPostRedisplay();
break;
case 'v' : detruitBouteilleDeKlein();
npv++;
initBouteilleDeKlein();
glutPostRedisplay();
break;
case 'V' : detruitBouteilleDeKlein();
npv--;
if ( npv < 6 )
npv = 6;
initBouteilleDeKlein();
glutPostRedisplay();
break;
case ' ' : texture = 1-texture;
glutPostRedisplay();
break;
case 'l' : light = 1-light;
glutPostRedisplay();
break;
case 0x0D : aff = (aff+1)%3;
glutPostRedisplay();
break; }
}
int main(int argc,char **argv) {
initBouteilleDeKlein();
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
glutInitWindowSize(450,300);
glutInitWindowPosition(50,50);
glutCreateWindow("Bouteille de Klein");
myinit();
creationMenuBasique();
setParametresOrthoBasique(-16.0,16.0,-16.0,16.0,-50.0,50.0);
setManipulateurDistance(1.0F);
glutReshapeFunc(reshapeOrthoBasique);
glutKeyboardFunc(key);
glutSpecialFunc(specialBasique);
glutMotionFunc(motionBasique);
glutMouseFunc(sourisBasique);
glutIdleFunc(idleBasique);
glutDisplayFunc(display);
glutMainLoop();
return(0);
}