UV Mapping: Where do the (u, v) coordinates correspond to on a square texture?

Started by
4 comments, last by tom_mai78101 11 years, 10 months ago
pzy98.png

In the above picture shown, I have a square texture of nontrivial size. Each number labeled 0 through 3 in blue represents each corner of the texture. The purple texture coordinates, labeled A through D, is given with it's texture coordinates, designated as (u, v).

Where do the purple labels A, B, C, and D corresponds to on the texture?

This is to understand the following:
1. The direction I'm mapping from (either clockwise, or counter-clockwise).
2. How the texture is mapped into the model view, either clockwise or counter-clockwise.
3. Why texture coordinates must come in pairs.
4. Why texture coordinates do not necessarily follow the basic principles of (x, y) when the texture is just a 2D texture.

Thanks in advance.
Advertisement
0 = A
1 = C
2 = B
3 = D

at least in my implementations is does :)

see "u" as the x coordinate from left to right
and "v" as the y coordinate from top to bottom
0 = A, would be the Direct3D-way of mapping the upper-left coordinate. OpenGL has coordinates inverted along the v-axis (B).

The best way to understand the relation between objectspace-vertices and their uv counterparts, is to recreate the above quad in a 3d modeling app and see how the textured quad reacts to changes (rotating, mirroring etc.) in the uv-map.
I tried recreating them on my Android phone, with all glFrontFace() set to ClockWise, I still couldn't get why UV never flips when I intentionally flip the texture coordinates around.

I flipped A and C around, I get a front facing flipped texture.
I flipped A and B around, and I get a front facing flipped texture.
I flipped C and D, kept A and B from above, and I get a front facing normal texture.

Confused, confused, confused...

Source:


package test.es;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
public class Square {
public float angle = 0f;
private ByteBuffer indicesBuffer;
private FloatBuffer textureBuffer;
private FloatBuffer vertexBuffer;
private int[] textures = new int[1];
private float[] vertices = {
-2f, -2f, 0f, //Bottom left
2f, -2f, 0f, //bottom right
-2f, 2f, 0f, //Top left
2f, 2f, 0f //Top right
};
private float[] textureCoords = { //You move these rows up/down to flip textures here.
1f, 1f,
0f, 1f,
1f, 0f,
0f, 0f
};
private byte[] indices = {
0,1,2,
2,1,3
};
public Square(){
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4); //sizeof(float) = 4
byteBuffer.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuffer.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);

byteBuffer = ByteBuffer.allocateDirect(textureCoords.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(textureCoords);
textureBuffer.position(0);

indicesBuffer = ByteBuffer.allocateDirect(indices.length);
indicesBuffer.put(indices);
indicesBuffer.position(0);
}

public void draw(GL10 gl){
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glFrontFace(GL10.GL_CW);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//gl.glColor4f(0.1f, 0.4f, 0.9f, 1.0f);
//gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE, indicesBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
angle -= 0.2f;
}

public void loadTexture(GL10 gl, Context c){
InputStream input = c.getResources().openRawResource(R.drawable.ic_launcher);
Bitmap bitmap = null;
try{
bitmap = BitmapFactory.decodeStream(input);
}
finally {
try {
input.close();
input = null;
}
catch(IOException e) {
e.printStackTrace();
}
}
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
}
Keep in mind that because you've set the FrontFace state to

"GL10


.[color=#000000]GL_CW", you're actually viewing triangles from the backside (as you've assigned indices in counterclockwise order).

So, does indices in Direct3D and OpenGL follow differently on a 2D Cartesian coordinates (where positive X is upwards, and positive Y is rightwards)?

As in:

For indices 0 through 3, by following the above picture texture coordinates, the index for (u, v) = (0, 0) is 0, the index for (u, v) = (1, 0) is 1, the index for (u, v) = (0, 1) is 2, and the index for (u, v) = (1, 1) is 3?

Hope I didn't confuse you too much.

This topic is closed to new replies.

Advertisement