package shader; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL20; import org.newdawn.slick.Color; import org.newdawn.slick.Renderable; import org.newdawn.slick.SlickException; import org.newdawn.slick.opengl.InternalTextureLoader; import org.newdawn.slick.opengl.Texture; /** * Class to support the concept of a single artifact being * comprised of multiple image resources.
* For example a colourmap, normalmap, diffusemap, and specularmap. * This is currently extremely buggy, and I don't know why some * things have to be the way the are. * @author Chronocide (Jeremy Klix) * * * All drawing is done starting from the top left vertex and * moving counter clockwise.
*/ //TODO Make interface feel a little more like the familiar Image class //TODO Determine a method of dealing with the case were textures //are not all the same size. For instance should textures be //stretched, tiled, clamped? //TODO Way of handling images larger then the supporting cards //max texture size ala Slicks BigImage class. //TODO Needs way more attention to documenting inheritance. //TODO Test using different numbers of textures. public class MultiTex implements Renderable{ private static int units = -1; /** The top left corner identifier */ public static final int TOP_LEFT = 0; /** The top right corner identifier */ public static final int BOTTOM_LEFT = 1; /** The bottom left corner identifier */ public static final int BOTTOM_RIGHT = 3; /** The bottom right corner identifier */ public static final int TOP_RIGHT = 2; private List textures; private int primaryTextureIndex = 0; //Width and height based off primary texture loaded private float imgWidth, imgHeight; //Primary texture width and height clamped between 0 and 1 private float texWidth, texHeight; private float[] normals = new float[]{0,0,1, 0,0,1, 0,0,1, 0,0,1}; private float[] colours = new float[]{1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1}; /** * Constructs a new MultiTex object using the textures * identified in textures.
* The index of the textures in the list will be the texture unit * that the texture is bound to.
* @param textures a list of paths to the textures to use. * @throws SlickException If textures.size() is greater * than the maximum number of texture units. */ public MultiTex(List textures)throws SlickException{ //Check how many texture units are supported if(units==-1){ units = GL11.glGetInteger(GL20.GL_MAX_TEXTURE_IMAGE_UNITS); System.out.println(units); } if(units < textures.size()){ throw new UnsupportedOperationException("You attempted to " + "create an artifact with " + textures.size() + " textures, but your environment only supports " + units + " texure image units."); } //Create texture list this.textures = new ArrayList(textures.size()); //Load textures into texture list. InternalTextureLoader itl = InternalTextureLoader.get(); for(int i = 0; i */ public void draw(float x, float y){ draw(x, y, x + imgWidth, y+imgHeight, 0, 0, imgWidth, imgHeight); } /** * Draw a section of this MultTex at a particular location and * scale on the screen.
* * This is the draw method that all other overloaded draw * methods eventually evoke.
* * @param x1 * @param y1 * @param x2 * @param y2 * @param sx1 * @param sy1 * @param sx2 * @param sy2 */ public void draw(float x1, float y1, float x2, float y2, float sx1, float sy1, float sx2, float sy2){ //Bind textures to their correct locations for(int i = 0; i < textures.size(); i++){ GL13.glActiveTexture(GL13.GL_TEXTURE0 + i); GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glBindTexture(GL11.GL_TEXTURE_2D, textures.get(i).getTextureID()); } GL11.glBegin(GL11.GL_QUADS); drawEmbedded(x1, y1, x2, y2, sx1, sy1, sx2, sy2); GL11.glEnd(); //Clean up texture setting to allow basic slick to operate correctly. for(int i = textures.size()-1; i>=0; i--){ GL13.glActiveTexture(GL13.GL_TEXTURE0+i); GL11.glDisable(GL11.GL_TEXTURE_2D); } GL11.glEnable(GL11.GL_TEXTURE_2D); } public void draw(float x1, float y1, float x2, float y2, float sx1, float sy1, float sx2, float sy2, Color c){ float[] bu = colours;//Save the colour state setColour(c); draw(x1, y1, x2, y2, sx1, sy1, sx2, sy2); colours = bu;//Restore the colour state } /** * Sets the colour of a given corner.
* Note that this will have an effect only if: the * fixed pixel pipeline is being used; or the applied shader * takes the vertex colour into account.
* @param corner * @param c */ public void setColour(int corner, Color c){ colours[corner*4 + 0] = c.r; colours[corner*4 + 1] = c.g; colours[corner*4 + 2] = c.b; colours[corner*4 + 3] = c.a; } /** * Sets the colour of all four corners.
* @param c */ public void setColour(Color c){ for(int i=0; i<4; i++){ setColour(i, c); } } private void drawEmbedded(float x1, float y1, float x2, float y2, float sx1, float sy1, float sx2, float sy2){ //TODO reduce code duplication need to produce sequence 0,1,3,2 //TOP LEFT for(int i=0; i