gKit2 light

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

- File List
- File Members

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 }
vec3
vecteur generique, utilitaire.
Definition: vec.h:104
vec2
vecteur generique, utilitaire.
Definition: vec.h:94
Mesh
representation d'un objet / maillage.
Definition: mesh.h:88
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
Mesh::error
static Mesh & error()
Definition: mesh.h:250
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
wavefront.h
write_mesh
int write_mesh(const Mesh &mesh, const char *filename)
enregistre un mesh dans un fichier .obj.
Definition: wavefront.cpp:125
Mesh::normal
Mesh & normal(const vec3 &n)
definit la normale du prochain sommet.
Definition: mesh.cpp:43
Mesh::texcoord
Mesh & texcoord(const vec2 &uv)
definit les coordonnees de texture du prochain sommet.
Definition: mesh.cpp:49
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: wavefront.cpp:8