22 Mesh::Mesh(
const GLenum primitives,
const std::vector<vec3>& positions ) :
23 m_positions(), m_texcoords(), m_normals(), m_colors(), m_indices(),
24 m_color(
White()), m_primitives(GL_POINTS), m_vao(0), m_buffer(0), m_index_buffer(0), m_vertex_buffer_size(0), m_index_buffer_size(0), m_update_buffers(false)
27 m_positions= positions;
28 m_update_buffers=
true;
31 Mesh::Mesh(
const GLenum primitives,
const std::vector<vec3>& positions,
const std::vector<unsigned>& indices ) :
32 m_positions(), m_texcoords(), m_normals(), m_colors(), m_indices(),
33 m_color(
White()), m_primitives(GL_POINTS), m_vao(0), m_buffer(0), m_index_buffer(0), m_vertex_buffer_size(0), m_index_buffer_size(0), m_update_buffers(false)
36 m_positions= positions;
38 m_update_buffers=
true;
41 Mesh::Mesh(
const GLenum primitives,
const std::vector<vec3>& positions,
42 const std::vector<vec2>& texcoords,
43 const std::vector<vec3>&
normals,
44 const std::vector<vec4>& colors,
45 const std::vector<unsigned>& indices ) :
46 m_positions(), m_texcoords(), m_normals(), m_colors(), m_indices(),
47 m_color(
White()), m_primitives(GL_POINTS), m_vao(0), m_buffer(0), m_index_buffer(0), m_vertex_buffer_size(0), m_index_buffer_size(0), m_update_buffers(false)
50 m_positions= positions;
52 m_update_buffers=
true;
55 if(texcoords.size() > 0 && texcoords.size() == positions.size())
56 m_texcoords= texcoords;
59 if(colors.size() > 0 && colors.size() == positions.size())
66 printf(
"mesh release %d\n", m_vao);
68 glDeleteVertexArrays(1, &m_vao);
69 glDeleteBuffers(1, &m_buffer);
70 glDeleteBuffers(1, &m_index_buffer);
82 if(m_colors.size() <= m_positions.size())
83 m_colors.push_back(
color);
85 m_colors.back()=
color;
86 m_update_buffers=
true;
92 if(m_normals.size() <= m_positions.size())
93 m_normals.push_back(
normal);
96 m_update_buffers=
true;
102 if(m_texcoords.size() <= m_positions.size())
103 m_texcoords.push_back(uv);
105 m_texcoords.back()= uv;
106 m_update_buffers=
true;
113 m_update_buffers=
true;
114 m_positions.push_back(position);
117 if(m_texcoords.size() > 0 && m_texcoords.size() != m_positions.size())
118 m_texcoords.push_back(m_texcoords.back());
119 if(m_normals.size() > 0 && m_normals.size() != m_positions.size())
120 m_normals.push_back(m_normals.back());
121 if(m_colors.size() > 0 && m_colors.size() != m_positions.size())
122 m_colors.push_back(m_colors.back());
125 if(m_triangle_materials.size() > 0 &&
int(m_triangle_materials.size()) <
triangle_count())
126 m_triangle_materials.push_back(m_triangle_materials.back());
128 unsigned int index= m_positions.size() -1;
134 case GL_TRIANGLE_STRIP:
135 case GL_TRIANGLE_FAN:
136 m_indices.push_back(
index);
149 assert(
id < m_colors.size());
150 m_update_buffers=
true;
157 assert(
id < m_normals.size());
158 m_update_buffers=
true;
165 assert(
id < m_texcoords.size());
166 m_update_buffers=
true;
173 assert(
id < m_positions.size());
174 m_update_buffers=
true;
180 m_update_buffers=
true;
188 m_triangle_materials.clear();
194 assert(a < m_positions.size());
195 assert(b < m_positions.size());
196 assert(c < m_positions.size());
197 m_update_buffers=
true;
198 m_indices.push_back(a);
199 m_indices.push_back(b);
200 m_indices.push_back(c);
203 if(m_triangle_materials.size() > 0 &&
int(m_triangle_materials.size()) <
triangle_count())
204 m_triangle_materials.push_back(m_triangle_materials.back());
206 m_update_buffers=
true;
215 m_update_buffers=
true;
216 m_indices.push_back(
int(m_positions.size()) + a);
217 m_indices.push_back(
int(m_positions.size()) + b);
218 m_indices.push_back(
int(m_positions.size()) + c);
221 if(m_triangle_materials.size() > 0 &&
int(m_triangle_materials.size()) <
triangle_count())
222 m_triangle_materials.push_back(m_triangle_materials.back());
224 m_update_buffers=
true;
230 m_update_buffers=
true;
231 m_indices.push_back(~0u);
233 glPrimitiveRestartIndex(~0u);
234 glEnable(GL_PRIMITIVE_RESTART);
236 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
244 m_indices.push_back(
int(m_positions.size()) + a);
245 else if(a <
int(m_positions.size()))
246 m_indices.push_back(a);
249 printf(
"[error] Mesh::index(): invalid index...\n");
254 if(m_triangle_materials.size() > 0 &&
int(m_triangle_materials.size()) <
triangle_count())
255 m_triangle_materials.push_back(m_triangle_materials.back());
257 m_update_buffers=
true;
280 m_triangle_materials.push_back(
id);
282 m_triangle_materials.back()= id;
283 m_update_buffers=
true;
289 return m_triangle_materials;
294 assert((
size_t)
id < m_triangle_materials.size());
295 return m_triangle_materials[id];
300 assert((
size_t)
id < m_triangle_materials.size());
301 return m_materials.
material(m_triangle_materials[
id]);
307 return groups(m_triangle_materials);
310 std::vector<TriangleGroup>
Mesh::groups(
const std::vector<unsigned int>& triangle_properties )
312 if(m_primitives != GL_TRIANGLES)
319 return { {0, 0, int(m_indices.size())} };
321 return { {0, 0, int(m_positions.size())} };
326 for(
unsigned i= 0; i < remap.size(); i++)
331 const std::vector<unsigned int>& properties;
333 triangle_sort(
const std::vector<unsigned int>& _properties ) : properties(_properties) {}
335 bool operator() (
const int& a,
const int& b )
const
337 return properties[a] < properties[b];
341 std::stable_sort(remap.begin(), remap.end(), triangle_sort(triangle_properties));
344 std::vector<TriangleGroup>
groups;
348 int property_id= triangle_properties[remap[0]];
351 std::vector<unsigned int> indices;
353 for(
unsigned i= 0; i < remap.size(); i++)
355 int id= triangle_properties[remap[i]];
356 if(
id != property_id)
358 groups.push_back( {property_id, first, int(3*i) - first} );
363 indices.push_back(m_indices[3*remap[i]]);
364 indices.push_back(m_indices[3*remap[i]+1]);
365 indices.push_back(m_indices[3*remap[i]+2]);
371 groups.push_back( {property_id, first, int(3 * remap.size()) - first} );
373 std::swap(m_indices, indices);
379 int property_id= triangle_properties[remap[0]];
382 std::vector<vec3> positions;
383 std::vector<vec2> texcoords;
384 std::vector<vec3> normals;
385 std::vector<vec4> colors;
387 for(
unsigned i= 0; i < remap.size(); i++)
389 int id= triangle_properties[remap[i]];
390 if(
id != property_id)
392 groups.push_back( {property_id, first, int(3*i) - first} );
397 positions.push_back(m_positions[3*remap[i]]);
398 positions.push_back(m_positions[3*remap[i]+1]);
399 positions.push_back(m_positions[3*remap[i]+2]);
402 texcoords.push_back(m_texcoords[3*remap[i]]);
403 texcoords.push_back(m_texcoords[3*remap[i]+1]);
404 texcoords.push_back(m_texcoords[3*remap[i]+2]);
408 normals.push_back(m_normals[3*remap[i]]);
409 normals.push_back(m_normals[3*remap[i]+1]);
410 normals.push_back(m_normals[3*remap[i]+2]);
414 colors.push_back(m_colors[3*remap[i]]);
415 colors.push_back(m_colors[3*remap[i]+1]);
416 colors.push_back(m_colors[3*remap[i]+2]);
423 groups.push_back( {property_id, first, int(3 * remap.size()) - first} );
425 std::swap(m_positions, positions);
426 std::swap(m_texcoords, texcoords);
428 std::swap(m_colors, colors);
437 if(m_primitives != GL_TRIANGLES)
440 if(m_indices.size() > 0)
441 return int(m_indices.size() / 3);
443 return int(m_positions.size() / 3);
448 unsigned int a, b, c;
449 if(m_indices.size() > 0)
451 assert((
size_t)
id*3+2 < m_indices.size());
453 b= m_indices[
id*3 +1];
454 c= m_indices[
id*3 +2];
458 assert((
size_t)
id*3+2 < m_positions.size());
469 if(m_normals.size() == m_positions.size())
486 if(m_texcoords.size() == m_positions.size())
505 if(m_positions.size() < 1)
508 pmin=
Point(m_positions[0]);
511 for(
unsigned i= 1; i < m_positions.size(); i++)
513 vec3 p= m_positions[i];
528 void copy( GLenum target,
const size_t offset,
const size_t length,
const void *data )
531 glGenBuffers(1, &m_buffer);
534 glBindBuffer(GL_COPY_READ_BUFFER, m_buffer);
537 m_size= (
length / (16*1024*1024) + 1) * (16*1024*1024);
541 glBufferData(GL_COPY_READ_BUFFER, m_size,
nullptr, GL_DYNAMIC_DRAW);
542 printf(
"[UpdateBuffer] allocate %dMo staging buffer...\n",
int(m_size / 1024 / 1024));
546 glBufferSubData(GL_COPY_READ_BUFFER, 0,
length, data);
548 glCopyBufferSubData(GL_COPY_READ_BUFFER, target, 0, offset,
length);
560 glDeleteBuffers(1, &m_buffer);
581 GLuint
Mesh::create_buffers(
const bool use_texcoord,
const bool use_normal,
const bool use_color,
const bool use_material_index )
583 if(m_positions.size() == 0)
587 if(use_texcoord && !has_texcoord())
588 printf(
"[oops] mesh: no texcoord array...\n");
589 if(use_normal && !has_normal())
590 printf(
"[oops] mesh: no normal array...\n");
591 if(use_color && !has_color())
592 printf(
"[oops] mesh: no color array...\n");
593 if(use_material_index && !has_material_index())
594 printf(
"[oops] mesh: no material index array...\n");
602 glGenVertexArrays(1, &m_vao);
603 glBindVertexArray(m_vao);
607 if(use_texcoord && has_texcoord())
609 if(use_normal && has_normal())
611 if(use_color && has_color())
613 if(use_material_index && has_material_index())
614 m_vertex_buffer_size+= m_positions.size() *
sizeof(
unsigned char);
617 glGenBuffers(1, &m_buffer);
618 glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
619 glBufferData(GL_ARRAY_BUFFER, m_vertex_buffer_size,
nullptr, GL_STATIC_DRAW);
623 if(m_index_buffer_size)
625 glGenBuffers(1, &m_index_buffer);
626 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer);
627 glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer_size,
index_buffer(), GL_STATIC_DRAW);
631 update_buffers(use_texcoord, use_normal, use_color, use_material_index);
636 int Mesh::update_buffers(
const bool use_texcoord,
const bool use_normal,
const bool use_color,
const bool use_material_index )
639 assert(m_buffer > 0);
640 if(!m_update_buffers)
646 glBindVertexArray(m_vao);
647 glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
651 if(use_texcoord && has_texcoord())
653 if(use_normal && has_normal())
655 if(use_color && has_color())
657 if(use_material_index && has_material_index())
658 size+= m_positions.size() *
sizeof(
unsigned char);
660 if(size != m_vertex_buffer_size)
662 m_vertex_buffer_size= size;
663 glBufferData(GL_ARRAY_BUFFER, size,
nullptr, GL_STATIC_DRAW);
672 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (
const void *) offset);
673 glEnableVertexAttribArray(0);
675 if(use_texcoord && has_texcoord())
677 offset= offset + size;
682 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (
const void *) offset);
683 glEnableVertexAttribArray(1);
686 if(use_normal && has_normal())
688 offset= offset + size;
693 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (
const void *) offset);
694 glEnableVertexAttribArray(2);
697 if(use_color && has_color())
699 offset= offset + size;
704 glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, (
const void *) offset);
705 glEnableVertexAttribArray(3);
708 if(use_material_index && has_material_index())
712 offset= offset + size;
713 size= m_positions.size() *
sizeof(
unsigned char);
716 std::vector<unsigned char> buffer(m_positions.size());
721 for(
int triangle_id= 0; triangle_id < int(m_triangle_materials.size()); triangle_id++)
723 int material_id= m_triangle_materials[triangle_id];
724 assert(triangle_id*3+2 <
int(m_indices.size()));
725 unsigned a= m_indices[triangle_id*3];
726 unsigned b= m_indices[triangle_id*3 +1];
727 unsigned c= m_indices[triangle_id*3 +2];
729 buffer[a]= material_id;
730 buffer[b]= material_id;
731 buffer[c]= material_id;
736 for(
int triangle_id= 0; triangle_id < int(m_triangle_materials.size()); triangle_id++)
738 int material_id= m_triangle_materials[triangle_id];
739 assert(triangle_id*3+2 <
int(m_positions.size()));
740 unsigned a= triangle_id*3;
741 unsigned b= triangle_id*3 +1;
742 unsigned c= triangle_id*3 +2;
744 buffer[a]= material_id;
745 buffer[b]= material_id;
746 buffer[c]= material_id;
751 update.
copy(GL_ARRAY_BUFFER, offset, size, buffer.data());
753 glVertexAttribIPointer(4, 1, GL_UNSIGNED_BYTE, 0, (
const void *) offset);
754 glEnableVertexAttribArray(4);
759 if(size != m_index_buffer_size)
762 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer);
766 m_update_buffers=
false;
770 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 )
773 draw(0,
int(m_indices.size()), program, use_position, use_texcoord, use_normal, use_color, use_material_index);
775 draw(0,
int(m_positions.size()), program, use_position, use_texcoord, use_normal, use_color, use_material_index);
778 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 )
782 printf(
"[oops] no program... can't draw !!\n");
789 create_buffers(has_texcoord(), has_normal(), has_color(), has_material_index());
793 update_buffers(has_texcoord(), has_normal(), has_color(), has_material_index());
795 glBindVertexArray(m_vao);
799 char label[2048]= { 0 };
800 #ifdef GL_VERSION_4_3
803 glGetObjectLabel(GL_PROGRAM, program,
sizeof(tmp),
nullptr, tmp);
804 sprintf(
label,
"program( %u '%s' )", program, tmp);
807 sprintf(
label,
"program( %u )", program);
812 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) ¤t);
813 if(current != program)
814 printf(
"[oops] %s: not active... undefined draw !!\n",
label);
819 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n);
827 glGetActiveAttrib(program,
index,
sizeof(name),
nullptr, &glsl_size, &glsl_type, name);
829 GLint location= glGetAttribLocation(program, name);
833 printf(
"[oops] position attribute '%s' in %s: no data... undefined draw !!\n", name,
label);
834 if(glsl_size != 1 || glsl_type != GL_FLOAT_VEC3)
835 printf(
"[oops] position attribute '%s' is not declared as a vec3 in %s... undefined draw !!\n", name,
label);
837 else if(location == 1)
839 if(!use_texcoord || !has_texcoord())
840 printf(
"[oops] texcoord attribute '%s' in %s: no data... undefined draw !!\n", name,
label);
841 if(glsl_size != 1 || glsl_type != GL_FLOAT_VEC2)
842 printf(
"[oops] texcoord attribute '%s' is not declared as a vec2 in %s... undefined draw !!\n", name,
label);
844 else if(location == 2)
846 if(!use_normal || !has_normal())
847 printf(
"[oops] normal attribute '%s' in %s: no data... undefined draw !!\n", name,
label);
848 if(glsl_size != 1 || glsl_type != GL_FLOAT_VEC3)
849 printf(
"[oops] attribute '%s' is not declared as a vec3 in %s... undefined draw !!\n", name,
label);
851 else if(location == 3)
853 if(!use_color || !has_color())
854 printf(
"[oops] color attribute '%s' in %s: no data... undefined draw !!\n", name,
label);
855 if(glsl_size != 1 || glsl_type != GL_FLOAT_VEC4)
856 printf(
"[oops] attribute '%s' is not declared as a vec4 in %s... undefined draw !!\n", name,
label);
858 else if(location == 4)
860 if(!use_material_index || !has_material_index())
861 printf(
"[oops] material_index attribute '%s' in %s: no data... undefined draw !!\n", name,
label);
862 if(glsl_size != 1 || glsl_type != GL_UNSIGNED_INT)
863 printf(
"[oops] attribute '%s' is not declared as a uint in %s... undefined draw !!\n", name,
label);
869 if(m_indices.size() > 0)
870 glDrawElements(m_primitives, n, GL_UNSIGNED_INT, (
void *) (first *
sizeof(
unsigned)));
872 glDrawArrays(m_primitives, first, n);
representation d'un objet / maillage.
std::size_t texcoord_buffer_size() const
renvoie la taille (en octets) du texcoord buffer.
const float * color_buffer() const
renvoie l'adresse de la couleur du premier sommet. par convention, la couleur est un vec4,...
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 float * vertex_buffer() const
renvoie l'adresse de la position du premier sommet. permet de construire les vertex buffers openGL....
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....
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.
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.
std::size_t index_buffer_size() const
renvoie la taille (en octets) de l'index buffer.
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)
Mesh & normal(const vec3 &n)
definit la normale du prochain sommet.
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 float * texcoord_buffer() const
renvoie l'adresse des coordonnees de textures du premier sommet. par convention, c'est un vec2,...
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 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.
const float * normal_buffer() const
renvoie l'adresse de la normale du premier sommet. par convention, la normale est un vec3,...
buffer unique de copie / mise a jour des vertex buffers statiques. singleton. tous les meshs utilisen...
void release()
detruit le buffer.
static UpdateBuffer & manager()
acces au singleton.
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.
void label(Widgets &w, const char *format,...)
cree un texte. meme fonctionnement que printf().
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.
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,...
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,...
Vector normalize(const Vector &v)
renvoie un vecteur unitaire / longueur == 1.
float length(const Vector &v)
renvoie la longueur d'un vecteur.
Vector cross(const Vector &u, const Vector &v)
renvoie le produit vectoriel de 2 vecteurs.
void normals(MeshData &data)
(re-) calcule les normales des sommets. utiliser avant les reindexations, cf indices() et vertices().
representation d'une couleur (rgba) transparente ou opaque.
const Material & material(const int id) const
renvoie la ieme matiere.
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.