Skip to main content
gamedev.net
🔒 Locked

Texturing a cube

Started by Mybowlcut 18 replies 1.6k views
Original Post
Mybowlcut
Mybowlcut
Hey. I've got a function to render a cube (I call it box here - just ignore that):
namespace Box
{
    void Render_Box();
    void Render_Textured_Box();

	// 3 xyz per vertex * 4 vertices per face * 6 faces.
    const short QTY_CUBE_SIDES = 6;
    const short QTY_CUBE_FACE_VERTICES = 4;
    const short QTY_CUBE_DIMENSIONS = 3;
    const short QTY_CUBE_VERTICES = QTY_CUBE_DIMENSIONS * QTY_CUBE_FACE_VERTICES * QTY_CUBE_SIDES;
    const double CUBE_VERTICES[QTY_CUBE_VERTICES ] =
    {
        .5, .5, -.5, -.5, .5, -.5, -.5, .5, .5, .5, .5, .5, // TOP
        .5, -.5, .5, -.5, -.5, .5, -.5, -.5, -.5, .5, -.5, -.5, // BOTTOM
        .5, .5, .5, -.5, .5, .5, -.5, -.5, .5, .5, -.5, .5, // FRONT
        .5, -.5, -.5, -.5, -.5, -.5, -.5, .5, -.5, .5, .5, -.5, // BACK
        -.5, .5, .5, -.5, .5, -.5, -.5, -.5, -.5, -.5, -.5, .5, // LEFT
        .5, .5, -.5, .5, .5, .5, .5, -.5, .5, .5, -.5, -.5 // RIGHT
    };
}

void Box::Render_Box()
{
    glBegin(GL_QUADS);
    for(unsigned short i = QTY_CUBE_DIMENSIONS; i < QTY_CUBE_VERTICES; i += QTY_CUBE_DIMENSIONS)
    { // Want to draw every vertex - each vertex has 3 co-ordinates (x,y,z).
        // One vertex of one face. Run 4 times for each face.
        glVertex3d(CUBE_VERTICES[i - 3], CUBE_VERTICES[i - 2], CUBE_VERTICES[i - 1]);
    }
    glEnd();
}

void Box::Render_Textured_Box(GLuint id_top, GLuint id_bottom,
GLuint id_front, GLuint id_back, GLuint id_left, GLuint id_right)
{
    // Accepting named individual params and then mapping to an array is more user-friendly..
    GLuint texture_ids[6] = {id_top, id_bottom, id_front, id_back, id_left, id_right};
    glBegin(GL_QUADS);
    for(unsigned short i = QTY_CUBE_DIMENSIONS; i < QTY_CUBE_VERTICES; i += QTY_CUBE_DIMENSIONS)
    {
        glVertex3d(CUBE_VERTICES[i - 3], CUBE_VERTICES[i - 2], CUBE_VERTICES[i - 1]);
    }
    glEnd();
}

I'm a bit confused as to how I'd specify the texture co-ordinates for each vertex of each face inside the for loop in Render_Textured_Box... would I specify 2d co-ordinates or 3d? Any help would be greatly appreciated. Cheers.

dmatter
dmatter
Textures are usually two dimensional so the texture coordinates are also two dimensional (u, v). This image demonstrates it quite well, a vertex with u, v coordinates of (1, 0) would be textured with that top right corner of the texture's image, a vertex with u, v coordinates of (0.5, 0.5) would be textured with the middle of that image. Fragments between those two vertices would be textured with coordinates parts of the image between (1, 0) and (0.5, 0.5).
bitplane
bitplane
Stick-
glTexCoord2f(x, y);

in your draw loop before sending the vertices.

You'll also have to create a texture, bind it to some data, set the filtering mode and all that stuff too.
Mybowlcut
Mybowlcut
Quote:
Original post by dmatter
Textures are usually two dimensional so the texture coordinates are also two dimensional (u, v). This image demonstrates it quite well, a vertex with u, v coordinates of (1, 0) would be textured with that top right corner of the texture's image, a vertex with u, v coordinates of (0.5, 0.5) would be textured with the middle of that image. Fragments between those two vertices would be textured with coordinates parts of the image between (1, 0) and (0.5, 0.5).
What do u and v stand for? I thought that (1, 0) was x=1, y=0 but then realised that that wouldn't be right haha..

Quote:
Original post by bitplane
Stick-
glTexCoord2f(x, y);

in your draw loop before sending the vertices.

You'll also have to create a texture, bind it to some data, set the filtering mode and all that stuff too.
Like this?
void Box::Render_Textured_Box(GLuint id_top, GLuint id_bottom,GLuint id_front, GLuint id_back, GLuint id_left, GLuint id_right){    // Accepting named individual params and then mapping to an array is more user-friendly.    GLuint texture_ids[6] = {id_top, id_bottom, id_front, id_back, id_left, id_right};    glBegin(GL_QUADS);    for(unsigned short i = QTY_CUBE_DIMENSIONS; i < QTY_CUBE_VERTICES; i += QTY_CUBE_DIMENSIONS)    {        // Set the correct texture for this vertex.        glBindTexture (GL_TEXTURE_2D, texture_ids[i / QTY_CUBE_VERTICES]);        // Specify x, y co-ordinates of texture.        glTexCoord2d(CUBE_VERTICES[i - 3], CUBE_VERTICES[i - 2]);        // Specify x, y, z co-ordinates of vertex.        glVertex3d(CUBE_VERTICES[i - 3], CUBE_VERTICES[i - 2], CUBE_VERTICES[i - 1]);    }    glEnd();}


This is my code that draws the cube (lecturer's instructions were to use code from a previous lesson, hence the excavator... just ignore that as well, it's actually going to be a skybox when I'm done):
void RendererOpenGL::Render(Excavator bigExcavator) // this does the drawing{		double ExcavatorX = bigExcavator.getLocationX();	double ExcavatorZ = bigExcavator.getLocationZ();	double angleAroundY = bigExcavator.getZAngleInDegrees();		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // clear buffers from last frame	glLoadIdentity(); // clear coordinate transformation - (0,0,0) is the screen centre   	// set up camera coordinates and point the camera at (0,0,0)	double cameraDistance = 20;	static double cameraHeight = 2;	double cameraAngle = (90-(180/3.1415927)*atan(cameraDistance/cameraHeight));	// perform the viewing transformation	glRotated(cameraAngle,1,0,0);	glTranslated(0,-cameraHeight,-cameraDistance);		// draw the ground	glColor3d(0,1,0);	double planeSize = 100;	glBegin(GL_QUADS);	  glVertex3d(planeSize,0,planeSize);	  glVertex3d(planeSize,0,-planeSize);	  glVertex3d(-planeSize,0,-planeSize);	  glVertex3d(-planeSize,0,planeSize);	glEnd();    		glPushMatrix();	{            glScaled(10, 10, 10);		Box::Render_Textured_Box(textures["sb_top.bmp"], textures["sb_bottom.bmp"],            textures["sb_front.bmp"], textures["sb_back.bmp"],            textures["sb_left.bmp"], textures["sb_right.bmp"]);	}	glPopMatrix();	SwapBuffers(hDC);}


I loaded my textures like this:
void RendererOpenGL::Load_Textures(){	if(!textures.empty()) return;	ilInit();		glEnable(GL_TEXTURE_2D);	const char* file_names[QTY_TEXTURES] = {"sb_top.bmp", "sb_north.bmp",		"sb_south.bmp", "sb_east.bmp", "sb_west.bmp"};	for(int i = 0; i < QTY_TEXTURES; ++i)	{		// Load image.		ILuint image = 0;		ilGenImages(1, ℑ); // generate handle for image		ilBindImage(image); // make the handle current		ILboolean success = ilLoadImage((ILstring)file_names);			ILenum x = ilGetError();		if(!success)		{			MessageBox(NULL, "could not load texture", "problem", 0);		}		// Create texture.		GLuint texture_id = 0;		glGenTextures(1, &texture_id); // get a unique texture ID		glBindTexture(GL_TEXTURE_2D, texture_id);		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);		glTexImage2D(GL_TEXTURE_2D,	0, ilGetInteger(IL_IMAGE_BPP),			ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 0,			ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());		textures.insert(std::make_pair(file_names, texture_id));	}	}


But it ends up looking like this:


Cheers.

dmatter
dmatter
Quote:
Original post by Mybowlcut
What do u and v stand for? I thought that (1, 0) was x=1, y=0 but then realised that that wouldn't be right haha..
u and v are just coordinate components like x and y, but (x, y) are usually used to refer to spatial coordinates, so (u, v) get used to unambiguously refer to texture coordinates.

Quote:
Original post by bitplane
Like this?*** Source Snippet Removed ***
When you bind a texture it stays bound until you bind a different texture, as such you wouldn't continuously bind a texture per-vertex, you might do it per-face or even better per group of faces, the fewer state changes the better.
Mybowlcut
Mybowlcut
Quote:
Original post by dmatter
Quote:
Original post by Mybowlcut
What do u and v stand for? I thought that (1, 0) was x=1, y=0 but then realised that that wouldn't be right haha..
u and v are just coordinate components like x and y, but (x, y) are usually used to refer to spatial coordinates, so (u, v) get used to unambiguously refer to texture coordinates.

Quote:
Original post by bitplane
Like this?*** Source Snippet Removed ***
When you bind a texture it stays bound until you bind a different texture, as such you wouldn't continuously bind a texture per-vertex, you might do it per-face or even better per group of faces, the fewer state changes the better.
void Box::Render_Textured_Box(GLuint id_top, GLuint id_bottom,GLuint id_front, GLuint id_back, GLuint id_left, GLuint id_right){    // Accepting named individual params and then mapping to an array is more user-friendly.    GLuint texture_ids[6] = {id_top, id_bottom, id_front, id_back, id_left, id_right};    glBegin(GL_QUADS);    for(unsigned short i = QTY_CUBE_DIMENSIONS; i < QTY_CUBE_VERTICES; i += QTY_CUBE_DIMENSIONS)    {        if(i % 4 == 0)        { // Each face has one texture only.            // Set the correct texture for this vertex.            glBindTexture (GL_TEXTURE_2D, texture_ids[i / QTY_CUBE_VERTICES]);        }        // Specify x, y co-ordinates of texture.        glTexCoord2d(CUBE_VERTICES[i - 3], CUBE_VERTICES[i - 2]);        // Specify x, y, z co-ordinates of vertex.        glVertex3d(CUBE_VERTICES[i - 3], CUBE_VERTICES[i - 2], CUBE_VERTICES[i - 1]);    }    glEnd();}
Does that look right? It will specify a texture for i == 0, i == 4, etc... until i == 24 (does it matter if I specify a texture at the end even though it's redundant? Should I make a check in the if statement?). It's still giving me those two weird green coloured textures though...

dmatter
dmatter
Quote:
Original post by Mybowlcut
Does that look right? It will specify a vertex for i == 0, i == 4, etc... until i == 20. It's still giving me those two weird green coloured textures though...
You can't call glBindTexture between glBegin and glEnd calls, it would set the error state to GL_INVALID_OPERATION. If you want to change texture you'll have to start a new chunk of vertices, this is why it's common to apply a single texture to an entire mesh, rather than a texure per face.
Mybowlcut
Mybowlcut
Quote:
Original post by dmatter
Quote:
Original post by Mybowlcut
Does that look right? It will specify a vertex for i == 0, i == 4, etc... until i == 20. It's still giving me those two weird green coloured textures though...
You can't call glBindTexture between glBegin and glEnd calls, it would set the error state to GL_INVALID_OPERATION. If you want to change texture you'll have to start a new chunk of vertices, this is why it's common to apply a single texture to an entire mesh, rather than a texure per face.
Oh... crap. So a nested for loop would work? When you say entire mesh, do you mean the whole box? I haven't had much exposure to 3d stuff... just starting to learn about it.

Edit: This looks like it should work:
void Box::Render_Textured_Box(GLuint id_top, GLuint id_bottom,GLuint id_front, GLuint id_back, GLuint id_left, GLuint id_right){    // Accepting named individual params and then mapping to an array is more user-friendly.    GLuint texture_ids[6] = {id_top, id_bottom, id_front, id_back, id_left, id_right};    for(unsigned short i = 0; i < QTY_CUBE_SIDES; ++i)    {        // Set the correct texture for this side.        glBindTexture(GL_TEXTURE_2D, texture_ids);        glBegin(GL_QUADS);        for(unsigned short v = QTY_CUBE_DIMENSIONS;        v <= QTY_CUBE_VERTICES / QTY_CUBE_SIDES; v += QTY_CUBE_DIMENSIONS)        {                        // Specify x, y co-ordinates of texture.            glTexCoord2d(CUBE_VERTICES[i * v + v - 3], CUBE_VERTICES[i * v + v - 2]);            // Specify x, y, z co-ordinates of vertex.            glVertex3d(CUBE_VERTICES[i * v + v - 3], CUBE_VERTICES[i * v + v - 2], CUBE_VERTICES[i * v + v - 1]);        }        glEnd();    }}
But it ends up looking like this:


Should I just stop trying to be clever and specify the vertices & textures manually?

Cheers.

dmatter
dmatter
Quote:
Original post by Mybowlcut
When you say entire mesh, do you mean the whole box?
Yeah, I'm using the terminology that a mesh is a collection of vertices which represent some kind of object: your box, a person, a house, etc.

Quote:
Edit: This looks like it should work:*** Source Snippet Removed ***But it ends up looking like this:
It looks like the box is being assembled correctly so I can assume your indexing maths is all correct, so it's just texturing.

This is wrong:

// Specify x, y co-ordinates of texture.
glTexCoord2d(CUBE_VERTICES[i * v + v - 3], CUBE_VERTICES[i * v + v - 2]);


You're using the spatial coordinates of the vertices to try and set the texture coordinates. Spatial coordinates indicate the position of the vertex in 3D space, whereas texture coordinates indicate the position on the 2D image that you would like to use. Texture coordinate components lie in the range 0 to 1 (see that image from earlier).

Mybowlcut
Mybowlcut
Quote:
Original post by dmatter
Quote:
Original post by Mybowlcut
When you say entire mesh, do you mean the whole box?
Yeah, I'm using the terminology that a mesh is a collection of vertices which represent some kind of object: your box, a person, a house, etc.

Quote:
Edit: This looks like it should work:*** Source Snippet Removed ***But it ends up looking like this:
It looks like the box is being assembled correctly so I can assume your indexing maths is all correct, so it's just texturing.

This is wrong:

// Specify x, y co-ordinates of texture.
glTexCoord2d(CUBE_VERTICES[i * v + v - 3], CUBE_VERTICES[i * v + v - 2]);


You're using the spatial coordinates of the vertices to try and set the texture coordinates. Spatial coordinates indicate the position of the vertex in 3D space, whereas texture coordinates indicate the position on the 2D image that you would like to use. Texture coordinate components lie in the range 0 to 1 (see that image from earlier).
Oh.. so bitplane wasn't right then?

Ok. I now have this:
void Box::Render_Textured_Box(GLuint id_top, GLuint id_bottom,GLuint id_front, GLuint id_back, GLuint id_left, GLuint id_right){    // Accepting named individual params and then mapping to an array is more user-friendly.    GLuint texture_ids[6] = {id_top, id_bottom, id_front, id_back, id_left, id_right};    short U_COORDS[QTY_CUBE_FACE_VERTICES] = {0, 1, 1, 0};    short V_COORDS[QTY_CUBE_FACE_VERTICES] = {0, 0, 1, 1};    for(unsigned short i = 0; i < QTY_CUBE_SIDES; ++i)    {        // Set the correct texture for this side.        glBindTexture(GL_TEXTURE_2D, texture_ids);        glBegin(GL_QUADS);        for(unsigned short v = QTY_CUBE_DIMENSIONS;        v <= QTY_CUBE_VERTICES / QTY_CUBE_SIDES; v += QTY_CUBE_DIMENSIONS)        {                        // Specify x, y co-ordinates of texture.            glTexCoord2s(U_COORDS[v / 3], V_COORDS[v / 3]);            // Specify x, y, z co-ordinates of vertex.            glVertex3d(CUBE_VERTICES[i * v + v - 3], CUBE_VERTICES[i * v + v - 2], CUBE_VERTICES[i * v + v - 1]);        }        glEnd();    }}


I changed the cube's colour so you can see what's going on. I'm still getting a funky cube (albeit a bit different from the last one):


Edit: Interesting... I logged the Render_Textured_Box function and this is what it was doing:
Bound texture 0glBegin()	texture uv coords: 1 0	mesh xyz coords: 0.5 0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: -13108 -13108	mesh xyz coords: 0.5 0.5 0.5glEnd()Bound texture 1glBegin()	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 0 1	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: -13108 -13108	mesh xyz coords: 0.5 -0.5 -0.5glEnd()Bound texture 2glBegin()	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: -13108 -13108	mesh xyz coords: 0.5 -0.5 0.5glEnd()Bound texture 3glBegin()	texture uv coords: 1 0	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 -0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: -13108 -13108	mesh xyz coords: 0.5 0.5 -0.5glEnd()Bound texture 4glBegin()	texture uv coords: 1 0	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 0 1	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: -13108 -13108	mesh xyz coords: -0.5 -0.5 0.5glEnd()Bound texture 5glBegin()	texture uv coords: 1 0	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: -13108 -13108	mesh xyz coords: 0.5 -0.5 -0.5glEnd()
I'll fix that up and see if it fixes it.

Another edit: Getting there... but still looks a bit screwed up... just a bit haha:

Bound texture 0glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 0.5 0.5glEnd()Bound texture 1glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()Bound texture 2glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 0.5glEnd()Bound texture 3glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 -0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 0.5 -0.5glEnd()Bound texture 4glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: -0.5 -0.5 0.5glEnd()Bound texture 5glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()


Cheers.

[Edited by - Mybowlcut on March 26, 2009 2:58:05 AM]

Mybowlcut
Mybowlcut
I fixed a few things that were wrong... eg
Box::Render_Textured_Box(textures["sb_top.bmp"], -1, textures["sb_south.bmp"],            textures["sb_north.bmp"], textures["sb_west.bmp"],            textures["sb_east.bmp"]);
I was passing in the wrong names... haha. Looking even better, but still slightly deformed:

I also made it so that you don't have to specify a texture for every side, since the lecturer has told us we don't need a texture for the bottom of the skybox since it won't be seen:
if(texture_ids > 0)        { // A texture was specified.            // Set the correct texture for this side.            glBindTexture(GL_TEXTURE_2D, texture_ids);            stream << "Bound texture " << texture_ids << std::endl;        }

But looking at the log after that, I get this:
Bound texture 1glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 0.5 0.5glEnd()Bound texture 4294967295glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()Bound texture 3glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 0.5glEnd()Bound texture 2glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 -0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 0.5 -0.5glEnd()Bound texture 5glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: -0.5 -0.5 0.5glEnd()Bound texture 4glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()
Is that because I didn't specify a texture? :s

Cheers.

dmatter
dmatter
Quote:
Original post by Mybowlcut
Oh.. so bitplane wasn't right then?
Ah, he was, but he was just using x and y to mean the texture coordinates (rather than spatial coordinates this time); I prefer to use either (u, v) or (s, t) and you'll find that both are commonly used to refer to texture coordinates.

Quote:
I changed the cube's colour so you can see what's going on.
That helps, it looks like you aren't actually constructing the cube correctly after all. So it's time to rexamine your indexing:

        for(unsigned short v = QTY_CUBE_DIMENSIONS;        v <= QTY_CUBE_VERTICES / QTY_CUBE_SIDES; v += QTY_CUBE_DIMENSIONS)        {                        // Specify x, y co-ordinates of texture.            glTexCoord2s(U_COORDS[v / 3], V_COORDS[v / 3]);            // Specify x, y, z co-ordinates of vertex.            glVertex3d(CUBE_VERTICES[i * v + v - 3], CUBE_VERTICES[i * v + v - 2], CUBE_VERTICES[i * v + v - 1]);        }


I'd go for this:

        const int verts_per_face = 4;        const int components_per_vert = 3;        int face_offset = i * verts_per_face;        for(int v = 0; v <= verts_per_face; ++v)        {            // Specify x, y co-ordinates of texture.            glTexCoord2s(U_COORDS[v], V_COORDS[v]);            // Specify x, y, z co-ordinates of vertex.            int vert_offset = v * components_per_vert;            int vert_idx = face_offset + vert_offset;            glVertex3d(CUBE_VERTICES[vert_idx + 0], CUBE_VERTICES[vert_idx + 1], CUBE_VERTICES[vert_idx + 2]);        }

It's probably beneficial for you to consider making vertex and face structures, something like this:
struct vertex{    float x, y, z;    float u, v;};struct quadface{    int texture_id;    vertex vertices[4];};
Then just keeping an array of quadfaces, it would make indexing a lot simpler [smile].
dmatter
dmatter
Right, in the time I've written that you've made lots of edits with logs and all sorts [grin]. Anyway, it now looks like you're spatial coordinates are wrong and your indexing was fine all along. The ordering of coordinates on a face is important, they need to be either clockwise or anti-clockwise (often the former); you have some that aren't ordered correctly.
Mybowlcut
Mybowlcut
Quote:
Original post by dmatter
Quote:
Original post by Mybowlcut
Oh.. so bitplane wasn't right then?
Ah, he was, but he was just using x and y to mean the texture coordinates (rather than spatial coordinates this time); I prefer to use either (u, v) or (s, t) and you'll find that both are commonly used to refer to texture coordinates.

Quote:
I changed the cube's colour so you can see what's going on.
That helps, it looks like you aren't actually constructing the cube correctly after all. So it's time to rexamine your indexing:

*** Source Snippet Removed ***

I'd go for this:

*** Source Snippet Removed ***
It's probably beneficial for you to consider making vertex and face structures, something like this:
struct vertex{    float x, y, z;    float u, v;};struct quadface{    int texture_id;    vertex vertices[4];};
Then just keeping an array of quadfaces, it would make indexing a lot simpler [smile].
If it's cool with you (ie if it's bearable) I'll try and get it working the hard way before I introduce those structs. A question about the vertex struct, though... will u and v be useful for anything outside texturing?

I changed my code as per your advice (changing a few names haha):
void Box::Render_Textured_Box(GLuint id_top, GLuint id_bottom,GLuint id_front, GLuint id_back, GLuint id_left, GLuint id_right){    std::ofstream stream;    stream.open("log.txt");    // Accepting named individual params and then mapping to an array is more user-friendly.    GLuint texture_ids[6] = {id_top, id_bottom, id_front, id_back, id_left, id_right};    short U_COORDS[VERTS_PER_FACE] = {0, 1, 1, 0};    short V_COORDS[VERTS_PER_FACE] = {0, 0, 1, 1};    for(unsigned short i = 0; i < SIDES; ++i)    {        if(texture_ids > 0)        { // A texture was specified.            // Set the correct texture for this side.            glBindTexture(GL_TEXTURE_2D, texture_ids);            stream << "Bound texture " << texture_ids << std::endl;        }                int face_offset = i * VERTS_PER_FACE;        glBegin(GL_QUADS);        stream << "glBegin()" << std::endl;        for(int v = 0; v < VERTS_PER_FACE; ++v)        {            // Specify x, y co-ordinates of texture.            glTexCoord2s(U_COORDS[v], V_COORDS[v]);            stream << "\ttexture uv coords: " << U_COORDS[v] << ' ' << V_COORDS[v] << std::endl;            // Specify x, y, z co-ordinates of vertex.            int vert_offset = v * COORDS_PER_VERT;            int vert_idx = face_offset + vert_offset;            glVertex3d(CUBE_VERTICES[vert_idx + 0], CUBE_VERTICES[vert_idx + 1], CUBE_VERTICES[vert_idx + 2]);            stream << "\tmesh xyz coords: " << CUBE_VERTICES[vert_idx + 0] << ' ' <<                CUBE_VERTICES[vert_idx + 1] << ' ' << CUBE_VERTICES[vert_idx + 2] << std::endl;        }        glEnd();        stream << "glEnd()" << std::endl;    }}


Bound texture 1glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 0.5 0.5glEnd()Bound texture 4294967295glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 -0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 0 1	mesh xyz coords: -0.5 0.5 -0.5glEnd()Bound texture 3glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 -0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()Bound texture 2glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 -0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()Bound texture 5glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 0.5 -0.5glEnd()Bound texture 4glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()

dmatter
dmatter
From the log, it looks like your vertex coordinates are still messed up (the second face, for example, has repeating vertices). From the look of the screenshot fixing this should be the last hurdle [smile].

Also, note this line:

if(texture_ids > 0)

And then this line:

GLuint texture_ids[6] = {id_top, id_bottom, id_front, id_back, id_left, id_right};

Since its type is an unsigned integer it can never be less than zero, it will just 'wrap around' to the largest value, which explains your dodgy log value, in other words you're trying to bind a non-existent texture, in this case I believe a default blank texture is used, you shouldn't rely on this though. The correct way to access the default blank texture is call glBindTexture(0); This won't disable texturing (it just uses a blank one), to actualy disable texturing you can call glDisable(GL_TEXTURE_2D); There is an associated glEnable call, that you must have already used at some point, to re-enable texturing again.
Mybowlcut
Mybowlcut
Quote:
Original post by dmatter
From the log, it looks like your vertex coordinates are still messed up (the second face, for example, has repeating vertices). From the look of the screenshot fixing this should be the last hurdle [smile].

Also, note this line:

if(texture_ids > 0)

And then this line:

GLuint texture_ids[6] = {id_top, id_bottom, id_front, id_back, id_left, id_right};

Since its type is an unsigned integer it can never be less than zero, it will just 'wrap around' to the largest value, which explains your dodgy log value, in other words you're trying to bind a non-existent texture, in this case I believe a default blank texture is used, you shouldn't rely on this though. The correct way to access the default blank texture is call glBindTexture(0); This won't disable texturing (it just uses a blank one), to actualy disable texturing you can call glDisable(GL_TEXTURE_2D); There is an associated glEnable call, that you must have already used at some point, to re-enable texturing again.
Hmm.. that's strange. I copied the vertex locations from here, (changed from 1 to .5 though) so it should all be good. Here's what CUBE_VERTICES is defined as:
const double CUBE_VERTICES[QTY_CUBE_VERTICES] =	{		.5, .5, -.5, -.5, .5, -.5, -.5, .5, .5, .5, .5, .5, // TOP		.5, -.5, .5, -.5, -.5, .5, -.5, -.5, -.5, .5, -.5, -.5, // BOTTOM		.5, .5, .5, -.5, .5, .5, -.5, -.5, .5, .5, -.5, .5, // FRONT		.5, -.5, -.5, -.5, -.5, -.5, -.5, .5, -.5, .5, .5, -.5, // BACK		-.5, .5, .5, -.5, .5, -.5, -.5, -.5, -.5, -.5, -.5, .5, // LEFT		.5, .5, -.5, .5, .5, .5, .5, -.5, .5, .5, -.5, -.5 // RIGHT	};
Perhaps it is the calls to glVertex that are wrong (ie the index of vertices passed to it)?

Thanks for the texture thing! I changed that and the log looks right now.

Edit: Here's your code, its log and screenshot:
void Box::Render_Textured_Box(GLuint id_top, GLuint id_bottom,GLuint id_front, GLuint id_back, GLuint id_left, GLuint id_right){    std::ofstream stream;    stream.open("log.txt");    // Accepting named individual params and then mapping to an array is more user-friendly.    GLuint texture_ids[6] = {id_top, id_bottom, id_front, id_back, id_left, id_right};    short U_COORDS[VERTS_PER_FACE] = {0, 1, 1, 0};    short V_COORDS[VERTS_PER_FACE] = {0, 0, 1, 1};    for(unsigned short i = 0; i < SIDES; ++i)    {        // Set the correct texture for this side.        glBindTexture(GL_TEXTURE_2D, texture_ids);        stream << "Bound texture " << texture_ids << std::endl;                int face_offset = i * VERTS_PER_FACE;        glBegin(GL_QUADS);        stream << "glBegin()" << std::endl;        for(int v = 0; v < VERTS_PER_FACE; ++v)        {            // Specify x, y co-ordinates of texture.            glTexCoord2s(U_COORDS[v], V_COORDS[v]);            stream << "\ttexture uv coords: " << U_COORDS[v] << ' ' << V_COORDS[v] << std::endl;            // Specify x, y, z co-ordinates of vertex.            int vert_offset = v * COORDS_PER_VERT;            int vert_idx = face_offset + vert_offset;            glVertex3d(CUBE_VERTICES[vert_idx + 0], CUBE_VERTICES[vert_idx + 1], CUBE_VERTICES[vert_idx + 2]);            stream << "\tmesh xyz coords: " << CUBE_VERTICES[vert_idx + 0] << ' ' <<                CUBE_VERTICES[vert_idx + 1] << ' ' << CUBE_VERTICES[vert_idx + 2] << std::endl;        }        glEnd();        stream << "glEnd()" << std::endl;    }}
Bound texture 1glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 0.5 0.5glEnd()Bound texture 0glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 -0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 0 1	mesh xyz coords: -0.5 0.5 -0.5glEnd()Bound texture 3glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 -0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()Bound texture 2glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 -0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()Bound texture 5glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 0.5 -0.5glEnd()Bound texture 4glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()
screenshot

My code, its log and screenshot:
void Box::Render_Textured_Box(GLuint id_top, GLuint id_bottom,GLuint id_front, GLuint id_back, GLuint id_left, GLuint id_right){    std::ofstream stream;    stream.open("log.txt");    // Accepting named individual params and then mapping to an array is more user-friendly.    GLuint texture_ids[6] = {id_top, id_bottom, id_front, id_back, id_left, id_right};    short U_COORDS[VERTS_PER_FACE] = {0, 1, 1, 0};    short V_COORDS[VERTS_PER_FACE] = {0, 0, 1, 1};    for(unsigned short i = 0; i < SIDES; ++i)    {        // Set the correct texture for this side.        glBindTexture(GL_TEXTURE_2D, texture_ids);        stream << "Bound texture " << texture_ids << std::endl;                int face_offset = i * VERTS_PER_FACE;        glBegin(GL_QUADS);        stream << "glBegin()" << std::endl;        for(unsigned short v = COORDS_PER_VERT;        v <= QTY_CUBE_VERTICES / SIDES; v += COORDS_PER_VERT)        {                        // Specify x, y co-ordinates of texture.            glTexCoord2s(U_COORDS[v / 3 - 1], V_COORDS[v / 3 - 1]);            stream << "\ttexture uv coords: " << U_COORDS[v / 3 - 1] << ' ' << V_COORDS[v / 3 - 1] << std::endl;            // Specify x, y, z co-ordinates of vertex.            glVertex3d(CUBE_VERTICES[i * v + v - 3], CUBE_VERTICES[i * v + v - 2], CUBE_VERTICES[i * v + v - 1]);            stream << "\tmesh xyz coords: " << CUBE_VERTICES[i * v + v - 3] << ' ' <<                CUBE_VERTICES[i * v + v - 2] << ' ' << CUBE_VERTICES[i * v + v - 1] << std::endl;        }        glEnd();        stream << "glEnd()" << std::endl;    }}
Bound texture 1glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 0.5 0.5glEnd()Bound texture 0glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()Bound texture 3glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 0.5glEnd()Bound texture 2glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 -0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 0.5 -0.5glEnd()Bound texture 5glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: -0.5 -0.5 0.5glEnd()Bound texture 4glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()
screenshot

Cheers.

dmatter
dmatter
Quote:
Original post by Mybowlcut
Perhaps it is the calls to glVertex that are wrong (ie the index of vertices passed to it)?
I think you're right, I'm very tired and I'm making mistakes, looks like I've missed a multiply:

int face_offset = i * VERTS_PER_FACE * COMPONENTS_PER_VERT;
Mybowlcut
Mybowlcut
Quote:
Original post by dmatter
Quote:
Original post by Mybowlcut
Perhaps it is the calls to glVertex that are wrong (ie the index of vertices passed to it)?
I think you're right, I'm very tired and I'm making mistakes, looks like I've missed a multiply:

int face_offset = i * VERTS_PER_FACE * COMPONENTS_PER_VERT;
Oh now it's looking more like a skybox! Haha.



Bound texture 1glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 0.5 0.5glEnd()Bound texture 0glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 -0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()Bound texture 3glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 0.5glEnd()Bound texture 2glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 -0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 -0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 0.5 -0.5glEnd()Bound texture 5glBegin()	texture uv coords: 0 0	mesh xyz coords: -0.5 0.5 0.5	texture uv coords: 1 0	mesh xyz coords: -0.5 0.5 -0.5	texture uv coords: 1 1	mesh xyz coords: -0.5 -0.5 -0.5	texture uv coords: 0 1	mesh xyz coords: -0.5 -0.5 0.5glEnd()Bound texture 4glBegin()	texture uv coords: 0 0	mesh xyz coords: 0.5 0.5 -0.5	texture uv coords: 1 0	mesh xyz coords: 0.5 0.5 0.5	texture uv coords: 1 1	mesh xyz coords: 0.5 -0.5 0.5	texture uv coords: 0 1	mesh xyz coords: 0.5 -0.5 -0.5glEnd()


I'll get movement to work and then I'll see if it looks good on all sides (I know I could just rotate the screen but I've gotta get movement working anyway haha). Thanks so much for all your help so far! Friggon legend!

Cheers.

dmatter
dmatter
Quote:
Original post by Mybowlcut
Thanks so much for all your help so far! Friggon legend!

Cheers.
No problem, glad to see it working now [smile]

To answer a question I missed earlier (again, due to tiredness, sorry):

Quote:
A question about the vertex struct, though... will u and v be useful for anything outside texturing?
Nope, u and v are just texture coordinates, that's all they're good for, in the same way that x, y and z are only useful as spatial coordinates. You could add r, g, b for colour too and they'd only be useful for colouring.

Bedtime for me I reckon.
Mybowlcut
Mybowlcut
Quote:
Original post by dmatter
Quote:
Original post by Mybowlcut
Thanks so much for all your help so far! Friggon legend!

Cheers.
No problem, glad to see it working now [smile]

To answer a question I missed earlier (again, due to tiredness, sorry):

Quote:
A question about the vertex struct, though... will u and v be useful for anything outside texturing?
Nope, u and v are just texture coordinates, that's all they're good for, in the same way that x, y and z are only useful as spatial coordinates. You could add r, g, b for colour too and they'd only be useful for colouring.

Bedtime for me I reckon.
Oh, ok.



It's working now! Some sides are upside-down but hopefully I have enough brains to figure that out on my own (*crickets chirping*). Thanks for all your help again, and enjoy your sleep!


Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.