Jump to content
  • Advertisement
Sign in to follow this  
silentcoder89

Need advice on my first obj file loader (just saying that Im a noob.. TQ)

This topic is 2910 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi All,

I'm a newcomer in 3D programming.
Currently, i'm working on a project to load an OBJ file using CsGL wrapper for OpenGL in C#. I realized that my obj loader cannot read an obj file if the 'f v/vn/vt...' commands isn't put at the end of the file (for example, if the content of the obj file is like the following, the loader runs just fine.

v 1 1 1
v 1 1 -1
v 1 -1 1
v 1 -1 -1
v -1 1 1
v -1 1 -1
v -1 -1 1
v -1 -1 -1
f 1 3 4 2
f 1 5 6 2
f 1 5 6 2
f 3 7 8 4
f 1 5 7 3
f 2 6 8 4

however, if the 'f ...' commands relocated somewhere in the middle of the obj file, like the following,

v 1 1 1
v 1 1 -1
v 1 -1 1
v 1 -1 -1
f 1 3 4 2
f 1 5 6 2
f 1 5 6 2
f 3 7 8 4
f 1 5 7 3
f 2 6 8 4
v -1 1 1
v -1 1 -1
v -1 -1 1
v -1 -1 -1

the loader will crash. (i knew what caused it, and planning to make the loader reads the obj file twice -- 1st read -> collect vertices informations, 2nd read -> collect faces information. however, i think it will cause performance problem.

will someone take a look at my code (in the following link) and give suggestions on improving it?

http://hotfile.com/dl/52025645/661417e/first_obj_loader.still.contain.bug.zip.html

thank you in advance.

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by silentcoder89
planning to make the loader reads the obj file twice -- 1st read -> collect vertices informations, 2nd read -> collect faces information. however, i think it will cause performance problem.
Why in two passes? You could just collect both vertex and face data in one pass through the file, close it and then work on assembling the mesh from the face indices afterwards.

Share this post


Link to post
Share on other sites
Quote:
Original post by dmatter
Why in two passes? You could just collect both vertex and face data in one pass through the file, close it and then work on assembling the mesh from the face indices afterwards.

Because, in my loader, i stored the vertices in an arrayList, then created the faces "on-the-fly" while reading the 'f..' command. as we know, the f command in obj file is in this syntax - f v1/vn1/vt1, which v or vn or vt is the index of vertices which are required to construct the face. However, what if the vertices that certain 'f..' command refers isn't yet loaded into the array? say -

[vertex index:100] v 1 1 1 1
f 100 101 102
[vertex index:101] v 1 0 1 -1
[vertex index:102] v 1 0 0 0

what about the above? according to the 'f..' command, it takes the vertices from index 100, 101, and 102. Maybe the 100th vertex will do, but i don't think the 101st n 102nd will be available to be referred. Because, it doesn't yet loaded into the array.

Or did we should load all the information first (into the array) then construct it? My approach is -- construct on the fly. (inside the file reading loop)
Thanks for your help.


Share this post


Link to post
Share on other sites
Quote:
Original post by silentcoder89
However, what if the vertices that certain 'f..' command refers isn't yet loaded into the array?
A well-formed obj file wouldn't do that to you, faces should only reference backwards into the file. That said, it's always a good idea to code defensively and it'd be a more robust loader if you can handle this case.

Quote:
Or did we should load all the information first (into the array) then construct it? My approach is -- construct on the fly. (inside the file reading loop)
Yes. It is easier to simply load all infos in first and then construct the mesh. It's also certainly better than scanning through the file twice.

Share this post


Link to post
Share on other sites
i see. But, won't it be 'time-taking'? I got your point. I'll implement that right away. Meanwhile, is it ideal to use ArrayList to store the vertices and faces information? Im seeking a better way. And i'm trying to use the traditional array. But it wasn't dynamic. So, it will be a bit hard to implement.

Share this post


Link to post
Share on other sites
Side question: is there that much flexibility in the .obj file type that different exporters can inject face data in the middle of a vert list? I've only really used Blender to create .obj files, so I may be uninformed here, but I always had face lists after all vert data was written.

When I wrote my .obj loader for a Java library, I just maintained a list of Face objects that stored their verts (edit: well, the vert's index), and as I read in individual v lines I appended to an Arraylist (vector). That way no matter what order you read in the data, the faces should refer to valid array indexes when you go to render polygons.

Share this post


Link to post
Share on other sites
Here's a partial rewrite of your code to make it shorter. Completely untested.


void LoadObj(string filename)
{
try
{
using (StreamReader sr = new StreamReader(filename, System.Text.ASCIIEncoding.ASCII))
{
string line;
while ((line = sr.ReadLine()) != null)
{
line = line.Trim();
if (line.Length == 0 || line.StartsWith("#")) continue;

if (line[0] == 'v')
{
ParseVertex(line);
}
else if (line[0] == 'f')
{
//...
}
}
}
}
catch (Exception e)
{
//...
}
}

void ParseVertex(string line)
{
string[] cLine = line.Split(' ');
float a = float.Parse(cLine[1]);
float b = float.Parse(cLine[2]);
float c = cLine.Length <= 3 ? 0.0f : float.Parse(cLine[3]);

switch (line[1])
{
case 't':
VTexture.Add(new VertexTexture(a, b, c));
break;
case 'n':
VNormal.Add(new VertexNormal(a, b, c));
break;
default:
Vertices.Add(new Vertex(a, b, c));
break;
}
}



Also, you should use List<> instead of ArrayList:

List<Vertex> Vertices = new List<Vertex>();
List<VertexTexture> VTexture = new List<VertexTexture>();
List<VertexNormal> VNormal = new List<VertexNormal>();
List<Face> Faces = new List<Face>();

Share this post


Link to post
Share on other sites
Side question: is there that much flexibility in the .obj file type that different exporters can inject face data in the middle of a vert list?[/QUOTE]
I'm not sure. But most of them puts the face commands at the end of the file. Try to take a look at one of the model in this site http://www.oyonale.com/modeles.php?lang=en&format=OBJ, i can't load most of it's obj file.

Share this post


Link to post
Share on other sites

Also, you should use List<> instead of ArrayList:

List<Vertex> Vertices = new List<Vertex>();
List<VertexTexture> VTexture = new List<VertexTexture>();
List<VertexNormal> VNormal = new List<VertexNormal>();
List<Face> Faces = new List<Face>();

[/QUOTE]

Actually i'm not so familiar with it. Would you care to explain?

Share this post


Link to post
Share on other sites
According to MSDN (I was curious) the List<> collection is the generic equivalent of the ArrayList, and in most cases performs better. It still grants you the ability to search by index like an ArrayList would.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!