Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "objloader.h"
- istream &safeGetline(istream &is, string &t)
- {
- t.clear();
- istream::sentry se(is, true);
- auto sb = is.rdbuf();
- for (;;)
- {
- auto c = sb->sbumpc();
- switch (c)
- {
- case '\n':
- return is;
- case '\r':
- if ('\n' == sb->sgetc())
- sb->sbumpc();
- return is;
- case EOF:
- if (t.empty())
- is.setstate(ios::eofbit);
- return is;
- default:
- t += static_cast<char>(c);
- }
- }
- }
- string parseString(const char **token) {
- string s;
- *token += strspn(*token, " \n\t");
- auto e = strcspn(*token, " \n\t\r");
- s = string(*token, &(*token)[e]);
- *token += e;
- return s;
- }
- struct VerticeA
- {
- float x;
- float y;
- float z;
- };
- struct NormalA
- {
- float x;
- float y;
- float z;
- };
- struct UVA
- {
- float u;
- float v;
- };
- struct FaceIndexes
- {
- int v;
- int vt;
- int vn;
- };
- struct Face
- {
- FaceIndexes point[3];
- };
- struct ObjectAttributes
- {
- int vcnt = 0;
- int ncnt = 0;
- int tcnt = 0;
- int fcnt = 0;
- vector<VerticeA> vertices;
- vector<NormalA> normals;
- vector<UVA> uvs;
- vector<Face> faces;
- string name;
- };
- static const unordered_map<string, function<void(ObjectAttributes& attrib, string arguments)>> ProcessMap =
- {
- {
- "v",
- [](ObjectAttributes& attrib, string arguments)
- {
- auto cs = arguments.c_str();
- auto nextfloat = [&cs]() { size_t sz; auto f = stof(string(cs), &sz); cs += sz; return f; };
- attrib.vertices.push_back({ nextfloat(), nextfloat(), nextfloat() });
- ++attrib.vcnt;
- }
- },
- {
- "vt",
- [](ObjectAttributes& attrib, string arguments)
- {
- auto cs = arguments.c_str();
- auto nextfloat = [&cs]() { size_t sz; auto f = stof(string(cs), &sz); cs += sz; return f; };
- attrib.uvs.push_back({ nextfloat(), nextfloat() });
- ++attrib.tcnt;
- }
- },
- {
- "vn",
- [](ObjectAttributes& attrib, string arguments)
- {
- auto cs = arguments.c_str();
- auto nextfloat = [&cs]() { size_t sz; auto f = stof(string(cs), &sz); cs += sz; return f; };
- attrib.normals.push_back({ nextfloat(), nextfloat(), nextfloat() });
- ++attrib.ncnt;
- }
- },
- {
- "f",
- [](ObjectAttributes& attrib, string arguments)
- {
- auto cs = arguments.c_str();
- auto token = &cs;
- Face f;
- for (auto i = 0; i < 3; ++i)
- {
- string indexes = parseString(token);
- auto cs = indexes.c_str();
- auto nextindex = [&cs]()
- {
- size_t sz;
- auto f = stof(string(cs), &sz);
- cs += sz;
- if ('/' == *cs)
- ++cs;
- return f;
- };
- f.point[i].v = static_cast<int>(nextindex());
- f.point[i].vt = static_cast<int>(nextindex());
- f.point[i].vn = static_cast<int>(nextindex());
- }
- attrib.faces.push_back(f);
- ++attrib.fcnt;
- }
- },
- {
- "o",
- [](ObjectAttributes& attrib, string arguments)
- {
- auto cs = arguments.c_str();
- auto token = &cs;
- attrib.name = parseString(token);
- }
- },
- {
- "s",
- [](ObjectAttributes& attrib, string arguments)
- {
- //cout << "[SMOOTH GROUP]" << endl;
- }
- }
- };
- bool ProcessString(string currentString, ObjectAttributes& attrib)
- {
- static int line;
- ++line;
- auto cs = currentString.c_str();
- auto token = &cs;
- string parameter = parseString(token);
- if (parameter.empty() || '#' == parameter.at(0))
- return true;
- try
- {
- string arguments(*token);
- ProcessMap.at(parameter)(attrib, arguments);
- return true;
- }
- catch (out_of_range)
- {
- cout << "Obj Loader: Unsuppoted parameter: [" << parameter << "] line: " << line << endl;
- return false;
- }
- }
- void LoadObj(string filename)
- {
- cout << "Obj Loader: load file [" << filename << "]" << endl;
- ifstream ifs(filename);
- if (!ifs)
- {
- cout << "Cannot open file!" << endl;
- return;
- }
- ObjectAttributes attrib;
- while (true)
- {
- string currentString;
- safeGetline(ifs, currentString);
- if (ifs.eof())
- break;
- if (!ifs)
- {
- cout << "Cannot read file!" << endl;
- return;
- }
- if (!ProcessString(currentString, attrib))
- return;
- }
- cout << "Mesh [" << attrib.name << "]" << endl;
- cout << "Vertices:\t" << attrib.vcnt << endl;
- cout << "Normals:\t" << attrib.ncnt << endl;
- cout << "UVs:\t" << attrib.tcnt << endl;
- cout << "Faces:\t" << attrib.fcnt << endl;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement