PDA

View Full Version : glDrawElements and texture mapping



GabrielStuff
02-02-2011, 02:17 AM
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 :)
Have a nice day

mobeen
02-02-2011, 02:59 AM
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

GabrielStuff
02-02-2011, 03:22 AM
Whaou thanks for the very fast reply !
Unfortunately here's what I get changing the stride :

http://img262.imageshack.us/img262/8841/screenshot2011020211191.png

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

http://img262.imageshack.us/img262/1643/screenshot2011020211195.png

any other idea ? How could I test my implementation...

GabrielStuff
02-02-2011, 04:23 AM
My bad :(
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 :
http://img87.imageshack.us/img87/4774/screenshot2011020212215.png

Somekind of blending ?

Thanks !

mobeen
02-02-2011, 04:30 AM
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.

GabrielStuff
02-02-2011, 04:36 AM
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 !

mobeen
02-02-2011, 04:47 AM
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);

GabrielStuff
02-02-2011, 05:20 AM
Hé hé... I've already tried this...

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


glGenTextures ( 1, &amp;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 );
}

mobeen
02-02-2011, 05:47 AM
OK since your image is GL_RGB call this


glPixelStorei(GL_UNPACK_ALIGNMENT,1);

before you call your texture generation function.

GabrielStuff
02-02-2011, 05:49 AM
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.... :)

mobeen
02-02-2011, 06:22 AM
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.

Dan Bartlett
02-02-2011, 09:50 AM
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.