22 int Mesh::create(
const GLenum primitives,
const std::vector<vec3>& positions )
26 m_positions= positions;
30 int Mesh::create(
const GLenum primitives,
const std::vector<vec3>& positions,
const std::vector<unsigned>& indices )
34 m_positions= positions;
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 )
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;
51 m_positions= positions;
53 m_texcoords= texcoords;
64 printf(
"mesh release %d\n", m_vao);
66 glDeleteVertexArrays(1, &m_vao);
67 glDeleteBuffers(1, &m_buffer);
68 glDeleteBuffers(1, &m_index_buffer);
80 if(m_colors.size() <= m_positions.size())
81 m_colors.push_back(
color);
83 m_colors.back()=
color;
84 m_update_buffers=
true;
90 if(m_normals.size() <= m_positions.size())
91 m_normals.push_back(
normal);
94 m_update_buffers=
true;
100 if(m_texcoords.size() <= m_positions.size())
101 m_texcoords.push_back(uv);
103 m_texcoords.back()= uv;
104 m_update_buffers=
true;
111 m_update_buffers=
true;
112 m_positions.push_back(position);
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());
123 if(m_triangle_materials.size() > 0 &&
int(m_triangle_materials.size()) <
triangle_count())
124 m_triangle_materials.push_back(m_triangle_materials.back());
126 unsigned int index= m_positions.size() -1;
132 case GL_TRIANGLE_STRIP:
133 case GL_TRIANGLE_FAN:
134 m_indices.push_back(
index);
147 assert(
id < m_colors.size());
148 m_update_buffers=
true;
155 assert(
id < m_normals.size());
156 m_update_buffers=
true;
163 assert(
id < m_texcoords.size());
164 m_update_buffers=
true;
171 assert(
id < m_positions.size());
172 m_update_buffers=
true;
178 m_update_buffers=
true;
186 m_triangle_materials.clear();
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);
201 if(m_triangle_materials.size() > 0 &&
int(m_triangle_materials.size()) <
triangle_count())
202 m_triangle_materials.push_back(m_triangle_materials.back());
204 m_update_buffers=
true;
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);
219 if(m_triangle_materials.size() > 0 &&
int(m_triangle_materials.size()) <
triangle_count())
220 m_triangle_materials.push_back(m_triangle_materials.back());
222 m_update_buffers=
true;
228 m_update_buffers=
true;
229 m_indices.push_back(~0u);
231 glPrimitiveRestartIndex(~0u);
232 glEnable(GL_PRIMITIVE_RESTART);
234 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
242 m_indices.push_back(
int(m_positions.size()) + a);
243 else if(a <
int(m_positions.size()))
244 m_indices.push_back(a);
247 printf(
"[error] Mesh::index(): invalid index...\n");
252 if(m_triangle_materials.size() > 0 &&
int(m_triangle_materials.size()) <
triangle_count())
253 m_triangle_materials.push_back(m_triangle_materials.back());
255 m_update_buffers=
true;
278 m_triangle_materials.push_back(
id);
280 m_triangle_materials.back()= id;
281 m_update_buffers=
true;
287 return m_triangle_materials;
292 assert((
size_t)
id < m_triangle_materials.size());
293 return m_triangle_materials[id];
298 assert((
size_t)
id < m_triangle_materials.size());
299 return m_materials.
material(m_triangle_materials[
id]);
305 return groups(m_triangle_materials);
308 std::vector<TriangleGroup>
Mesh::groups(
const std::vector<unsigned int>& triangle_properties )
310 if(m_primitives != GL_TRIANGLES)
317 return { {0, 0, int(m_indices.size())} };
319 return { {0, 0, int(m_positions.size())} };
324 for(
unsigned i= 0; i < remap.size(); i++)
329 const std::vector<unsigned int>& properties;
331 triangle_sort(
const std::vector<unsigned int>& _properties ) : properties(_properties) {}
333 bool operator() (
const int& a,
const int& b )
const
335 return properties[a] < properties[b];
339 std::stable_sort(remap.begin(), remap.end(), triangle_sort(triangle_properties));
342 std::vector<TriangleGroup>
groups;
346 int property_id= triangle_properties[remap[0]];
349 std::vector<unsigned int> indices;
351 for(
unsigned i= 0; i < remap.size(); i++)
353 int id= triangle_properties[remap[i]];
354 if(
id != property_id)
356 groups.push_back( {property_id, first, int(3*i) - first} );
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]);
369 groups.push_back( {property_id, first, int(3 * remap.size()) - first} );
371 std::swap(m_indices, indices);
377 int property_id= triangle_properties[remap[0]];
380 std::vector<vec3> positions;
381 std::vector<vec2> texcoords;
382 std::vector<vec3> normals;
383 std::vector<vec4> colors;
385 for(
unsigned i= 0; i < remap.size(); i++)
387 int id= triangle_properties[remap[i]];
388 if(
id != property_id)
390 groups.push_back( {property_id, first, int(3*i) - first} );
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]);
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]);
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]);
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]);
421 groups.push_back( {property_id, first, int(3 * remap.size()) - first} );
423 std::swap(m_positions, positions);
424 std::swap(m_texcoords, texcoords);
426 std::swap(m_colors, colors);
435 if(m_primitives != GL_TRIANGLES)
438 if(m_indices.size() > 0)
439 return int(m_indices.size() / 3);
441 return int(m_positions.size() / 3);
446 unsigned int a, b, c;
447 if(m_indices.size() > 0)
449 assert((
size_t)
id*3+2 < m_indices.size());
451 b= m_indices[
id*3 +1];
452 c= m_indices[
id*3 +2];
456 assert((
size_t)
id*3+2 < m_positions.size());
467 if(m_normals.size() == m_positions.size())
484 if(m_texcoords.size() == m_positions.size())
503 if(m_positions.size() < 1)
506 pmin=
Point(m_positions[0]);
509 for(
unsigned i= 1; i < m_positions.size(); i++)
511 vec3 p= m_positions[i];
526 void copy( GLenum target,
const size_t offset,
const size_t length,
const void *data )
529 glGenBuffers(1, &m_buffer);
532 glBindBuffer(GL_COPY_READ_BUFFER, m_buffer);
535 m_size= (
length / (16*1024*1024) + 1) * (16*1024*1024);
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));
544 glBufferSubData(GL_COPY_READ_BUFFER, 0,
length, data);
546 glCopyBufferSubData(GL_COPY_READ_BUFFER, target, 0, offset,
length);
558 glDeleteBuffers(1, &m_buffer);
579 GLuint
Mesh::create_buffers(
const bool use_texcoord,
const bool use_normal,
const bool use_color,
const bool use_material_index )
581 if(m_positions.size() == 0)
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");
600 glGenVertexArrays(1, &m_vao);
601 glBindVertexArray(m_vao);
605 if(use_texcoord && has_texcoord())
607 if(use_normal && has_normal())
609 if(use_color && has_color())
611 if(use_material_index && has_material_index())
612 m_vertex_buffer_size+= m_positions.size() *
sizeof(
unsigned char);
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);
621 if(m_index_buffer_size)
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);
629 update_buffers(use_texcoord, use_normal, use_color, use_material_index);
634 int Mesh::update_buffers(
const bool use_texcoord,
const bool use_normal,
const bool use_color,
const bool use_material_index )
637 assert(m_buffer > 0);
638 if(!m_update_buffers)
644 glBindVertexArray(m_vao);
645 glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
649 if(use_texcoord && has_texcoord())
651 if(use_normal && has_normal())
653 if(use_color && has_color())
655 if(use_material_index && has_material_index())
656 size+= m_positions.size() *
sizeof(
unsigned char);
658 if(size != m_vertex_buffer_size)
660 m_vertex_buffer_size= size;
661 glBufferData(GL_ARRAY_BUFFER, size,
nullptr, GL_STATIC_DRAW);
670 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (
const void *) offset);
671 glEnableVertexAttribArray(0);
673 if(use_texcoord && has_texcoord())
675 offset= offset + size;
680 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (
const void *) offset);
681 glEnableVertexAttribArray(1);
684 if(use_normal && has_normal())
686 offset= offset + size;
691 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (
const void *) offset);
692 glEnableVertexAttribArray(2);
695 if(use_color && has_color())
697 offset= offset + size;
702 glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, (
const void *) offset);
703 glEnableVertexAttribArray(3);
706 if(use_material_index && has_material_index())
710 offset= offset + size;
711 size= m_positions.size() *
sizeof(
unsigned char);
714 std::vector<unsigned char> buffer(m_positions.size());
719 for(
int triangle_id= 0; triangle_id < int(m_triangle_materials.size()); triangle_id++)
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];
727 buffer[a]= material_id;
728 buffer[b]= material_id;
729 buffer[c]= material_id;
734 for(
int triangle_id= 0; triangle_id < int(m_triangle_materials.size()); triangle_id++)
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;
742 buffer[a]= material_id;
743 buffer[b]= material_id;
744 buffer[c]= material_id;
749 update.
copy(GL_ARRAY_BUFFER, offset, size, buffer.data());
751 glVertexAttribIPointer(4, 1, GL_UNSIGNED_BYTE, 0, (
const void *) offset);
752 glEnableVertexAttribArray(4);
757 if(size != m_index_buffer_size)
760 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer);
764 m_update_buffers=
false;
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 )
771 draw(0,
int(m_indices.size()), program, use_position, use_texcoord, use_normal, use_color, use_material_index);
773 draw(0,
int(m_positions.size()), program, use_position, use_texcoord, use_normal, use_color, use_material_index);
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 )
780 printf(
"[oops] no program... can't draw !!\n");
787 create_buffers(has_texcoord(), has_normal(), has_color(), has_material_index());
791 update_buffers(has_texcoord(), has_normal(), has_color(), has_material_index());
793 glBindVertexArray(m_vao);
797 char label[2048]= { 0 };
798 #ifdef GL_VERSION_4_3
801 glGetObjectLabel(GL_PROGRAM, program,
sizeof(tmp),
nullptr, tmp);
802 sprintf(
label,
"program( %u '%s' )", program, tmp);
805 sprintf(
label,
"program( %u )", program);
810 glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) ¤t);
811 if(current != program)
812 printf(
"[oops] %s: not active... undefined draw !!\n",
label);
817 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n);
825 glGetActiveAttrib(program,
index,
sizeof(name),
nullptr, &glsl_size, &glsl_type, name);
827 GLint location= glGetAttribLocation(program, name);
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);
835 else if(location == 1)
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);
842 else if(location == 2)
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);
849 else if(location == 3)
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);
856 else if(location == 4)
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);
867 if(m_indices.size() > 0)
868 glDrawElements(m_primitives, n, GL_UNSIGNED_INT, (
void *) (first *
sizeof(
unsigned)));
870 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.
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().
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.