5 Faire de la 3D

Pour que OpenGl fasse un rendu 3D il faut lui dire quel volume il doit afficher, pour cela nous avons la fonction :

1
void gluPerspective( GLdouble fovy, Gldouble aspect, GLdouble zNear, GLdouble zFar);
  • fovy : angle de vue (pour l'œil humain 70°)
  • aspect : ratio de la fenêtre (largeur/hauteur)
  • zNear : point le plus près que l'on peut afficher (généralement 1)
  • zFar : point le plus loin que l'on peut afficher

Mais cela ne suffit pas, il faut aussi préciser le mode de calcul :

1
glMatrixMode( GL_PROJECTION );

Ici on indique à OpenGl d'utiliser un mode de projection (couramment utilisé pour faire du rendu 3D).

Pour faire un rendu OpenGl utilise des matrices, mais pour les utilisées il faut les initialiser :

1
glLoadIdentity();

Cette fonction initialise la matrice de projection comme une base canonique de matrice (4,4), (des 1 sur la diagonale et des 0 partout ailleurs) :

plop

Pourquoi une matrice 4x4 ?

Nous n'allons pas rentrer dans les détails, mais c'est un moyen de pouvoir faire des translations et des rotations en même temps.

Encore une chose : le z-buffer, il est très important en 3D, il permet de mettre en place une sorte de système de priorité pour que les formes affichée en premier au premier plan ne soient pas recouvertes par le fond (par défaut OpenGl affiche dans l'ordre des appels).

Pour l'initialiser :

1
glEnable(GL_DEPTH_TEST);

Mais cela ne suffit pas dans la boucle il faut aussi effacer le z-buffer :

1
glClear(GL_COLOR_BUFFER_BIT);

Devient :

1
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Donc si on se résume l'initialisation va ressemblé à cela :

1
2
3
4
5
6
7
SDL_Init(SDL_INIT_VIDEO);
SDL_WM_SetCaption("SDL GL Application", NULL);
SDL_SetVideoMode(640, 480, 32, SDL_OPENGL);
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
gluPerspective(70,(double)640/480,1,1000);
glEnable(GL_DEPTH_TEST); //initialise le z-buffer

Vous pouvez déjà commencer à vous amuser avec ça, mais sans caméra, vous avez de grandes chances de vouloir afficher quelque chose se trouvant en fait derrière vous.

Donc vous ne voyez rien alors que vous avez effectivement fait un appel pour faire un affichage.

1
2
3
4
5
6
7
8
9
void gluLookAt(	GLdouble eyeX,
		GLdouble eyeY,
		GLdouble eyeZ,
		GLdouble centerX,
		GLdouble centerY,
		GLdouble centerZ,
		GLdouble upX,
		GLdouble upY,
		GLdouble upZ);

Où :

  • eye est la position de l'observateur en (x, y, z)
  • center est la position de ce que l'on observe en (x, y, z)
  • up est le vecteur vertical de la caméra en (x, y, z)

Le mieux c'est encore un exemple. Je vous conseil de faire cet exemple dans un nouveau dossier.

Dans un fichier main.cpp :

1
2
3
4
5
6
#include <SDL/SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>

const unsigned int WIDTH = 800;
const unsigned int HEIGHT = 600;

Je vous conseil de rajouter des constantes pour la taille de la fenêtre, ça évite de devoir changer tout les paramètres que l'on passe aux fonctions dès que l'on veut changer la taille de la fenêtre.

La fonction d'affichage :

1
2
3
4
5
6
7
8
9
10
void draw(){
	glBegin(GL_TRIANGLES);
		glColor3ub(0, 0, 255);
		glVertex3d(-0.75, -0.75, 0.0);
		glColor3ub(0, 255, 0);
		glVertex3d(-0.0, 0.75, 0.0);
		glColor3ub(255, 0, 0);
		glVertex3d(0.75, -0.75, 0.0);
	glEnd();
}

La fonction main :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main(int argc, char **argv){
	SDL_Init(SDL_INIT_VIDEO);
	SDL_WM_SetCaption("programme de base avec OpenGL pour faire de la 3D", NULL);
	SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_OPENGL);
	glMatrixMode( GL_PROJECTION ); //mode de projection
	glLoadIdentity();
	//init matrice de projection
	glEnable(GL_DEPTH_TEST); //init le z buffer
	gluPerspective(70, (double)WIDTH/HEIGHT, 1, 1000);
	gluLookAt(1.5, 1.5, 5, 0, 0, 0, 0, 1, 0); //init caméra
	SDL_Event event;
	while (event.type != SDL_QUIT){
		SDL_WaitEvent(&event);
		//on efface l'écran, que l'on a pas à trimballer
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		draw(); //notre fonction d'affichage
		glFlush();
		SDL_GL_SwapBuffers(); //ça vous rappel quelque chose
	}
	SDL_Quit(); //c'est aussi SDL qui arrête OpenGl
	return 0;
}

Voici le CMakeLists.txt qui correspond :

1
2
3
4
5
6
7
8
9
10
11
12
project(exOpengl3d)
cmake_minimum_required(VERSION 2.6)
#on demande a CMake de trouver les paquets SDL et OpenGl
find_package(SDL REQUIRED)
find_package(OpenGl)
#il faut inclure de dossier ${SDL_INCLUDE_DIR} ou il y a les .h de SDL
include_directories(${SDL_INCLUDE_DIR})

#on créé l’exécutable
add_executable(exOpengl3d main.cpp)
#on lie SDL au programme
target_link_libraries(exOpengl3d SDL GL GLU)

Donc, vous créez un nouveau dossier build :

mkdir build

Ensuite vous entrez dedans :

cd build

Et vous appelez CMake :

cmake ..
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Looking for include files CMAKE_HAVE_PTHREAD_H
-- Looking for include files CMAKE_HAVE_PTHREAD_H - found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE 
CMake Warning at CMakeLists.txt:5 (find_package):
  Could not find module FindOpenGl.cmake or a configuration file for package
  OpenGl.

  Adjust CMAKE_MODULE_PATH to find FindOpenGl.cmake or set OpenGl_DIR to the
  directory containing a CMake configuration file for OpenGl.  The file will
  have one of the following names:

    OpenGlConfig.cmake
    opengl-config.cmake



-- Configuring done
-- Generating done

Ensuite on appel Make :

make
Scanning dependencies of target exOpengl3d
[100%] Building CXX object CMakeFiles/exOpengl3d.dir/main.cpp.o
Linking CXX executable exOpengl3d
[100%] Built target exOpengl3d

Exécutons le programme :

./exOpengl3d

plop

L'affichage du triangle est déformé car on le voit de biais maintenant.

Maintenant qu'on fait vraiment de la 3D vous pouvez tester toutes les formes que fournit OpenGl.