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();
}
🔒 Locked
Texturing a cube
Advertisement
Original Post
Hey. I've got a function to render a cube (I call it box here - just ignore that):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.
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).
Quote: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..
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).
Quote:Like this?
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.
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.
Quote: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.
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..
Quote: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.
Original post by bitplane
Like this?*** Source Snippet Removed ***
Quote:
Original post by dmatter Quote: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.
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..Quote: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.
Original post by bitplane
Like this?*** Source Snippet Removed ***
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();}Quote: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.
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...
Quote: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.
Original post by dmatter Quote: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.
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...
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(); }}
Should I just stop trying to be clever and specify the vertices & textures manually?
Cheers.
Quote: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.
Original post by Mybowlcut
When you say entire mesh, do you mean the whole box?
Quote:It looks like the box is being assembled correctly so I can assume your indexing maths is all correct, so it's just texturing.
Edit: This looks like it should work:*** Source Snippet Removed ***But it ends up looking like this:
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).
Quote:Oh.. so bitplane wasn't right then?
Original post by dmatter Quote: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.
Original post by Mybowlcut
When you say entire mesh, do you mean the whole box?Quote:It looks like the box is being assembled correctly so I can assume your indexing maths is all correct, so it's just texturing.
Edit: This looks like it should work:*** Source Snippet Removed ***But it ends up looking like this:
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).
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()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]
I fixed a few things that were wrong... egI 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:
But looking at the log after that, I get this:Is that because I didn't specify a texture? :s
Cheers.
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 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()Cheers.
Quote: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.
Original post by Mybowlcut
Oh.. so bitplane wasn't right then?
Quote:That helps, it looks like you aren't actually constructing the cube correctly after all. So it's time to rexamine your indexing:
I changed the cube's colour so you can see what's going on.
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].
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.
Quote: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?
Original post by dmatter Quote: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.
Original post by Mybowlcut
Oh.. so bitplane wasn't right then?Quote:That helps, it looks like you aren't actually constructing the cube correctly after all. So it's time to rexamine your indexing:
I changed the cube's colour so you can see what's going on.
*** 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:Then just keeping an array of quadfaces, it would make indexing a lot simpler [smile].struct vertex{ float x, y, z; float u, v;};struct quadface{ int texture_id; vertex vertices[4];};
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()
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.
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.
Quote: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:
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.
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 };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()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()Cheers.
Quote:Oh now it's looking more like a skybox! Haha.
Original post by dmatter Quote:I think you're right, I'm very tired and I'm making mistakes, looks like I've missed a multiply:
Original post by Mybowlcut
Perhaps it is the calls to glVertex that are wrong (ie the index of vertices passed to it)?
int face_offset = i * VERTS_PER_FACE * COMPONENTS_PER_VERT;

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.
Quote:No problem, glad to see it working now [smile]
Original post by Mybowlcut
Thanks so much for all your help so far! Friggon legend!
Cheers.
To answer a question I missed earlier (again, due to tiredness, sorry):
Quote: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.
A question about the vertex struct, though... will u and v be useful for anything outside texturing?
Bedtime for me I reckon.
Quote:Oh, ok.
Original post by dmatter Quote:No problem, glad to see it working now [smile]
Original post by Mybowlcut
Thanks so much for all your help so far! Friggon legend!
Cheers.
To answer a question I missed earlier (again, due to tiredness, sorry):Quote: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.
A question about the vertex struct, though... will u and v be useful for anything outside texturing?
Bedtime for me I reckon.

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.
Advertisement