La programmation Open GL sur OS X
Par Contributeur - Publié le
Petit avertissement...
Tout d'abord, un petit avertissement : pour programmer en Open GL, il faut utiliser le langage C. Si vous n'en connaissez pas les bases, vous allez vous sentir un peu perdu. Toutefois, cet article est plutôt simple à comprendre, et vous pouvez toujours faire un simple copier coller et suivre les instructions. Sachez seulement qu'il faut respecter les majuscules et la syntaxe. Les passages situés derrière // ou entre /[ et ]/ sont des commentaires qui ne sont pas nécessaire ni pris en charge par le compilateur mais je vous conseille fortement d'en mettre si vous voulez vous y retrouver.
Vous allez aussi devoir installer les developpers tools inclus dans la boite de Mac OS X.
Créer un projet
Pour commencer, vous devez créer un nouveau projet. Faites 'newproject' dans le menu file. Choisissez 'empty project' et faites next. Donnez un nom et un emplacement au nouveau projet. Une fenêtre s'ouvre: c'est votre environnement de travail. A gauche, vous pourrez voir tout les fichiers qui composent votre programme et les visualiser dans la fenêtre principale en cliquant dessus.
Faites 'new target' dans le menu project, choisissez "cocoa application" et faites next. Donnez lui un nom et ajoutez la à votre projet. Elle apparaîtra à gauche dans l'onglet targets.
Vous devez maintenant ajouter les librairies glut à votre programme. Faite add framework dans le menu project et sélectionnez "GLUT.framework", "AppKit.framework" et "OpenGL.framework". Ajoutez le à votre projet. Il devrait apparaître dans l'onglet files.
Faites maintenant new file dans le menu file et sélectionnez "C file". Appelez le fichier "source.c".
Vous devriez normalement avoir quelquechose qui ressemble à la copie d'écran ci-dessus (attention ! le point à gauche de source.c et des trois ".framework" doit être présent, sinon cliquez à leur gauche pour qu'il apparaisse).
Le programme
Cliquez sur source.c dans l'onglet files. Son contenu apparaît au centre.
Rajoutez "#include ‹GLUT/glut.h›" en dessous de "#include ‹CARBON/carbon.h›" afin d'établir un lien entre les librairies openGL et votre programme.
Nous avons maintenant besoin de définir quelques valeurs:
tapez ces 2 lignes :
#define kWWidth 500
#define kWHeight 500
Le programme se compose pour l'instant de 3 fonctions: une d'initialisation, une pour donner des instructions (en l'occurrence, dessiner quelque chose) et une pour exécuter le tout.
Voici la première qui se contente d'initialiser les fonctions openGL :
GLvoid initialisation(GLvoid) { // n'oubliez pas l'accolade pour ouvrir et fermer la fonction
glClearColor(0.0f,0.0f,0.0f,0.0f); /[ les f après les valeurs sont nécessaires pour indiquer qu'il s'agit de décimaux]/
glClearDepth(1.0);
// Ça, c'est juste pour tout remettre à 0
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)kWWidth/(GLfloat)kWHeight,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
/[et tout ça, c'est des histoires de modes de projections. On va pas rentrer dans les details, Vous les mettez, sans vous en occuper.
N'oubliez pas l'accolade pour signaler au programme la fin de votre fonction.]/
}
La prochaine étape consiste à écrire une fonction qui va créer des polygones
Pour cela, il faut définir les coordonnées de chaque point dans l'espace. On peut régler 3 valeurs par point : x,y et z: respectivement la longueur, la hauteur et la profondeur. Le plus difficile est de se représenter les points dans l'espace. Je vous conseille pour cela de faire un petit schéma. Les points sont calculés à partir du centre que l'on peut déplacer avec la fonction "translatef(x,y,z)". On utilise la fonction glVertex3f(x,y,z) pour définir la position des points.
Par exemple, un simple carré aura donc besoin de 4 points :
1er point: en haut à droite -> glVertex3f(1.0f,1.0f,0.0f);
c'est à dire 1 unité au dessus du centre et une unité à droite du centre.
2e point: en haut à gauche -> glVertex3f(-1.0f,1.0f,0.0f);
c'est à dire 1 unité au dessus du centre et une unité à gauche du centre.
3e point: en bas à gauche -> glVertex(-1.0f,-1.0f,0.0f);
c'est à dire 1 unité en dessous du centre et une unité à gauche du centre.
4e point: en bas à droite -> glVertex3f(1.0f,1.0f,0.0f);
c'est à dire 1 unité en dessous du centre et une unité à droite du centre.
Note: il est impératif de suivre cet ordre sinon vous allez vous retrouver avec des formes bizarres n'ayant rien à voir avec votre carré.
Mais ce n'est pas tout, il faut aussi définir une couleur sinon, vous ne verrez pas vos polygones. On utilise la fonction glColor3f(r,g,b) où r,g et b sont red green et blue. En mélangeant ces 3 trois couleurs, vous pouvez obtenir toutes les couleurs. Pour trouver à quelles couleurs correspondent les valeurs, utilisez n'importe quel logiciel de dessin (graphic converter par exemple) et choisissez le mode rgb, faites des essais et une fois la couleur trouvée, retenez les valeurs pour le rouge le bleu et le vert (100 % correspond à1.0f et 50% correspond à 0.5f). Le moyen le plus simple est d'utiliser seulement le bleu, le rouge ou le vert : il suffit de mettre 1.0f pour la couleur désirée et 0.0f pour les autres.
Exemple : pour du bleu, on donnera les valeurs suivantes "glColor3f(0.0f,0.0f,1.0f);" -> 0% de rouge, 0% de vert et 100% de bleu mais pour du violet, il faudra utiliser plusieurs couleurs :
"glColor3f(0.5f,0.0f,1.0f);" -> 50% de rouge, 0% de vert et 100% de bleu
Sachez aussi que 100% de chaque couleur donne du blanc et 0 % de chaque couleur donne du noir.
Voici donc la fonction de dessin :
GLvoid creation(GLvoid) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // le signe | s'obtient avec shift alt l
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f); // recule le centre de 5
glBegin(GL_QUADS); // mode de dessin : carrés
/[face frontale]/
glColor3f(0.0f,0.0f,1.0f); // couleur: bleu
glVertex3f(-1.0f,1.0f,0.0f);
glVertex3f(1.0f,1.0f,0.0f);
glVertex3f(1.0f,-1.0f,0.0f);
glVertex3f(-1.0f,-1.0f,0.0f);
/[face arrière]/
glColor3f(1.0f,0.0f,0.0f);
glVertex3f(-1.0f,1.0f,-1.0f);
glVertex3f(1.0f,1.0f,-1.0f);
glVertex3f(1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
/[dessus du cube]/
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
/[dessous du cube ]/
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,1.0f,1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
/[côté gauche du cube]/
glColor3f(0.0f,0.5f,1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
/[côté droit du cube ]/
glColor3f(0.5f,0.0f,1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glEnd(); // fin du mode carré
glPushMatrix(); //valider le tout
glutSwapBuffers(); // afficher
}
Et enfin, la fonction principale, qui va faire appel à toutes les autres :
int main(int argc,char*[ argv) {
glutInit(&argc, argv); //initialisation ...
glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE); // encore de l'initialisation
glutInitWindowSize(kWWidth,kWHeight); // initialisation de la taille d la fenetre du programme
glutInitWindowPosition(250,250); // initialisation de la position de la fenêtre du programme
glutCreateWindow("mac4ever"); // création de la fenêtre du programme avec le nom mac4ever
initialisation(); // appel à la fonction initialisation
glutDisplayFunc(creation); // le programme se sert de la fonction creation pour afficher le contenu
glutMainLoop();
return 0; // cette instruction est requise par l' ANSI C
}
Voilà ! Une fois que vous avez écrit tout ça, compilez et lancez le programme (ou faites directement pomme R).
C'est bien beau me direz vous, mais on voit qu'un côté. Logique !
Nous allons donc rajouter de quoi faire tourner notre cube:
Tout d'abord, rajoutez la variable "GLfloat r = 0.0f;" après "#define kWHeight 500" au début du fichier:
Puis il nous faut une 4e fonction :
GLvoid Idle(GLvoid) {
r += 0.5f; // augmente la vitesse de 0.5
glutPostRedisplay(); // redessine l'objet
}
Dans la fonction main(), après "glutDisplayFunc(creation);" , ajoutez à la ligne "glutIdleFunc(Idle);" puis ajoutez "r=0;" avant "return 0;"
Ensuite, dans la fonction creation() rajoutez juste ceci avant
glBegin(GL_QUADS);
glRotatef(r,1.0f,1.0f,0.0f);
où r indique la vitesse de rotation, les 3 autres valeurs correspondant
aux trois axes. Dans ce cas-ci, le cube tourne autour d'un axe vertical et horizontal.
La source complète en une seule partie
#include <GLUT/glut.h>
#define kWWidth 500
#define kWHeight 500
GLfloat r = 0.0f;
GLvoid initialisation(GLvoid) {
glClearColor(0.0f,0.0f,0.0f,0.0f);
glClearDepth(1.0);
/[ Ca, c'est juste pour tout remettre à 0 ]/
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)kWWidth/(GLfloat)kWHeight,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
/[N'oubliez pas l'accolade pour signaler au programme la fin de votre fonction.]/
}
GLvoid Idle(GLvoid) {
r += 0.5f; // augmente la vitesse de 0.5
glutPostRedisplay(); // redessine l'objet
}
GLvoid creation(GLvoid) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f); // recule le centre de 5
glRotatef(r,1.0f,1.0f,0.0f); /[ r indique la vitesse de rotation, les 3 autres valeurs correspondant
aux trois axes. Dans ce cas-ci, le cube tourne autour d'un axe vertical et horizontal. ]/
glBegin(GL_QUADS); // mode de dessin : carrés
/[ face frontale ]/
glColor3f(0.0f,0.0f,1.0f); // couleur: bleu
glVertex3f(-1.0f,1.0f,1.0f); // en haut àgauche
glVertex3f(1.0f,1.0f,1.0f); // en haut à droite
glVertex3f(1.0f,-1.0f,1.0f); // en bas à droite
glVertex3f(-1.0f,-1.0f,1.0f); // en bas à gauche
/[ face arrière ]/
glColor3f(1.0f,0.0f,0.0f); rouge
glVertex3f(-1.0f,1.0f,-1.0f); // en haut à gauche
glVertex3f(1.0f,1.0f,-1.0f); // en haut à droite
glVertex3f(1.0f,-1.0f,-1.0f); // en bas à droite
glVertex3f(-1.0f,-1.0f,-1.0f); // en bas à gauche
/[ dessus du cube ]/
glColor3f(0.0f,1.0f,0.0f); vert
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
/[ dessous du cube ]/
glColor3f(1.0f,0.0f,0.0f); rouge
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,1.0f,1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
/[ côté gauche du cube ]/
glColor3f(0.0f,0.5f,1.0f); orange
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
/[ côté droit du cube ]/
glColor3f(0.5f,0.0f,1.0f); violet
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glEnd(); // fin du mode carrés
glPushMatrix(); //valider le tout
glutSwapBuffers(); // afficher
}
int main(int argc,char][ argv) {
glutInit(&argc, argv); //initialisation ...
glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE); // encore de l'initialisation
glutInitWindowSize(kWWidth,kWHeight); /[ initialisation de la taille de la fenêtre du programme ]/
glutInitWindowPosition(250,250); /[ initialisation de la position de la fenetre du programme ]/
glutCreateWindow("mac4ever"); /[ création de la fenêtre du programme avec le nom mac4ever ]/
initialisation(); /[ appel à la fonction initialisation ]/
glutDisplayFunc(creation); /[ le programme se sert de la fonction creation pour afficher le contenu ]/
glutIdleFunc(Idle); /[ appel de la fonction pour augmenter la vitesse et ainsi fair tourner le cube ]/
glutMainLoop();
r=0;
return 0; // cette instruction est requise par l' ANSI C
}
A vous de jouer...
Et voilà le travail ! Vous avez maintenant un joli cube qui tourne sur lui même ! Et ça sert à quoi ? A rien ! C'est juste pour faire joli ;-).
Maitenant que vous connaissez la marche à suivre pour programmer des scènes OpenGL, à vous d'étendre et de nous développer des Quake IV ou Unreal II...