PDA

View Full Version : Loading a mesh


billrobertson42
05-13-2006, 05:01 AM
Ok, so I am just noodling around, and I'd like to be able to load a mesh into memory. The immediate goal would be to just be able to look at it on the screen.

There are numerous descriptions of wavefront's .obj file format out there and it looks easy enough. So just loading it and creating an arbitrary internal representation would be easy enough to do. However, it seems to me that I might want to pick some internal representation that is similar to or the same as what open gl would expect?

If you have any thoughts on this I'd appreciate hearing them.

Thanks

tciny
05-13-2006, 08:19 AM
Well, you could just read it to a vertex/normal/uv buffer... that'd be fast to draw. But then again, thats assuming you have a triangulated mesh already. If you really want to handle n-sided polys and dont want to convert them yourself, you can do that too, but it'd be quite slow to do so.
It kind of depends if you're loading meshes that you can edit yourself or not.

billrobertson42
05-13-2006, 09:09 PM
My only real plan is just to display them for this experiment. However I'm open to doing something other than just the fastest route to learn more and to make it more open ended for future experimenting.

*edit* Ok, I've been reading up a bit. It looks like you basically need to load the data into your own structures and then hand it off to opengl via. whatever means. Which I think is what tciny was telling me.

tciny
05-14-2006, 09:51 AM
Thats one way. Store it in some custom structure and then call glBegin with Triangles, Quads, whatever you need. What I meant was glVertexPointer, glNormalPointer. It's a lot faster than those other calls but requires all Polygons in one pointer to be of the same type (all tris, all quads).

billrobertson42
05-15-2006, 12:49 AM
Ok, thank you for the clarification. I wonder if you could group the model into sets of tris, quads and "others" and load the tris and quads that way in two passes and then the rest of the polygons separately.

At the moment I'm fiddling with a simple open gl on win32 tutorial. It doesn't seem like that big of a deal but it could take some time. I know enough to understand the basics of how to create a win32 app from scratch (or more accurately, I pretty much understand the code that the wizard generated), but I have only done it a few times and that was a long time ago. So I if I run into any hitches it will take awhile to get past them.

*edit* ok. I have spinning triangles in a window now (followed a tutorial from opengl.org) I think if I wanted to do something serious I would definitely look at some sort of windowing toolkit that had some open gl support rather than starting from scratch like this, but this will do for now.

I assume that I just have to make the gl calls and anything that can be accelerated by the video drivers/card will is that correct? Just curious.

tciny
05-15-2006, 11:06 AM
If you're looking for OGL tutorials the ones at http://nehe.gamedev.net/ are pretty good. Especially since the examples there have been ported to pretty much every platform :)

If you're looking for something nicer to set up you Windows you might want to check out wxWindows or Qt.

Yes. OGL is all hardware accelerated.

billrobertson42
05-16-2006, 03:34 AM
Thanks that looks like a really nice set of tutorials. I had not found the right words in google to get there.

Thanks for the tip on qt and wxwidgets.

playmesumch00ns
05-16-2006, 08:33 AM
Have you looked at GLUT? It's the "standard" way of doing things if all you really want to do is open a window and draw to it.

playmesumch00ns
05-16-2006, 08:38 AM
And regarding mesh structure in memory...

OBJ files store mesh data as indexed faces, and that's generally the best method to use to store your data in memory as well. I'd advise triangulating any n-sided polygons at load time too.

To get started drawing you should just use a standard glBegin/glEnd with a loop over your triangle data.

Once you're comfortable doing that, look into vertex arrays. In order to use these, the simplest method is to flatten your triangle data before passing it to gl.

Once you're comfortable with vertex arrays look into vertex buffer objects for more speed. If you really wnat to make things as fast as humanly possible you could also render you mesh as triangle strips.

tciny
05-16-2006, 10:46 AM
While we're at it:
Does somebody here know about fast algorithms to convert a given mesh to triangle strips?

mummey
05-16-2006, 11:20 AM
there's one built into DirectX. I forgot what it was called though. I don't work with DirectX much.

tciny
05-16-2006, 11:57 AM
Me neither :)
I'd rather be interested in the basic concept they use because I'd like an exporter to do the conversion already.

nurcc
05-16-2006, 10:16 PM
About the original question, there are some handy openGL tutors (http://www.xmission.com/%7Enate/tutors.html) available at Nate Robins' website.

They include source code, which is handy. One especially useful part of it is a little library he uses called glm, which is about the easiest way I've seen to load and display obj files with opengl.

Also recommended is the trimesh2 library (http://www.cs.princeton.edu/gfx/proj/trimesh2/) from princeton. It's got support for various mesh formats, and it uses some of the acceleration methods mentioned here, like triangle strips and vertex buffers.

It's a little bit more complicated though, so if you want to stay a bit simpler, I'd stick with the glm library.

billrobertson42
05-17-2006, 02:01 AM
Thanks for the advice all.

I know about glut. I want to experiment and learn a bit though, so I don't mind digging into the guts of things, even if the results are less than satisfactory now it helps fill in the pieces later. One thing that I did find interesting is that when I resized my goofy spinning triangle program the scene stayed in the same spot on the screen. It didn't recenter to the window. Which is the same annoying thing that Wings3d does.

My plan was to pretty much make store the vertices/edges and faces in and indexed fashion as playmesumch00ns suggested. I think that it might make it easier to do things like use simd type instructions (sse2) to crunch through the data if need be, although that's nothing more than a guess right now, and until I have done a lot more work of no real consequence anyway.

Thanks for the other set of tutorials nurcc. I will definitely look at those.

One thing that I was looking at with the .obj format. It doesn't really seem possible to store holes in faces in a .obj file. Is that correct or have I just not seen enough documenation?

e.g.

ThE_JacO
05-17-2006, 06:16 AM
it's different.

pretty much all applications that allow arbitrarily shaped holes in a face really are simply hiding the connectivity from you (and in winged edge models you can't even have a hole at all, it's faked by culling from rendering some faces).

that shape is possible, but to guarantee the output you're better off connecting it explicitly yourself adding one edge for each corner point (from innermost to outermost).

it's also worth adding that while some applications will allow you such connectivity, like Maya, some other won't, as they don't have the same inbuilt heuristics to solve missing connectivity.
Some, like XSI, will do a decent job of guessing it for you, some others, like LW, will simply barf on it as illegal topology.

in all cases you simply shouldn't have something like that in a mesh regardless of application, doubly so if you're going to render it by OGL or DX.

playmesumch00ns
05-17-2006, 09:13 AM
Absolutely agree with Jaco. If you want a shape like that, model it. there's a thousand different reasons why, but the most important is your sanity. When you get to actually doing something with your mesh library, having to handle cases like arbitrary numbers of edges, holes and loops will quickly drive you mad. :)

ThE_JacO
05-17-2006, 09:50 AM
also, the sooner you stop thinking in terms of faces and features in a format like OBJ, the sooner your life will get easier.
dealing with OBJ, OGL, DX etc. all you're doing is using a decades old paradigm that's based on two things: point clouds and connectivity.
There's nothing like "a hole" in most geometric description models outside of trim supporting surfaces of some nature; and there surely isn't one in any triangulating bugger out there :)

The fact maya internally deals with supersets of informations to abstract some details from you doesn't mean it's legal, let alone suitable, for much more primitive descriptors.

as with anything based on such a simple set of information, the more you declare explicitly the easier your life will be.

Realtime rendering systems are not exactly popular for their extensibility in terms of how geometry handled at input stage.

Robert Bateman
05-17-2006, 01:53 PM
OBJ files store mesh data as indexed faces, and that's generally the best method to use to store your data in memory as well. I'd advise triangulating any n-sided polygons at load time too.

as long as you are aware that storing the data in that way is the least efficient way of doing it.

If you really wnat to make things as fast as humanly possible you could also render you mesh as triangle strips.

I've never seen a big real world difference by using tri-strips vs tri-lists. it makes an obvious difference with glBegin/glEnd, and with un-indexed vertex arrays, but i've always found tri-strips to be no different to tri lists when using say an indexed VBO. It makes a difference in immediate mode, because you have instantly reduced the number of glVertex calls, therefore reducing the number of verts that need to be transformed.

For an indexed list however, current drivers will T&L that single list of vertices; tri-stripping or lists won't affect the amount of work done at this stage. Tri-strips will reduce index buffer lengths, and the only speed improvement i've seen has been a smaller amount of data sent to the graphics card, which can be essential if you are bandwidth limited (normally you are not). This however is offset by the overhead of greater numbers of render calls to render strips vs a single list.

In my experiance, it's more important to look at the locality of vertices within the vertex buffer, rather than worrying too much about what primitive you are using.

see:
http://developer.nvidia.com/object/vertex_cache_opt.html

My plan was to pretty much make store the vertices/edges and faces in and indexed fashion as playmesumch00ns suggested. I think that it might make it easier to do things like use simd type instructions (sse2) to crunch through the data if need be, although that's nothing more than a guess right now, and until I have done a lot more work of no real consequence anyway.

it will only be *easier* to use SIMD, is you first design the data layout with sse2 in mind. (16 byte alignment etc). The reality is that SIMD will only help you for things that are likely to be dynamic (verts & normals), UV's and indices rarely change. It's also worth considering that all of that optimisation is going to be a waste of time anyway, a GPU shader has intrinsic matrix and vector operations which will outperform your optimised code most of the time. Ideally, you want to make as much data resident on the graphics card, rather than main system memory. tbh, i have very little data resident in main memory - a single global buffer used as temp space before uploading to the graphics card is more or less all i use.

The data layout of an obj file is good for model editors and the like because it makes it easy to manipulate the data. That form of structure is pretty much useless for real time graphics. (note: Maya has two versions of each mesh, an unoptimised obj style, and a vertex array equivalent for fast rendering).

billrobertson42
05-17-2006, 03:30 PM
In short I see part of the issue like this.

There's a pointcloud as mentioned -- a set of points in space where you have to define the connections

There's a wireframe -- an undirected cyclic graph of points in space

There's a 3d object -- which is a wireframe with the addition of faces

But that's awfully abstract, so it's interesting to see how the rubber meets the road especially in the corner cases. The question about holes in mesh and persistent representation in that format ocurred to me as I was looking at the contents of a file, but that isn't how I see the problem.

Thanks for the answers. It's interesting to learn a bit more about how it's dealt with.

billrobertson42
05-17-2006, 04:59 PM
i have very little data resident in main memory - a single global buffer used as temp space before uploading to the graphics card is more or less all i use.

Do you shuffle things back and forth if there's not enough memory on the card? Also, if may ask, what do you use it for?

Thanks.

playmesumch00ns
05-18-2006, 08:53 AM
The graphics card handles that all for you. It does so by caching a copy of the data in main memory, which isn't a problem at the moment, but will start to be so when we get 1GB graphics cards, maybe next year. I guess nvidia et al are counting on us all having 8GB of ram by that time :)

I'm pretty sure all the ways of sending vertex array data to the card work like this (although rob might want to correct me on this), and it's a good idea just to let the GPU handle all the memory management for the vertex and texture data itself.

Robert Bateman
05-18-2006, 04:32 PM
Do you shuffle things back and forth if there's not enough memory on the card?

no need. The driver will wang it into system ram if not enough is available. For PC's this is normally enough. For consoles I tend to do some slightly cleverer things (dependant on game type, and console ability), Dropping High LOD levels if i'm running low (i used to drop the highest mip levels on PS2, since texture data is often more than the geometry). On consoles though, there is no standard scheme, it very much depends on the game type and what you are trying to eek out of the system.

Also, if may ask, what do you use it for?

Pretty much everything (games, graphics apps, you name it), unless i have a specific requirement (eg consoles) that requires me to do something different. As an example, take a Nurbs surface, apply blend shapes, lattices and skinning to it, and you can probably assume that you are not going to be doing it in a shader. On the assumption that most work takes place when you change LODs, i would upload the evaluated UV's and indices when the LOD changes, then each frame evaluate the deformations in system ram, then upload the new normals & verts. This makes nurbs *very* fast....

Again, it very much depends on what you are limited by. For example, the MD2 loader i have here (http://www.robthebloke.org/opengl_programming.html#5) (version 3), uses software vertex processing, where the evaluation is staggered on alternate frames (if you do half the work per frame, you get a 4x frame rate increase, sounds wrong, but it's true). This form of caching allows for loads of animating models, at the expense of having a fair amount of storage needed for each instances vertices. (which on a PC is not much). Notice though, that all of those models share the same UV and index buffer.... (for they are all the same model).

However, if you were limited by amount of Ram, this method would be a fairly bad idea. Instead it would be better to run that through a shader to evaluate the frames (and if possible, keep the data in the original MD2 format, and expand within the shader). You would not be able to get the same num of characters independantly animating, so you'd duplicate models and instance them (ie, for ones in the distance pick the closest set of verts from the models in the foreground). So say, per frame you evaluate 10 models, each using the same vertex buffer. Any models in the distance would get rendered at the same time. This would reduce your overhead to

memory usage = ( (numFrames+1)*numVerts*sizeof(MD2Vert)) + (numUVs*sizeof(UV)) + (numIndices*sizeof(short));

But yeah, there is no one solution fits all, but generally they are similar! (If you are using GL or DX, the same techniques apply....)

CGTalk Moderation
05-18-2006, 04:32 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.