Correction du TD 2 : placement automatique de la caméra

Déclaration de la Bounding Box dans object.h

typedef struct BoundingBoxStruct {
  VERTEX Vertex[8];  /* Les 8 sommets de la bbox */
  double Height;     /* Sa hauteur               */
  double Width;      /* Sa longueur              */
  double Depth;      /* Sa profondeur            */
  double plus_grand_cote_sur_2; /* Le plus grand cote sur deux
                                    utile pour le placement de la camera */
} BBOX;


typedef struct ObjectStruct {
  ...
  /* Sa bounding box */
  BBOX bbox;
} Object;

Placer le repère de l'objet en son centre de gravité, Calcul de la Bounding Box (dans object.c)

/*------------------------------------------*/
static void CenterObjectPoints(Object *obj)
/*------------------------------------------*/
/* Positionne le centre du repere objet sur le barycentre de l'objet  et 
   calcule la bounding box de l'objet */
 
{
  double Somme_x=0, Somme_y=0, Somme_z=0;
  double Min_x, Min_y, Min_z;
  double Max_x, Max_y, Max_z;
  int i;
  for (i=0; i < obj->NbVertices; i++){
    Somme_x += obj->Vertex[i].ObjectVertex.x;
    Somme_y += obj->Vertex[i].ObjectVertex.y;
    Somme_z += obj->Vertex[i].ObjectVertex.z;
  }
  Somme_x = (Somme_x / obj->NbVertices);
  Somme_y = (Somme_y / obj->NbVertices);
  Somme_z = (Somme_z / obj->NbVertices);
  
  Min_x = obj->Vertex[0].ObjectVertex.x - Somme_x;
  Min_y = obj->Vertex[0].ObjectVertex.y - Somme_y;
  Min_z = obj->Vertex[0].ObjectVertex.z - Somme_z;
  Max_x = Min_x; Max_y = Min_y; Max_z = Min_z;
  
  for (i=0; i < obj->NbVertices; i++){
     if ((obj->Vertex[i].ObjectVertex.x -= Somme_x) < Min_x)
      Min_x = obj->Vertex[i].ObjectVertex.x ;
    else
      if (obj->Vertex[i].ObjectVertex.x > Max_x)
        Max_x = obj->Vertex[i].ObjectVertex.x;

    if ((obj->Vertex[i].ObjectVertex.y -= Somme_y) < Min_y)
      Min_y = obj->Vertex[i].ObjectVertex.y ;
    else
      if (obj->Vertex[i].ObjectVertex.y > Max_y)
        Max_y = obj->Vertex[i].ObjectVertex.y;
 
   if ((obj->Vertex[i].ObjectVertex.z -= Somme_z) < Min_z)
      Min_z = obj->Vertex[i].ObjectVertex.z ;
    else
      if (obj->Vertex[i].ObjectVertex.z > Max_z)
        Max_z = obj->Vertex[i].ObjectVertex.z;
  }
  
  CreateBBox(obj, Min_x, Min_y, Min_z, Max_x, Max_y, Max_z);
}
/******************************************/
void CreateBBox(Object *obj, double Min_x, double  Min_y, double Min_z, 
                             double Max_x, double Max_y, double Max_z)
/******************************************/    
{
  obj->bbox.Vertex[0].ObjectVertex.x = Min_x;
  obj->bbox.Vertex[0].ObjectVertex.y = Min_y;
  obj->bbox.Vertex[0].ObjectVertex.z = Min_z;
    
  obj->bbox.Vertex[1].ObjectVertex.x = Min_x;
  obj->bbox.Vertex[1].ObjectVertex.y = Max_y;
  obj->bbox.Vertex[1].ObjectVertex.z = Min_z;
  
  obj->bbox.Vertex[2].ObjectVertex.x = Max_x;
  obj->bbox.Vertex[2].ObjectVertex.y = Max_y;
  obj->bbox.Vertex[2].ObjectVertex.z = Min_z;
  
  obj->bbox.Vertex[3].ObjectVertex.x = Max_x;
  obj->bbox.Vertex[3].ObjectVertex.y = Min_y;
  obj->bbox.Vertex[3].ObjectVertex.z = Min_z;
  
  obj->bbox.Vertex[4].ObjectVertex.x = Max_x;
  obj->bbox.Vertex[4].ObjectVertex.y = Min_y;
  obj->bbox.Vertex[4].ObjectVertex.z = Max_z;
  
  obj->bbox.Vertex[5].ObjectVertex.x = Min_x;
  obj->bbox.Vertex[5].ObjectVertex.y = Min_y;
  obj->bbox.Vertex[5].ObjectVertex.z = Max_z;
  
  obj->bbox.Vertex[6].ObjectVertex.x = Min_x;
  obj->bbox.Vertex[6].ObjectVertex.y = Max_y;
  obj->bbox.Vertex[6].ObjectVertex.z = Max_z;
  
  obj->bbox.Vertex[7].ObjectVertex.x = Max_x;
  obj->bbox.Vertex[7].ObjectVertex.y = Max_y;
  obj->bbox.Vertex[7].ObjectVertex.z = Max_z;
  
  obj->bbox.Height = Max_x - Min_x;
  obj->bbox.Width = Max_y - Min_y;
  obj->bbox.Depth = Max_z - Min_z;


  obj->bbox.plus_grand_cote_sur_2 =
    MAX(MAX(obj->bbox.Height, obj->bbox.Width), obj->bbox.Depth)/2.0;

  printf ("CBB: W=%g H=%g D=%g PGC=%g\n",obj->bbox.Width, 
                                         obj->bbox.Height, 
                                         obj->bbox.Depth,
                                         obj->bbox.plus_grand_cote_sur_2); 
}


/*                 1 ----------- 2
                    / |        /|
                   /  |      /  |
                6 ---------- 7  |
                  |   |     |   |
                  |   |     |   | 
                  |  0 --------/ 3
                  |   /     | /
                  | /       |/
                5 ----------- 4

*/

Placement de la caméra (dans object.c)

/********************************************/
void PlaceCamera (Camera *cam, Object *obj){
/********************************************/
  double Ox, Oy, Oz, z;

  SetMatrixToIdentity(&cam->LocalToGlobal);
  SetMatrixToIdentity(&cam->GlobalToLocal);

  Ox = obj->LocalToGlobal.elem[0][3];
  Oy = obj->LocalToGlobal.elem[1][3];
  Oz = obj->LocalToGlobal.elem[2][3];

  z = Oz + obj->bbox.plus_grand_cote_sur_2 * (1 + 1/tan ((M_PI*cam->fovX) / 180.0)); 

  TranslateCamera(cam, Ox, Oy, z);
}

Dessin de la Bounding Box (dans graphics.c)

/*-----------------------------------------------*/
static void draw_object(Object *obj, Camera *cam)
/*-----------------------------------------------*/
/* Affiche dans la fenetre graphique l'objet passe en 1er parametre, comme
   s'il etait vu par la camera passe en 2eme parametre */
{
    ...
    draw_boundingBox(obj, cam); 
    ...
}
/*******************************************************/
static void draw_boundingBox(Object *obj, Camera *cam){
/*******************************************************/
  int i;
  /* D'abord, projection des points */
  for (i=0; i < 8; i++){
    TransformPoint(&(obj->bbox.Vertex[i].ObjectVertex),
                   &(obj->LocalToCamera),
                   &(obj->bbox.Vertex[i].CameraVertex));

    obj->bbox.Vertex[i].ScreenVertex.x = ((obj->bbox.Vertex[i].CameraVertex.x / 
                                           obj->bbox.Vertex[i].CameraVertex.z) *
                                           cam->sx + cam->tx);
    obj->bbox.Vertex[i].ScreenVertex.y = ((obj->bbox.Vertex[i].CameraVertex.y / 
                                           obj->bbox.Vertex[i].CameraVertex.z) *
                                           cam->sy + cam->ty);                                   
  }

  /* Ensuite affichage des aretes de la bounding box */
  DrawFace(&(obj->bbox.Vertex[0].ScreenVertex),
           &(obj->bbox.Vertex[1].ScreenVertex),
           &(obj->bbox.Vertex[2].ScreenVertex),
           &(obj->bbox.Vertex[3].ScreenVertex));
  DrawFace(&(obj->bbox.Vertex[5].ScreenVertex),
           &(obj->bbox.Vertex[6].ScreenVertex),
           &(obj->bbox.Vertex[7].ScreenVertex),
           &(obj->bbox.Vertex[4].ScreenVertex));
  DrawFace(&(obj->bbox.Vertex[5].ScreenVertex),
           &(obj->bbox.Vertex[6].ScreenVertex),
           &(obj->bbox.Vertex[1].ScreenVertex),
           &(obj->bbox.Vertex[0].ScreenVertex));
  DrawFace(&(obj->bbox.Vertex[4].ScreenVertex),
           &(obj->bbox.Vertex[7].ScreenVertex),
           &(obj->bbox.Vertex[2].ScreenVertex),
           &(obj->bbox.Vertex[3].ScreenVertex)); 
}