glDrawElements and texture mapping

Hi there,

I’ve been struggling for a long time now… and I can not see what is wrong with my code.

I’ve got a bunch of vertices that are modified from click input. I also have the texCoordinates that are modified from click input.
Finaly I draw all my elements.

I would like to know how to check the state of my opengl draw function and how to check for each line… meaning, how to be sure that the array I passed thru the various function are consistent. Here is the code :


-(void)ripple_redraw{	
	
//no need to enable texture 2D, cocos do it

	glBindTexture(GL_TEXTURE_2D, [texture_ name]);
	
	// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
	// Needed states: GL_VERTEX_ARRAY, 
	// Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY	
	
	//by default in cocos2D
	//glEnableClientState( GL_VERTEX_ARRAY );
	//glEnableClientState( GL_TEXTURE_COORD_ARRAY );	
	
	glVertexPointer  ( 2, GL_FLOAT, sizeof( struct Ripple_VERTEX ), ripple_vertex[0][0].x );
	glTexCoordPointer( 2, GL_FLOAT, sizeof( struct Ripple_VERTEX ), ripple_vertex[0][0].t );	
	glDrawElements   ( GL_TRIANGLES, GRID_SIZE_X * GRID_SIZE_Y * 6, GL_UNSIGNED_SHORT, ripple_Indices );
	}

Here is the init for my surfaces and vertices that I call before the draw :

-(void) initRipple{
	
	posX = 0;
	posY = 0;

	CGSize winSize = [[CCDirector sharedDirector] winSize];

	int	i, j, index;
	ripple_max = (int) sqrt( (float) ( 768 * 768 + 1024 * 1024 ) );
	
	for ( i = 0; i < RIPPLE_COUNT; i++ )
	{
		t  [i] = ripple_max + RIPPLE_LENGTH;
		cx [i] = 0;
		cy [i] = 0;
		max[i] = 0;
	}
	
	for ( i = 0; i < GRID_SIZE_X; i++ )
	{
		for ( j = 0; j < GRID_SIZE_Y; j++ )
		{
			ripple_vertex[i][j].x [0] = i / ( GRID_SIZE_X - 1.f ) * gscrx;
			ripple_vertex[i][j].x [1] = j / ( GRID_SIZE_Y - 1.f ) * gscry;
			ripple_vertex[i][j].dt[0] = i / ( GRID_SIZE_X - 1.f );
			ripple_vertex[i][j].dt[1] = j / ( GRID_SIZE_Y - 1.f );
		}
	}
	
	for ( i = 0; i < GRID_SIZE_Y-1; i++ )
	{
		for ( j = 0; j < GRID_SIZE_X-1; j++ )
		{	
			index = i * GRID_SIZE_X + j;
			ripple_Indices[index * 6 + 0] = ( i     ) * GRID_SIZE_X + j;
			ripple_Indices[index * 6 + 1] = ( i + 1 ) * GRID_SIZE_X + j;
			ripple_Indices[index * 6 + 2] = ( i + 1 ) * GRID_SIZE_X + j + 1;
			ripple_Indices[index * 6 + 3] = ( i     ) * GRID_SIZE_X + j;
			ripple_Indices[index * 6 + 4] = ( i + 1 ) * GRID_SIZE_X + j + 1;
			ripple_Indices[index * 6 + 5] = ( i     ) * GRID_SIZE_X + j + 1;
		}
	}
	[self ripple_reshape:winSize.width height:winSize.height];

	[self schedule:@selector(ripple_dynamics:)];
	NSLog(@"initRipple End");
}

Here is the init for GL :

-(void) initGL{
		
	// ask director the the window size
	//CGSize winSize = [[CCDirector sharedDirector] winSize];
	

	//image = [CCSprite node];
	//[image setPosition:ccp(winSize.width/2, winSize.height/2)];

	
	//asign pixelData from loaded image it is equivalent to

	[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
	CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: @"image.jpg"];
	if( texture ) {
		CGRect rect = CGRectZero;
		rect.size = texture.contentSize;
		[texture_ release];
		texture_ = [texture retain];
	}
	

	
	/*No need to call this, cocos2d do it.
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
	glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );*/
	NSLog(@"initGL end");
}

Finaly if I had a simple test case in the draw like this :

ccVertex2F newPoint[5];	
	bool closePolygon = FALSE;
	
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnableClientState(GL_COLOR_ARRAY);
	
	glBindTexture(GL_TEXTURE_2D, [texture_ name]);
	
	if( sizeof(CGPoint) == sizeof(ccVertex2F) ) {
		
		// convert to pixels ?
		if( CC_CONTENT_SCALE_FACTOR() != 1 ) {
			memcpy( newPoint, vertices, 5 * sizeof(ccVertex2F) );
			for( NSUInteger i=0; i<5;i++)
				newPoint[i] = (ccVertex2F) { vertices[i].x * CC_CONTENT_SCALE_FACTOR(), vertices[i].y * CC_CONTENT_SCALE_FACTOR() };
			
			glVertexPointer(2, GL_FLOAT, 0, newPoint);
			
		} else
			glVertexPointer(2, GL_FLOAT, 0, vertices);
		
		
	}else {
		for( NSUInteger i=0; i<5;i++)
			newPoint[i] = (ccVertex2F) { vertices[i].x, vertices[i].y };
		
		glVertexPointer(2, GL_FLOAT, 0, newPoint );
	}
	 
	 if( closePolygon )
		 glDrawArrays(GL_LINE_LOOP, 0, 5);
	 else
		 glDrawArrays(GL_LINE_STRIP, 0, 5);

I can see the texture drawn on the line between my vertices.

The whole thing is in 2D.

The thing is that I do not know where to look, I wish I could test my bunch of vertices and textures coordinates…

If you have cocos2d you can try to run a test from this file :
http://demo.ovh.net/fr/142c945fa1e9512ce5f70bd47fe7ae8f/

Thank you very much for any hints or infos :slight_smile:
Have a nice day

You are passing the wrong value for stride (3rd param of gl[Vertex/TexCoord]Pointer functions) which instead should be the size in bytes for each successive element. I think it should be this.


glVertexPointer  ( 2, GL_FLOAT, sizeof(ripple_vertex[0][0].x), ripple_vertex[0][0].x );
glTexCoordPointer( 2, GL_FLOAT, sizeof( ripple_vertex[0][0].t), ripple_vertex[0][0].t);

See if this helps,
Mobeen

Whaou thanks for the very fast reply !
Unfortunately here’s what I get changing the stride :

Without changing the stride I get this (different program) :

any other idea ? How could I test my implementation…

My bad :frowning:
I was passing an empty array : /… I finaly decided to double check the init and the value of my vertices by printin’ them and guess what (0,0)

Unfortunately it goes like this :

Somekind of blending ?

Thanks !

I should have asked this earlier. How is ur struct Ripple_VERTEX defined? I thought it is something like this, correct me if I am wrong.


struct Ripple_VERTEX {
   float x[2];
   float t[2];
}

I thought u r using separate arrays for position and uvs.
What do u want to test in your implementation.
If u want to know whether the opengl state machine is fine. You can call glGetError(); which will return an error code (GLuint) that will tell u whether everything is fine. Add this call in your render function


assert(glGetError()==GL_NO_ERROR);

that will give assertion failure in case there is something wrong.

Hi thank you for your time, here is the structure :

struct 	Ripple_VECTOR		
{										
	float			dx[2];
	int				r;									// distance from origin, in pixels 
};

struct 	Ripple_AMP										
{					
	float			amplitude;
};

struct Ripple_VERTEX
{
	float			x[2];								// initial vertex location 
	float			t[2];								// texture coordinate 
	float			dt[2];								// default texture coordinate 
};

Running the code I do not get anymore trouble displaying the image… only it is very weird like if there were lighting and shadow ?

Thank you !

Hi,
Where is the glTexImage2D or gluBuildMipmaps call? I saw the texture parameter setting but I didn’t see this call?

And one more thing, what is the image format GL_RGB or GL_RGBA ?

You also should make sure that the lighting is disabled before drawing (if u r using lighting elsewhere in your code.

glDisable(GL_LIGHTING);

Hé hé… I’ve already tried this…

In my working setup (the other app not including cocos), I do like this :


glGenTextures   ( 1, &tls->tex );
	glEnable	    ( GL_TEXTURE_2D );
	glBindTexture   ( GL_TEXTURE_2D , tls->tex );	
	glTexImage2D    ( GL_TEXTURE_2D , 0, GL_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
	glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
	glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

In cocos, I do not need to glTexImage2D, I think, as I can see the texture. But It shows up weird things…

and :

void ripple_redraw(void)
{	
	//glLoadIdentity();

	glEnableClientState( GL_VERTEX_ARRAY );
	glEnableClientState( GL_TEXTURE_COORD_ARRAY );

	glVertexPointer  ( 2, GL_FLOAT, sizeof( RIPPLE_VERTEX ), ripple_vertex[0][0].x );
	glTexCoordPointer( 2, GL_FLOAT, sizeof( RIPPLE_VERTEX ), ripple_vertex[0][0].t );	
	glDrawElements   ( GL_TRIANGLES, GRID_SIZE_X * GRID_SIZE_Y * 6, GL_UNSIGNED_SHORT, ripple_Indices );

	glDisableClientState( GL_VERTEX_ARRAY );
	glDisableClientState( GL_TEXTURE_COORD_ARRAY );	
}

OK since your image is GL_RGB call this


glPixelStorei(GL_UNPACK_ALIGNMENT,1);

before you call your texture generation function.

Hey It was also necessary to unable GL_COLOR_ARRAY

glDisableClientState(GL_COLOR_ARRAY);

The image is now ok. but the pixel are not moving… :slight_smile:

Recheck your code maybe some condition is preventing the update of ur vertex array. Remove all the conditions and directly set the new vertices to the vertex array and then see if the vertices are animated. Otherwise check your new values.

Your last picture looks almost like the normals are all screwed up, have you got a normal array bound that isn’t meant to be?

You could test whether disabling it makes any improvement:

glDisableClientState(GL_NORMAL_ARRAY);
glNormal3f(0.0f, 0.0f, 1.0f);

or if you are making a smooth looking wave, then you will probably also want to provide smooth normals with glNormalPointer.