PDA

View Full Version : scaling and texture



James3D
04-08-2017, 11:48 AM
Dear all,

I'm encountering an issue when scaling a shape where a texture is applied. Using the following primitives to set up my texture:



glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


And my code to draw a cube by faces:



void drawBox(GLfloat size, GLenum type)
{
static GLfloat n[6][3] =
{
{ -1.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0 },
{ 1.0, 0.0, 0.0 },
{ 0.0, -1.0, 0.0 },
{ 0.0, 0.0, 1.0 },
{ 0.0, 0.0, -1.0 }
};
static GLint faces[6][4] =
{
{ 0, 1, 2, 3 },
{ 3, 2, 6, 7 },
{ 7, 6, 5, 4 },
{ 4, 5, 1, 0 },
{ 5, 6, 2, 1 },
{ 7, 4, 0, 3 }
};
GLfloat v[8][3];
GLint i;

v[0][0] = v[1][0] = v[2][0] = v[3][0] = -size / 2;
v[4][0] = v[5][0] = v[6][0] = v[7][0] = size / 2;
v[0][1] = v[1][1] = v[4][1] = v[5][1] = -size / 2;
v[2][1] = v[3][1] = v[6][1] = v[7][1] = size / 2;
v[0][2] = v[3][2] = v[4][2] = v[7][2] = -size / 2;
v[1][2] = v[2][2] = v[5][2] = v[6][2] = size / 2;

for (i = 5; i >= 0; i--) {
glBegin(type);
glNormal3fv(&n[i][0]);
glTexCoord2f(size, size); glVertex3fv(&v[faces[i][0]][0]);
glTexCoord2f(0, size); glVertex3fv(&v[faces[i][1]][0]);
glTexCoord2f(0, 0); glVertex3fv(&v[faces[i][2]][0]);
glTexCoord2f(size, 0); glVertex3fv(&v[faces[i][3]][0]);
glEnd();
}
}




glBindTexture(GL_TEXTURE_2D, BRICK_TEXTURE);
// Load texture with primitives above and gluBuild2DMipmaps...
drawBox(2, GL_POLYGON);


2354

Nevertheless, as soon as I apply a scaling, such as glScalef(0.5, 3, 1);, the result is the following:

2355

I was expecting that the texture ratio would stay the same or cropped, in order to prevent any distortion of the texture. Do you have any idea on how I can prevent the distortion ?

Many thanks !
James

john_connor
04-08-2017, 02:10 PM
scale also the texture coordinates like you scaled the cube vertices if you want the texture to be "static" / not stretched

James3D
04-08-2017, 02:32 PM
scale also the texture coordinates like you scaled the cube vertices if you want the texture to be "static" / not stretched

Dear John, thanks for your reply. I'm not sure to understand what you mean by scaling texture coordinates. Is it not already the case as I supply the size of the cube to glTexCoord2f calls ?

Thanks

john_connor
04-08-2017, 05:09 PM
I'm not sure to understand what you mean by scaling texture coordinates. Is it not already the case as I supply the size of the cube to glTexCoord2f calls ?

no, its not, after the transformation (that mean multiplication with the scale / rotation / translation matrix) the cube has obviously another size, if you want an unstretched texture applied, you also have to scale the texture coords

James3D
04-08-2017, 06:36 PM
no, its not, after the transformation (that mean multiplication with the scale / rotation / translation matrix) the cube has obviously another size, if you want an unstretched texture applied, you also have to scale the texture coords

Hi John, my function drawBox now takes a triplet [width, height, depth] instead of a size.

Thus, my vectors array is construct in that way now:



v[0][0] = v[1][0] = v[2][0] = v[3][0] = -_width / 2;
v[4][0] = v[5][0] = v[6][0] = v[7][0] = _width / 2;
v[0][1] = v[1][1] = v[4][1] = v[5][1] = -_height / 2;
v[2][1] = v[3][1] = v[6][1] = v[7][1] = _height / 2;
v[0][2] = v[3][2] = v[4][2] = v[7][2] = -_depth / 2;
v[1][2] = v[2][2] = v[5][2] = v[6][2] = _depth / 2;


And the scaling of the texture per face your mentioned is now calculated in an additional array:



_texels[0][0] = _texels[0][3] = _texels[1][2] =_texels[1][1] = _texels[2][0] =_texels[2][3] = _texels[3][1] = _texels[3][2] = _depth;
_texels[0][1] = _texels[0][2] = _texels[2][1] = _texels[2][2] = _texels[4][1] = _texels[4][2] = _texels[5][1] = _texels[5][2] = _height;
_texels[1][0] = _texels[1][3] = _texels[3][0] = _texels[3][3] = _texels[4][0] = _texels[4][3] = _texels[5][0] = _texels[5][3] = _width;


Finally, the code to draw the box, acting as a cuboid, looks like:



for (int i = 5; i >= 0; i--) {
// bind the texture...
glBegin(GL_QUADS);
glNormal3dv(_normalVectors[i], 0);
glTexCoord2d(_texels[i][0], _texels[i][1]);
glVertex3dv(v[_faces[i][0]], 0);
glTexCoord2d(0, _texels[i][2]);
glVertex3dv(v[_faces[i][1]], 0);
glTexCoord2d(0, 0);
glVertex3dv(v[_faces[i][2]], 0);
glTexCoord2d(_texels[i][3], 0);
glVertex3dv(v[_faces[i][3]], 0);
glEnd();
}


The result is pretty neat:

2358

What do you think about this approach ?

Thanks for your help

GClements
04-09-2017, 06:08 AM
Note that with the fixed-function pipeline, you can scale texture coordinates using the texture matrix: glMatrixMode(GL_TEXTURE).

However, this probably isn't particularly useful in this case as the matrix would need to be different for different faces. It can be useful for "extrusion", where you only scale one axis, or at least where two axes always have the same scale factor.

Another option is to generate texture coordinates from vertex coordinates using glTexGen(). But again, you'd need different settings for the different faces.