/*! \brief load the geometry defined in an OBJ/Wavefront file * \param filename is the path to the OJB file */ ObjReader::ObjReader(const char *filename) { std::ifstream ifs; // extract the path from the filename (used to read the material file) std::string path = getFilePath(filename); try { ifs.open(filename); if (ifs.fail()) throw std::runtime_error("can't open file " + std::string(filename)); // create a default material std::shared_ptr<Material> defaultMaterial(new Material("Default")); curMaterial = defaultMaterial; char line[MAX_LINE_LENGTH]; // line buffer while (ifs.peek() != EOF) // read each line until EOF is found { ifs.getline(line, sizeof(line), '\n'); const char* token = line + strspn(line, " \t"); // ignore space and tabs //printf("strncmp(token, vt, 2) --> %d\n", strncmp(token, "vt", 2)); if (token[0] == 0) continue; // line is empty, ignore // read a vertex if (token[0] == 'v' && isSep(token[1])) { v.push_back(getVec3f(token += 2)); continue; } // read a normal if (!strncmp(token, "vn", 2) && isSep(token[2])) { vn.push_back(getVec3f(token += 3)); continue; } // read a texture coordinates if (!strncmp(token, "vt", 2) && isSep(token[2])) { vt.push_back(getVec2f(token += 3)); continue; } //if (!strncmp(token, "vt", 2) && isSep(token[2])) { printf("vt: %.3f\n", getVec2f(token += 3).x); continue; } // read a face if (token[0] == 'f' && isSep(token[1])) { parseSep(token += 1); std::vector<Vertex> face; while (token[0]) { face.push_back(getInt3(token)); parseSepOpt(token); } curGroup.push_back(face); continue; } /*! use material */ if (!strncmp(token, "usemtl", 6) && isSep(token[6])) { flushFaceGroup(); std::string name(parseSep(token += 6)); if (materials.find(name) == materials.end()) curMaterial = defaultMaterial; else curMaterial = materials[name]; continue; } /* load material library */ if (!strncmp(token, "mtllib", 6) && isSep(token[6])) { loadMTL(path + "/" + std::string(parseSep(token += 6))); continue; } } } catch (const std::exception &e) { std::cerr << e.what() << std::endl; } flushFaceGroup(); // flush the last loaded object ifs.close(); }
OBJLoader::OBJLoader(const FileName &fileName, const bool subdivMode) : path(fileName.path()), group(new SceneGraph::GroupNode), subdivMode(subdivMode) { /* open file */ std::ifstream cin; cin.open(fileName.c_str()); if (!cin.is_open()) { THROW_RUNTIME_ERROR("cannot open " + fileName.str()); return; } /* generate default material */ Material objmtl; new (&objmtl) OBJMaterial; Ref<SceneGraph::MaterialNode> defaultMaterial = new SceneGraph::MaterialNode(objmtl); curMaterial = defaultMaterial; char line[10000]; memset(line, 0, sizeof(line)); while (cin.peek() != -1) { /* load next multiline */ char* pline = line; while (true) { cin.getline(pline, sizeof(line) - (pline - line) - 16, '\n'); ssize_t last = strlen(pline) - 1; if (last < 0 || pline[last] != '\\') break; pline += last; *pline++ = ' '; } const char* token = trimEnd(line + strspn(line, " \t")); if (token[0] == 0) continue; /*! parse position */ if (token[0] == 'v' && isSep(token[1])) { v.push_back(getVec3f(token += 2)); continue; } /* parse normal */ if (token[0] == 'v' && token[1] == 'n' && isSep(token[2])) { vn.push_back(getVec3f(token += 3)); continue; } /* parse texcoord */ if (token[0] == 'v' && token[1] == 't' && isSep(token[2])) { vt.push_back(getVec2f(token += 3)); continue; } /*! parse face */ if (token[0] == 'f' && isSep(token[1])) { parseSep(token += 1); std::vector<Vertex> face; while (token[0]) { Vertex vtx = getInt3(token); face.push_back(vtx); parseSepOpt(token); } curGroup.push_back(face); continue; } /*! parse edge crease */ if (token[0] == 'e' && token[1] == 'c' && isSep(token[2])) { parseSep(token += 2); float w = getFloat(token); parseSepOpt(token); int a = fix_v(getInt(token)); parseSepOpt(token); int b = fix_v(getInt(token)); parseSepOpt(token); ec.push_back(Crease(w, a, b)); continue; } /*! use material */ if (!strncmp(token, "usemtl", 6) && isSep(token[6])) { flushFaceGroup(); std::string name(parseSep(token += 6)); if (material.find(name) == material.end()) curMaterial = defaultMaterial; else curMaterial = material[name]; continue; } /* load material library */ if (!strncmp(token, "mtllib", 6) && isSep(token[6])) { loadMTL(path + std::string(parseSep(token += 6))); continue; } // ignore unknown stuff } flushFaceGroup(); cin.close(); }