OSDN Git Service

added Bresenham for 2D
authorbadlogic <badlogicgames@gmail.com>
Sat, 13 Jul 2013 11:14:00 +0000 (13:14 +0200)
committerbadlogic <badlogicgames@gmail.com>
Sat, 13 Jul 2013 11:14:00 +0000 (13:14 +0200)
gdx/src/com/badlogic/gdx.gwt.xml
gdx/src/com/badlogic/gdx/math/Bresenham2.java [new file with mode: 0644]
tests/gdx-tests-lwjgl/src/com/badlogic/gdx/tests/lwjgl/LwjglDebugStarter.java
tests/gdx-tests/src/com/badlogic/gdx/tests/Bresenham2Test.java [new file with mode: 0644]
tests/gdx-tests/src/com/badlogic/gdx/tests/g3d/voxel/VoxelTest.java
tests/gdx-tests/src/com/badlogic/gdx/tests/g3d/voxel/VoxelWorld.java
tests/gdx-tests/src/com/badlogic/gdx/tests/utils/GdxTests.java

index 27aa350..d6bd316 100644 (file)
        
        <!-- math -->
                <include name="math/Bezier.java"/>
+               <include name="math/Bresenham2.java"/>
                <include name="math/BSpline.java"/>
                <include name="math/CatmullRomSpline.java"/>
                <include name="math/Circle.java"/>
diff --git a/gdx/src/com/badlogic/gdx/math/Bresenham2.java b/gdx/src/com/badlogic/gdx/math/Bresenham2.java
new file mode 100644 (file)
index 0000000..17da5a3
--- /dev/null
@@ -0,0 +1,106 @@
+package com.badlogic.gdx.math;
+
+import com.badlogic.gdx.utils.Array;
+import com.badlogic.gdx.utils.Pool;
+
+/**
+ * Returns a list of {@link Vector2} instances at integer coordinates for
+ * a line in 2D, using the Bresenham algorithm.<p>
+ * 
+ * Instances of this class own the returned array of vectors and the vectors
+ * themselves to avoid garbage collection as much as possible. Calling
+ * {@link #line(Vector2, Vector2)} or {@link #line(float, float, float, float)} will
+ * result in the reuse of the previously returned array and vectors. 
+ * @author badlogic
+ *
+ */
+public class Bresenham2 {
+       private final Array<Vector2> points = new Array<Vector2>();
+       private final Pool<Vector2> pool = new Pool<Vector2>() {
+               @Override
+               protected Vector2 newObject () {
+                       return new Vector2();
+               }
+       };
+       
+       /**
+        * Returns a list of {@link Vector2} instances along the given line, at integer coordinates.
+        * The input coordinates are cast to integers using a floor operation.
+        * @param start the start of the line
+        * @param end the end of the line
+        * @return the list of points on the line at integer coordinates
+        */
+       public Array<Vector2> line(Vector2 start, Vector2 end) {
+               return line(start.x, start.y, end.y, end.y);
+       }
+       
+       /**
+        * Returns a list of {@link Vector2} instances along the given line, at integer coordinates.
+        * The input coordinates are cast to integers using a floor operation.
+        * @param startX the start x coordinate of the line
+        * @param startY the start y coordinate of the line
+        * @param endX the end x coordinate of the line
+        * @param endY the end y coordinate of the line
+        * @return the list of points on the line at integer coordinates
+        */
+       public Array<Vector2> line(float startX, float startY, float endX, float endY) {
+               pool.freeAll(points);
+               points.clear();
+               line(startX, startY, endX, endY, pool, points);
+               return points;
+       }
+       
+       /**
+        * Returns a list of {@link Vector2} instances along the given line, at integer coordinates.
+        * The input coordinates are cast to integers using a floor operation.
+        * @param startX the start x coordinate of the line
+        * @param startY the start y coordinate of the line
+        * @param endX the end x coordinate of the line
+        * @param endY the end y coordinate of the line
+        * @param pool the pool from which Vector2 instances are fetched
+        * @param output the output array, will be cleared in this method
+        * @return the list of points on the line at integer coordinates
+        */
+       public Array<Vector2> line(float startX, float startY, float endX, float endY, Pool<Vector2> pool, Array<Vector2> output) {
+               int x1 = (int)startX;
+               int y1 = (int)startY;
+               int x2 = (int)endX;
+               int y2 = (int)endY;
+               
+               int w = x2 - x1;
+               int h = y2 - y1;
+               int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0;
+               if(w < 0) {
+                       dx1 = -1;
+                       dx2 = -1;
+               } else if(w > 0) {
+                       dx1 = 1;
+                       dx2 = 1;
+               }
+               if(h < 0) dy1 = -1; else if(h > 0) dy1 = 1;
+               int longest = Math.abs(w);
+               int shortest = Math.abs(h);
+               if(longest <= shortest) {
+                       longest = Math.abs(h);
+                       shortest = Math.abs(w);
+                       if(h < 0) dy2 = -1; else if(h > 0) dy2 = 1;
+                       dx2 = 0;
+               }
+               int numerator = longest >> 1;
+               for(int i = 0; i <= longest; i++) {
+                       Vector2 point = pool.obtain();
+                       point.set(x1, y1);
+                       output.add(point);
+                       numerator += shortest;
+                       if(numerator > longest) {
+                               numerator -= longest;
+                               x1 += dx1;
+                               y1 += dy1;
+                       } else {
+                               x1 += dx2;
+                               y1 += dy2;
+                       }
+               }
+               return output;
+       }
+}
index a17189c..83cff2a 100644 (file)
@@ -26,6 +26,7 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
 import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;\r
 import com.badlogic.gdx.math.Vector2;\r
 import com.badlogic.gdx.scenes.scene2d.Stage;\r
+import com.badlogic.gdx.tests.Bresenham2Test;\r
 import com.badlogic.gdx.tests.MeshShaderTest;\r
 import com.badlogic.gdx.tests.TimerTest;\r
 import com.badlogic.gdx.tests.g3d.Basic3DSceneTest;\r
@@ -44,7 +45,7 @@ public class LwjglDebugStarter {
 //             new SharedLibraryLoader("../../extensions/gdx-controllers/gdx-controllers-desktop/libs/gdx-controllers-desktop-natives.jar").load("gdx-controllers-desktop");\r
 //             new SharedLibraryLoader("../../gdx/libs/gdx-natives.jar").load("gdx");\r
 \r
-               GdxTest test = new VoxelTest();\r
+               GdxTest test = new Bresenham2Test();\r
                LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();\r
                config.useGL20 = test.needsGL20();\r
                config.width = 1024;\r
diff --git a/tests/gdx-tests/src/com/badlogic/gdx/tests/Bresenham2Test.java b/tests/gdx-tests/src/com/badlogic/gdx/tests/Bresenham2Test.java
new file mode 100644 (file)
index 0000000..f18c613
--- /dev/null
@@ -0,0 +1,40 @@
+package com.badlogic.gdx.tests;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.Pixmap;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.Pixmap.Format;
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.badlogic.gdx.math.Bresenham2;
+import com.badlogic.gdx.math.Vector2;
+import com.badlogic.gdx.tests.utils.GdxTest;
+
+public class Bresenham2Test extends GdxTest {
+       SpriteBatch batch;
+       Texture result;
+       
+       @Override
+       public void create () {
+               Pixmap pixmap = new Pixmap(512, 512, Format.RGBA8888);
+               pixmap.setColor(Color.WHITE);
+               
+               Bresenham2 bresenham = new Bresenham2();
+               for(Vector2 point: bresenham.line(0, 0, 512, 512)) pixmap.drawPixel((int)point.x, (int)point.y);
+               for(Vector2 point: bresenham.line(512, 0, 0, 512)) pixmap.drawPixel((int)point.x, (int)point.y);
+               for(Vector2 point: bresenham.line(0, 0, 512, 256)) pixmap.drawPixel((int)point.x, (int)point.y);
+               for(Vector2 point: bresenham.line(512, 0, 0, 256)) pixmap.drawPixel((int)point.x, (int)point.y);
+               
+               result = new Texture(pixmap);
+               batch = new SpriteBatch();
+       }
+
+       @Override
+       public void render () {
+               Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+               batch.begin();
+               batch.draw(result, 0, 0);
+               batch.end();
+       }
+}
index 91e30f7..1df0a0e 100644 (file)
@@ -46,7 +46,7 @@ public class VoxelTest extends GdxTest {
                DefaultShader.defaultCullFace = GL20.GL_FRONT;
                GLES10Shader.defaultCullFace = GL20.GL_FRONT;
                camera = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
-               camera.near = 1;
+               camera.near = 0.5f;
                camera.far = 1000;
                controller = new FirstPersonCameraController(camera);
                Gdx.input.setInputProcessor(controller);
@@ -59,12 +59,11 @@ public class VoxelTest extends GdxTest {
                TextureRegion[][] tiles = TextureRegion.split(texture, 32, 32);
                
                MathUtils.random.setSeed(0);
-               voxelWorld = new VoxelWorld(tiles[0], 10, 4, 10);
+               voxelWorld = new VoxelWorld(tiles[0], 20, 4, 20);
                PerlinNoiseGenerator.generateVoxels(voxelWorld, 0, 63, 10);
-//             voxelWorld.setCube(0, 0, 0, 16, 16, 16, (byte)1);
                float camX = voxelWorld.voxelsX / 2f;
                float camZ = voxelWorld.voxelsZ / 2f;
-               float camY = voxelWorld.getHighest(camX, camZ);
+               float camY = voxelWorld.getHighest(camX, camZ) + 1.5f;
                camera.position.set(camX, camY, camZ);
        }
 
@@ -78,7 +77,7 @@ public class VoxelTest extends GdxTest {
                controller.update();
                
                spriteBatch.begin();
-               font.draw(spriteBatch, "fps: " + Gdx.graphics.getFramesPerSecond(), 0, 20);
+               font.draw(spriteBatch, "fps: " + Gdx.graphics.getFramesPerSecond() + ", #visible chunks: " + voxelWorld.renderedChunks + "/" + voxelWorld.numChunks, 0, 20);
                spriteBatch.end();
        }
        
index cc47ab6..ecd9926 100644 (file)
@@ -31,6 +31,8 @@ public class VoxelWorld implements RenderableProvider {
        public final int voxelsX;
        public final int voxelsY;
        public final int voxelsZ;
+       public int renderedChunks;
+       public int numChunks;
        private final TextureRegion[] tiles;
        
        public VoxelWorld(TextureRegion[] tiles, int chunksX, int chunksY, int chunksZ) {
@@ -39,6 +41,7 @@ public class VoxelWorld implements RenderableProvider {
                this.chunksX = chunksX;
                this.chunksY = chunksY;
                this.chunksZ = chunksZ;
+               this.numChunks = chunksX * chunksY * chunksZ;
                this.voxelsX = chunksX * CHUNK_SIZE_X;
                this.voxelsY = chunksY * CHUNK_SIZE_Y;
                this.voxelsZ = chunksZ * CHUNK_SIZE_Z;
@@ -160,6 +163,7 @@ public class VoxelWorld implements RenderableProvider {
        
        @Override
        public void getRenderables (Array<Renderable> renderables, Pool<Renderable> pool) {
+               renderedChunks = 0;
                for(int i = 0; i < chunks.length; i++) {
                        VoxelChunk chunk = chunks[i];
                        Mesh mesh = meshes[i];
@@ -169,6 +173,7 @@ public class VoxelWorld implements RenderableProvider {
                                mesh.setVertices(vertices, 0, numVerts * VoxelChunk.VERTEX_SIZE);
                                dirty[i] = false;
                        }
+                       if(numVertices[i] == 0) continue;
                        Renderable renderable = pool.obtain();
                        renderable.material = materials[i];
                        renderable.mesh = mesh;
@@ -176,6 +181,7 @@ public class VoxelWorld implements RenderableProvider {
                        renderable.meshPartSize = numVertices[i];
                        renderable.primitiveType = GL20.GL_TRIANGLES;
                        renderables.add(renderable);
+                       renderedChunks++;
                }
        }
 }
index 6743b1d..0ac4332 100644 (file)
@@ -86,7 +86,7 @@ public class GdxTests {
                ExternalMusicTest.class, SoftKeyboardTest.class, DirtyRenderingTest.class, YDownTest.class,\r
                ScreenCaptureTest.class, BitmapFontTest.class, LabelScaleTest.class, GamepadTest.class, NetAPITest.class, TideMapAssetManagerTest.class, TideMapDirectLoaderTest.class, TiledMapAssetManagerTest.class, TiledMapBench.class,\r
                RunnablePostTest.class, Vector2dTest.class, SuperKoalio.class, NinePatchTest.class, Basic3DSceneTest.class, Animation3DTest.class,\r
-               ModelTest.class, Basic3DTest.class, ShaderTest.class, SkeletonTest.class, HexagonalTiledMapTest.class, FogTest.class, TimerTest.class));\r
+               ModelTest.class, Basic3DTest.class, ShaderTest.class, SkeletonTest.class, HexagonalTiledMapTest.class, FogTest.class, TimerTest.class, Bresenham2Test.class));\r
        \r
        public static List<String> getNames () {\r
                List<String> names = new ArrayList<String>(tests.size());\r