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