TextureAtlas.java 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. package me.hammerle.snuviengine.api;
  2. import java.awt.image.BufferedImage;
  3. import java.io.File;
  4. import java.io.IOException;
  5. import java.nio.IntBuffer;
  6. import javax.imageio.ImageIO;
  7. import org.lwjgl.BufferUtils;
  8. import static org.lwjgl.opengl.GL11.*;
  9. import static org.lwjgl.opengl.GL12.*;
  10. import static org.lwjgl.opengl.GL13.*;
  11. public class TextureAtlas
  12. {
  13. private static final Texture NULL_TEXTURE = new Texture(0.0f, 0.0f, 0.0f, 0.0f);
  14. private static class Texture
  15. {
  16. private final float minX;
  17. private final float minY;
  18. private final float maxX;
  19. private final float maxY;
  20. private Texture(float minX, float minY, float maxX, float maxY)
  21. {
  22. this.minX = minX;
  23. this.minY = minY;
  24. this.maxX = maxX;
  25. this.maxY = maxY;
  26. }
  27. }
  28. private final int tileWidth;
  29. private final int tileHeight;
  30. private final int width;
  31. private final int height;
  32. private Texture[] textures;
  33. private int textureIndex = 0;
  34. private final int[][] data;
  35. private int texture = -1;
  36. private boolean generated = false;
  37. protected TextureAtlas(int tileWidth, int tileHeight, int width, int height)
  38. {
  39. this.tileWidth = tileWidth;
  40. this.tileHeight = tileHeight;
  41. this.width = width * tileWidth;
  42. this.height = height * tileHeight;
  43. textures = new Texture[width * height];
  44. for(int i = 0; i < textures.length; i++)
  45. {
  46. textures[i] = NULL_TEXTURE;
  47. }
  48. data = new int[this.width][this.height];
  49. for(int x = 0; x < this.width; x++)
  50. {
  51. for(int y = 0; y < this.height; y++)
  52. {
  53. data[x][y] = 0xFF0000FF;
  54. }
  55. }
  56. }
  57. protected void generateTexture()
  58. {
  59. if(generated)
  60. {
  61. throw new TextureException("the texture is already generated");
  62. }
  63. generated = true;
  64. texture = glGenTextures();
  65. glBindTexture(GL_TEXTURE_2D, texture);
  66. IntBuffer buffer = BufferUtils.createIntBuffer(width * height);
  67. for(int y = 0; y < height; y++)
  68. {
  69. for(int x = 0; x < width; x++)
  70. {
  71. buffer.put(data[x][y]);
  72. }
  73. }
  74. buffer.flip();
  75. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, buffer);
  76. }
  77. protected void bindTexture()
  78. {
  79. glActiveTexture(GL_TEXTURE0);
  80. glBindTexture(GL_TEXTURE_2D, texture);
  81. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  82. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  83. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  84. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  85. }
  86. private int convertColor(int c)
  87. {
  88. return (c << 8) | ((c >> 24) & 0xFF);
  89. }
  90. public int addTexture(String path)
  91. {
  92. if(generated)
  93. {
  94. throw new TextureException("cannot add a texture to an already generated texture atlas");
  95. }
  96. else if(textureIndex == textures.length)
  97. {
  98. throw new TextureException("the texture atlas is full");
  99. }
  100. BufferedImage image;
  101. try
  102. {
  103. image = ImageIO.read(new File(path));
  104. }
  105. catch(IOException | IllegalArgumentException ex)
  106. {
  107. throw new TextureException("cannot add texture '" + path + "'");
  108. }
  109. if(image.getWidth() != tileWidth || image.getHeight() != tileHeight)
  110. {
  111. throw new TextureException("size of '" + path + "' is " + image.getWidth() + "x" + image.getHeight() + ", expected is " + tileWidth + "x" + tileHeight);
  112. }
  113. int x = (textureIndex % width) * tileWidth;
  114. int y = (textureIndex / height) * tileHeight;
  115. textures[textureIndex] = new Texture(((float) x) / width, ((float) y) / height, ((float) (x + tileWidth)) / width, ((float) (y + tileHeight)) / height);
  116. textureIndex++;
  117. for(int ix = 0; ix < image.getWidth(); ix++)
  118. {
  119. for(int iy = 0; iy < image.getHeight(); iy++)
  120. {
  121. data[ix + x][iy + y] = convertColor(image.getRGB(ix, image.getHeight() - iy - 1));
  122. }
  123. }
  124. return textureIndex - 1;
  125. }
  126. protected float getTextureMinX(int index, boolean hFlip)
  127. {
  128. if(hFlip)
  129. {
  130. return textures[index].maxX;
  131. }
  132. return textures[index].minX;
  133. }
  134. protected float getTextureMaxX(int index, boolean hFlip)
  135. {
  136. if(hFlip)
  137. {
  138. return textures[index].minX;
  139. }
  140. return textures[index].maxX;
  141. }
  142. protected float getTextureMinY(int index, boolean vFlip)
  143. {
  144. if(vFlip)
  145. {
  146. return textures[index].maxY;
  147. }
  148. return textures[index].minY;
  149. }
  150. protected float getTextureMaxY(int index, boolean vFlip)
  151. {
  152. if(vFlip)
  153. {
  154. return textures[index].minY;
  155. }
  156. return textures[index].maxY;
  157. }
  158. }