gKit2 light
Loading...
Searching...
No Matches
utilitaires pour manipuler des objets 3d

Files

file  src/gKit/mesh.h
file  src/gKit/orbiter.h
file  src/gKit/wavefront.h
file  src/gKit/wavefront_fast.h

Classes

struct  TriangleData
 representation d'un triangle. More...
struct  TriangleGroup
 representation d'un ensemble de triangles de meme matiere. More...
class  Mesh
 representation d'un objet / maillage. More...
class  Orbiter
 representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet. More...

Enumerations

enum  : unsigned {
  USE_POSITION = 1 , USE_TEXCOORD = 2 , USE_NORMAL = 4 , USE_COLOR = 8 ,
  USE_MATERIAL_INDEX = 16
}
 flags pour identifier les attributs de sommets de Mesh. à utiliser avec Mesh::create_buffers(). More...

Functions

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_buffers();
Mesh read_mesh (const char *filename)
 charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes. utiliser glDrawArrays pour l'afficher. a detruire avec Mesh::release( ).
Mesh read_indexed_mesh (const char *filename)
 charge un fichier wavefront .obj et renvoie un mesh compose de triangles indexes. utiliser glDrawElements pour l'afficher. a detruire avec Mesh::release( ).
int write_mesh (const Mesh &mesh, const char *filename, const char *materials_filename=nullptr)
 enregistre un mesh dans un fichier .obj.
Materials read_materials (const char *filename)
 charge une description de matieres, utilise par read_mesh.
int write_materials (const Materials &materials, const char *filename, const char *path="")
 enregistre une description de matieres.
Mesh read_mesh_fast (const char *filename)
 charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes. utiliser glDrawArrays pour l'afficher. a detruire avec Mesh::release( ).
Mesh read_indexed_mesh_fast (const char *filename)
 charge un fichier wavefront .obj et renvoie un mesh compose de triangles indexes. utiliser glDrawElements pour l'afficher. a detruire avec Mesh::release( ).

Detailed Description


Class Documentation

◆ TriangleGroup

struct TriangleGroup

representation d'un ensemble de triangles de meme matiere.

Definition at line 102 of file mesh.h.

Class Members
int index indice de la "propriete"du groupe de triangles, par defaut : indice de la matiere
int first premier triangle du groupe
int n nombre de triangles du groupe

Enumeration Type Documentation

◆ anonymous enum

anonymous enum : unsigned

flags pour identifier les attributs de sommets de Mesh. à utiliser avec Mesh::create_buffers().

Enumerator
USE_POSITION 

inclut l'attribut position dans les buffers.

USE_TEXCOORD 

inclut l'attribut coordonnees de texture dans les buffers.

USE_NORMAL 

inclut l'attribut normale dans les buffers.

USE_COLOR 

inclut l'attribut couleur dans les buffers.

USE_MATERIAL_INDEX 

inclut l'attribut indice de matiere dans les buffers.

Definition at line 110 of file mesh.h.

111{
112 USE_POSITION= 1,
113 USE_TEXCOORD= 2,
114 USE_NORMAL= 4,
115 USE_COLOR= 8,
117};
@ USE_COLOR
inclut l'attribut couleur dans les buffers.
Definition mesh.h:115
@ USE_POSITION
inclut l'attribut position dans les buffers.
Definition mesh.h:112
@ 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

Function Documentation

◆ release_buffers()

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_buffers();

Definition at line 863 of file mesh.cpp.

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}

◆ read_mesh()

Mesh read_mesh ( const char * filename)

charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes. utiliser glDrawArrays pour l'afficher. a detruire avec Mesh::release( ).

Definition at line 14 of file wavefront.cpp.

15{
16 FILE *in= fopen(filename, "rb");
17 if(in == NULL)
18 {
19 printf("[error] loading mesh '%s'...\n", filename);
20 return {};
21 }
22
23 Mesh data(GL_TRIANGLES);
24
25 printf("loading mesh '%s'...\n", filename);
26
27 std::vector<vec3> positions;
28 std::vector<vec2> texcoords;
29 std::vector<vec3> normals;
30 int material_id= -1;
31
32 std::vector<int> idp;
33 std::vector<int> idt;
34 std::vector<int> idn;
35
36 char tmp[1024];
37 char line_buffer[1024];
38 bool error= true;
39 for(;;)
40 {
41 // charge une ligne du fichier
42 if(fgets(line_buffer, sizeof(line_buffer), in) == NULL)
43 {
44 error= false; // fin du fichier, pas d'erreur detectee
45 break;
46 }
47
48 // force la fin de la ligne, au cas ou
49 line_buffer[sizeof(line_buffer) -1]= 0;
50
51 // saute les espaces en debut de ligne
52 char *line= line_buffer;
53 while(*line && isspace(*line))
54 line++;
55
56 if(line[0] == 'v')
57 {
58 float x, y, z;
59 if(line[1] == ' ') // position x y z
60 {
61 if(sscanf(line, "v %f %f %f", &x, &y, &z) != 3)
62 break;
63 positions.push_back( vec3(x, y, z) );
64 }
65 else if(line[1] == 'n') // normal x y z
66 {
67 if(sscanf(line, "vn %f %f %f", &x, &y, &z) != 3)
68 break;
69 normals.push_back( vec3(x, y, z) );
70 }
71 else if(line[1] == 't') // texcoord x y
72 {
73 if(sscanf(line, "vt %f %f", &x, &y) != 2)
74 break;
75 texcoords.push_back( vec2(x, y) );
76 }
77 }
78
79 else if(line[0] == 'f') // triangle a b c, les sommets sont numerotes a partir de 1 ou de la fin du tableau (< 0)
80 {
81 idp.clear();
82 idt.clear();
83 idn.clear();
84
85 int next;
86 for(line= line +1; ; line= line + next)
87 {
88 idp.push_back(0);
89 idt.push_back(0);
90 idn.push_back(0); // 0: invalid index
91
92 // analyse les attributs du sommet : p/t/n ou p//n ou p/t ou p...
93 next= 0;
94 if(sscanf(line, " %d/%d/%d %n", &idp.back(), &idt.back(), &idn.back(), &next) == 3)
95 continue;
96 else if(sscanf(line, " %d/%d %n", &idp.back(), &idt.back(), &next) == 2)
97 continue;
98 else if(sscanf(line, " %d//%d %n", &idp.back(), &idn.back(), &next) == 2)
99 continue;
100 else if(sscanf(line, " %d %n", &idp.back(), &next) == 1)
101 continue;
102 else if(next == 0) // fin de ligne
103 break;
104 }
105 assert(idt.size() == idp.size());
106 assert(idn.size() == idp.size());
107
108 // force une matiere par defaut, si necessaire
109 if(material_id == -1)
110 {
111 material_id= data.materials().default_material_index();
112 printf("usemtl default\n");
113 }
114
115 data.material(material_id);
116
117 // triangule la face
118 for(int v= 2; v +1 < int(idp.size()); v++)
119 {
120 int idv[3]= { 0, v -1, v };
121 for(int i= 0; i < 3; i++)
122 {
123 int k= idv[i];
124 int p= (idp[k] < 0) ? int(positions.size()) + idp[k] : idp[k] -1;
125 int t= (idt[k] < 0) ? int(texcoords.size()) + idt[k] : idt[k] -1;
126 int n= (idn[k] < 0) ? int(normals.size()) + idn[k] : idn[k] -1;
127
128 if(p < 0) break; // error
129
130 // attribut du ieme sommet
131 if(t >= 0) data.texcoord(texcoords[t]);
132 if(n >= 0) data.normal(normals[n]);
133 data.vertex(positions[p]);
134 }
135 }
136 }
137
138 else if(line[0] == 'm')
139 {
140 if(sscanf(line, "mtllib %[^\r\n]", tmp) == 1)
141 {
142 std::string materials_filename;
143 if(tmp[0] != '/' && tmp[1] != ':') // windows c:\ pour les chemins complets...
144 materials_filename= normalize_filename(pathname(filename) + tmp);
145 else
146 materials_filename= std::string(tmp);
147
148 // charge les matieres
149 Materials materials= read_materials( materials_filename.c_str() );
150
151 // enregistre les matieres dans le mesh
152 data.materials(materials);
153 }
154 }
155
156 else if(line[0] == 'u')
157 {
158 if(sscanf(line, "usemtl %[^\r\n]", tmp) == 1)
159 material_id= data.materials().find(tmp);
160 }
161 }
162
163 fclose(in);
164
165 if(error)
166 printf("[error] loading mesh '%s'...\n%s\n\n", filename, line_buffer);
167 else
168 printf("mesh '%s': %d positions %s %s\n", filename, int(data.positions().size()), data.has_texcoord() ? "texcoord" : "", data.has_normal() ? "normal" : "");
169
170 return data;
171}
representation d'un objet / maillage.
Definition mesh.h:121
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
Materials read_materials(const char *filename)
charge une description de matieres, utilise par read_mesh.
void normals(MeshData &data)
(re-) calcule les normales des sommets. utiliser avant les reindexations, cf indices() et vertices().
vecteur generique, utilitaire.
Definition vec.h:152
vecteur generique, utilitaire.
Definition vec.h:169

◆ read_indexed_mesh()

Mesh read_indexed_mesh ( const char * filename)

charge un fichier wavefront .obj et renvoie un mesh compose de triangles indexes. utiliser glDrawElements pour l'afficher. a detruire avec Mesh::release( ).

Definition at line 197 of file wavefront.cpp.

198{
199 FILE *in= fopen(filename, "rb");
200 if(in == NULL)
201 {
202 printf("[error] loading indexed mesh '%s'...\n", filename);
203 return {};
204 }
205
206 Mesh data(GL_TRIANGLES);
207
208 printf("loading indexed mesh '%s'...\n", filename);
209
210 std::vector<vec3> positions;
211 std::vector<vec2> texcoords;
212 std::vector<vec3> normals;
213 int material_id= -1;
214
215 std::vector<int> idp;
216 std::vector<int> idt;
217 std::vector<int> idn;
218
219 std::map<vertex, int> remap;
220
221 char tmp[1024];
222 char line_buffer[1024];
223 bool error= true;
224 for(;;)
225 {
226 // charge une ligne du fichier
227 if(fgets(line_buffer, sizeof(line_buffer), in) == NULL)
228 {
229 error= false; // fin du fichier, pas d'erreur detectee
230 break;
231 }
232
233 // force la fin de la ligne, au cas ou
234 line_buffer[sizeof(line_buffer) -1]= 0;
235
236 // saute les espaces en debut de ligne
237 char *line= line_buffer;
238 while(*line && isspace(*line))
239 line++;
240
241 if(line[0] == 'v')
242 {
243 float x, y, z;
244 if(line[1] == ' ') // position x y z
245 {
246 if(sscanf(line, "v %f %f %f", &x, &y, &z) != 3)
247 break;
248 positions.push_back( vec3(x, y, z) );
249 }
250 else if(line[1] == 'n') // normal x y z
251 {
252 if(sscanf(line, "vn %f %f %f", &x, &y, &z) != 3)
253 break;
254 normals.push_back( vec3(x, y, z) );
255 }
256 else if(line[1] == 't') // texcoord x y
257 {
258 if(sscanf(line, "vt %f %f", &x, &y) != 2)
259 break;
260 texcoords.push_back( vec2(x, y) );
261 }
262 }
263
264 else if(line[0] == 'f') // triangle a b c, les sommets sont numerotes a partir de 1 ou de la fin du tableau (< 0)
265 {
266 idp.clear();
267 idt.clear();
268 idn.clear();
269
270 int next;
271 for(line= line +1; ; line= line + next)
272 {
273 idp.push_back(0);
274 idt.push_back(0);
275 idn.push_back(0); // 0: invalid index
276
277 // analyse les attributs du sommet : p/t/n ou p//n ou p/t ou p...
278 next= 0;
279 if(sscanf(line, " %d/%d/%d %n", &idp.back(), &idt.back(), &idn.back(), &next) == 3)
280 continue;
281 else if(sscanf(line, " %d/%d %n", &idp.back(), &idt.back(), &next) == 2)
282 continue;
283 else if(sscanf(line, " %d//%d %n", &idp.back(), &idn.back(), &next) == 2)
284 continue;
285 else if(sscanf(line, " %d %n", &idp.back(), &next) == 1)
286 continue;
287 else if(next == 0) // fin de ligne
288 break;
289 }
290
291 // force une matiere par defaut, si necessaire
292 if(material_id == -1 && data.materials().count() > 0)
293 {
294 material_id= data.materials().default_material_index();
295 printf("usemtl default\n");
296 }
297
298 data.material(material_id);
299
300 // triangule la face
301 for(int v= 2; v +1 < (int) idp.size(); v++)
302 {
303 int idv[3]= { 0, v -1, v };
304 for(int i= 0; i < 3; i++)
305 {
306 int k= idv[i];
307 // indices des attributs du sommet
308 int p= (idp[k] < 0) ? (int) positions.size() + idp[k] : idp[k] -1;
309 int t= (idt[k] < 0) ? (int) texcoords.size() + idt[k] : idt[k] -1;
310 int n= (idn[k] < 0) ? (int) normals.size() + idn[k] : idn[k] -1;
311
312 if(p < 0) break; // error
313
314 // recherche / insere le sommet
315 auto found= remap.insert( std::make_pair(vertex(material_id, p, t, n), int(remap.size())) );
316 if(found.second)
317 {
318 // pas trouve, copie les nouveaux attributs
319 if(t != -1) data.texcoord(texcoords[t]);
320 if(n != -1) data.normal(normals[n]);
321 data.vertex(positions[p]);
322 assert(data.texcoords().size() > 0 && data.positions().size() == data.texcoords().size());
323 assert(data.normals().size() > 0 && data.positions().size() == data.normals().size());
324 }
325
326 // construit l'index buffer
327 assert(found.first->second < data.positions().size());
328 assert(remap.size() == data.positions().size());
329 data.index(found.first->second);
330 }
331 }
332 }
333
334 else if(line[0] == 'm')
335 {
336 if(sscanf(line, "mtllib %[^\r\n]", tmp) == 1)
337 {
338 Materials materials= read_materials( normalize_filename(pathname(filename) + tmp).c_str() );
339 // enregistre les matieres dans le mesh
340 data.materials(materials);
341 }
342 }
343
344 else if(line[0] == 'u')
345 {
346 if(sscanf(line, "usemtl %[^\r\n]", tmp) == 1)
347 material_id= data.materials().find(tmp);
348 }
349 }
350
351 fclose(in);
352
353 if(error)
354 printf("[error] loading indexed mesh '%s'...\n%s\n\n", filename, line_buffer);
355 else
356 printf(" %d indices, %d positions %d texcoords %d normals\n",
357 int(data.indices().size()), int(data.positions().size()), int(data.texcoords().size()), int(data.normals().size()));
358
359 return data;
360}
representation de l'indexation complete d'un sommet

◆ write_mesh()

int write_mesh ( const Mesh & mesh,
const char * filename,
const char * materials_filename = nullptr )

enregistre un mesh dans un fichier .obj.

Definition at line 363 of file wavefront.cpp.

364{
365 if(mesh.primitives() != GL_TRIANGLES)
366 return -1;
367 if(mesh.positions().size() == 0)
368 return -1;
369 if(filename == nullptr)
370 return -1;
371
372 FILE *out= fopen(filename, "wt");
373 if(out == nullptr)
374 return -1;
375
376 printf("writing mesh '%s'...\n", filename);
377 if(materials_filename && materials_filename[0] && strcmp(filename, materials_filename))
378 {
379 printf(" materials '%s'...\n", materials_filename);
380 fprintf(out, "mtllib %s\n", materials_filename);
381 }
382 {
383 printf(" %d positions, %d texcoords, %d normals\n", int(mesh.positions().size()), int(mesh.texcoords().size()), int(mesh.normals().size()));
384 }
385
386 const std::vector<vec3>& positions= mesh.positions();
387 for(unsigned i= 0; i < positions.size(); i++)
388 fprintf(out, "v %f %f %f\n", positions[i].x, positions[i].y, positions[i].z);
389 fprintf(out, "\n");
390
391 //~ bool has_texcoords= false;
392 const std::vector<vec2>& texcoords= mesh.texcoords();
393 bool has_texcoords= (texcoords.size() == positions.size());
394 for(unsigned i= 0; i < texcoords.size(); i++)
395 fprintf(out, "vt %f %f\n", texcoords[i].x, texcoords[i].y);
396 fprintf(out, "\n");
397
398 //~ bool has_normals= false;
399 const std::vector<vec3>& normals= mesh.normals();
400 bool has_normals= (normals.size() == positions.size());
401 for(unsigned i= 0; i < normals.size(); i++)
402 fprintf(out, "vn %f %f %f\n", normals[i].x, normals[i].y, normals[i].z);
403 fprintf(out, "\n");
404
405 int material_id= -1;
406 const std::vector<unsigned>& materials= mesh.material_indices();
407 bool has_materials= (materials.size() > 0);
408
409 const std::vector<unsigned>& indices= mesh.indices();
410 bool has_indices= (indices.size() > 0);
411
412 unsigned n= has_indices ? indices.size() : positions.size();
413 for(unsigned i= 0; i +2 < n; i+= 3)
414 {
415 if(has_materials && material_id != int(materials[i/3]))
416 {
417 material_id= int(materials[i/3]);
418 if(material_id != -1)
419 {
420 fprintf(out, "o %s\n", mesh.materials().name(material_id));
421 fprintf(out, "usemtl %s\n", mesh.materials().name(material_id));
422 }
423 }
424
425 fprintf(out, "f");
426 for(unsigned k= 0; k < 3; k++)
427 {
428 unsigned id= has_indices ? indices[i+k] +1 : i+k +1;
429 fprintf(out, " %u", id);
431 fprintf(out, "/%u/%u", id, id);
432 else if(has_texcoords)
433 fprintf(out, "/%u", id);
434 else if(has_normals)
435 fprintf(out, "//%u", id);
436 }
437 fprintf(out, "\n");
438 }
439
440 fclose(out);
441 return 0;
442}
bool has_normals(const Hit &hit, const GLTFScene &scene)
verifie la presence des normales par sommet.
bool has_texcoords(const Hit &hit, const GLTFScene &scene)
verifie la presence des coordonnees de texture...

◆ read_materials()

Materials read_materials ( const char * filename)

charge une description de matieres, utilise par read_mesh.

Definition at line 455 of file wavefront.cpp.

456{
457 Materials materials;
458
459 FILE *in= fopen(filename, "rt");
460 if(in == NULL)
461 {
462 printf("[error] loading materials '%s'...\n", filename);
463 return materials;
464 }
465
466 printf("loading materials '%s'...\n", filename);
467
468 Material *material= NULL;
469 char tmp[1024];
470 char line_buffer[1024];
471 bool error= true;
472 for(;;)
473 {
474 // charge une ligne du fichier
475 if(fgets(line_buffer, sizeof(line_buffer), in) == NULL)
476 {
477 error= false; // fin du fichier, pas d'erreur detectee
478 break;
479 }
480
481 // force la fin de la ligne, au cas ou
482 line_buffer[sizeof(line_buffer) -1]= 0;
483
484 // saute les espaces en debut de ligne
485 char *line= line_buffer;
486 while(*line && isspace(*line))
487 line++;
488
489 if(line[0] == 'n')
490 {
491 if(sscanf(line, "newmtl %[^\r\n]", tmp) == 1)
492 {
493 int id= materials.insert(Material(Black()), tmp);
494 material= &materials.material(id);
495 }
496 }
497
498 if(material == nullptr)
499 continue;
500
501 if(line[0] == 'K')
502 {
503 float r, g, b;
504 if(sscanf(line, "Kd %f %f %f", &r, &g, &b) == 3)
505 material->diffuse= Color(r, g, b);
506 else if(sscanf(line, "Ks %f %f %f", &r, &g, &b) == 3)
507 material->specular= Color(r, g, b);
508 else if(sscanf(line, "Ke %f %f %f", &r, &g, &b) == 3)
509 material->emission= Color(r, g, b);
510 }
511
512 else if(line[0] == 'N')
513 {
514 float n;
515 if(sscanf(line, "Ns %f", &n) == 1) // Ns, puissance / concentration du reflet, modele blinn phong
516 material->ns= n;
517 }
518
519 else if(line[0] == 'm')
520 {
521 if(sscanf(line, "map_Kd %[^\r\n]", tmp) == 1)
522 material->diffuse_texture= materials.insert_texture( texture_filename(tmp, pathname(filename)).c_str() );
523
524 else if(sscanf(line, "map_Ks %[^\r\n]", tmp) == 1)
525 material->specular_texture= materials.insert_texture( texture_filename(tmp, pathname(filename)).c_str() );
526
527 else if(sscanf(line, "map_Ke %[^\r\n]", tmp) == 1)
528 material->emission_texture= materials.insert_texture( texture_filename(tmp, pathname(filename)).c_str() );
529 }
530
531 }
532
533 fclose(in);
534 if(error)
535 printf("[error] parsing line :\n%s\n", line_buffer);
536
537 return materials;
538}
Color Black()
utilitaire. renvoie une couleur noire.
Definition color.cpp:18
representation d'une couleur (rgba) transparente ou opaque.
Definition color.h:14
int diffuse_texture
indice de la texture de la couleur de base, ou -1.
Definition materials.h:21
float ns
concentration des reflets, exposant pour les reflets blinn-phong.
Definition materials.h:20
Color emission
pour une source de lumiere.
Definition materials.h:19
Color diffuse
couleur diffuse / de base.
Definition materials.h:17
int emission_texture
indice de la texture, ou -1.
Definition materials.h:23
Color specular
couleur du reflet.
Definition materials.h:18
int specular_texture
indice de la texture, ou -1.
Definition materials.h:22
int insert(const Material &material, const char *name)
ajoute une matiere.
Definition materials.h:62
int insert_texture(const char *filename)
ajoute une texture / nom du fichier.
Definition materials.h:76
const Material & material(const int id) const
renvoie la ieme matiere.
Definition materials.h:110

◆ write_materials()

int write_materials ( const Materials & materials,
const char * filename,
const char * path = "" )

enregistre une description de matieres.

Definition at line 541 of file wavefront.cpp.

542{
543 FILE *out= fopen(filename, "wt");
544 if(out == NULL)
545 return -1;
546
547 printf("writing materials '%s'...\n", filename);
548
549 for(int i= 0; i < materials.count(); i++)
550 {
551 const Material& m= materials.material(i);
552
553 fprintf(out, "newmtl %s\n", materials.name(i));
554
555 if(m.diffuse.r + m.diffuse.g + m.diffuse.b)
556 fprintf(out, " Kd %f %f %f\n", m.diffuse.r, m.diffuse.g, m.diffuse.b);
557 if(m.diffuse_texture != -1)
558 fprintf(out, " map_Kd %s\n", relative_filename(materials.filename(m.diffuse_texture), path).c_str());
559
560 if(m.specular.r + m.specular.g + m.specular.b)
561 fprintf(out, " Ks %f %f %f\n", m.specular.r, m.specular.g, m.specular.b);
562 if(m.specular_texture != -1)
563 fprintf(out, " map_Ks %s\n", relative_filename(materials.filename(m.specular_texture), path).c_str());
564
565 if(m.specular.power() > 0)
566 {
567 fprintf(out, " Ns %f\n", m.ns);
568 if(m.ns_texture != -1)
569 fprintf(out, " map_Ns %s\n", relative_filename(materials.filename(m.ns_texture), path).c_str());
570 }
571
572 if(m.emission.power() > 0)
573 {
574 fprintf(out, " Ke %f %f %f\n", m.emission.r, m.emission.g, m.emission.b);
575 if(m.emission_texture != -1)
576 fprintf(out, " map_Ke %s\n", relative_filename(materials.filename(m.emission_texture), path).c_str());
577 }
578
579 fprintf(out, "\n");
580 }
581
582 fclose(out);
583 return 0;
584}
int ns_texture
indice de la texture de reflet, ou -1.
Definition materials.h:24
const char * filename(const int id) const
renvoie le nom de fichier d'une texture.
Definition materials.h:149
int count() const
nombre de matieres.
Definition materials.h:102
const char * name(const int id) const
renvoie le nom de la ieme matiere.
Definition materials.h:105

◆ read_mesh_fast()

Mesh read_mesh_fast ( const char * filename)

charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes. utiliser glDrawArrays pour l'afficher. a detruire avec Mesh::release( ).

Definition at line 151 of file wavefront_fast.cpp.

152{
153 FILE *in= fopen(filename, "rb");
154 if(in == NULL)
155 {
156 printf("[error] loading mesh '%s'...\n", filename);
157 return {};
158 }
159
160 Mesh data(GL_TRIANGLES);
161
162 printf("loading mesh '%s'...\n", filename);
163
164 std::vector<vec3> positions;
165 std::vector<vec2> texcoords;
166 std::vector<vec3> normals;
167 int material_id= -1;
168
169 std::vector<int> idp;
170 std::vector<int> idt;
171 std::vector<int> idn;
172
173 char tmp[1024*64];
174 char line_buffer[1024*64];
175 bool error= true;
176 for(;;)
177 {
178 // charge une ligne du fichier
179 if(fgets(line_buffer, sizeof(line_buffer), in) == NULL)
180 {
181 error= false; // fin du fichier, pas d'erreur detectee
182 break;
183 }
184
185 // force la fin de la ligne, au cas ou
186 line_buffer[sizeof(line_buffer) -1]= 0;
187
188 // saute les espaces en debut de ligne
189 const char *line= skip_whitespace(line_buffer);
190 if(line[0] == 'v')
191 {
192 float x, y, z;
193 if(line[1] == ' ') // position x y z
194 {
195 line+= 2;
196 line= parse_float(line, &x);
197 line= parse_float(line, &y);
198 line= parse_float(line, &z);
199
200 positions.push_back( vec3(x, y, z) );
201 }
202 else if(line[1] == 'n') // normal x y z
203 {
204 line+= 3;
205 line= parse_float(line, &x);
206 line= parse_float(line, &y);
207 line= parse_float(line, &z);
208
209 normals.push_back( vec3(x, y, z) );
210 }
211 else if(line[1] == 't') // texcoord x y
212 {
213 line+= 3;
214 line= parse_float(line, &x);
215 line= parse_float(line, &y);
216
217 texcoords.push_back( vec2(x, y) );
218 }
219 }
220
221 else if(line[0] == 'f') // triangle a b c, les sommets sont numerotes a partir de 1 ou de la fin du tableau (< 0)
222 {
223 idp.clear();
224 idt.clear();
225 idn.clear();
226
227 line+= 2;
228 while(*line)
229 {
230 idp.push_back(0);
231 idt.push_back(0);
232 idn.push_back(0); // 0: invalid index
233
234 line= parse_int(line, &idp.back());
235 if(*line == '/')
236 {
237 line++;
238 if(*line != '/')
239 line= parse_int(line, &idt.back());
240
241 if(*line == '/')
242 {
243 line++;
244 line= parse_int(line, &idn.back());
245 }
246 }
247
248 while(isspace(*line))
249 line++;
250 }
251
252 // verifie qu'une matiere est deja definie pour le triangle
253 if(material_id == -1)
254 // sinon affecte une matiere par defaut
255 material_id= data.materials().default_material_index();
256
257 data.material(material_id);
258
259 // triangulation de la face (supposee convexe)
260 for(int v= 2; v < int(idp.size()); v++)
261 {
262 int idv[3]= { 0, v -1, v };
263 for(int i= 0; i < 3; i++)
264 {
265 int k= idv[i];
266 int p= (idp[k] < 0) ? (int) positions.size() + idp[k] : idp[k] -1;
267 int t= (idt[k] < 0) ? (int) texcoords.size() + idt[k] : idt[k] -1;
268 int n= (idn[k] < 0) ? (int) normals.size() + idn[k] : idn[k] -1;
269
270 if(p < 0) break; // error
271 if(t >= 0) data.texcoord(texcoords[t]);
272 if(n >= 0) data.normal(normals[n]);
273 data.vertex(positions[p]);
274 }
275 }
276 }
277
278 else if(line[0] == 'm')
279 {
280 if(sscanf(line, "mtllib %[^\r\n]", tmp) == 1)
281 {
282 Materials materials= read_materials( normalize_filename(pathname(filename) + tmp).c_str() );
283 // enregistre les matieres dans le mesh
284 data.materials(materials);
285 }
286 }
287
288 else if(line[0] == 'u')
289 {
290 if(sscanf(line, "usemtl %[^\r\n]", tmp) == 1)
291 material_id= data.materials().find(tmp);
292 }
293 }
294
295 fclose(in);
296
297 if(error)
298 printf("[error] loading mesh '%s'...\n%s\n\n", filename, line_buffer);
299 else
300 printf("mesh '%s': %d positions %s %s\n", filename, int(data.positions().size()), data.has_texcoord() ? "texcoord" : "", data.has_normal() ? "normal" : "");
301
302 return data;
303}

◆ read_indexed_mesh_fast()

Mesh read_indexed_mesh_fast ( const char * filename)

charge un fichier wavefront .obj et renvoie un mesh compose de triangles indexes. utiliser glDrawElements pour l'afficher. a detruire avec Mesh::release( ).

Definition at line 329 of file wavefront_fast.cpp.

330{
331 FILE *in= fopen(filename, "rb");
332 if(in == NULL)
333 {
334 printf("[error] loading indexed mesh '%s'...\n", filename);
335 return {};
336 }
337
338 Mesh data(GL_TRIANGLES);
339
340 printf("loading indexed mesh '%s'...\n", filename);
341
342 std::vector<vec3> positions;
343 std::vector<vec2> texcoords;
344 std::vector<vec3> normals;
345 int material_id= -1;
346
347 std::vector<int> idp;
348 std::vector<int> idt;
349 std::vector<int> idn;
350
351 std::map<vertex, int> remap;
352
353 char tmp[1024*64];
354 char line_buffer[1024*64];
355 bool error= true;
356 for(;;)
357 {
358 // charge une ligne du fichier
359 if(fgets(line_buffer, sizeof(line_buffer), in) == NULL)
360 {
361 error= false; // fin du fichier, pas d'erreur detectee
362 break;
363 }
364
365 // force la fin de la ligne, au cas ou
366 line_buffer[sizeof(line_buffer) -1]= 0;
367
368 // saute les espaces en debut de ligne
369 const char *line= skip_whitespace(line_buffer);
370 if(line[0] == 'v')
371 {
372 float x, y, z;
373 if(line[1] == ' ') // position x y z
374 {
375 line+= 2;
376 line= parse_float(line, &x);
377 line= parse_float(line, &y);
378 line= parse_float(line, &z);
379
380 positions.push_back( vec3(x, y, z) );
381 }
382 else if(line[1] == 'n') // normal x y z
383 {
384 line+= 3;
385 line= parse_float(line, &x);
386 line= parse_float(line, &y);
387 line= parse_float(line, &z);
388
389 normals.push_back( vec3(x, y, z) );
390 }
391 else if(line[1] == 't') // texcoord x y
392 {
393 line+= 3;
394 line= parse_float(line, &x);
395 line= parse_float(line, &y);
396
397 texcoords.push_back( vec2(x, y) );
398 }
399 }
400
401 else if(line[0] == 'f') // triangle a b c, les sommets sont numerotes a partir de 1 ou de la fin du tableau (< 0)
402 {
403 idp.clear();
404 idt.clear();
405 idn.clear();
406
407 line+= 2;
408 while(*line)
409 {
410 idp.push_back(0);
411 idt.push_back(0);
412 idn.push_back(0); // 0: invalid index
413
414 line= parse_int(line, &idp.back());
415 if(*line == '/')
416 {
417 line++;
418 if(*line != '/')
419 line= parse_int(line, &idt.back());
420
421 if(*line == '/')
422 {
423 line++;
424 line= parse_int(line, &idn.back());
425 }
426 }
427
428 while(isspace(*line))
429 line++;
430 }
431
432 // force une matiere par defaut, si necessaire
433 if(material_id == -1)
434 {
435 material_id= data.materials().default_material_index();
436 printf("usemtl default\n");
437 }
438
439 data.material(material_id);
440
441 // triangule la face
442 for(int v= 2; v < int(idp.size()); v++)
443 {
444 int idv[3]= { 0, v -1, v };
445 for(int i= 0; i < 3; i++)
446 {
447 int k= idv[i];
448 // indices des attributs du sommet
449 int p= (idp[k] < 0) ? (int) positions.size() + idp[k] : idp[k] -1;
450 int t= (idt[k] < 0) ? (int) texcoords.size() + idt[k] : idt[k] -1;
451 int n= (idn[k] < 0) ? (int) normals.size() + idn[k] : idn[k] -1;
452
453 if(p < 0) break; // error
454
455 // recherche / insere le sommet
456 auto found= remap.insert( std::make_pair(vertex(material_id, p, t, n), int(remap.size())) );
457 if(found.second)
458 {
459 // pas trouve, copie les nouveaux attributs
460 if(t != -1) data.texcoord(texcoords[t]);
461 if(n != -1) data.normal(normals[n]);
462 data.vertex(positions[p]);
463 }
464
465 // construit l'index buffer
466 data.index(found.first->second);
467 }
468 }
469 }
470
471 else if(line[0] == 'm')
472 {
473 if(sscanf(line, "mtllib %[^\r\n]", tmp) == 1)
474 {
475 Materials materials= read_materials( normalize_filename(pathname(filename) + tmp).c_str() );
476 // enregistre les matieres dans le mesh
477 data.materials(materials);
478 }
479 }
480
481 else if(line[0] == 'u')
482 {
483 if(sscanf(line, "usemtl %[^\r\n]", tmp) == 1)
484 material_id= data.materials().find(tmp);
485 }
486 }
487
488 fclose(in);
489
490 if(error)
491 printf("[error] loading indexed mesh '%s'...\n%s\n\n", filename, line_buffer);
492 else
493 printf(" %d indices, %d positions %d texcoords %d normals\n",
494 int(data.indices().size()), int(data.positions().size()), int(data.texcoords().size()), int(data.normals().size()));
495
496 return data;
497}