// Stencil : localisation dans un volume // TP OPENGL // Fabrice Aubert #include #include #include #include #include "sgi.h" #include "glm.h" #include "trackball.h" typedef enum {M_JPG,M_RGB} FormatImage; // *********************************************************** // VARIABLES GLOBALES (textures, animation) GLint tex_id; // identificateur de texture // Variables globales pour la cinématique de la scène (voir myIdle) GLfloat angScene=60.0; // angle de rotation de la scene GLfloat deplaceZ=0.0; // position de l'objet en Z GLfloat incrZ=-0.02; // increment pour la position de l'objet GLMmodel *pmodel1=0; // contiendra un objet (structure d'objet WaveFront // lu grace à glm.c) GLMmodel *pmodel2=0; // contiendra un objet (structure d'objet WaveFront // lu grace à glm.c) // caractéristiques de lumière : GLfloat ldif[]={1,1,1,1}; GLfloat lpos_init[]={4,5,0,1}; // position initiale de la lumière bool ANIME; //***************************************************************** // INITIALISATIONS ET ACTIVATION TEXTURES GLuint initTexture(char *nom,FormatImage format) { GLubyte *image; GLint longueur,largeur,depthi; GLuint res; switch (format) { case M_JPG:image=read_jpg(nom,&longueur,&largeur,&depthi);break; case M_RGB:image=read_sgi(nom,&longueur,&largeur,&depthi);break; default:exit(0); } glGenTextures(1,&res); glBindTexture(GL_TEXTURE_2D,res); glPixelStorei(GL_UNPACK_ALIGNMENT,1); glTexImage2D(GL_TEXTURE_2D,0,3,longueur,largeur,0,GL_RGB,GL_UNSIGNED_BYTE,image); 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); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL); return res; } void activerTextureCoord(GLint texId) { glBindTexture(GL_TEXTURE_2D,texId); glEnable(GL_TEXTURE_2D); } void desactiverTexture() { glDisable(GL_TEXTURE_2D); } // ************************************************************************ // AFFICHAGE DES PRIMITIVES void tracerPlanCoupe() { glPushMatrix(); glRotatef(90,0,0,1); glTranslatef(3,deplaceZ-2,0); activerTextureCoord(tex_id); glMatrixMode(GL_TEXTURE); glPushMatrix();glRotatef(90,0,0,1); glBegin(GL_POLYGON); glTexCoord2f(0.0,0.0);glVertex3f(-5,0,-5); glTexCoord2f(1.0,0.0);glVertex3f(5,0,-5); glTexCoord2f(1.0,1.0);glVertex3f(5,0,5); glTexCoord2f(0.0,1.0);glVertex3f(-5,0,5); glEnd(); glPopMatrix(); glMatrixMode(GL_MODELVIEW); desactiverTexture(); glPopMatrix(); } // tracé de l'objet (utilisation de fonction glm) void tracerObjet() { glPushMatrix(); glTranslatef(0,2,0); glScalef(3.5,3.5,3.5); // sinon objet trop petit. glColor4f(1,0.2,0.3,0.2); glmDraw(pmodel1, GLM_SMOOTH); // procédure de tracé donnée par glm // pmodel contient la structure de l'objet (variable globale) // (cf chargement dans myInit) glTranslatef(0.7,0,0); glRotatef(60,0,1,0); glColor4f(0,0.3,1,0.2); glmDraw(pmodel2, GLM_SMOOTH); glPopMatrix(); } // **************************************************************** // LES EVENEMENTS : myDraw, myReshape, myIdle void myDisplay(void) { glClearColor(1,1,1,0); glClearDepth(1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glPushMatrix(); glRotatef(20,1,0,0); glTranslatef(0,-7.5,-15); tbMatrix(); glRotatef(angScene,0,1,0); //Réalisation de la coupe // Désactivation du tracage des couleurs glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Tracé du plan tracerPlanCoupe(); // Desactivation du Zbuffer (pour éviter de cacher ce qu'il y a derrière) glDepthMask(GL_FALSE); // Incrémentation à chauqe fois que le z buffer passe glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // Trace le plan tracerObjet(); // Reactivation du Zbuffer glDepthMask(GL_TRUE); glClear(GL_DEPTH_BUFFER_BIT); // Reactivation des couleurs glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // Choix des pixels à tracer selon le stencil glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // Passe pour les pairs glStencilFunc(GL_EQUAL, 0, 0x1); // Trace la coupe tracerPlanCoupe(); glStencilFunc(GL_ALWAYS, 1, 1); //tracerObjet(); glPopMatrix(); glutSwapBuffers(); } void myReshape(GLint width,GLint height) { glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45,(GLfloat)width/height,.1,100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); tbReshape(width,height); } void myIdle(void) { if (ANIME) { // angScene+=1.0; deplaceZ+=incrZ; if (deplaceZ>3.5 || deplaceZ<-1.5) incrZ=-incrZ; } glutPostRedisplay(); } // CallBack clavier void myKey(unsigned char c,int x,int y) { switch (c) { case 27: exit(1); break; // sortie violente si appui sur "Echap" case 'a':ANIME=!ANIME;break; default: break; } } // Callback de la souris void myMouse(int button, int status, int x, int y) { tbMouse(button,status,x,y); } void myMotion(int x,int y) { tbMotion(x,y); } // ***************************************************** // INITIALISATION OPENGL (+lecture texture+lecture objet) void myInit() { ANIME=true; glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); pmodel1 = glmReadOBJ("../data/flamingo.obj"); if (!pmodel1) exit(0); pmodel2 = glmReadOBJ("../data/porsche.obj"); if (!pmodel2) exit(0); glmUnitize(pmodel1); glmFacetNormals(pmodel1); glmVertexNormals(pmodel1, 90.0); glmUnitize(pmodel2); glmFacetNormals(pmodel2); glmVertexNormals(pmodel2, 90.0); tex_id=initTexture("../data/foret512x256.jpg",M_JPG); glLightfv(GL_LIGHT1,GL_DIFFUSE,ldif); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); glEnable(GL_NORMALIZE); // les normales sont renormalisées en cas de glScale tbInit(GLUT_LEFT_BUTTON); } int main(int argv,char **argc) { glutInit(&argv,argc); glutInitWindowSize(512,512); glutInitDisplayMode(GLUT_ALPHA | GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL); glutCreateWindow("Coupe"); glutReshapeFunc(myReshape); glutDisplayFunc(myDisplay); glutIdleFunc(myIdle); glutKeyboardFunc(myKey); glutMouseFunc(myMouse); glutMotionFunc(myMotion); myInit(); glutMainLoop(); return 0; }