• Advertisement
Sign in to follow this  

Anyone here using VBO's with .3ds files?

This topic is 4332 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

I have just encountered my HUGE slow down in my engine. I am using immediate mode to render my models and OUCH... I haven't done anything with .3ds files other than some code to load and display them I had gotten off the net. I have modified it to suit my needs for GLSL ect... but never have I tried to use VBO's instead. How would I go about doing this? Is there a tutorial on it? I have setup my terrain to use VBO's but I know my data is 2D and easy to setup as strips... Now with models I have no idea how this is going to work for strips or fans ect... So are you all using just triangles and no strips? Thanks

Share this post


Link to post
Share on other sites
Advertisement
I wasn't sure whether to reply or just rate you down for such badly thought out questions.

After 5 minutes of trying to sort your question into some realistic ones I decided you weren't worth wasting my lunch hour on. Sorry.

Spend more time thinking about what the gaps in your knowledge are, then work out how to explain them to us.

I'm happy to help, but this reads like you've thought about it for 10 seconds, got a vague idea that it might not be exactly the same as your terrain code, googled "3ds VBO tutorial" and then posted here. Think about it in more depth, ask better questions, and you'll get lots of help.


Share this post


Link to post
Share on other sites
3DS is a file format from Autodesk. It defines a 3D mesh and its properties.

VBO is a standardized data structure that obeys base rules, so that when sent to the graphcis card it allows an increase in speed.

You need to read the 3DS file and re-interpret its data into a VBO-compatible structure.

VBOs also suport TriStrips, but that means you'll have to further work upon your in-engine 3D data and convert the face list into a triangle strip list.

I suggest reading:
* NeHe to learn about VBOs
* NvTriStrip is a Library by nVidia to Stripify your 3D Data.

...and yes, please format your posts better in the future. People here like to help, but they can't be bothered translating people posts into something that makes sense. [wink]

Share this post


Link to post
Share on other sites
Sorry, but I am working on my coding late at night after working 12hr days 7 days a week and my mind is gone... :( Anyway currently I am using immediate mode to render my .3ds models. What I need to know is the data that is loaded from a .3ds file how is it laid out. Can I just dump that data into a VBO along with a IB from the data directly? If so what data do I work with the face data or the vertices? Not 100% sure why I need to work with the face data if I have access to the vertices. Also for the IB does .3ds store the index data along with the file so I don't have to arrange the data in the IB to render the mesh? Hope this is clarifies my problems...

Share this post


Link to post
Share on other sites
Quote:
Original post by MARS_999
Sorry, but I am working on my coding late at night after working 12hr days 7 days a week and my mind is gone... :( Anyway currently I am using immediate mode to render my .3ds models. What I need to know is the data that is loaded from a .3ds file how is it laid out. Can I just dump that data into a VBO along with a IB from the data directly? If so what data do I work with the face data or the vertices? Not 100% sure why I need to work with the face data if I have access to the vertices. Also for the IB does .3ds store the index data along with the file so I don't have to arrange the data in the IB to render the mesh? Hope this is clarifies my problems...


Re-read my post, the answers are there.

Share this post


Link to post
Share on other sites
Quote:
Original post by MARS_999
Sorry, but I am working on my coding late at night after working 12hr days 7 days a week and my mind is gone... :( Anyway currently I am using immediate mode to render my .3ds models. What I need to know is the data that is loaded from a .3ds file how is it laid out. Can I just dump that data into a VBO along with a IB from the data directly? If so what data do I work with the face data or the vertices? Not 100% sure why I need to work with the face data if I have access to the vertices. Also for the IB does .3ds store the index data along with the file so I don't have to arrange the data in the IB to render the mesh? Hope this is clarifies my problems...


As prozak pointed out you have to convert to a VBO friendly format. The same case is with the glDrawElements where you will have to load and convert data to a glDrawElement friendly format. This would have been evident if you had looked at closely the immediate mode rendering.

Share this post


Link to post
Share on other sites
VBO was evolved from Vertex Array implementation. Therefore, if you know Vertex Array method to render meshes using glDrawArrays() or glDraw[Range]Elements(), then implementing VBO is quite easy. Top of vertex array implementation, you only need to know how to create vertex buffer objects and how to bind it before use, similar to texture objects.

The difference between Vertex Array and VBO is that: In vertex array mode, the vertex data are stored in your program and needed to transfer to render every frame, but in VBO mode, the data can be cached in high performance video memory and don't need to be re-sent every frame.

I think the first thing you do is: modify your 3ds loader in order to store its vertex data (vertex coords, color comp., normals, texture coords) into vertex array structure.

Share this post


Link to post
Share on other sites
Quote:
Original post by songho
I think the first thing you do is: modify your 3ds loader in order to store its vertex data (vertex coords, color comp., normals, texture coords) into vertex array structure.


Yes, and it is quite easy to do with the .3DS format.

Share this post


Link to post
Share on other sites
Quote:
Original post by songho
VBO was evolved from Vertex Array implementation. Therefore, if you know Vertex Array method to render meshes using glDrawArrays() or glDraw[Range]Elements(), then implementing VBO is quite easy. Top of vertex array implementation, you only need to know how to create vertex buffer objects and how to bind it before use, similar to texture objects.

The difference between Vertex Array and VBO is that: In vertex array mode, the vertex data are stored in your program and needed to transfer to render every frame, but in VBO mode, the data can be cached in high performance video memory and don't need to be re-sent every frame.

I think the first thing you do is: modify your 3ds loader in order to store its vertex data (vertex coords, color comp., normals, texture coords) into vertex array structure.




Thanks for the helpful solution. I wasn't sure if that was what I needed to do or not. So load all the vertex data from the .3ds file into a struct that holds all vertex data and then of course upload that to the VBO. Now for my IBO can I just use triangles and wind them in CCW/CW order 0,1,2,3 ect... or will I need more info to accomplish that? With the total number of vertices known all I should have to do is just loop through the total number of vertices and make a IBO as I stated above? Thanks for the patience with my question.

Share this post


Link to post
Share on other sites
you may want to experiment with using VBO's and also without. If your polygon count is not very high for each 3ds mesh you may find that using many small VBO's will actually give you worse performance than just using a standard array.

Share this post


Link to post
Share on other sites
MARS_999,
The simplest and easiest way is just dumping all vertices into vertex array as you mentioned and draw the triangles with glDrawArrays(). Let's say if a model has 10 triangles, then the total number of vertices will be 30 (some of them might be duplicated here) and the size of vertex coords array will be 90 because each vertex has x, y and z components:
GLfloat *vertices = new GLfloat[numTris * 3 * 3];

And draw the triangles with glDrawArrays(). It is identical on both VA and VBO mode:
glDrawArrays(GL_TRIANGLES, 0, numTris*3);

However, there may be many duplicated shared vertices in the above method. You may filter out the duplicated vertices and create an index array to access the associated vertex data with glDrawElements() or glDrawRangeElements(). By doing this way, the size of vertex array gets smaller, which means faster transferring data to OpenGL.

Share this post


Link to post
Share on other sites
ok, thanks guys for the info. I will try to get to it this weekend. If not next week sometime. I will let you know if I get it working or not.

Share this post


Link to post
Share on other sites
Ok, now I got VA running my .3ds files, but one question lets say I have 10 different model types and display all 10 but each type has 50each? Now can I use the same model object for the other 49 units? If so I am thinking I need to keep each unit with its own xyz data and other info like hitpoints ect... So if I know ahead of time that each model type is going to use the same texture for all 10 models types should I make the texture variable in the class static? How about the mesh data static also, so I am not wasting memory... Thanks Oh BTW would moving to VBO over VA give me much faster performance or would it be worth the time?

Share this post


Link to post
Share on other sites
Quote:
Original post by MARS_999
Ok, now I got VA running my .3ds files, but one question lets say I have 10 different model types and display all 10 but each type has 50each? Now can I use the same model object for the other 49 units? If so I am thinking I need to keep each unit with its own xyz data and other info like hitpoints ect...

Create one array for the entire model, set the pointers once (this is important because it's an expensive operation when using vertex buffers) and then call DrawElements (or DrawArrays or whatever method of dereferencing) as many times as required ...

Quote:
Thanks Oh BTW would moving to VBO over VA give me much faster performance or would it be worth the time?

It'll typically take 10-15 minutes of work, and the performance increases can be upto 50% (that's what it was for me), so I say yes you should do it! [wink]

Share this post


Link to post
Share on other sites
Quote:
Original post by deavik
Quote:
Original post by MARS_999
Ok, now I got VA running my .3ds files, but one question lets say I have 10 different model types and display all 10 but each type has 50each? Now can I use the same model object for the other 49 units? If so I am thinking I need to keep each unit with its own xyz data and other info like hitpoints ect...

Create one array for the entire model, set the pointers once (this is important because it's an expensive operation when using vertex buffers) and then call DrawElements (or DrawArrays or whatever method of dereferencing) as many times as required ...

Quote:
Thanks Oh BTW would moving to VBO over VA give me much faster performance or would it be worth the time?

It'll typically take 10-15 minutes of work, and the performance increases can be upto 50% (that's what it was for me), so I say yes you should do it! [wink]


Ok I am trying to switch over my .3ds files to VBO's and here is what I have


void Model_3DS::SetupVBO(void)
{
glGenBuffers(2, vbo_buffers);
vboObjectSizeArrayVertices = sizeof(float) * totalVerts * 3;
vboObjectSizeArrayNormals = sizeof(float) * totalVerts * 3;
vboObjectSizeArrayTextCoords = sizeof(float) * totalVerts * 2;
glBindBuffer(GL_ARRAY_BUFFER, vbo_buffers[0]);
glBufferData(GL_ARRAY_BUFFER, vboObjectSizeArrayVertices + vboObjectSizeArrayNormals + vboObjectSizeArrayTextCoords, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vboObjectSizeArrayVertices, Objects[0].Vertexes);
glBufferSubData(GL_ARRAY_BUFFER, vboObjectSizeArrayVertices, vboObjectSizeArrayNormals, Objects[0].Normals);
glBufferSubData(GL_ARRAY_BUFFER, vboObjectSizeArrayVertices + vboObjectSizeArrayNormals, vboObjectSizeArrayTextCoords, Objects[0].TexCoords);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_buffers[1]);
vboObjectSizeElement = sizeof(unsigned int) * 3;
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vboObjectSizeElement, Objects[0].MatFaces[0].subFaces, GL_STATIC_DRAW);
}

//now to render

glBindBuffer(GL_ARRAY_BUFFER, vbo_buffers[0]);

glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));
glEnableClientState(GL_VERTEX_ARRAY);
glNormalPointer(GL_FLOAT, 0, BUFFER_OFFSET(vboObjectSizeArrayVertices));
glEnableClientState(GL_NORMAL_ARRAY);

glActiveTextureARB(GL_TEXTURE0_ARB);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, BUFFER_OFFSET(vboObjectSizeArrayVertices + vboObjectSizeArrayNormals));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_buffers[1]);


glDrawElements(GL_TRIANGLES, Objects.MatFaces[j].numSubFaces, GL_UNSIGNED_INT, BUFFER_OFFSET(Objects.MatFaces[j].numSubFaces * sizeof(unsigned int)));


//shutdown vbos
glActiveTextureARB(GL_TEXTURE0_ARB);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);




and I crash... If I comment out the glDrawElements() I have no crashes... I am thinking I have the math wrong, I am don't think my setup code is wrong, just must be over bounds on some array?

Share this post


Link to post
Share on other sites
You are most likely outside array bounds on your index array, because when a card deals with VBOs and it accesses outside an array, rather than crashing, you get a bogus vertex (thats my experience with NVIDIA drivers anyways)

cheers
-Dan

Share this post


Link to post
Share on other sites
Quote:
Original post by MARS_999
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_buffers[1]);
vboObjectSizeElement = sizeof(unsigned int) * 3;
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vboObjectSizeElement, Objects[0].MatFaces[0].subFaces, GL_STATIC_DRAW);

I think you forgot to multiply by the number of triangles [grin].

Share this post


Link to post
Share on other sites
Well I am not sure what variable I should be taking from the .3ds file format?
Shouldn't I be taking the total number of sub faces? I have a pointer to the subfaces and then a total number of the subfaces. I am taking number of subfaces * sizeof(unsigned int) and it loads and doesn't crash unless I use line mode, but the models are still render all wrong...


void Model_3DS::SetupVBO(void)
{
glGenBuffers(2, vbo_buffers);
vboObjectSizeArrayVertices = sizeof(float) * totalVerts * 3;
vboObjectSizeArrayNormals = sizeof(float) * totalVerts * 3;
vboObjectSizeArrayTextCoords = sizeof(float) * totalVerts * 2;
glBindBuffer(GL_ARRAY_BUFFER, vbo_buffers[0]);
glBufferData(GL_ARRAY_BUFFER, vboObjectSizeArrayVertices + vboObjectSizeArrayNormals + vboObjectSizeArrayTextCoords,
NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vboObjectSizeArrayVertices, Objects[0].Vertexes);
glBufferSubData(GL_ARRAY_BUFFER, vboObjectSizeArrayVertices, vboObjectSizeArrayNormals, Objects[0].Normals);
glBufferSubData(GL_ARRAY_BUFFER, vboObjectSizeArrayVertices + vboObjectSizeArrayNormals, vboObjectSizeArrayTextCoords, Objects[0].TexCoords);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_buffers[1]);
for(int z = 0; z < numObjects; z++)
{
for(int x = 0; x < Objects[z].numMatFaces; x++)
{
vboObjectSizeElement += Objects[z].MatFaces[x].numSubFaces;
}
}
vboObjectSizeElement *= sizeof(unsigned int);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vboObjectSizeElement, Objects[0].MatFaces[0].subFaces, GL_STATIC_DRAW);
}



this is what I have now... I can't remember the math to figure out how many indices I need for GL_TRIANGLES and what value I should be using from the .3ds models to determine the index count... Any help would be greatly appreciated.

Share this post


Link to post
Share on other sites
Quote:
Original post by deavik
Quote:
Original post by MARS_999
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_buffers[1]);
vboObjectSizeElement = sizeof(unsigned int) * 3;
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vboObjectSizeElement, Objects[0].MatFaces[0].subFaces, GL_STATIC_DRAW);

I think you forgot to multiply by the number of triangles [grin].


Yeah I seen that after I posted, but I think the issue is where do I get that info from the .3ds format? Faces, subfaces ect... I am lost on that and what value I should end up with... :(

Share this post


Link to post
Share on other sites
Hmmm now I have a new issue. If I load .3ds files with more than one group I crash. I am assuming this is due to the way I am going about it is based on only 1 group? So will I have to call gl*Pointer() for each group in each model when rendering? Thanks

Share this post


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

  • Advertisement