L'exécutable

Pour implanter la solution en un seul exécutable, j'ai réorganisé le programme en déplaçant vers la fonction display le code de définition de la caméra habituellement placé dans la fonction reshape. J'utilise deux variables globale wtx et wty pour communiquer la résolution du viewport à la fonction display de façon que celle-ci puisse en tenir compte pour l'adaptation du ratio de la caméra au ratio du viewport.
Tous les paramétrages de la caméra de visualisation en perspective sauf le dernier reprennent la même technique de calcul. J'ai donc développé une fonction ad hoc.
Pour le dernier paramètrage, j'ai considéré un parti pris de développement différent (plus anthropocentré) :
 - L'ouverture de la caméra ne change pas.
 - Les valeurs cmin et cmax ne changent pas non plus et sont choisies avec un cmin petit mais pas anormalement petit et un cmax grand mais pas anormalement grand compte tenu des caractéristiques de la scène et de la caméra.

Pour tenir compte du fait que la dimension apparente d'un cube, contrairement à une sphère (voir TD), est plus ou moins grande, à distances égales, suivant le point de vue adopté, j'ai introduit dans mon code un facteur multiplicatif sur l'angle calculé mathématiquement.

ParametrageCameraSolution-01.png
Caméra de visualisation en projection parallèle orthographique

ParametrageCameraSolution-02.png  ParametrageCameraSolution-03.png  ParametrageCameraSolution-04.png  ParametrageCameraSolution-05.png  ParametrageCameraSolution-06.png  ParametrageCameraSolution-07.png  ParametrageCameraSolution-08.png
Caméras de visualisation en projection en perspective

Fichier source : ParametrageCameraSolution.cpp
Modules utilitaires

static int wtx;                    // Resolution horizontale du viewport
static int wty;                    // Resolution verticale du viewport

static double px = 0.0;            // Position en x de la caméra
static double py = 0.0;            // Position en y de la caméra
static double pz = -25.0;          // Position en z de la caméra

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

static void displayOrthographique(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPolygonMode(GL_FRONT_AND_BACK,(aff) ? GL_FILL : GL_LINE);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  double ratio =(double) wtx / wty;
  if ( ratio >= 1.0 )
    glOrtho(-4.0F*ratio,4.0F*ratio,-4.0F,4.0F,90.0F,110.0F);
    else
    glOrtho(-4.0F,4.0F,-4.0F/ratio,4.0F/ratio,90.0F,110.0F);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glPushMatrix();
  scene();
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Erreur OpenGL: %d\n",error);
}

/* Configuration des caractéristiques           */
/* virtuelle de visualisation en perspective    */
/* tx : Résolution horizontale du viewport      */
/* ty : Résolution verticale du viewport        */
/* distance : Distance en -z entre la caméra    */
/*            et le centre de visualisation     */
/* dZ : Déport en z des plan de clipping        */
/*      near et far de la caméra par rapport    */
/*      au centre de visualisation              */
/* taille : La taille de la scène               */
/* facteur : Facteur correctif multiplicatif    */
/*           sur l'ouverture verticale          */

static void setCameraPerspective(int tx,int ty,double distance,double dZ,double taille,double facteur) {
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  double ratio =(double) tx / ty;
  double angle = atan2(taille/2.0,distance-taille/2.0)*2*180.0/3.14159*facteur;
  printf("angle = %lf\n",angle);
  double cmin = distance-dZ;
  if ( cmin < 0.0 )
    cmin = 0.01;
  if ( ratio >= 1.0 )
    gluPerspective(angle,ratio,cmin,distance+dZ);
    else
    gluPerspective(angle/ratio,ratio,cmin,distance+dZ);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

static void displayPerspectiveB(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPolygonMode(GL_FRONT_AND_BACK,(aff) ? GL_FILL : GL_LINE);
  setCameraPerspective(wtx,wty,100.0,3.5,6.5,4.0/3.25);
  glPushMatrix();
  scene();
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Erreur OpenGL: %d\n",error);
}

static void displayPerspectiveC(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPolygonMode(GL_FRONT_AND_BACK,(aff) ? GL_FILL : GL_LINE);
  setCameraPerspective(wtx,wty,50.0,3.5,6.5,4.0/3.25);
  glPushMatrix();
  gluLookAt(0.0,0.0,-50.0,0.0,0.0,-100.0,0.0,1.0,0.0);
  scene();
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Erreur OpenGL: %d\n",error);
}

static void displayPerspectiveD1(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPolygonMode(GL_FRONT_AND_BACK,(aff) ? GL_FILL : GL_LINE);
  setCameraPerspective(wtx,wty,10.0,3.5,6.5,4.0/3.25*0.97);
  glPushMatrix();
  gluLookAt(0.0,0.0,-90.0,0.0,0.0,-100.0,0.0,1.0,0.0);
  scene();
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Erreur OpenGL: %d\n",error);
}

static void displayPerspectiveD2(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPolygonMode(GL_FRONT_AND_BACK,(aff) ? GL_FILL : GL_LINE);
  setCameraPerspective(wtx,wty,5.0,3.5,6.5,4.0/3.25*0.87);
  glPushMatrix();
  gluLookAt(0.0,0.0,-95.0,0.0,0.0,-100.0,0.0,1.0,0.0);
  scene();
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Erreur OpenGL: %d\n",error);
}

static void displayPerspectiveD3(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPolygonMode(GL_FRONT_AND_BACK,(aff) ? GL_FILL : GL_LINE);
  setCameraPerspective(wtx,wty,sqrt(5.0*5.0+5.0*5.0+5.0*5.0),6.0,6.5,1.25);
  glPushMatrix();
  gluLookAt(-5.0,-5.0,-95.0,0.0,0.0,-100.0,0.0,1.0,0.0);
  scene();
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Erreur OpenGL: %d\n",error);
}

static void displayPerspectiveD4(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPolygonMode(GL_FRONT_AND_BACK,(aff) ? GL_FILL : GL_LINE);
  setCameraPerspective(wtx,wty,sqrt(10.0*10.0+15.0*15.0+10.0*10.0),6.0,6.5,1.5);
  glPushMatrix();
  gluLookAt(-10.0,-15.0,-90.0,0.0,0.0,-100.0,0.0,1.0,0.0);
  scene();
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Erreur OpenGL: %d\n",error);
}

static void displayPerspectiveD5(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPolygonMode(GL_FRONT_AND_BACK,(aff) ? GL_FILL : GL_LINE);
  setCameraPerspective(wtx,wty,sqrt(10.0*10.0+15.0*15.0+20.0*20.0),6.0,6.5,1.6);
  glPushMatrix();
  gluLookAt(-10.0,-15.0,-120.0,0.0,0.0,-100.0,0.0,1.0,0.0);
  scene();
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Erreur OpenGL: %d\n",error);
}

static void displayInteractif(void) {
  printf("%8.2lf%8.2lf%8.2lf\n",px,py,pz);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPolygonMode(GL_FRONT_AND_BACK,(aff) ? GL_FILL : GL_LINE);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  double ratio =(double) wtx / wty;
  double angle = 10.0;
  if ( ratio >= 1.0 )
    gluPerspective(angle,ratio,0.01,1000.0);
    else
    gluPerspective(angle/ratio,ratio,0.01,1000.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glPushMatrix();
  gluLookAt(px,py,pz,0.0,0.0,-100.0,0.0,1.0,0.0);
  scene();
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Erreur OpenGL: %d\n",error);
}

/* Fonction executee lors d'un changement       */
/* de la taille de la fenetre OpenGL            */
/* -> Ajustement de la camera de visualisation  */

static void reshape(int tx,int ty) {
  glViewport(0,0,tx,ty); 
  wtx = tx;
  wty = ty;
}

/* Fonction executee lors dde l'utilisation     */
/* d'une touche non alphanumérique du clavier   */

static void special(int key,int x,int y) {
  switch(key) {
    case GLUT_KEY_UP :
      py += 0.25F;
      glutPostRedisplay();
      break;
    case GLUT_KEY_DOWN :
      py -= 0.25F;
      glutPostRedisplay();
      break;
    case GLUT_KEY_RIGHT :
      px += 0.25F;
      glutPostRedisplay();
      break;
    case GLUT_KEY_LEFT :
      px -= 0.25F;
      glutPostRedisplay();
      break;
    case GLUT_KEY_PAGE_UP :
      pz -= 0.25F;
      glutPostRedisplay();
      break;
    case GLUT_KEY_PAGE_DOWN :
      pz += 0.25F;
      glutPostRedisplay();
      break; }
}

RETOUR