// Adapted from https://raw.githubusercontent.com/tamato/simple-obj-loader/master/objloader.cpp #include "objloader.hpp" #include #include #include #include #include #include #include namespace inferno::scene { struct FaceVert { FaceVert() : vert(-1), norm(-1), coord(-1) {} int vert; int norm; int coord; }; struct vert_less { bool operator() (const FaceVert& lhs, const FaceVert& rhs) const { // handle any size mesh if (lhs.vert != rhs.vert) return (lhs.vert verts; std::vector norms; std::vector texcoords; std::map uniqueverts; unsigned int vert_count = 0; while (inf.good()) { memset( (void*)line, 0, CHARACTER_COUNT); inf.getline(line, CHARACTER_COUNT); if (inf.eof()) break; char *token = strtok(line, delims); if (token == NULL || token[0] == '#' || token[0] == '$') continue; // verts look like: // v float float float if (strcmp(token, "v") == 0) { float x=0, y=0, z=0, w=1; sscanf(line+2, "%f %f %f %f", &x, &y, &z, &w); verts.push_back( glm::vec3(x/w,y/w,z/w) ); } // normals: // nv float float float else if (strcmp(token, "vn") == 0) { float x=0, y=0, z=0; sscanf(line+3, "%f %f %f", &x, &y, &z); norms.push_back( glm::vec3(x,y,z) ); } // texcoords: // vt float float else if (strcmp(token, "vt") == 0) { float x=0, y=0, z=0; sscanf(line+3, "%f %f %f", &x, &y, &z); texcoords.push_back( glm::vec2(x, y) ); } // keep track of smoothing groups // s [number|off] else if (strcmp(token, "s") == 0) { } // faces start with: // f else if (strcmp(token, "f") == 0) { std::vector vindices; std::vector nindices; std::vector tindices; // fill out a triangle from the line, it could have 3 or 4 edges char *lineptr = line + 2; while (lineptr[0] != 0) { while (lineptr[0] == ' ') ++lineptr; int vi=0, ni=0, ti=0; if (sscanf(lineptr, "%d/%d/%d", &vi, &ni, &ti) == 3) { vindices.push_back(vi-1); nindices.push_back(ni-1); tindices.push_back(ti-1); } else if (sscanf(lineptr, "%d//%d", &vi, &ni) == 2) { vindices.push_back(vi-1); nindices.push_back(ni-1); } else if (sscanf(lineptr, "%d/%d", &vi, &ti) == 2) { vindices.push_back(vi-1); tindices.push_back(ti-1); } else if (sscanf(lineptr, "%d", &vi) == 1) { vindices.push_back(vi-1); } while(lineptr[0] != ' ' && lineptr[0] != 0) ++lineptr; } // being that some exporters can export either 3 or 4 sided polygon's // convert what ever was exported into triangles for (size_t i=1; i 0) mNormals.resize(vert_count); if (texcoords.size() > 0) mTexCoords.resize(vert_count); std::map::iterator iter; for (iter = uniqueverts.begin(); iter != uniqueverts.end(); ++iter) { mPositions[iter->second] = verts[iter->first.vert]; if ( norms.size() > 0 ) { mNormals[iter->second] = norms[iter->first.norm]; } if ( texcoords.size() > 0) { mTexCoords[iter->second] = texcoords[iter->first.coord]; } } } int ObjLoader::getIndexCount() { yolo::debug("Face count: {}", mFaces.size()); return (int)mFaces.size() * 3; } int ObjLoader::getVertCount() { return (int)mPositions.size(); } const uint32_t* ObjLoader::getFaces() { return (const uint32_t*)&mFaces[0]; } const float* ObjLoader::getPositions() { return (const float*)&mPositions[0]; } const float* ObjLoader::getNormals() { return (const float*)&mNormals[0]; } uint32_t ObjLoader::getTexCoordLayers() { return mTexCoordLayers; } const float* ObjLoader::getTexCoords(int multiTexCoordLayer) { assert(multiTexCoordLayer < mTexCoordLayers); return (const float*)&mTexCoords[0]; } }