cgv
Loading...
Searching...
No Matches
obj_loader.cxx
1#include "obj_loader.h"
2#include <cgv/utils/file.h>
3#include <cgv/type/standard_types.h>
4
5using namespace cgv::utils::file;
6using namespace cgv::type;
7using namespace cgv::media::illum;
8
9#ifdef WIN32
10#pragma warning (disable:4996)
11#endif
12
13namespace cgv {
14 namespace media {
15 namespace mesh {
16
17 line_info::line_info(unsigned _nr, unsigned _vi0, int _ti0, int _ni0, unsigned _gi)
18 : length(_nr),
19 first_vertex_index(_vi0),
20 first_texcoord_index(_ti0),
21 first_normal_index(_ni0),
22 group_index(_gi)
23 {
24 }
25
26 face_info::face_info(unsigned _nr, unsigned _vi0, int _ti0, int _ni0, unsigned _gi, unsigned _mi)
27 : degree(_nr),
28 first_vertex_index(_vi0),
29 first_texcoord_index(_ti0),
30 first_normal_index(_ni0),
31 group_index(_gi),
32 material_index(_mi)
33 {
34 }
35
37template <typename T>
39{
40 vertices.push_back(p);
41}
42
44template <typename T>
46{
47 texcoords.push_back(t);
48}
50template <typename T>
52{
53 normals.push_back(n);
54}
55
56template <typename T>
58{
59 colors.push_back(c);
60}
61
63template <typename T>
64void obj_loader_generic<T>::process_line(unsigned vcount, int* vertices,
65 int* texcoords, int* normals)
66{
67 this->convert_to_positive(vcount, vertices, texcoords, normals,
68 (unsigned)this->vertices.size(), (unsigned)this->normals.size(), (unsigned)this->texcoords.size());
69 lines.push_back(line_info(vcount, (unsigned)vertex_indices.size(),
70 texcoords == 0 ? -1 : (int)texcoord_indices.size(),
71 normals == 0 ? -1 : (int)normal_indices.size(),
72 this->get_current_group()));
73 unsigned i;
74 for (i = 0; i < vcount; ++i)
75 vertex_indices.push_back(vertices[i]);
76 if (normals)
77 for (i = 0; i < vcount; ++i)
78 normal_indices.push_back(normals[i]);
79 if (texcoords)
80 for (i = 0; i < vcount; ++i)
81 texcoord_indices.push_back(texcoords[i]);
82}
83
85template <typename T>
86void obj_loader_generic<T>::process_face(unsigned vcount, int *vertices,
87 int *texcoords, int *normals)
88{
89 this->convert_to_positive(vcount,vertices,texcoords,normals,
90 (unsigned)this->vertices.size(), (unsigned)this->normals.size(), (unsigned)this->texcoords.size());
91 faces.push_back(face_info(vcount,(unsigned)vertex_indices.size(),
92 texcoords == 0 ? -1 : (int)texcoord_indices.size(),
93 normals == 0 ? -1 : (int)normal_indices.size(),
94 this->get_current_group(),this->get_current_material()));
95 unsigned i;
96 for (i=0; i<vcount; ++i)
97 vertex_indices.push_back(vertices[i]);
98 if (normals)
99 for (i=0; i<vcount; ++i)
100 normal_indices.push_back(normals[i]);
101 if (texcoords)
102 for (i=0; i<vcount; ++i)
103 texcoord_indices.push_back(texcoords[i]);
104}
105
106
108template <typename T>
109void obj_loader_generic<T>::process_group(const std::string& name, const std::string& parameters)
110{
111 group_info gi;
112 gi.name = name;
113 gi.parameters = parameters;
114 groups.push_back(gi);
115}
116
118template <typename T>
120{
121 if (idx >= materials.size())
122 materials.push_back(mtl);
123 else
124 materials[idx] = mtl;
125}
126
127template <typename T>
128const char* get_bin_extension()
129{
130 return ".bin_obj";
131}
132
133template <>
134const char* get_bin_extension<float>()
135{
136 return ".bin_objf";
137}
138
140template <typename T>
141bool obj_loader_generic<T>::read_obj(const std::string& file_name)
142{
143 // check if binary file exists
144 std::string bin_fn = drop_extension(file_name) + get_bin_extension<T>();
145 if (exists(bin_fn) &&
146 get_last_write_time(bin_fn) > get_last_write_time(file_name) &&
147 read_obj_bin(bin_fn)) {
148 this->path_name = get_path(file_name);
149 if (!this->path_name.empty())
150 this->path_name += "/";
151 return true;
152 }
153
154 vertices.clear();
155 normals.clear();
156 texcoords.clear();
157 faces.clear();
158 colors.clear();
159
160 if (!obj_reader_generic<T>::read_obj(file_name))
161 return false;
162
163 // correct colors in case of 8bit colors
164 unsigned i;
165 bool do_correct = false;
166 for (i = 0; i < colors.size(); ++i) {
167 if (colors[i][0] > 5 ||colors[i][1] > 5 ||colors[i][2] > 5) {
168 do_correct = true;
169 break;
170 }
171 }
172 if (do_correct) {
173 for (i = 0; i < colors.size(); ++i) {
174 colors[i] *= 1.0f/255;
175 }
176 }
177 write_obj_bin(bin_fn);
178 return true;
179}
180
181template <typename T>
182bool obj_loader_generic<T>::read_obj_bin(const std::string& file_name)
183{
184 // open binary file
185 FILE* fp = fopen(file_name.c_str(), "rb");
186 if (!fp)
187 return false;
188
189 // read element count
190 uint32_type v, n, t, f, h, g, m, l = 0;
191 if (1!=fread(&v, sizeof(uint32_type), 1, fp) ||
192 1!=fread(&n, sizeof(uint32_type), 1, fp) ||
193 1!=fread(&t, sizeof(uint32_type), 1, fp) ||
194 1!=fread(&f, sizeof(uint32_type), 1, fp) ||
195 1!=fread(&h, sizeof(uint32_type), 1, fp) ||
196 1!=fread(&g, sizeof(uint32_type), 1, fp) ||
197 1!=fread(&m, sizeof(uint32_type), 1, fp)) {
198 fclose(fp);
199 return false;
200 }
201 bool has_colors = false;
202 if (v > 0x7FFFFFFF) {
203 v = 0xFFFFFFFF - v;
204 has_colors = true;
205 }
206 bool has_lines = false;
207 if (f > 0x7FFFFFFF) {
208 f = 0xFFFFFFFF - f;
209 has_lines = true;
210 }
211 if (has_lines) {
212 if (1 != fread(&l, sizeof(uint32_type), 1, fp)) {
213 fclose(fp);
214 return false;
215 }
216 }
217 // reserve space
218 vertices.resize(v);
219 if (has_colors)
220 colors.resize(v);
221
222 vertex_indices.resize(h);
223 if (v != fread(&vertices[0], sizeof(vec3_type), v, fp) ||
224 h > 0 && h != fread(&vertex_indices[0], sizeof(unsigned), h, fp) )
225 {
226 fclose(fp);
227 return false;
228 }
229 if (has_colors) {
230 if (v != fread(&colors[0], sizeof(color_type), v, fp))
231 {
232 fclose(fp);
233 return false;
234 }
235 }
236 if (n > 0) {
237 normals.resize(n);
238 normal_indices.resize(h);
239 if (n != fread(&normals[0], sizeof(vec3_type), n, fp) ||
240 h > 0 && h != fread(&normal_indices[0], sizeof(unsigned), h, fp) )
241 {
242 fclose(fp);
243 return false;
244 }
245 }
246 if (t > 0) {
247 texcoords.resize(t);
248 texcoord_indices.resize(h);
249 if (t != fread(&texcoords[0], sizeof(vec2_type), t, fp) ||
250 h > 0 && h != fread(&texcoord_indices[0], sizeof(unsigned), h, fp) )
251 {
252 fclose(fp);
253 return false;
254 }
255 }
256 lines.resize(l);
257 if (l > 0 && l != fread(&lines[0], sizeof(line_info), l, fp))
258 {
259 fclose(fp);
260 return false;
261 }
262 faces.resize(f);
263 if (f > 0 && f != fread(&faces[0], sizeof(face_info), f, fp))
264 {
265 fclose(fp);
266 return false;
267 }
268 groups.resize(g);
269 for (unsigned gi=0; gi<g; ++gi) {
270 if (!read_string_bin(groups[gi].name, fp) ||
271 !read_string_bin(groups[gi].parameters, fp))
272 {
273 fclose(fp);
274 return false;
275 }
276 }
277 if (1 != fread(&this->have_default_material, sizeof(bool), 1, fp))
278 {
279 fclose(fp);
280 return false;
281 }
282 if (this->have_default_material)
283 materials.push_back(obj_material());
284
285 for (unsigned mi=0; mi<m; ++mi) {
286 std::string s;
287 if (!read_string_bin(s, fp)) {
288 fclose(fp);
289 return false;
290 }
292 }
293 fclose(fp);
294 return true;
295}
296
298template <typename T>
300{
302
303 vertices.clear();
304 normals.clear();
305 texcoords.clear();
306
307 vertex_indices.clear();
308 normal_indices.clear();
309 texcoord_indices.clear();
310
311 faces.clear();
312 groups.clear();
313 materials.clear();
314}
315
316template <typename T>
317bool obj_loader_generic<T>::write_obj_bin(const std::string& file_name) const
318{
319 // open binary file
320 FILE* fp = fopen(file_name.c_str(), "wb");
321 if (!fp)
322 return false;
323
324
325
326 // read element count
327 uint32_type v = (unsigned) vertices.size(),
328 n = (unsigned) normals.size(),
329 t = (unsigned) texcoords.size(),
330 f = (unsigned) faces.size(),
331 l = (unsigned) lines.size(),
332 h = (unsigned) vertex_indices.size(),
333 g = (unsigned) groups.size(),
334 m = (unsigned) this->mtl_lib_files.size();
335 uint32_type v_write = v;
336 bool has_colors = (colors.size() == vertices.size());
337 if (has_colors)
338 v_write = 0xFFFFFFFF - v;
339
340 uint32_type f_write = f;
341 if (l > 0)
342 f_write = 0xFFFFFFFF - f;
343
344 if (1!=fwrite(&v_write, sizeof(uint32_type), 1, fp) ||
345 1!=fwrite(&n, sizeof(uint32_type), 1, fp) ||
346 1!=fwrite(&t, sizeof(uint32_type), 1, fp) ||
347 1!=fwrite(&f_write, sizeof(uint32_type), 1, fp) ||
348 1!=fwrite(&h, sizeof(uint32_type), 1, fp) ||
349 1!=fwrite(&g, sizeof(uint32_type), 1, fp) ||
350 1!=fwrite(&m, sizeof(uint32_type), 1, fp)) {
351 fclose(fp);
352 return false;
353 }
354 if (l > 0) {
355 if (1 != fwrite(&l, sizeof(uint32_type), 1, fp)) {
356 fclose(fp);
357 return false;
358 }
359 }
360 if (v != fwrite(&vertices[0], sizeof(vec3_type), v, fp) ||
361 h > 0 && h != fwrite(&vertex_indices[0], sizeof(unsigned), h, fp) )
362 {
363 fclose(fp);
364 return false;
365 }
366
367 if (has_colors) {
368 if (v != fwrite(&colors[0], sizeof(color_type), v, fp) )
369 {
370 fclose(fp);
371 return false;
372 }
373 }
374 if (n > 0) {
375 if (n != fwrite(&normals[0], sizeof(vec3_type), n, fp) ||
376 h > 0 && h != fwrite(&normal_indices[0], sizeof(unsigned), h, fp) )
377 {
378 fclose(fp);
379 return false;
380 }
381 }
382 if (t > 0) {
383 if (t != fwrite(&texcoords[0], sizeof(vec2_type), t, fp) ||
384 h > 0 && h != fwrite(&texcoord_indices[0], sizeof(unsigned), h, fp) )
385 {
386 fclose(fp);
387 return false;
388 }
389 }
390 if (l > 0 && l != fwrite(&lines[0], sizeof(line_info), l, fp))
391 {
392 fclose(fp);
393 return false;
394 }
395 if (f > 0 && f != fwrite(&faces[0], sizeof(face_info), f, fp))
396 {
397 fclose(fp);
398 return false;
399 }
400 for (unsigned gi=0; gi<g; ++gi) {
401 if (!write_string_bin(groups[gi].name, fp) ||
402 !write_string_bin(groups[gi].parameters, fp))
403 {
404 fclose(fp);
405 return false;
406 }
407 }
408
409 if (1 != fwrite(&this->have_default_material, sizeof(bool), 1, fp))
410 {
411 fclose(fp);
412 return false;
413 }
414
415 std::set<std::string>::const_iterator mi = this->mtl_lib_files.begin();
416 for (; mi != this->mtl_lib_files.end(); ++mi) {
417 if (!write_string_bin(*mi, fp))
418 {
419 fclose(fp);
420 return false;
421 }
422 }
423 fclose(fp);
424 return true;
425}
426
427template <typename T>
429{
430 std::cout << "num vertices "<<vertices.size()<<std::endl;
431 std::cout << "num normals "<<normals.size()<<std::endl;
432 std::cout << "num texcoords "<<texcoords.size()<<std::endl;
433 std::cout << "num faces "<<faces.size()<<std::endl;
434 std::cout << "num materials "<<materials.size()<<std::endl;
435 std::cout << "num groups "<<groups.size()<<std::endl;
436}
437
438template class obj_loader_generic < float >;
439template class obj_loader_generic < double >;
440
441
442 }
443 }
444}
complete implementation of method actions that only call one method when entering a node
Definition action.h:113
>extension of a phong material with support for texture mapped color channels
bool write_obj_bin(const std::string &file_name) const
write the information from the last read obj file in binary format
void process_vertex(const vec3_type &p)
overide this function to process a vertex
void process_normal(const vec3_type &n)
overide this function to process a normal
bool read_obj(const std::string &file_name)
overloads reading to support binary file format
void process_face(unsigned vcount, int *vertices, int *texcoords=0, int *normals=0)
overide this function to process a face
void process_material(const cgv::media::illum::obj_material &mtl, unsigned idx)
process a material definition
void show_stats() const
use this after reading to show status information about the number of read entities
void process_color(const color_type &c)
overide this function to process a color (this called for vc prefixes which is is not in the standard...
void clear()
prepare for reading another file
bool read_obj_bin(const std::string &file_name)
read a binary version of an obj file
void process_group(const std::string &name, const std::string &parameters)
overide this function to process a group given by name
void process_line(unsigned vcount, int *vertices, int *texcoords=0, int *normals=0)
overide this function to process a line
void process_texcoord(const vec2_type &t)
overide this function to process a texcoord
virtual bool read_mtl(const std::string &file_name)
read a material file
virtual void clear()
clear the reader such that a new file can be read
implements the pure reading of an obj file and calls virtual callback functions to allow a derived cl...
Definition obj_reader.h:98
namespace for compile time type information
the cgv namespace
Definition print.h:11
simple structure to describe a face
Definition obj_loader.h:16
face_info(unsigned _nr=0, unsigned _vi0=0, int _ti0=-1, int _ni0=-1, unsigned gi=-1, unsigned mi=-1)
construct face info
simple structure to describe a group
Definition obj_loader.h:53
std::string parameters
parameters string
Definition obj_loader.h:57
std::string name
name of the group
Definition obj_loader.h:55
simple structure to describe a line
Definition obj_loader.h:35
line_info(unsigned _nr=0, unsigned _vi0=0, int _ti0=-1, int _ni0=-1, unsigned gi=-1)
construct face info