Problem: gldrawElements / texture coordinate

I would like to use this function: glDrawElements to draw the 6 faces of my cube.
Here is my code


Structure:

const GLbyte vertices[] =
{
	-1.0, -1.0, -1.0,	// 0
	1.0, -1.0, -1.0,	// 1
	1.0, -1.0, 1.0,	// 2
	-1.0, -1.0, 1.0,	// 3
	-1.0, 1.0, -1.0,	// 4
	1.0, 1.0, -1.0,	// 5
	1.0, 1.0, 1.0,	// 6
	-1.0, 1.0, 1.0,	// 7
};

const GLubyte elements[] =
{
	2, 6, 3, 7,
	4, 5, 0, 1,
	7, 4, 3, 0,
	1, 5, 2, 6,
	4, 7, 5, 6,
	3, 0, 2, 1,
};

const GLfloat texCoords[6][16] =
{
	// 2 6 3 7
	{
		0.0f,0.0f, // 0
		0.0f,0.0f, // 1
		0.0f,0.0f, // 2 <- 0
		0.0f,1.0f, // 3 <- 2
		0.0f,0.0f, // 4
		0.0f,0.0f, // 5
		1.0f,0.0f, // 6 <- 1
		1.0f,1.0f, // 7 <- 3
	},
	// 4 5 0 1
	{
		0.0f,1.0f, // 0 <- 2
		1.0f,1.0f, // 1 <- 3
		0.0f,0.0f, // 2
		0.0f,0.0f, // 3
		0.0f,0.0f, // 4 <- 0
		1.0f,0.0f, // 5 <- 1
		0.0f,0.0f, // 6
		0.0f,0.0f, // 7
	},
	// 7 4 3 0
	{
		1.0f,1.0f, // 0 <- 3
		0.0f,0.0f, // 1
		0.0f,0.0f, // 2
		0.0f,1.0f, // 3 <- 2
		1.0f,0.0f, // 4 <- 1
		0.0f,0.0f, // 5
		0.0f,0.0f, // 6
		0.0f,0.0f, // 7 <- 0
	},
	// 1 5 2 6
	{
		0.0f,0.0f, // 0
		0.0f,0.0f, // 1 <- 0
		0.0f,1.0f, // 2 <- 2
		0.0f,0.0f, // 3
		0.0f,0.0f, // 4
		1.0f,0.0f, // 5 <- 1
		1.0f,1.0f, // 6 <- 3
		0.0f,0.0f, // 7
	},
	// 4 7 5 6
	{
		0.0f,0.0f, // 0
		0.0f,0.0f, // 1
		0.0f,0.0f, // 2
		0.0f,0.0f, // 3
		0.0f,0.0f, // 4 <- 0
		0.0f,1.0f, // 5 <- 2
		1.0f,1.0f, // 6 <- 3
		1.0f,0.0f, // 7 <- 1
	},
	// 3 0 2 1
	{
		1.0f,0.0f, // 0 <- 1
		1.0f,1.0f, // 1 <- 3
		0.0f,1.0f, // 2 <- 2
		0.0f,0.0f, // 3 <- 0
		0.0f,0.0f, // 4
		0.0f,0.0f, // 5
		0.0f,0.0f, // 6
		0.0f,0.0f, // 7
	},
};

Display:


	glPushMatrix();
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, spriteTexture);

	glLoadIdentity();
	glTranslatef(0.0, 0.0, transz);
	glRotatef(BallRotation, 1.0f, 0.0f, 0.0f);
	glRotatef(BallRotation/7, 0.0f, 1.0f, 0.0f);
	glRotatef(BallRotation/13, 0.0f, 0.0f, 1.0f);
	glVertexPointer(3, GL_BYTE, 0, vertices);

	// Initial setup
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	// Lower and upper faces
	glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
	glNormal3f(0.0f, -1.0f, 0.0f);
	glTexCoordPointer(2, GL_FLOAT, 0, texCoords[0]);
	glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, elements);
	glNormal3f(0.0f, 1.0f, 0.0f);
	glTexCoordPointer(2, GL_FLOAT, 0, texCoords[1]);
	glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, elements + 4);
	
	// Front and back faces
	glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
	glNormal3f(0.0f, 0.0f, -1.0f);
	glTexCoordPointer(2, GL_FLOAT, 0, texCoords[2]);
	glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, elements + 8);
	glNormal3f(0.0f, 0.0f, 1.0f);
	glTexCoordPointer(2, GL_FLOAT, 0, texCoords[3]);
	glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, elements + 12);
	
	// Right and left faces
	glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
	glNormal3f(1.0f, 0.0f, 0.0f);
	glTexCoordPointer(2, GL_FLOAT, 0, texCoords[4]);
	glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, elements + 16);
	glNormal3f(-1.0f, 0.0f, 0.0f);
	glTexCoordPointer(2, GL_FLOAT, 0, texCoords[5]);
	glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, elements + 20);

	glPopMatrix();

This code works however I think it isn’t optimized. I created an array which contains the texture coordinates for each face.
For all faces, only four texture coordinates are used.
I was forced to do that because the function glDrawElements uses the point indice to reference the texture coordinates.

Do you know if it exists a best way to realise that?

Tks

May be this solution is better…

Structure:


// 2 float => texture coordinate
// 3 float => vertex position
const GLfloat vertices[] =
{
	0.0f,0.0f,1.0,-1.0,1.0,			// 2
	1.0f,0.0f,1.0,1.0,1.0,			// 6
	0.0f,1.0f,-1.0,-1.0,1.0,		// 3
	1.0f,1.0f,-1.0,1.0,1.0,			// 7

	0.0f,0.0f,-1.0,1.0,-1.0,		// 4
	1.0f,0.0f,1.0,1.0,-1.0,			// 5
	0.0f,1.0f,-1.0,-1.0,-1.0,		// 0
	1.0f,1.0f,1.0,-1.0,-1.0,		// 1

	0.0f,0.0f,-1.0,1.0,1.0,			// 7
	1.0f,0.0f,-1.0,1.0,-1.0,		// 4
	0.0f,1.0f,-1.0,-1.0,1.0,		// 3
	1.0f,1.0f,-1.0,-1.0,-1.0,		// 0

	0.0f,0.0f,1.0,-1.0,-1.0,		// 1
	1.0f,0.0f,1.0,1.0,-1.0,			// 5
	0.0f,1.0f,1.0,-1.0,1.0,			// 2
	1.0f,1.0f,1.0,1.0,1.0,			// 6

	0.0f,0.0f,-1.0,1.0,-1.0,		// 4
	1.0f,0.0f,-1.0,1.0,1.0,			// 7
	0.0f,1.0f,1.0,1.0,-1.0,			// 5
	1.0f,1.0f,1.0,1.0,1.0,			// 6

	0.0f,0.0f,-1.0,-1.0,1.0,		// 3
	1.0f,0.0f,-1.0,-1.0,-1.0,		// 0
	0.0f,1.0f,1.0,-1.0,1.0,			// 2
	1.0f,1.0f,1.0,-1.0,-1.0,		// 1
};

// Cube's faces (list of indexes)
const GLubyte elements[] =
{
	0,1,2,3,
	4,5,6,7,
	8,9,10,11,
	12,13,14,15,
	16,17,18,19,
	20,21,22,23,
};

Display:


	glPushMatrix();
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, spriteTexture);
	
	glLoadIdentity();
	glTranslatef(0.0, 0.0, transz);
	glRotatef(BallRotation, 1.0f, 0.0f, 0.0f);
	glRotatef(BallRotation/2, 0.0f, 1.0f, 0.0f);
	glRotatef(BallRotation/3, 0.0f, 0.0f, 1.0f);
	glTexCoordPointer(2, GL_FLOAT, 5*sizeof(GL_FLOAT), vertices);
	glVertexPointer(3, GL_FLOAT, 5*sizeof(GL_FLOAT), vertices + 2);

	// Initial setup
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	// Lower and upper faces
	glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
	glNormal3f(0.0f, -1.0f, 0.0f);
	glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, elements);
	glNormal3f(0.0f, 1.0f, 0.0f);
	glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, elements + 4);
	
	// Front and back faces
	glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
	glNormal3f(0.0f, 0.0f, -1.0f);
	glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, elements + 8);
	glNormal3f(0.0f, 0.0f, 1.0f);
	glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, elements + 12);
	
	// Right and left faces
	glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
	glNormal3f(1.0f, 0.0f, 0.0f);
	glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, elements + 16);
	glNormal3f(-1.0f, 0.0f, 0.0f);
	glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, elements + 20);
	
	glPopMatrix();

It depends on the OpenGL ES implementation, but on some implementations you should pack all data (including normal and color) into one array and use a single glDrawElements call instead of one for each face. Duplicate data may be less overhead than multiple draw calls. I would also recommend using smaller types where possible, but aligning every vertex attribute to a 32 bit boundary. You’re only using the values 0, 1, and -1 so GLbyte should be sufficient, but may need padding bytes.

I.e. as a struct for vertices, assuming the compiler will pack the elements:

struct vertex
{
GLbyte position[4];
GLbyte normal[4];
GLubyte color[4];
GLbyte texcoord[4];
};

Thank you :-).

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.