[SOLVED] [LWJGL] Render multiple VBO's

Hello!

I am trying to render multiple VBO’s in my current Java project.

Currently, I have my own model format which creates a vertex buffer object from its vertex coordinates, texture coordinates, and normal coordinates. When I draw my first model, it draws perfectly fine, however, when I draw my second model it draws the first model’s VBO.

Here is how I am drawing the models:

//Enable the ability to use VBO's
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY);
GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

//setup the model pointers
int bytes_per_variable = 4;
int stride = 8 * bytes_per_variable;
GL11.glVertexPointer(3, GL11.GL_FLOAT, stride, 0);
GL11.glNormalPointer(GL11.GL_FLOAT, stride, (3 * bytes_per_variable));
GL11.glTexCoordPointer(2, GL11.GL_FLOAT, stride, (6 * bytes_per_variable));

//Draw the model
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, vertex_data_array.length / 8);

//Disable VBO's
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

Here is how I am creating the VBO:

this.vertex_data_array = new float[amountVertices * 8];
int counter = 0;
//Pack the new array with data from the model
for (int i = 0; i < amountVertices; i++) {
	vertex_data_array[counter] = (float) vertX[i]; counter++;
	vertex_data_array[counter] = (float) vertY[i]; counter++;
	vertex_data_array[counter] = (float) vertZ[i]; counter++;
	vertex_data_array[counter] = (float) norX[i]; counter++;
	vertex_data_array[counter] = (float) norY[i]; counter++;
	vertex_data_array[counter] = (float) norZ[i]; counter++;
	vertex_data_array[counter] = (float) texX[i]; counter++;
	vertex_data_array[counter] = (float) texY[i]; counter++;
}

//Setup the floatbuffer
FloatBuffer vertex_buffer_data = BufferUtils.createFloatBuffer(vertex_data_array.length);
vertex_buffer_data.put(vertex_data_array);
vertex_buffer_data.rewind();

//Bind buffer to id
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertex_buffer_id);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertex_buffer_data, GL15.GL_STATIC_DRAW);

Here is how I generate the vertex buffer id:

IntBuffer buffer = BufferUtils.createIntBuffer(1);
GL15.glGenBuffers(buffer);
this.vertex_buffer_id = buffer.get(0);

Any help would be appreciated!

Thanks,
Andrew

You’ll need to unbind the buffer first by calling glBindBuffer with an I’d of 0.

I still cannot seem to get it to work…

//Bind buffer to id
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertex_buffer_id);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertex_buffer_data, GL15.GL_STATIC_DRAW);

//Enable the ability to use VBO's
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY);
GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

//setup the model pointers
int bytes_per_variable = 4;
int stride = 8 * bytes_per_variable;
GL11.glVertexPointer(3, GL11.GL_FLOAT, stride, 0);
GL11.glNormalPointer(GL11.GL_FLOAT, stride, (3 * bytes_per_variable));
GL11.glTexCoordPointer(2, GL11.GL_FLOAT, stride, (6 * bytes_per_variable));

//Draw the model
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, vertex_data_array.length / 8);

GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

//Disable VBO's
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

Am I doing it correctly?

[EDIT]
My apologies, I found that the model was in fact drawing at (0, 0, 0). Now to figure out how to position a VBO mmodel :slight_smile:

Thanks!

Positioning is easy, just specify the coordinates when you create the vbo data, and then add the size to the coordinates. DO NOT use glTranslate for large amounts of data, just do the math yourself!

Wouldn’t I have to recreate all of the vertex data array data? If so, wouldn’t that defeat the purpose of using a VBO (assuming this model is going to always be moving)?

True, I was thinking about creating terrain data. Never mind!

If you are going to be moving lots of vertices around every second (I.E. its not a static VBO), then I would seriously recommend looking into shaders. Getting closer to the metal when programming is always good, it just might be harder. If your model isn’t too high - poly, I guess it wouldn’t matter if you use glTranslate.

Well I use glTranslate for my camera, and when I translate the model as well, it moves the camera!

Does this have anything to do with glPushMatrix?

If you need to only move one vertex, or set of vertices, you need to wrap it in glPushMatrix and glPopMatrix. For example:


camera.translate();
glLoadIdentity();

glPushMatrix();
model.translate();
glPopMatrix();

Basically, pushing and popping a matrix is pushing the top matrix off the matrix stack, modifying it, then sticking it back on top, so that only the vertices that were translated are affected. This means that only your model will translate while all other vertices will stay at the same coordinates.

I see…
I tried doing this, but it appears that now the camera ceases to move. Am I missing a step? I’m still quite new to lwjgl, please excuse my “newbieness”

Here, post some code, I’d be glad to help! You should be translating the camera, then drawing your model, and then calling glLoadIdentity after all of that. Sorry, I had the order a little mixed up!

Main threads render method:

Game.getSingleplayerGame().getPlayerController().render();
Game.getSingleplayerGame().getWorld().render();
GL11.glLoadIdentity();

Player Controller (camera) rendering method:

float yaw = player.getLocation().getYaw();
float pitch = player.getLocation().getPitch();

GL11.glRotatef(pitch - 90, 1, 0, 0);
GL11.glRotatef(0,     0, 1, 0);
GL11.glRotatef(yaw  , 0, 0, 1);

GL11.glTranslatef(-player.getLocation().getX(), -player.getLocation().getY(), -player.getLocation().getZ());

World rendering method:

GL11.glPushMatrix();
GL11.glTranslated(-x, -y, -z);

//Bind buffer to id
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertex_buffer_id);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertex_buffer_data, GL15.GL_DYNAMIC_DRAW);

//Enable the ability to use VBO's
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY);
//GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

//setup the model pointers
int bytes_per_variable = 4;
int stride = 8 * bytes_per_variable;
GL11.glVertexPointer(3, GL11.GL_FLOAT, stride, 0);
GL11.glNormalPointer(GL11.GL_FLOAT, stride, (3 * bytes_per_variable));
//GL11.glColorPointer(4, GL11.GL_DOUBLE, stride, 6 * bytes_double);
GL11.glTexCoordPointer(2, GL11.GL_FLOAT, stride, (6 * bytes_per_variable));

//Draw the model
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, vertex_data_array.length / 8);

GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

//Disable VBO's
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

GL11.glPopMatrix();

Note, the world rendering method calls the bove cods for the world map, and all the entities in it (which have models).

After changing the loadIdentity to after drawing everything, the camera goes back to being stuck at 0,0,0. If I put it right after translating the camera, then it does the same thing.

[EDIT]
If I ONLY draw ONE vbo, then there are no issues. But once I start drawing multiple vbo’s, the problem is created.

That’s because you should be translating the data after you create the VBO. Right now you’re translating before. So, remove the push and pop matrix calls, the translate call, and translate the vbo after its created. Wrap the translate function in the push and pop calls!

Well I appear to have everything working! :slight_smile:
Thanks a bunch!

I do have one more question, however… I tried using glRotate() on my model (before translating it), and it appears to rotate it as if it was already translated, so the model is miles away from where it should be.

the setup:
glpushmatrix();
glrotate(…);
gltranslate(…);
draw();
glpopmatrix();

For rotation of model, first translate and then rotate. It should work then.