gKit2 light

- Main Page
- Related Pages
- Modules
- Classes
- Files

- File List
- File Members

mesh.cpp
1
2 #include <cstdio>
3 #include <cassert>
4 #include <string>
5 #include <algorithm>
6
7 #include "program.h"
8 #include "uniforms.h"
9 #include "buffer.h"
10 #include "mesh.h"
11
12
13 int Mesh::create( const GLenum primitives )
14 {
15 m_primitives= primitives;
16 return 0;
17 }
18
19 void Mesh::release( )
20 {
21 if(m_vao)
22 release_vertex_format(m_vao);
23
24 // detruit tous les shaders crees...
25 for(std::unordered_map<unsigned int, GLuint>::iterator it= m_state_map.begin(); it != m_state_map.end(); ++it)
26 if(it->second > 0)
27 release_program(it->second);
28 }
29
30 // definit les attributs du prochain sommet
31 Mesh& Mesh::default_color( const Color& color )
32 {
33 m_color= color;
34 return *this;
35 }
36
37 Mesh& Mesh::color( const vec4& color )
38 {
39 m_colors.push_back(color);
40 return *this;
41 }
42
43 Mesh& Mesh::normal( const vec3& normal )
44 {
45 m_normals.push_back(normal);
46 return *this;
47 }
48
49 Mesh& Mesh::texcoord( const vec2& uv )
50 {
51 m_texcoords.push_back(uv);
52 return *this;
53 }
54
55 // insere un nouveau sommet
56 unsigned int Mesh::vertex( const vec3& position )
57 {
58 m_positions.push_back(position);
59
60 // copie les autres attributs du sommet, uniquement s'ils sont definis
61 if(m_texcoords.size() > 0 && m_texcoords.size() != m_positions.size())
62 m_texcoords.push_back(m_texcoords.back());
63 if(m_normals.size() > 0 && m_normals.size() != m_positions.size())
64 m_normals.push_back(m_normals.back());
65 if(m_colors.size() > 0 && m_colors.size() != m_positions.size())
66 m_colors.push_back(m_colors.back());
67
68 unsigned int index= (unsigned int) m_positions.size() -1;
69 // construction de l'index buffer pour les strip
70 switch(m_primitives)
71 {
72 case GL_LINE_STRIP:
73 case GL_LINE_LOOP:
74 case GL_TRIANGLE_STRIP:
75 case GL_TRIANGLE_FAN:
76 m_indices.push_back(index);
77 break;
78 default:
79 break;
80 }
81
82 // renvoie l'indice du sommet
83 return index;
84 }
85
86 // update attributes
87 Mesh& Mesh::color( const unsigned int id, const vec4& c )
88 {
89 assert(id < m_colors.size());
90 m_update_buffers= true;
91 m_colors[id]= c;
92 return *this;
93 }
94
95 Mesh& Mesh::normal( const unsigned int id, const vec3& n )
96 {
97 assert(id < m_normals.size());
98 m_update_buffers= true;
99 m_normals[id]= n;
100 return *this;
101 }
102
103 Mesh& Mesh::texcoord( const unsigned int id, const vec2& uv )
104 {
105 assert(id < m_texcoords.size());
106 m_update_buffers= true;
107 m_texcoords[id]= uv;
108 return *this;
109 }
110
111 void Mesh::vertex( const unsigned int id, const vec3& p )
112 {
113 assert(id < m_positions.size());
114 m_update_buffers= true;
115 m_positions[id]= p;
116 }
117
118 //
119 Mesh& Mesh::triangle( const unsigned int a, const unsigned int b, const unsigned int c )
120 {
121 assert(a < m_positions.size());
122 assert(b < m_positions.size());
123 assert(c < m_positions.size());
124 m_indices.push_back(a);
125 m_indices.push_back(b);
126 m_indices.push_back(c);
127 return *this;
128 }
129
130 Mesh& Mesh::triangle_last( const int a, const int b, const int c )
131 {
132 assert(a < 0);
133 assert(b < 0);
134 assert(c < 0);
135 m_indices.push_back((int) m_positions.size() + a);
136 m_indices.push_back((int) m_positions.size() + b);
137 m_indices.push_back((int) m_positions.size() + c);
138 return *this;
139 }
140
141 Mesh& Mesh::restart_strip( )
142 {
143 m_indices.push_back(~0u); // ~0u plus grand entier non signe representable
144 #if 1
145 glPrimitiveRestartIndex(~0u);
146 glEnable(GL_PRIMITIVE_RESTART);
147 #else
148 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); // n'existe pas sur mac ?!
149 #endif
150 return *this;
151 }
152
153 void Mesh::bounds( Point& pmin, Point& pmax )
154 {
155 if(m_positions.size() < 1)
156 return;
157
158 pmin= Point(m_positions[0]);
159 pmax= pmin;
160
161 for(unsigned int i= 1; i < (unsigned int) m_positions.size(); i++)
162 {
163 vec3 p= m_positions[i];
164 pmin= Point( std::min(pmin.x, p.x), std::min(pmin.y, p.y), std::min(pmin.z, p.z) );
165 pmax= Point( std::max(pmax.x, p.x), std::max(pmax.y, p.y), std::max(pmax.z, p.z) );
166 }
167 }
168
169 const void *Mesh::attribute_buffer( const unsigned int id ) const
170 {
171 assert(id < 4);
172 switch(id)
173 {
174 case 0: return vertex_buffer(); break;
175 case 1: return texcoord_buffer(); break;
176 case 2: return normal_buffer(); break;
177 case 3: return color_buffer(); break;
178 default: return nullptr;
179 }
180 }
181
182 std::size_t Mesh::attribute_buffer_size( const unsigned int id ) const
183 {
184 assert(id < 4);
185 switch(id)
186 {
187 case 0: return vertex_buffer_size(); break;
188 case 1: return texcoord_buffer_size(); break;
189 case 2: return normal_buffer_size(); break;
190 case 3: return color_buffer_size(); break;
191 default: return 0;
192 }
193 }
194
195
196 GLuint Mesh::create_buffers( const bool use_texcoord, const bool use_normal, const bool use_color )
197 {
198 if(m_positions.size() == 0)
199 return 0;
200
201 // ne creer que les buffers necessaires
202 GLuint vao= create_vertex_format();
203 make_vertex_buffer(vao, 0, 3, GL_FLOAT, vertex_buffer_size(), vertex_buffer());
204
205 if(m_indices.size() > 0)
206 make_index_buffer(vao, index_buffer_size(), index_buffer());
207
208 #if 1
209 if(m_texcoords.size() > 0 && m_texcoords.size() < m_positions.size() && use_texcoord)
210 printf("[error] invalid texcoords array...\n");
211 if(m_normals.size() > 0 && m_normals.size() < m_positions.size() && use_normal)
212 printf("[error] invalid normals array...\n");
213 if(m_colors.size() > 0 && m_colors.size() < m_positions.size() && use_color)
214 printf("[error] invalid colors array...\n");
215 #endif
216
217 if(m_texcoords.size() == m_positions.size() && use_texcoord)
218 make_vertex_buffer(vao, 1, 2, GL_FLOAT, texcoord_buffer_size(), texcoord_buffer());
219 if(m_normals.size() == m_positions.size() && use_normal)
220 make_vertex_buffer(vao, 2, 3, GL_FLOAT, normal_buffer_size(), normal_buffer());
221 if(m_colors.size() == m_positions.size() && use_color)
222 make_vertex_buffer(vao, 3, 4, GL_FLOAT, color_buffer_size(), color_buffer());
223
224 m_update_buffers= false;
225 return vao;
226 }
227
228 int Mesh::update_buffers( const bool use_texcoord, const bool use_normal, const bool use_color )
229 {
230 assert(m_vao > 0);
231 if(!m_update_buffers)
232 return 0;
233
234 glBindVertexArray(m_vao);
235 update_vertex_buffer(m_vao, 0, vertex_buffer_size(), vertex_buffer());
236
237 // ne modifier que les attributs des sommets, pas la topologie / structure du maillage
238 if(m_texcoords.size() == m_positions.size() && use_texcoord)
239 update_vertex_buffer(m_vao, 1, texcoord_buffer_size(), texcoord_buffer());
240 if(m_normals.size() == m_positions.size() && use_normal)
241 update_vertex_buffer(m_vao, 2, normal_buffer_size(), normal_buffer());
242 if(m_colors.size() == m_positions.size() && use_color)
243 update_vertex_buffer(m_vao, 3, color_buffer_size(), color_buffer());
244
245 m_update_buffers= false;
246 return 1;
247 }
248
249
250 GLuint Mesh::create_program( const bool use_texcoord, const bool use_normal, const bool use_color, const bool use_light )
251 {
252 std::string definitions;
253
254 if(m_texcoords.size() == m_positions.size() && use_texcoord)
255 definitions.append("#define USE_TEXCOORD\n");
256 if(m_normals.size() == m_positions.size() && use_normal)
257 definitions.append("#define USE_NORMAL\n");
258 if(m_colors.size() == m_positions.size() && use_color)
259 definitions.append("#define USE_COLOR\n");
260 if(use_light)
261 definitions.append("#define USE_LIGHT\n");
262
263 bool use_mesh_color= (m_primitives == GL_POINTS || m_primitives == GL_LINES || m_primitives == GL_LINE_STRIP || m_primitives == GL_LINE_LOOP);
264 if(!use_mesh_color)
265 return read_program("data/shaders/mesh.glsl", definitions.c_str());
266 else
267 return read_program("data/shaders/mesh_color.glsl", definitions.c_str());
268 }
269
270
271 void Mesh::draw( const Transform& model, const Transform& view, const Transform& projection,
272 const bool use_light, const Point& light, const Color& light_color,
273 const bool use_texture, const GLuint texture )
274 {
275 bool use_texcoord= (m_texcoords.size() == m_positions.size() && texture > 0);
276 bool use_normal= (m_normals.size() == m_positions.size());
277 bool use_color= (m_colors.size() == m_positions.size());
278
279 if(m_vao == 0)
280 // force la creation de tous les buffers
281 m_vao= create_buffers(true, true, true);
282 if(m_update_buffers)
283 update_buffers(true, true, true);
284
285 unsigned int key= 0;
286 if(use_texcoord) key= key | 1;
287 if(use_normal) key= key | 2;
288 if(use_color) key= key | 4;
289 if(use_texture) key= key | 8;
290 if(use_light) key= key | 16;
291
292 if(m_state != key)
293 // recherche un shader deja compile pour ce type de draw
294 m_program= m_state_map[key];
295
296 if(m_program == 0)
297 {
298 // pas de shader pour ce type de draw
299 m_program= create_program(use_texcoord, use_normal, use_color, use_light);
300 program_print_errors(m_program);
301
302 // conserver le shader
303 m_state_map[key]= m_program;
304 }
305
306 // conserve la config du shader selectionne.
307 m_state= key;
308
309 glBindVertexArray(m_vao);
310 glUseProgram(m_program);
311
312 program_uniform(m_program, "mesh_color", default_color());
313
314 Transform mv= view * model;
315 Transform mvp= projection * view * model;
316
317 program_uniform(m_program, "mvpMatrix", mvp);
318 program_uniform(m_program, "mvMatrix", mv);
319 program_uniform(m_program, "normalMatrix", mv.normal()); // transforme les normales dans le repere camera.
320
321 // utiliser une texture, elle ne sera visible que si le mesh a des texcoords...
322 if(texture && use_texcoord && use_texture)
323 program_use_texture(m_program, "diffuse_color", 0, texture);
324
325 if(use_light)
326 {
327 program_uniform(m_program, "light", view(light)); // transforme la position de la source dans le repere camera, comme les normales
328 program_uniform(m_program, "light_color", light_color);
329 }
330
331 if(m_indices.size() > 0)
332 glDrawElements(m_primitives, (GLsizei) m_indices.size(), GL_UNSIGNED_INT, 0);
333 else
334 glDrawArrays(m_primitives, 0, (GLsizei) m_positions.size());
335 }
336
Mesh::restart_strip
Mesh & restart_strip()
demarre un nouveau strip. a utiliser avec un objet composes de GL_TRIANGLE_STRIP, doit aussi fonction...
Definition: mesh.cpp:141
Mesh::normal_buffer
const float * normal_buffer() const
renvoie l'adresse de la normale du premier sommet. par convention, la normale est un vec3...
Definition: mesh.h:200
Mesh::index_buffer_size
std::size_t index_buffer_size() const
renvoie la taille (en octets) de l'index buffer.
Definition: mesh.h:217
Mesh::vertex_buffer
const float * vertex_buffer() const
renvoie l'adresse de la position du premier sommet. permet de construire les vertex buffers openGL...
Definition: mesh.h:195
uniforms.h
Mesh::bounds
void bounds(Point &pmin, Point &pmax)
renvoie min et max les coordonnees des extremites des positions des sommets de l'objet (boite engloba...
Definition: mesh.cpp:153
vec3
vecteur generique, utilitaire.
Definition: vec.h:104
update_vertex_buffer
bool update_vertex_buffer(const GLuint vao, const GLint attribute, const size_t data_size, const void *data)
modifie le contenu d'un vertex buffer associe au vertex format, vao.
Definition: buffer.cpp:121
Transform::normal
Transform normal() const
renvoie la transformation a appliquer aux normales d'un objet transforme par la matrice m...
Definition: mat.cpp:97
Mesh::draw
void draw(const Transform &model, const Transform &view, const Transform &projection, const bool use_light, const Point &light, const Color &light_color, const bool use_texture, const GLuint texture)
Definition: mesh.cpp:271
vec2
vecteur generique, utilitaire.
Definition: vec.h:94
mesh.h
Mesh::normal_buffer_size
std::size_t normal_buffer_size() const
renvoie la longueur (en octets) du normal buffer.
Definition: mesh.h:202
Mesh::color
Mesh & color(const vec4 &c)
definit la couleur du prochain sommet.
Definition: mesh.cpp:37
Mesh
representation d'un objet / maillage.
Definition: mesh.h:88
release_vertex_format
void release_vertex_format(const GLuint vao)
detruit le vertex array vao et les buffers associes, crees par make_vertex_buffer() et make_index_buf...
Definition: buffer.cpp:31
Color
representation d'une couleur (rgba) transparente ou opaque.
Definition: color.h:13
Mesh::vertex_buffer_size
std::size_t vertex_buffer_size() const
renvoie la longueur (en octets) du vertex buffer.
Definition: mesh.h:197
Mesh::triangle
Mesh & triangle(const unsigned int a, const unsigned int b, const unsigned int c)
Definition: mesh.cpp:119
Mesh::create_program
GLuint create_program(const bool use_texcoord=true, const bool use_normal=true, const bool use_color=true, const bool use_light=false)
construit un shader program configure.
Definition: mesh.cpp:250
Mesh::create_buffers
GLuint create_buffers(const bool use_texcoord=true, const bool use_normal=true, const bool use_color=true)
Definition: mesh.cpp:196
Mesh::texcoord_buffer
const float * texcoord_buffer() const
renvoie l'adresse des coordonnees de textures du premier sommet. par convention, c'est un vec2...
Definition: mesh.h:205
Mesh::vertex
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:56
vec4
vecteur generique 4d, ou 3d homogene, utilitaire.
Definition: vec.h:121
program.h
Mesh::attribute_buffer_size
std::size_t attribute_buffer_size(const unsigned int id) const
renvoie la taille (en octets) d'un attribut.
Definition: mesh.cpp:182
program_uniform
void program_uniform(const GLuint program, const char *uniform, const unsigned int v)
affecte une valeur a un uniform du shader program. uint.
Definition: uniforms.cpp:68
program_use_texture
void program_use_texture(const GLuint program, const char *uniform, const int unit, const GLuint texture, const GLuint sampler)
configure le pipeline et le shader program pour utiliser une texture, et des parametres de filtrages...
Definition: uniforms.cpp:118
create_vertex_format
GLuint create_vertex_format()
cree un vertex array. a detruire avec release_vertex_format( ).
Definition: buffer.cpp:23
Mesh::attribute_buffer
const void * attribute_buffer(const unsigned int id) const
Definition: mesh.cpp:169
make_index_buffer
GLuint make_index_buffer(const GLuint vao, const size_t data_size, const void *data)
cree un index buffer et configure le vertex array vao. detruit par release_vertex_format( )...
Definition: buffer.cpp:86
Mesh::create
int create(const GLenum primitives)
construit les objets openGL.
Definition: mesh.cpp:13
Mesh::color_buffer_size
std::size_t color_buffer_size() const
renvoie la taille (en octets) du color buffer.
Definition: mesh.h:212
Mesh::release
void release()
detruit les objets openGL.
Definition: mesh.cpp:19
program_print_errors
int program_print_errors(const GLuint program)
affiche les erreurs de compilation.
Definition: program.cpp:330
Mesh::index_buffer
const void * index_buffer() const
renvoie l'adresse du premier indice du premier triangle. par convention c'est un uint, 1, GL_UNSIGNED_INT.
Definition: mesh.h:215
read_program
GLuint read_program(const char *filename, const char *definitions)
Definition: program.cpp:150
Mesh::texcoord_buffer_size
std::size_t texcoord_buffer_size() const
renvoie la taille (en octets) du texcoord buffer.
Definition: mesh.h:207
Mesh::triangle_last
Mesh & triangle_last(const int a, const int b, const int c)
Definition: mesh.cpp:130
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().
Definition: text.cpp:140
buffer.h
Transform
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition: mat.h:20
release_program
int release_program(const GLuint program)
detruit les shaders et le program.
Definition: program.cpp:157
Point
representation d'un point 3d.
Definition: vec.h:19
Mesh::normal
Mesh & normal(const vec3 &n)
definit la normale du prochain sommet.
Definition: mesh.cpp:43
make_vertex_buffer
GLuint make_vertex_buffer(const GLuint vao, const GLint attribute, const int size, const GLenum type, const size_t data_size, const void *data)
cree un vertex buffer et configure le vertex array vao. detruit par release_vertex_format( )...
Definition: buffer.cpp:59
Mesh::texcoord
Mesh & texcoord(const vec2 &uv)
definit les coordonnees de texture du prochain sommet.
Definition: mesh.cpp:49
Mesh::color_buffer
const float * color_buffer() const
renvoie l'adresse de la couleur du premier sommet. par convention, la couleur est un vec4...
Definition: mesh.h:210
Mesh::default_color
Color default_color() const
renvoie la couleur par defaut du mesh, utilisee si les sommets n'ont pas de couleur associee...
Definition: mesh.h:105