Advertisement
Guest User

Untitled

a guest
Mar 10th, 2012
215
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 15.21 KB | None | 0 0
  1.  
  2. import java.nio.FloatBuffer;
  3.  
  4. import org.lwjgl.BufferUtils;
  5. import org.lwjgl.opengl.GL11;
  6. import org.lwjgl.opengl.GLContext;
  7. import org.newdawn.slick.Color;
  8. import org.newdawn.slick.Image;
  9. import org.newdawn.slick.opengl.Texture;
  10. import org.newdawn.slick.util.FastTrig;
  11.  
  12. public class SpriteBatch {
  13.  
  14.     public static final int STRATEGY_VERTEX_ARRAYS = 2;
  15.     public static final int STRATEGY_VBO = 4;
  16.     public static final int STRATEGY_VBO_MAPPED = 8;
  17.     public static final int STRATEGY_SHADER = 16;
  18.     public static final int STRATEGY_BEST = 32; //tries to use shader, then VBO mapped
  19.     //something like new SpriteBatch(
  20.    
  21.     public static boolean isVBOSupported() {
  22.         return GLContext.getCapabilities().GL_ARB_vertex_buffer_object;
  23.     }
  24.    
  25.     public static final int ALIGN_LEFT = 0;
  26.     public static final int ALIGN_CENTER = 1;
  27.     public static final int ALIGN_RIGHT = 2;
  28.    
  29.     /**
  30.      * Whether to send the image data as GL_TRIANGLES
  31.      * or GL_QUADS. By default, GL_TRIANGLES is used.
  32.      *
  33.      * @param b true to use triangle rendering
  34.      */
  35.     public static void setUseTriangles(boolean b) {
  36.         mode = b ? GL11.GL_TRIANGLES : GL11.GL_QUADS;
  37.     }
  38.    
  39.     /**
  40.      * Returns whether to send the image data as GL_TRIANGLES
  41.      * or GL_QUADS. By default, GL_TRIANGLES is used.
  42.      *
  43.      * @return true if we are using triangle rendering
  44.      */
  45.     public static boolean isUseTriangles() {
  46.         return mode==GL11.GL_TRIANGLES;
  47.     }
  48.    
  49.     private static int mode = GL11.GL_TRIANGLES;
  50.     private final int TOLERANCE = 48; //we assume triangles is in use...
  51.    
  52.     private int idx = 0;
  53.     private Texture texture;
  54.     public int renderCalls = 0;
  55.    
  56.     private FloatBuffer vertices, colors, texcoords;
  57.     private int maxVerts;
  58.     private Color currentColor = Color.white;
  59.    
  60.     private int vboID = 0;
  61.    
  62.     public SpriteBatch() {
  63.         this(1000);
  64.     }
  65.    
  66.     public SpriteBatch(int size) {
  67.         if (size<=0)
  68.             throw new IllegalArgumentException("batch size must be larger than 0");
  69.         this.maxVerts = size;
  70.         int len = size * 8;
  71.         vertices = BufferUtils.createFloatBuffer(len);
  72.         colors = BufferUtils.createFloatBuffer(len);
  73.         texcoords = BufferUtils.createFloatBuffer(len);
  74.         GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
  75.         GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
  76.         GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
  77. //        
  78. //        if (strategy==STRATEGY_VBO) {
  79. //          if (!isVBOSupported())
  80. //              throw new UnsupportedOperationException("trying to use VBO with SpriteBatch when it's not supported");
  81. //          vboID = GL15.glGenBuffers();
  82. //         
  83. //          GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
  84. //          GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);
  85. //          GL15.
  86. //        }
  87.        
  88.     }
  89.    
  90.    
  91.     /**
  92.      * Returns the size of this ImageBatch as given in construction (default 1000).
  93.      * The internal array will have a capacity of size * 8.
  94.      *
  95.      * A large internal array will require less calls to render(), but will take up
  96.      * more memory.
  97.      * For example, an ImageBatch with a size of 6 would be ideal if we are only
  98.      * rendering a single image (made up of tris) within begin/end
  99.      * (six vertices, 8 bytes per vertex -- 2 for XY, 2 for texture UV, 4 for RGBA).
  100.      *
  101.      * However, it's usually better to create a single large-size ImageBatch instance
  102.      * and re-use it throughout your game.
  103.      *
  104.      * @return how many vertices to expect
  105.      */
  106.     public int getSize() {
  107.         return maxVerts;
  108.     }
  109.    
  110.     public void setColor(Color color) {
  111.         this.currentColor = color;
  112.     }
  113.    
  114.     public Color getColor() {
  115.         return currentColor;
  116.     }
  117.    
  118.     public void flush() {
  119.         if (idx>0)
  120.             render();
  121.         idx = 0;
  122.         texture = null;
  123.         vertices.clear();
  124.         texcoords.clear();
  125.         colors.clear();
  126.     }
  127.    
  128.     /**
  129.      * Sends vertex, color and UV data to the GPU.
  130.      */
  131.     protected void render() {
  132.         if (idx==0)
  133.             return;
  134.         renderCalls++;
  135.         //bind the last texture
  136.         if (texture!=null)
  137.             texture.bind();
  138.         vertices.flip();
  139.         colors.flip();
  140.         texcoords.flip();
  141.        
  142.         GL11.glVertexPointer(2, 0, vertices);    
  143.         GL11.glColorPointer(4, 0, colors);    
  144.         GL11.glTexCoordPointer(2, 0, texcoords);    
  145.        
  146.         GL11.glDrawArrays(mode, 0, idx);
  147.         vertices.clear();
  148.         colors.clear();
  149.         texcoords.clear();
  150.         idx = 0;
  151.     }
  152. // 
  153. //  public void drawText(SpriteFont defaultFont, StyledText text, float x, float y) {
  154. //      SpriteFont.Glyph lastDef = null;
  155. //      SpriteFont lastFont = null;
  156. //      Color old = currentColor;
  157. //     
  158. //      float maxLineHeight = defaultFont.getLineHeight();
  159. //      float minY = text.getGroupCount()>0 ? Integer.MAX_VALUE : 0;
  160. //      float maxBaseline = 0;
  161. //      for (int gc=0; gc<text.getGroupCount(); gc++) {
  162. //          StyledText.Group g = text.getGroup(gc);
  163. //          if (g.getFont()!=null) {
  164. //              maxLineHeight = Math.max(maxLineHeight, g.getFont().getLineHeight());
  165. //              minY = Math.min(minY, g.getYOffset());
  166. //              maxBaseline = Math.max(maxBaseline, g.getFont().getAscent());
  167. //          } else {
  168. //              minY = Math.min(minY, defaultFont.getYOffset(g.getText()));
  169. //              maxBaseline = Math.max(maxBaseline, defaultFont.getAscent());
  170. //          }
  171. //         
  172. //      }
  173. //     
  174. //      for (int gc=0; gc<text.getGroupCount(); gc++) {
  175. //          StyledText.Group g = text.getGroup(gc);
  176. //          SpriteFont newFont = g.getFont()!=null ? g.getFont() : defaultFont;
  177. //          Color newColor = g.getColor()!=null ? g.getColor() : old;
  178. //          CharSequence newStr = g.getText();
  179. //          //TODO: clean up this method
  180. //          float minYOff = g.getFont()==null ? defaultFont.getYOffset(newStr) : g.getYOffset();
  181. //          float height = g.getFont()==null ? defaultFont.getHeight(newStr) : g.getHeight();
  182. //          float baseline = g.getFont()==null ? defaultFont.getAscent() : g.getFont().getAscent();
  183. //          float descent = g.getFont()==null ? defaultFont.getDescent() : g.getFont().getDescent();
  184. //          float yoff = maxBaseline - baseline;
  185. //         
  186. //          if (newFont!=lastFont) { //reset the last glyph
  187. //              lastDef = null;
  188. //          }
  189. //         
  190. //          for (int i=0; i<newStr.length(); i++) {
  191. //              char c = newStr.charAt(i);
  192. //              SpriteFont.Glyph def = newFont.getGlyph(c);
  193. //              if (def==null)
  194. //                  continue;
  195. //              if (lastDef!=null)
  196. //                  x += lastDef.getKerning(c);
  197. //              lastDef = def;
  198. //              setColor(newColor);
  199. //              drawImage(def.image, x + def.xoffset, y + def.yoffset + yoff - minY);
  200. //              x += def.xadvance;
  201. //          }
  202. //      }
  203. //      setColor(old);
  204. //  }
  205.    
  206.     private void drawTextImpl(SpriteFont font, CharSequence text, float x, float y,
  207.             int startIndex, int endIndex, boolean multiLine) {
  208.         SpriteFont.Glyph lastDef = null;
  209.        
  210.         float startX = x;
  211.         for (; startIndex < endIndex; startIndex++) {
  212.             char c = text.charAt(startIndex);
  213.             if (multiLine && c=='\n') {
  214.                 y += font.getLineHeight();
  215.                 x = startX;
  216.             }
  217.             SpriteFont.Glyph def = font.getGlyph(c);
  218.             if (def==null)
  219.                 continue;
  220.             if (lastDef!=null)
  221.                 x += lastDef.getKerning(c);
  222.             lastDef = def;
  223.             drawImage(def.image, x + def.xoffset, y + def.yoffset);
  224.             x += def.xadvance;
  225.         }
  226.     }
  227.    
  228.     public void drawTextMultiLine(SpriteFont font, CharSequence text, float x, float y) {
  229.         drawTextImpl(font, text, x, y, 0, text.length(), true);
  230.     }
  231.    
  232.     public void drawTextMultiLine(SpriteFont font, CharSequence text,
  233.             float x, float y, int startIndex, int endIndex) {
  234.         drawTextImpl(font, text, x, y, startIndex, endIndex, true);
  235.     }
  236.    
  237.     public void drawText(SpriteFont font, CharSequence text, float x, float y) {
  238.         drawTextImpl(font, text, x, y, 0, text.length(), false);
  239.     }
  240.    
  241.     public void drawText(SpriteFont font, CharSequence text, float x, float y, int startIndex, int endIndex) {
  242.         drawTextImpl(font, text, x, y, startIndex, endIndex, false);
  243.     }
  244.    
  245.     public void drawImageScaled(Image image, float x, float y, float scale) {
  246.         drawImage(image, x, y, image.getWidth()*scale, image.getHeight()*scale);
  247.     }
  248.    
  249.     public void drawImage(Image image) {
  250.         drawImage(image, 0, 0);
  251.     }
  252.    
  253.     public void drawImage(Image image, float x, float y) {
  254.         drawImage(image, x, y, null);
  255.     }
  256.  
  257.     public void drawImage(Image image, float x, float y, Color[] corners) {
  258.         drawImage(image, x, y, image.getWidth(), image.getHeight(), corners);
  259.     }
  260.    
  261.     public void drawImage(Image image, float x, float y, float w, float h) {
  262.         drawImage(image, x, y, w, h, null);
  263.     }
  264.  
  265.     public void drawImage(Image image, float x, float y, float rotation) {
  266.         drawImage(image, x, y, rotation, image.getWidth(), image.getHeight(), null);
  267.     }
  268.    
  269.     public void drawImage(Image image, float x, float y, float rotation, float w, float h, Color[] corners) {
  270.         if (rotation==0) {
  271.             drawImage(image, x, y, w, h, corners);
  272.             return;
  273.         }
  274.        
  275.         checkRender(image);
  276.        
  277.         float scaleX = w/image.getWidth();
  278.         float scaleY = h/image.getHeight();
  279.        
  280.         float cx = image.getCenterOfRotationX()*scaleX;
  281.         float cy = image.getCenterOfRotationY()*scaleY;
  282.  
  283.         float p1x = -cx;
  284.         float p1y = -cy;
  285.         float p2x = w - cx;
  286.         float p2y = -cy;
  287.         float p3x = w - cx;
  288.         float p3y = h - cy;
  289.         float p4x = -cx;
  290.         float p4y = h - cy;
  291.  
  292.         double rad = Math.toRadians(rotation);
  293.         final float cos = (float) FastTrig.cos(rad);
  294.         final float sin = (float) FastTrig.sin(rad);
  295.  
  296.         float tx = image.getTextureOffsetX();
  297.         float ty = image.getTextureOffsetY();
  298.         float tw = image.getTextureWidth();
  299.         float th = image.getTextureHeight();
  300.  
  301.         float x1 = (cos * p1x - sin * p1y) + cx; // TOP LEFT
  302.         float y1 = (sin * p1x + cos * p1y) + cy;
  303.         float x2 = (cos * p2x - sin * p2y) + cx; // TOP RIGHT
  304.         float y2 = (sin * p2x + cos * p2y) + cy;
  305.         float x3 = (cos * p3x - sin * p3y) + cx; // BOTTOM RIGHT
  306.         float y3 = (sin * p3x + cos * p3y) + cy;
  307.         float x4 = (cos * p4x - sin * p4y) + cx; // BOTTOM LEFT
  308.         float y4 = (sin * p4x + cos * p4y) + cy;
  309.         drawQuadElement(x+x1, y+y1, tx, ty, corners!=null ? corners[0] : null,
  310.                         x+x2, y+y2, tx+tw, ty, corners!=null ? corners[1] : null,
  311.                         x+x3, y+y3, tx+tw, ty+th, corners!=null ? corners[2] : null,
  312.                         x+x4, y+y4, tx, ty+th, corners!=null ? corners[3] : null);
  313.     }
  314.    
  315.     public void drawImage(Image image, float x, float y, float w, float h, Color[] corners) {
  316.         checkRender(image);
  317.         float tx = image.getTextureOffsetX();
  318.         float ty = image.getTextureOffsetY();
  319.         float tw = image.getTextureWidth();
  320.         float th = image.getTextureHeight();
  321.         drawImage(image, x, y, w, h, tx, ty, tw, th, corners);
  322. //      drawQuadElement(x, y, tx, ty, corners!=null ? corners[0] : null,
  323. //                      x+w, y, tx+tw, ty, corners!=null ? corners[1] : null,
  324. //                      x+w, y+h, tx+tw, ty+th, corners!=null ? corners[2] : null,
  325. //                      x, y+h, tx, ty+th, corners!=null ? corners[3] : null);
  326.     }
  327.  
  328.     public void drawSubImage(Image image, float srcx, float srcy,
  329.             float srcwidth, float srcheight, float x, float y) {
  330.         drawSubImage(image, srcx, srcy, srcwidth, srcheight, x, y, srcwidth, srcheight);
  331.     }
  332.    
  333.     public void drawSubImage(Image image, float srcx, float srcy,
  334.             float srcwidth, float srcheight, float x, float y, float w, float h) {
  335.         drawSubImage(image, srcx, srcy, srcwidth, srcheight, x, y, w, h, null);
  336.     }
  337.  
  338.     public void drawSubImage(Image image, float srcx, float srcy,
  339.             float srcwidth, float srcheight, float x, float y, float w,
  340.             float h, Color[] corners) {
  341.         checkRender(image);
  342.  
  343.         float iw = image.getWidth();
  344.         float ih = image.getHeight();
  345.         float tx = (srcx / iw * image.getTextureWidth()) + image.getTextureOffsetX();
  346.         float ty = (srcy / ih * image.getTextureHeight()) + image.getTextureOffsetY();
  347.         float tw = w / iw * image.getTextureWidth();
  348.         float th = h / ih * image.getTextureHeight();
  349.         drawQuadElement(x, y, tx, ty, corners != null ? corners[0] : null, x
  350.                 + w, y, tx + tw, ty, corners != null ? corners[1] : null,
  351.                 x + w, y + h, tx + tw, ty + th, corners != null ? corners[2]
  352.                         : null, x, y + h, tx, ty + th,
  353.                 corners != null ? corners[3] : null);
  354.     }
  355.    
  356.     public void drawImage(Image image, float x, float y, float width, float height,
  357.                     float u, float v, float uWidth, float vHeight, Color[] corners) {
  358.         checkRender(image);
  359.         drawQuadElement(x, y, u, v, corners!=null ? corners[0] : null,
  360.                         x+width, y, u+uWidth, v, corners!=null ? corners[1] : null,
  361.                         x+width, y+height, u+uWidth, v+vHeight, corners!=null ? corners[2] : null,
  362.                         x, y+height, u, v+vHeight, corners!=null ? corners[3] : null);
  363.     }
  364.    
  365.     /**
  366.      *
  367.      * @param image
  368.      * @param x
  369.      * @param y
  370.      * @param points
  371.      * @param texcoords a texcoord for each vertex (8 elements
  372.      * @param offset
  373.      * @param corners
  374.      */
  375.     public void drawImage(Image image, float x, float y, float[] points,
  376.             float[] texcoords, int offset, int texcoordsOffset, Color[] corners) {
  377.         checkRender(image);
  378.        
  379.         float x1 = points[offset++];
  380.         float y1 = points[offset++];
  381.         float x2 = points[offset++];
  382.         float y2 = points[offset++];
  383.         float x3 = points[offset++];
  384.         float y3 = points[offset++];
  385.         float x4 = points[offset++];
  386.         float y4 = points[offset++];
  387.        
  388.         float u1 = texcoords[texcoordsOffset++];
  389.         float v1 = texcoords[texcoordsOffset++];
  390.         float u2 = texcoords[texcoordsOffset++];
  391.         float v2 = texcoords[texcoordsOffset++];
  392.         float u3 = texcoords[texcoordsOffset++];
  393.         float v3 = texcoords[texcoordsOffset++];
  394.         float u4 = texcoords[texcoordsOffset++];
  395.         float v4 = texcoords[texcoordsOffset++];
  396.         drawQuadElement(x+x1, y+y1, u1, v1, corners!=null ? corners[0] : null,
  397.                         x+x2, y+y2, u2, v2, corners!=null ? corners[1] : null,
  398.                         x+x3, y+y3, u3, v3, corners!=null ? corners[2] : null,
  399.                         x+x4, y+y4, u4, v4, corners!=null ? corners[3] : null);
  400.     }
  401.    
  402.     private void checkRender(Image image) {
  403.         if (image==null || image.getTexture()==null)
  404.             throw new NullPointerException("null texture");
  405.        
  406.         //we need to bind a different texture. this is
  407.         //for convenience; ideally the user should order
  408.         //their rendering wisely to minimize texture binds 
  409.         if (image.getTexture()!=texture) {
  410.             //apply the last texture
  411.             render();
  412.             texture = image.getTexture();
  413.         } else if (idx >= maxVerts - TOLERANCE)
  414.             render();
  415.     }
  416.    
  417.     /**
  418.      * Specifies vertex data.
  419.      *
  420.      * @param x the x position
  421.      * @param y the y position
  422.      * @param u the U texcoord
  423.      * @param v the V texcoord
  424.      * @param color the color for this vertex
  425.      */
  426.     protected void vertex(float x, float y, float u, float v, Color color) {
  427.         vertices.put(x);
  428.         vertices.put(y);
  429.         texcoords.put(u);
  430.         texcoords.put(v);
  431.         Color c = color!=null ? color : currentColor;
  432.         colors.put(c.r);
  433.         colors.put(c.g);
  434.         colors.put(c.b);
  435.         colors.put(c.a);
  436.         idx++;
  437.     }
  438.    
  439.     /**
  440.      * Draws a quad-like element using either GL_QUADS or GL_TRIANGLES, depending
  441.      * on this batch's configuration.
  442.      */
  443.     protected void drawQuadElement(
  444.                         float x1, float y1, float u1, float v1, Color c1,   //TOP LEFT
  445.                         float x2, float y2, float u2, float v2, Color c2,   //TOP RIGHT
  446.                         float x3, float y3, float u3, float v3, Color c3,   //BOTTOM RIGHT
  447.                         float x4, float y4, float u4, float v4, Color c4) { //BOTTOM LEFT
  448.         if (mode == GL11.GL_TRIANGLES) {
  449.             //top left, top right, bottom left
  450.             vertex(x1, y1, u1, v1, c1);
  451.             vertex(x2, y2, u2, v2, c2);
  452.             vertex(x4, y4, u4, v4, c4);
  453.             //top right, bottom right, bottom left
  454.             vertex(x2, y2, u2, v2, c2);
  455.             vertex(x3, y3, u3, v3, c3);
  456.             vertex(x4, y4, u4, v4, c4);
  457.         } else {
  458.             //quads: top left, top right, bottom right, bottom left
  459.             vertex(x1, y1, u1, v1, c1);
  460.             vertex(x2, y2, u2, v2, c2);
  461.             vertex(x3, y3, u3, v3, c3);
  462.             vertex(x4, y4, u4, v4, c4);
  463.         }
  464.     }
  465. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement