16 FILE *in= fopen(filename,
"rb");
19 printf(
"[error] loading mesh '%s'...\n", filename);
23 Mesh data(GL_TRIANGLES);
25 printf(
"loading mesh '%s'...\n", filename);
27 std::vector<vec3> positions;
28 std::vector<vec2> texcoords;
37 char line_buffer[1024];
42 if(fgets(line_buffer,
sizeof(line_buffer), in) == NULL)
49 line_buffer[
sizeof(line_buffer) -1]= 0;
52 char *line= line_buffer;
53 while(*line && isspace(*line))
61 if(sscanf(line,
"v %f %f %f", &x, &y, &z) != 3)
63 positions.push_back(
vec3(x, y, z) );
65 else if(line[1] ==
'n')
67 if(sscanf(line,
"vn %f %f %f", &x, &y, &z) != 3)
71 else if(line[1] ==
't')
73 if(sscanf(line,
"vt %f %f", &x, &y) != 2)
75 texcoords.push_back(
vec2(x, y) );
79 else if(line[0] ==
'f')
86 for(line= line +1; ; line= line + next)
94 if(sscanf(line,
" %d/%d/%d %n", &idp.back(), &idt.back(), &idn.back(), &next) == 3)
96 else if(sscanf(line,
" %d/%d %n", &idp.back(), &idt.back(), &next) == 2)
98 else if(sscanf(line,
" %d//%d %n", &idp.back(), &idn.back(), &next) == 2)
100 else if(sscanf(line,
" %d %n", &idp.back(), &next) == 1)
105 assert(idt.size() == idp.size());
106 assert(idn.size() == idp.size());
109 if(material_id == -1)
112 printf(
"usemtl default\n");
118 for(
int v= 2; v +1 < int(idp.size()); v++)
120 int idv[3]= { 0, v -1, v };
121 for(
int i= 0; i < 3; 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;
131 if(t >= 0) data.
texcoord(texcoords[t]);
133 data.
vertex(positions[p]);
138 else if(line[0] ==
'm')
140 if(sscanf(line,
"mtllib %[^\r\n]", tmp) == 1)
142 std::string materials_filename;
143 if(tmp[0] !=
'/' && tmp[1] !=
':')
144 materials_filename= normalize_filename(
pathname(filename) + tmp);
146 materials_filename= std::string(tmp);
156 else if(line[0] ==
'u')
158 if(sscanf(line,
"usemtl %[^\r\n]", tmp) == 1)
166 printf(
"[error] loading mesh '%s'...\n%s\n\n", filename, line_buffer);
168 printf(
"mesh '%s': %d positions %s %s\n", filename,
int(data.positions().size()), data.has_texcoord() ?
"texcoord" :
"", data.has_normal() ?
"normal" :
"");
182 vertex( ) : material(-1), position(-1), texcoord(-1), normal(-1) {}
183 vertex(
const int m,
const int p,
const int t,
const int n ) : material(m), position(p), texcoord(t), normal(n) {}
186 bool operator< (
const vertex& b )
const
188 if(material != b.material)
return material < b.material;
189 if(position != b.position)
return position < b.position;
190 if(texcoord != b.texcoord)
return texcoord < b.texcoord;
191 if(normal != b.normal)
return normal < b.normal;
199 FILE *in= fopen(filename,
"rb");
202 printf(
"[error] loading indexed mesh '%s'...\n", filename);
206 Mesh data(GL_TRIANGLES);
208 printf(
"loading indexed mesh '%s'...\n", filename);
210 std::vector<vec3> positions;
211 std::vector<vec2> texcoords;
215 std::vector<int> idp;
216 std::vector<int> idt;
217 std::vector<int> idn;
219 std::map<vertex, int> remap;
222 char line_buffer[1024];
227 if(fgets(line_buffer,
sizeof(line_buffer), in) == NULL)
234 line_buffer[
sizeof(line_buffer) -1]= 0;
237 char *line= line_buffer;
238 while(*line && isspace(*line))
246 if(sscanf(line,
"v %f %f %f", &x, &y, &z) != 3)
248 positions.push_back(
vec3(x, y, z) );
250 else if(line[1] ==
'n')
252 if(sscanf(line,
"vn %f %f %f", &x, &y, &z) != 3)
256 else if(line[1] ==
't')
258 if(sscanf(line,
"vt %f %f", &x, &y) != 2)
260 texcoords.push_back(
vec2(x, y) );
264 else if(line[0] ==
'f')
271 for(line= line +1; ; line= line + next)
279 if(sscanf(line,
" %d/%d/%d %n", &idp.back(), &idt.back(), &idn.back(), &next) == 3)
281 else if(sscanf(line,
" %d/%d %n", &idp.back(), &idt.back(), &next) == 2)
283 else if(sscanf(line,
" %d//%d %n", &idp.back(), &idn.back(), &next) == 2)
285 else if(sscanf(line,
" %d %n", &idp.back(), &next) == 1)
295 printf(
"usemtl default\n");
301 for(
int v= 2; v +1 < (int) idp.size(); v++)
303 int idv[3]= { 0, v -1, v };
304 for(
int i= 0; i < 3; i++)
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;
315 auto found= remap.insert( std::make_pair(
vertex(material_id, p, t, n), int(remap.size())) );
319 if(t != -1) data.
texcoord(texcoords[t]);
321 data.
vertex(positions[p]);
325 data.
index(found.first->second);
330 else if(line[0] ==
'm')
332 if(sscanf(line,
"mtllib %[^\r\n]", tmp) == 1)
340 else if(line[0] ==
'u')
342 if(sscanf(line,
"usemtl %[^\r\n]", tmp) == 1)
350 printf(
"[error] loading indexed mesh '%s'...\n%s\n\n", filename, line_buffer);
352 printf(
" %d indices, %d positions %d texcoords %d normals\n",
353 int(data.indices().size()),
int(data.positions().size()),
int(data.texcoords().size()),
int(data.normals().size()));
359 int write_mesh(
const Mesh& mesh,
const char *filename,
const char *materials_filename )
366 if(mesh.positions().size() == 0)
368 if(filename ==
nullptr)
371 FILE *out= fopen(filename,
"wt");
375 printf(
"writing mesh '%s'...\n", filename);
376 if(materials_filename && materials_filename[0] && strcmp(filename, materials_filename))
378 printf(
" materials '%s'...\n", materials_filename);
379 fprintf(out,
"mtllib %s\n", materials_filename);
382 printf(
" %d positions, %d texcoords, %d normals\n",
int(mesh.positions().size()),
int(mesh.texcoords().size()),
int(mesh.normals().size()));
385 const std::vector<vec3>& positions= mesh.positions();
386 for(
unsigned i= 0; i < positions.size(); i++)
387 fprintf(out,
"v %f %f %f\n", positions[i].x, positions[i].y, positions[i].z);
391 const std::vector<vec2>& texcoords= mesh.texcoords();
393 for(
unsigned i= 0; i < texcoords.size(); i++)
394 fprintf(out,
"vt %f %f\n", texcoords[i].x, texcoords[i].y);
398 const std::vector<vec3>&
normals= mesh.normals();
400 for(
unsigned i= 0; i <
normals.size(); i++)
406 bool has_materials= (materials.size() > 0);
408 const std::vector<unsigned>& indices= mesh.indices();
409 bool has_indices= (indices.size() > 0);
411 unsigned n= has_indices ? indices.size() : positions.size();
412 for(
unsigned i= 0; i +2 < n; i+= 3)
414 if(has_materials && material_id !=
int(materials[i/3]))
416 material_id= int(materials[i/3]);
417 if(material_id != -1)
420 fprintf(out,
"usemtl %s\n", mesh.
materials().
name(material_id));
425 for(
unsigned k= 0; k < 3; k++)
427 unsigned id= has_indices ? indices[i+k] +1 : i+k +1;
428 fprintf(out,
" %u",
id);
430 fprintf(out,
"/%u/%u",
id,
id);
432 fprintf(out,
"/%u",
id);
434 fprintf(out,
"//%u",
id);
445 std::string texture_filename(
const std::string& filename,
const std::string& path )
447 if(filename[0] ==
'.' || filename[0] ==
'/')
448 return normalize_filename(filename);
450 return normalize_filename(path + filename);
458 FILE *in= fopen(filename,
"rt");
461 printf(
"[error] loading materials '%s'...\n", filename);
465 printf(
"loading materials '%s'...\n", filename);
469 char line_buffer[1024];
474 if(fgets(line_buffer,
sizeof(line_buffer), in) == NULL)
481 line_buffer[
sizeof(line_buffer) -1]= 0;
484 char *line= line_buffer;
485 while(*line && isspace(*line))
490 if(sscanf(line,
"newmtl %[^\r\n]", tmp) == 1)
497 if(material ==
nullptr)
503 if(sscanf(line,
"Kd %f %f %f", &r, &g, &b) == 3)
505 else if(sscanf(line,
"Ks %f %f %f", &r, &g, &b) == 3)
507 else if(sscanf(line,
"Ke %f %f %f", &r, &g, &b) == 3)
511 else if(line[0] ==
'N')
514 if(sscanf(line,
"Ns %f", &n) == 1)
518 else if(line[0] ==
'm')
520 if(sscanf(line,
"map_Kd %[^\r\n]", tmp) == 1)
523 else if(sscanf(line,
"map_Ks %[^\r\n]", tmp) == 1)
526 else if(sscanf(line,
"map_Ke %[^\r\n]", tmp) == 1)
534 printf(
"[error] parsing line :\n%s\n", line_buffer);
542 FILE *out= fopen(filename,
"wt");
546 printf(
"writing materials '%s'...\n", filename);
548 for(
int i= 0; i < materials.
count(); i++)
552 fprintf(out,
"newmtl %s\n", materials.
name(i));
566 fprintf(out,
" Ns %f\n", m.
ns);
568 fprintf(out,
" map_Ns %s\n", relative_filename(materials.
filename(m.
ns_texture), path).c_str());
representation d'un objet / maillage.
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 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 & normal(const vec3 &n)
definit la normale du prochain sommet.
Mesh & index(const int a)
GLenum primitives() const
renvoie le type de primitives.
const Materials & materials() const
renvoie la description des matieres.
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 Black()
utilitaire. renvoie une couleur noire.
int write_materials(const Materials &materials, const char *filename, const char *path)
enregistre une description de matieres.
Materials read_materials(const char *filename)
charge une description de matieres, utilise par read_mesh.
Mesh read_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes....
int write_mesh(const Mesh &mesh, const char *filename, const char *materials_filename)
enregistre un mesh dans un fichier .obj.
Mesh read_indexed_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles indexes. utiliser glDrawElem...
void normals(MeshData &data)
(re-) calcule les normales des sommets. utiliser avant les reindexations, cf indices() et vertices().
std::string pathname(const std::string &filename)
representation d'une couleur (rgba) transparente ou opaque.
int diffuse_texture
indice de la texture de la couleur de base, ou -1.
float ns
concentration des reflets, exposant pour les reflets blinn-phong.
int ns_texture
indice de la texture de reflet, ou -1.
Color emission
pour une source de lumiere.
Color diffuse
couleur diffuse / de base.
int emission_texture
indice de la texture, ou -1.
Color specular
couleur du reflet.
int specular_texture
indice de la texture, ou -1.
int insert(const Material &material, const char *name)
ajoute une matiere.
const Material & material(const int id) const
renvoie la ieme matiere.
int find(const char *name)
recherche une matiere avec son nom. renvoie son indice dans materials, ou -1.
int insert_texture(const char *filename)
ajoute une texture / nom du fichier.
int count() const
nombre de matieres.
const char * filename(const int id) const
renvoie le nombre de noms de fichiers de textures.
const char * name(const int id) const
renvoie le nom de la ieme matiere.
int default_material_index()
indice de la matiere par defaut dans le tableau materials.
vecteur generique, utilitaire.
vecteur generique, utilitaire.
representation de l'indexation complete d'un sommet
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...