I'm trying to write a reader for Wavefront .OBJ files so I can draw meshes in OpenGL. To do this, I've tried to accumulate some basic C++ file IO knowledge since I mostly know java. I understand from this questions answer that >>
can be used to read in data from the stream.
My strategy for reading my OBJ file is too first read in the char which identifies what the next pieces of data are, then keep trying to read in the numbers until I can't anymore. Then I try to read in the next char. My code is as follows:
std::ifstream objReader;
objReader.open("resources//file.obj");
char m;
int vindex = 0;
int iindex = 0;
while (objReader >> m) {
std::cout << "here" << std::endl;
if (m == 'v') {
GLfloat cv;
while (objReader >> cv) {
objData[vindex] = cv; //obj data is my verticies array to be drawn
std::cout << objData[vindex] << std::endl;
vindex++;
}
}
else if (m == 'f') {
GLuint ci;
while (objReader >> ci) {
indicies[iindex] = ci; //indicies is my EBO array
std::cout << indicies[iindex] << std::endl;
iindex++;
}
}
}
The file data I'm using can be found here.
Now when I run this code, it opens up the file fine and it sucesfully reads in the first line. It indetifies the marker as the char v
then it stores the following 3 floats into my array. The problem is, it just ends there. The loop breaks and it never even continues to the second line. Somehow, it can no longer find any other chars in the file. Why does this happen and how can I fix it?
Thanks!
Your inner loop parses the floats like this:
while (objReader >> cv)
I'm assuming that this GLfloat
is a typedef
for a float
or a double
, based on your description.
The only way that this loop ends is when the operator>>
fails. And when operator>>
fails, it puts the stream into an error state. After the error state is set, all subsequent operations on the stream fail automatically.
So, subsequent to this, when execution returns to the top level loop the second time around:
while (objReader >> m) {
This will now fail immediately, because the stream is now in an error state.
You could manually clear the error state, but this is not really a clean way to handle input.
If you always expect three float values, replace the inner loop with a for
loop that iterates three times.
If the number of float variables varies, I guess you can stick with your current approach, and explicitly clear the error condition by invoking the clear()
method, after the while loop:
objReader.clear();
For a simple parsing requirement that's probably good enough...