L'exécutable

L'exemple ci-dessous illustre l'intérêt que peut avoir la facettisation proposée comme sujet d'exercice. En effet, les calculs d'éclairage ont une qualité clairement impactée par la facettisation. L'éclairage des facettes étant créé par dégradé de couleur entre les éclairages calculés pour leurs sommets, il est difficile d'obtenir une grande précision d'éclairage pour des détails de taille inférieure à la taille des facettes.
Dans l'exemple, trois lumières ponctuelles rouge, verte et bleue placées au dessus de la facette éclairent celle-ci. Les trois lumières sont immobiles. La souris permet de faire tourner la facette sur elle-même. On peut afficher une facette unique de coté c ou bien les deux solutions. Il est aussi possible de contrôler le nombre n.

Solution1.cpp

/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Novembre 2007                                */
/* Un carre de carres                           */

#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>

/* Dessin d'un carre au moyen d'une primitive   */
/* de type GL_QUADS (n x n quads)               */

void solution1(int n,float c) {
  float ct = c / n;
  c *= 0.5F;
  glBegin(GL_QUADS);
  glNormal3f(0.0F,0.0F,1.0F);
  for ( int i = 0 ; i < n ; i++ )
    for ( int j = 0 ; j < n ; j++ ) {
      float xi = c-i*ct;
      float yi = c-j*ct;
      glVertex2f(xi,yi);
      glVertex2f(xi-ct,yi);
      glVertex2f(xi-ct,yi-ct);
      glVertex2f(xi,yi-ct); }
  glEnd();
}

Solution1.h

/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Novembre 2007                                */
/* Un carre de carres                           */

#ifndef __SOLUTION1__
#define __SOLUTION1__

void solution1(int n,float c);

#endif

Solution2.cpp

/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Novembre 2007                                */
/* Un carre de carres                           */

#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>

/* Dessin d'un carre au moyen  de plusieurs     */
/* primitives de type GL_QUAD_STRIP             */
/* (n quad_strips)                              */

void solution2(int n,float c) {
  float ct = c / n;
  c *= 0.5F;
  glNormal3f(0.0F,0.0F,1.0F);
  float yi;
  float yf = -c;
  for ( int j = 0 ; j < n ; j++ ) {
    yi = yf;
    yf += ct;
    glBegin(GL_QUAD_STRIP);
    float x = c;
    for ( int i = 0 ; i <= n ; i++ ) {
      glVertex2f(x,yi);
      glVertex2f(x,yf);
      x -= ct; }
    glEnd(); }
}

Solution2.h

/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Novembre 2007                                */
/* Un carre de carres                           */

#ifndef __SOLUTION2__
#define __SOLUTION2__

void solution2(int n,float c);

#endif

CarreDeCarres.cpp

/* Auteur: Nicolas JANEY                        */
/* nicolas.janey@univ-fcomte.fr                 */
/* Novembre 2007                                */
/* Un carre de carres                           */

#include <stdio.h>

#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>

#include "Solution1.h"
#include "Solution2.h"

/* Variables et constantes globales             */

static int solution = 1;
static int disc = 25;
static float cote = 10.0F;
static int mode = 1;
static const float blanc[] = { 2.0F,2.0F,2.0F,1.0F };
static const float rouge[] = { 10.0F,0.0F,0.0F,1.0F };
static const float vert[] = { 0.0F,10.0F,0.0F,1.0F };
static const float bleu[] = { 0.0F,0.0F,10.0F,1.0F };

/* Variables globales de gestion                */
/* de l'interactivite clavier et souris         */

static int clic = 0;
static int mx;
static int my;
static float rx = 0.0F;
static float ry = 0.0F;

/* Fonction d'initialisation des parametres     */
/* OpenGL ne changeant pas au cours de la vie   */
/* du programme                                 */

void init(void) {
  const GLfloat mat_shininess[] = { 50.0 };
  const GLfloat light0_position[] = { 2.0,2.0,2.0,1.0 };
  const GLfloat light1_position[] = { -2.0,2.0,2.0,1.0 };
  const GLfloat light2_position[] = { 2.0,-2.0,2.0,1.0 };
  glMaterialfv(GL_FRONT,GL_SPECULAR,blanc);
  glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
  glLightfv(GL_LIGHT0,GL_DIFFUSE,rouge);
  glLightfv(GL_LIGHT1,GL_DIFFUSE,vert);
  glLightfv(GL_LIGHT2,GL_DIFFUSE,bleu);
  glLightfv(GL_LIGHT0,GL_POSITION,light0_position);
  glLightfv(GL_LIGHT1,GL_POSITION,light1_position);
  glLightfv(GL_LIGHT2,GL_POSITION,light2_position);
  glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,1.0F);
  glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,1.0F);
  glLightf(GL_LIGHT1,GL_LINEAR_ATTENUATION,1.0F);
  glLightf(GL_LIGHT1,GL_QUADRATIC_ATTENUATION,1.0F);
  glLightf(GL_LIGHT2,GL_LINEAR_ATTENUATION,1.0F);
  glLightf(GL_LIGHT2,GL_QUADRATIC_ATTENUATION,1.0F);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_LIGHT1);
  glEnable(GL_LIGHT2);
  glDepthFunc(GL_LESS);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_NORMALIZE);
  glEnable(GL_AUTO_NORMAL);
}

/* Dessin d'un carre simple                     */

void carreBasique(float c) {
  c *= 0.5F;
  glBegin(GL_QUADS);
  glNormal3f(0.0F,0.0F,1.0F);
  glVertex2f(c,c);
  glVertex2f(-c,c);
  glVertex2f(-c,-c);
  glVertex2f(c,-c);
  glEnd();
}

/* Scene dessinee                               */

void scene(void) {
  glPushMatrix();
  glRotatef(rx,1.0F,0.0F,0.0F);
  glRotatef(ry,0.0F,1.0F,0.0F);
  switch (solution) {
    case 0 : carreBasique(cote);
             break;
    case 1 : solution1(disc,cote);
             break;
    case 2 : solution2(disc,cote);
             break; }
  glPopMatrix();
}

/* Fonction executee lors d'un rafraichissement */
/* de la fenetre de dessin                      */

void display(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPushMatrix();
  glPolygonMode(GL_FRONT,(mode) ? GL_FILL : GL_LINE);
  glPolygonMode(GL_BACK,(mode) ? GL_FILL : GL_LINE);
  scene();
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
}

/* Fonction executee lors de la frappe          */
/* d'une touche alphanumerique du clavier       */

void key(unsigned char key,int x,int y) {
  switch ( key ) {
    case 43   : disc++;
                glutPostRedisplay();
                break;
    case 45   : disc--;
                if ( disc < 1 )
                  disc = 1;
                glutPostRedisplay();
                break;
    case 0x20 : mode = !mode;
                glutPostRedisplay();
                break;
    case 0x0D : solution = (solution+1)%3;
                glutPostRedisplay();
                break;
    case 0x1B : exit(0);
                break; }
}

/* Fonction executee lors d'un clic de souris   */
/* dans la fenetre                              */

void mouse(int bouton,int etat,int x,int y) {
  if ( bouton == GLUT_LEFT_BUTTON ) {
    if ( etat == GLUT_DOWN ) {
      clic = 1;
      mx = x;
      my = y; }
    if ( etat == GLUT_UP ) {
      clic = 0; } }
}

/* Fonction executee lors d'un deplacement      */
/* de la souris sur la fenetre                  */
/* avec un bouton appuye                        */

void motion(int x,int y) {
  if ( clic ) {
    ry += (x-mx);
    rx += (y-my);
    mx = x;
    my = y;
    glutPostRedisplay(); }
}

/* Fonction executee lors d'un changement       */
/* de la taille de la fenetre OpenGL            */

void reshape(int x,int y) {
  glViewport(0,0,x,y); 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-8.0,8.0,(double) -8.0*y/x,(double) 8.0*y/x,-8.0,8.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

/* Fonction principale                          */

int main(int argc,char **argv) {
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
  glutInitWindowSize(196,189); 
  glutInitWindowPosition(50,50); 
  glutCreateWindow("Un carre de carres"); 
  init();
  glutReshapeFunc(reshape);
  glutKeyboardFunc(key);
  glutMotionFunc(motion);
  glutMouseFunc(mouse);
  glutDisplayFunc(display);
  glutMainLoop();
  return(0);
}

RETOUR