15 int is_whitespace(
const char c )
17 return (c ==
' ' || c ==
'\t' || c ==
'\r');
20 int is_digit(
const char c )
22 return (c >=
'0' && c <=
'9');
25 int is_exponent(
const char c )
27 return (c ==
'e' || c ==
'E');
30 const char* skip_whitespace(
const char* ptr )
32 while (is_whitespace(*ptr))
38 const char* parse_int(
const char* ptr,
int* val )
40 ptr = skip_whitespace(ptr);
54 while (is_digit(*ptr))
55 num = 10 * num + (*ptr++ -
'0');
65 double POWER_10_POS[MAX_POWER] =
67 1.0e0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9,
68 1.0e10, 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15, 1.0e16, 1.0e17, 1.0e18, 1.0e19,
72 double POWER_10_NEG[MAX_POWER] =
74 1.0e0, 1.0e-1, 1.0e-2, 1.0e-3, 1.0e-4, 1.0e-5, 1.0e-6, 1.0e-7, 1.0e-8, 1.0e-9,
75 1.0e-10, 1.0e-11, 1.0e-12, 1.0e-13, 1.0e-14, 1.0e-15, 1.0e-16, 1.0e-17, 1.0e-18, 1.0e-19,
78 const char* parse_float(
const char* ptr,
float* val)
80 ptr = skip_whitespace(ptr);
101 while (is_digit(*ptr))
102 num = 10.0 * num + (double)(*ptr++ -
'0');
109 while (is_digit(*ptr))
111 fra = 10.0 * fra + (double)(*ptr++ -
'0');
117 if (is_exponent(*ptr))
121 const double* powers=
nullptr;
125 powers = POWER_10_POS;
130 powers = POWER_10_NEG;
135 powers = POWER_10_POS;
139 unsigned int eval= 0;
140 while (is_digit(*ptr))
141 eval = 10 * eval + (*ptr++ -
'0');
143 num *= (eval >= MAX_POWER) ? 0.0 : powers[eval];
146 *val = (float)(sign * num);
153 FILE *in= fopen(filename,
"rb");
156 printf(
"[error] loading mesh '%s'...\n", filename);
160 Mesh data(GL_TRIANGLES);
162 printf(
"loading mesh '%s'...\n", filename);
164 std::vector<vec3> positions;
165 std::vector<vec2> texcoords;
169 std::vector<int> idp;
170 std::vector<int> idt;
171 std::vector<int> idn;
174 char line_buffer[1024*64];
179 if(fgets(line_buffer,
sizeof(line_buffer), in) == NULL)
186 line_buffer[
sizeof(line_buffer) -1]= 0;
189 const char *line= skip_whitespace(line_buffer);
196 line= parse_float(line, &x);
197 line= parse_float(line, &y);
198 line= parse_float(line, &z);
200 positions.push_back(
vec3(x, y, z) );
202 else if(line[1] ==
'n')
205 line= parse_float(line, &x);
206 line= parse_float(line, &y);
207 line= parse_float(line, &z);
211 else if(line[1] ==
't')
214 line= parse_float(line, &x);
215 line= parse_float(line, &y);
217 texcoords.push_back(
vec2(x, y) );
221 else if(line[0] ==
'f')
234 line= parse_int(line, &idp.back());
239 line= parse_int(line, &idt.back());
244 line= parse_int(line, &idn.back());
248 while(isspace(*line))
253 if(material_id == -1)
260 for(
int v= 2; v < int(idp.size()); v++)
262 int idv[3]= { 0, v -1, v };
263 for(
int i= 0; i < 3; 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;
271 if(t >= 0) data.
texcoord(texcoords[t]);
273 data.
vertex(positions[p]);
278 else if(line[0] ==
'm')
280 if(sscanf(line,
"mtllib %[^\r\n]", tmp) == 1)
288 else if(line[0] ==
'u')
290 if(sscanf(line,
"usemtl %[^\r\n]", tmp) == 1)
298 printf(
"[error] loading mesh '%s'...\n%s\n\n", filename, line_buffer);
300 printf(
"mesh '%s': %d positions %s %s\n", filename,
int(data.positions().size()), data.has_texcoord() ?
"texcoord" :
"", data.has_normal() ?
"normal" :
"");
314 vertex( ) : material(-1), position(-1), texcoord(-1), normal(-1) {}
315 vertex(
const int m,
const int p,
const int t,
const int n ) : material(m), position(p), texcoord(t), normal(n) {}
318 bool operator< (
const vertex& b )
const
320 if(material != b.material)
return material < b.material;
321 if(position != b.position)
return position < b.position;
322 if(texcoord != b.texcoord)
return texcoord < b.texcoord;
323 if(normal != b.normal)
return normal < b.normal;
331 FILE *in= fopen(filename,
"rb");
334 printf(
"[error] loading indexed mesh '%s'...\n", filename);
338 Mesh data(GL_TRIANGLES);
340 printf(
"loading indexed mesh '%s'...\n", filename);
342 std::vector<vec3> positions;
343 std::vector<vec2> texcoords;
347 std::vector<int> idp;
348 std::vector<int> idt;
349 std::vector<int> idn;
351 std::map<vertex, int> remap;
354 char line_buffer[1024*64];
359 if(fgets(line_buffer,
sizeof(line_buffer), in) == NULL)
366 line_buffer[
sizeof(line_buffer) -1]= 0;
369 const char *line= skip_whitespace(line_buffer);
376 line= parse_float(line, &x);
377 line= parse_float(line, &y);
378 line= parse_float(line, &z);
380 positions.push_back(
vec3(x, y, z) );
382 else if(line[1] ==
'n')
385 line= parse_float(line, &x);
386 line= parse_float(line, &y);
387 line= parse_float(line, &z);
391 else if(line[1] ==
't')
394 line= parse_float(line, &x);
395 line= parse_float(line, &y);
397 texcoords.push_back(
vec2(x, y) );
401 else if(line[0] ==
'f')
414 line= parse_int(line, &idp.back());
419 line= parse_int(line, &idt.back());
424 line= parse_int(line, &idn.back());
428 while(isspace(*line))
433 if(material_id == -1)
436 printf(
"usemtl default\n");
442 for(
int v= 2; v < int(idp.size()); v++)
444 int idv[3]= { 0, v -1, v };
445 for(
int i= 0; i < 3; i++)
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;
456 auto found= remap.insert( std::make_pair(
vertex(material_id, p, t, n), int(remap.size())) );
460 if(t != -1) data.
texcoord(texcoords[t]);
462 data.
vertex(positions[p]);
466 data.
index(found.first->second);
471 else if(line[0] ==
'm')
473 if(sscanf(line,
"mtllib %[^\r\n]", tmp) == 1)
481 else if(line[0] ==
'u')
483 if(sscanf(line,
"usemtl %[^\r\n]", tmp) == 1)
491 printf(
"[error] loading indexed mesh '%s'...\n%s\n\n", filename, line_buffer);
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()));
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.
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)
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().
Mesh read_mesh_fast(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes....
Materials read_materials(const char *filename)
charge une description de matieres, utilise par read_mesh.
Mesh read_indexed_mesh_fast(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)
int find(const char *name)
recherche une matiere avec son nom. renvoie son indice dans materials, ou -1.
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