gKit2 light
tuto_decal.cpp
Go to the documentation of this file.
1 
3 
4 
5 #include "wavefront.h"
6 #include "texture.h"
7 #include "program.h"
8 #include "uniforms.h"
9 
10 #include "orbiter.h"
11 #include "draw.h"
12 #include "app_camera.h" // classe Application a deriver
13 
14 
15 // utilitaire. creation d'une grille / repere.
16 // n= 0 ne dessine que les axes du repere.
17 Mesh make_grid( const int n= 10 )
18 {
19  glLineWidth(2);
20  Mesh grid= Mesh(GL_LINES);
21 
22  // grille
23  grid.color(White());
24  for(int x= 0; x < n; x++)
25  {
26  float px= float(x) - float(n)/2 + .5f;
27  grid.vertex(px, 0, - float(n)/2 + .5f);
28  grid.vertex(px, 0, float(n)/2 - .5f);
29  }
30 
31  for(int z= 0; z < n; z++)
32  {
33  float pz= float(z) - float(n)/2 + .5f;
34  grid.vertex(- float(n)/2 + .5f, 0, pz);
35  grid.vertex(float(n)/2 - .5f, 0, pz);
36  }
37 
38  // axes XYZ
39  grid.color(Red());
40  grid.vertex(0, .1, 0);
41  grid.vertex(1, .1, 0);
42 
43  grid.color(Green());
44  grid.vertex(0, .1, 0);
45  grid.vertex(0, 1, 0);
46 
47  grid.color(Blue());
48  grid.vertex(0, .1, 0);
49  grid.vertex(0, .1, 1);
50 
51  return grid;
52 }
53 
54 // utilitaire. creation d'un plan / sol
55 Mesh make_ground( const int n= 10 )
56 {
57  Mesh grid= Mesh(GL_TRIANGLES);
58 
59  grid.normal(0, 1, 0);
60  int a= grid.vertex(-n/2, -1, n/2);
61  int b= grid.vertex( n/2, -1, n/2);
62  int c= grid.vertex( n/2, -1, -n/2);
63  int d= grid.vertex(-n/2, -1, -n/2);
64  grid.triangle(a, b, c);
65  grid.triangle(a, c, d);
66 
67  return grid;
68 }
69 
70 Mesh make_xyz( )
71 {
72  glLineWidth(2);
73  Mesh camera= Mesh(GL_LINES);
74 
75  // axes XYZ
76  camera.color(Red());
77  camera.vertex(Point(0, 0, 0));
78  camera.vertex(Point(1, 0, 0));
79 
80  camera.color(Green());
81  camera.vertex(Point(0, 0, 0));
82  camera.vertex(Point(0, 1, 0));
83 
84  camera.color(Blue());
85  camera.vertex(Point(0, 0, 0));
86  camera.vertex(Point(0, 0, 1));
87 
88  return camera;
89 }
90 
91 Mesh make_frustum( )
92 {
93  glLineWidth(2);
94  Mesh camera= Mesh(GL_LINES);
95 
96  camera.color(Yellow());
97  // face avant
98  camera.vertex(-1, -1, -1);
99  camera.vertex(-1, 1, -1);
100  camera.vertex(-1, 1, -1);
101  camera.vertex(1, 1, -1);
102  camera.vertex(1, 1, -1);
103  camera.vertex(1, -1, -1);
104  camera.vertex(1, -1, -1);
105  camera.vertex(-1, -1, -1);
106 
107  // face arriere
108  camera.vertex(-1, -1, 1);
109  camera.vertex(-1, 1, 1);
110  camera.vertex(-1, 1, 1);
111  camera.vertex(1, 1, 1);
112  camera.vertex(1, 1, 1);
113  camera.vertex(1, -1, 1);
114  camera.vertex(1, -1, 1);
115  camera.vertex(-1, -1, 1);
116 
117  // aretes
118  camera.vertex(-1, -1, -1);
119  camera.vertex(-1, -1, 1);
120  camera.vertex(-1, 1, -1);
121  camera.vertex(-1, 1, 1);
122  camera.vertex(1, 1, -1);
123  camera.vertex(1, 1, 1);
124  camera.vertex(1, -1, -1);
125  camera.vertex(1, -1, 1);
126 
127  return camera;
128 }
129 
130 Mesh make_camera( )
131 {
132  Mesh camera= Mesh(GL_LINES);
133 
134  camera.color(Yellow());
135  camera.vertex(0,0,0);
136  camera.vertex(-0.5, -0.5, -1);
137  camera.vertex(0,0,0);
138  camera.vertex(-0.5, 0.5, -1);
139  camera.vertex(0,0,0);
140  camera.vertex(0.5, 0.5, -1);
141  camera.vertex(0,0,0);
142  camera.vertex(0.5, -0.5, -1);
143 
144  camera.vertex(-0.5, -0.5, -1);
145  camera.vertex(-0.5, 0.5, -1);
146 
147  camera.vertex(-0.5, 0.5, -1);
148  camera.vertex(0.5, 0.5, -1);
149 
150  camera.vertex(0.5, 0.5, -1);
151  camera.vertex(0.5, -0.5, -1);
152 
153  camera.vertex(0.5, -0.5, -1);
154  camera.vertex(-0.5, -0.5, -1);
155 
156  // axes XYZ
157  camera.color(Red());
158  camera.vertex(Point(0, 0, 0));
159  camera.vertex(Point(1, 0, 0));
160 
161  camera.color(Green());
162  camera.vertex(Point(0, 0, 0));
163  camera.vertex(Point(0, 1, 0));
164 
165  camera.color(Blue());
166  camera.vertex(Point(0, 0, 0));
167  camera.vertex(Point(0, 0, 1));
168 
169  glLineWidth(2);
170 
171  return camera;
172 }
173 
174 
175 class TP : public AppCamera
176 {
177 public:
178  // constructeur : donner les dimensions de l'image, et eventuellement la version d'openGL.
179  TP( ) : AppCamera(1024, 640) {}
180 
181  // creation des objets de l'application
182  int init( )
183  {
184  // decrire un repere / grille
185  m_repere= make_grid(20);
186  m_local= make_grid(2);
187  m_ground= make_ground(20);
188  //~ m_ground= read_mesh("ground.obj"); // pas dans le depot...
189  m_proxy= make_xyz();
190  //~ m_proxy= make_camera();
191  m_frustum= make_frustum();
192 
193  // charge l'element
194  m_objet= read_mesh("data/robot.obj");
195 
196  m_texture= read_texture(0, "data/grid.png");
197  //~ m_texture= read_texture(0, "orange_splash.png"); // pas dans le depot
198  //~ m_texture= read_texture(0, "decal_shadow.png"); // pas dans le depot
199 
200  // gestion des bordures :
201  // solution 1 : utiliser les parametres openGL pour renvoyer du blanc en dehors de la texture,
202  // soit c'est le shader qui fait le boulot...
203  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
204  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
205  float border[]= { 1, 1, 1, 1 };
206  glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);
207 
208  m_program= read_program("tutos/decal.glsl");
209  program_print_errors(m_program);
210 
211  // position initiale de l'objet
212  m_position= Identity();
213 
214  // si l'objet est "gros", il faut regler la camera pour l'observer entierement :
215  // recuperer les points extremes de l'objet (son englobant)
216  Point pmin, pmax;
217  m_ground.bounds(pmin, pmax);
218  // parametrer la camera de l'application, renvoyee par la fonction camera()
219  camera().lookat(pmin, pmax);
220 
221  // etat openGL par defaut
222  glClearColor(0.2f, 0.2f, 0.2f, 1.f); // couleur par defaut de la fenetre
223 
224  glClearDepth(1.f); // profondeur par defaut
225  glDepthFunc(GL_LESS); // ztest, conserver l'intersection la plus proche de la camera
226  glEnable(GL_DEPTH_TEST); // activer le ztest
227 
228  return 0; // ras, pas d'erreur
229  }
230 
231  // destruction des objets de l'application
232  int quit( )
233  {
234  m_objet.release();
235  m_repere.release();
236  m_local.release();
237  m_ground.release();
238  m_proxy.release();
239 
240  release_program(m_program);
241  glDeleteTextures(1, &m_texture);
242  return 0;
243  }
244 
245  // dessiner une nouvelle image
246  int render( )
247  {
248  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
249 
250  // modifie la position de l'objet en fonction des fleches de direction
251  if(key_state(SDLK_UP))
252  m_position= m_position * Translation(0, 0, 0.15); // en avant
253  if(key_state(SDLK_DOWN))
254  m_position= m_position * Translation(0, 0, -0.15); // en arriere
255  if(key_state(SDLK_PAGEUP))
256  m_position= m_position * Translation(0, 0.15, 0); // en haut
257  if(key_state(SDLK_PAGEDOWN))
258  m_position= m_position * Translation(0, -0.15, 0); // en bas
259 
260  if(key_state(SDLK_LEFT))
261  m_position= m_position * RotationY(2); // tourne vers la droite
262  if(key_state(SDLK_RIGHT))
263  m_position= m_position * RotationY(-2); // tourne vers la gauche
264 
265 
266  // dessine le meme objet a un autre endroit. il faut modifier la matrice model, qui sert a ca : placer un objet dans le monde, ailleurs qu'a l'origine.
267  // par exemple, a la verticale au dessus du premier cube :
268  // la transformation est une translation le long du vecteur Y= (0, 1, 0), si on veut placer le cube plus haut, il suffit d'utiliser une valeur > 1
269 
270  Transform r= RotationX(-90);
271  Transform t= Translation(0,0, 8);
272  Transform m= r * t;
273 
274  Transform decal_view= Inverse(m_position * m);
275  //~ Transform decal_projection= Perspective(35, 1, float(0.1), float(10));
276  Transform decal_projection= Ortho(-2, 2, -2, 2, float(0.1), float(10));
277 
278  // transformations de la camera de l'application
279  Transform view= camera().view();
280  Transform projection= camera().projection();
281 
282  if(key_state('d'))
283  {
284  // change de point de vue
285  view= decal_view;
286  projection= decal_projection;
287  }
288 
289  draw(m_objet, /* model */ m_position, view, projection);
290  // dessine aussi le repere local
291  draw(m_local, /* model */ m_position, view, projection);
292 
293  // dessine le 2ieme objet par rapport au premier objet...
294  // compose leurs 2 transformations, les coordonnees du 2ieme objet sont connues dans le repere local du premier objet
295 
296  // dessine le repere utilise pour placer le decal...
297  draw(m_proxy, /* model */ m_position * m, view, projection);
298 
299  // dessine aussi le frustum
300  if(key_state('f'))
301  {
302  // passage repere projection vers global : inverse de projection*view
303  Transform decal_m= Inverse(decal_projection * decal_view);
304 
305  draw(m_frustum, decal_m, view, projection);
306  }
307 
308 
309  if(key_state(' '))
310  {
311  // dessine le repere global, pour le meme point de vue
312  draw(m_ground, Identity(), view, projection);
313  // affichage standard, sans texture projective...
314  }
315  else
316  {
317  // affichage du sol avec le decal / texture projective
318  glUseProgram(m_program);
319 
320  // transformations standards
321  Transform model;
322  Transform mv= view * model;
323  Transform mvp= projection * mv;
324 
325  program_uniform(m_program, "mvpMatrix", mvp);
326  program_uniform(m_program, "mvMatrix", mv);
327 
328  // transformations pour le decal
329  // transformation supplementaire pour lire la texture :
330  // passage repere projectif vers repere [0 1]x[0 1]
331  Transform decal_viewport= Viewport(1, 1);
332  Transform decal= decal_viewport * decal_projection * decal_view;
333 
334  program_uniform(m_program, "decalMatrix", decal);
335  program_use_texture(m_program, "texture", 0, m_texture);
336 
337  m_ground.draw(m_program, /* use position */ true, /* use texcoord */ false, /* use normal */ true, /* use color */ false, /* use material index*/ false);
338  }
339 
340 
341  // screenshot
342  if(key_state('s'))
343  {
344  clear_key_state('s');
345  static int id= 1;
346  screenshot("camera", id++);
347  }
348 
349  // continuer...
350  return 1;
351  }
352 
353 protected:
354  Mesh m_objet;
355  Mesh m_repere;
356  Mesh m_local;
357  Mesh m_proxy;
358  Mesh m_frustum;
359  Mesh m_ground;
360  Transform m_position;
361  GLuint m_texture;
362  GLuint m_program;
363 };
364 
365 
366 int main( int argc, char **argv )
367 {
368  // il ne reste plus qu'a creer un objet application et la lancer
369  TP tp;
370  tp.run();
371 
372  return 0;
373 }
classe application.
Definition: app_camera.h:19
const Orbiter & camera() const
renvoie l'orbiter gere par l'application.
Definition: app_camera.h:37
int run()
execution de l'application.
Definition: app.cpp:36
representation d'un objet / maillage.
Definition: mesh.h:112
unsigned int vertex(const vec3 &p)
insere un sommet de position p, et ses attributs (s'ils sont definis par color(), texcoord(),...
Definition: mesh.cpp:111
void bounds(Point &pmin, Point &pmax) const
renvoie min et max les coordonnees des extremites des positions des sommets de l'objet (boite engloba...
Definition: mesh.cpp:503
void draw(const GLuint program, const bool use_position, const bool use_texcoord, const bool use_normal, const bool use_color, const bool use_material_index)
dessine l'objet avec un shader program.
Definition: mesh.cpp:770
Mesh & triangle(const unsigned int a, const unsigned int b, const unsigned int c)
Definition: mesh.cpp:192
Mesh & normal(const vec3 &n)
definit la normale du prochain sommet.
Definition: mesh.cpp:90
void release()
detruit les objets openGL.
Definition: mesh.cpp:64
Mesh & color(const vec4 &c)
definit la couleur du prochain sommet.
Definition: mesh.cpp:80
void lookat(const Point &center, const float size)
observe le point center a une distance size.
Definition: orbiter.cpp:7
Transform projection(const int width, const int height, const float fov)
fixe la projection reglee pour une image d'aspect width / height, et une demi ouverture de fov degres...
Definition: orbiter.cpp:47
Transform view() const
renvoie la transformation vue.
Definition: orbiter.cpp:40
Definition: alpha.cpp:59
int render()
a deriver pour afficher les objets. renvoie 1 pour continuer, 0 pour fermer l'application.
Definition: tuto_decal.cpp:246
int quit()
a deriver pour detruire les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
Definition: tuto_decal.cpp:232
int init()
a deriver pour creer les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
Definition: tuto_decal.cpp:182
void clear_key_state(const SDL_Keycode key)
desactive une touche du clavier.
Definition: window.cpp:48
int key_state(const SDL_Keycode key)
renvoie l'etat d'une touche du clavier. cf la doc SDL2 pour les codes.
Definition: window.cpp:42
Color Red()
utilitaire. renvoie une couleur rouge.
Definition: color.cpp:57
Color Yellow()
utilitaire. renvoie une couleur jaune.
Definition: color.cpp:72
Color Blue()
utilitaire. renvoie une couleur bleue.
Definition: color.cpp:67
Color Green()
utilitaire. renvoie une couleur verte.
Definition: color.cpp:62
Color White()
utilitaire. renvoie une couleur blanche.
Definition: color.cpp:52
Transform Inverse(const Transform &m)
renvoie l'inverse de la matrice.
Definition: mat.cpp:197
Transform Viewport(const float width, const float height)
renvoie la matrice representant une transformation viewport.
Definition: mat.cpp:357
Transform Identity()
construit la transformation identite.
Definition: mat.cpp:187
Transform RotationX(const float a)
renvoie la matrice representation une rotation de angle degree autour de l'axe X.
Definition: mat.cpp:230
Transform RotationY(const float a)
renvoie la matrice representation une rotation de a degree autour de l'axe Y.
Definition: mat.cpp:242
Transform Ortho(const float left, const float right, const float bottom, const float top, const float znear, const float zfar)
renvoie la matrice representant une transformation orthographique, passage d'un cube []x[]x[] vers [-...
Definition: mat.cpp:343
Transform Translation(const Vector &v)
renvoie la matrice representant une translation par un vecteur.
Definition: mat.cpp:216
Mesh read_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes....
Definition: wavefront.cpp:14
int screenshot(const char *filename)
enregistre le contenu de la fenetre dans un fichier. doit etre de type .png / .bmp
Definition: texture.cpp:188
GLuint read_program(const char *filename, const char *definitions)
Definition: program.cpp:204
void program_uniform(const GLuint program, const char *uniform, const std::vector< unsigned > &v)
affecte un tableau de valeurs a un uniform du shader program.
Definition: uniforms.cpp:94
int program_print_errors(const GLuint program)
affiche les erreurs de compilation.
Definition: program.cpp:432
int release_program(const GLuint program)
detruit les shaders et le program.
Definition: program.cpp:211
void program_use_texture(const GLuint program, const char *uniform, const int unit, const GLuint texture, const GLuint sampler)
configure le pipeline et le shader program pour utiliser une texture, et des parametres de filtrage,...
Definition: uniforms.cpp:198
GLuint read_texture(const int unit, const char *filename, const GLenum texel_type)
Definition: texture.cpp:148
representation d'un point 3d.
Definition: vec.h:21
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition: mat.h:21