Some help with VBOs and glDrawElements()

Hey new here, and new to OpenGL I also will apologize if there has already been a thread or a discussion (as I am a bit lazy to use the Search function and didn’t really find anything that pertained to my question when I did) Anyways the issue is that I’m building a 3D game engine in Java using OpenGL and the LWJGL and i’m trying to get multi-texturing to work however when I try to render it (with a glDrawElements() call

glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexBuffer );
glDrawElements(GL_TRIANGLES, m_index.length, GL_UNSIGNED_INT, (long)0);

I get the error of “cannot use an offset when ELEMENT_ARRAY_BUFFER is disabled” which is driving me mad and I’ve been caught on this for 3 weeks now and I really need to move on from it. [NOTE]3dgep.com/?p=1116[/NOTE] this is the site that i’m trying to convert C++ to Java from to get the very effect shown in it.

If anyone can help me solve this issue, and maybe explain how Buffers and the like work would be much appreciated too. I’m also using Java to do this just as a reminder.

Has indexBuffer been initialised with glGenBuffers()? Has the buffer been populated with e.g. glBufferData()?

This link should help you:

http://lwjgl.org/forum/index.php?topic=4494.0

Regards
elFarto

yes I have used glGenBuffers()

createVertBuffer(indexBuffer);

//Method used:
private static int createVertBuffer(int ID)
	{
		deleteVertBuffer(ID);
		ID = glGenBuffers();
		return ID;
	}
	
private static void deleteVertBuffer(int ID)
	{
		if (ID != 0)
		{
			glDeleteBuffers(ID);
			ID = 0;
		}
	}

Probably how i’m doing it is incorrect and should just say “indexBuffer = glGenBuffer();” and leave the fancy method stuff out.

Also elFarto I’m going to read that thread a bit and see, It seems close to my error and I tried changing the binding of my buffer and even using and glEnable still get this error:
[NOTE]Exception in thread “main” org.lwjgl.opengl.OpenGLException: Cannot use offsets when Element Array Buffer Object is disabled
at org.lwjgl.opengl.GLChecks.ensureElementVBOenabled(GLChecks.java:105)
at org.lwjgl.opengl.GL11.glDrawElements(GL11.java:1117)
at terrain.Chunk.drawChunk(Chunk.java:320)
at terrain.Terrain.draw(Terrain.java:84)
at Main.render(Main.java:145)
at Main.main(Main.java:83)
[/NOTE]

If you are wondering how I put data into some of my buffers I have a init method that runs before the drawChunk can even be called.
when I run this code: (PS the part of the code with a problem I added a bunch of “//” spacers so you can quickly scroll to it.)

public void drawChunk()
	{
		ByteBuffer off = BufferUtils.createByteBuffer(1);
		
		glMatrixMode( GL_MODELVIEW );
		glPushMatrix();
		//Below is suppose to take a float? Ref code:
		//glMultMatrixf( glm::value_ptr(m_LocalToWorldMatrix) );
//		glMultMatrix(m);
		
		/* Setting up texture stage 0 (or bottom texture) */
		glActiveTexture( GL_TEXTURE0 );
		glMatrixMode( GL_TEXTURE );
		glPushMatrix();
//		glScalef(32.0f, 32.0f, 1.0f); scaling out for now
		
		glEnable( GL_TEXTURE_2D );
		glBindTexture(GL_TEXTURE_2D, textures[0]);
		
		glClientActiveTexture( GL_TEXTURE0 );
		glEnableClientState( GL_TEXTURE_COORD_ARRAY );
		glBindBuffer( GL_ARRAY_BUFFER, tex0Buffer);
		glTexCoordPointer(2, GL_FLOAT, 0, off );
		
	    // Disable lighting because it changes the primary color of the vertices that are
	    // used for the multitexture blending.
	    glDisable( GL_LIGHTING );
	 
	    // Texture Stage 1
	    // Perform a linear interpolation between the output of stage 0
	    // (i.e texture0) and texture1 and use the RGB portion of the vertex's
	    // color to mix the two.
	    glActiveTexture(GL_TEXTURE1 );
	    glMatrixMode( GL_TEXTURE );
	    glPushMatrix();
//	    glScalef( 32.0f, 32.0f , 1.0f );
	 
	    glEnable( GL_TEXTURE_2D );
	    glBindTexture( GL_TEXTURE_2D, textures[1] );
	 
	    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
	    glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE );
	 
	    glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
	    glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
	 
	    glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
	    glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
	 
	    glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR );
	    glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR );
	 
	    glClientActiveTexture(GL_TEXTURE1);
	    glEnableClientState( GL_TEXTURE_COORD_ARRAY );
	    glBindBuffer( GL_ARRAY_BUFFER, tex1Buffer );
	    glTexCoordPointer(2, GL_FLOAT, 0, off );
	    
	    // Texture Stage 2
	    // Perform a linear interpolation between the output of stage 1
	    // (i.e texture0 mixed with texture1) and texture2 and use the ALPHA
	    // portion of the vertex's color to mix the two.
	    glActiveTexture( GL_TEXTURE2 );
	    glMatrixMode( GL_TEXTURE );
	    glPushMatrix();
//	    glScalef( 32.0f, 32.0f , 1.0f );
	     
	    glEnable( GL_TEXTURE_2D );
	    glBindTexture( GL_TEXTURE_2D, textures[2] );
	     
	    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
	    glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE );
	     
	    glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
	    glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
	     
	    glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE );
	    glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
	     
	    glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR );
	    glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA );
	     
	    glClientActiveTexture(GL_TEXTURE2);
	    glEnableClientState( GL_TEXTURE_COORD_ARRAY );
	    glBindBuffer( GL_ARRAY_BUFFER, tex2Buffer );
	    glTexCoordPointer(2, GL_FLOAT, 0, off );
	    
	    //Rendering
	    glEnableClientState( GL_VERTEX_ARRAY );
	    glEnableClientState( GL_COLOR_ARRAY );
	    glEnableClientState( GL_NORMAL_ARRAY );
	     
	    glBindBuffer( GL_ARRAY_BUFFER, vboVertexHandle );
	    glVertexPointer( 3, GL_FLOAT, 0, off );
//	    glBindBuffer( GL_ARRAY_BUFFER, color );
//	    glColorPointer( 4, GL_FLOAT, 0, 0 );
	    glBindBuffer( GL_ARRAY_BUFFER, vboNormalHandle );
	    glNormalPointer( GL_FLOAT, 0, off );
	    
//
//
//
//
            glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexBuffer );
	    glDrawElements(GL_TRIANGLES, m_index.length, GL_UNSIGNED_INT, (long)0);
//	    glDrawArrays(GL_TRIANGLES, 0, 3); //Works but causes crashes and weird rendering
//
//
//

	    //Cleanup 
	    glDisableClientState( GL_NORMAL_ARRAY );
	    glDisableClientState( GL_COLOR_ARRAY );
	    glDisableClientState( GL_VERTEX_ARRAY );
	 
	    glActiveTexture(GL_TEXTURE2);
	    glPopMatrix();
	    glDisable(GL_TEXTURE_2D);
	    glClientActiveTexture(GL_TEXTURE2);
	    glDisableClientState( GL_TEXTURE_COORD_ARRAY );
	 
	    glActiveTexture(GL_TEXTURE1);
	    glPopMatrix();
	    glDisable(GL_TEXTURE_2D);
	    glClientActiveTexture(GL_TEXTURE1);
	    glDisableClientState( GL_TEXTURE_COORD_ARRAY );
 
	    glActiveTexture(GL_TEXTURE0);
	    glPopMatrix();
	    glDisable(GL_TEXTURE_2D);
	    glClientActiveTexture(GL_TEXTURE0);
	    glDisableClientState( GL_TEXTURE_COORD_ARRAY );
	 
	    glBindBuffer( GL_ARRAY_BUFFER, 0 );
	    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
	 
	    glMatrixMode( GL_MODELVIEW );
	    glPopMatrix();
	}

Also Thank you guys for posting.

Edit:
Also sorry that this code is a mess, as some of the the spots I’m putting a byteBuffer called “off” that is size one, could be giving me grief but idk I’m new to all this (VBOs and OpenGL)

Change this:

glVertexPointer( 3, GL_FLOAT, 0, off );

to:

glVertexPointer( 3, GL_FLOAT, 0, 0 );

Aswell as the glNormalPointer and glTexCoordPointer calls.

And you’ll probably need:

glEnableClientState(GL_INDEX_ARRAY);

Regards
elFarto

Alright i’ve changed the pointers to use 0 now it’s complaining about the Array Buffer now and is failing ont he texcoord pointer

	    glClientActiveTexture(GL_TEXTURE2);
	    glEnableClientState( GL_TEXTURE_COORD_ARRAY );
	    glEnableClientState(GL_ARRAY_BUFFER);
	    glBindBuffer( GL_ARRAY_BUFFER, tex2Buffer );
	    glTexCoordPointer(2, GL_FLOAT, 0, 0 );

also I added this:

	    //Rendering
	    glEnableClientState( GL_INDEX_ARRAY );
	    glEnableClientState( GL_VERTEX_ARRAY );
	    glEnableClientState( GL_COLOR_ARRAY );
	    glEnableClientState( GL_NORMAL_ARRAY );
	     
	    glBindBuffer( GL_ARRAY_BUFFER, vboVertexHandle );
	    glVertexPointer( 3, GL_FLOAT, 0, 0 );
//	    glBindBuffer( GL_ARRAY_BUFFER, color );
//	    glColorPointer( 4, GL_FLOAT, 0, 0 );
	    glBindBuffer( GL_ARRAY_BUFFER, vboNormalHandle );
	    glNormalPointer( GL_FLOAT, 0, 0 );

Firstly, remove the glEnableClientState(GL_ARRAY_BUFFER); call, that’s not legal.

Secondly, check that tex2Buffer really is non-zero.

Regards
elFarto

[QUOTE=elFarto;1252683]And you’ll probably need:

glEnableClientState(GL_INDEX_ARRAY);

[/QUOTE]
Nope. GL_INDEX_ARRAY is the equivalent of GL_COLOR_ARRAY, except the former uses palette indices while the latter uses RGBA colours.

That only answers one of the questions. Have you allocated the buffer’s data store with glBufferData()?

Here is my Method for filling data

public void setUpVBO()
	{
		/* size the m_holders */
		m_position = new Vector3f[faces.size() * 9];// not sure if this is the height * width??
		m_color = new Vector4f[faces.size() * 9];
		m_normal = new Vector3f[faces.size() * 9];
		m_tex0 = new Vector2f[faces.size() * 9];
		
		//set up the handles
		createVertBuffer(vboVertexHandle);
		createVertBuffer(vboNormalHandle);
        
        //set up the buffers
        FloatBuffer verticesBuffer = BufferTools.reserveData(faces.size() * 9);
        FloatBuffer normalsBuffer = BufferTools.reserveData(faces.size() * 9);     		
                
        //loop through every face in the chunk
        for (Face face : faces) {
        	verticesBuffer.put(BufferTools.asFloats(vertices.get(face.getVertexIndices()[0])));
        	verticesBuffer.put(BufferTools.asFloats(vertices.get(face.getVertexIndices()[1])));
        	verticesBuffer.put(BufferTools.asFloats(vertices.get(face.getVertexIndices()[2])));
        	
        	normalsBuffer.put(BufferTools.asFloats(normals.get(face.getVertexIndices()[0])));
        	normalsBuffer.put(BufferTools.asFloats(normals.get(face.getVertexIndices()[1])));
        	normalsBuffer.put(BufferTools.asFloats(normals.get(face.getVertexIndices()[2])));
        }
       // Vector3f n1 = normals.get(face.getVertexIndices()[0]);
        //glNormal3f(n1.x, n1.y, n1.z);
        
        verticesBuffer.flip();
        normalsBuffer.flip();
        
        glPushMatrix();
        glTranslatef(location.x, 0, location.y);
        glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
        glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_DYNAMIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, vboNormalHandle);
        glBufferData(GL_ARRAY_BUFFER, normalsBuffer, GL_DYNAMIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        
        if (len.length > 0)
        {        	
        	int numTriangles = (len.length - 1) * (len.length - 1) * 2;
        	
        	m_index = new int[numTriangles * 3];
        	int index = 0;
        	for (int j = 0; j < (len.length - 1); ++j)
        	{
        		for (int i = 0; i < (len.length - 1); ++i)
        		{
        			int vertexIndex = (j * len.length) + i;
        			//Top Triangle
        			m_index[index++] = vertexIndex;
        			m_index[index++] = vertexIndex + len.length + 1;
        			m_index[index++] = vertexIndex + 1;
        			//Bottom Triangle
        			m_index[index++] = vertexIndex;
        			m_index[index++] = vertexIndex + len.length;
        			m_index[index++] = vertexIndex + len.length + 1;
        		}
        	}
        }
        
        /* create the buffers for drawing */
		createVertBuffer(vertBuffer);
		createVertBuffer(normBuffer);
		createVertBuffer(colBuffer);
		createVertBuffer(tex0Buffer);
		createVertBuffer(tex1Buffer);
		createVertBuffer(tex2Buffer);
		createVertBuffer(indexBuffer);
		
		glBindBuffer( GL_ARRAY_BUFFER, colBuffer );
	    glBufferData( GL_ARRAY_BUFFER, m_color.length, GL_STATIC_DRAW );
		
		/* setup the textures and give the buffers the intel */
		textures[0]=setupTextures("res/textures/Grass.png");
		
        glBindBuffer(GL_ARRAY_BUFFER, tex0Buffer);
        glBufferData(GL_ARRAY_BUFFER, textures[0], GL_DYNAMIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        
        textures[1]=setupTextures("res/textures/Dirt.png");
        
        glBindBuffer(GL_ARRAY_BUFFER, tex1Buffer);
        glBufferData(GL_ARRAY_BUFFER, textures[1], GL_DYNAMIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        
        textures[2]=setupTextures("res/textures/Stone.png");
        
        glBindBuffer(GL_ARRAY_BUFFER, tex2Buffer);
        glBufferData(GL_ARRAY_BUFFER, textures[2], GL_DYNAMIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
                        
        glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexBuffer );
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_index.length, GL_STATIC_DRAW);
        
        hasList = true;

	}

And I will check the Tex2Buffer != 0 when I get back from work. Thanks for helping guys.

EDIT:
Ok I ran some lines to output the buffers int (the id placeholder) and yes Tex2Buffer was 0, so I scrapped the idea of my “createVertBuffer” method and went right for <buffer> = glGenBuffers(); which now I stop getting the “Cannot do this since the Array Buffer is disabled” can it now runs without crashing. However nothing renders at this point. If anyone can see how to get it to render correctly that’d be nice, however I’m gonna try to plug away at this and see if something jumps to life.

Thank you for all the help, and if anymore help on getting this stuff to actually get drawn would be nice too. But overall thank you (never thought to see if my helper method was not doing it’s job)