我正在用C ++编写一个光线跟踪器程序。该程序的一部分应该能够从mesh.obj文件中读取3D模型。
我目前在使用std::ifstream
阅读文件时遇到问题。
我编写了一个函数read_mesh
,它接受一个字符串参数,该参数指定用户给出的.obj文件的路径。该函数返回一个三角形基元列表,用于渲染网格。
我正在使用LOG(INFO) << "specific info";
,以便我能够查看我的计划中发生了什么。
这是我的功能:
std::vector<Primitive> read_mesh(const std::string& path) const
{
LOG(INFO) << "Reading mesh";
LOG(INFO) << "Attempting to open file at " << path;
std::ifstream obj;
obj.exceptions(std::ifstream::failbit | std::ifstream::badbit);
// Open the file from the given path
try {
obj.open(path, ios::in);
}
catch (std::ifstream::failure::exception e) {
LOG(INFO) << "Exception when opening file \n" << e.what();
}
LOG(INFO) << "File opened";
// Initialize list of vertices
std::vector<Point3D> vertices;
// Initialize list of triangles
std::vector<Primitive> triangles;
std::string line;
// Read each line of the .obj file
while (std::getline(obj, line))
{
LOG(INFO) << "New line";
std::istringstream iss(line);
std::string method;
// Extract the type of data from the line
iss >> method;
// Checks if the data on the line represents a vertex
if (method == "v")
{
double x, y, z;
// Extract the x, y and z coordinates from the line
iss >> x >> y >> z;
LOG(INFO) << "New vertex (" << x << ", " << y << ", " << z << ")";
// Create a Point3D from the coordinates
Point3D p(x, y, z);
// Add the point to the list of vertices
vertices.push_back(p);
}
// Checks if the data on the line represents a set of triangles
else if (method == "f")
{
int a, b, c;
char s;
// Read the set of triangles from the polygon line with the index of the vertices seperated by a '/'
while ((iss >> a >> s >> b >> s >> c) && s == '/')
{
LOG(INFO) << "New triangle (v" << a << ", v" << b << ", v" << c << ")";
// Create a triangle from the corresponding vertices (index -1 because they start at 1 in .obj files) and add it to the triangles list
triangles.push_back(triangle(vertices[a - 1], vertices[b - 1], vertices[b - 1]));
}
}
else
{
LOG(INFO) << "Ignored this line";
}
}
if (!std::getline(obj, line))
{
LOG(INFO) << "Reached end of file";
}
obj.close();
LOG(INFO) << "Finished reading mesh, " << triangles.size() << " triangles found";
// Return the list of triangles
return triangles;
}
我可以看到每一行都被正确读取,在最后一行之后,不再读取任何行。但不是打印&#34;达到文件结束&#34;和#34;完成阅读网格,找到290个三角形&#34;,程序停止执行。
所以我认为问题在于程序从未真正退出while循环,尽管它会停止打印&#34;新行&#34;和&#34;到达行尾&#34;。
任何人都可以帮我找到这个功能的问题吗?非常感谢任何帮助,谢谢!
编辑:
以下示例应用程序使用与上述函数相同的功能:
int main()
{
std::ifstream obj;
obj.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try {
// Enter the path to the example.obj file
obj.open("C:/Users/Bram/Desktop/example-obj.txt", ios::in);
}
catch (std::ifstream::failure::exception e) {
std::cout << "Failed to open file";
return(1);
}
std::cout << "Reading file";
std::string line;
while (std::getline(obj, line))
{
std::cout << "New line";
std::istringstream iss(line);
std::string method;
iss >> method;
if (method == "v")
{
double x, y, z;
iss >> x >> y >> z;
std::cout << "New vertex (" << x << ", " << y << ", " << z << ")";
}
else if (method == "f")
{
int a, b, c;
char s;
while ((iss >> a >> s >> b >> s >> c) && s == '/')
{
std::cout << "New triangle using vertices " << a << ", " << b << ", " << c;
}
}
else
{
std::cout << "Ignored line";
}
}
std::cout << "Finished reading file";
obj.close();
return(0);
}
它读取以下示例-obj.txt文件,该文件代表一个三角形:
# example.obj
v -7.8541 121.3862 17.1093
v 7.1431 113.8654 23.1824
v 15.3955 112.2824 13.7628
f 1/2/3
程序打印正确的顶点和三角形,并在执行时给出以下错误消息:
Unhandled exception at 0x75EA08B2 in meshreader.exe: Microsoft C++ exception: std::ios_base::failure at memory location 0x008FF3F0.
答案 0 :(得分:0)
obj.exceptions(std::ifstream::failbit | std::ifstream::badbit);
这将设置流对象的内部状态,以便在I / O操作尝试设置其中任何一个位时抛出异常。
while (std::getline(obj, line))
这表示要保持循环,直到对std::getline
的调用失败。通常这样做是因为在读取完最后一行之后调用std::getline
时对std::getline
的调用将失败。
但是在这种情况下,当尝试输入失败时,流已设置为抛出异常。因此循环不会正常终止,因为对std::getline
的最终调用会引发异常。
如果删除设置流的行以抛出异常,那么事情将按照您期望的方式运行。