/**
 * @file libtpnote.h
 *
 * @brief Fichier d'en-tête de la bibliothèque de fonctions utilisées pour le
 * TP noté.
 *
 * Cette bibliothèque propose une réécriture de certaines fonctions d'OpenGL
 * utilisées au cours des TP précédents et une fonction permettant de récupérer
 * les coordonnées des points d'une facette triangulaire et de leur projection
 * sur la fenêtre de rendu.
 *
 * Cette bibliothèque gère directement ses propres matrices et chaque fonction
 * ne porte que sur une matrice spécifique. Il n'y a donc pas d'équivalent à la
 * fonction glEnable(), fonction qui ne doit pas être utilisée.
 */



#ifndef TP_NOTE_H
#define TP_NOTE_H



/**
 * Cette structure définit un point dans un environnement 3D, avec
 * coordonnée homogène.
 */
typedef struct {
  double x; /**< coordonnée X du point. */
  double y; /**< coordonnée Y du point. */
  double z; /**< coordonnée Z du point. */
  double t; /**< coordonnée homogène du point. */
} Point3D;



/**
 * Cette structure définit un point projeté sur l'écran, donc en 2
 * dimensions, mais conservant les coordonnées initiales du point.
 * Les coordonnées du point initial sont (real_x, real_y, real_z)
 * et les coordonnées du point où il est projeté sur l'écran sont
 * (proj_x, proj_y).
 */
typedef struct {
  int    proj_x;        /**< coordonnée X du point projeté sur l'écran. */
  int    proj_y;        /**< coordonnée Y du point projeté sur l'écran. */
  double proj_distance; /**< Distance du point à la caméra. */
} PointProjete;



/**
 * Définit les paramètres de la projection perspective à utiliser.
 * @param foc Largeur de l'angle d'observation, selon y, en degrés
 * @param ratio Rationde la largeur sur la hauteur de la fenêtre
 * @param znear Distance, à partir du point d'observation, du plan de clipping
 * proche. Cette valeur doit toujours être strictement positive.
 * @param zfar Distance, à partir du point d'observation, du plan de clipping
 * lointain. Cette valeur doit toujours être strictement positive.
 * @see Cette fonction est équivalente à la fonction OpenGL gluPerspective()
 * que nous avons utilisée lors des TP précédents.
 */
void libtpnotePerspective(double foc, double ratio, double znear, double zfar);	



/**
 * Définit une transformation d'observation.
 * @param px Coordonnée x du point d'observation
 * @param py Coordonnée y du point d'observation
 * @param pz Coordonnée z du point d'observation
 * @param dx Coordonnée x du point de référence (direction de la caméra)
 * @param dy Coordonnée y du point de référence (direction de la caméra)
 * @param dz Coordonnée z du point de référence (direction de la caméra)
 * @param upx Coordonnée x du vecteur parallèle au vecteur y de la fenêtre
 * @param upy Coordonnée y du vecteur parallèle au vecteur y de la fenêtre
 * @param upz Coordonnée y du vecteur parallèle au vecteur y de la fenêtre
 * @see Cette fonction est équivalente à la fonction OpenGL gluLookAt() que
 * nous avons utilisée lors des TP précédents.
 */
void libtpnoteLookAt(double px, double py, double pz,
		     double dx, double dy, double dz,
		     double upx, double upy, double upz);



/**
 * Rotation du prochain objet à afficher.
 * @param angle Angle de rotation, en degrés
 * @param x Coordonnée x du vecteur utilisé comme axe de rotation
 * @param y Coordonnée y du vecteur utilisé comme axe de rotation
 * @param z Coordonnée z du vecteur utilisé comme axe de rotation
 * @see Cette fonction est équivalente à la fonction OpenGL glRotated() que
 * nous avons utilisée lors des TP précédents.
 */
void libtpnoteRotated(double angle, double x, double y, double z);



/**
 * Rotation du prochain objet à afficher.
 * @param angle Angle de rotation, en degrés
 * @param x Coordonnée x du vecteur utilisé comme axe de rotation
 * @param y Coordonnée y du vecteur utilisé comme axe de rotation
 * @param z Coordonnée z du vecteur utilisé comme axe de rotation
 * @see Cette fonction est équivalente à la fonction OpenGL glRotatef() que
 * nous avons utilisée lors des TP précédents.
 */
void libtpnoteRotatef(float angle, float x, float y, float z);



/**
 * Translation du prochain objet à afficher.
 * @param x Coordonnée x du vecteur de translation
 * @param y Coordonnée y du vecteur de translation
 * @param z Coordonnée z du vecteur de translation
 * @see Cette fonction est équivalente à la fonction OpenGL glTranslated() que
 * nous avons utilisée lors des TP précédents.
 */
void libtpnoteTranslated(double x, double y, double z);



/**
 * Translation du prochain objet à afficher.
 * @param x Coordonnée x du vecteur de translation
 * @param y Coordonnée y du vecteur de translation
 * @param z Coordonnée z du vecteur de translation
 * @see Cette fonction est équivalente à la fonction OpenGL glTranslatef() que
 * nous avons utilisée lors des TP précédents.
 */
void libtpnoteTranslatef(float x, float y, float z);



/**
 * Mise à l'échelle du prochain objet à afficher.
 * @param x Facteur d'échelle selon le vecteur x
 * @param y Facteur d'échelle selon le vecteur y
 * @param z Facteur d'échelle selon le vecteur z
 * @see Cette fonction est équivalente à la fonction OpenGL glScaled() que
 * nous avons utilisée lors des TP précédents.
 */
void libtpnoteScaled(double x, double y, double z);



/**
 * Mise à l'échelle du prochain objet à afficher.
 * @param x Facteur d'échelle selon le vecteur x
 * @param y Facteur d'échelle selon le vecteur y
 * @param z Facteur d'échelle selon le vecteur z
 * @see Cette fonction est équivalente à la fonction OpenGL glScalef() que
 * nous avons utilisée lors des TP précédents.
 */
void libtpnoteScalef(float x, float y, float z);



/**
 * Mémorise la matrice de transformation des objets en cours.
 * @see libtpnotePopMatrix()
 * @see Cette fonction est équivalente à la fonction OpenGL glPushMatrix() que
 * nous avons utilisée lors des TP précédents.
 */
void libtpnotePushMatrix();



/**
 * Récupère la dernière matrice de transformation des objets mémorisée avec la
 * fonction libtpnotePushMatrix(), qui devient alors la matrice de transformation
 * des objets en cours.
 * @see libtpnotePushMatrix()
 * @see Cette fonction est équivalente à la fonction OpenGL glPopMatrix() que
 * nous avons utilisée lors des TP précédents.
 */
void libtpnotePopMatrix();



/**
 * Cette fonction génère un tableau contenant tous les points devant être
 * afficher à l'écran pour représenter le facette dont les trois points sont
 * passés en paramètre. Ce calcul dépend des matrices de déplacement de l'objet
 * et des matrices d'affichage définies par les autre fonctions de la
 * bibliothèque, comme cela se fait sous openGL.
 * @param [in] a Premier sommet de la facette.
 * @param [in] b Second sommet de la facette.
 * @param [in] c Troisième sommet de la facette.
 * @param [out] resultat Pointeur sur le tableau qui va contenir les points
 * projetés sur l'écran.
 * @param [in] largeur_fenetre Largeur de la fenêtre (en pixels).
 * @param [in] hauteur_fenetre Hauteur de la fenêtre (en pixels).
 * @return Le nombre de points calculés et placés dans le tableau resultat.
 * @warning Le tableau pointé par *resultat sera libéré et réalloué par la
 * fonction realloc(). Le pointeur doit être initialisé à NULL avant le
 * premier appel à cette fonction et ne doit plus être modifié ni désalloué
 * ensuite hors de la fonction. De plus, la fonction devra toujours utiliser
 * le même pointeur.
 */
unsigned int generate_pixels(Point3D a, Point3D b, Point3D c,
			     PointProjete ** resultat,
			     int largeur_fenetre, int hauteur_fenetre);



/**
 * Transforme le point 3D avec coordonnée homogène en lui appliquant la matrice
 * de transformation de l'objet en cours.
 * @param point Le point à transformer.
 * @return Le point transformé
 * @warning Souvenez-vous de la différence entre points et vecteurs vue en TD.
 */
Point3D transformePoint(Point3D point);


#endif // TP_NOTE_H
