Texture Repeating Instead of Stretching

Hello again!

When I try to read in a RGB texture via given coordinates from an OBJ file, it keeps repeating across the object I’ve drawn in. I have GL_CLAMP set, and the coordinates are all within the range of 0-1. For every face, I read in the texture coordinate using glTexCoord2f() (my values are stored in a vector float array) and then the vertex - essentially drawing a series of triangles.

How do I go about getting it to stretch to the model? I’ve tried mipmaps, changing various environment settings, trying to enlarge the texture (unsuccessfully).

Any light shed on this would be appreciated.

Thanks!

Screenshot here: bit.ly/opengltexrepeat
Code here: pastebin.com/NPckMhj7

Well, hi again :slight_smile:

I looked at your code and the thing that seems strange is that you fetch texture coordinate indices from the vector that apparently stores vertex position indices. So shouldn’t the lines:


tI = (facesVertices[i] - 1) * 2;
tI2 = (facesVertices[i + 1] - 1) * 2;
tI3 = (facesVertices[i + 2] - 1) * 2;

actually be:


tI = (facesTextures[i] - 1) * 2;
tI2 = (facesTextures[i + 1] - 1) * 2;
tI3 = (facesTextures[i + 2] - 1) * 2;

Hey :smiley:

Well, that part, to be honest, doesn’t matter much. In the OBJ I am loading, the values are equal - so in a line f v1/t1 v1/t2 v2/t3, the value at v1 and t1 are equal, and it is the same for the other two pairs. I had created the two arrays before I realised they held exactly the same values.

The indices might be the same for this particular obj file but in general your code shouldn’t assume they’re the same. The more seams in uv layout there are in the model, the more likely the texture coordinate indices will not coincide with position indices. Also, an exporter might have its own logic for assigning indices so it could happen that none of the position indices coincide with uv indices, etc… The best approach would be to maintain separate arrays.

Second, even if you assume the indices are the same, when getting the texture coord indices you happen to reference the position array assuming there are 2 vertices per face, whereas in fact, there are 3

So this:


tI = (facesVertices[i] - 1) * 2;
tI2 = (facesVertices[i + 1] - 1) * 2;
tI3 = (facesVertices[i + 2] - 1) * 2;

should become:


tI = (facesVertices[i] - 1) * 3;
tI2 = (facesVertices[i + 1] - 1) * 3;
tI3 = (facesVertices[i + 2] - 1) * 3;

or to show more obviously what you’re actually doing:


tI = vI;
tI2 = vI2;
tI3 =  vI3;

Note that this a bad approach although it seemingly might work for the model in question. But as I said earlier - maintain a separate array to avoid headache in the future.

Oh, I totally agree. This program is specifically fine-tuned to parse one specific OBJ right through - which is a horrible approach for a general OBJ loader. I did that on purpose though. :stuck_out_tongue: With the teapot problem earlier, I realised one of the OBJ test files I was using, a lamp, sometimes had 4 or 5 indices for vertices in the same row. I intend on accomodating all that later before I post the entire thing online. There’s no way I can post this - it’s embarrassing, heh.

I changed the array to the separate one - facesTextures.

Now, what you pointed out… I didn’t take the values from the vertices and texture coordinates the same way. Because this is file-specific, I took:

  • 3 values in a row for vertices. Hence the *3. As they are stored v x y z, I took all x, y, z.
  • 2 values in a row for textures, as the third one was a 0. Hence the *2. They are stored vt u v w. And w was always 0.0. So I ignored w completely and it’s not in the array.

Still stuck with the same problem. Meh.

Can we see the obj file?

There’s 302k lines… I tried posting it, but it won’t let me. =.= Is this excerpt okay?

# 75972 vertices.
v -55.51 -46.45 -20.38
v -55.23 -47.11 -20.50
v -55.16 -47.80 -20.63
.
.
.

v 63.12 -53.27 -8.39
v 63.11 -53.89 -8.58
mtllib train_02463_1.mtl
usemtl default
vt 0.000 0.199 0.0
vt 0.000 0.197 0.0
vt 0.000 0.194 0.0
vt 0.000 0.191 0.0
.
.
.
vt 1.000 0.179 0.0
vt 1.000 0.176 0.0
vt 1.000 0.173 0.0
vt 1.000 0.171 0.0
vt 1.000 0.168 0.0
vt 1.000 0.165 0.0
vt 1.000 0.162 0.0
# 150958 triangles.
f 36599/36599 36600/36600 36253/36253
f 36947/36947 36600/36600 36599/36599
f 36599/36599 36946/36946 36947/36947
f 37294/37294 36947/36947 36946/36946
f 36946/36946 37293/37293 37294/37294
f 37641/37641 37294/37294 37293/37293
f 37293/37293 37640/37640 37641/37641
.
.
.

Ok.
What’s your texture file format?

File type? SGI RGB.

Well then that’s your problem. You seem to be ignoring the file header and you’re assuming the pixel format is just raw interleaved RGB pixels. I’m not too familiar with the format but by skimming the reference it seems that it typically stores its pixel data in scanlines per channel. So you should first read the header, determine the format from info found there, and then read in the pixel data accordingly.

http://paulbourke.net/dataformats/sgirgb/sgiversion.html

Or better yet, use image loading library like freeimage that’ll do all that for you in one function call and deliver you the pixel data in one of the pixel formats expected by glTexImage.

WELL. That is good to know! I used a converter just now to switch it to BMP to see what happens… The face does not load exactly right, but it’s much larger and not repeated than loading the RGB file. I’ll have to figure out how to use FreeImage, looks like a nice library.

Thanks! Your assistance is much appreciated. =)

BMP won’t work properly either due to file header bytes being interpreted as pixel data. Depending on the header size, your channels might get shifted and colors not interpreted properly, and you’ll probably see a bit of “junk” somewhere in the corner of the image.

With you current code, the only thing that will be loaded correctly-to-pixel is headerless interleaved raw format. So try to re-save it like that from an image editing program.