Le code montre comment choisir un point avec la souris, comment charger une texture et comment faire bouger des objets.
#include <GL/glut.h> #include <stdlib.h> #include <math.h> #include <assert.h> #include "traqueboule.h" #include "argumentParser.h" //some simple functions to facilitate vector usage. //if you dont like c++ this still helps a lot! void add(float v[3], float v2[3], float res[3]) { res[0]=v[0]+v2[0]; res[1]=v[1]+v2[1]; res[2]=v[2]+v2[2]; } void mult(float v[3], float f, float res[3]) { res[0]=v[0]*f; res[1]=v[1]*f; res[2]=v[2]*f; } float normsquare(float v[3]) { return v[0]*v[0]+v[1]*v[1]+v[2]*v[2]; } float scalar(float v[3], float v2[3]) { return v[0]*v2[0]+v[1]*v2[1]+v[2]*v2[2]; } void add(double v[3], double v2[3], double res[3]) { res[0]=v[0]+v2[0]; res[1]=v[1]+v2[1]; res[2]=v[2]+v2[2]; } void mult(double v[3], double f, double res[3]) { res[0]=v[0]*f; res[1]=v[1]*f; res[2]=v[2]*f; } double normsquare(double v[3]) { return v[0]*v[0]+v[1]*v[1]+v[2]*v[2]; } double scalar(double v[3], double v2[3]) { return v[0]*v2[0]+v[1]*v2[1]+v[2]*v2[2]; } GLuint Texture; double projectedPoint[3]; double projectedPoint2[3]; double projectedPointOnPlane[3]; double squarePositionX; double squarePositionY; double squareSize=0.1; bool squareIncreasing=false; void myGameFunction() { //we calculate the intersection of the ray from projectedPoint to //projectedPoint2 with the plane X,Y double alpha=-projectedPoint[2]/(projectedPoint2[2]-projectedPoint[2]); double temp[3]; mult(projectedPoint,-1.0,temp); double temp2[3]; add(projectedPoint2,temp,temp2); double temp3[3]; mult(temp2,alpha,temp3); add(projectedPoint,temp3,projectedPointOnPlane); projectedPointOnPlane[2]=0; //here projectedPointOnPlane contains the position of the click on the //plane X,Y in world space //now we move the square over time to chase the selected point if (squarePositionX<projectedPointOnPlane[0]) squarePositionX+=0.001; else squarePositionX-=0.001; if (squarePositionY<projectedPointOnPlane[1]) squarePositionY+=0.001; else squarePositionY-=0.001; //To make it look more interesting and to give an example of animation, //we modify its size over time if (squareIncreasing) { if (squareSize<0.1) squareSize+=0.0001; else squareIncreasing=false; } else { if (squareSize>0.01) squareSize-=0.0001; else squareIncreasing=true; } glutPostRedisplay(); } void init(void) { //or load a texture like shown in TP1!!!! float *image= new float[3*3*3]; for (int i=0;i<9;++i) { image[3*i]=((float)i+1)/9; image[3*i+1]=((float)i+1)/9; image[3*i+2]=1.0;//((float)i+1)/size; } //weird open gl call, just copy and forget about it... glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(1,&Texture); glBindTexture(GL_TEXTURE_2D,Texture); float border_color[]={1.0,1.0,1.0,1.0}; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); glTexParameterfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, border_color); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); glTexImage2D(GL_TEXTURE_2D,0,GL_RGB8, 3,3,0,GL_RGB,GL_FLOAT,image); glTexParameteri(GL_TEXTURE_ENV, GL_TEXTURE_ENV, GL_MODULATE); } //you already know this #include "global.h" #include "Maillage.h" #include "dessiner.h" unsigned int W_fen = 800; // largeur fenetre unsigned int H_fen = 800; // hauteur fenetre //draw an axis void dessinerRepere(float length, float width=3) { //we modify lighting and linewidth glPushAttrib(GL_ALL_ATTRIB_BITS); glDisable(GL_LIGHTING); glLineWidth(width); glBegin(GL_LINES); glColor3f(1,0,0); glVertex3f(0,0,0); glVertex3f(length,0,0); glColor3f(0,1,0); glVertex3f(0,0,0); glVertex3f(0,length,0); glColor3f(0,0,1); glVertex3f(0,0,0); glVertex3f(0,0,length); glEnd(); //recover old settings glPopAttrib(); } //draw a deformed box void dessinerBox(float posx, float posy, float posz, float size=0.1) { glPushMatrix(); glTranslatef(posx,posy,posz); glScalef(size,size,size); glutSolidCube(1.0); glPopMatrix(); } void drawSphere(float posx, float posy, float posz, float radius, int discrPhi=100, int discrTheta=50) { glPushMatrix(); glTranslatef(posx,posy,posz); glScalef(radius, radius, radius); glPushAttrib(GL_ALL_ATTRIB_BITS); glBegin(GL_TRIANGLES); for (int i=0; i<discrPhi;++i) { float phi=2.0*3.141* ((float)(i))/discrPhi; float phi2=2.0*3.141* ((float)((i+1)%discrPhi))/discrPhi; for (int j=0;j<discrTheta;++j) { float theta=3.141* ((float)(j))/discrTheta; float theta2=3.141* ((float)(j+1))/discrTheta; float point11[3]; float point21[3]; float point12[3]; float point22[3]; point11[0]= cos(phi)*sin(theta); point11[1]= sin(phi)*sin(theta); point11[2]=cos(theta); point21[0]= cos(phi2)*sin(theta); point21[1]= sin(phi2)*sin(theta); point21[2]=cos(theta); point12[0]= cos(phi)*sin(theta2); point12[1]= sin(phi)*sin(theta2); point12[2]=cos(theta2); point22[0]= cos(phi2)*sin(theta2); point22[1]= sin(phi2)*sin(theta2); point22[2]=cos(theta2); glColor3f(1,1,1); glNormal3fv(point22); glVertex3fv(point22); glNormal3fv(point21); glVertex3fv(point21); glNormal3fv(point11); glVertex3fv(point11); glNormal3fv(point11); glVertex3fv(point11); glNormal3fv(point12); glVertex3fv(point12); glNormal3fv(point22); glVertex3fv(point22); } } glEnd(); glPopAttrib(); glPopMatrix(); } /** * we draw the ray shot from the point the user selected by pressing space */ void dessiner( ) { dessinerRepere(2.0); drawSphere(1,1,1,0.1,10,10); //show the selected point on the plane glDisable(GL_LIGHTING); glPointSize(5); glColor3f(1,0,0); glBegin(GL_POINTS); glVertex3dv(projectedPointOnPlane); glEnd(); //we show the ray that has been selected at last! glColor3f(1,1,1); glLineWidth(10); glBegin(GL_LINES); glVertex3dv(projectedPoint); glVertex3dv(projectedPoint2); glEnd(); //we show the plane we play in //to make it more interesting we use a texture glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,Texture); glColor3f(1,1,1); glBegin(GL_QUADS); glTexCoord2f(0,1); glVertex2f(0,0); glTexCoord2f(1,1); glVertex2f(1,0); glTexCoord2f(1,0); glVertex2f(1,1); glTexCoord2f(0,0); glVertex2f(0,1); glEnd(); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D); //finally we draw the cube //we are always in the xy plane glEnable(GL_LIGHTING); glLineWidth(1); glColor3f(1,0,1); //the third parameter is the z position, as the square should lie on the //plane, we move it up by its size dessinerBox(squarePositionX, squarePositionY, squareSize, squareSize); } void display(void); void reshape(int w, int h); void keyboard(unsigned char key, int x, int y); /** * Programme principal */ int main(int argc, char** argv) { projectedPoint[0]=0; projectedPoint[1]=0; projectedPoint[2]=2; projectedPoint2[0]=0; projectedPoint2[1]=0; projectedPoint2[2]=1; projectedPointOnPlane[0]=0; projectedPointOnPlane[1]=0; projectedPointOnPlane[2]=0; animal::parse("Maillages et illumination. Voici la liste des options: ") .option(&W_fen,'L',"Largeur","largeur de la fenêtre en pixels") .option(&H_fen,'H',"Hauteur","hauteur de la fenêtre en pixels") (argc,argv); glutInit(&argc, argv); // couches du framebuffer utilisees par l'application glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH ); // position et taille de la fenetre glutInitWindowPosition(200, 100); glutInitWindowSize(W_fen,H_fen); glutCreateWindow(argv[0]); // Initialisation du point de vue glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0,0,-4); tbInitTransform(); // initialisation du point de vue tbHelp(); // affiche l'aide sur la traqueboule // // Active la lumière // Pour la partie // ECLAIRAGE glEnable( GL_LIGHTING ); glEnable( GL_LIGHT0 ); glEnable(GL_COLOR_MATERIAL); int MatSpec [4] = {1,1,1,1}; GLfloat LightPos[]={1,1,2,1}; glLightfv(GL_LIGHT0,GL_POSITION,LightPos); glMaterialiv(GL_FRONT_AND_BACK,GL_SPECULAR,MatSpec); glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,10); glEnable(GL_NORMALIZE); // cablage des callback glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); init(); glutDisplayFunc(display); glutMouseFunc(tbMouseFunc); // traqueboule utilise la souris glutMotionFunc(tbMotionFunc); // traqueboule utilise la souris glutIdleFunc( myGameFunction ); // lancement de la boucle principale glutMainLoop(); return 0; // instruction jamais exécutée } /** * Fonctions de gestion opengl à ne pas toucher */ // Actions d'affichage // Ne pas changer void display(void) { // Details sur le mode de tracé glEnable( GL_DEPTH_TEST ); // effectuer le test de profondeur //glEnable(GL_CULL_FACE); //glCullFace(GL_BACK); glPolygonMode(GL_FRONT,GL_FILL); glPolygonMode(GL_BACK,GL_LINE); glShadeModel(GL_SMOOTH); // Effacer tout glClearColor(0.4,0.4,0.0,1.0); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // la couleur et le z glLoadIdentity(); // repere camera tbVisuTransform(); // origine et orientation de la scene dessiner( ); glutSwapBuffers(); } // pour changement de taille ou desiconification void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //glOrtho (-1.1, 1.1, -1.1,1.1, -1000.0, 1000.0); gluPerspective (50, (float)w/h, 1, 10); glMatrixMode(GL_MODELVIEW); } // prise en compte du clavier void keyboard(unsigned char key, int x, int y) { GLint viewport[4]; GLdouble modelMatrix[16]; GLdouble projectionMatrix[16]; printf("key %d pressed at %d,%d\n",key,x,y); fflush(stdout); switch (key) { case ' ': glGetIntegerv(GL_VIEWPORT,viewport); glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix); glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); //we unproject (get the world coordinates from the mouse position. //here we suppose the depth is 0 so the point will be on the near plane gluUnProject((double)x, (double)(viewport[3]-y), (double)0., modelMatrix, projectionMatrix, viewport, &(projectedPoint[0]), &(projectedPoint[1]), &(projectedPoint[2])); //here we suppose the depth is 1 so the point will be on the far plane gluUnProject((double)x, (double)(viewport[3]-y), (double)1., modelMatrix, projectionMatrix, viewport, &(projectedPoint2[0]), &(projectedPoint2[1]), &(projectedPoint2[2])); break; case 27: // touche ESC exit(0); } }