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)
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)
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)
41 if(texcoords.size() > 0 && texcoords.size() == positions.size())
42 m_texcoords= texcoords;
43 if(normals.size() > 0 && normals.size() == positions.size())
45 if(colors.size() > 0 && colors.size() == positions.size())
52 printf(
"mesh release %d\n", m_vao);
54 glDeleteVertexArrays(1, &m_vao);
55 glDeleteBuffers(1, &m_buffer);
56 glDeleteBuffers(1, &m_index_buffer);
68 if(m_colors.size() <= m_positions.size())
69 m_colors.push_back(
color);
71 m_colors.back()=
color;
72 m_update_buffers=
true;
78 if(m_normals.size() <= m_positions.size())
79 m_normals.push_back(
normal);
82 m_update_buffers=
true;
88 if(m_texcoords.size() <= m_positions.size())
89 m_texcoords.push_back(uv);
91 m_texcoords.back()= uv;
92 m_update_buffers=
true;
99 m_update_buffers=
true;
100 m_positions.push_back(position);
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());
111 if(m_triangle_materials.size() > 0 &&
int(m_triangle_materials.size()) <
triangle_count())
112 m_triangle_materials.push_back(m_triangle_materials.back());
114 unsigned int index= m_positions.size() -1;
120 case GL_TRIANGLE_STRIP:
121 case GL_TRIANGLE_FAN:
122 m_indices.push_back(
index);
135 assert(
id < m_colors.size());
136 m_update_buffers=
true;
143 assert(
id < m_normals.size());
144 m_update_buffers=
true;
151 assert(
id < m_texcoords.size());
152 m_update_buffers=
true;
159 assert(
id < m_positions.size());
160 m_update_buffers=
true;
166 m_update_buffers=
true;
174 m_triangle_materials.clear();
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);
189 if(m_triangle_materials.size() > 0 &&
int(m_triangle_materials.size()) <
triangle_count())
190 m_triangle_materials.push_back(m_triangle_materials.back());
192 m_update_buffers=
true;
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);
207 if(m_triangle_materials.size() > 0 &&
int(m_triangle_materials.size()) <
triangle_count())
208 m_triangle_materials.push_back(m_triangle_materials.back());
210 m_update_buffers=
true;
216 m_update_buffers=
true;
217 m_indices.push_back(~0u);
219 glPrimitiveRestartIndex(~0u);
220 glEnable(GL_PRIMITIVE_RESTART);
222 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
230 m_indices.push_back(
int(m_positions.size()) + a);
231 else if(a <
int(m_positions.size()))
232 m_indices.push_back(a);
235 printf(
"[error] Mesh::index(): invalid index...\n");
240 if(m_triangle_materials.size() > 0 &&
int(m_triangle_materials.size()) <
triangle_count())
241 m_triangle_materials.push_back(m_triangle_materials.back());
243 m_update_buffers=
true;
266 m_triangle_materials.push_back(
id);
268 m_triangle_materials.back()= id;
269 m_update_buffers=
true;
275 return m_triangle_materials;
280 assert((
size_t)
id < m_triangle_materials.size());
281 return m_triangle_materials[id];
286 assert((
size_t)
id < m_triangle_materials.size());
287 return m_materials.material(m_triangle_materials[
id]);
293 return groups(m_triangle_materials);
296std::vector<TriangleGroup>
Mesh::groups(
const std::vector<unsigned int>& triangle_properties )
298 if(m_primitives != GL_TRIANGLES)
305 return { {0, 0, int(m_indices.size())} };
307 return { {0, 0, int(m_positions.size())} };
312 for(
unsigned i= 0; i < remap.size(); i++)
317 const std::vector<unsigned int>& properties;
319 triangle_sort(
const std::vector<unsigned int>& _properties ) : properties(_properties) {}
321 bool operator() (
const int& a,
const int& b )
const
323 return properties[a] < properties[b];
327 std::stable_sort(remap.begin(), remap.end(), triangle_sort(triangle_properties));
330 std::vector<TriangleGroup>
groups;
334 int property_id= triangle_properties[remap[0]];
337 std::vector<unsigned int> indices;
339 for(
unsigned i= 0; i < remap.size(); i++)
341 int id= triangle_properties[remap[i]];
342 if(
id != property_id)
344 groups.push_back( {property_id, first, int(3*i) - first} );
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]);
357 groups.push_back( {property_id, first, int(3 * remap.size()) - first} );
359 std::swap(m_indices, indices);
365 int property_id= triangle_properties[remap[0]];
368 std::vector<vec3> positions;
369 std::vector<vec2> texcoords;
370 std::vector<vec3> normals;
371 std::vector<vec4> colors;
373 for(
unsigned i= 0; i < remap.size(); i++)
375 int id= triangle_properties[remap[i]];
376 if(
id != property_id)
378 groups.push_back( {property_id, first, int(3*i) - first} );
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]);
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]);
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]);
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]);
409 groups.push_back( {property_id, first, int(3 * remap.size()) - first} );
411 std::swap(m_positions, positions);
412 std::swap(m_texcoords, texcoords);
413 std::swap(m_normals, normals);
414 std::swap(m_colors, colors);
423 if(m_primitives != GL_TRIANGLES)
426 if(m_indices.size() > 0)
427 return int(m_indices.size() / 3);
429 return int(m_positions.size() / 3);
434 unsigned int a, b, c;
435 if(m_indices.size() > 0)
437 assert((
size_t)
id*3+2 < m_indices.size());
439 b= m_indices[
id*3 +1];
440 c= m_indices[
id*3 +2];
444 assert((
size_t)
id*3+2 < m_positions.size());
455 if(m_normals.size() == m_positions.size())
472 if(m_texcoords.size() == m_positions.size())
491 if(m_positions.size() < 1)
494 pmin=
Point(m_positions[0]);
497 for(
unsigned i= 1; i < m_positions.size(); i++)
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) );
510 void copy( GLenum target,
const size_t offset,
const size_t length,
const void *data )
513 glGenBuffers(1, &m_buffer);
516 glBindBuffer(GL_COPY_READ_BUFFER, m_buffer);
519 m_size= (length / (16*1024*1024) + 1) * (16*1024*1024);
520 assert(m_size >= length);
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));
528 glBufferSubData(GL_COPY_READ_BUFFER, 0, length, data);
530 glCopyBufferSubData(GL_COPY_READ_BUFFER, target, 0, offset, length);
542 glDeleteBuffers(1, &m_buffer);
563GLuint
Mesh::create_buffers(
const bool use_texcoord,
const bool use_normal,
const bool use_color,
const bool use_material_index )
569 glGenVertexArrays(1, &m_vao);
570 glBindVertexArray(m_vao);
574 if(use_texcoord && has_texcoord())
576 if(use_normal && has_normal())
578 if(use_color && has_color())
580 if(use_material_index && has_material_index())
581 m_vertex_buffer_size+= m_positions.size() *
sizeof(
unsigned char);
583 if(m_vertex_buffer_size == 0)
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);
593 if(m_index_buffer_size)
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);
601 update_buffers(use_texcoord, use_normal, use_color, use_material_index);
608 return create_buffers( has_texcoord(), has_normal(), has_color(), has_material_index() );
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; }
623int Mesh::update_buffers(
const bool use_texcoord,
const bool use_normal,
const bool use_color,
const bool use_material_index )
626 assert(m_buffer > 0);
627 if(!m_update_buffers)
633 glBindVertexArray(m_vao);
634 glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
638 if(use_texcoord && has_texcoord())
640 if(use_normal && has_normal())
642 if(use_color && has_color())
644 if(use_material_index && has_material_index())
645 size+= m_positions.size() *
sizeof(
unsigned char);
647 if(size != m_vertex_buffer_size)
649 m_vertex_buffer_size= size;
650 glBufferData(GL_ARRAY_BUFFER, size,
nullptr, GL_STATIC_DRAW);
659 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (
const void *) offset);
660 glEnableVertexAttribArray(0);
662 if(use_texcoord && has_texcoord())
664 offset= offset + size;
669 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (
const void *) offset);
670 glEnableVertexAttribArray(1);
673 if(use_normal && has_normal())
675 offset= offset + size;
680 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (
const void *) offset);
681 glEnableVertexAttribArray(2);
684 if(use_color && has_color())
686 offset= offset + size;
691 glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, (
const void *) offset);
692 glEnableVertexAttribArray(3);
695 if(use_material_index && has_material_index())
699 offset= offset + size;
700 size= m_positions.size() *
sizeof(
unsigned char);
703 std::vector<unsigned char> buffer(m_positions.size());
708 for(
unsigned triangle_id= 0; triangle_id < m_triangle_materials.size(); triangle_id++)
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];
716 buffer[a]= material_id;
717 buffer[b]= material_id;
718 buffer[c]= material_id;
723 for(
unsigned triangle_id= 0; triangle_id < m_triangle_materials.size(); triangle_id++)
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;
731 buffer[a]= material_id;
732 buffer[b]= material_id;
733 buffer[c]= material_id;
738 update.
copy(GL_ARRAY_BUFFER, offset, size, buffer.data());
740 glVertexAttribIPointer(4, 1, GL_UNSIGNED_BYTE, 0, (
const void *) offset);
741 glEnableVertexAttribArray(4);
746 if(size != m_index_buffer_size)
749 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer);
753 m_update_buffers=
false;
760 draw(0,
int(m_indices.size()), program);
762 draw(0,
int(m_positions.size()), program);
765void Mesh::draw(
const int first,
const int count,
const GLuint program )
769 printf(
"[oops] no program... can't draw !!\n");
776 create_buffers(has_texcoord(), has_normal(), has_color(), has_material_index());
780 update_buffers(has_texcoord(), has_normal(), has_color(), has_material_index());
782 glBindVertexArray(m_vao);
786 char label[2048]= { 0 };
787 #ifdef GL_VERSION_4_3
790 glGetObjectLabel(GL_PROGRAM, program,
sizeof(tmp),
nullptr, tmp);
791 sprintf(label,
"program( %u '%s' )", program, tmp);
794 sprintf(label,
"program( %u )", program);
799 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) ¤t);
800 if(current != program)
801 printf(
"[oops] %s: not active... undefined draw !!\n", label);
806 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n);
814 glGetActiveAttrib(program,
index,
sizeof(name),
nullptr, &glsl_size, &glsl_type, name);
816 GLint location= glGetAttribLocation(program, name);
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);
824 else if(location == 1)
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);
831 else if(location == 2)
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);
838 else if(location == 3)
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);
845 else if(location == 4)
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);
856 if(m_indices.size() > 0)
857 glDrawElements(m_primitives, count, GL_UNSIGNED_INT, (
void *) (first *
sizeof(
unsigned)));
859 glDrawArrays(m_primitives, first, count);
866 glBindVertexArray(vao);
870 glGetIntegerv( GL_MAX_VERTEX_ATTRIBS, &n);
873 for(
int i= 0; i < n; i++)
876 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &status);
877 if(status != GL_FALSE)
880 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, (GLint *) &buffer);
881 glDeleteBuffers(1, &buffer);
887 glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint *) &buffer);
888 glDeleteBuffers(1, &buffer);
890 glBindVertexArray(0);
891 glDeleteVertexArrays(1, &vao);
std::size_t texcoord_buffer_size() const
renvoie la taille (en octets) du texcoord buffer.
const float * vertex_buffer() const
renvoie l'adresse de la position du premier sommet. permet de construire les vertex buffers openGL....
unsigned int vertex(const vec3 &p)
insere un sommet de position p, et ses attributs (s'ils sont definis par color(), texcoord(),...
Mesh & texcoord(const vec2 &uv)
definit les coordonnees de texture du prochain sommet.
Mesh()
constructeur par defaut.
const std::vector< unsigned int > & material_indices() const
renvoie les indices des matieres des triangles.
Mesh & material(const unsigned int id)
definit la matiere du prochain triangle. id est l'indice d'une matiere ajoutee dans materials(),...
Mesh & restart_strip()
demarre un nouveau strip. a utiliser avec un objet composes de GL_TRIANGLE_STRIP, doit aussi fonction...
std::vector< TriangleGroup > groups()
renvoie les groupes de triangles de meme matiere. re-organise les triangles. permet d'afficher l'obje...
void bounds(Point &pmin, Point &pmax) const
renvoie min et max les coordonnees des extremites des positions des sommets de l'objet (boite engloba...
Color default_color() const
renvoie la couleur par defaut du mesh, utilisee si les sommets n'ont pas de couleur associee.
std::size_t index_buffer_size() const
renvoie la taille (en octets) de l'index buffer.
void draw(const GLuint program)
dessine l'objet avec un shader program.
int create(const GLenum primitives)
construit les objets openGL.
void clear()
vide la description.
Mesh & triangle(const unsigned int a, const unsigned int b, const unsigned int c)
GLuint create_buffers()
construit les buffers et le vertex array object necessaires pour dessiner l'objet avec openGL....
const float * color_buffer() const
renvoie l'adresse de la couleur du premier sommet. par convention, la couleur est un vec4,...
Mesh & normal(const vec3 &n)
definit la normale du prochain sommet.
const float * texcoord_buffer() const
renvoie l'adresse des coordonnees de textures du premier sommet. par convention, c'est un vec2,...
int triangle_count() const
renvoie le nombre de triangles.
std::size_t vertex_buffer_size() const
renvoie la longueur (en octets) du vertex buffer.
const Material & triangle_material(const unsigned int id) const
renvoie la matiere d'un triangle.
int triangle_material_index(const unsigned int id) const
renvoie l'indice de la matiere d'un triangle.
const void * index_buffer() const
renvoie l'adresse du premier indice du premier triangle. par convention c'est un uint,...
Mesh & index(const int a)
GLenum primitives() const
renvoie le type de primitives.
void release()
detruit les objets openGL.
Mesh & color(const vec4 &c)
definit la couleur du prochain sommet.
Mesh & triangle_last(const int a, const int b, const int c)
bool has_position() const
verifie que les attributs sont decrits de maniere coherente.
const float * normal_buffer() const
renvoie l'adresse de la normale du premier sommet. par convention, la normale est un vec3,...
const Materials & materials() const
renvoie la description des matieres.
std::size_t normal_buffer_size() const
renvoie la longueur (en octets) du normal buffer.
std::size_t color_buffer_size() const
renvoie la taille (en octets) du color buffer.
buffer unique de copie / mise a jour des vertex buffers statiques. singleton. tous les meshs utilisen...
void release()
detruit le buffer.
void copy(GLenum target, const size_t offset, const size_t length, const void *data)
transfere les donnees dans un buffer statique.
~UpdateBuffer()
detruit le buffer.
UpdateBuffer()
constructeur prive. singleton.
static UpdateBuffer & manager()
acces au singleton.
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().
Color White()
utilitaire. renvoie une couleur blanche.
Vector normalize(const Vector &v)
renvoie un vecteur unitaire / longueur == 1.
Vector cross(const Vector &u, const Vector &v)
renvoie le produit vectoriel de 2 vecteurs.
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...
@ USE_COLOR
inclut l'attribut couleur dans les buffers.
@ USE_TEXCOORD
inclut l'attribut coordonnees de texture dans les buffers.
@ USE_MATERIAL_INDEX
inclut l'attribut indice de matiere dans les buffers.
@ USE_NORMAL
inclut l'attribut normale dans les buffers.
representation d'une couleur (rgba) transparente ou opaque.
representation d'un point 3d.
representation d'un triangle.
representation d'un vecteur 3d.
vecteur generique, utilitaire.
vecteur generique, utilitaire.
vecteur generique 4d, ou 3d homogene, utilitaire.