8.9.3 Plaquer des textures sur des surfaces carrée ou triangulaire

Ça tombe bien, nous avons justement un carré dans notre scène.

En fait ce que l'on vient de faire avec les sphère fonctionne aussi avec toutes les formes de OpenGl, vous avez bien vu le petit problème que l'on eut tout à l'heure avec le plaquage de la texture.

Alors pourquoi on ferrait différemment si ça fonctionne.

C'est que, la plupart du temps la texture ne va pas se plaquer comme vous voulez, donc il faut le faire plus précisément.

Résumons la situation.

Vous écrivez ceci pour faire un carré :

1
2
3
4
5
6
glBegin(GL_QUADS);
	glVertex3d(10.0, 10.0, 0.0);
	glVertex3d(10.0, -10.0, 0.0);
	glVertex3d(-10.0, -10.0, 0.0);
	glVertex3d(-10.0, 10.0, 0.0);
glEnd();

Tout d'abord il faut savoir comment est définit le repère d'une image (et oui, il y en a un).

L'image peut faire la taille que vous voulez, cela ne changera rien :

  • (0,0) correspond au coin en bas à gauche de l'image
  • (0,1) correspond au coin en bas à droite de l'image
  • (1,0) correspond au coin en haut à gauche de l'image
  • (1,1) correspond au coin en haut à droite de l'image

Et bien, il faut rajouter à chaque vertex une position de texture, avec la fonction :

1
void glTexCoord2d(GLdouble s, GLdouble t);

Vous pouvez aussi utiliser les homologues de cette fonction :

1
2
3
void glTexCoord2f(GLfloat s, GLfloat t);   //si vous utilisez des float
void glTexCoord2i(GLint s, GLint t);             //si vous utilisez des int
void glTexCoord2s(GLshort s, GLshort t);        //si vous utilisez des short

Comment on les utilise ?

Il faut appeler cette fonctions juste avant de définir un vertex, comme ceci :

1
2
3
4
5
6
7
glBindTexture(GL_TEXTURE_2D, idDeTexture);
glBegin(GL_QUADS);		
	glTexCoord2d(1,1);  glVertex3d(10.0, 10.0, 0.0);
	glTexCoord2d(1,0);  glVertex3d(10.0, -10.0, 0.0);
	glTexCoord2d(0,0);  glVertex3d(-10.0, -10.0, 0.0);
	glTexCoord2d(0,1);  glVertex3d(-10.0, 10.0, 0.0);
glEnd();

En fait ça fonctionne comme quand vous voulez mettre une couleur sur un vertex, il faut définir la couleur avant, et bien là c'est pareil.

Faisons un exemple.

Voici l'image que l'on va plaquer sur le carré de notre scène ici.

Il faut, comme pour la Terre, ajouter un attribut privé à la classe AppTest dans apptest.h :

1
GLuint p_textureSol;

Voici a quoi ressemble la classe apptest.h :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef APPTEST_H
#define APPTEST_H

#include "sdlopengl_app.h"

class AppTest : public SDLOpenGl_app {
	public:
		AppTest(double width = 640, double height = 480, double near = 1, double far = 1000, double angle = 70, const std::string & titre = "SDL_Application", const std::string & icon = "");
		//destructeur
		virtual ~AppTest();
		
	protected:
		virtual void draw();
		virtual void update(float dt);
		
	private:
		void init();
		GLUquadric* p_params;
		GLuint p_textureTerre; 
		GLuint p_textureSol;
};

#endif

Du côté du fichier apptest.cpp, il faut rajouter le nom du fichier pour récupérer la texture, que je vous conseil de mettre dans le dossier image de votre projet avec le fichier carte-terre.jpg :

Voilà à quoi ressemble le début du fichier apptest.cpp :

1
2
3
4
5
6
7
#include "apptest.h"

const std::string TERRE = "../image/carte-terre.jpg";
const std::string SOL = "../image/metal091.jpg";

const double VITESSE_CAMERA(2.0);
const double VITESSE_ROTATION_CAMERA(0.1);

Ensuite on initialise la texture dans la fonction init :

1
p_textureSol = loadTexture(SOL.c_str());

Cette fonction ressemble donc à ceci :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void AppTest::init(){
	this->addKeyEvent("forward", SDLK_z, false);
	this->addKeyEvent("backward", SDLK_s, false);
	this->addKeyEvent("right", SDLK_d, false);
	this->addKeyEvent("left", SDLK_q, false);
	this->addKeyEvent("turnUp", SDLK_UP, false);
	this->addKeyEvent("turnDown", SDLK_DOWN, false);
	this->addKeyEvent("turnRight", SDLK_RIGHT, false);
	this->addKeyEvent("turnLeft", SDLK_LEFT, false);
	glEnable(GL_TEXTURE_2D);
	p_textureTerre = loadTexture(TERRE.c_str());
	p_textureSol = loadTexture(SOL.c_str());
	p_params = gluNewQuadric();
}

Et maintenant nous n'oublions pas de changer la place du glEnable(GL_TEXTURE_2D); pour que l'on puisse plaquer la texture sur le carré et on rajoute ce qu'il faut pour pouvoir plaquer cette texture :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void AppTest::draw(){
	glEnable(GL_TEXTURE_2D);
	
	glBindTexture(GL_TEXTURE_2D, p_textureSol);
	glBegin(GL_QUADS);
		glColor3ub(255, 0, 0);
		
		glTexCoord2d(1,1); glVertex3d(10.0, 10.0, 0.0);
		glTexCoord2d(1,0); glVertex3d(10.0, -10.0, 0.0);
		glTexCoord2d(0,0); glVertex3d(-10.0, -10.0, 0.0);
		glTexCoord2d(0,1);glVertex3d(-10.0, 10.0, 0.0);
	glEnd();
	
	glTranslated(0.0, 0.0, 2.0);
	
	glBindTexture(GL_TEXTURE_2D, p_textureTerre);
	gluQuadricDrawStyle(p_params, GLU_FILL);
	gluQuadricTexture(p_params, GL_TRUE);
	
	glColor3ub(255, 255, 255);
	gluSphere(p_params, 1.0, 20, 20);
	
	glDisable(GL_TEXTURE_2D);
	
	
	glTranslated(5.0, 5.0, 5.0);
	glColor3ub(0, 0, 255);
	gluSphere(p_params, 1.0, 20, 20);
}

Si vous compilez et que vous exécuter le programme vous obtiendrez ceci :

plop

Et vous pouvez bouger la caméra pour avoir un autre angle de vue :

plop

Comme si ça allait aider.

Oui bon d'accord.

Comment on fait pour que ça ne soit pas moche ?

Alors, si vous voulez afficher une texture sans que sa couleur change il faut l'afficher avec une couleur blanche, comme la Terre.

Donc, il faut afficher le carré en blanc et plaquer la texture dessus pour qu'elle ne soit pas changée.

Ce qui nous donne cette fonction draw :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void AppTest::draw(){
	glEnable(GL_TEXTURE_2D);
	
	glBindTexture(GL_TEXTURE_2D, p_textureSol);
	glBegin(GL_QUADS);
		glColor3ub(255, 255, 255);
		glTexCoord2d(1,1); glVertex3d(10.0, 10.0, 0.0);
		glTexCoord2d(1,0); glVertex3d(10.0, -10.0, 0.0);
		glTexCoord2d(0,0); glVertex3d(-10.0, -10.0, 0.0);
		glTexCoord2d(0,1);glVertex3d(-10.0, 10.0, 0.0);
	glEnd();
	
	glTranslated(0.0, 0.0, 2.0);
	
	glBindTexture(GL_TEXTURE_2D, p_textureTerre);
	gluQuadricDrawStyle(p_params, GLU_FILL);
	gluQuadricTexture(p_params, GL_TRUE);
	
	glColor3ub(255, 255, 255);
	gluSphere(p_params, 1.0, 20, 20);
	
	glDisable(GL_TEXTURE_2D);
	
	
	glTranslated(5.0, 5.0, 5.0);
	glColor3ub(0, 0, 255);
	gluSphere(p_params, 1.0, 20, 20);
}

Et voilà le travail :

plop

Et regardons avec un autre angle de vue :

plop

C'est très joli, mais elle n'est pas un peut grande la texture ?

Ah, ça se passe juste après.