OSDN Git Service

Added new ShapeRenderer.
authorStefan Bachmann <st.lebach@gmail.com>
Fri, 1 Feb 2013 04:59:33 +0000 (20:59 -0800)
committerStefan Bachmann <st.lebach@gmail.com>
Fri, 1 Feb 2013 04:59:33 +0000 (20:59 -0800)
gdx/src/com/badlogic/gdx/graphics/glutils/ShapeRenderer2.java [new file with mode: 0644]
tests/gdx-tests/src/com/badlogic/gdx/tests/ShapeRendererTest.java

diff --git a/gdx/src/com/badlogic/gdx/graphics/glutils/ShapeRenderer2.java b/gdx/src/com/badlogic/gdx/graphics/glutils/ShapeRenderer2.java
new file mode 100644 (file)
index 0000000..31ff833
--- /dev/null
@@ -0,0 +1,644 @@
+/*******************************************************************************
+ * Copyright 2011 See AUTHORS file.
+ * 
+ * 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.badlogic.gdx.graphics.glutils;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.Camera;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.GL10;
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
+import com.badlogic.gdx.math.MathUtils;
+import com.badlogic.gdx.math.Matrix4;
+import com.badlogic.gdx.utils.GdxRuntimeException;
+
+/** Renders points, lines, rectangles, filled rectangles and boxes.</p>
+ * 
+ * This class works with OpenGL ES 1.x and 2.0. In its base configuration a 2D orthographic projection with the origin in the
+ * lower left corner is used. Units are given in screen pixels.</p>
+ * 
+ * To change the projection properties use the {@link #setProjectionMatrix(Matrix4)} method. Usually the {@link Camera#combined}
+ * matrix is set via this method. If the screen orientation or resolution changes, the projection matrix might have to be adapted
+ * as well.</p>
+ * 
+ * Shapes are rendered in batches to increase performance. The standard use-pattern looks as follows:
+ * 
+ * <pre>
+ * {@code
+ * camera.update();
+ * shapeRenderer.setProjectionMatrix(camera.combined);
+ * 
+ * shapeRenderer.begin(ShapeType.Line);
+ * shapeRenderer.color(1, 1, 0, 1);
+ * shapeRenderer.line(x, y, x2, y2);
+ * shapeRenderer.line(x3, y3, x4, y4);
+ * shapeRenderer.end();
+ * 
+ * shapeRenderer.begin(ShapeType.Box);
+ * shapeRenderer.color(0, 1, 0, 1);
+ * shapeRenderer.box(x, y, z, width, height, depth);
+ * shapeRenderer.end();
+ * }
+ * </pre>
+ * 
+ * The class has a second matrix called the transformation matrix which is used to rotate, scale and translate shapes in a more
+ * flexible manner. This mechanism works much like matrix operations in OpenGL ES 1.x. The following example shows how to rotate a
+ * rectangle around its center using the z-axis as the rotation axis and placing it's center at (20, 12, 2):
+ * 
+ * <pre>
+ * shapeRenderer.begin(ShapeType.Rectangle);
+ * shapeRenderer.identity();
+ * shapeRenderer.translate(20, 12, 2);
+ * shapeRenderer.rotate(0, 0, 1, 90);
+ * shapeRenderer.rect(-width / 2, -height / 2, width, height);
+ * shapeRenderer.end();
+ * </pre>
+ * 
+ * Matrix operations all use postmultiplication and work just like glTranslate, glScale and glRotate. The last transformation
+ * specified will be the first that is applied to a shape (rotate then translate in the above example).
+ * 
+ * The projection and transformation matrices are a state of the ShapeRenderer, just like the color and will be applied to all
+ * shapes until they are changed.
+ * 
+ * @author mzechner, stbachmann */
+public class ShapeRenderer2 {
+       /** Shape types to be used with {@link #begin(ShapeType)}.
+        * @author mzechner, stbachmann */
+       public enum ShapeType {
+               Point(GL10.GL_POINTS),
+               Line(GL10.GL_LINES),
+               Filled(GL10.GL_TRIANGLES);
+
+               private final int glType;
+
+               ShapeType (int glType) {
+                       this.glType = glType;
+               }
+
+               public int getGlType () {
+                       return glType;
+               }
+       }
+       
+       ImmediateModeRenderer renderer;
+       boolean matrixDirty = false;
+       Matrix4 projView = new Matrix4();
+       Matrix4 transform = new Matrix4();
+       Matrix4 combined = new Matrix4();
+       Matrix4 tmp = new Matrix4();
+       Color color = new Color(1, 1, 1, 1);
+       ShapeType currType = null;
+
+       public ShapeRenderer2 () {
+               this(5000);
+       }
+
+       public ShapeRenderer2 (int maxVertices) {
+               if (Gdx.graphics.isGL20Available())
+                       renderer = new ImmediateModeRenderer20(maxVertices, false, true, 0);
+               else
+                       renderer = new ImmediateModeRenderer10(maxVertices);
+               projView.setToOrtho2D(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
+               matrixDirty = true;
+       }
+       
+       /** Sets the {@link Color} to be used by shapes.
+        * @param color */
+       public void setColor (Color color) {
+               this.color.set(color);
+       }
+
+       /** Sets the {@link Color} to be used by shapes.
+        * @param r
+        * @param g
+        * @param b
+        * @param a */
+       public void setColor (float r, float g, float b, float a) {
+               this.color.set(r, g, b, a);
+       }
+
+       /** Sets the projection matrix to be used for rendering. Usually this will be set to {@link Camera#combined}.
+        * @param matrix */
+       public void setProjectionMatrix (Matrix4 matrix) {
+               projView.set(matrix);
+               matrixDirty = true;
+       }
+
+       public void setTransformMatrix (Matrix4 matrix) {
+               transform.set(matrix);
+               matrixDirty = true;
+       }
+
+       /** Sets the transformation matrix to identity. */
+       public void identity () {
+               transform.idt();
+               matrixDirty = true;
+       }
+
+       /** Multiplies the current transformation matrix by a translation matrix.
+        * @param x
+        * @param y
+        * @param z */
+       public void translate (float x, float y, float z) {
+               transform.translate(x, y, z);
+               matrixDirty = true;
+       }
+
+       /** Multiplies the current transformation matrix by a rotation matrix.
+        * @param angle angle in degrees
+        * @param axisX
+        * @param axisY
+        * @param axisZ */
+       public void rotate (float axisX, float axisY, float axisZ, float angle) {
+               transform.rotate(axisX, axisY, axisZ, angle);
+               matrixDirty = true;
+       }
+
+       /** Multiplies the current transformation matrix by a scale matrix.
+        * @param scaleX
+        * @param scaleY
+        * @param scaleZ */
+       public void scale (float scaleX, float scaleY, float scaleZ) {
+               transform.scale(scaleX, scaleY, scaleZ);
+               matrixDirty = true;
+       }
+       
+       /** Starts a new batch of shapes. All shapes within the batch have to have the type specified. E.g. if {@link ShapeType#Point}
+        * is specified, only call #point().
+        * 
+        * The call to this method must be paired with a call to {@link #end()}.
+        * 
+        * In case OpenGL ES 1.x is used, the projection and modelview matrix will be modified.
+        * 
+        * @param type the {@link ShapeType}. */
+       public void begin (ShapeType type) {
+               if (currType != null) throw new GdxRuntimeException("Call end() before beginning a new shape batch");
+               currType = type;
+               if (matrixDirty) {
+                       combined.set(projView);
+                       Matrix4.mul(combined.val, transform.val);
+                       matrixDirty = false;
+               }
+               renderer.begin(combined, currType.getGlType());
+       }
+       
+       /** Draws a point. The {@link ShapeType} passed to begin has to be {@link ShapeType#Point}.
+        * @param x
+        * @param y
+        * @param z */
+       public void point(float x, float y, float z){
+               if (currType != ShapeType.Point) throw new GdxRuntimeException("Must call begin(ShapeType.Point)");
+               checkDirty();
+               checkFlush(1);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y, z);
+       }
+
+       /** Draws a line. The {@link ShapeType} passed to begin has to be {@link ShapeType#Line}.
+        * @param x
+        * @param y
+        * @param z
+        * @param x2
+        * @param y2
+        * @param z2 */
+       public void line(float x, float y, float z, float x2, float y2, float z2){
+               if (currType != ShapeType.Line) throw new GdxRuntimeException("Must call begin(ShapeType.Line)");
+               checkDirty();
+               checkFlush(2);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y, z);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x2, y2, z2);
+       }
+       
+       /** Draws a line in the x/y plane. The {@link ShapeType} passed to begin has to be {@link ShapeType#Line}.
+        * @param x
+        * @param y
+        * @param x2
+        * @param y2 */
+       public void line(float x, float y, float x2, float y2){
+               if (currType != ShapeType.Line) throw new GdxRuntimeException("Must call begin(ShapeType.Line)");
+               checkDirty();
+               checkFlush(2);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y, 0);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x2, y2, 0);
+       }
+       
+       public void curve(float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, int segments){
+               if (currType != ShapeType.Line) throw new GdxRuntimeException("Must call begin(ShapeType.Line)");
+               checkDirty();
+               checkFlush(segments * 2 + 2);
+
+               // Algorithm from: http://www.antigrain.com/research/bezier_interpolation/index.html#PAGE_BEZIER_INTERPOLATION
+               float subdiv_step = 1f / segments;
+               float subdiv_step2 = subdiv_step * subdiv_step;
+               float subdiv_step3 = subdiv_step * subdiv_step * subdiv_step;
+
+               float pre1 = 3 * subdiv_step;
+               float pre2 = 3 * subdiv_step2;
+               float pre4 = 6 * subdiv_step2;
+               float pre5 = 6 * subdiv_step3;
+
+               float tmp1x = x1 - cx1 * 2 + cx2;
+               float tmp1y = y1 - cy1 * 2 + cy2;
+
+               float tmp2x = (cx1 - cx2) * 3 - x1 + x2;
+               float tmp2y = (cy1 - cy2) * 3 - y1 + y2;
+
+               float fx = x1;
+               float fy = y1;
+
+               float dfx = (cx1 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3;
+               float dfy = (cy1 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3;
+
+               float ddfx = tmp1x * pre4 + tmp2x * pre5;
+               float ddfy = tmp1y * pre4 + tmp2y * pre5;
+
+               float dddfx = tmp2x * pre5;
+               float dddfy = tmp2y * pre5;
+
+               while (segments-- > 0) {
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(fx, fy, 0);
+                       fx += dfx;
+                       fy += dfy;
+                       dfx += ddfx;
+                       dfy += ddfy;
+                       ddfx += dddfx;
+                       ddfy += dddfy;
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(fx, fy, 0);
+               }
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(fx, fy, 0);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x2, y2, 0);
+       }
+       
+       public void triangle(float x1, float y1, float x2, float y2, float x3, float y3){
+               if (currType != ShapeType.Filled && currType != ShapeType.Line) 
+                       throw new GdxRuntimeException("Must call begin(ShapeType.Filled) or begin(ShapeType.Line)");
+               checkDirty();
+               checkFlush(6);
+               if(currType == ShapeType.Line){
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x1, y1, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x2, y2, 0);
+       
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x2, y2, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x3, y3, 0);
+       
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x3, y3, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x1, y1, 0);
+               }
+               else {
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x1, y1, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x2, y2, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x3, y3, 0);
+               }
+       }
+       
+       /** Draws a rectangle in the x/y plane. The x and y coordinate specify the bottom left corner of the rectangle. The
+        * {@link ShapeType} passed to begin has to be {@link ShapeType#Filled} or  {@link ShapeType#Line}.
+        * @param x
+        * @param y
+        * @param width
+        * @param height */
+       public void rect(float x, float y, float width, float height){
+               if (currType != ShapeType.Filled && currType != ShapeType.Line) 
+                       throw new GdxRuntimeException("Must call begin(ShapeType.Filled) or begin(ShapeType.Line)");
+               
+               checkDirty();
+               checkFlush(8);
+               
+               if(currType == ShapeType.Line){
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x, y, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x + width, y, 0);
+       
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x + width, y, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x + width, y + height, 0);
+       
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x + width, y + height, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x, y + height, 0);
+       
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x, y + height, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x, y, 0);
+               }
+               else {
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x, y, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x + width, y, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x + width, y + height, 0);
+
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x + width, y + height, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x, y + height, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x, y, 0);
+               }
+       }
+       
+       /** Draws a box. The x, y and z coordinate specify the bottom left front corner of the rectangle. The {@link ShapeType} passed
+        * to begin has to be {@link ShapeType#Line}.
+        * @param x
+        * @param y
+        * @param width
+        * @param height */
+       public void box(float x, float y, float z, float width, float height, float depth){
+               if (currType != ShapeType.Line) throw new GdxRuntimeException("Must call begin(ShapeType.Line)");
+               
+               checkDirty();
+               checkFlush(16);
+               
+               depth = -depth;
+               
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y, z);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + width, y, z);
+
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + width, y, z);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + width, y, z + depth);
+
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + width, y, z + depth);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y, z + depth);
+
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y, z + depth);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y, z);
+
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y, z);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y + height, z);
+
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y + height, z);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + width, y + height, z);
+
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + width, y + height, z);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + width, y + height, z + depth);
+
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + width, y + height, z + depth);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y + height, z + depth);
+
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y + height, z + depth);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y + height, z);
+
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + width, y, z);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + width, y + height, z);
+
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + width, y, z + depth);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + width, y + height, z + depth);
+
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y, z + depth);
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x, y + height, z + depth);
+       }
+       
+       /** Calls {@link #circle(float, float, float, int)} by estimating the number of segments needed for a smooth circle. */
+       public void circle (float x, float y, float radius) {
+               circle(x, y, radius, (int)(6 * (float)Math.cbrt(radius)));
+       }
+       
+       public void circle(float x, float y, float radius, int segments){
+               if (segments <= 0) throw new IllegalArgumentException("segments must be >= 0.");
+               if (currType != ShapeType.Filled && currType != ShapeType.Line) 
+                       throw new GdxRuntimeException("Must call begin(ShapeType.Filled) or begin(ShapeType.Line)");
+               checkDirty();
+               checkFlush(segments * 2 + 2);
+
+               float angle = 2 * 3.1415926f / segments;
+               float cos = MathUtils.cos(angle);
+               float sin = MathUtils.sin(angle);
+               float cx = radius, cy = 0;
+               if(currType == ShapeType.Line){
+                       for (int i = 0; i < segments; i++) {
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x + cx, y + cy, 0);
+                               float temp = cx;
+                               cx = cos * cx - sin * cy;
+                               cy = sin * temp + cos * cy;
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x + cx, y + cy, 0);
+                       }
+                       // Ensure the last segment is identical to the first.
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x + cx, y + cy, 0);
+               }
+               else {
+                       segments--;
+                       for (int i = 0; i < segments; i++) {
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x, y, 0);
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x + cx, y + cy, 0);
+                               float temp = cx;
+                               cx = cos * cx - sin * cy;
+                               cy = sin * temp + cos * cy;
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x + cx, y + cy, 0);
+                       }
+                       // Ensure the last segment is identical to the first.
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x, y, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x + cx, y + cy, 0);
+               }
+               
+               float temp = cx;
+               cx = radius;
+               cy = 0;
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + cx, y + cy, 0);
+       }
+       
+       /** Calls {@link #cone(float, float, float, float, float, int)} by estimating the number of segments needed for a smooth
+        * circular base. */
+       public void cone (float x, float y, float z, float radius, float height) {
+               cone(x, y, z, radius, height, (int)(4 * (float)Math.sqrt(radius)));
+       }
+       
+       public void cone(float x, float y, float z, float radius, float height, int segments){
+               if (segments <= 0) throw new IllegalArgumentException("segments must be >= 0.");
+               if (currType != ShapeType.Filled && currType != ShapeType.Line) 
+                       throw new GdxRuntimeException("Must call begin(ShapeType.Filled) or begin(ShapeType.Line)");
+               checkDirty();
+               checkFlush(segments * 4 + 2);
+               float angle = 2 * 3.1415926f / segments;
+               float cos = MathUtils.cos(angle);
+               float sin = MathUtils.sin(angle);
+               float cx = radius, cy = 0;
+               if(currType == ShapeType.Line){
+                       for (int i = 0; i < segments; i++) {
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x + cx, y + cy, z);
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x, y, z + height);
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x + cx, y + cy, z);
+                               float temp = cx;
+                               cx = cos * cx - sin * cy;
+                               cy = sin * temp + cos * cy;
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x + cx, y + cy, z);
+                       }
+                       // Ensure the last segment is identical to the first.
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x + cx, y + cy, z);
+               }
+               else {
+                       segments--;
+                       for (int i = 0; i < segments; i++) {
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x, y, z);
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x + cx, y + cy, z);
+                               float temp = cx;
+                               float temp2 = cy;
+                               cx = cos * cx - sin * cy;
+                               cy = sin * temp + cos * cy;
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x + cx, y + cy, z);
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x + temp, y + temp2, z);
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x + cx, y + cy, z);
+                               renderer.color(color.r, color.g, color.b, color.a);
+                               renderer.vertex(x, y, z + height);
+                       }
+                       // Ensure the last segment is identical to the first.
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x, y, z);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x + cx, y + cy, z);
+               }
+               cx = radius;
+               cy = 0;
+               renderer.color(color.r, color.g, color.b, color.a);
+               renderer.vertex(x + cx, y + cy, z);
+       }
+       
+       /** Draws a polygon in the x/y plane. The vertices must contain at least 3 points (6 floats x,y). The
+        * {@link ShapeType} passed to begin has to be {@link ShapeType#Line}.
+        * @param vertices */
+       public void polygon(float[] vertices){
+               if (currType != ShapeType.Line) throw new GdxRuntimeException("Must call begin(ShapeType.Line)");
+               if (vertices.length < 6) throw new IllegalArgumentException("Polygons must contain at least 3 points.");
+               if (vertices.length % 2 != 0) throw new IllegalArgumentException("Polygons must have a pair number of vertices.");
+               final int numFloats = vertices.length;
+               
+               checkDirty();
+               checkFlush(numFloats);
+               
+               float firstX = vertices[0];
+               float firstY = vertices[1];
+               
+               for (int i = 0; i < numFloats; i += 2) {
+                       float x1 = vertices[i];
+                       float y1 = vertices[i + 1];
+                       
+                       float x2;
+                       float y2;
+                       
+                       if(i + 2 >= numFloats){
+                               x2 = firstX;
+                               y2 = firstY;
+                       }else{
+                               x2 = vertices[i + 2];
+                               y2 = vertices[i + 3];
+                       }
+                       
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x1, y1, 0);
+                       renderer.color(color.r, color.g, color.b, color.a);
+                       renderer.vertex(x2, y2, 0);
+               }
+       }
+       
+       private void checkDirty () {
+               if (!matrixDirty) return;
+               ShapeType type = currType;
+               end();
+               begin(type);
+       }
+
+       private void checkFlush (int newVertices) {
+               if (renderer.getMaxVertices() - renderer.getNumVertices() >= newVertices) return;
+               ShapeType type = currType;
+               end();
+               begin(type);
+       }
+
+       /** Finishes the batch of shapes and ensures they get rendered. */
+       public void end () {
+               renderer.end();
+               currType = null;
+       }
+
+       public void flush () {
+               ShapeType type = currType;
+               end();
+               begin(type);
+       }
+       
+       /** Returns the current {@link ShapeType} used */
+       public ShapeType getCurrentType () {
+               return currType;
+       }
+
+       public void dispose () {
+               renderer.dispose();
+       }
+}
index af2a020..63c43e4 100644 (file)
 package com.badlogic.gdx.tests;\r
 \r
 import com.badlogic.gdx.Gdx;\r
+import com.badlogic.gdx.Input.Keys;\r
 import com.badlogic.gdx.graphics.Color;\r
 import com.badlogic.gdx.graphics.GL10;\r
 import com.badlogic.gdx.graphics.PerspectiveCamera;\r
 import com.badlogic.gdx.graphics.g2d.BitmapFont;\r
 import com.badlogic.gdx.graphics.g2d.SpriteBatch;\r
-import com.badlogic.gdx.graphics.glutils.ShapeRenderer;\r
-import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;\r
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer2;\r
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer2.ShapeType;\r
 import com.badlogic.gdx.math.MathUtils;\r
 import com.badlogic.gdx.tests.utils.GdxTest;\r
 import com.badlogic.gdx.tests.utils.PerspectiveCamController;\r
@@ -34,14 +35,14 @@ public class ShapeRendererTest extends GdxTest {
                return true;\r
        }\r
 \r
-       ShapeRenderer renderer;\r
+       ShapeRenderer2 renderer;\r
        PerspectiveCamera cam;\r
        PerspectiveCamController controller;\r
        SpriteBatch batch;\r
        BitmapFont font;\r
 \r
        public void create () {\r
-               renderer = new ShapeRenderer();\r
+               renderer = new ShapeRenderer2();\r
                cam = new PerspectiveCamera(47, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());\r
                cam.position.set(0, 0, 2);\r
                cam.near = 0.1f;\r
@@ -53,7 +54,7 @@ public class ShapeRendererTest extends GdxTest {
 \r
        public void render () {\r
                Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);\r
-               Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);\r
+\r
                cam.update();\r
                renderer.setProjectionMatrix(cam.combined);\r
                renderer.identity();\r
@@ -61,136 +62,59 @@ public class ShapeRendererTest extends GdxTest {
                renderer.translate(-0.5f, -0.5f, 0);\r
 \r
                MathUtils.random.setSeed(0);\r
-\r
-               renderer.begin(ShapeType.Line);\r
-               renderer.setColor(Color.GREEN);\r
-               for (int i = 0; i < 1000; i++) {\r
-                       renderer.line(MathUtils.random(), MathUtils.random(), MathUtils.random(), MathUtils.random());\r
-               }\r
-               renderer.end();\r
-\r
+               \r
                renderer.begin(ShapeType.Point);\r
-               renderer.setColor(Color.BLUE);\r
-               for (int i = 0; i < 1000; i++) {\r
-                       renderer.point(MathUtils.random(), MathUtils.random(), MathUtils.random());\r
-               }\r
+               \r
+               renderer.setColor(Color.PINK);\r
+               for(int i=0; i<100; i++)\r
+                       renderer.point(MathUtils.random(0.0f, 1.0f), MathUtils.random(0.0f, 1.0f), 0);\r
+               \r
                renderer.end();\r
 \r
-               renderer.begin(ShapeType.Rectangle);\r
-               renderer.setColor(Color.RED);\r
-               for (int i = 0; i < 20; i++) {\r
-                       float x = MathUtils.random();\r
-                       float y = MathUtils.random();\r
-                       float width = MathUtils.random();\r
-                       float height = MathUtils.random();\r
-                       renderer.identity();\r
-                       renderer.translate(-0.5f + x, -0.5f + y, MathUtils.random());\r
-                       renderer.translate(width / 2, height / 2, 0);\r
-                       renderer.rotate(0, 1, 0, MathUtils.random() * 360);\r
-                       renderer.translate(-width / 2, -height / 2, 0);\r
-                       renderer.rect(0, 0, width, height);\r
+               if(Gdx.input.isKeyPressed(Keys.F)){\r
+                       renderer.begin(ShapeType.Filled);\r
+                       \r
+                       renderer.setColor(Color.RED);\r
+                       renderer.rect(0, 0, 1, 1);\r
+                       \r
+                       renderer.setColor(Color.BLUE);\r
+                       renderer.circle(0.2f, 0.2f, 0.5f, 40);\r
+                       \r
+                       renderer.setColor(Color.GREEN);\r
+                       renderer.cone(0.6f, 0.6f, 0, 0.3f, 0.75f, 20);\r
+                       \r
+                       renderer.setColor(Color.MAGENTA);\r
+                       renderer.triangle(-0.1f, 0.1f, -0.6f, -0.1f, -0.3f, 0.5f);\r
+                       \r
+                       renderer.end();\r
                }\r
-               renderer.end();\r
-\r
-               renderer.begin(ShapeType.FilledRectangle);\r
-               renderer.setColor(Color.WHITE);\r
-               for (int i = 0; i < 20; i++) {\r
-                       float x = MathUtils.random();\r
-                       float y = MathUtils.random();\r
-                       float width = MathUtils.random();\r
-                       float height = MathUtils.random();\r
-                       renderer.identity();\r
-                       renderer.translate(-0.5f + x, -0.5f + y, -MathUtils.random());\r
-                       renderer.translate(width / 2, height / 2, 0);\r
-                       renderer.rotate(0, 1, 0, MathUtils.random() * 360);\r
-                       renderer.translate(-width / 2, -height / 2, 0);\r
-                       renderer.filledRect(0, 0, width, height);\r
-               }\r
-               renderer.end();\r
-\r
-               renderer.begin(ShapeType.Box);\r
-               renderer.setColor(1, 1, 0, 1);\r
-               for (int i = 0; i < 20; i++) {\r
-                       float x = MathUtils.random();\r
-                       float y = MathUtils.random();\r
-                       float width = MathUtils.random();\r
-                       float height = MathUtils.random();\r
-                       float depth = MathUtils.random();\r
-                       renderer.identity();\r
-                       renderer.translate(-1.5f + x, -0.5f + y, MathUtils.random());\r
-                       renderer.translate(width / 2, height / 2, depth / 2);\r
-                       renderer.rotate(0, 1, 0, MathUtils.random() * 360);\r
-                       renderer.translate(-width / 2, -height / 2, depth / 2);\r
-                       renderer.box(0, 0, 0, width, height, depth);\r
-               }\r
-               renderer.end();\r
-\r
-               renderer.begin(ShapeType.Circle);\r
-               renderer.setColor(1, 0, 1, 1);\r
-               renderer.identity();\r
-               for (int i = 0; i < 20; i++) {\r
-                       float x = MathUtils.random();\r
-                       float y = MathUtils.random();\r
-                       float radius = MathUtils.random();\r
-                       renderer.circle(x, y, radius, 40);\r
+               else {\r
+                       renderer.begin(ShapeType.Line);\r
+                       \r
+                       renderer.setColor(Color.RED);\r
+                       renderer.rect(0, 0, 1, 1);\r
+                       \r
+                       renderer.setColor(Color.BLUE);\r
+                       renderer.circle(0.2f, 0.2f, 0.5f, 40);\r
+                       \r
+                       renderer.setColor(Color.YELLOW);\r
+                       renderer.line(0, 0, 1, 1);\r
+                       \r
+                       renderer.setColor(Color.WHITE);\r
+                       renderer.box(0.1f, 0.1f, 0.1f, 0.3f, 0.25f, 0.1f);\r
+                       \r
+                       renderer.setColor(Color.GREEN);\r
+                       renderer.cone(0.6f, 0.6f, 0, 0.3f, 0.75f, 20);\r
+                       \r
+                       renderer.setColor(Color.MAGENTA);\r
+                       renderer.triangle(-0.1f, 0.1f, -0.6f, -0.1f, -0.3f, 0.5f);\r
+\r
+                       renderer.setColor(Color.CYAN);\r
+                       renderer.curve(0.0f, 0.25f, 0.2f, 0.3f, 0.3f, 0.6f, 0.1f, 0.5f, 30);\r
+                       \r
+                       renderer.end();\r
                }\r
-               renderer.end();\r
-\r
-               renderer.begin(ShapeType.FilledCircle);\r
-               renderer.setColor(0, 1, 1, 1);\r
-               renderer.identity();\r
-               renderer.rotate(0, 1, 0, 45);\r
-               for (int i = 0; i < 5; i++) {\r
-                       float x = MathUtils.random();\r
-                       float y = MathUtils.random();\r
-                       float width = MathUtils.random();\r
-                       float height = MathUtils.random();\r
-                       renderer.identity();\r
-                       renderer.translate(0.5f + x, -0.5f + y, -MathUtils.random());\r
-                       renderer.translate(width / 2, height / 2, 0);\r
-                       renderer.rotate(0, 1, 0, MathUtils.random() * 360);\r
-                       renderer.translate(-width / 2, -height / 2, 0);\r
-                       renderer.filledCircle(0, 0, width, 40);\r
-               }\r
-               renderer.end();\r
-\r
-               renderer.begin(ShapeType.Triangle);\r
-               renderer.setColor(0, 0, 1, 1);\r
-               renderer.identity();\r
-               renderer.rotate(0, 1, 0, 45);\r
-               for (int i = 0; i < 15; i++) {\r
-                       float x = MathUtils.random();\r
-                       float y = MathUtils.random();\r
-                       float width = MathUtils.random();\r
-                       float height = MathUtils.random();\r
-                       renderer.identity();\r
-                       renderer.translate(-0.5f + x, -0.5f + y, -MathUtils.random());\r
-                       renderer.translate(width / 2, height / 2, 0);\r
-                       renderer.rotate(0, 1, 0, MathUtils.random() * 360);\r
-                       renderer.translate(-width / 2, -height / 2, 0);\r
-                       renderer.triangle(0, 0, width, 0, 0, height);\r
-               }\r
-               renderer.end();\r
-\r
-               renderer.begin(ShapeType.FilledTriangle);\r
-               renderer.setColor(0, 0, 1, 1);\r
-               renderer.identity();\r
-               renderer.rotate(0, 1, 0, 45);\r
-               for (int i = 0; i < 15; i++) {\r
-                       float x = MathUtils.random();\r
-                       float y = MathUtils.random();\r
-                       float width = MathUtils.random();\r
-                       float height = MathUtils.random();\r
-                       renderer.identity();\r
-                       renderer.translate(0.5f + x, -0.5f + y, -MathUtils.random());\r
-                       renderer.translate(width / 2, height / 2, 0);\r
-                       renderer.rotate(0, 1, 0, MathUtils.random() * 360);\r
-                       renderer.translate(-width / 2, -height / 2, 0);\r
-                       renderer.filledTriangle(0, 0, width, 0, 0, height);\r
-               }\r
-               renderer.end();\r
-\r
-               Gdx.gl.glDisable(GL10.GL_DEPTH_TEST);\r
+               \r
                batch.begin();\r
                font.draw(batch, "fps: " + Gdx.graphics.getFramesPerSecond(), 0, 20);\r
                batch.end();\r