javaopengljogl

Jogl uv coordinates for tilesets


I am currently learning jogl so I can make my own 2d game. All the textures for the tiles are stored in a single large tileset. I tried to use Texture.getSubImageTexCoords() to draw a single tile, but the result was weird: weird result

I'm not sure exactly how to describe it, but the upper left triangle that makes up the quad is stretching in a very strange way. I want to display just a section of the tileset. I tried looking for something online but couldn't find anything.

here is my code:

public class TestSubImage {
    private GLU glu = new GLU();
    private GLCanvas mainCanvas;
    private Texture texture;
    private TextureCoords tc;

    class Listener implements GLEventListener {
        public void init(GLAutoDrawable drawable) {
            // Load texture
            try {
                texture = TextureIO.newTexture(TestSubImage.class.getResource("/images/sheet.png"), false, null);
                texture.setTexParameteri(drawable.getGL(), drawable.getGL().GL_TEXTURE_MAG_FILTER, drawable.getGL().GL_NEAREST);
                tc = texture.getSubImageTexCoords(0, 16, 16, 32); // sub texture coords
            } catch (IOException e) {
                e.printStackTrace();
            }

            // Set up
            drawable.getGL().glClearColor(0.3f, 0.3f, 0.3f, 0);
            glu = new GLU();
            glu.gluOrtho2D(0, 512, 512, 0);
        }

        public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {

        }

        public void dispose(GLAutoDrawable drawable) {
        }

        public void display(GLAutoDrawable drawable) {
            GL2 gl = drawable.getGL().getGL2();
            gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

            // where to draw the image
            int x = 100;
            int y = 100;
            int width = 200;
            int height = 200;

            gl.glColor3f(1, 1, 1);

            // Draw the image
            texture.enable(gl);
            texture.bind(gl);

            gl.glBegin(GL2.GL_QUADS);
            gl.glVertex2f(x, y);
            gl.glTexCoord2f(tc.left(), tc.bottom());
            gl.glVertex2f(x, y + height);
            gl.glTexCoord2f(tc.right(), tc.bottom());
            gl.glVertex2f(x + width, y + height);
            gl.glTexCoord2f(tc.right(), tc.top());
            gl.glVertex2f(x + width, y);
            gl.glTexCoord2f(tc.left(), tc.top());
            gl.glEnd();
            texture.disable(gl);
        }
    }

    private void run() {

        // Create window
        JFrame frame = new JFrame("Texture Coords Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Create profile and capabilities
        final GLProfile profile = GLProfile.get(GLProfile.GL2);
        GLCapabilities caps = new GLCapabilities(profile);

        // Now set up the main GLCanvas
        mainCanvas = new GLCanvas(caps);
        mainCanvas.addGLEventListener(new Listener());

        frame.getContentPane().add(mainCanvas);
        frame.setSize(512, 512);
        frame.setResizable(false);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        new TestSubImage().run();
    }
}

The tileset is here.


Solution

  • glTexCoord2f sets the texcoord for the next vertex. So, you are rendering one vertex with the default texcoord (whatever that is), and then you are rendering each vertex with the previous vertex's texcoord. And the last texcoord call does nothing. (Well, it probably hangs around as the current texcoord and gets used for the first vertex on the next frame)

    You need to call glTexCoord2f before glVertex2f.

    P.S. It works the same for glColor3f/4f, glNormal3f, etc.