On Sat, Dec 4, 2010 at 4:05 PM, Ian Mallett <[email protected]> wrote:

>
> On Sat, Dec 4, 2010 at 1:21 PM, Christopher Night 
> <[email protected]>wrote:
>
>> Hi, I'm working on a standalone OBJ loader based on the well-known one on
>> the pygame wiki:
>> http://www.pygame.org/wiki/OBJFileLoader
>>
>> My goal is to speed up load times by making the model objects picklable,
>> so the OBJ file doesn't have to be read every time you start up. Here's my
>> current version:
>> http://christophernight.net/stuff/fasterobj-0.tgz
>>
>> It still needs some cleaning up, but it's got almost all the functionality
>> I wanted. In addition to making things picklable, it has a small
>> optimization by combining triangles and quads when possible to reduce the
>> number of GL calls.
>>
>> There are three classes: OBJ (using fixed function), OBJ_array (using
>> vertex arrays), and OBJ_vbo (using vertex buffer objects). Additionally, any
>> of these can be used with or without a display list. Here's the results of
>> my test on some model I had lying around:
>>
>>    type  list? parse save load   render
>> 1. fixed False  146   13   14    0.03fps
>> 2. fixed  True  124   10  950  117.80fps
>> 3. array False  179    8    9    1.26fps
>> 4. array  True  174    7   30  121.08fps
>> 5. vbo   False  143    7    8   16.06fps
>> 6. vbo    True  142    8   12  112.98fps
>>
>> #2 is the method in the original OBJ loader. The times listed under parse,
>> save, and load are times in milliseconds to read from the OBJ file and do
>> some preprocessing, pickle to a file, and unpickle from a file. The load
>> step also includes generating the display list, if necessary.
>>
>

> I completely would have expected the results in 1-4.
>
> However, I'm quite surprised at the vbo method 5.  It should run in speed
> between 2 and 4.  I also would have expected 4 and 6 to be much closer.
>
> How many VBOs are you using?  If you switch buffer bindings a lot for each
> draw (like your object has 10 different parts, each with a vertex, normal,
> and texcoord VBO) then you *might* get results like that . . .
>

Awesome, thanks so much for taking a look! I'm using 3 VBOs, one each for
vertex, normal, and texcoord. This is the entire rendering code for OBJ_vbo:

glEnable(GL_TEXTURE_2D)
glFrontFace(GL_CCW)
self.vbo_v.bind()
glVertexPointerf(self.vbo_v)
self.vbo_n.bind()
glNormalPointerf(self.vbo_n)
self.vbo_t.bind()
glTexCoordPointerf(self.vbo_t)
glEnableClientState(GL_VERTEX_ARRAY)
texon, normon = None, None
for material, mindices in self.indices:
self.mtl.bind(material)
 for nvs, dotex, donorm, ioffset, isize in mindices:
 if donorm != normon:
 normon = donorm
 (glEnableClientState if donorm else glDisableClientState)(GL_NORMAL_ARRAY)
 if dotex != texon:
 texon = dotex
 (glEnableClientState if dotex else
glDisableClientState)(GL_TEXTURE_COORD_ARRAY)
 shape = [GL_TRIANGLES, GL_QUADS, GL_POLYGON][nvs-3]
 glDrawArrays(shape, ioffset, isize)
glDisable(GL_TEXTURE_2D)

For this model, glEnableClientState gets called once for vertices, normals,
and texcoords. There are 5 materials, each with one glBindTexture and two
glDrawArrays (one for triangles, one for quads). So the total calls per
render is:

2 x glEnable/glDisable
1 x glFrontFace
3 x vbo.bind
3 x glEnableClientState
10 x glDrawArrays
5 x glBindTexture
4 x glColor

And I'm rendering 40 sprites, so I'm doing this 40 times per frame. I'm
assuming that in a real application, each model would have its own separate
VBOs. Is that what I'm doing wrong? Or is there something else?

The reason it takes so long to load on 2 is generating the display list.
This method was taken from the objloader on the wiki, and it involves 1646
glVertex3f calls, one for each vertex in the model, and similarly with
glNormal and glTexCoords.

Thanks again!

-Christopher

Reply via email to