Introduction
Dans ce projet, nous allons créer une simple animation d'horloge à l'aide d'OpenGL et de GLUT (Graphics Library Utility Toolkit). Cette animation affichera une horloge avec des aiguilles d'horloge en mouvement pour représenter l'heure actuelle. L'horloge sera mise à jour en temps réel, simulant le mouvement des aiguilles des heures, des minutes et des secondes. Nous commencerons par configurer les fichiers du projet puis procéderons avec le code nécessaire.
👀 Aperçu

🎯 Tâches
Dans ce projet, vous allez apprendre :
- Comment configurer les fichiers et les bibliothèques du projet
- Comment créer la fenêtre et initialiser OpenGL
- Comment dessiner le fond et le contour de l'horloge
- Comment tourner l'horloge pour avoir la position des 12 heures en haut
- Comment obtenir l'heure actuelle et calculer les positions des aiguilles d'horloge
- Comment dessiner les aiguilles des heures, des minutes et des secondes sur l'horloge
- Comment redimensionner la fenêtre et afficher l'horloge en temps réel
🏆 Réalisations
Après avoir terminé ce projet, vous serez capable de :
- Configurer et initialiser OpenGL et GLUT
- Dessiner des formes et des lignes de base à l'aide d'OpenGL
- Tourner des objets dans OpenGL
- Récupérer l'heure actuelle et l'utiliser pour animer des objets
- Gérer le redimensionnement de la fenêtre et l'affichage en temps réel des graphiques
Créer les fichiers du projet
Tout d'abord, exécutez la commande suivante dans le terminal pour installer les bibliothèques OpenGL et GLUT :
sudo apt update
sudo apt-get install mesa-utils freeglut3-dev -y
Cela installera la bibliothèque de graphiques 3D Mesa ainsi que la bibliothèque GLUT. Après cela, vous pourrez compiler des programmes OpenGL à l'aide de gcc.
Ensuite, créez un nouveau fichier nommé clock_opengl.c et ouvrez-le dans votre éditeur de code préféré.
cd ~/projet
touch clock_opengl.c
Inclure les en-têtes et définir les variables
Ensuite, nous allons écrire le code étape par étape pour implémenter ce projet.
#include <GL/gl.h>
#include <GL/glut.h>
#include <time.h>
#include <math.h>
#include <stdio.h>
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
const int ROTATE_DEGREES = 180;
Trois constantes entières sont définies, WINDOW_WIDTH, WINDOW_HEIGHT et ROTATE_DEGREES. Ces constantes sont utilisées pour définir la largeur et la hauteur de la fenêtre et l'angle de rotation.
Configurer la fenêtre et initialiser OpenGL
Dans cette étape, nous allons configurer la taille de la fenêtre et initialiser OpenGL et GLUT.
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow("Horloge Animation");
glutDisplayFunc(drawClockHands);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
glClearColor(0.0, 0.0, 0.0, 1.0);
glutMainLoop();
return 0;
}
glutInit(): Elle est utilisée pour initialiser la bibliothèque GLUT.glutInitDisplayMode(): Définit le mode d'affichage de la fenêtre.GLUT_DOUBLEsignifie d'utiliser le double-buffering, etGLUT_RGBsignifie d'utiliser le mode de couleur RGB.glutInitWindowSize(): Définit la taille de la fenêtre.glutCreateWindow(): Crée une fenêtre et définit le titre de la fenêtre surHorloge Animation.glutDisplayFunc(): Définit la fonction de dessin de sorte que la fonctiondrawClockHandssoit appelée lorsqu'un graphique doit être dessiné.glutReshapeFunc(): Définit la fonction de rappel pour le redimensionnement de la fenêtre, c'est-à-dire que lorsque la taille de la fenêtre change, la fonctionreshapesera appelée.glutIdleFunc(): Définit la fonction de rappel inactif, c'est-à-dire que la fonctionidlesera appelée lorsqu'il n'y a pas d'autres traitements d'événements.glClearColor(0.0, 0.0, 0.0, 1.0): Définit la couleur vide sur le noir (valeur de couleur RGBA).glutMainLoop(): Entrer dans la boucle principale de GLUT, qui continue de fonctionner, gère les événements de fenêtrage, dessine les graphiques et les entrées utilisateur.
Dessiner l'arrière-plan de l'horloge
Créez une fonction appelée drawClockHands, nous allons ajouter du code pour dessiner l'arrière-plan de l'horloge, y compris un cercle de couleur foncée.
void drawClockHands() {
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_QUADS);
glColor3f(0.1, 0.1, 0.1);
glVertex2f(-1, -1);
glVertex2f(1, -1);
glVertex2f(1, 1);
glVertex2f(-1, 1);
glEnd();
}
glClear(): Cette fonction d'appel efface le tampon de couleur en préparation pour le dessin d'un nouveau graphique.GL_COLOR_BUFFER_BITsignifie d'effacer le tampon de couleur de sorte que le contenu du dessin précédent soit effacé avant le dessin d'un nouveau dessin.glBegin(): Cette fonction indique le début de la définition d'un élément (dans ce cas, un quadrilatère).GL_QUADSsignifie que nous voulons utiliser des quadrangles pour définir le graphique.glColor3f(): Définit la valeur à virgule flottante de la couleur de dessin actuelle en tant que couleurs RGB (rouge, vert, bleu). Ici, la couleur est définie en gris foncé, avec les valeurs RGB(0,1, 0,1, 0,1)représentant le gris foncé.glVertex2f(): Définit les coins d'un quadrilatère.
Le but ici est de dessiner un rectangle gris foncé dans la fenêtre OpenGL comme arrière-plan de l'horloge. Les quatre sommets définissent les limites du rectangle, et le code entre glBegin et glEnd est utilisé pour définir l'apparence du graphique. Ceci est une partie du dessin de l'arrière-plan de l'horloge, qui est généralement dessiné avant d'autres éléments tels que l'aiguille des heures, l'aiguille des minutes, l'aiguille des secondes, etc.
Faire tourner l'horloge
Nous allons ajouter du code pour faire tourner l'horloge de 180 degrés pour avoir la position des 12 heures en haut.
// Dans la fonction drawClockHands()
glPushMatrix();
glRotatef(ROTATE_DEGREES, 0, 0, 1);
glPushMatrix(): C'est une fonction en OpenGL qui place l'état actuel de la matrice (généralement la matrice de vue 3D) sur la pile pour qu'elle puisse être restaurée plus tard. C'est une pratique courante car vous pouvez avoir besoin de faire plusieurs transformations de matrice différentes dans un dessin, et vous devez vous assurer que les transformations suivantes n'affectent pas les états précédents.glRotatef(): C'est une autre fonction OpenGL qui effectue la transformation de rotation. Elle fait tourner la matrice de vue 3D actuelle deROTATE_DEGREESautour de l'axe Z.(0, 0, 1)est la définition de l'axe de rotation, ce qui signifie ici une rotation autour de l'axe Z. La première valeur est la composante de rotation autour de l'axe X, la deuxième valeur est la composante de rotation autour de l'axe Y, et la troisième valeur est la composante de rotation autour de l'axe Z.
Dessiner le contour de l'horloge
Nous allons dessiner le contour de l'horloge avec des marques pour chaque heure.
// Dans la fonction drawClockHands()
glLineWidth(3.0);
glBegin(GL_LINE_LOOP);
for (int i = 0; i < 360; i += 6) {
double angle = i * M_PI / 180;
double x = 0.9 * cos(angle);
double y = 0.9 * sin(angle);
glColor3f(1.0, 1.0, 1.0);
glVertex2d(x, y);
}
glEnd();
Le principal but ici est de dessiner un contour circulaire blanc sur l'arrière-plan de l'horloge, représentant le cadre extérieur de l'horloge. glLineWidth définit la largeur de la ligne, et la boucle entre glBegin et glEnd dessine une série de points sur un cercle centré à l'origine, qui sont ensuite connectés pour former une boucle fermée, le contour extérieur de l'horloge.
Obtenir l'heure actuelle et calculer les positions des aiguilles d'une horloge
Nous allons récupérer l'heure actuelle et calculer les positions des aiguilles de l'horloge : heures, minutes et secondes.
// Dans la fonction drawClockHands()
time_t rawtime;
struct tm* timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
int hours = timeinfo->tm_hour % 12;
int minutes = timeinfo->tm_min;
int seconds = timeinfo->tm_sec;
Une variable nommée rawtime est définie pour stocker les données de temps brute issues du système. time_t est un type de données couramment utilisé pour représenter le nombre de secondes dans le temps, depuis un point de temps spécifique (généralement le 1er janvier 1970) jusqu'à présent.
Définit un pointeur vers une structure tm appelée timeinfo. La structure tm est utilisée pour stocker les différents composants d'informations de date et d'heure, telles que l'année, le mois, le jour, l'heure, les minutes, les secondes, etc.
Utilise la fonction time pour obtenir l'heure système actuelle, en stockant les secondes de l'heure dans la variable rawtime. Le nombre de secondes renvoyé par la fonction time représente le nombre de secondes depuis un point de temps spécifique (généralement le 1er janvier 1970, également appelé timestamp UNIX) jusqu'à l'heure actuelle.
Utilise la fonction localtime pour convertir le nombre de secondes obtenu à partir de la fonction time (stocké dans la variable rawtime) en informations concrètes de date et d'heure, et stocke le résultat dans une structure timeinfo. La fonction localtime convertit le nombre de secondes en informations telles que l'année, le mois, le jour, l'heure, les minutes, les secondes, etc., et stocke ces informations dans la structure timeinfo.
Obtient le nombre d'heures actuelles à partir de la structure timeinfo, puis module 12 pour limiter le nombre d'heures à une échelle de 12 heures, tm_hour indique l'heure. Obtient le nombre de minutes actuelles à partir de la structure timeinfo, tm_min indique les minutes. Obtient le nombre de secondes actuelles à partir de la structure timeinfo, tm_sec indique les secondes.
Dessiner l'aiguille des heures
Nous allons dessiner l'aiguille des heures sur l'horloge.
// Dans la fonction drawClockHands()
double hourAngle = -(90 + hours * 360 / 12) + (360 / 12) * minutes / 60;
glLineWidth(5.0); // Définir la largeur de la ligne
glBegin(GL_LINES);
glVertex2d(0, 0);
glColor3f(1.0, 0.0, 0.0); // Couleur de l'aiguille des heures
glVertex2d(0.5 * cos(hourAngle * M_PI / 180), 0.5 * sin(hourAngle * M_PI / 180));
glEnd();
Tout d'abord, les horloges sont généralement sur une échelle de 12 heures, donc le nombre d'heures doit être converti en Angle sur le cadran de l'horloge. Ce calcul commence par projeter le nombre d'heures d'une échelle de 12 heures sur une plage angulaire de 360 degrés. La contribution des minutes (par la position de l'aiguille des minutes) est ensuite ajoutée à l'angle des heures. Le hourAngle résultant représente l'angle de l'aiguille des heures par rapport à la direction des 12 heures.
Ensuite, définir un élément, dans ce cas un segment de ligne, représentant l'aiguille des heures. Le point de départ du segment de ligne est situé aux coordonnées (0, 0), le centre de l'horloge. Le point d'arrivée du segment de ligne, en utilisant les fonctions trigonométriques cos et sin pour calculer la position finale de l'aiguille des heures. Les aiguilles des minutes et des secondes suivantes sont également dessinées de cette manière.
Dessiner l'aiguille des minutes
Nous allons ajouter du code pour dessiner l'aiguille des minutes sur l'horloge.
// Dans la fonction drawClockHands()
double minuteAngle = -(90 + minutes * 360 / 60);
glLineWidth(3.0); // Définir la largeur de la ligne
glBegin(GL_LINES);
glVertex2d(0, 0);
glColor3f(0.0, 1.0, 0.0); // Couleur de l'aiguille des minutes
glVertex2d(0.7 * cos(minuteAngle * M_PI / 180), 0.7 * sin(minuteAngle * M_PI / 180));
glEnd();
Le cadran de l'horloge est généralement de 60 minutes, donc le nombre de minutes doit être converti en Angle sur le cadran de l'horloge. Ce calcul projette d'abord le nombre de minutes sur une plage angulaire de 360 degrés et le soustrait de 90 degrés pour que 0 minute corresponde à la direction des 12 heures. Le minuteAngle résultant représente l'angle de l'aiguille des minutes par rapport à la direction des 12 heures.
Dessiner l'aiguille des secondes
Nous allons ajouter du code pour dessiner l'aiguille des secondes sur l'horloge.
// Dans la fonction drawClockHands()
double secondAngle = -(90 + seconds * 360 / 60);
glLineWidth(1.0); // Définir la largeur de la ligne
glBegin(GL_LINES);
glVertex2d(0, 0);
glColor3f(0.0, 0.0, 1.0); // Couleur de l'aiguille des secondes
glVertex2d(0.9 * cos(secondAngle * M_PI / 180), 0.9 * sin(secondAngle * M_PI / 180));
glEnd();
Les horloges ont généralement 60 secondes, donc le nombre de secondes doit être converti en Angle sur la face de l'horloge. Ce calcul projette d'abord le nombre de secondes sur une plage angulaire de 360 degrés et le soustrait de 90 degrés pour que 0 seconde corresponde à la direction des 12 heures. Le secondAngle résultant représente l'angle de l'aiguille des secondes par rapport à la direction des 12 heures.
Enfin, nous allons restaurer la rotation d'origine et afficher l'animation de l'horloge.
// Dans la fonction drawClockHands()
glPopMatrix();
glutSwapBuffers();
glPopMatrix() est utilisé pour restaurer l'état de la matrice précédemment enregistré, et glutSwapBuffers() est utilisé pour terminer le dessin à double tampon, affichant l'image dessinée sur l'écran pour obtenir des effets d'animation fluides.
Redimensionnement de la fenêtre et affichage en temps réel
Nous allons créer une fonction reshape qui est appelée lorsque la taille de la fenêtre change.
void reshape(int w, int h) {
glViewport(0, 0, w, h); // Définir la vue OpenGL pour ajuster la taille de la fenêtre
glMatrixMode(GL_PROJECTION); // Passer en mode de matrice de projection
glLoadIdentity(); // Réinitialiser la matrice actuelle
gluOrtho2D(-1, 1, -1, 1); // Définir la matrice de projection orthographique
glMatrixMode(GL_MODELVIEW); // Revenir en mode de matrice vue-modèle
}
Le but de cette fonction reshape est d'ajuster la vue OpenGL en fonction de la nouvelle taille de la fenêtre lorsque la taille de la fenêtre change, et de définir la matrice de projection appropriée pour s'assurer que le graphique dessiné s'affichera toujours correctement sous la nouvelle taille de la fenêtre.
Ensuite, nous définissons une fonction appelée idle pour effectuer certaines opérations lorsque le programme est inactif.
void idle() {
glutPostRedisplay(); // Demander un redessin lorsque le programme est inactif
}
Le but de cette fonction idle est d'appeler glutPostRedisplay() lorsque le programme est inactif ; Pour demander que le contenu de la fenêtre soit redessiné afin d'animer ou de mettre à jour en temps réel le contenu de la fenêtre.
Compiler et exécuter le projet
- Ouvrez votre terminal et accédez au répertoire du projet.
cd ~/projet
- Compilez le code à l'aide de la commande suivante :
gcc -o clock_opengl clock_opengl.c -lGL -lglut -lGLU -lm
- Exécutez l'application :
./clock_opengl

Résumé
Dans ce projet, vous avez appris à créer une animation simple d'horloge à l'aide d'OpenGL et de GLUT. Nous avons abordé la configuration des fichiers du projet, l'initialisation de la fenêtre et d'OpenGL, le dessin du fond de l'horloge, la rotation de l'horloge, le dessin du contour de l'horloge, la récupération de l'heure actuelle et le dessin des aiguilles de l'horloge. En suivant ces étapes, vous pouvez créer une animation de base d'horloge qui affiche l'heure actuelle de manière visuellement attrayante.



