Skip to main content
gamedev.net
🔒 Locked

Model file parser

Started by Jost Jun 16, 2010 at 2:04 PM 9 replies 3k views
Original Post
Jost
Jost
Hi all,

i know, this is probably just another thread in a long row of model loader threads. I am searching for some model file parsing library.

It should be able to parse the most common formats for 3d objects, but it should not implement the data structures into which the data is stored after parsing. I want to do that myself for learning and experimental purposes.

A possible interface for the library i want could be that i register a bunch of callbacks, which are called by the library for every read vertex, normal, texture coordinate, face etc.
Another approach could be, that the library parses the data into internal data structures and then makes it available via some Get/Set methods.

Does someone know a library which is able to do things like that and could give me a hint? It would also be fine, if it is a more complex library, which can be used in the described way.

Greeting, Jost
Jason Z
Jason Z
You might be able to put a callback system on top of AssetImport, although I don't think it does anything like that natively. This is probably a good place to start though, and since it is open source you could always contribute your new callback strategy back to the project.
Jason Zink :: DirectX MVP   Direct3D 11 engine on CodePlex: Hieroglyph 3 Direct3D Books: 
Jost
Jost
Hi,

Assimp looks good, they seem to do what i want. I looked into this library before, but obviously not close enough.

Greetings,
Jost
vertexbuff3r
vertexbuff3r
Hello Jost, I had same goal for an obj loader, but I didn't really found one I liked.

Anything I found on the net similar to same spec as you have, was objlib: http://people.cs.kuleuven.be/~ares.lagae/libobj/index.html.

However it uses stl, boost and c++ and it is kinda too big for my taste, so I have written my own :-). Coded in C, it is 12 kbytes for .mtl importer and 20 kbytes for .obj importer. It parsers all commands of .mtl respective .obj formats and it uses C callbacks and is event based. You kind-a sett callback for vertex command, for face command etc, and those are called and data is passed back to callback when parser reads in respective command.

It should be thread safe too since there is no global data used. Does not create any kind of structure, because I wanted it to be as flexible as possible. Imposing a predefined mesh/material structures is jsut plain unflexible in my eyes.

I have just finnished it, and I would need some help in debugging and testing. If you are interested I might release it. So long I have just written two simple text apps that tests all commands, and one that displays simple materials in glut window. But there are probably many bugs to find out, so I would be glad if somebody else would like to try it.

It is strictly .obj and .mtl importer; no other formats are supported (nor planned).
Jost
Jost
Hi vertexbuff3r,

thanks for your post. I would like to try your loader, although i probably will try libobj first, as my aim is to experiment with shadow volumes, and not with model loaders. On the other hand, libobj was last updated 3 years ago... So please send me your loader as well.

I've tried assimp, and it works, but there is one big drawback: It replicates vertices, even if told to join identical vertices. If i load an .obj file of a cube with 8 vertices for example, assimp gives me an array of 24 (with joining) or 36 (without joining) vertices.

Greeting, Jost
Jost
Jost
So, i have now checked out the libobj thing. Its not usable. It contains a method with this signature:

void face_callbacks(const triangular_face_geometric_vertices_callback_type& triangular_face_geometric_vertices_callback, const triangular_face_geometric_vertices_texture_vertices_callback_type& triangular_face_geometric_vertices_texture_vertices_callback, const triangular_face_geometric_vertices_vertex_normals_callback_type& triangular_face_geometric_vertices_vertex_normals_callback, const triangular_face_geometric_vertices_texture_vertices_vertex_normals_callback_type& triangular_face_geometric_vertices_texture_vertices_vertex_normals_callback, const quadrilateral_face_geometric_vertices_callback_type& quadrilateral_face_geometric_vertices_callback, const quadrilateral_face_geometric_vertices_texture_vertices_callback_type& quadrilateral_face_geometric_vertices_texture_vertices_callback, const quadrilateral_face_geometric_vertices_vertex_normals_callback_type& quadrilateral_face_geometric_vertices_vertex_normals_callback, const quadrilateral_face_geometric_vertices_texture_vertices_vertex_normals_callback_type& quadrilateral_face_geometric_vertices_texture_vertices_vertex_normals_callback, const polygonal_face_geometric_vertices_begin_callback_type& polygonal_face_geometric_vertices_begin_callback, const polygonal_face_geometric_vertices_vertex_callback_type& polygonal_face_geometric_vertices_vertex_callback, const polygonal_face_geometric_vertices_end_callback_type& polygonal_face_geometric_vertices_end_callback, const polygonal_face_geometric_vertices_texture_vertices_begin_callback_type& polygonal_face_geometric_vertices_texture_vertices_begin_callback, const polygonal_face_geometric_vertices_texture_vertices_vertex_callback_type& polygonal_face_geometric_vertices_texture_vertices_vertex_callback, const polygonal_face_geometric_vertices_texture_vertices_end_callback_type& polygonal_face_geometric_vertices_texture_vertices_end_callback, const polygonal_face_geometric_vertices_vertex_normals_begin_callback_type& polygonal_face_geometric_vertices_vertex_normals_begin_callback, const polygonal_face_geometric_vertices_vertex_normals_vertex_callback_type& polygonal_face_geometric_vertices_vertex_normals_vertex_callback, const polygonal_face_geometric_vertices_vertex_normals_end_callback_type& polygonal_face_geometric_vertices_vertex_normals_end_callback, const polygonal_face_geometric_vertices_texture_vertices_vertex_normals_begin_callback_type& polygonal_face_geometric_vertices_texture_vertices_vertex_normals_begin_callback, const polygonal_face_geometric_vertices_texture_vertices_vertex_normals_vertex_callback_type& polygonal_face_geometric_vertices_texture_vertices_vertex_normals_vertex_callback, const polygonal_face_geometric_vertices_texture_vertices_vertex_normals_end_callback_type& polygonal_face_geometric_vertices_texture_vertices_vertex_normals_end_callback);


2819 characters [headshake]
KulSeran
KulSeran
Quote:

I've tried assimp, and it works, but there is one big drawback: It replicates vertices, even if told to join identical vertices. If i load an .obj file of a cube with 8 vertices for example, assimp gives me an array of 24 (with joining) or 36 (without joining) vertices.

Unless your object is untextured, it is going to have to do that. To create an indexed vertex buffer, it has to have unique groups of vertex/uv/normal to index. This means, for a 6 sided cube, you need a minimum 4*6 vert/uv pairs to texture it, since you can't index the vertex and uv sets separately.
Jost
Jost
Why can't i index them separately? It works in Wavefront object files: f 1/1/2 7/2/2 5/3/2. Of course an equivalent storage method would probably be inefficient when rendering (considering that such an approach will probably produce many cache misses), but for some calculations (creating shadow volume silhoulettes) this seems to be better (and easier).

The point at which i am stuck at the moment is the calculation of the set of edges of a closed model - which simply occurs because i can not identify neighboring faces in a simple manner. And i don't want to compare float values, as that will most probably end up in errors (and the exact information was available before).

I guess the fastest way to get this to work is to simply download antlr or something and generate a parser myself, which fits all my needs.
alagtriste
alagtriste
Dis you use some Assimp post process flags? For example:
Assimp post process flags

aiProcess_JoinIdenticalVertices should take care of duplicates if possible. If not possible maybe you should mix it with aiProcess_RemoveComponent.

P.D. It's obvius I don't read carefully your post. Maybe if you just reap all other vertex components (UV, Normals, etc) the joint process gives you the mesh without duplicates. Of course, if you need that data then you should parse data two times (if there are no performance requeriments).
Jost
Jost
Hi alagtriste,

the thing in your P.D. is the same thing i came up with after reading the first part of your post. There are no performance requirements, except the obvious one: It should not take more than some minutes to load a big file.

It is partly implemented that way at the moment, and i'm fine with it for now. Thanks for all the suggestions.

Greetings, Jost

[Edited by - Jost on June 22, 2010 5:55:28 PM]
vertexbuff3r
vertexbuff3r
I do no processing in my loader. It is based on idea that you sett callbacks for stuff you need, and handle data yourself; inclusive of vertices, faces etc.

By the way, to reduce number of vertices you will have to organize data in fans or strips I guess.

I do have one working version; which I can put on the webb but there are some bugs I know of. I also work on another version that will hopefully be more efficient, but I am not done with it yet. If you are intrested to try the one that works just to test the concept I will put it somewhere for the download. Project is done in VS Express; but it easily compiled with gcc (just a bunch of plain old .c files and 2 headers).

This mini cooper model is about 39 meg uncompressed; it reads in few seconds:

http://www.oyonale.com/modeles.php?page=58

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.