How should I store a model this way?

Started by
4 comments, last by TTT_Dutch 12 years, 7 months ago
Well I know how I want to store a model but I am not sure how to do it. Now, what I want to do is have a Model class that can load a model's data into a VBO or multiple VBOs. For example:

class Model
{
public:
bool Load(string filename);
private:
//Data is loaded into these VBOs
VBO m_verts;
VBO m_normals;
VBO m_texcoords;
VBO m_faces;
}


or something similar to that. But the thing is, I am not sure how to load the data into the VBO's and bind the attributes outside of the VBO. So right now I have this:
glGenBuffers(2, m_buffers);

glBindBuffer(GL_ARRAY_BUFFER, m_buffers[0]);
glBufferData(GL_ARRAY_BUFFER, size, 0, GL_STATIC_DRAW);

glBufferSubData(GL_ARRAY_BUFFER, 0, vertexSize, &m_vertices[0].x);
glBufferSubData(GL_ARRAY_BUFFER, vertexSize, texCoordSize, &m_textureCoords[0].s);
glBufferSubData(GL_ARRAY_BUFFER, vertexSize + texCoordSize, normalSize, &m_normals[0].x);

if(NumFaces() * 3 > 65535)
{
m_dataType = GL_UNSIGNED_INT;
unsignedInt = true;
}
else
{
m_dataType = GL_UNSIGNED_SHORT;
}

int indexSize = NumFaces() * 3 * sizeof(m_dataType);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, 0, GL_STATIC_DRAW);

for(int i = 0;i < NumFaces();i++)
{
if(unsignedInt)
{
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, i * 3 * sizeof(m_dataType), 3 * sizeof(m_dataType), &m_faces.m_index[0]);
}
else
{
Uint16 index[3] = {m_faces.m_index[0], m_faces.m_index[1], m_faces.m_index[2]};
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, i * 3 * sizeof(m_dataType), 3 * sizeof(m_dataType), &index[0]);
}
}

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

m_nFaces = m_faces.size();

m_faces.clear();
m_normals.clear();
m_textureCoords.clear();
m_vertices.clear();

m_program.Init();

m_program.Attach(vert);
m_program.Attach(frag);

string pos = "in_Pos", tex_coord = "in_TexCoord", normal = "in_Normal";

m_program.BindAttribute(0, pos);
m_program.BindAttribute(1, tex_coord);
m_program.BindAttribute(2, normal);



The problem with this is that I have to provide the shaders in order to bind the attributes, which is not what i want to do. I just want this class to store the data on the GPU. But I am not sure how to do this. All help is appreciated.

Thanks,
Brent
Advertisement
I guess I am asking, how should I store a mesh on the GPU as a VBO then be able to bind its attibutes to a shader?
From where are you getting this model data?
Are you sure there are 3 points on every face? If there is such a guarantee, they would be calling them triangles, not faces. Faces usually implies any number of vertices.

Why are you skipping the unraveling of the vertex data? Are you guaranteed that the length of the vertex pool is the same as the length of the normal pool, and that each vertex in the pool corresponds exactly to the same normal in the normal pool? Typically the point of using pools is to remove duplicates, and each pool can have any number of duplicates. But some people store them unraveled and put an index buffer into the file, which increases the file size, but decreases loading times. I just assume you are doing this.


In any case, you need to interleave your vertex attributes. You have multiple VBO’s declared but you are only using one of them.
You are then filling it with all vertices, then all normals, then all texture coordinates.
If you are using only one vertex buffer, you need to store each vertex as: Vertex[0], Normal[0], Tex[0], Vertex[1], Normal[1], Tex[1], etc.
Actually you can store them tex-normal-vertex or whatever order you prefer, but the point is they should be interleaved.

Typically this is done “offline” from the OpenGL API. That is, you would make your own vertex buffer, fill it manually, and then send the whole thing at once to OpenGL, not using glBufferSubData() (a function I have never used at all).


If you wish to use multiple vertex buffers, you need to create them all (now you only create m_buffers[0]), bind them one at a time, and fill them one at a time.
If you have a vertex buffer for vertices, then you don’t interleave it with normals etc. You just fill it with vertices that are tightly packed. Then repeat for normals, etc.
The advantage of using multiple vertex buffers is that you don’t have to send all of the vertex data when not all of it is needed for a particular render (creating shadow maps only requires the vertices).



Will give more help on binding attributes when the time comes.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Okay well I only pasted a section of the code. I know how to change my code according to your specifications, and I will do this when i start changing the class.

Also, I am loading from a model file. I am hoping that I can send the data straight from the model file right into a VBO. I know how to do all this. But I need help on the one part you didn't help me with, binding attributes to the buffers from outside of the class. :)

Thanks,
Brent
glVertexAttribPointer?

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal


glVertexAttribPointer?


I mean like how am I supposed to do this:
m_program.Init();

m_program.Attach(vert);
m_program.Attach(frag);

string pos = "in_Pos", tex_coord = "in_TexCoord", normal = "in_Normal";

m_program.BindAttribute(0, pos);
m_program.BindAttribute(1, tex_coord);
m_program.BindAttribute(2, normal);

m_program.Link();

glGenVertexArrays(1, &m_buffers[2]);
glBindVertexArray(m_buffers[2]);

glBindBuffer(GL_ARRAY_BUFFER, m_buffers[0]);
m_program.LoadAttribute(0, 3, GL_FLOAT, false, 0, BUFFER_OFFSET(0));
m_program.LoadAttribute(1, 2, GL_FLOAT, false, 0, BUFFER_OFFSET(vertexSize));
m_program.LoadAttribute(2, 3, GL_FLOAT, false, 0, BUFFER_OFFSET(vertexSize + texCoordSize));

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);



With only the GLint buffers available. Like the "m_buffers[]" in this code. Kinda like:

Program.BindAttribute(BufferObject, "name") //I guess I could make a VBO class and store like the size, index count, and other attributes in. SO like BufferObject.GetOffset();
Program.LoadAttribute(BufferObject.GetOffset(),3, GL_FLOAT, false,0,BUFFER_OFFSET(BufferObject.GetSize()));



Thing is I am not sure how I should go about doing something similar to that ^^

This topic is closed to new replies.

Advertisement