glVertex  5.5.2
glvertex_objformat.h
Go to the documentation of this file.
1 // (c) by Stefan Roettger / Matthias Hopf, licensed under MIT license
2 
5 #ifndef GLVERTEX_OBJFORMAT_H
6 #define GLVERTEX_OBJFORMAT_H
7 
8 #include "glvertex_core.h"
9 
11 inline bool lglLoadObjInto(lglVBO *vbo,
12  FILE *file,
13  lgl_texgenmode_enum texgen = LGL_TEXGEN_NONE,
14  bool flip_v = true,
15  const char *name = "obj file")
16 {
17  bool hasv, hasvc, hasvn, hasvt;
18 
19  std::vector<vec3> vertices;
20  std::vector<vec3f> colors;
21  std::vector<vec3f> normals;
22  std::vector<vec2f> uvs;
23 
24  std::vector<int> vertexIndices, normalIndices, uvIndices;
25 
26  if (file == NULL)
27  {
28  lglError("improper obj file handle");
29  return(false);
30  }
31 
32  hasv = hasvc = hasvn = hasvt = false;
33 
34  while (true)
35  {
36  char lineHeader[128];
37  lineHeader[127] = 0;
38 
39  // read the first word of the line
40  int result = fscanf(file, "%127s", lineHeader);
41 
42  // check for end-of-file
43  if (result == EOF) break;
44 
45  // check first word of the line
46  if (strcmp(lineHeader, "v") == 0)
47  {
48  vec3 vertex;
49  vec3f color;
50  long int rewind = ftell(file);
51  int result = fscanf(file, "%lf %lf %lf %f %f %f\n", &vertex.x, &vertex.y, &vertex.z, &color.r, &color.g, &color.b);
52  if (result != 6)
53  {
54  fseek(file, rewind, SEEK_SET);
55  int result = fscanf(file, "%lf %lf %lf\n", &vertex.x, &vertex.y, &vertex.z);
56  if (result != 3) lglError("invalid vertex specification");
57  else vertices.push_back(vertex);
58  colors.push_back(vec3f(1,1,1));
59  }
60  else
61  {
62  vertices.push_back(vertex);
63  colors.push_back(color);
64  hasvc = true;
65  }
66  hasv = true;
67  }
68  else if (strcmp(lineHeader, "vn") == 0)
69  {
70  vec3f normal;
71  int result = fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
72  if (result != 3) lglError("invalid normal specification");
73  else normals.push_back(normal);
74  hasvn = true;
75  }
76  else if (strcmp(lineHeader, "vt") == 0)
77  {
78  vec2f uv;
79  int result = fscanf(file, "%f %f\n", &uv.x, &uv.y);
80  if (result != 2) lglError("invalid uv specification");
81  else uvs.push_back(uv);
82  hasvt = true;
83  }
84  else if (strcmp(lineHeader, "f") == 0)
85  {
86  int vertexIndex[3], normalIndex[3], uvIndex[3];
87 
88  if (hasv)
89  {
90  long int rewind = ftell(file);
91 
92  int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n",
93  &vertexIndex[0], &uvIndex[0], &normalIndex[0],
94  &vertexIndex[1], &uvIndex[1], &normalIndex[1],
95  &vertexIndex[2], &uvIndex[2], &normalIndex[2]);
96 
97  if (matches != 9)
98  {
99  fseek(file, rewind, SEEK_SET);
100 
101  int matches = fscanf(file, "%d//%d %d//%d %d//%d\n",
102  &vertexIndex[0], &normalIndex[0],
103  &vertexIndex[1], &normalIndex[1],
104  &vertexIndex[2], &normalIndex[2]);
105 
106  uvIndex[0] = uvIndex[1] = uvIndex[2] = -1;
107 
108  if (matches != 6)
109  {
110  fseek(file, rewind, SEEK_SET);
111 
112  int matches = fscanf(file, "%d/%d %d/%d %d/%d\n",
113  &vertexIndex[0], &uvIndex[0],
114  &vertexIndex[1], &uvIndex[1],
115  &vertexIndex[2], &uvIndex[2]);
116 
117  normalIndex[0] = normalIndex[1] = normalIndex[2] = -1;
118 
119  if (matches != 6)
120  {
121  fseek(file, rewind, SEEK_SET);
122 
123  int matches = fscanf(file, "%d %d %d\n",
124  &vertexIndex[0],
125  &vertexIndex[1],
126  &vertexIndex[2]);
127 
128  if (hasvn && normals.size() >= vertices.size())
129  {
130  normalIndex[0] = vertexIndex[0];
131  normalIndex[1] = vertexIndex[1];
132  normalIndex[2] = vertexIndex[2];
133  }
134  else
135  normalIndex[0] = normalIndex[1] = normalIndex[2] = -1;
136 
137  if (hasvt && uvs.size() >= vertices.size())
138  {
139  uvIndex[0] = vertexIndex[0];
140  uvIndex[1] = vertexIndex[1];
141  uvIndex[2] = vertexIndex[2];
142  }
143  else
144  uvIndex[0] = uvIndex[1] = uvIndex[2] = -1;
145 
146  if (matches != 3)
147  {
148  lglError("invalid index specification");
149  return(false);
150  }
151  }
152  }
153  }
154 
155  vertexIndices.push_back(vertexIndex[0]);
156  vertexIndices.push_back(vertexIndex[1]);
157  vertexIndices.push_back(vertexIndex[2]);
158 
159  normalIndices.push_back(normalIndex[0]);
160  normalIndices.push_back(normalIndex[1]);
161  normalIndices.push_back(normalIndex[2]);
162 
163  uvIndices.push_back(uvIndex[0]);
164  uvIndices.push_back(uvIndex[1]);
165  uvIndices.push_back(uvIndex[2]);
166  }
167  else
168  {
169  lglError("invalid face specification");
170  return(false);
171  }
172  }
173  else if (strcmp(lineHeader, "#") == 0)
174  {
175  while (!feof(file))
176  if (fgetc(file) == '\n') break;
177  }
178  else if (strcmp(lineHeader, "o") == 0 || // skip object names
179  strcmp(lineHeader, "s") == 0 || // skip object smoothing
180  strcmp(lineHeader, "g") == 0 || // skip group names
181  strcmp(lineHeader, "l") == 0 || // skip indexed lines
182  strcmp(lineHeader, "mtllib") == 0 || // skip material libraries
183  strcmp(lineHeader, "usemtl") == 0) // skip materials
184  {
185  while (!feof(file))
186  if (fgetc(file) == '\n') break;
187  }
188  else if (strlen(lineHeader) == 0) // skip empty lines
189  {
190  while (!feof(file))
191  if (fgetc(file) == '\n') break;
192  }
193  else
194  {
195  lglError("invalid command specification");
196  return(false);
197  }
198  }
199 
200  // check for vertices
201  if (!hasv)
202  {
203  lglError("invalid vertex count");
204  return(false);
205  }
206 
207  // check vertex colors
208  if (hasvc)
209  if (colors.size() != vertices.size())
210  {
211  lglError("invalid color count");
212  return(false);
213  }
214 
215  // check vertex indices
216  for (unsigned int i=0; i<vertexIndices.size(); i++)
217  {
218  if (vertexIndices.at(i) <= 0 ||
219  vertexIndices.at(i) > (int)vertices.size())
220  {
221  lglError("invalid vertex index");
222  return(false);
223  }
224  }
225 
226  // check normal indices
227  for (unsigned int i=0; i<normalIndices.size(); i++)
228  {
229  if (normalIndices.at(i) == 0 ||
230  normalIndices.at(i) > (int)normals.size())
231  {
232  lglError("invalid normal index");
233  return(false);
234  }
235  }
236 
237  // check uv indices
238  for (unsigned int i=0; i<uvIndices.size(); i++)
239  {
240  if (uvIndices.at(i) == 0 ||
241  uvIndices.at(i) > (int)uvs.size())
242  {
243  lglError("invalid uv index");
244  return(false);
245  }
246  }
247 
248  // setup vbo
249  if (!hasvt && texgen != LGL_TEXGEN_NONE) vbo->lglTexCoordGen(texgen);
250 
251  // start vbo
252  vbo->lglBegin(LGL_TRIANGLES);
253 
254  // for each vertex of each triangle
255  for (unsigned int i=0; i<vertexIndices.size(); i++)
256  {
257  // define vertex color attribute
258  if (hasvc)
259  vbo->lglColor(colors.at(vertexIndices.at(i)-1));
260 
261  // define vertex normal attribute
262  if (hasvn)
263  {
264  int index = normalIndices.at(i);
265  if (index < 0) vbo->lglNormal(0,0,0);
266  else vbo->lglNormal(normals.at(index-1));
267  }
268 
269  // define vertex texture coordinate attribute
270  if (hasvt)
271  {
272  int index = uvIndices.at(i);
273  if (index < 0) vbo->lglTexCoord(0,0);
274  else
275  {
276  // flip uv origin
277  vec2 uv = uvs.at(index-1);
278  if (flip_v) uv.y = 1 - uv.y;
279 
280  vbo->lglTexCoord(uv);
281  }
282  }
283 
284  // put the vertex and its attributes into vbo
285  vbo->lglVertex(vertices.at(vertexIndices.at(i)-1));
286  }
287 
288  // finish vbo
289  vbo->lglEnd();
290 
291  // set vbo name
292  vbo->setName(name);
293 
294  return(true);
295 }
296 
298 inline bool lglLoadObjInto(lglVBO *vbo, const char *path, lgl_texgenmode_enum texgen = LGL_TEXGEN_NONE, bool flip_v = true)
299 {
300  FILE *file = fopen(path, "rb");
301 
302  if (file)
303  {
304  bool ok = lglLoadObjInto(vbo, file, texgen, flip_v, path);
305  fclose(file);
306  return(ok);
307  }
308 
309  return(false);
310 }
311 
313 inline bool lglLoadObj(lglVBO *vbo, const char *path, bool silent = false, lgl_texgenmode_enum texgen = LGL_TEXGEN_NONE, bool flip_v = true)
314 {
315  bool ok = lglLoadObjInto(vbo, path, texgen);
316 
317  if (!ok) ok = lglLoadObjInto(vbo, (std::string("../") + path).c_str(), texgen, flip_v);
318  if (!ok) ok = lglLoadObjInto(vbo, (std::string("obj/") + path).c_str(), texgen, flip_v);
319  if (!ok) ok = lglLoadObjInto(vbo, (std::string("../obj/") + path).c_str(), texgen, flip_v);
320  if (!ok) ok = lglLoadObjInto(vbo, (std::string("data/") + path).c_str(), texgen, flip_v);
321  if (!ok) ok = lglLoadObjInto(vbo, (std::string("../data/") + path).c_str(), texgen, flip_v);
322 #ifndef _WIN32
323  if (!ok) ok = lglLoadObjInto(vbo, (std::string("/usr/local/share/") + path).c_str(), texgen, flip_v);
324 #else
325  if (!ok) ok = lglLoadObjInto(vbo, (std::string("C:\\glvertex\\") + path).c_str(), texgen, flip_v);
326 #endif
327 
328  if (!ok)
329  if (!silent) lglError("cannot read obj file");
330 
331  return(ok);
332 }
333 
335 inline lglVBO *lglLoadObj(const char *path, bool silent = false, lgl_texgenmode_enum texgen = LGL_TEXGEN_MIXED_HEDGEHOG, bool flip_v = true)
336 {
337  // create vbo
338  lglVBO *vbo = new lglVBO;
339 
340  // load vbo
341  if (!lglLoadObj(vbo, path, silent, texgen, flip_v))
342  {
343  delete vbo;
344  return(NULL);
345  }
346 
347  return(vbo);
348 }
349 
351 inline lglVBO *lglLoadObj(std::string path, bool silent = false, lgl_texgenmode_enum texgen = LGL_TEXGEN_MIXED_HEDGEHOG, bool flip_v = true)
352 {
353  return(lglLoadObj(path.c_str(), silent, texgen, flip_v));
354 }
355 
357 inline bool lglLoadObjData(lglVBO *vbo,
358  const char *data,
359  lgl_texgenmode_enum texgen = LGL_TEXGEN_NONE,
360  bool flip_v = true,
361  const char *name = "obj data")
362 {
363  bool hasv, hasvc, hasvn, hasvt;
364 
365  std::vector<vec3> vertices;
366  std::vector<vec3f> colors;
367  std::vector<vec3f> normals;
368  std::vector<vec2f> uvs;
369 
370  std::vector<int> vertexIndices, normalIndices, uvIndices;
371 
372  int n;
373 
374  if (data == NULL)
375  {
376  lglError("improper obj data");
377  return(false);
378  }
379 
380  hasv = hasvc = hasvn = hasvt = false;
381 
382  while (true)
383  {
384  char lineHeader[128];
385  lineHeader[127] = 0;
386 
387  // read the first word of the line
388  int result = sscanf(data, "%127s%n", lineHeader, &n);
389  data += n;
390 
391  // check for end-of-file
392  if (result == EOF) break;
393 
394  // check first word of the line
395  if (strcmp(lineHeader, "v") == 0)
396  {
397  vec3 vertex;
398  vec3f color;
399  int result = sscanf(data, "%lf %lf %lf %f %f %f%n\n", &vertex.x, &vertex.y, &vertex.z, &color.r, &color.g, &color.b, &n);
400  if (result != 6)
401  {
402  int result = sscanf(data, "%lf %lf %lf%n\n", &vertex.x, &vertex.y, &vertex.z, &n);
403  if (result != 3) lglError("invalid vertex specification");
404  else vertices.push_back(vertex);
405  colors.push_back(vec3f(1,1,1));
406  }
407  else
408  {
409  vertices.push_back(vertex);
410  colors.push_back(color);
411  hasvc = true;
412  }
413  hasv = true;
414  data += n;
415  }
416  else if (strcmp(lineHeader, "vn") == 0)
417  {
418  vec3f normal;
419  int result = sscanf(data, "%f %f %f%n\n", &normal.x, &normal.y, &normal.z, &n);
420  if (result != 3) lglError("invalid normal specification");
421  else normals.push_back(normal);
422  hasvn = true;
423  data += n;
424  }
425  else if (strcmp(lineHeader, "vt") == 0)
426  {
427  vec2f uv;
428  int result = sscanf(data, "%f %f%n\n", &uv.x, &uv.y, &n);
429  if (result != 2) lglError("invalid uv specification");
430  else uvs.push_back(uv);
431  hasvt = true;
432  data += n;
433  }
434  else if (strcmp(lineHeader, "f") == 0)
435  {
436  int vertexIndex[3], normalIndex[3], uvIndex[3];
437 
438  if (hasv)
439  {
440  int matches = sscanf(data, "%d/%d/%d %d/%d/%d %d/%d/%d%n\n",
441  &vertexIndex[0], &uvIndex[0], &normalIndex[0],
442  &vertexIndex[1], &uvIndex[1], &normalIndex[1],
443  &vertexIndex[2], &uvIndex[2], &normalIndex[2], &n);
444 
445  if (matches != 9)
446  {
447  int matches = sscanf(data, "%d//%d %d//%d %d//%d%n\n",
448  &vertexIndex[0], &normalIndex[0],
449  &vertexIndex[1], &normalIndex[1],
450  &vertexIndex[2], &normalIndex[2], &n);
451 
452  uvIndex[0] = uvIndex[1] = uvIndex[2] = -1;
453 
454  if (matches != 6)
455  {
456  int matches = sscanf(data, "%d/%d %d/%d %d/%d%n\n",
457  &vertexIndex[0], &uvIndex[0],
458  &vertexIndex[1], &uvIndex[1],
459  &vertexIndex[2], &uvIndex[2], &n);
460 
461  normalIndex[0] = normalIndex[1] = normalIndex[2] = -1;
462 
463  if (matches != 6)
464  {
465  int matches = sscanf(data, "%d %d %d%n\n",
466  &vertexIndex[0],
467  &vertexIndex[1],
468  &vertexIndex[2], &n);
469 
470  if (hasvn && normals.size() >= vertices.size())
471  {
472  normalIndex[0] = vertexIndex[0];
473  normalIndex[1] = vertexIndex[1];
474  normalIndex[2] = vertexIndex[2];
475  }
476  else
477  normalIndex[0] = normalIndex[1] = normalIndex[2] = -1;
478 
479  if (hasvt && uvs.size() >= vertices.size())
480  {
481  uvIndex[0] = vertexIndex[0];
482  uvIndex[1] = vertexIndex[1];
483  uvIndex[2] = vertexIndex[2];
484  }
485  else
486  uvIndex[0] = uvIndex[1] = uvIndex[2] = -1;
487 
488  if (matches != 3)
489  {
490  lglError("invalid index specification");
491  return(false);
492  }
493  }
494  }
495  }
496 
497  vertexIndices.push_back(vertexIndex[0]);
498  vertexIndices.push_back(vertexIndex[1]);
499  vertexIndices.push_back(vertexIndex[2]);
500 
501  normalIndices.push_back(normalIndex[0]);
502  normalIndices.push_back(normalIndex[1]);
503  normalIndices.push_back(normalIndex[2]);
504 
505  uvIndices.push_back(uvIndex[0]);
506  uvIndices.push_back(uvIndex[1]);
507  uvIndices.push_back(uvIndex[2]);
508 
509  data += n;
510  }
511  else
512  {
513  lglError("invalid face specification");
514  return(false);
515  }
516  }
517  else if (strcmp(lineHeader, "#") == 0)
518  {
519  while (*data!='\0')
520  if (*data++ == '\n') break;
521  }
522  else if (strcmp(lineHeader, "o") == 0 || // skip object names
523  strcmp(lineHeader, "s") == 0 || // skip object smoothing
524  strcmp(lineHeader, "g") == 0 || // skip group names
525  strcmp(lineHeader, "l") == 0 || // skip indexed lines
526  strcmp(lineHeader, "mtllib") == 0 || // skip material libraries
527  strcmp(lineHeader, "usemtl") == 0) // skip materials
528  {
529  while (*data!='\0')
530  if (*data++ == '\n') break;
531  }
532  else if (strlen(lineHeader) == 0) // skip empty lines
533  {
534  while (*data!='\0')
535  if (*data++ == '\n') break;
536  }
537  else
538  {
539  lglError("invalid command specification");
540  return(false);
541  }
542  }
543 
544  // check for vertices
545  if (!hasv)
546  {
547  lglError("invalid vertex count");
548  return(false);
549  }
550 
551  // check vertex colors
552  if (hasvc)
553  if (colors.size() != vertices.size())
554  {
555  lglError("invalid color count");
556  return(false);
557  }
558 
559  // check vertex indices
560  for (unsigned int i=0; i<vertexIndices.size(); i++)
561  {
562  if (vertexIndices.at(i) <= 0 ||
563  vertexIndices.at(i) > (int)vertices.size())
564  {
565  lglError("invalid vertex index");
566  return(false);
567  }
568  }
569 
570  // check normal indices
571  for (unsigned int i=0; i<normalIndices.size(); i++)
572  {
573  if (normalIndices.at(i) == 0 ||
574  normalIndices.at(i) > (int)normals.size())
575  {
576  lglError("invalid normal index");
577  return(false);
578  }
579  }
580 
581  // check uv indices
582  for (unsigned int i=0; i<uvIndices.size(); i++)
583  {
584  if (uvIndices.at(i) == 0 ||
585  uvIndices.at(i) > (int)uvs.size())
586  {
587  lglError("invalid uv index");
588  return(false);
589  }
590  }
591 
592  // setup vbo
593  if (!hasvt && texgen != LGL_TEXGEN_NONE) vbo->lglTexCoordGen(texgen);
594 
595  // start vbo
596  vbo->lglBegin(LGL_TRIANGLES);
597 
598  // for each vertex of each triangle
599  for (unsigned int i=0; i<vertexIndices.size(); i++)
600  {
601  // define vertex color attribute
602  if (hasvc)
603  vbo->lglColor(colors.at(vertexIndices.at(i)-1));
604 
605  // define vertex normal attribute
606  if (hasvn)
607  {
608  int index = normalIndices.at(i);
609  if (index < 0) vbo->lglNormal(0,0,0);
610  else vbo->lglNormal(normals.at(index-1));
611  }
612 
613  // define vertex texture coordinate attribute
614  if (hasvt)
615  {
616  int index = uvIndices.at(i);
617  if (index < 0) vbo->lglTexCoord(0,0);
618  else
619  {
620  // flip uv origin
621  vec2 uv = uvs.at(index-1);
622  if (flip_v) uv.y = 1 - uv.y;
623 
624  vbo->lglTexCoord(uv);
625  }
626  }
627 
628  // put the vertex and its attributes into vbo
629  vbo->lglVertex(vertices.at(vertexIndices.at(i)-1));
630  }
631 
632  // finish vbo
633  vbo->lglEnd();
634 
635  // set vbo name
636  vbo->setName(name);
637 
638  return(true);
639 }
640 
642 inline lglVBO *lglLoadObjData(const char *data,
643  lgl_texgenmode_enum texgen = LGL_TEXGEN_NONE,
644  bool flip_v = true,
645  const char *name = "obj data")
646 {
647  // create vbo
648  lglVBO *vbo = new lglVBO;
649 
650  // load vbo
651  if (!lglLoadObjData(vbo, data, texgen, flip_v, name))
652  {
653  delete vbo;
654  return(NULL);
655  }
656 
657  return(vbo);
658 }
659 
661 inline bool lglSaveObjInto(lglVBO *vbo, FILE *file, int &index, int &nindex, int &tindex, bool flip_v = true)
662 {
663  if (file == NULL)
664  {
665  lglError("improper obj file handle");
666  return(false);
667  }
668 
669  if (vbo->lglGetVertexMode() != LGL_TRIANGLES &&
670  vbo->lglGetVertexMode() != LGL_QUADS &&
671  vbo->lglGetVertexMode() != LGL_TRIANGLE_STRIP &&
672  vbo->lglGetVertexMode() != LGL_QUAD_STRIP)
673  {
674  lglError("unsupported primitive type");
675  return(false);
676  }
677 
678  std::vector<vec4> vertices = vbo->lglGetVertexCoordinates();
679  std::vector<vec4f> colors = vbo->lglGetColorAttributes();
680  std::vector<vec3f> normals = vbo->lglGetNormalAttributes();
681  std::vector<vec4f> texcoords = vbo->lglGetTexCoordAttributes();
682 
683  for (unsigned int i=0; i<vertices.size(); i++)
684  if (!vbo->lglActiveColoring())
685  fprintf(file, "v %f %f %f\n", vertices[i].x, vertices[i].y, vertices[i].z);
686  else
687  fprintf(file, "v %f %f %f %f %f %f\n", vertices[i].x, vertices[i].y, vertices[i].z, colors[i].r, colors[i].g, colors[i].b);
688 
689  for (unsigned int i=0; i<normals.size(); i++)
690  if (vbo->lglActiveLighting())
691  fprintf(file, "vn %f %f %f\n", normals[i].x, normals[i].y, normals[i].z);
692 
693  for (unsigned int i=0; i<texcoords.size(); i++)
694  if (vbo->lglActiveTexturing())
695  if (flip_v)
696  fprintf(file, "vt %f %f\n", texcoords[i].x, 1 - texcoords[i].y); // flip uv origin
697  else
698  fprintf(file, "vt %f %f\n", texcoords[i].x, texcoords[i].y);
699 
700  if (vbo->lglGetVertexMode() == LGL_TRIANGLES)
701  {
702  for (unsigned int i=2; i<vertices.size(); i+=3)
703  {
704  int j = i+index;
705  int k = i+tindex;
706  int l = i+nindex;
707 
708  if (vbo->lglActiveLighting() && vbo->lglActiveTexturing())
709  fprintf(file, "f %u/%u/%u %u/%u/%u %u/%u/%u\n", j-2,k-2,l-2, j-1,k-1,l-1, j,k,l);
710  else if (vbo->lglActiveTexturing())
711  fprintf(file, "f %u/%u %u/%u %u/%u\n", j-2,k-2, j-1,k-1, j,k);
712  else if (vbo->lglActiveLighting())
713  fprintf(file, "f %u//%u %u//%u %u//%u\n", j-2,l-2, j-1,l-1, j,l);
714  else
715  fprintf(file, "f %u %u %u\n", j-2, j-1, j);
716  }
717  }
718  else if (vbo->lglGetVertexMode() == LGL_QUADS)
719  {
720  for (unsigned int i=3; i<vertices.size(); i+=4)
721  {
722  int j = i+index;
723  int k = i+tindex;
724  int l = i+nindex;
725 
726  if (vbo->lglActiveLighting() && vbo->lglActiveTexturing())
727  fprintf(file, "f %u/%u/%u %u/%u/%u %u/%u/%u\n", j-3,k-3,l-3, j-2,k-2,l-2, j-1,k-1,l-1);
728  else if (vbo->lglActiveTexturing())
729  fprintf(file, "f %u/%u %u/%u %u/%u\n", j-3,k-3, j-2,k-2, j-1,k-1);
730  else if (vbo->lglActiveLighting())
731  fprintf(file, "f %u//%u %u//%u %u//%u\n", j-3,l-3, j-2,l-2, j-1,l-1);
732  else
733  fprintf(file, "f %u %u %u\n", j-3, j-2, j-1);
734 
735  if (vbo->lglActiveLighting() && vbo->lglActiveTexturing())
736  fprintf(file, "f %u/%u/%u %u/%u/%u %u/%u/%u\n", j,k,l, j-2,k-2,l-2, j-1,k-1,l-1);
737  else if (vbo->lglActiveTexturing())
738  fprintf(file, "f %u/%u %u/%u %u/%u\n", j,k, j-2,k-2, j-1,k-1);
739  else if (vbo->lglActiveLighting())
740  fprintf(file, "f %u//%u %u//%u %u//%u\n", j,l, j-2,l-2, j-1,l-1);
741  else
742  fprintf(file, "f %u %u %u\n", j, j-2, j-1);
743  }
744  }
745  else if (vbo->lglGetVertexMode() == LGL_TRIANGLE_STRIP ||
746  vbo->lglGetVertexMode() == LGL_QUAD_STRIP)
747  {
748  vec4 v1(0), v2(0), v3(0);
749 
750  for (unsigned int i=0; i<vertices.size(); i++)
751  {
752  v1 = v2;
753  v2 = v3;
754  v3 = vertices[i];
755 
756  if (i > 1)
757  if (v1!=v2 && v2!=v3 && v3!=v1)
758  {
759  int j = i+index;
760  int k = i+tindex;
761  int l = i+nindex;
762 
763  if (i%2 == 0)
764  {
765  if (vbo->lglActiveLighting() && vbo->lglActiveTexturing())
766  fprintf(file, "f %u/%u/%u %u/%u/%u %u/%u/%u\n", j-2,k-2,l-2, j-1,k-1,l-1, j,k,l);
767  else if (vbo->lglActiveTexturing())
768  fprintf(file, "f %u/%u %u/%u %u/%u\n", j-2,k-2, j-1,k-1, j,k);
769  else if (vbo->lglActiveLighting())
770  fprintf(file, "f %u//%u %u//%u %u//%u\n", j-2,l-2, j-1,l-1, j,l);
771  else
772  fprintf(file, "f %u %u %u\n", j-2, j-1, j);
773  }
774  else
775  {
776  if (vbo->lglActiveLighting() && vbo->lglActiveTexturing())
777  fprintf(file, "f %u/%u/%u %u/%u/%u %u/%u/%u\n", j,k,l, j-1,k-1,l-1, j-2,k-2,l-2);
778  else if (vbo->lglActiveTexturing())
779  fprintf(file, "f %u/%u %u/%u %u/%u\n", j,k, j-1,k-1, j-2,k-2);
780  else if (vbo->lglActiveLighting())
781  fprintf(file, "f %u//%u %u//%u %u//%u\n", j,l, j-1,l-1, j-2,l-2);
782  else
783  fprintf(file, "f %u %u %u\n", j, j-1, j-2);
784  }
785  }
786  }
787  }
788 
789  index += vertices.size();
790  if (vbo->lglActiveLighting()) nindex += normals.size();
791  if (vbo->lglActiveTexturing()) tindex += texcoords.size();
792 
793  return(true);
794 }
795 
797 inline bool lglSaveObj(lglVBO *vbo, const char *path, bool silent = false, bool flip_v = true)
798 {
799  bool ok = false;
800 
801  FILE *file = fopen(path, "wb");
802 
803  if (file)
804  {
805  fprintf(file, "# glVertex OBJ File\n\n");
806 
807  int index = 1;
808  int nindex = 1;
809  int tindex = 1;
810 
811  ok = lglSaveObjInto(vbo, file, index, nindex, tindex, flip_v);
812 
813  fclose(file);
814  }
815 
816  if (!ok)
817  if (!silent) lglError("cannot write obj file");
818 
819  return(ok);
820 }
821 
823 inline bool lglSaveObj(lglVBO *vbo, std::string path, bool silent = false, bool flip_v = true)
824 {
825  return(lglSaveObj(vbo, path.c_str(), silent, flip_v));
826 }
827 
828 #endif
lglSaveObjInto
bool lglSaveObjInto(lglVBO *vbo, FILE *file, int &index, int &nindex, int &tindex, bool flip_v=true)
save vbo to file descriptor
Definition: glvertex_objformat.h:661
vec3f
3D float vector
Definition: glslmath.h:584
lgl::lglGetVertexCoordinates
std::vector< vec4 > lglGetVertexCoordinates() const
return a copy of the vertex coordinates in vbo
Definition: glvertex_core.h:1893
lgl::lglGetTexCoordAttributes
std::vector< vec4f > lglGetTexCoordAttributes() const
return a copy of the texture coordinate attributes in vbo
Definition: glvertex_core.h:1919
lgl::lglTexCoordGen
void lglTexCoordGen(lgl_texgenmode_enum mode=LGL_TEXGEN_LINEAR, double mix=0.5)
enable texture coordinate generation
Definition: glvertex_core.h:4327
vec2
2D double vector
Definition: glslmath.h:108
lgl::lglGetColorAttributes
std::vector< vec4f > lglGetColorAttributes() const
return a copy of the color attributes in vbo
Definition: glvertex_core.h:1901
vec4
4D double vector
Definition: glslmath.h:713
lgl::lglActiveTexturing
bool lglActiveTexturing() const
check for active vertex texture coordinate attributes
Definition: glvertex_core.h:3334
lgl::lglEnd
void lglEnd()
end a series of vertices
Definition: glvertex_core.h:981
vec2f
2D float vector
Definition: glslmath.h:261
vec3
3D double vector
Definition: glslmath.h:372
lglLoadObjInto
bool lglLoadObjInto(lglVBO *vbo, FILE *file, lgl_texgenmode_enum texgen=LGL_TEXGEN_NONE, bool flip_v=true, const char *name="obj file")
load OBJ into vbo from file descriptor
Definition: glvertex_objformat.h:11
lglLoadObj
bool lglLoadObj(lglVBO *vbo, const char *path, bool silent=false, lgl_texgenmode_enum texgen=LGL_TEXGEN_NONE, bool flip_v=true)
load OBJ into vbo from file path (and from default installation paths)
Definition: glvertex_objformat.h:313
lglError
void lglError(std::string e)
generate an error message
Definition: glvertex_api.h:928
glvertex_core.h
lgl::lglActiveColoring
bool lglActiveColoring() const
check for active vertex color attributes
Definition: glvertex_core.h:3316
lglVBO
LGL API: vbo class definition.
Definition: glvertex_core.h:5827
lglLoadObjData
bool lglLoadObjData(lglVBO *vbo, const char *data, lgl_texgenmode_enum texgen=LGL_TEXGEN_NONE, bool flip_v=true, const char *name="obj data")
load OBJ into vbo from memory chunk
Definition: glvertex_objformat.h:357
lgl_texgenmode_enum
lgl_texgenmode_enum
texgen mode enum
Definition: glvertex_core.h:56
lgl::lglBegin
void lglBegin(lgl_primitive_enum primitive)
begin a series of vertices for a particular graphics primitive
Definition: glvertex_core.h:917
lglSaveObj
bool lglSaveObj(lglVBO *vbo, const char *path, bool silent=false, bool flip_v=true)
save vbo into OBJ file
Definition: glvertex_objformat.h:797
lgl::lglGetVertexMode
lgl_primitive_enum lglGetVertexMode() const
get the primitive mode of vertices contained in vbo
Definition: glvertex_core.h:1784
lgl::lglGetNormalAttributes
std::vector< vec3f > lglGetNormalAttributes() const
return a copy of the normal attributes in vbo
Definition: glvertex_core.h:1910
lgl::setName
void setName(std::string name="")
set the vbo name
Definition: glvertex_core.h:209
lgl::lglActiveLighting
bool lglActiveLighting() const
check for active vertex normal attributes
Definition: glvertex_core.h:3328