gKit2 light
mesh_viewer.cpp
Go to the documentation of this file.
1 
3 #include <algorithm>
4 
5 #include "mat.h"
6 #include "mesh_data.h"
7 #include "mesh_buffer.h"
8 #include "material_data.h"
9 
10 #include "orbiter.h"
11 #include "program.h"
12 #include "uniforms.h"
13 
14 #include "app.h"
15 #include "widgets.h"
16 
17 
18 class MeshViewer: public App
19 {
20 public:
21  // constructeur : donner les dimensions de l'image, et eventuellement la version d'openGL.
22  MeshViewer( const char *file ) : App(1024, 640), m_filename(file) {}
23 
24  int init( )
25  {
26  // lit les donnees
27  MeshData data= read_mesh_data(m_filename);
28  if(data.positions.size() == 0)
29  return -1;
30 
31  // calcule l'englobant
32  Point pmin, pmax;
33  bounds(data, pmin, pmax);
34  m_camera.lookat(pmin, pmax);
35 
36  // recalcule les normales des sommets, si necessaire
37  if(data.normals.size() == 0)
38  normals(data);
39 
40  // construit les buffers
41  m_mesh= buffers(data);
42 
43  // conserve le nombre de sommets et d'indices
44  m_vertex_count= m_mesh.positions.size();
45  m_texcoord_count= m_mesh.texcoords.size();
46  m_normal_count= m_mesh.normals.size();
47  m_index_count= m_mesh.indices.size();
48 
49  // construit les buffers openGL
50  size_t size= m_mesh.vertex_buffer_size() + m_mesh.texcoord_buffer_size() + m_mesh.normal_buffer_size();
51  glGenBuffers(1, &m_vertex_buffer);
52  glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
53  glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
54 
55  glGenVertexArrays(1, &m_vao);
56  glBindVertexArray(m_vao);
57 
58  // transfere les positions des sommets
59  size_t offset= 0;
60  size= m_mesh.vertex_buffer_size();
61  glBufferSubData(GL_ARRAY_BUFFER, offset, size, m_mesh.vertex_buffer());
62  // et configure l'attribut 0, vec3 position
63  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, /* stride */ 0, (const GLvoid *) offset);
64  glEnableVertexAttribArray(0);
65 
66  // transfere les texcoords des sommets
67  if(m_mesh.texcoord_buffer_size())
68  {
69  offset= offset + size;
70  size= m_mesh.texcoord_buffer_size();
71  glBufferSubData(GL_ARRAY_BUFFER, offset, size, m_mesh.texcoord_buffer());
72  // et configure l'attribut 1, vec2 texcoord
73  glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, /* stride */ 0, (const GLvoid *) offset);
74  glEnableVertexAttribArray(1);
75  }
76 
77  // transfere les normales des sommets
78  offset= offset + size;
79  size= m_mesh.normal_buffer_size();
80  glBufferSubData(GL_ARRAY_BUFFER, offset, size, m_mesh.normal_buffer());
81  // et configure l'attribut 2, vec3 normal
82  glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, /* stride */ 0, (const GLvoid *) offset);
83  glEnableVertexAttribArray(2);
84 
85  // index buffer
86  glGenBuffers(1, &m_index_buffer);
87  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer);
88  glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_mesh.index_buffer_size(), m_mesh.index_buffer(), GL_STATIC_DRAW);
89 
90  // nettoyage
91  glBindVertexArray(0);
92  glBindBuffer(GL_ARRAY_BUFFER, 0);
93  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
94 
95  // charge les textures des matieres
96  if(m_mesh.texcoord_buffer_size())
97  {
98  read_textures(m_mesh.materials);
99 
100  // configure le filtrage des textures de l'unite 0
101  //~ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f);
102 
103  // configure le filtrage des textures, mode repeat
104  glGenSamplers(1, &m_sampler);
105  glSamplerParameteri(m_sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
106  glSamplerParameteri(m_sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
107  glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_S, GL_REPEAT);
108  glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_T, GL_REPEAT);
109  }
110 
111  // creer le shader program
112  m_program= read_program( smart_path("tutos/mesh_viewer.glsl") );
113  program_print_errors(m_program);
114 
115  // initialise les widgets
116  m_widgets= create_widgets();
117 
118  // etat openGL par defaut
119  glClearColor(0.2f, 0.2f, 0.2f, 1.f); // couleur par defaut de la fenetre
120 
121  glClearDepth(1.f); // profondeur par defaut
122  glDepthFunc(GL_LESS); // ztest, conserver l'intersection la plus proche de la camera
123  glEnable(GL_DEPTH_TEST); // activer le ztest
124 
125  return 0; // ras, pas d'erreur
126  }
127 
128  // destruction des objets de l'application
129  int quit( )
130  {
131  release_textures(m_mesh.materials);
132  glDeleteBuffers(1, &m_vertex_buffer);
133  glDeleteBuffers(1, &m_index_buffer);
134  glDeleteVertexArrays(1, &m_vao);
135  release_program(m_program);
136 
137  release_widgets(m_widgets);
138 
139  return 0;
140  }
141 
142  // dessiner une nouvelle image
143  int render( )
144  {
145  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
146 
147  static bool wireframe= false;
148  if(key_state('w'))
149  {
150  clear_key_state('w');
151  wireframe= !wireframe;
152  }
153 
154  if(!wireframe)
155  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
156  else
157  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
158 
159  // deplace la camera
160  int mx, my;
161  unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
162  if(mb & SDL_BUTTON(1)) // le bouton gauche est enfonce
163  m_camera.rotation(mx, my);
164  else if(mb & SDL_BUTTON(2)) // le bouton milieu est enfonce
165  m_camera.translation((float) mx / (float) window_width(), (float) my / (float) window_height());
166  //~ m_camera.move(mx);
167  else if(mb & SDL_BUTTON(3)) // le bouton droit est enfonce
168  m_camera.translation((float) mx / (float) window_width(), (float) my / (float) window_height());
169 
170  SDL_MouseWheelEvent wheel= wheel_event();
171  if(wheel.y != 0)
172  {
174  m_camera.move(16.f * wheel.y);
175  }
176 
177 
178  // etape 2 : dessiner m_objet avec le shader program
179  // configurer le pipeline
180  glUseProgram(m_program);
181 
182  // configurer le shader program
183  // . recuperer les transformations
184  Transform model; //= RotationX(global_time() / 20);
185  Transform view= m_camera.view();
186  Transform projection= m_camera.projection(window_width(), window_height(), 45);
187 
188  // . composer les transformations : model, view et projection
189  Transform mv= view * model;
190  Transform mvp= projection * mv;
191 
192  // . parametrer le shader program :
193  // . transformation : la matrice declaree dans le vertex shader s'appelle mvpMatrix
194  program_uniform(m_program, "mvpMatrix", mvp);
195  program_uniform(m_program, "mvMatrix", mv);
196 
197  // . parametres "supplementaires" :
198  // . couleur des pixels, cf la declaration 'uniform vec4 color;' dans le fragment shader
199  program_uniform(m_program, "diffuse_color", vec4(1, 1, 1, 1));
200 
201  static bool flat= false;
202  if(key_state('f'))
203  {
204  clear_key_state('f');
205  flat= !flat;
206  }
207 
208  static int show= 0;
209  static int show_lights= 0;
210  static int show_material= 0;
211 
212  if(key_state(SDLK_RIGHT) || key_state(SDLK_UP))
213  {
214  clear_key_state(SDLK_RIGHT);
215  clear_key_state(SDLK_UP);
216  show_material= (show_material +1) % m_mesh.material_groups.size();
217  }
218  if(key_state(SDLK_LEFT) || key_state(SDLK_DOWN))
219  {
220  clear_key_state(SDLK_LEFT);
221  clear_key_state(SDLK_DOWN);
222  show_material= (show_material +m_mesh.material_groups.size() -1) % m_mesh.material_groups.size();
223  }
224 
225  // go !
226  glBindVertexArray(m_vao);
227  for(int i= 0; i < (int) m_mesh.material_groups.size(); i++)
228  {
229  int material_id= m_mesh.material_groups[i].material;
230  const MaterialData& material= m_mesh.materials[material_id];
231 
232  program_uniform(m_program, "flat_shading", float(flat));
233 
234  if(show)
235  program_uniform(m_program, "diffuse_color", Color((material_id % 100) / 99.f, 1 - (material_id % 10) / 9.f, (material_id % 4) / 3.f));
236  else
237  program_uniform(m_program, "diffuse_color", material.diffuse);
238 
239  if(show && material_id == show_material)
240  program_uniform(m_program, "diffuse_color", Color(1, 0, 0));
241 
242  if(show_lights && material.emission.power() > 0)
243  program_uniform(m_program, "diffuse_color", Color(.8f, .4f, 0));
244 
245  program_use_texture(m_program, "diffuse_texture", 0, material.diffuse_texture, m_sampler);
246 
247  glDrawElements(GL_TRIANGLES, m_mesh.material_groups[i].count,
248  GL_UNSIGNED_INT, m_mesh.index_buffer_offset(m_mesh.material_groups[i].first));
249  }
250 
251  // affiche les infos
252  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
253 
254  begin(m_widgets);
255  label(m_widgets, "mesh '%s', %d vertices %s %s", m_filename, m_vertex_count,
256  m_texcoord_count ? "texcoords" : "", m_normal_count ? "normals" : "");
257 
258  begin_line(m_widgets);
259  label(m_widgets, "%d materials", int(m_mesh.materials.size()));
260 
261  begin_line(m_widgets);
262  button(m_widgets, "show materials", show);
263  button(m_widgets, "show lights", show_lights);
264 
265  if(show)
266  {
267  const MaterialData& material= m_mesh.materials[show_material];
268 
269  begin_line(m_widgets);
270  label(m_widgets, "material%02d", show_material);
271  if(material.specular.power() == 0)
272  label(m_widgets, "diffuse material");
273  else if(material.ns > 1)
274  label(m_widgets, "glossy material");
275  else
276  label(m_widgets, "undef material ??");
277 
278  begin_line(m_widgets);
279  label(m_widgets, " Kd %.2f %.2f %.2f", material.diffuse.r, material.diffuse.g, material.diffuse.b);
280  begin_line(m_widgets);
281  label(m_widgets, " Ks %.2f %.2f %.2f", material.specular.r, material.specular.g, material.specular.b);
282  begin_line(m_widgets);
283  label(m_widgets, " Ns %.2f", material.ns);
284 
285  begin_line(m_widgets);
286  label(m_widgets, " Kd texture %s", material.diffuse_filename.c_str());
287  begin_line(m_widgets);
288  label(m_widgets, " Ns texture %s", material.ns_filename.c_str());
289 
290  }
291 
292  end(m_widgets);
293  draw(m_widgets, window_width(), window_height());
294 
295  return 1;
296  }
297 
298 protected:
299  MeshBuffer m_mesh;
300  GLuint m_vao;
301  GLuint m_vertex_buffer;
302  GLuint m_index_buffer;
303  int m_vertex_count;
304  int m_texcoord_count;
305  int m_normal_count;
306  int m_index_count;
307 
308  Transform m_model;
309  Orbiter m_camera;
310  GLuint m_texture;
311  GLuint m_sampler;
312  GLuint m_program;
313 
314  Widgets m_widgets;
315 
316  const char *m_filename;
317 };
318 
319 
320 int main( int argc, char **argv )
321 {
322  const char *filename= "data/bigguy.obj";
323  if(argc > 1)
324  filename= argv[1];
325 
326  MeshViewer tp(filename);
327  tp.run();
328 
329  return 0;
330 }
classe application.
Definition: app.h:20
App(const int width, const int height, const int major=3, const int minor=3, const int samples=0)
constructeur, dimensions de la fenetre et version d'openGL.
Definition: app.cpp:11
int quit()
a deriver pour detruire les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
int init()
a deriver pour creer les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
Definition: mesh_viewer.cpp:24
int render()
a deriver pour afficher les objets. renvoie 1 pour continuer, 0 pour fermer l'application.
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet.
Definition: orbiter.h:17
void lookat(const Point &center, const float size)
observe le point center a une distance size.
Definition: orbiter.cpp:7
void move(const float z)
rapproche / eloigne la camera du centre.
Definition: orbiter.cpp:33
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
void translation(const float x, const float y)
deplace le centre / le point observe.
Definition: orbiter.cpp:27
void rotation(const float x, const float y)
change le point de vue / la direction d'observation.
Definition: orbiter.cpp:21
Transform view() const
renvoie la transformation vue.
Definition: orbiter.cpp:40
void begin(Widgets &w)
debut de la description des elements de l'interface graphique.
Definition: widgets.cpp:29
Widgets create_widgets()
cree une interface graphique. a detruire avec release_widgets( ).
Definition: widgets.cpp:12
void release_widgets(Widgets &w)
detruit l'interface graphique.
Definition: widgets.cpp:23
bool button(Widgets &w, const char *text, int &status)
Definition: widgets.cpp:155
void label(Widgets &w, const char *format,...)
cree un texte. meme fonctionnement que printf().
Definition: widgets.cpp:142
int window_height()
renvoie la hauteur de la fenetre de l'application.
Definition: window.cpp:29
void clear_key_state(const SDL_Keycode key)
desactive une touche du clavier.
Definition: window.cpp:48
void clear_wheel_event()
desactive l'evenement.
Definition: window.cpp:116
void end(Widgets &w)
termine la description des elements de l'interface graphique.
Definition: widgets.cpp:404
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
void begin_line(Widgets &w)
place les prochains elements sur une nouvelle ligne.
Definition: widgets.cpp:129
SDL_MouseWheelEvent wheel_event()
renvoie le dernier evenement. etat de la molette de la souris / glisser sur le pad.
Definition: window.cpp:112
int window_width()
renvoie la largeur de la fenetre de l'application.
Definition: window.cpp:25
const char * smart_path(const char *filename)
renvoie le chemin(path) vers le fichier 'filename' apres l'avoir cherche dans un repertoire standard....
Definition: window.cpp:431
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
void release_textures(std::vector< MaterialData > &materials)
detruit les textures.
int read_textures(std::vector< MaterialData > &materials, const size_t max_size)
charge les textures associees a un ensemble de matieres, sans depasser une limite de taille,...
charge les textures utiilisees par un ensemble de matieres.
MeshBuffer buffers(const MeshData &data)
construction a partir des donnees d'un maillage.
Definition: mesh_buffer.cpp:48
representation d'un objet openGL.
void normals(MeshData &data)
(re-) calcule les normales des sommets. utiliser avant les reindexations, cf indices() et vertices().
Definition: mesh_data.cpp:307
MeshData read_mesh_data(const char *filename)
charge un fichier wavefront .obj et renvoie les donnees.
Definition: mesh_data.cpp:16
void bounds(const MeshData &data, Point &pmin, Point &pmax)
renvoie l'englobant.
Definition: mesh_data.cpp:290
representation des donnees d'un fichier wavefront .obj
representation d'une couleur (rgba) transparente ou opaque.
Definition: color.h:14
representation d'une matiere texturee.
Definition: mesh_data.h:16
Color specular
couleur du reflet
Definition: mesh_data.h:23
Color emission
pour une source de lumiere
Definition: mesh_data.h:25
GLuint diffuse_texture
texture diffuse
Definition: mesh_data.h:21
std::string diffuse_filename
nom de la texture diffuse
Definition: mesh_data.h:20
float ns
exposant pour les reflets blinn-phong
Definition: mesh_data.h:26
Color diffuse
couleur diffuse
Definition: mesh_data.h:17
std::string ns_filename
nom de la texture exposant
Definition: mesh_data.h:28
representation d'un objet.
Definition: mesh_buffer.h:22
std::vector< vec3 > positions
attribut position
Definition: mesh_buffer.h:23
std::vector< MeshGroup > material_groups
sequence de triangles groupes par matiere
Definition: mesh_buffer.h:31
std::vector< MaterialData > materials
ensemble de matieres
Definition: mesh_buffer.h:30
std::vector< int > indices
indices des sommets des triangles
Definition: mesh_buffer.h:28
std::vector< vec2 > texcoords
attribut coordonnees de texture
Definition: mesh_buffer.h:24
std::vector< vec3 > normals
attribut normale
Definition: mesh_buffer.h:25
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
vecteur generique 4d, ou 3d homogene, utilitaire.
Definition: vec.h:168