gKit2 light
mesh.cpp
1 
2 #include <cstdio>
3 #include <cassert>
4 #include <string>
5 #include <algorithm>
6 
7 #include "vec.h"
8 #include "mesh.h"
9 
10 #include "program.h"
11 #include "uniforms.h"
12 
13 #include "window.h"
14 
15 
16 int Mesh::create( const GLenum primitives )
17 {
18  m_primitives= primitives;
19  return 0;
20 }
21 
22 int Mesh::create( const GLenum primitives, const std::vector<vec3>& positions )
23 {
24  clear();
25  m_primitives= primitives;
26  m_positions= positions;
27  return 0;
28 }
29 
30 int Mesh::create( const GLenum primitives, const std::vector<vec3>& positions, const std::vector<unsigned>& indices )
31 {
32  clear();
33  m_primitives= primitives;
34  m_positions= positions;
35  m_indices= indices;
36  return 0;
37 }
38 
39 int Mesh::create( const GLenum primitives, const std::vector<vec3>& positions,
40  const std::vector<vec2>& texcoords,
41  const std::vector<vec3>& normals,
42  const std::vector<vec4>& colors,
43  const std::vector<unsigned>& indices )
44 {
45  clear();
46  if(texcoords.size() > 0 && texcoords.size() != positions.size()) return -1;
47  if(normals.size() > 0 && normals.size() != positions.size()) return -1;
48  if(colors.size() > 0 && colors.size() != positions.size()) return -1;
49 
50  m_primitives= primitives;
51  m_positions= positions;
52  m_indices= indices;
53  m_texcoords= texcoords;
54  m_normals= normals;
55  m_colors= colors;
56 
57  return 0;
58 }
59 
60 
61 
63 {
64  printf("mesh release %d\n", m_vao);
65 
66  glDeleteVertexArrays(1, &m_vao);
67  glDeleteBuffers(1, &m_buffer);
68  glDeleteBuffers(1, &m_index_buffer);
69 }
70 
71 // definit les attributs du prochain sommet
72 Mesh& Mesh::default_color( const Color& color )
73 {
74  m_color= color;
75  return *this;
76 }
77 
78 Mesh& Mesh::color( const vec4& color )
79 {
80  if(m_colors.size() <= m_positions.size())
81  m_colors.push_back(color);
82  else
83  m_colors.back()= color;
84  m_update_buffers= true;
85  return *this;
86 }
87 
88 Mesh& Mesh::normal( const vec3& normal )
89 {
90  if(m_normals.size() <= m_positions.size())
91  m_normals.push_back(normal);
92  else
93  m_normals.back()= normal;
94  m_update_buffers= true;
95  return *this;
96 }
97 
98 Mesh& Mesh::texcoord( const vec2& uv )
99 {
100  if(m_texcoords.size() <= m_positions.size())
101  m_texcoords.push_back(uv);
102  else
103  m_texcoords.back()= uv;
104  m_update_buffers= true;
105  return *this;
106 }
107 
108 // insere un nouveau sommet
109 unsigned int Mesh::vertex( const vec3& position )
110 {
111  m_update_buffers= true;
112  m_positions.push_back(position);
113 
114  // copie les autres attributs du sommet, uniquement s'ils sont definis
115  if(m_texcoords.size() > 0 && m_texcoords.size() != m_positions.size())
116  m_texcoords.push_back(m_texcoords.back());
117  if(m_normals.size() > 0 && m_normals.size() != m_positions.size())
118  m_normals.push_back(m_normals.back());
119  if(m_colors.size() > 0 && m_colors.size() != m_positions.size())
120  m_colors.push_back(m_colors.back());
121 
122  // copie la matiere courante, uniquement si elle est definie
123  if(m_triangle_materials.size() > 0 && int(m_triangle_materials.size()) < triangle_count())
124  m_triangle_materials.push_back(m_triangle_materials.back());
125 
126  unsigned int index= m_positions.size() -1;
127  // construction de l'index buffer pour les strip
128  switch(m_primitives)
129  {
130  case GL_LINE_STRIP:
131  case GL_LINE_LOOP:
132  case GL_TRIANGLE_STRIP:
133  case GL_TRIANGLE_FAN:
134  m_indices.push_back(index);
135  break;
136  default:
137  break;
138  }
139 
140  // renvoie l'indice du sommet
141  return index;
142 }
143 
144 // update attributes
145 Mesh& Mesh::color( const unsigned int id, const vec4& c )
146 {
147  assert(id < m_colors.size());
148  m_update_buffers= true;
149  m_colors[id]= c;
150  return *this;
151 }
152 
153 Mesh& Mesh::normal( const unsigned int id, const vec3& n )
154 {
155  assert(id < m_normals.size());
156  m_update_buffers= true;
157  m_normals[id]= n;
158  return *this;
159 }
160 
161 Mesh& Mesh::texcoord( const unsigned int id, const vec2& uv )
162 {
163  assert(id < m_texcoords.size());
164  m_update_buffers= true;
165  m_texcoords[id]= uv;
166  return *this;
167 }
168 
169 void Mesh::vertex( const unsigned int id, const vec3& p )
170 {
171  assert(id < m_positions.size());
172  m_update_buffers= true;
173  m_positions[id]= p;
174 }
175 
176 void Mesh::clear( )
177 {
178  m_update_buffers= true;
179 
180  m_positions.clear();
181  m_texcoords.clear();
182  m_normals.clear();
183  m_colors.clear();
184  m_indices.clear();
185  //~ m_materials.clear();
186  m_triangle_materials.clear();
187 }
188 
189 //
190 Mesh& Mesh::triangle( const unsigned int a, const unsigned int b, const unsigned int c )
191 {
192  assert(a < m_positions.size());
193  assert(b < m_positions.size());
194  assert(c < m_positions.size());
195  m_update_buffers= true;
196  m_indices.push_back(a);
197  m_indices.push_back(b);
198  m_indices.push_back(c);
199 
200  // copie la matiere courante, uniquement si elle est definie
201  if(m_triangle_materials.size() > 0 && int(m_triangle_materials.size()) < triangle_count())
202  m_triangle_materials.push_back(m_triangle_materials.back());
203 
204  m_update_buffers= true;
205  return *this;
206 }
207 
208 Mesh& Mesh::triangle_last( const int a, const int b, const int c )
209 {
210  assert(a < 0);
211  assert(b < 0);
212  assert(c < 0);
213  m_update_buffers= true;
214  m_indices.push_back(int(m_positions.size()) + a);
215  m_indices.push_back(int(m_positions.size()) + b);
216  m_indices.push_back(int(m_positions.size()) + c);
217 
218  // copie la matiere courante, uniquement si elle est definie
219  if(m_triangle_materials.size() > 0 && int(m_triangle_materials.size()) < triangle_count())
220  m_triangle_materials.push_back(m_triangle_materials.back());
221 
222  m_update_buffers= true;
223  return *this;
224 }
225 
227 {
228  m_update_buffers= true;
229  m_indices.push_back(~0u); // ~0u plus grand entier non signe representable, ou UINT_MAX...
230 #if 1
231  glPrimitiveRestartIndex(~0u);
232  glEnable(GL_PRIMITIVE_RESTART);
233 #else
234  glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); // n'existe pas sur mac ?!
235 #endif
236  return *this;
237 }
238 
239 Mesh& Mesh::index( const int a )
240 {
241  if(a < 0)
242  m_indices.push_back(int(m_positions.size()) + a);
243  else if(a < int(m_positions.size()))
244  m_indices.push_back(a);
245  else
246  {
247  printf("[error] Mesh::index(): invalid index...\n");
248  return *this; // erreur
249  }
250 
251  // copie la matiere courante, uniquement si elle est definie
252  if(m_triangle_materials.size() > 0 && int(m_triangle_materials.size()) < triangle_count())
253  m_triangle_materials.push_back(m_triangle_materials.back());
254 
255  m_update_buffers= true;
256  return *this;
257 }
258 
259 
261 {
262  return m_materials;
263 }
264 
265 const Materials& Mesh::materials( ) const
266 {
267  return m_materials;
268 }
269 
270 void Mesh::materials( const Materials& materials )
271 {
272  m_materials= materials;
273 }
274 
275 Mesh& Mesh::material( const unsigned int id )
276 {
277  if(int(m_triangle_materials.size()) <= triangle_count())
278  m_triangle_materials.push_back(id);
279  else
280  m_triangle_materials.back()= id;
281  m_update_buffers= true;
282  return *this;
283 }
284 
285 const std::vector<unsigned int>& Mesh::material_indices( ) const
286 {
287  return m_triangle_materials;
288 }
289 
290 int Mesh::triangle_material_index( const unsigned int id ) const
291 {
292  assert((size_t) id < m_triangle_materials.size());
293  return m_triangle_materials[id];
294 }
295 
296 const Material &Mesh::triangle_material( const unsigned int id ) const
297 {
298  assert((size_t) id < m_triangle_materials.size());
299  return m_materials.material(m_triangle_materials[id]);
300 }
301 
302 
303 std::vector<TriangleGroup> Mesh::groups( )
304 {
305  return groups(m_triangle_materials);
306 }
307 
308 std::vector<TriangleGroup> Mesh::groups( const std::vector<unsigned int>& triangle_properties )
309 {
310  if(m_primitives != GL_TRIANGLES)
311  return {};
312 
313  // pas le bon nombre d'infos, renvoyer un seul groupe
314  if(int(triangle_properties.size()) != triangle_count())
315  {
316  if(m_indices.size())
317  return { {0, 0, int(m_indices.size())} };
318  else
319  return { {0, 0, int(m_positions.size())} };
320  }
321 
322  // trie les triangles
323  std::vector<int> remap(triangle_count());
324  for(unsigned i= 0; i < remap.size(); i++)
325  remap[i]= i;
326 
327  struct triangle_sort
328  {
329  const std::vector<unsigned int>& properties;
330 
331  triangle_sort( const std::vector<unsigned int>& _properties ) : properties(_properties) {}
332 
333  bool operator() ( const int& a, const int& b ) const
334  {
335  return properties[a] < properties[b];
336  }
337  };
338 
339  std::stable_sort(remap.begin(), remap.end(), triangle_sort(triangle_properties));
340 
341  // re-organise les triangles, et construit les groupes
342  std::vector<TriangleGroup> groups;
343  if(m_indices.size())
344  {
345  int first= 0;
346  int property_id= triangle_properties[remap[0]];
347 
348  // re-organise l'index buffer...
349  std::vector<unsigned int> indices;
350  std::vector<unsigned int> material_indices;
351  for(unsigned i= 0; i < remap.size(); i++)
352  {
353  int id= triangle_properties[remap[i]];
354  if(id != property_id)
355  {
356  groups.push_back( {property_id, first, int(3*i) - first} );
357  first= 3*i;
358  property_id= id;
359  }
360 
361  indices.push_back(m_indices[3*remap[i]]);
362  indices.push_back(m_indices[3*remap[i]+1]);
363  indices.push_back(m_indices[3*remap[i]+2]);
364 
365  material_indices.push_back(m_triangle_materials[remap[i]]);
366  }
367 
368  // dernier groupe
369  groups.push_back( {property_id, first, int(3 * remap.size()) - first} );
370 
371  std::swap(m_indices, indices);
372  std::swap(m_triangle_materials, material_indices);
373  }
374  else
375  {
376  int first= 0;
377  int property_id= triangle_properties[remap[0]];
378 
379  // re-organise les attributs !!
380  std::vector<vec3> positions;
381  std::vector<vec2> texcoords;
382  std::vector<vec3> normals;
383  std::vector<vec4> colors;
384  std::vector<unsigned int> material_indices;
385  for(unsigned i= 0; i < remap.size(); i++)
386  {
387  int id= triangle_properties[remap[i]];
388  if(id != property_id)
389  {
390  groups.push_back( {property_id, first, int(3*i) - first} );
391  first= 3*i;
392  property_id= id;
393  }
394 
395  positions.push_back(m_positions[3*remap[i]]);
396  positions.push_back(m_positions[3*remap[i]+1]);
397  positions.push_back(m_positions[3*remap[i]+2]);
398  if(has_texcoord())
399  {
400  texcoords.push_back(m_texcoords[3*remap[i]]);
401  texcoords.push_back(m_texcoords[3*remap[i]+1]);
402  texcoords.push_back(m_texcoords[3*remap[i]+2]);
403  }
404  if(has_normal())
405  {
406  normals.push_back(m_normals[3*remap[i]]);
407  normals.push_back(m_normals[3*remap[i]+1]);
408  normals.push_back(m_normals[3*remap[i]+2]);
409  }
410  if(has_color())
411  {
412  colors.push_back(m_colors[3*remap[i]]);
413  colors.push_back(m_colors[3*remap[i]+1]);
414  colors.push_back(m_colors[3*remap[i]+2]);
415  }
416 
417  material_indices.push_back(m_triangle_materials[remap[i]]);
418  }
419 
420  // dernier groupe
421  groups.push_back( {property_id, first, int(3 * remap.size()) - first} );
422 
423  std::swap(m_positions, positions);
424  std::swap(m_texcoords, texcoords);
425  std::swap(m_normals, normals);
426  std::swap(m_colors, colors);
427  std::swap(m_triangle_materials, material_indices);
428  }
429 
430  return groups;
431 }
432 
434 {
435  if(m_primitives != GL_TRIANGLES)
436  return 0;
437 
438  if(m_indices.size() > 0)
439  return int(m_indices.size() / 3);
440  else
441  return int(m_positions.size() / 3);
442 }
443 
444 TriangleData Mesh::triangle( const unsigned int id ) const
445 {
446  unsigned int a, b, c;
447  if(m_indices.size() > 0)
448  {
449  assert((size_t) id*3+2 < m_indices.size());
450  a= m_indices[id*3];
451  b= m_indices[id*3 +1];
452  c= m_indices[id*3 +2];
453  }
454  else
455  {
456  assert((size_t) id*3+2 < m_positions.size());
457  a= id*3;
458  b= id*3 +1;
459  c= id*3 +2;
460  }
461 
463  triangle.a= m_positions[a];
464  triangle.b= m_positions[b];
465  triangle.c= m_positions[c];
466 
467  if(m_normals.size() == m_positions.size())
468  {
469  triangle.na= m_normals[a];
470  triangle.nb= m_normals[b];
471  triangle.nc= m_normals[c];
472  }
473  else
474  {
475  // calculer la normale geometrique
476  Vector ab= Point(m_positions[b]) - Point(m_positions[a]);
477  Vector ac= Point(m_positions[c]) - Point(m_positions[a]);
478  Vector n= normalize(cross(ab, ac));
479  triangle.na= vec3(n);
480  triangle.nb= vec3(n);
481  triangle.nc= vec3(n);
482  }
483 
484  if(m_texcoords.size() == m_positions.size())
485  {
486  triangle.ta= m_texcoords[a];
487  triangle.tb= m_texcoords[b];
488  triangle.tc= m_texcoords[c];
489  }
490  else
491  {
492  // coordonnees barycentriques des sommets, convention p(u, v)= w*a + u*b + v*c, avec w= 1 - u -v
493  triangle.ta= vec2(0, 0); // w= 1
494  triangle.tb= vec2(1, 0); // w= 0
495  triangle.tc= vec2(0, 1); // w= 0
496  }
497 
498  return triangle;
499 }
500 
501 void Mesh::bounds( Point& pmin, Point& pmax ) const
502 {
503  if(m_positions.size() < 1)
504  return;
505 
506  pmin= Point(m_positions[0]);
507  pmax= pmin;
508 
509  for(unsigned i= 1; i < m_positions.size(); i++)
510  {
511  vec3 p= m_positions[i];
512  pmin= Point( std::min(pmin.x, p.x), std::min(pmin.y, p.y), std::min(pmin.z, p.z) );
513  pmax= Point( std::max(pmax.x, p.x), std::max(pmax.y, p.y), std::max(pmax.z, p.z) );
514  }
515 }
516 
517 
518 
519 
520 
523 {
524 public:
526  void copy( GLenum target, const size_t offset, const size_t length, const void *data )
527  {
528  if(m_buffer == 0)
529  glGenBuffers(1, &m_buffer);
530 
531  assert(m_buffer);
532  glBindBuffer(GL_COPY_READ_BUFFER, m_buffer);
533  if(length > m_size)
534  {
535  m_size= (length / (16*1024*1024) + 1) * (16*1024*1024); // alloue par bloc de 16Mo
536  assert(m_size >= length);
537 
538  // alloue un buffer intermediaire dynamique...
539  glBufferData(GL_COPY_READ_BUFFER, m_size, nullptr, GL_DYNAMIC_DRAW);
540  printf("[UpdateBuffer] allocate %dMo staging buffer...\n", int(m_size / 1024 / 1024));
541  }
542 
543  // place les donnees dans le buffer intermediaire
544  glBufferSubData(GL_COPY_READ_BUFFER, 0, length, data);
545  // copie les donnees dans le vertex buffer statique
546  glCopyBufferSubData(GL_COPY_READ_BUFFER, target, 0, offset, length);
547  }
548 
551  {
552  release();
553  }
554 
556  void release( )
557  {
558  glDeleteBuffers(1, &m_buffer);
559  m_buffer= 0;
560  m_size= 0;
561  }
562 
565  {
566  static UpdateBuffer buffer;
567  return buffer;
568  }
569 
570 protected:
572  UpdateBuffer( ) : m_buffer(0), m_size(0) {}
573 
574  GLuint m_buffer;
575  size_t m_size;
576 };
577 
578 
579 GLuint Mesh::create_buffers( const bool use_texcoord, const bool use_normal, const bool use_color, const bool use_material_index )
580 {
581  if(m_positions.size() == 0)
582  return 0;
583 
584 #if 1
585  if(use_texcoord && !has_texcoord())
586  printf("[oops] mesh: no texcoord array...\n");
587  if(use_normal && !has_normal())
588  printf("[oops] mesh: no normal array...\n");
589  if(use_color && !has_color())
590  printf("[oops] mesh: no color array...\n");
591  if(use_material_index && !has_material_index())
592  printf("[oops] mesh: no material index array...\n");
593 #endif
594 
595  if(m_vao)
596  // c'est deja fait...
597  return m_vao;
598 
599  // configuration du format de sommet
600  glGenVertexArrays(1, &m_vao);
601  glBindVertexArray(m_vao);
602 
603  // determine la taille du buffer pour stocker tous les attributs et les indices
604  m_vertex_buffer_size= vertex_buffer_size();
605  if(use_texcoord && has_texcoord())
606  m_vertex_buffer_size+= texcoord_buffer_size();
607  if(use_normal && has_normal())
608  m_vertex_buffer_size+= normal_buffer_size();
609  if(use_color && has_color())
610  m_vertex_buffer_size+= color_buffer_size();
611  if(use_material_index && has_material_index())
612  m_vertex_buffer_size+= m_positions.size() * sizeof(unsigned char);
613 
614  // alloue le buffer
615  glGenBuffers(1, &m_buffer);
616  glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
617  glBufferData(GL_ARRAY_BUFFER, m_vertex_buffer_size, nullptr, GL_STATIC_DRAW);
618 
619  // index buffer
620  m_index_buffer_size= index_buffer_size();
621  if(m_index_buffer_size)
622  {
623  glGenBuffers(1, &m_index_buffer);
624  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer);
625  glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_size, index_buffer(), GL_STATIC_DRAW);
626  }
627 
628  // transfere les donnees dans les buffers
629  update_buffers(use_texcoord, use_normal, use_color, use_material_index);
630 
631  return m_vao;
632 }
633 
634 int Mesh::update_buffers( const bool use_texcoord, const bool use_normal, const bool use_color, const bool use_material_index )
635 {
636  assert(m_vao > 0);
637  assert(m_buffer > 0);
638  if(!m_update_buffers)
639  return 0;
640 
641  // alloue un buffer de copie, necessaire pour transferer plus de 256Mo... cf tuto_stream.cpp / transfert de donnees gpu
643 
644  glBindVertexArray(m_vao);
645  glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
646 
647  // determine la taille du buffer pour stocker tous les attributs et les indices
648  size_t size= vertex_buffer_size();
649  if(use_texcoord && has_texcoord())
650  size+= texcoord_buffer_size();
651  if(use_normal && has_normal())
652  size+= normal_buffer_size();
653  if(use_color && has_color())
654  size+= color_buffer_size();
655  if(use_material_index && has_material_index())
656  size+= m_positions.size() * sizeof(unsigned char);
657 
658  if(size != m_vertex_buffer_size)
659  {
660  m_vertex_buffer_size= size;
661  glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
662  }
663 
664  // transferer les attributs et configurer le format de sommet (vao)
665  size_t offset= 0;
666  size= vertex_buffer_size();
667  //~ glBufferSubData(GL_ARRAY_BUFFER, offset, size, vertex_buffer()); // copie les donnees dans le vertex buffer
668  update.copy(GL_ARRAY_BUFFER, offset, size, vertex_buffer()); // copie les donnees dans le vertex buffer
669 
670  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const void *) offset);
671  glEnableVertexAttribArray(0);
672 
673  if(use_texcoord && has_texcoord())
674  {
675  offset= offset + size;
676  size= texcoord_buffer_size();
677  //~ glBufferSubData(GL_ARRAY_BUFFER, offset, size, texcoord_buffer()); // copie les donnees dans le vertex buffer
678  update.copy(GL_ARRAY_BUFFER, offset, size, texcoord_buffer()); // copie les donnees dans le vertex buffer
679 
680  glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (const void *) offset);
681  glEnableVertexAttribArray(1);
682  }
683 
684  if(use_normal && has_normal())
685  {
686  offset= offset + size;
687  size= normal_buffer_size();
688  //~ glBufferSubData(GL_ARRAY_BUFFER, offset, size, normal_buffer()); // copie les donnees dans le vertex buffer
689  update.copy(GL_ARRAY_BUFFER, offset, size, normal_buffer()); // copie les donnees dans le vertex buffer
690 
691  glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (const void *) offset);
692  glEnableVertexAttribArray(2);
693  }
694 
695  if(use_color && has_color())
696  {
697  offset= offset + size;
698  size= color_buffer_size();
699  //~ glBufferSubData(GL_ARRAY_BUFFER, offset, size, color_buffer()); // copie les donnees dans le vertex buffer
700  update.copy(GL_ARRAY_BUFFER, offset, size, color_buffer()); // copie les donnees dans le vertex buffer
701 
702  glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, (const void *) offset);
703  glEnableVertexAttribArray(3);
704  }
705 
706  if(use_material_index && has_material_index())
707  {
708  assert(int(m_triangle_materials.size()) == triangle_count());
709 
710  offset= offset + size;
711  size= m_positions.size() * sizeof(unsigned char);
712 
713  // prepare un indice de matiere par sommet / 3 indices par triangle
714  std::vector<unsigned char> buffer(m_positions.size());
715  if(m_indices.size())
716  {
719  for(int triangle_id= 0; triangle_id < int(m_triangle_materials.size()); triangle_id++)
720  {
721  int material_id= m_triangle_materials[triangle_id];
722  assert(triangle_id*3+2 < int(m_indices.size()));
723  unsigned a= m_indices[triangle_id*3];
724  unsigned b= m_indices[triangle_id*3 +1];
725  unsigned c= m_indices[triangle_id*3 +2];
726 
727  buffer[a]= material_id;
728  buffer[b]= material_id;
729  buffer[c]= material_id;
730  }
731  }
732  else
733  {
734  for(int triangle_id= 0; triangle_id < int(m_triangle_materials.size()); triangle_id++)
735  {
736  int material_id= m_triangle_materials[triangle_id];
737  assert(triangle_id*3+2 < int(m_positions.size()));
738  unsigned a= triangle_id*3;
739  unsigned b= triangle_id*3 +1;
740  unsigned c= triangle_id*3 +2;
741 
742  buffer[a]= material_id;
743  buffer[b]= material_id;
744  buffer[c]= material_id;
745  }
746  }
747 
748  //~ glBufferSubData(GL_ARRAY_BUFFER, offset, size, buffer.data()); // copie les donnees dans le vertex buffer
749  update.copy(GL_ARRAY_BUFFER, offset, size, buffer.data()); // copie les donnees dans le vertex buffer
750 
751  glVertexAttribIPointer(4, 1, GL_UNSIGNED_BYTE, 0, (const void *) offset);
752  glEnableVertexAttribArray(4);
753  }
754 
755  // index buffer
756  size= index_buffer_size();
757  if(size != m_index_buffer_size)
758  {
759  m_index_buffer_size= index_buffer_size();
760  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer);
761  glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_buffer_size(), index_buffer(), GL_STATIC_DRAW);
762  }
763 
764  m_update_buffers= false;
765  return 1;
766 }
767 
768 void Mesh::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 )
769 {
770  if(m_indices.size())
771  draw(0, int(m_indices.size()), program, use_position, use_texcoord, use_normal, use_color, use_material_index);
772  else
773  draw(0, int(m_positions.size()), program, use_position, use_texcoord, use_normal, use_color, use_material_index);
774 }
775 
776 void Mesh::draw( const int first, const int n, const GLuint program, const bool use_position, const bool use_texcoord, const bool use_normal, const bool use_color, const bool use_material_index )
777 {
778  if(program == 0)
779  {
780  printf("[oops] no program... can't draw !!\n");
781  return;
782  }
783 
784  // transfere toutes les donnees disponibles (et correctement definies)
785  // le meme mesh peut etre dessine avec plusieurs shaders utilisant des attributs differents...
786  if(m_vao == 0)
787  create_buffers(has_texcoord(), has_normal(), has_color(), has_material_index());
788  assert(m_vao != 0);
789 
790  if(m_update_buffers)
791  update_buffers(has_texcoord(), has_normal(), has_color(), has_material_index());
792 
793  glBindVertexArray(m_vao);
794 
795  #ifndef GK_RELEASE
796  {
797  char label[2048]= { 0 };
798  #ifdef GL_VERSION_4_3
799  {
800  char tmp[1024];
801  glGetObjectLabel(GL_PROGRAM, program, sizeof(tmp), nullptr, tmp);
802  sprintf(label, "program( %u '%s' )", program, tmp);
803  }
804  #else
805  sprintf(label, "program( %u )", program);
806  #endif
807 
808  // verifie que le program est selectionne
809  GLuint current;
810  glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &current);
811  if(current != program)
812  printf("[oops] %s: not active... undefined draw !!\n", label);
813 
814  // verifie que les attributs necessaires a l'execution du shader sont presents dans le mesh...
815  // etape 1 : recuperer le nombre d'attributs
816  GLint n= 0;
817  glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n);
818 
819  // etape 2 : recuperer les infos de chaque attribut
820  char name[1024];
821  for(int index= 0; index < n; index++)
822  {
823  GLint glsl_size;
824  GLenum glsl_type;
825  glGetActiveAttrib(program, index, sizeof(name), nullptr, &glsl_size, &glsl_type, name);
826 
827  GLint location= glGetAttribLocation(program, name);
828  if(location == 0) // attribut position necessaire a l'execution du shader
829  {
830  if(!use_position || !has_position())
831  printf("[oops] position attribute '%s' in %s: no data... undefined draw !!\n", name, label);
832  if(glsl_size != 1 || glsl_type != GL_FLOAT_VEC3)
833  printf("[oops] position attribute '%s' is not declared as a vec3 in %s... undefined draw !!\n", name, label);
834  }
835  else if(location == 1) // attribut texcoord necessaire
836  {
837  if(!use_texcoord || !has_texcoord())
838  printf("[oops] texcoord attribute '%s' in %s: no data... undefined draw !!\n", name, label);
839  if(glsl_size != 1 || glsl_type != GL_FLOAT_VEC2)
840  printf("[oops] texcoord attribute '%s' is not declared as a vec2 in %s... undefined draw !!\n", name, label);
841  }
842  else if(location == 2) // attribut normal necessaire
843  {
844  if(!use_normal || !has_normal())
845  printf("[oops] normal attribute '%s' in %s: no data... undefined draw !!\n", name, label);
846  if(glsl_size != 1 || glsl_type != GL_FLOAT_VEC3)
847  printf("[oops] attribute '%s' is not declared as a vec3 in %s... undefined draw !!\n", name, label);
848  }
849  else if(location == 3) // attribut color necessaire
850  {
851  if(!use_color || !has_color())
852  printf("[oops] color attribute '%s' in %s: no data... undefined draw !!\n", name, label);
853  if(glsl_size != 1 || glsl_type != GL_FLOAT_VEC4)
854  printf("[oops] attribute '%s' is not declared as a vec4 in %s... undefined draw !!\n", name, label);
855  }
856  else if(location == 4) // attribut material_index necessaire
857  {
858  if(!use_material_index || !has_material_index())
859  printf("[oops] material_index attribute '%s' in %s: no data... undefined draw !!\n", name, label);
860  if(glsl_size != 1 || glsl_type != GL_UNSIGNED_INT)
861  printf("[oops] attribute '%s' is not declared as a uint in %s... undefined draw !!\n", name, label);
862  }
863  }
864  }
865  #endif
866 
867  if(m_indices.size() > 0)
868  glDrawElements(m_primitives, n, GL_UNSIGNED_INT, (void *) (first * sizeof(unsigned)));
869  else
870  glDrawArrays(m_primitives, first, n);
871 }
representation d'un objet / maillage.
Definition: mesh.h:112
std::size_t texcoord_buffer_size() const
renvoie la taille (en octets) du texcoord buffer.
Definition: mesh.h:308
const float * color_buffer() const
renvoie l'adresse de la couleur du premier sommet. par convention, la couleur est un vec4,...
Definition: mesh.h:311
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:109
Mesh & texcoord(const vec2 &uv)
definit les coordonnees de texture du prochain sommet.
Definition: mesh.cpp:98
const float * vertex_buffer() const
renvoie l'adresse de la position du premier sommet. permet de construire les vertex buffers openGL....
Definition: mesh.h:296
GLuint create_buffers(const bool use_texcoord, const bool use_normal, const bool use_color, const bool use_material_index)
construit les buffers et le vertex array object necessaires pour dessiner l'objet avec openGL....
Definition: mesh.cpp:579
const std::vector< unsigned int > & material_indices() const
renvoie les indices des matieres des triangles.
Definition: mesh.cpp:285
Mesh & material(const unsigned int id)
definit la matiere du prochain triangle. id est l'indice d'une matiere ajoutee dans materials(),...
Definition: mesh.cpp:275
Mesh & restart_strip()
demarre un nouveau strip. a utiliser avec un objet composes de GL_TRIANGLE_STRIP, doit aussi fonction...
Definition: mesh.cpp:226
std::vector< TriangleGroup > groups()
renvoie les groupes de triangles de meme matiere. re-organise les triangles. permet d'afficher l'obje...
Definition: mesh.cpp:303
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:501
Color default_color() const
renvoie la couleur par defaut du mesh, utilisee si les sommets n'ont pas de couleur associee.
Definition: mesh.h:284
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:768
std::size_t index_buffer_size() const
renvoie la taille (en octets) de l'index buffer.
Definition: mesh.h:318
int create(const GLenum primitives)
construit les objets openGL.
Definition: mesh.cpp:16
void clear()
vide la description.
Definition: mesh.cpp:176
Mesh & triangle(const unsigned int a, const unsigned int b, const unsigned int c)
Definition: mesh.cpp:190
Mesh & normal(const vec3 &n)
definit la normale du prochain sommet.
Definition: mesh.cpp:88
int triangle_count() const
renvoie le nombre de triangles.
Definition: mesh.cpp:433
std::size_t vertex_buffer_size() const
renvoie la longueur (en octets) du vertex buffer.
Definition: mesh.h:298
const Material & triangle_material(const unsigned int id) const
renvoie la matiere d'un triangle.
Definition: mesh.cpp:296
int triangle_material_index(const unsigned int id) const
renvoie l'indice de la matiere d'un triangle.
Definition: mesh.cpp:290
const float * texcoord_buffer() const
renvoie l'adresse des coordonnees de textures du premier sommet. par convention, c'est un vec2,...
Definition: mesh.h:306
const void * index_buffer() const
renvoie l'adresse du premier indice du premier triangle. par convention c'est un uint,...
Definition: mesh.h:316
Mesh & index(const int a)
Definition: mesh.cpp:239
GLenum primitives() const
renvoie le type de primitives.
Definition: mesh.h:336
void release()
detruit les objets openGL.
Definition: mesh.cpp:62
Mesh & color(const vec4 &c)
definit la couleur du prochain sommet.
Definition: mesh.cpp:78
Mesh & triangle_last(const int a, const int b, const int c)
Definition: mesh.cpp:208
bool has_position() const
verifie que les attributs sont decrits de maniere coherente.
Definition: mesh.h:328
const Materials & materials() const
renvoie la description des matieres.
Definition: mesh.cpp:265
std::size_t normal_buffer_size() const
renvoie la longueur (en octets) du normal buffer.
Definition: mesh.h:303
std::size_t color_buffer_size() const
renvoie la taille (en octets) du color buffer.
Definition: mesh.h:313
const float * normal_buffer() const
renvoie l'adresse de la normale du premier sommet. par convention, la normale est un vec3,...
Definition: mesh.h:301
buffer unique de copie / mise a jour des vertex buffers statiques. singleton. tous les meshs utilisen...
Definition: mesh.cpp:523
void release()
detruit le buffer.
Definition: mesh.cpp:556
static UpdateBuffer & manager()
acces au singleton.
Definition: mesh.cpp:564
void copy(GLenum target, const size_t offset, const size_t length, const void *data)
transfere les donnees dans un buffer statique.
Definition: mesh.cpp:526
~UpdateBuffer()
detruit le buffer.
Definition: mesh.cpp:550
UpdateBuffer()
constructeur prive. singleton.
Definition: mesh.cpp:572
void label(Widgets &w, const char *format,...)
cree un texte. meme fonctionnement que printf().
Definition: widgets.cpp:142
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
Definition: text.cpp:140
Point max(const Point &a, const Point &b)
renvoie la plus grande composante de chaque point. x, y, z= max(a.x, b.x), max(a.y,...
Definition: vec.cpp:35
Point min(const Point &a, const Point &b)
renvoie la plus petite composante de chaque point. x, y, z= min(a.x, b.x), min(a.y,...
Definition: vec.cpp:30
Vector normalize(const Vector &v)
renvoie un vecteur unitaire / longueur == 1.
Definition: vec.cpp:123
float length(const Vector &v)
renvoie la longueur d'un vecteur.
Definition: vec.cpp:142
Vector cross(const Vector &u, const Vector &v)
renvoie le produit vectoriel de 2 vecteurs.
Definition: vec.cpp:129
void normals(MeshData &data)
(re-) calcule les normales des sommets. utiliser avant les reindexations, cf indices() et vertices().
Definition: mesh_data.cpp:307
representation d'une couleur (rgba) transparente ou opaque.
Definition: color.h:14
const Material & material(const int id) const
renvoie la ieme matiere.
Definition: materials.h:102
representation d'un point 3d.
Definition: vec.h:21
representation d'un triangle.
Definition: mesh.h:95
representation d'un vecteur 3d.
Definition: vec.h:59
vecteur generique, utilitaire.
Definition: vec.h:131
vecteur generique, utilitaire.
Definition: vec.h:146
vecteur generique 4d, ou 3d homogene, utilitaire.
Definition: vec.h:168