gKit2 light
wavefront.cpp
1 
2 #include <ctype.h>
3 #include <cstdio>
4 
5 #include "wavefront.h"
6 
7 
8 Mesh read_mesh( const char *filename )
9 {
10  FILE *in= fopen(filename, "rt");
11  if(in == NULL)
12  {
13  printf("loading mesh '%s'... failed.\n", filename);
14  return Mesh::error();
15  }
16 
17  Mesh data(GL_TRIANGLES);
18 
19  printf("loading mesh '%s'...\n", filename);
20 
21  std::vector<vec3> positions;
22  std::vector<vec2> texcoords;
23  std::vector<vec3> normals;
24 
25  std::vector<int> idp;
26  std::vector<int> idt;
27  std::vector<int> idn;
28 
29  char line_buffer[1024];
30  bool error= true;
31  for(;;)
32  {
33  // charge une ligne du fichier
34  if(fgets(line_buffer, sizeof(line_buffer), in) == NULL)
35  {
36  error= false; // fin du fichier, pas d'erreur detectee
37  break;
38  }
39 
40  // force la fin de la ligne, au cas ou
41  line_buffer[sizeof(line_buffer) -1]= 0;
42 
43  // saute les espaces en debut de ligne
44  char *line= line_buffer;
45  while(*line && isspace(*line))
46  line++;
47 
48  if(line[0] == 'v')
49  {
50  float x, y, z;
51  if(line[1] == ' ') // position x y z
52  {
53  if(sscanf(line, "v %f %f %f", &x, &y, &z) != 3)
54  break;
55  positions.push_back( vec3(x, y, z) );
56  }
57  else if(line[1] == 'n') // normal x y z
58  {
59  if(sscanf(line, "vn %f %f %f", &x, &y, &z) != 3)
60  break;
61  normals.push_back( vec3(x, y, z) );
62  }
63  else if(line[1] == 't') // texcoord x y
64  {
65  if(sscanf(line, "vt %f %f", &x, &y) != 2)
66  break;
67  texcoords.push_back( vec2(x, y) );
68  }
69  }
70 
71  else if(line[0] == 'f') // triangle a b c, les sommets sont numerotes a partir de 1 ou de la fin du tableau (< 0)
72  {
73  idp.clear();
74  idt.clear();
75  idn.clear();
76 
77  int next;
78  for(line= line +1; ; line= line + next)
79  {
80  idp.push_back(0);
81  idt.push_back(0);
82  idn.push_back(0); // 0: invalid index
83 
84  next= 0;
85  if(sscanf(line, " %d/%d/%d %n", &idp.back(), &idt.back(), &idn.back(), &next) == 3)
86  continue;
87  else if(sscanf(line, " %d/%d %n", &idp.back(), &idt.back(), &next) == 2)
88  continue;
89  else if(sscanf(line, " %d//%d %n", &idp.back(), &idn.back(), &next) == 2)
90  continue;
91  else if(sscanf(line, " %d %n", &idp.back(), &next) == 1)
92  continue;
93  else if(next == 0) // fin de ligne
94  break;
95  }
96 
97  for(int v= 2; v +1 < (int) idp.size(); v++)
98  {
99  int idv[3]= { 0, v -1, v };
100  for(int i= 0; i < 3; i++)
101  {
102  int k= idv[i];
103  int p= (idp[k] < 0) ? (int) positions.size() + idp[k] : idp[k] -1;
104  int t= (idt[k] < 0) ? (int) texcoords.size() + idt[k] : idt[k] -1;
105  int n= (idn[k] < 0) ? (int) normals.size() + idn[k] : idn[k] -1;
106 
107  if(t >= 0) data.texcoord(texcoords[t]);
108  if(n >= 0) data.normal(normals[n]);
109 
110  if(p < 0) break; // error
111  data.vertex(positions[p]);
112  }
113  }
114  }
115  }
116 
117  fclose(in);
118 
119  if(error)
120  printf("loading mesh '%s'...\n[error]\n%s\n\n", filename, line_buffer);
121 
122  return data;
123 }
124 
125 int write_mesh( const Mesh& mesh, const char *filename )
126 {
127  if(mesh == Mesh::error())
128  return -1;
129 
130  if(mesh.primitives() != GL_TRIANGLES)
131  return -1;
132  if(mesh.positions().size() == 0)
133  return -1;
134  if(filename == NULL)
135  return -1;
136 
137  FILE *out= fopen(filename, "wt");
138  if(out == NULL)
139  return -1;
140 
141  printf("writing mesh '%s'...\n", filename);
142 
143  const std::vector<vec3>& positions= mesh.positions();
144  for(unsigned int i= 0; i < (unsigned int) positions.size(); i++)
145  fprintf(out, "v %f %f %f\n", positions[i].x, positions[i].y, positions[i].z);
146  fprintf(out, "\n");
147 
148  const std::vector<vec2>& texcoords= mesh.texcoords();
149  bool has_texcoords= (texcoords.size() == positions.size());
150  for(unsigned int i= 0; i < (unsigned int) texcoords.size(); i++)
151  fprintf(out, "vt %f %f\n", texcoords[i].x, texcoords[i].y);
152  fprintf(out, "\n");
153 
154  const std::vector<vec3>& normals= mesh.normals();
155  bool has_normals= (normals.size() == positions.size());
156  for(unsigned int i= 0; i < (unsigned int) normals.size(); i++)
157  fprintf(out, "vn %f %f %f\n", normals[i].x, normals[i].y, normals[i].z);
158  fprintf(out, "\n");
159 
160  const std::vector<unsigned int>& indices= mesh.indices();
161  bool has_indices= (indices.size() > 0);
162  unsigned int n= has_indices ? (unsigned int) indices.size() : (unsigned int) positions.size();
163  for(unsigned int i= 0; i +2 < n; i+= 3)
164  {
165  fprintf(out, "f");
166  for(unsigned int k= 0; k < 3; k++)
167  {
168  unsigned int id= has_indices ? indices[i+k] +1 : i+k +1;
169  fprintf(out, " %u", id);
170  if(has_texcoords && has_normals)
171  fprintf(out, "/%u/%u", id, id);
172  else if(has_texcoords)
173  fprintf(out, "/%u", id);
174  else if(has_normals)
175  fprintf(out, "//%u", id);
176  }
177  fprintf(out, "\n");
178  }
179 
180  fclose(out);
181  return 0;
182 }
vecteur generique, utilitaire.
Definition: vec.h:104
vecteur generique, utilitaire.
Definition: vec.h:94
representation d'un objet / maillage.
Definition: mesh.h:88
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
static Mesh & error()
Definition: mesh.h:250
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
int write_mesh(const Mesh &mesh, const char *filename)
enregistre un mesh dans un fichier .obj.
Definition: wavefront.cpp:125
Mesh & normal(const vec3 &n)
definit la normale du prochain sommet.
Definition: mesh.cpp:43
Mesh & texcoord(const vec2 &uv)
definit les coordonnees de texture du prochain sommet.
Definition: mesh.cpp:49
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: wavefront.cpp:8