problem with buffer objects and glDrawArray

Started by
6 comments, last by TheSeb 18 years, 2 months ago
Hi ! i have two problems : 1. my implementation of VBOs don't work with glDrawElement or glDrawArray (my program works with glDrawElement without VBOs) 2. with or without VBOs, glDrawArray don't works : i have strange rendering I put my code here for both :

void  loader3ds::buildBOs()
{
	for (i=0 ; i<=myLoader->getCounterObj() ; i++)
	{	
		
		glGenBuffers(1, &myLoader->myObjects.vertexBufferName );
				
		glBindBuffer( GL_ARRAY_BUFFER, myLoader->myObjects.vertexBufferName );

		glBufferData( GL_ARRAY_BUFFER, sizeof(float)*3*myLoader->myObjects.nbVertices, &myLoader->myObjects.myVertices, GL_STATIC_DRAW );
		
		glGenBuffers(1, &myLoader->myObjects.indexBufferName );
				
		glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, myLoader->myObjects.indexBufferName );

		glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short int)*myLoader->myObjects.nbVertices, &myLoader->myObjects.myIndices, GL_STATIC_DRAW );

		glGenBuffers(1, &myLoader->myObjects.texCoordName );
		// Get A Valid Name
		glBindBufferARB( GL_ARRAY_BUFFER_ARB, myLoader->myObjects.texCoordName );		// Bind The Buffer
	// Load The Data
		glBufferData( GL_ARRAY_BUFFER_ARB, sizeof(float)*2*myLoader->myObjects.nbVertices, &myLoader->myObjects.myMapping, GL_STATIC_DRAW_ARB );
	
		glGenBuffers(1, &myLoader->myObjects.normalsBufferName );
		
		glBindBuffer( GL_ARRAY_BUFFER, myLoader->myObjects.normalsBufferName );		// Bind The Buffer
	
		glBufferData( GL_ARRAY_BUFFER, sizeof(float)*3*myLoader->myObjects.nbVertices, &myLoader->myObjects.perVertexNormals, GL_STATIC_DRAW );
	// Our Copy Of The Data Is No Longer Necessary, It Is Safe In The Graphics Card
		glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
		delete [] myLoader->myObjects.perVertexNormals ;
		delete [] myLoader->myObjects.myVertices ;
	}
}
void display ()
{

	glClear (GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT ) ;

	glEnableClientState (GL_VERTEX_ARRAY);
	glEnableClientState (GL_INDEX_ARRAY);
	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
	glEnableClientState (GL_NORMAL_ARRAY);
	
	glFrontFace(GL_CCW) ;

	glEnable (GL_CULL_FACE) ;
	glCullFace(GL_BACK) ;

	int i ;
	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL) ;
	glRotatef(c, 0.0, 1.0, 0.0) ;
	for (i=0 ; i<=myLoader->getCounterObj() ; i++)
	{	
		
		glBindBuffer( GL_ARRAY_BUFFER, myLoader->myObjects.vertexBufferName );
		glVertexPointer (3, GL_FLOAT, 0, (char *) NULL  );
		
		glBindBuffer( GL_ARRAY_BUFFER, myLoader->myObjects.indexBufferName );
		glIndexPointer (GL_SHORT, 0, (char *) NULL );

		glBindTexture (GL_TEXTURE_2D, texname) ;
		glBindBuffer( GL_ARRAY_BUFFER_ARB, myLoader->myObjects.texCoordName );
		glTexCoordPointer (2, GL_FLOAT, 0, (char *) NULL  );
		
		glBindBuffer( GL_ARRAY_BUFFER, myLoader->myObjects.normalsBufferName );

		
		//glDrawElements (GL_TRIANGLES, (myLoader->myObjects.nbPoly*3), GL_UNSIGNED_SHORT, &(myLoader->myObjects.myIndices[0][0])) ;
			
		glDrawArrays( GL_TRIANGLES, 0, myLoader->myObjects.nbVertices);
		
	glutSwapBuffers() ;
}

int main(int argc, char *argv[])
{
	myLoader= new loader3ds() ;
	//cout<<"pos cam "<<myLoader->getCamPosX()<<" "<<myLoader->getCamPosY()<<" "<<myLoader->getCamPosZ()<<endl ;
	//cout<<"target cam "<<myLoader->getCamTargetX()<<" "<<myLoader->getCamTargetY()<<" "<<myLoader->getCamTargetZ()<<endl ;
	


	glutInit (&argc, argv) ;
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH) ;
	glutInitWindowSize (640, 480) ;
	glutInitWindowPosition (250,250) ;
	glutCreateWindow (argv [0]) ;
	glewInit();

	glEnable( GL_DEPTH_TEST );
	glClearColor(0, 0, 1, 0);
	
	myLoader->buildBOs();
	myLoader->loadTextures() ;
	myLoader->lighting() ;

	glutReshapeFunc (reshape) ;
	glutKeyboardFunc (keyboard) ;
	glutDisplayFunc (display) ;
	glutIdleFunc(display);

	glutMainLoop () ;
	return 0 ;
}


Advertisement
Are you using same vertex arrays for glDrawArrays() and glDrawElements() ?

They cannot be same because glDrawElements() allows hopping around arrays with indices, but glDrawArrays() does not.

You have to repeat the shared vertices once per face with glDrawArrays().
Hi,
I would try with both, what is the best for performances ?
i have added glNormalPointer in the display function but it still doesn't work. Do you have an idea ?
up
void  loader3ds::buildBOs(){	for (i=0 ; i<=myLoader->getCounterObj() ; i++)

I really hope that you've cut this down for the sake of posting or incorrectly copied it. You don't really have a global/member loop variable, do you?
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short int)*myLoader->myObjects.nbVertices, &myLoader->myObjects.myIndices, GL_STATIC_DRAW );

Presumably that first should be nbIndices or equivalent, although since you're clearly using C++ I would strongly recommend using std::vector instead of doing manual memory management. Strongly recommend it.
glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);

glMapBuffer is used for updating the contets of a buffer. It maps the buffer into application memory so that it can be written to. You should not be using it here. When mapped the buffer must be unmapped before being used as a rendering source.
glEnableClientState (GL_INDEX_ARRAY);

This enables the colour index array for use in indexed colour modes, not the element index array. Remove this line.
glBindBuffer( GL_ARRAY_BUFFER, myLoader->myObjects.indexBufferName );glIndexPointer (GL_SHORT, 0, (char *) NULL );

You generated it as an element index buffer, now you're trying to use it as a colour index buffer. Replace with:
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, myLoader->myObjects.indexBufferName );

glBindBuffer( GL_ARRAY_BUFFER, myLoader->myObjects.normalsBufferName );

As you noted, you will need a glNormalPointer call too.
//glDrawElements (GL_TRIANGLES, (myLoader->myObjects.nbPoly*3), GL_UNSIGNED_SHORT, &(myLoader->myObjects.myIndices[0][0]));

Should be:
glDrawElements (GL_TRIANGLES, (myLoader->myObjects.nbPoly*3), GL_UNSIGNED_SHORT, static_cast< void * >(0));

to use the GL_ELEMENT_ARRAY_BUFFER.
glDrawArrays( GL_TRIANGLES, 0, myLoader->myObjects.nbVertices);

Don't use glDrawArrays - you have indices.

Σnigma
Hi,
Thanks for your answer !
About it :

for (i=0 ; i<=myLoader->getCounterObj() ; i++)

i use it to count the number of models which i have in the scene. I shouldn't do like this ? if no, how ?
I was commenting on the fact that you don't have a local definition of i, suggesting that you must have a global or member variable named i. I would have expected to see:

for (int i = 0; i <= myLoader->getCounterObj(); i++)

(and having just noticed it, did you really mean <= and not just <?)

At any rate, a better encapsulation would probably be just:

myLoader->buildBOs();.

and delegate the work to the object that owns the various variables.

Σnigma
Quote:Original post by Enigma
I was commenting on the fact that you don't have a local definition of i, suggesting that you must have a global or member variable named i. I would have expected to see:

for (int i = 0; i <= myLoader->getCounterObj(); i++)

(and having just noticed it, did you really mean <= and not just <?)

At any rate, a better encapsulation would probably be just:

myLoader->buildBOs();.

and delegate the work to the object that owns the various variables.

Σnigma


ok thanks for your help.
I do " <= " because getCounterObj() start at 0

This topic is closed to new replies.

Advertisement