Jump to content

  • Log In with Google      Sign In   
  • Create Account


Create a parser for blender.obj file to use in Opengl


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
15 replies to this topic

#1 Michael_Ruff   Members   -  Reputation: 101

Like
0Likes
Like

Posted 05 November 2013 - 07:09 AM

Im trying to finish up a project I been working on. I took a floor plan of a house in blender and made a 3D model house with windows and doors. I want to put that into openGl and be able to walk through the home but I havent been able to understand the parsing. Ive downloaded a few that people have created and all of them have errors. Is there any way someone can help me understand the parser or know of where i can get one just to get my blender program into opengl



Sponsor:

#2 haegarr   Crossbones+   -  Reputation: 3995

Like
2Likes
Like

Posted 05 November 2013 - 07:26 AM


Is there any way someone can help me understand the parser ...

For sure. Please ask explicit questions along with snippets of code about it, if available. So we could answer your questions.


Edited by haegarr, 05 November 2013 - 07:27 AM.


#3 samoth   Crossbones+   -  Reputation: 4660

Like
6Likes
Like

Posted 05 November 2013 - 08:09 AM

Going a slightly different route, if you do not want to do this for academic purposes (that is, your goal is to produce something that works), I recommend that you use

 

a) a different format (obj is pretty much a horrible format, and Blender can export much better formats).

b) Assimp. It works, and it works better that what most people can write in several weeks of time.

 

What format you use is up to you in the end, but for example Collada is able to much better represent not only 3D scenes but also other data that belongs to it.

 

The difference won't be visible on a scene with a ground plane and house with a dozen vertices. But it will become apparent once you want to go further from there and have more complex geometry, include some characters that are animated, etc. etc.


Edited by samoth, 05 November 2013 - 08:11 AM.


#4 mhagain   Crossbones+   -  Reputation: 7648

Like
2Likes
Like

Posted 06 November 2013 - 06:22 PM

a different format (obj is pretty much a horrible format, and Blender can export much better formats).

 

I can only second this.  From your (OP's) post, you have absolutely no requirement whatsoever for a plain text format and using one isn't going to give you anything useful for what you want to do; it'll just be a world of pain.  You're far better off with something like a binary format that you can fread in a single operation (no parsing needed - yayy!) and squirt directly into a glBufferData call.


It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#5 Krohm   Crossbones+   -  Reputation: 3020

Like
2Likes
Like

Posted 07 November 2013 - 01:31 AM

I also suggest to drop the idea of writing your own parser. It's really wasted effort and the concepts involved are of little interest in the long term. Use AssImp, as above noted.



#6 Stragen   Members   -  Reputation: 253

Like
2Likes
Like

Posted 10 November 2013 - 03:02 AM

I'll disagree with the idea of dropping investigation into writing your own parser, this is IMO and mileage may vary but:

 

Parsing data, and doing it efficiently can be difficult, but the lessons you learn from doing this are invaluable.

 

Learning the tradeoffs between string functions vs char pointer arrays, the costs of vectors vs malloc'd arrays, the various different ways of reading data, and the most important of all, how to accurately benchmark your code, were all major lessons i took away from doing parsing myself that get hidden away in the guts of AssImp and other libraries.



#7 Krohm   Crossbones+   -  Reputation: 3020

Like
4Likes
Like

Posted 11 November 2013 - 01:47 AM

And all things you can learn by also doing everything else!



#8 ShadowFlar3   Members   -  Reputation: 1249

Like
0Likes
Like

Posted 11 November 2013 - 03:56 AM

I of course support self improvement by writing your own parser but if you just want to walk through your house why not use the game engine packed with Blender? Just switch to blender game, make a player cube/empty, parent the camera to it and attach WASD controls and mouselook to it. Next you can design lighting and furnishing as well :)

 

Or Unity3D can also take a .blend file and convert it as you import it. Drag and drop the FPS controller to the scene.

 

Both could be used to have you WASD move and mouselook in your house in less than 5 minutes.



#9 mhagain   Crossbones+   -  Reputation: 7648

Like
1Likes
Like

Posted 12 November 2013 - 03:50 PM

Writing a parser is OK if you really must write a parser; there are some concievable circumstances in which compressing/deduplicating, then parsing data makes sense.

 

I think one needs to look at what the OP is doing first though.  He's taking a binary file format (the blender model), converting it to plain text (.obj), then parsing that plain text and converting it back to binary for drawing with.  That's not a productive use of anyone's time; his objective is to draw a model and this kind of round-tripping doesn't support that objective; it's just make-work for the sake of having a parser, and parsing plain text sucks to begin with (it's slow and error-prone).

 

If writing a parser for the sake of a learning exercise is to be recommended, one can think of any number of better ways of going about it.


It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#10 tool_2046   Members   -  Reputation: 1005

Like
0Likes
Like

Posted 12 November 2013 - 08:09 PM

Writing a parser is OK if you really must write a parser; there are some concievable circumstances in which compressing/deduplicating, then parsing data makes sense.

 

I think one needs to look at what the OP is doing first though.  He's taking a binary file format (the blender model), converting it to plain text (.obj), then parsing that plain text and converting it back to binary for drawing with.  That's not a productive use of anyone's time; his objective is to draw a model and this kind of round-tripping doesn't support that objective; it's just make-work for the sake of having a parser, and parsing plain text sucks to begin with (it's slow and error-prone).

 

If writing a parser for the sake of a learning exercise is to be recommended, one can think of any number of better ways of going about it.

 

I agree on some levels, but I see a few good reasons for writing an OBJ parser.

 

For starters, it's easy. Probably the easiest model format I've dealt with. There isn't a whole lot of variation you'll encounter between exporters (watch out for negative indices!) and it will support static meshes pretty well. 

 

It's also widely supported in modeling applications. There aren't many modeling applications that do not support OBJ, and again, you aren't hitting COLLADA style variations here.

 

The data is generally organized well and easily translates to graphics APIs. No, you aren't getting shaders here. Yes it's not binary. In my experience though, you are likely writing your own format, complete with your own exporters from whatever application you are using. OBJ may be less efficient, but it's a good starting off point. 


Edited by tool_2046, 12 November 2013 - 08:14 PM.


#11 mhagain   Crossbones+   -  Reputation: 7648

Like
1Likes
Like

Posted 13 November 2013 - 03:37 AM

The data is generally organized well and easily translates to graphics APIs. 

 

Most people are going to disagree with that.  The data is fine for OpenGL glBegin/glEnd code, and if you don't mind cache misses; it's absolutely lousy for vertex buffers (witness the questions on this and other sites from .obj users asking if they can have multiple index buffers).


It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#12 samoth   Crossbones+   -  Reputation: 4660

Like
1Likes
Like

Posted 13 November 2013 - 09:12 AM


The data is generally organized well and easily translates to graphics APIs. No, you aren't getting shaders here. Yes it's not binary. In my experience though, you are likely writing your own format, complete with your own exporters from whatever application you are using. OBJ may be less efficient, but it's a good starting off point.

Except it doesn't map at all to how GPUs work.

 

A GPU expects exactly one index per vertex that points to a complete set of vertex attributes (such as position, normal, texcoord). OBJ will use different indices for each, optimizing the file format such that identical elements have the same index.

 

Which means for example that on a simple textured model with smooth normals (a very common thing), three rectangles will have the same index for the normal, and the same index for the texcoord (though not necessarily the same as for the normal). In order to get OpenGL to grok this, you must replicate the normal and texcoord data (lookup using the respective indices) into a set of unique vertices, each containing the replicated data. It is a nuisance, and loading is quite slow.

 

It is much, much easier to use a readily available library like Assimp to load whatever format you want into GPU-compatible buffers. Optionally, you can write a tool of your own using Assimp and save those "binary chunks" to disk in your own format afterwards. When the game loads, it just loads the whole bunch of data into memory in one block, calculates a few pointer offsets, and throws everything at OpenGL. It will work, and it will work fast. Loading is defined by the amount of time it takes the disk to shove data into RAM.


Edited by samoth, 13 November 2013 - 09:13 AM.


#13 tool_2046   Members   -  Reputation: 1005

Like
1Likes
Like

Posted 13 November 2013 - 10:08 AM

Alright, my apologies. I don't disagree that using a single vertex and index buffer per subset is better than using one per positions/normals/texture coordinates. I do disagree that collapsing vertices and indices down is difficult. Identifying unique vertices is a matter of looking at the triplet of indices specifying a vertex. 

 

Like I said, your game probably isn't going to be using any standard format natively. If you just want to load in a standard model file to mess around, writing an OBJ loader is quick to do. I honestly thought it was pretty fun and educational. Could your time be spent better elsewhere? Probably, but it's not like you are wasting a month trying to convince Collada or something to load. assimp is a fine solution. But if you want to spend a day or so, you can write an effective OBJ loader.



#14 mhagain   Crossbones+   -  Reputation: 7648

Like
1Likes
Like

Posted 13 November 2013 - 11:01 AM

I do disagree that collapsing vertices and indices down is difficult. Identifying unique vertices is a matter of looking at the triplet of indices specifying a vertex.

 

It's not about collapsing them down though; it's that .obj has them already collapsed down in a format that's not suitable for use in vertex buffers.


It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#15 tool_2046   Members   -  Reputation: 1005

Like
0Likes
Like

Posted 13 November 2013 - 11:12 AM

I think I'm misunderstanding you. I thought the complaint with how OBJ's store vertices is that there's separate lists for positions, normals and texture coordinates. By "collapse them down" I mean make a single vertex list where each vertex has a position, normal and texture coordinate, and a single index buffer that indexes into that list. 



#16 samoth   Crossbones+   -  Reputation: 4660

Like
1Likes
Like

Posted 14 November 2013 - 04:12 AM

Let's say for example that OBJ contains something like this:

Index (1,1,1) (2,1,2) (3,3,2)
Pos   (x1,y1,z1),(x2,y2,z2), ...
Norm  (nx1,ny1,nz1),(nx2,ny2,nz2), ...
Tex   (u1,v1),(u2,v2), ...

where all in Pos, Norm, and Tex are individual tuples, i.e. you do not find two positions or two normals that are the same. The three indices in Index are not always necessarily the same, such as in the second vertex with indices (2,1,2), which uses position #2 and texture coordinate #2, but normal #1.


The GPU (or OpenGL for that matter) expects that information in a representation like this:

Index  1, 2, 3, ...
Vertex [(x1,y1,z1), (nx1,ny1,nz1), (u1,u1)], [(x2,y2,z2), (nx2,ny2,nz2), (u2,u2)], [(x3,y3,z3), (nx3,ny3,nz3), (u3,u3)]

where there is only one value in Index per vertex, and where (nx2,ny2,nz2) == (nx1,ny1,nz1) and (u3,u3) == (u1,u2). However, you do not tell anyone that you know about that relationship, you simply broadcast the duplicate values to any vertex that uses them.

 

It is of course not too hard to convert one representation to the other, but it is still kind of awkward juggling those variable amounts of indices as you read them from a text file, and it takes considerable work both in terms of writing the code and runtime.

Which means you spend extra time writing code that makes your game load a lot slower than it could without you spending that time.

If the goal is to get a game finished, writing that code is the kind of useless-work-that-gets-you-nowhere that one usually wants to avoid when there is already a readily available, well-tested, functional library that does the job.

 

From an academic point of view, it might be interesting to write a vertex shader that takes multiple indices as input (via a vertex attribute) and which pulls the actual data from a set of buffer textures. That way, it would be possible to directly consume OBJ data. However, this would totally defeat the post-transform cache, so it would only work reasonably well on ATI cards (which have a poor cache implementation but compensate that with higher ALU).


Edited by samoth, 14 November 2013 - 04:13 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS