TextureIO Flipping Out??

I’ve just been testing my OBJ file loader with JSR-231 RC 2, and the texturing started going ‘wrong’.

It seems that the latest version of TextureIO is flipping the loaded images around their y-axis, which is messing up my rendering code. This didn’t happen back in the December version of JOGL.

I’m not sure if this is a ‘problem’, but it’s certainly an inconvenience. Would it be possible to expose a ‘doFlip’ flag in TextureIO’s newTexture() methods to turn the flipping on/off?

  • Andrew

This was an intentional change to BufferedImage-based textures loaded via TextureIO and is highlighted in the 1.1.0-rc2 release notes posted on this thread. This change enabled the introduction of one of the new Texture.updateSubImage() APIs and the new Java 2D interoperability helper classes, including the TextureRenderer and TextRenderer. Correct code using TextureIO should have been using either the Texture.getImageTexCoords() or Texture.getSubImageTexCoords() APIs, or paying attention to the return value of Texture.getMustFlipVertically(). I’m sorry this change affected you, but you’re going to have to update your code. The efficiency gains from not flipping the contents of BufferedImage-based textures far outweigh the downsides.

My loader reads the texture coordinates from an OBJ file, which was generated by a graphics app. Those coordinates are specified as if the image isn’t flipped.

What I’m concerned about is why things use to work in my loader, but now don’t. It seems like the texture image I’m using wasn’t flipped in the December version of JOGL, but now is. That’s a backward compatibility issue that could affect lots of people (?).

Also, I thought that flipping was an optional feature. For example, it’s exposed in some of the TextureData() constructors. Couldn’t that be made visible via TextureIO as well?

  • Andrew

In order to use these texture coordinates correctly with the TextureIO classes, you need to feed them through the Texture.getSubImageTexCoords() methods. I’m assuming the graphics application generates (s, t) coordinates from [0…1]. Depending on whether the image has power-of-two dimensions or not, the TextureIO classes may, for example, use the GL_ARB_texture_rectangle extension, in which case the texture coordinates to display the entire texture go from (0, 0) to (image width - 1, image height - 1). The getImageTexCoords() and getSubImageTexCoords() methods abstract away this difference. Your loader should always have been doing this transformation.

It is a change in behavior, but one which should not affect correctly written code according to the previous API definitions.

The “vertical flip” bit is an indicator to the end user whether the texture coordinates need to be flipped vertically in order to display the image in upright orientation via OpenGL. It is intended to abstract away differences in image file formats where some supply the image data from the bottom up and some from the top down. As a convenience to the end user, we used to manually flip the image data in BufferedImages before transferring them to OpenGL textures, but we stopped doing this in 1.1.0-rc2 because it introduced large inefficiencies when trying to update sub-portions of textures on the fly. There’s no way to reasonably support an “override” bit telling the TextureIO implementation to manually flip image data vertically – this doesn’t work for many image formats.

I am having a similar problem. Is there some place that clearly explains how to use these functions to get the texture coordinates in situations where they are pre calculated separately from the image.

Also, in the mean time is there a webstart link that will give us the RC1 version that does not flip the textures? If I use:

it gives me RC2 which flips all my textures. If I use:

it gives me 1,0 which crashes with certain versions of the JRE. I would normally use the stable release version, but in this case it is not stable (I understand the problem is in the JRE and not JOGL, so I am not criticizing JOGL for this problem)

I have to deliver a webstart demo tomorrow, of the product we have been working on for the past year that is now effectively broken. It works with RC1 but I am not sure how to include that in webstart without a link to it. I can modify my code later, but this will take quite awhile (unless there is an easy fix that I am missing) .

Thanks,

Jeff

Please see the javadoc for Texture.getSubImageTexCoords(). We’ve tried to make it clear but I have to admit we don’t have any concrete examples in the jogl-demos workspace using this API, though the new TextureRenderer in the jogl workspace does use it. We do have a demo using getImageTexCoords() however. If you have pre-computed texture coordinates (typically ranging from 0 to 1) then what you need to do is for each one, multiply it by the width and height to get the texel x and y you’re talking about, and then feed that into getSubImageTexCoords(). You can feed in (0, 0) as the lower-left corner of the sub-image and only use the resulting TextureCoords’ right() and top() values for the rescaled coordinates.

Please use

Sorry for the last minute trouble.

Cool. Thanks Ken. The demo was a success.

Thanks for your help. I did not really understand exactly how the getSubImageTexCoords function worked from the javadoc, but your description above made everything click. I get it now.

Thanks for all your dedication and hard work. It is greatly appreciated.

Jeff

I still have a problem with this for cubemaps. ???

Koen

Could you please be more concrete and supply a test case showing what the problem is?

Are you sure you can’t solve this by putting in a matrix somewhere along the line which flips the space vertically, and swapping the top and bottom faces of the cubemap?

The problem was that uvw coordinates are used for cubemaps. I solved it for now by swapping the positive & negative faces of the entire cubemap (it was a procedural texture anyway so that doesn’t matter much).

Thx for the hint. :wink:

Koen

Would it be possible to change the method getSubImageTexCoords, so we can feed it with a TextureCoords object ?

For example :

TextureCoords loopTC = new TextureCoords();
while (moreUVsToProcess){
int p1x = …
int p1y = …
texture.getSubImageTexCoords(p1x,p1y,p1x,p1y,loopTC);
// write back the new texture coordinates
}

I can’t speak for Ken of course, but I can tell you that what you want goes against the advise given by various very knowledgeable people like to author of Effective Java.

Chapter 13 of Effective Java “Favor immutability” for example tells you to use value-objects wherever possible. It gives a bunch of advantages for using them, besides the most obvious disadvantages of course: the need to make a copy each time you need a different value.

The TextureCoords class does not adhere completely to the rules though because it’s methods are not final, to be a true immutable objects they should be. So somebody should probably decide which way to go: either go for full immutability or make it easily mutable by default.

I am aware of the advantages of Immutable objects.

However in this case, a lot of very temporary objects are created. In all cases the reference to the object will only exist inside the loop that transforms the textures coordinates.

An alternative solution would be to add a batch processing method like this :

calculateSubImageTexCoords(float[] uvs);
&
calculateSubImageTexCoords(FloatBuffer uvs);

Koen

I’m facing this problem in another context and I think I’m going to solve it by setting up a texture matrix. That would also save you from having to mutate your texture coordinates. Would that approach work better? You can compute the values that have to go into the texture matrix from the various parameters of the Texture object (look at the implementation of getSubImageTexCoords for pointers).

[quote]I’m facing this problem in another context and I think I’m going to solve it by setting up a texture matrix. That would also save you from having to mutate your texture coordinates. Would that approach work better? You can compute the values that have to go into the texture matrix from the various parameters of the Texture object (look at the implementation of getSubImageTexCoords for pointers).
[/quote]
A matrix would be the best solution (wish I thought of it :), it’s the simplest and cleanest solution.

Koen