Reading in a file.

Started by
13 comments, last by dreamslayerx 12 years, 7 months ago
[attachment=5280:Cube OBJ JPEG.jpg]

Here is a small example of how you could get started parsing the file.
I have to admit, its going to be more than 10 lines lol.
Note that this example is far from finished.
[source lang="cpp"]
void readFile()
{
ifstream inFile("cube.obj"); // Create and open file
if (!inFile.is_open())
{
cout << "Unable to open file" << endl;
exit(1);
}

string line, item, lib;
float x, y, z;

while(getline(inFile, line)) // Continue to read the next line until the end of file
{
stringstream ss(line); // Create a new stringstream and fill it with the line
if(!(ss >> item)) // Extract the first item. If there is no items left, this expression will be false and we continue to read the next line.
continue;

if(item == "#")
continue; // We found a comment. Continue to read the next line.
else if(item == "v")
{
ss >> x >> y >> z; // Extract and convert the next three items from the stream
cout << "We found a v: " << x << " " << y << " " << z << endl;
}
else if(item == "vt")
{
ss >> x >> y; // Extract and convert the next two items from the stream
cout << "We found a vt: " << x << " " << y << endl;
}
else if(item == "mtllib")
{
ss >> lib; // Extract the next item from the stream
cout << "We found a mtllib: " << lib << endl;
}
// And so on...
}
}[/source]

Since an expression like this ss >> x >> y >> z; returns false if there is less that three items left in the stream, we can take advantage of this to make the function a bit more robust:
if(!(ss >> x >> y >> z)) // report error...

Also note that the expression else if(item == "vt") is case sensitive, so it won't match a VT or a Vt.


Nice and clear code. I was looking for a way to read things in clearly. I used your code and here is the output for the v and vt portion below. But the question is how do I handle reading in the face porition of the file. All I want is the integers values and not the / or the spaces. Here is the face porition:

usemtl Material_cube_Cube.bmp

s off

f 5/1 1/2 4/3

f 5/1 4/3 8/4

f 3/5 7/6 8/7

f 3/5 8/7 4/8

f 2/2 6/7 3/9

f 6/7 7/6 3/9

f 1/10 5/5 2/11

f 5/5 6/12 2/11

f 5/9 8/13 6/4

f 8/13 7/14 6/4

f 1/10 2/11 3/13

f 1/10 3/13 4/9


Sometimes faces can also be discrible as f 1/2/3 where 1 is the vertex number, 2 is the vertex texture number, and 3 is the vertex normal.



[color="#0000ff"][color="#0000ff"]void readFile() [color="#008000"][color="#008000"]//Working section Used to count the number of floats in a file. This section can make program slower.

{

ifstream inFile;

inFile.open([color="#a31515"][color="#a31515"]"cube.obj");

[color="#0000ff"][color="#0000ff"]if (!inFile.is_open())

{

cout << [color="#a31515"][color="#a31515"]"Unable to open file"; [color="#008000"][color="#008000"]///C:\Users\Alanzo Granville\Documents\Visual Studio 2008\Projects\Opening_A_File_Program\Opening_A_File_Program

exit(1); [color="#008000"][color="#008000"]/// terminate with error

}
string line, item, lib;

[color="#0000ff"][color="#0000ff"]float x,y,z;

[color="#0000ff"][color="#0000ff"]int v_Num, vt_Num, vn_Num;

[color="#0000ff"][color="#0000ff"]while(getline(inFile, line))

{

stringstream ss(line);

[color="#0000ff"][color="#0000ff"]if(!(ss>>item))

[color="#0000ff"][color="#0000ff"]continue;

[color="#0000ff"][color="#0000ff"]if(item == [color="#a31515"][color="#a31515"]"#")

[color="#0000ff"][color="#0000ff"]continue;

[color="#0000ff"][color="#0000ff"]else [color="#0000ff"][color="#0000ff"]if(item == [color="#a31515"][color="#a31515"]"v")

{

ss>> x>> y >>z;

cout<<[color="#a31515"][color="#a31515"]"We found a v: "<<x <<[color="#a31515"][color="#a31515"]" "<<y<<[color="#a31515"][color="#a31515"]" "<<z<<endl;

}

[color="#0000ff"][color="#0000ff"]else [color="#0000ff"][color="#0000ff"]if(item == [color="#a31515"][color="#a31515"]"vt")

{

ss >> x >> y;

cout<<[color="#a31515"][color="#a31515"]"We found a vt " <<x <<[color="#a31515"][color="#a31515"]" "<<y<<endl;

}

[color="#0000ff"][color="#0000ff"]else [color="#0000ff"][color="#0000ff"]if(item == [color="#a31515"][color="#a31515"]"f") [color="#008000"][color="#008000"]//faces, Here we have to read character by character from file

{

[color="#008000"][color="#008000"]//Assuming I need a loop in the statment to finish reading the entire file



}

[color="#0000ff"][color="#0000ff"]else [color="#0000ff"][color="#0000ff"]if(item ==[color="#a31515"][color="#a31515"]"mtllib")

{

ss>>lib;

cout<<[color="#a31515"][color="#a31515"]"We found a mtllib :" <<lib<<endl;

}

}

}




[/output]

We found a mtllib :cube.mtl
We found a v: 1 -1 -1
We found a v: 1 -1 1
We found a v: -1 -1 1
We found a v: -1 -1 -1
We found a v: 1 1 -1
We found a v: 0.999999 1 1
We found a v: -1 1 1
We found a v: -1 1 -1
We found a vt 0.666667 0
We found a vt 0.666667 0.333333
We found a vt 0.333334 0.333333
We found a vt 0.333333 0
We found a vt 0.333333 1
We found a vt 0.333334 0.666667
We found a vt 0.666667 0.666667
We found a vt 0.666667 1
We found a vt 0.333333 0.333333
We found a vt 0.333333 0.666667
We found a vt 0 0.666667
We found a vt 0 1
We found a vt 0 0.333333
We found a vt 0 0

Press any key to continue . . .

[/output]

Advertisement
Sorry for double posting, but here is something that I have got. Below is the code I wrote,but it doesn't satisfy the condition for normals since it will have two /'s instead of just one.




[color="#0000ff"][color="#0000ff"]else [color="#0000ff"][color="#0000ff"]if(item == [color="#a31515"][color="#a31515"]"f") [color="#008000"][color="#008000"]//faces, Here we have to read character by character from file

{

[color="#008000"][color="#008000"]//Assuming I need a loop in the statment to finish reading the entire file

cout<<ss.str()<<endl;

[color="#0000ff"][color="#0000ff"]char ch;

[color="#0000ff"][color="#0000ff"]int v, vt;

[color="#0000ff"][color="#0000ff"]for(i=0;i<3;i++) [color="#008000"][color="#008000"]//reads 3 faces

{

ss>> v>>ch>>vt;

cout<<v<<[color="#a31515"][color="#a31515"]" "<<ch<<[color="#a31515"][color="#a31515"]" "<<vt<<endl;

}




[/output]

f 5/1 1/2 4/3 //This section of output is from the ss.str() function so that I can read the entire string to ensure the proper output
5 / 1 //These are the outputs which is int v =5, char ch = '/', int vt = 1 and the for loop makes it read 3 times
1 / 2
4 / 3
f 5/1 4/3 8/4
5 / 1
4 / 3
8 / 4
f 3/5 7/6 8/7
3 / 5
7 / 6
8 / 7
f 3/5 8/7 4/8
3 / 5
8 / 7
4 / 8
f 2/2 6/7 3/9
2 / 2
6 / 7
3 / 9
f 6/7 7/6 3/9
6 / 7
7 / 6
3 / 9
f 1/10 5/5 2/11
1 / 10
5 / 5
2 / 11
f 5/5 6/12 2/11
5 / 5
6 / 12
2 / 11
f 5/9 8/13 6/4
5 / 9
8 / 13
6 / 4
f 8/13 7/14 6/4
8 / 13
7 / 14
6 / 4
f 1/10 2/11 3/13
1 / 10
2 / 11
3 / 13
f 1/10 3/13 4/9
1 / 10
3 / 13
4 / 9

Press any key to continue . . .

[/output]

Well done cool.gif

Here is a little twist I made that uses peek to find out if the vertex has a normal



char ch;
int v, vt, n;
for(int i = 0; i < 3; i++)
{
ss >> v >> ch >> vt;
cout << v << " " << ch << " " << vt;
if(ss.peek() == '/')
{
ss >> ch >> n;
cout << " " << ch << " " << n;
}
cout << endl;
}



I would also advice that you store the data in structs, and use the vector as arrays. You can see a good example of that in rip-off's post

Just for future reference, from your first code, this doesn't work the way you think:


if(ch == 'v' || 't'||'f'||'/')


In english, it means: if ch equals v or if t isn't zero or if f isn't zero or if / isn't zero. Since none of the latter three are zero, the condition will always be true.


if(ch == 'v' || ch == 't' || ch == 'f' || ch == '/')


would be correct.


else if(c == 'v')
{
if(stream.peek() == 't')
{
TexPoint texture;
if((stream >> texture.u >> texture.v) && (stream >> std::ws) && stream.eof())


Sorry if having a senior moment, ripoff, but would you not need to consume that 't' after the peek before reading the first number?



Yeah I agree. I am planning on string the data into structs one being struct for vertices, vertex textures, and vertex normals. then the faces will be in a struct called triangles. Thanks guys. I'll show you the results when I display the image usng OpenGL.
OK guys here is the final result. The program works great. I actually built a house model and textured it. The image may be a little off since I had it rotating to check each side. Thanks so much for the help.

[attachment=5386:HouseTextureWithUVs.jpg]

This topic is closed to new replies.

Advertisement