/******************************************************************************* * 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.tests; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.PolygonRegion; import com.badlogic.gdx.graphics.g2d.PolygonRegionLoader; import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.tests.utils.GdxTest; import com.badlogic.gdx.utils.Disposable; public class PolygonRegionTest extends GdxTest { PolygonSpriteBatch batch; PolygonRegionDebugRenderer debugRenderer; Texture texture; OrthographicCamera camera; PolygonRegion region; PolygonRegion region2; boolean usePolygonBatch = true; @Override public void create () { texture = new Texture(Gdx.files.internal("data/tree.png")); PolygonRegionLoader loader = new PolygonRegionLoader(); region = loader.load(new TextureRegion(texture), Gdx.files.internal("data/tree.psh")); // create a region from an arbitrary set of vertices (a triangle in this case) region2 = new PolygonRegion(new TextureRegion(texture), new float[] {0, 0, 100, 100, 0, 100}, new short[] {0, 1, 2}); camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); camera.position.x = 0; camera.position.y = 0; batch = new PolygonSpriteBatch(); debugRenderer = new PolygonRegionDebugRenderer(); Gdx.input.setInputProcessor(this); } @Override public void resize (int width, int height) { camera.viewportWidth = width; camera.viewportHeight = height; camera.update(); } @Override public void render () { Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); Gdx.gl.glClearColor(0.25f, 0.25f, 0.25f, 1.0f); camera.update(); batch.setProjectionMatrix(camera.combined); batch.begin(); // draw bot regions side-by-side float width = 256; float x = -width; batch.draw(region, x, -128, 256, 256); batch.draw(region2, x + width + 10, -128, 256, 256); batch.end(); debugRenderer.setProjectionMatrix(camera.combined); debugRenderer.draw(region, x, -128, 0, 0, 256, 256, 1, 1, 0); debugRenderer.draw(region2, x + width + 10, -128, 0, 0, 256, 256, 1, 1, 0); } @Override public void dispose () { debugRenderer.dispose(); texture.dispose(); batch.dispose(); } public class PolygonRegionDebugRenderer implements Disposable { ShapeRenderer renderer; public PolygonRegionDebugRenderer () { renderer = new ShapeRenderer(); } public void draw (PolygonRegion region, float x, float y, float originX, float originY, float width, float height, float scaleX, float scaleY, float rotation) { float[] vertices = region.getVertices(); short[] triangles = region.getTriangles(); float[] textureCoords = region.getTextureCoords(); // bottom left and top right corner points relative to origin final float worldOriginX = x + originX; final float worldOriginY = y + originY; float sX = width / region.getRegion().getRegionWidth(); float sY = height / region.getRegion().getRegionHeight(); float fx1, fx2, fx3, px1, px2, px3; float fy1, fy2, fy3, py1, py2, py3; final float cos = MathUtils.cosDeg(rotation); final float sin = MathUtils.sinDeg(rotation); renderer.setColor(Color.RED); renderer.begin(ShapeType.Line); for (int i = 0, n = triangles.length; i < n; i += 3) { int p1 = triangles[i] * 2; int p2 = triangles[i + 1] * 2; int p3 = triangles[i + 2] * 2; fx1 = vertices[p1] * sX; fy1 = vertices[p1 + 1] * sY; fx2 = vertices[p2] * sX; fy2 = vertices[p2 + 1] * sY; fx3 = vertices[p3] * sX; fy3 = vertices[p3 + 1] * sY; fx1 -= originX; fy1 -= originY; fx2 -= originX; fy2 -= originY; fx3 -= originX; fy3 -= originY; if (scaleX != 1 || scaleY != 1) { fx1 *= scaleX; fy1 *= scaleY; fx2 *= scaleX; fy2 *= scaleY; fx3 *= scaleX; fy3 *= scaleY; } px1 = cos * fx1 - sin * fy1; py1 = sin * fx1 + cos * fy1; px2 = cos * fx2 - sin * fy2; py2 = sin * fx2 + cos * fy2; px3 = cos * fx3 - sin * fy3; py3 = sin * fx3 + cos * fy3; px1 += worldOriginX; py1 += worldOriginY; px2 += worldOriginX; py2 += worldOriginY; px3 += worldOriginX; py3 += worldOriginY; renderer.line(px1, py1, px2, py2); renderer.line(px2, py2, px3, py3); renderer.line(px3, py3, px1, py1); } renderer.end(); renderer.setColor(Color.BLUE); renderer.begin(ShapeType.Filled); renderer.circle(worldOriginX, worldOriginY, 4); renderer.end(); // Calculate the bounding rect, is there a better way?! // bottom left and top right corner points relative to origin fx1 = -originX; fy1 = -originY; fx2 = width - originX; fy2 = height - originY; // scale if (scaleX != 1 || scaleY != 1) { fx1 *= scaleX; fy1 *= scaleY; fx2 *= scaleX; fy2 *= scaleY; } // construct corner points, start from top left and go counter clockwise final float p1x = fx1; final float p1y = fy1; final float p2x = fx1; final float p2y = fy2; final float p3x = fx2; final float p3y = fy2; final float p4x = fx2; final float p4y = fy1; float x1; float y1; float x2; float y2; float x3; float y3; float x4; float y4; // rotate if (rotation != 0) { x1 = cos * p1x - sin * p1y; y1 = sin * p1x + cos * p1y; x2 = cos * p2x - sin * p2y; y2 = sin * p2x + cos * p2y; x3 = cos * p3x - sin * p3y; y3 = sin * p3x + cos * p3y; x4 = x1 + (x3 - x2); y4 = y3 - (y2 - y1); } else { x1 = p1x; y1 = p1y; x2 = p2x; y2 = p2y; x3 = p3x; y3 = p3y; x4 = p4x; y4 = p4y; } x1 += worldOriginX; y1 += worldOriginY; x2 += worldOriginX; y2 += worldOriginY; x3 += worldOriginX; y3 += worldOriginY; x4 += worldOriginX; y4 += worldOriginY; // Draw the bounding rectangle renderer.setColor(Color.GREEN); renderer.begin(ShapeType.Line); renderer.line(x1, y1, x2, y2); renderer.line(x2, y2, x3, y3); renderer.line(x3, y3, x4, y4); renderer.line(x4, y4, x1, y1); renderer.end(); } public void setProjectionMatrix (Matrix4 matrix) { this.renderer.setProjectionMatrix(matrix); } @Override public void dispose () { renderer.dispose(); } } }