Это как бы я это сделал.Вы также можете использовать operator>>
для каждого типа, если вам это нравится.
Отличия от вашего примера:
Я игнорирую все, кроме вершин и граней, и предполагаю, что в вертах нет w и нет vt, vn, vp и т. д. в файле.Возможно, есть имена, группы, материалы и т. Д., С которыми вы тоже можете столкнуться.Если у вас возникли проблемы с головой или ваше желание писать парсеры ослабло, вы можете проверить библиотеку, чтобы сделать это.http://www.assimp.org/ хороший, и здесь есть хороший зритель http://www.open3mod.com/, который определенно может помочь, если то, что вы анализируете, выглядит не совсем правильно.
Ваш код токенизирован изаписывая прямо в переменные назначения, я сначала выбрал токенизацию, а затем преобразовал токены в правильный тип после некоторой базовой проверки строки.Либо работает.Обычно я делаю это так, как вы, возможно, с помощью operator>>
или вспомогательной функции.
Я протестировал несколько файлов здесь: https://people.sc.fsu.edu/~jburkardt/data/obj/obj.html
Надеюсь, это поможет.
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
struct vertex
{
double x, y, z;
};
struct face
{
std::vector<int> v;
};
struct object
{
std::vector<vertex> verts;
std::vector<face> faces;
};
std::ostream& operator<<(std::ostream& out, const vertex& v)
{
out << "v "
<< std::fixed << std::setprecision(6) << v.x << " "
<< std::fixed << std::setprecision(6) << v.y << " "
<< std::fixed << std::setprecision(6) << v.z;
return out;
}
std::ostream& operator<<(std::ostream& out, const face& f)
{
out << "f";
for (size_t i = 0; i < f.v.size(); ++i)
{
out << " " << f.v[i];
}
return out;
}
std::ostream& operator<<(std::ostream& out, const object& o)
{
for (size_t i = 0; i < o.verts.size(); ++i)
{
out << o.verts[i] << "\n";
}
for (size_t i = 0; i < o.faces.size(); ++i)
{
out << o.faces[i] << "\n";
}
return out;
}
std::vector<std::string> split(const std::string& s)
{
std::vector<std::string> ret;
std::string token;
std::stringstream ss(s);
while (ss >> token)
{
ret.push_back(token);
}
return ret;
}
int main(int argc, char **argv)
{
if (argc != 2)
{
std::cerr << "Usage: " << argv[0] << " <obj filename>\n";
return -1;
}
std::fstream in(argv[1]);
if (!in)
{
std::cerr << "File: " << argv[1] << " could not be opened\n";
return -1;
}
object o;
std::string line;
int lineNumber = 0;
while (std::getline(in, line))
{
++lineNumber;
if (line.empty() || line[0] == '#')
{
continue;
}
std::vector<std::string> tokens = split(line);
if (line[0] == 'v')
{
if (tokens.size() < 4)
{
std::cerr << "Invalid vert: '" << line << "' on line: " << lineNumber << "\n";
continue;
}
vertex v;
v.x = std::stod(tokens[1]);
v.y = std::stod(tokens[2]);
v.z = std::stod(tokens[3]);
o.verts.push_back(v);
}
else if (line[0] == 'f')
{
if (tokens.size() < 4)
{
std::cerr << "Invalid face: '" << line << "' on line: " << lineNumber << "\n";
continue;
}
face f;
for (size_t i = 1; i < tokens.size(); ++i)
{
f.v.push_back(std::stoi(tokens[i]));
}
o.faces.push_back(f);
}
}
std::cout << o;
return 0;
}