5 #ifndef GLVERTEX_OBJFORMAT_H
6 #define GLVERTEX_OBJFORMAT_H
15 const char *name =
"obj file")
17 bool hasv, hasvc, hasvn, hasvt;
19 std::vector<vec3> vertices;
20 std::vector<vec3f> colors;
21 std::vector<vec3f> normals;
22 std::vector<vec2f> uvs;
24 std::vector<int> vertexIndices, normalIndices, uvIndices;
28 lglError(
"improper obj file handle");
32 hasv = hasvc = hasvn = hasvt =
false;
40 int result = fscanf(file,
"%127s", lineHeader);
43 if (result == EOF)
break;
46 if (strcmp(lineHeader,
"v") == 0)
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);
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));
62 vertices.push_back(vertex);
63 colors.push_back(color);
68 else if (strcmp(lineHeader,
"vn") == 0)
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);
76 else if (strcmp(lineHeader,
"vt") == 0)
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);
84 else if (strcmp(lineHeader,
"f") == 0)
86 int vertexIndex[3], normalIndex[3], uvIndex[3];
90 long int rewind = ftell(file);
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]);
99 fseek(file, rewind, SEEK_SET);
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]);
106 uvIndex[0] = uvIndex[1] = uvIndex[2] = -1;
110 fseek(file, rewind, SEEK_SET);
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]);
117 normalIndex[0] = normalIndex[1] = normalIndex[2] = -1;
121 fseek(file, rewind, SEEK_SET);
123 int matches = fscanf(file,
"%d %d %d\n",
128 if (hasvn && normals.size() >= vertices.size())
130 normalIndex[0] = vertexIndex[0];
131 normalIndex[1] = vertexIndex[1];
132 normalIndex[2] = vertexIndex[2];
135 normalIndex[0] = normalIndex[1] = normalIndex[2] = -1;
137 if (hasvt && uvs.size() >= vertices.size())
139 uvIndex[0] = vertexIndex[0];
140 uvIndex[1] = vertexIndex[1];
141 uvIndex[2] = vertexIndex[2];
144 uvIndex[0] = uvIndex[1] = uvIndex[2] = -1;
148 lglError(
"invalid index specification");
155 vertexIndices.push_back(vertexIndex[0]);
156 vertexIndices.push_back(vertexIndex[1]);
157 vertexIndices.push_back(vertexIndex[2]);
159 normalIndices.push_back(normalIndex[0]);
160 normalIndices.push_back(normalIndex[1]);
161 normalIndices.push_back(normalIndex[2]);
163 uvIndices.push_back(uvIndex[0]);
164 uvIndices.push_back(uvIndex[1]);
165 uvIndices.push_back(uvIndex[2]);
169 lglError(
"invalid face specification");
173 else if (strcmp(lineHeader,
"#") == 0)
176 if (fgetc(file) ==
'\n')
break;
178 else if (strcmp(lineHeader,
"o") == 0 ||
179 strcmp(lineHeader,
"s") == 0 ||
180 strcmp(lineHeader,
"g") == 0 ||
181 strcmp(lineHeader,
"l") == 0 ||
182 strcmp(lineHeader,
"mtllib") == 0 ||
183 strcmp(lineHeader,
"usemtl") == 0)
186 if (fgetc(file) ==
'\n')
break;
188 else if (strlen(lineHeader) == 0)
191 if (fgetc(file) ==
'\n')
break;
195 lglError(
"invalid command specification");
209 if (colors.size() != vertices.size())
216 for (
unsigned int i=0; i<vertexIndices.size(); i++)
218 if (vertexIndices.at(i) <= 0 ||
219 vertexIndices.at(i) > (
int)vertices.size())
227 for (
unsigned int i=0; i<normalIndices.size(); i++)
229 if (normalIndices.at(i) == 0 ||
230 normalIndices.at(i) > (
int)normals.size())
238 for (
unsigned int i=0; i<uvIndices.size(); i++)
240 if (uvIndices.at(i) == 0 ||
241 uvIndices.at(i) > (
int)uvs.size())
249 if (!hasvt && texgen != LGL_TEXGEN_NONE) vbo->
lglTexCoordGen(texgen);
255 for (
unsigned int i=0; i<vertexIndices.size(); i++)
259 vbo->lglColor(colors.at(vertexIndices.at(i)-1));
264 int index = normalIndices.at(i);
265 if (index < 0) vbo->lglNormal(0,0,0);
266 else vbo->lglNormal(normals.at(index-1));
272 int index = uvIndices.at(i);
273 if (index < 0) vbo->lglTexCoord(0,0);
277 vec2 uv = uvs.at(index-1);
278 if (flip_v) uv.y = 1 - uv.y;
280 vbo->lglTexCoord(uv);
285 vbo->lglVertex(vertices.at(vertexIndices.at(i)-1));
300 FILE *file = fopen(path,
"rb");
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);
323 if (!ok) ok =
lglLoadObjInto(vbo, (std::string(
"/usr/local/share/") + path).c_str(), texgen, flip_v);
325 if (!ok) ok =
lglLoadObjInto(vbo, (std::string(
"C:\\glvertex\\") + path).c_str(), texgen, flip_v);
329 if (!silent)
lglError(
"cannot read obj file");
341 if (!
lglLoadObj(vbo, path, silent, texgen, flip_v))
353 return(
lglLoadObj(path.c_str(), silent, texgen, flip_v));
361 const char *name =
"obj data")
363 bool hasv, hasvc, hasvn, hasvt;
365 std::vector<vec3> vertices;
366 std::vector<vec3f> colors;
367 std::vector<vec3f> normals;
368 std::vector<vec2f> uvs;
370 std::vector<int> vertexIndices, normalIndices, uvIndices;
380 hasv = hasvc = hasvn = hasvt =
false;
384 char lineHeader[128];
388 int result = sscanf(data,
"%127s%n", lineHeader, &n);
392 if (result == EOF)
break;
395 if (strcmp(lineHeader,
"v") == 0)
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);
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));
409 vertices.push_back(vertex);
410 colors.push_back(color);
416 else if (strcmp(lineHeader,
"vn") == 0)
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);
425 else if (strcmp(lineHeader,
"vt") == 0)
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);
434 else if (strcmp(lineHeader,
"f") == 0)
436 int vertexIndex[3], normalIndex[3], uvIndex[3];
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);
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);
452 uvIndex[0] = uvIndex[1] = uvIndex[2] = -1;
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);
461 normalIndex[0] = normalIndex[1] = normalIndex[2] = -1;
465 int matches = sscanf(data,
"%d %d %d%n\n",
468 &vertexIndex[2], &n);
470 if (hasvn && normals.size() >= vertices.size())
472 normalIndex[0] = vertexIndex[0];
473 normalIndex[1] = vertexIndex[1];
474 normalIndex[2] = vertexIndex[2];
477 normalIndex[0] = normalIndex[1] = normalIndex[2] = -1;
479 if (hasvt && uvs.size() >= vertices.size())
481 uvIndex[0] = vertexIndex[0];
482 uvIndex[1] = vertexIndex[1];
483 uvIndex[2] = vertexIndex[2];
486 uvIndex[0] = uvIndex[1] = uvIndex[2] = -1;
490 lglError(
"invalid index specification");
497 vertexIndices.push_back(vertexIndex[0]);
498 vertexIndices.push_back(vertexIndex[1]);
499 vertexIndices.push_back(vertexIndex[2]);
501 normalIndices.push_back(normalIndex[0]);
502 normalIndices.push_back(normalIndex[1]);
503 normalIndices.push_back(normalIndex[2]);
505 uvIndices.push_back(uvIndex[0]);
506 uvIndices.push_back(uvIndex[1]);
507 uvIndices.push_back(uvIndex[2]);
513 lglError(
"invalid face specification");
517 else if (strcmp(lineHeader,
"#") == 0)
520 if (*data++ ==
'\n')
break;
522 else if (strcmp(lineHeader,
"o") == 0 ||
523 strcmp(lineHeader,
"s") == 0 ||
524 strcmp(lineHeader,
"g") == 0 ||
525 strcmp(lineHeader,
"l") == 0 ||
526 strcmp(lineHeader,
"mtllib") == 0 ||
527 strcmp(lineHeader,
"usemtl") == 0)
530 if (*data++ ==
'\n')
break;
532 else if (strlen(lineHeader) == 0)
535 if (*data++ ==
'\n')
break;
539 lglError(
"invalid command specification");
553 if (colors.size() != vertices.size())
560 for (
unsigned int i=0; i<vertexIndices.size(); i++)
562 if (vertexIndices.at(i) <= 0 ||
563 vertexIndices.at(i) > (
int)vertices.size())
571 for (
unsigned int i=0; i<normalIndices.size(); i++)
573 if (normalIndices.at(i) == 0 ||
574 normalIndices.at(i) > (
int)normals.size())
582 for (
unsigned int i=0; i<uvIndices.size(); i++)
584 if (uvIndices.at(i) == 0 ||
585 uvIndices.at(i) > (
int)uvs.size())
593 if (!hasvt && texgen != LGL_TEXGEN_NONE) vbo->
lglTexCoordGen(texgen);
599 for (
unsigned int i=0; i<vertexIndices.size(); i++)
603 vbo->lglColor(colors.at(vertexIndices.at(i)-1));
608 int index = normalIndices.at(i);
609 if (index < 0) vbo->lglNormal(0,0,0);
610 else vbo->lglNormal(normals.at(index-1));
616 int index = uvIndices.at(i);
617 if (index < 0) vbo->lglTexCoord(0,0);
621 vec2 uv = uvs.at(index-1);
622 if (flip_v) uv.y = 1 - uv.y;
624 vbo->lglTexCoord(uv);
629 vbo->lglVertex(vertices.at(vertexIndices.at(i)-1));
645 const char *name =
"obj data")
665 lglError(
"improper obj file handle");
674 lglError(
"unsupported primitive type");
683 for (
unsigned int i=0; i<vertices.size(); i++)
685 fprintf(file,
"v %f %f %f\n", vertices[i].x, vertices[i].y, vertices[i].z);
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);
689 for (
unsigned int i=0; i<normals.size(); i++)
691 fprintf(file,
"vn %f %f %f\n", normals[i].x, normals[i].y, normals[i].z);
693 for (
unsigned int i=0; i<texcoords.size(); i++)
696 fprintf(file,
"vt %f %f\n", texcoords[i].x, 1 - texcoords[i].y);
698 fprintf(file,
"vt %f %f\n", texcoords[i].x, texcoords[i].y);
702 for (
unsigned int i=2; i<vertices.size(); i+=3)
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);
711 fprintf(file,
"f %u/%u %u/%u %u/%u\n", j-2,k-2, j-1,k-1, j,k);
713 fprintf(file,
"f %u//%u %u//%u %u//%u\n", j-2,l-2, j-1,l-1, j,l);
715 fprintf(file,
"f %u %u %u\n", j-2, j-1, j);
720 for (
unsigned int i=3; i<vertices.size(); i+=4)
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);
729 fprintf(file,
"f %u/%u %u/%u %u/%u\n", j-3,k-3, j-2,k-2, j-1,k-1);
731 fprintf(file,
"f %u//%u %u//%u %u//%u\n", j-3,l-3, j-2,l-2, j-1,l-1);
733 fprintf(file,
"f %u %u %u\n", j-3, j-2, j-1);
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);
738 fprintf(file,
"f %u/%u %u/%u %u/%u\n", j,k, j-2,k-2, j-1,k-1);
740 fprintf(file,
"f %u//%u %u//%u %u//%u\n", j,l, j-2,l-2, j-1,l-1);
742 fprintf(file,
"f %u %u %u\n", j, j-2, j-1);
748 vec4 v1(0), v2(0), v3(0);
750 for (
unsigned int i=0; i<vertices.size(); i++)
757 if (v1!=v2 && v2!=v3 && v3!=v1)
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);
768 fprintf(file,
"f %u/%u %u/%u %u/%u\n", j-2,k-2, j-1,k-1, j,k);
770 fprintf(file,
"f %u//%u %u//%u %u//%u\n", j-2,l-2, j-1,l-1, j,l);
772 fprintf(file,
"f %u %u %u\n", j-2, j-1, j);
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);
779 fprintf(file,
"f %u/%u %u/%u %u/%u\n", j,k, j-1,k-1, j-2,k-2);
781 fprintf(file,
"f %u//%u %u//%u %u//%u\n", j,l, j-1,l-1, j-2,l-2);
783 fprintf(file,
"f %u %u %u\n", j, j-1, j-2);
789 index += vertices.size();
797 inline bool lglSaveObj(
lglVBO *vbo,
const char *path,
bool silent =
false,
bool flip_v =
true)
801 FILE *file = fopen(path,
"wb");
805 fprintf(file,
"# glVertex OBJ File\n\n");
817 if (!silent)
lglError(
"cannot write obj file");
823 inline bool lglSaveObj(
lglVBO *vbo, std::string path,
bool silent =
false,
bool flip_v =
true)
825 return(
lglSaveObj(vbo, path.c_str(), silent, flip_v));