com.telinc1.rpjg.texture.Texture.java Source code

Java tutorial

Introduction

Here is the source code for com.telinc1.rpjg.texture.Texture.java

Source

/*
 * Copyright 2015-2016 Telinc1
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.telinc1.rpjg.texture;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.ByteBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.newdawn.slick.opengl.PNGDecoder;
import org.pmw.tinylog.Logger;

import com.telinc1.rpjg.util.DrawingUtils;

/**
 * Defines an OpenGL 1.1 compatible texture.
 * 
 * @author Telinc1, davedes
 */
public class Texture {
    public static int DEFAULT_FILTER = GL11.GL_NEAREST;
    public static int DEFAULT_WRAP = GL11.GL_REPEAT;

    protected int id;
    protected int width;
    protected int height;

    /**
     * @see com.telinc1.rpjg.texture.Texture#Texture(int, int, int, int, int)
     */
    protected Texture(int width, int height) {
        this(width, height, Texture.DEFAULT_FILTER);
    }

    /**
     * @see com.telinc1.rpjg.texture.Texture#Texture(int, int, int, int, int)
     */
    protected Texture(int width, int height, int filter) {
        this(width, height, filter, Texture.DEFAULT_WRAP);
    }

    /**
     * @see com.telinc1.rpjg.texture.Texture#Texture(int, int, int, int, int)
     */
    protected Texture(int width, int height, int filter, int wrap) {
        this(width, height, filter, filter, wrap);
    }

    /**
     * Creates a blank (transparent black) texture with the given width and height.
     * 
     * @param width The width of the texture to generate
     * @param height The height of the texture to generate
     * @param minFilter The minification filter to use
     * @param magFilter The magnification filter to use
     * @param wrap The wrap mode for the texture.
     */
    protected Texture(int width, int height, int minFilter, int magFilter, int wrap) {
        GL11.glEnable(this.getTarget());
        this.setID(GL11.glGenTextures());

        this.setWidth(width);
        this.setHeight(height);

        this.bind();
        this.setFilter(minFilter, magFilter);
        this.setWrap(wrap);

        ByteBuffer buffer = BufferUtils.createByteBuffer(this.getWidth() * this.getHeight() * 4);
        this.upload(GL11.GL_RGBA, buffer);
    }

    /**
     * @see com.telinc1.rpjg.texture.Texture.Texture(java.net.URL, int, int, int)
     */
    protected Texture(URL image) {
        this(image, Texture.DEFAULT_FILTER);
    }

    /**
     * @see com.telinc1.rpjg.texture.Texture.Texture(java.net.URL, int, int, int)
     */
    protected Texture(URL image, int filter) {
        this(image, filter, Texture.DEFAULT_WRAP);
    }

    /**
     * @see com.telinc1.rpjg.texture.Texture.Texture(java.net.URL, int, int, int)
     */
    protected Texture(URL image, int filter, int wrap) {
        this(image, filter, filter, wrap);
    }

    /**
     * Creates a texture out of the given URL.
     * 
     * @param image - The location of the image to use.
     * @param minFilter - The minification filter to use.
     * @param magFilter - The magnification filter to use.
     * @param wrap - The wrap mode to use.
     */
    protected Texture(URL image, int minFilter, int magFilter, int wrap) {
        InputStream input = null;

        try {
            input = image.openStream();
            PNGDecoder decoder = new PNGDecoder(input);

            this.setWidth(decoder.getWidth());
            this.setHeight(decoder.getHeight());

            ByteBuffer buffer = BufferUtils.createByteBuffer(this.getWidth() * this.getHeight() * 4);
            decoder.decode(buffer, this.getWidth() * 4, PNGDecoder.RGBA);
            buffer.flip();

            GL11.glEnable(this.getTarget());
            this.setID(GL11.glGenTextures());

            this.bind();
            this.setFilter(minFilter, magFilter);
            this.setWrap(wrap);
            this.upload(GL11.GL_RGBA, buffer);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void bind() {
        if (!this.exists()) {
            throw new TextureException("Tried to load a nonexistent (destroyed) texture.");
        }

        DrawingUtils.bindTexture(this);
    }

    public void dispose() {
        if (this.exists()) {
            Logger.info("Destroying texture {}.", this.getID());

            GL11.glDeleteTextures(this.getID());
            this.setID(0);
        }
    }

    public boolean exists() {
        return this.getID() != 0;
    }

    public int getHeight() {
        return this.height;
    }

    public int getID() {
        return this.id;
    }

    public int getTarget() {
        return GL11.GL_TEXTURE_2D;
    }

    public int getWidth() {
        return this.width;
    }

    public void setFilter(int filter) {
        this.setFilter(filter, filter);
    }

    public void setFilter(int minFilter, int magFilter) {
        this.bind();
        GL11.glTexParameteri(this.getTarget(), GL11.GL_TEXTURE_MIN_FILTER, minFilter);
        GL11.glTexParameteri(this.getTarget(), GL11.GL_TEXTURE_MAG_FILTER, magFilter);
    }

    void setHeight(int height) {
        this.height = height;
    }

    void setID(int id) {
        this.id = id;
    }

    protected void setUnpackAlignment() {
        GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
        GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1);
    }

    void setWidth(int width) {
        this.width = width;
    }

    public void setWrap(int wrap) {
        this.setWrap(wrap, wrap);
    }

    public void setWrap(int sWrap, int tWrap) {
        this.bind();
        GL11.glTexParameteri(this.getTarget(), GL11.GL_TEXTURE_WRAP_S, tWrap);
        GL11.glTexParameteri(this.getTarget(), GL11.GL_TEXTURE_WRAP_T, tWrap);
    }

    /**
     * Uploads the given image data to the texture.
     * 
     * @param format - The byte order to use.
     * @param data - The image data to upload.
     */
    public void upload(int format, ByteBuffer data) {
        this.bind();
        this.setUnpackAlignment();
        GL11.glTexImage2D(this.getTarget(), 0, GL11.GL_RGBA, this.getWidth(), this.getHeight(), 0, format,
                GL11.GL_UNSIGNED_BYTE, data);
    }

    /**
     * Positions an image on top of the texture.
     * 
     * @param x - The X position at which to place the subimage.
     * @param y - The Y position at which to place the subimage.
     * @param width - The width of the subimage.
     * @param height - The height of the subimage.
     * @param format - The byte order of the subimage.
     * @param data - The data to upload.
     */
    public void upload(int x, int y, int width, int height, int format, ByteBuffer data) {
        this.bind();
        this.setUnpackAlignment();
        GL11.glTexSubImage2D(this.getTarget(), 0, x, y, width, height, format, GL11.GL_UNSIGNED_BYTE, data);
    }
}