diff --git a/src/org/andengine/entity/primitive/Ellipse.java b/src/org/andengine/entity/primitive/Ellipse.java new file mode 100644 index 000000000..4849bb9c3 --- /dev/null +++ b/src/org/andengine/entity/primitive/Ellipse.java @@ -0,0 +1,113 @@ +package org.andengine.entity.primitive; + +import org.andengine.opengl.vbo.VertexBufferObject.DrawType; +import org.andengine.opengl.vbo.VertexBufferObjectManager; +import org.andengine.opengl.vbo.attribute.VertexBufferObjectAttribute; + +/** + * + * @author Rodrigo Castro + * @since 16:47:01 - 31.01.2012 + */ +public class Ellipse extends PolyLine { + // =========================================================== + // Constants + // =========================================================== + + static final int LOW_RESOLUTION = 15; + static final int MEDIUM_RESOLUTION = 30; + static final int HIGH_RESOLUTION = 50; + static final int DEFAULT_RESOLUTION = HIGH_RESOLUTION; + + // =========================================================== + // Fields + // =========================================================== + + protected final int mResolution; + + // =========================================================== + // Constructors + // =========================================================== + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public Ellipse(final float pX, final float pY, final float pRadiusA, final float pRadiusB, final VertexBufferObjectManager pVertexBufferObjectManager) { + this(pX, pY, pRadiusA, pRadiusB, Line.LINE_WIDTH_DEFAULT, pVertexBufferObjectManager); + } + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public Ellipse(final float pX, final float pY, final float pRadiusA, final float pRadiusB, final float pLineWidth, final VertexBufferObjectManager pVertexBufferObjectManager) { + this(pX, pY, pRadiusA, pRadiusB, pLineWidth, DEFAULT_RESOLUTION, pVertexBufferObjectManager); + } + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public Ellipse(final float pX, final float pY, final float pRadiusA, final float pRadiusB, final float pLineWidth, final int pResolution, final VertexBufferObjectManager pVertexBufferObjectManager) { + this(pX, pY, pRadiusA, pRadiusB, pLineWidth, pResolution, pVertexBufferObjectManager, DrawMode.LINE_LOOP); + } + + public Ellipse(final float pX, final float pY, final float pRadiusA, final float pRadiusB, final float pLineWidth, final int pResolution, final VertexBufferObjectManager pVertexBufferObjectManager, DrawMode pDrawMode) { + this(pX, pY, pRadiusA, pRadiusB, pLineWidth, pResolution, pVertexBufferObjectManager, pDrawMode, DrawType.STATIC); + } + + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} with the {@link VertexBufferObjectAttribute}s: {@link Rectangle#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public Ellipse(final float pX, final float pY, final float pRadiusA, final float pRadiusB, final float pLineWidth, final int pResolution, final VertexBufferObjectManager pVertexBufferObjectManager, DrawMode pDrawMode, final DrawType pDrawType) { + super(pX, pY, buildEllipseVertices(pRadiusA, pRadiusB, pResolution), pLineWidth, pVertexBufferObjectManager, pDrawMode, pDrawType); + + mResolution = pResolution; + } + + // =========================================================== + // Getter & Setter + // =========================================================== + + /** + * + * @param pRadiusA + * @param pRadiusB + * @return true if vertices were correctly updated + * false otherwise + */ + /* + public boolean setRadius( float pRadiusA, float pRadiusB ) + { + return this.updateVertices(buildEllipseVertices(pRadiusA, pRadiusB, mResolution)); + } + */ + + // =========================================================== + // Methods for/from SuperClass/Interfaces + // =========================================================== + + // =========================================================== + // Methods + // =========================================================== + + private static float[] buildEllipseVertices(float pRadiusA, float pRadiusB, int pResolution) { + + float[] vertices = new float[VERTEX_SIZE * pResolution]; + + for( int i = 0; i < pResolution; i++) + { + double theta = 2. * Math.PI * (double)i / (double) pResolution; + float x = (float) ( (double)pRadiusA * Math.cos( theta )); + float y = (float) ( (double)pRadiusB * Math.sin( theta )); + + vertices[(i * Mesh.VERTEX_SIZE) + Mesh.VERTEX_INDEX_X] = x; + vertices[(i * Mesh.VERTEX_SIZE) + Mesh.VERTEX_INDEX_Y] = y; + } + + return vertices; + } + + // =========================================================== + // Inner and Anonymous Classes + // =========================================================== +} \ No newline at end of file diff --git a/src/org/andengine/entity/primitive/Mesh.java b/src/org/andengine/entity/primitive/Mesh.java index aa74b1ee6..c40b100bc 100644 --- a/src/org/andengine/entity/primitive/Mesh.java +++ b/src/org/andengine/entity/primitive/Mesh.java @@ -1,11 +1,15 @@ package org.andengine.entity.primitive; +import java.security.spec.MGF1ParameterSpec; + import org.andengine.engine.camera.Camera; import org.andengine.entity.shape.IShape; import org.andengine.entity.shape.RectangularShape; import org.andengine.entity.shape.Shape; +import org.andengine.entity.sprite.Sprite; import org.andengine.opengl.shader.PositionColorShaderProgram; import org.andengine.opengl.shader.constants.ShaderProgramConstants; +import org.andengine.opengl.texture.region.ITextureRegion; import org.andengine.opengl.util.GLState; import org.andengine.opengl.vbo.HighPerformanceVertexBufferObject; import org.andengine.opengl.vbo.IVertexBufferObject; @@ -47,10 +51,20 @@ public class Mesh extends Shape { protected final IMeshVertexBufferObject mMeshVertexBufferObject; private int mVertexCountToDraw; private int mDrawMode; + protected ITextureRegion mTextureRegion; // =========================================================== // Constructors // =========================================================== + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public Mesh(final float pX, final float pY, final float[] pBufferData, final int pVertexCount, final DrawMode pDrawMode, final ITextureRegion pTextureRegion, final VertexBufferObjectManager pVertexBufferObjectManager) { + this(pX, pY, pBufferData, pVertexCount, pDrawMode, pVertexBufferObjectManager, DrawType.STATIC); + mTextureRegion = pTextureRegion; + this.onUpdateTextureCoordinates(); + } /** * Uses a default {@link HighPerformanceMeshVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. @@ -65,6 +79,13 @@ public Mesh(final float pX, final float pY, final float[] pBufferData, final int public Mesh(final float pX, final float pY, final float[] pBufferData, final int pVertexCount, final DrawMode pDrawMode, final VertexBufferObjectManager pVertexBufferObjectManager, final DrawType pDrawType) { this(pX, pY, pVertexCount, pDrawMode, new HighPerformanceMeshVertexBufferObject(pVertexBufferObjectManager, pBufferData, pVertexCount, pDrawType, true, Mesh.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT)); } + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public Mesh(final float pX, final float pY, final float[] pVertexX, final float[] pVertexY, final DrawMode pDrawMode, final VertexBufferObjectManager pVertexBufferObjectManager, final DrawType pDrawType) { + this(pX, pY, pVertexX.length, pDrawMode, new HighPerformanceMeshVertexBufferObject(pVertexBufferObjectManager, buildVertexList(pVertexX, pVertexY), pVertexX.length, pDrawType, true, Mesh.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT)); + } public Mesh(final float pX, final float pY, final int pVertexCount, final DrawMode pDrawMode, final IMeshVertexBufferObject pMeshVertexBufferObject) { super(pX, pY, PositionColorShaderProgram.getInstance()); @@ -93,6 +114,10 @@ public void setVertexCountToDraw(final int pVertexCountToDraw) { public void setDrawMode(final DrawMode pDrawMode) { this.mDrawMode = pDrawMode.mDrawMode; } + + public ITextureRegion getTextureRegion() { + return this.mTextureRegion; + } // =========================================================== // Methods for/from SuperClass/Interfaces @@ -106,7 +131,11 @@ public IMeshVertexBufferObject getVertexBufferObject() { @Override protected void preDraw(final GLState pGLState, final Camera pCamera) { super.preDraw(pGLState, pCamera); - + + // Check if polygon uses a texture + if( mTextureRegion != null) + this.mTextureRegion.getTexture().bind(pGLState); + this.mMeshVertexBufferObject.bind(pGLState, this.mShaderProgram); } @@ -131,6 +160,10 @@ protected void onUpdateColor() { protected void onUpdateVertices() { this.mMeshVertexBufferObject.onUpdateVertices(this); } + + protected void onUpdateTextureCoordinates() { + this.mMeshVertexBufferObject.onUpdateTextureCoordinates(this); + } @Override @Deprecated @@ -155,6 +188,24 @@ public boolean collidesWith(final IShape pOtherShape) { // Methods // =========================================================== + protected static float[] buildVertexList(float[] pVertexX, float[] pVertexY) + { + assert( pVertexX.length == pVertexY.length ); + + float[] bufferData = new float[VERTEX_SIZE * pVertexX.length]; + updateVertexList(pVertexX, pVertexY, bufferData); + return bufferData; + } + + protected static void updateVertexList(float[] pVertexX, float[] pVertexY, float[] pBufferData) + { + for( int i = 0; i < pVertexX.length; i++) + { + pBufferData[(i * Mesh.VERTEX_SIZE) + Mesh.VERTEX_INDEX_X] = pVertexX[i]; + pBufferData[(i * Mesh.VERTEX_SIZE) + Mesh.VERTEX_INDEX_Y] = pVertexY[i]; + } + } + // =========================================================== // Inner and Anonymous Classes // =========================================================== @@ -171,6 +222,7 @@ public static interface IMeshVertexBufferObject extends IVertexBufferObject { public float[] getBufferData(); public void onUpdateColor(final Mesh pMesh); public void onUpdateVertices(final Mesh pMesh); + public void onUpdateTextureCoordinates(final Mesh pMesh); } public static class HighPerformanceMeshVertexBufferObject extends HighPerformanceVertexBufferObject implements IMeshVertexBufferObject { @@ -221,6 +273,51 @@ public void onUpdateVertices(final Mesh pMesh) { this.setDirtyOnHardware(); } + + @Override + public void onUpdateTextureCoordinates(final Mesh pMesh) { + final float[] bufferData = this.mBufferData; + + final ITextureRegion textureRegion = pMesh.getTextureRegion(); // TODO Optimize with field access? + + final float u; + final float v; + final float u2; + final float v2; + + u = textureRegion.getU(); + u2 = textureRegion.getU2(); + v = textureRegion.getV(); + v2 = textureRegion.getV2(); + + if(textureRegion.isRotated()) { + bufferData[0 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_U] = u2; + bufferData[0 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_V] = v; + + bufferData[1 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_U] = u; + bufferData[1 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_V] = v; + + bufferData[2 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_U] = u2; + bufferData[2 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_V] = v2; + + bufferData[3 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_U] = u; + bufferData[3 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_V] = v2; + } else { + bufferData[0 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_U] = u; + bufferData[0 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_V] = v; + + bufferData[1 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_U] = u; + bufferData[1 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_V] = v2; + + bufferData[2 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_U] = u2; + bufferData[2 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_V] = v; + + bufferData[3 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_U] = u2; + bufferData[3 * Sprite.VERTEX_SIZE + Sprite.TEXTURECOORDINATES_INDEX_V] = v2; + } + + this.setDirtyOnHardware(); + } // =========================================================== // Methods diff --git a/src/org/andengine/entity/primitive/PolyLine.java b/src/org/andengine/entity/primitive/PolyLine.java new file mode 100644 index 000000000..054d2a6c4 --- /dev/null +++ b/src/org/andengine/entity/primitive/PolyLine.java @@ -0,0 +1,114 @@ +package org.andengine.entity.primitive; + +import org.andengine.engine.camera.Camera; +import org.andengine.opengl.util.GLState; +import org.andengine.opengl.vbo.VertexBufferObject.DrawType; +import org.andengine.opengl.vbo.VertexBufferObjectManager; +import org.andengine.opengl.vbo.attribute.VertexBufferObjectAttribute; + +/** + * + * @author Rodrigo Castro + * @since 22:54:17 - 30.01.2012 + */ +public class PolyLine extends Mesh { + // =========================================================== + // Constants + // =========================================================== + + // =========================================================== + // Fields + // =========================================================== + + private float mLineWidth; + + // =========================================================== + // Constructors + // =========================================================== + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public PolyLine(final float pX, final float pY, final float[] pVertexX, final float[] pVertexY, final VertexBufferObjectManager pVertexBufferObjectManager) { + this(pX, pY, pVertexX, pVertexY, Line.LINE_WIDTH_DEFAULT, pVertexBufferObjectManager); + } + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public PolyLine(final float pX, final float pY, final float[] pVertexX, final float[] pVertexY, final float pLineWidth, final VertexBufferObjectManager pVertexBufferObjectManager) { + this(pX, pY, pVertexX, pVertexY, pLineWidth, pVertexBufferObjectManager, DrawMode.LINE_LOOP); + } + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public PolyLine(final float pX, final float pY, final float[] pVertexX, final float[] pVertexY, final float pLineWidth, final VertexBufferObjectManager pVertexBufferObjectManager, DrawMode pDrawMode) { + this(pX, pY, pVertexX, pVertexY, pLineWidth, pVertexBufferObjectManager, pDrawMode, DrawType.STATIC); + } + + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public PolyLine(final float pX, final float pY, final float[] pVertexX, final float[] pVertexY, final float pLineWidth, final VertexBufferObjectManager pVertexBufferObjectManager, DrawMode pDrawMode, final DrawType pDrawType) { + this(pX, pY, buildVertexList(pVertexX, pVertexY), pLineWidth, pVertexBufferObjectManager, pDrawMode, pDrawType); + } + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public PolyLine(final float pX, final float pY, final float[] pBufferData, final float pLineWidth, final VertexBufferObjectManager pVertexBufferObjectManager, DrawMode pDrawMode, final DrawType pDrawType) { + super(pX, pY, pBufferData, pBufferData.length / VERTEX_SIZE, pDrawMode, pVertexBufferObjectManager, pDrawType); + + mLineWidth = pLineWidth; + } + + // =========================================================== + // Getter & Setter + // =========================================================== + + public float getLineWidth() + { + return mLineWidth; + } + + public void setLineWidth( float pLineWidth ) + { + mLineWidth = pLineWidth; + } + + // =========================================================== + // Methods for/from SuperClass/Interfaces + // =========================================================== + + @Override + protected void preDraw(final GLState pGLState, final Camera pCamera) { + super.preDraw(pGLState, pCamera); + + pGLState.lineWidth(this.mLineWidth); + + } + + // =========================================================== + // Methods + // =========================================================== + + /** + * + * @param pVertexX + * @param pVertexY + * @return true if vertices were correctly updated + * false otherwise + */ + public void updateVertices( float[] pVertexX, float[] pVertexY ) + { + assert( pVertexX.length == pVertexY.length ); + updateVertexList(pVertexX, pVertexY, getBufferData()); + onUpdateVertices(); + } + + // =========================================================== + // Inner and Anonymous Classes + // =========================================================== +} diff --git a/src/org/andengine/entity/primitive/Polygon.java b/src/org/andengine/entity/primitive/Polygon.java new file mode 100644 index 000000000..4ea71262e --- /dev/null +++ b/src/org/andengine/entity/primitive/Polygon.java @@ -0,0 +1,154 @@ +package org.andengine.entity.primitive; + +import java.util.ArrayList; +import java.util.List; + +import org.andengine.extension.physics.box2d.util.triangulation.EarClippingTriangulator; +import org.andengine.opengl.vbo.VertexBufferObject.DrawType; +import org.andengine.opengl.vbo.VertexBufferObjectManager; +import org.andengine.opengl.vbo.attribute.VertexBufferObjectAttribute; + +import android.util.Log; + +import com.badlogic.gdx.math.Vector2; + +/** + * + * @author Rodrigo Castro + * @since 22:10:11 - 28.01.2012 + */ +public class Polygon extends Mesh { + // =========================================================== + // Constants + // =========================================================== + + private static final float VERTEX_SIZE_DEFAULT_RATIO = 1.f; + + // =========================================================== + // Fields + // =========================================================== + + protected float[] mVertexX; + protected float[] mVertexY; + + protected static EarClippingTriangulator mTriangulator = new EarClippingTriangulator(); + + // =========================================================== + // Constructors + // =========================================================== + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public Polygon(final float pX, final float pY, final float[] pVertexX, final float[] pVertexY, final VertexBufferObjectManager pVertexBufferObjectManager) { + this(pX, pY, pVertexX, pVertexY, pVertexBufferObjectManager, DrawType.STATIC); + } + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public Polygon(final float pX, final float pY, final float[] pVertexX, float[] pVertexY, final VertexBufferObjectManager pVertexBufferObjectManager, final DrawType pDrawType) { + this(pX, pY, buildVertexList(mTriangulator.computeTriangles(buildListOfVector2(pVertexX, pVertexY))), VERTEX_SIZE_DEFAULT_RATIO, pVertexBufferObjectManager, pDrawType ); + + assert( mVertexX.length == mVertexY.length ); + mVertexX = pVertexX; + mVertexY = pVertexY; + } + + + /** + * Uses a default {@link HighPerformanceMeshVertexBufferObject} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public Polygon(final float pX, final float pY, final float[] pBufferData, final float sizeRatio, final VertexBufferObjectManager pVertexBufferObjectManager, final DrawType pDrawType) { + super(pX, pY, (int) ((pBufferData.length / VERTEX_SIZE)* sizeRatio), DrawMode.TRIANGLES, + new HighPerformanceMeshVertexBufferObject(pVertexBufferObjectManager, pBufferData, (int) ((pBufferData.length / VERTEX_SIZE )*sizeRatio), pDrawType, true, Mesh.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT)); + + onUpdateVertices(); + } + + // =========================================================== + // Getter & Setter + // =========================================================== + + public float[] getVertexX() + { + return mVertexX; + } + + public float[] getVertexY() + { + return mVertexY; + } + + /** + * + * @param pVertexX + * @param pVertexY + * @return true if vertices were correctly updated + * false otherwise + */ + public boolean updateVertices( float[] pVertexX, float[] pVertexY ) + { + mVertexX = pVertexX; + mVertexY = pVertexY; + assert( mVertexX.length == mVertexY.length ); + + List verticesVectors = mTriangulator.computeTriangles(buildListOfVector2(pVertexX, pVertexY)); + if( verticesVectors.size() == 0 ) + { + Log.e("AndEngine", "Error: Polygon - Polygon can't be triangulated. Will not update vertices"); + return false; + } + + updateVertices(verticesVectors, getBufferData()); + onUpdateVertices(); + + return true; + } + + // =========================================================== + // Methods for/from SuperClass/Interfaces + // =========================================================== + + // =========================================================== + // Methods + // =========================================================== + + protected static List buildListOfVector2(float[] pX, float [] pY ) + { + assert(pX.length == pY.length ); + ArrayList vectors = new ArrayList( pX.length ); + + for( int i = 0; i < pX.length; i++ ) + { + // TODO avoid using new + Vector2 v = new Vector2( pX[i], pY[i]); + vectors.add(v); + } + + return vectors; + } + + protected static float[] buildVertexList(List vertices ) + { + + float[] bufferData = new float[VERTEX_SIZE * vertices.size()]; + updateVertices( vertices, bufferData ); + return bufferData; + } + + protected static void updateVertices(List vertices, float[] pBufferData) { + int i = 0; + for( Vector2 vertex : vertices ) + { + pBufferData[(i * Mesh.VERTEX_SIZE) + Mesh.VERTEX_INDEX_X] = vertex.x; + pBufferData[(i * Mesh.VERTEX_SIZE) + Mesh.VERTEX_INDEX_Y] = vertex.y; + i++; + } + } + + // =========================================================== + // Inner and Anonymous Classes + // =========================================================== + +} diff --git a/src/org/andengine/entity/primitive/TexturedMesh.java b/src/org/andengine/entity/primitive/TexturedMesh.java new file mode 100644 index 000000000..7666c810e --- /dev/null +++ b/src/org/andengine/entity/primitive/TexturedMesh.java @@ -0,0 +1,401 @@ +package org.andengine.entity.primitive; + +import org.andengine.engine.camera.Camera; +import org.andengine.entity.shape.IShape; +import org.andengine.entity.shape.RectangularShape; +import org.andengine.entity.shape.Shape; +import org.andengine.opengl.shader.PositionColorTextureCoordinatesShaderProgram; +import org.andengine.opengl.shader.constants.ShaderProgramConstants; +import org.andengine.opengl.texture.region.ITextureRegion; +import org.andengine.opengl.util.GLState; +import org.andengine.opengl.vbo.HighPerformanceVertexBufferObject; +import org.andengine.opengl.vbo.IVertexBufferObject; +import org.andengine.opengl.vbo.VertexBufferObject.DrawType; +import org.andengine.opengl.vbo.VertexBufferObjectManager; +import org.andengine.opengl.vbo.attribute.VertexBufferObjectAttribute; +import org.andengine.opengl.vbo.attribute.VertexBufferObjectAttributes; +import org.andengine.opengl.vbo.attribute.VertexBufferObjectAttributesBuilder; +import org.andengine.util.debug.Debug; +import org.andengine.util.exception.MethodNotSupportedException; + +import android.opengl.GLES20; +import android.renderscript.Mesh; + +/** + * (c) Zynga 2012 + * + * @author Nicolas Gramlich + * @since 16:44:50 - 09.02.2012 + */ +public class TexturedMesh extends Shape { + // =========================================================== + // Constants + // =========================================================== + + public static final int VERTEX_INDEX_X = 0; + public static final int VERTEX_INDEX_Y = TexturedMesh.VERTEX_INDEX_X + 1; + public static final int COLOR_INDEX = TexturedMesh.VERTEX_INDEX_Y + 1; + public static final int TEXTURECOORDINATES_INDEX_U = TexturedMesh.COLOR_INDEX + 1; + public static final int TEXTURECOORDINATES_INDEX_V = TexturedMesh.TEXTURECOORDINATES_INDEX_U + 1; + + + public static final int VERTEX_SIZE = 5; + + public static final VertexBufferObjectAttributes VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT = new VertexBufferObjectAttributesBuilder(3) + .add(ShaderProgramConstants.ATTRIBUTE_POSITION_LOCATION, ShaderProgramConstants.ATTRIBUTE_POSITION, 2, GLES20.GL_FLOAT, false) + .add(ShaderProgramConstants.ATTRIBUTE_COLOR_LOCATION, ShaderProgramConstants.ATTRIBUTE_COLOR, 4, GLES20.GL_UNSIGNED_BYTE, true) + .add(ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES_LOCATION, ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES, 2, GLES20.GL_FLOAT, false) + .build(); + + // =========================================================== + // Fields + // =========================================================== + + protected final ITexturedMeshVertexBufferObject mMeshVertexBufferObject; + private int mVertexCountToDraw; + private int mDrawMode; + protected ITextureRegion mTextureRegion; + + // =========================================================== + // Constructors + // =========================================================== + + /** + * Uses a default {@link HighPerformanceTexturedMeshVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public TexturedMesh(final float pX, final float pY, final float[] pBufferData, final int pVertexCount, final DrawMode pDrawMode, final VertexBufferObjectManager pVertexBufferObjectManager) { + this(pX, pY, pBufferData, pVertexCount, pDrawMode, null, pVertexBufferObjectManager, DrawType.STATIC); + } + + /** + * Uses a default {@link HighPerformanceTexturedMeshVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public TexturedMesh(final float pX, final float pY, final float[] pBufferData, final int pVertexCount, final DrawMode pDrawMode, final ITextureRegion pTextureRegion, final VertexBufferObjectManager pVertexBufferObjectManager) { + this(pX, pY, pBufferData, pVertexCount, pDrawMode, pTextureRegion, pVertexBufferObjectManager, DrawType.STATIC); + } + + /** + * Uses a default {@link HighPerformanceTexturedMeshVertexBufferObject} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public TexturedMesh(final float pX, final float pY, final float[] pBufferData, final int pVertexCount, final DrawMode pDrawMode, final VertexBufferObjectManager pVertexBufferObjectManager, final DrawType pDrawType) { + this(pX, pY, pBufferData, pVertexCount, pDrawMode, null, pVertexBufferObjectManager, pDrawType); + } + + /** + * Uses a default {@link HighPerformanceTexturedMeshVertexBufferObject} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public TexturedMesh(final float pX, final float pY, final float[] pBufferData, final int pVertexCount, final DrawMode pDrawMode, final ITextureRegion pTextureRegion, final VertexBufferObjectManager pVertexBufferObjectManager, final DrawType pDrawType) { + this(pX, pY, pVertexCount, pDrawMode, pTextureRegion, new HighPerformanceTexturedMeshVertexBufferObject(pVertexBufferObjectManager, pBufferData, pVertexCount, pDrawType, true, TexturedMesh.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT)); + } + + /** + * Uses a default {@link HighPerformanceTexturedMeshVertexBufferObject} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public TexturedMesh(final float pX, final float pY, final float[] pVertexX, final float[] pVertexY, final DrawMode pDrawMode, final ITextureRegion pTextureRegion, final VertexBufferObjectManager pVertexBufferObjectManager, final DrawType pDrawType) { + this(pX, pY, pVertexX.length, pDrawMode, pTextureRegion, new HighPerformanceTexturedMeshVertexBufferObject(pVertexBufferObjectManager, buildVertexList(pVertexX, pVertexY), pVertexX.length, pDrawType, true, TexturedMesh.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT)); + } + + public TexturedMesh(final float pX, final float pY, final int pVertexCount, final DrawMode pDrawMode, final ITextureRegion pTextureRegion, final ITexturedMeshVertexBufferObject pMeshVertexBufferObject) { + super(pX, pY, PositionColorTextureCoordinatesShaderProgram.getInstance()); + + this.mDrawMode = pDrawMode.getDrawMode(); + this.mTextureRegion = pTextureRegion; + this.mMeshVertexBufferObject = pMeshVertexBufferObject; + this.mVertexCountToDraw = pVertexCount; + + if( pTextureRegion != null) + { + this.setBlendingEnabled(true); + this.initBlendFunction(pTextureRegion); + this.onUpdateTextureCoordinates(); + + } + + this.onUpdateVertices(); + this.onUpdateColor(); + + this.mMeshVertexBufferObject.setDirtyOnHardware(); + + this.setBlendingEnabled(true); + } + + // =========================================================== + // Getter & Setter + // =========================================================== + + public float[] getBufferData() { + return this.mMeshVertexBufferObject.getBufferData(); + } + + public void setVertexCountToDraw(final int pVertexCountToDraw) { + this.mVertexCountToDraw = pVertexCountToDraw; + } + + public void setDrawMode(final DrawMode pDrawMode) { + this.mDrawMode = pDrawMode.mDrawMode; + } + + public ITextureRegion getTextureRegion() { + return this.mTextureRegion; + } + + // =========================================================== + // Methods for/from SuperClass/Interfaces + // =========================================================== + + @Override + public ITexturedMeshVertexBufferObject getVertexBufferObject() { + return this.mMeshVertexBufferObject; + } + + @Override + public void reset() { + super.reset(); + + this.initBlendFunction(this.getTextureRegion().getTexture()); + } + + @Override + protected void preDraw(final GLState pGLState, final Camera pCamera) { + super.preDraw(pGLState, pCamera); + + this.mTextureRegion.getTexture().bind(pGLState); + + this.mMeshVertexBufferObject.bind(pGLState, this.mShaderProgram); + } + + @Override + protected void draw(final GLState pGLState, final Camera pCamera) { + this.mMeshVertexBufferObject.draw(this.mDrawMode, this.mVertexCountToDraw); + } + + @Override + protected void postDraw(final GLState pGLState, final Camera pCamera) { + this.mMeshVertexBufferObject.unbind(pGLState, this.mShaderProgram); + + super.postDraw(pGLState, pCamera); + } + + @Override + protected void onUpdateColor() { + this.mMeshVertexBufferObject.onUpdateColor(this); + } + + @Override + protected void onUpdateVertices() { + this.mMeshVertexBufferObject.onUpdateVertices(this); + } + + protected void onUpdateTextureCoordinates() { + this.mMeshVertexBufferObject.onUpdateTextureCoordinates(this); + } + + @Override + @Deprecated + public boolean contains(final float pX, final float pY) { + throw new MethodNotSupportedException(); + } + + @Override + public boolean collidesWith(final IShape pOtherShape) { + if(pOtherShape instanceof Line) { + // TODO + return false; + } else if(pOtherShape instanceof RectangularShape) { + // TODO + return false; + } else { + return false; + } + } + + // =========================================================== + // Methods + // =========================================================== + + protected static float[] buildVertexList(float[] pVertexX, float[] pVertexY) + { + assert( pVertexX.length == pVertexY.length ); + + float[] bufferData = new float[TexturedMesh.VERTEX_SIZE * pVertexX.length]; + updateVertexList(pVertexX, pVertexY, bufferData); + return bufferData; + } + + protected static void updateVertexList(float[] pVertexX, float[] pVertexY, float[] pBufferData) + { + for( int i = 0; i < pVertexX.length; i++) + { + pBufferData[(i * TexturedMesh.VERTEX_SIZE) + TexturedMesh.VERTEX_INDEX_X] = pVertexX[i]; + pBufferData[(i * TexturedMesh.VERTEX_SIZE) + TexturedMesh.VERTEX_INDEX_Y] = pVertexY[i]; + } + } + + // =========================================================== + // Inner and Anonymous Classes + // =========================================================== + + public static interface ITexturedMeshVertexBufferObject extends IVertexBufferObject { + // =========================================================== + // Constants + // =========================================================== + + // =========================================================== + // Methods + // =========================================================== + + public float[] getBufferData(); + public void onUpdateColor(final TexturedMesh pMesh); + public void onUpdateVertices(final TexturedMesh pMesh); + public void onUpdateTextureCoordinates(final TexturedMesh pMesh); + } + + public static class HighPerformanceTexturedMeshVertexBufferObject extends HighPerformanceVertexBufferObject implements ITexturedMeshVertexBufferObject { + // =========================================================== + // Constants + // =========================================================== + + // =========================================================== + // Fields + // =========================================================== + + private final int mVertexCount; + + // =========================================================== + // Constructors + // =========================================================== + + public HighPerformanceTexturedMeshVertexBufferObject(final VertexBufferObjectManager pVertexBufferObjectManager, final float[] pBufferData, final int pVertexCount, final DrawType pDrawType, final boolean pAutoDispose, final VertexBufferObjectAttributes pVertexBufferObjectAttributes) { + super(pVertexBufferObjectManager, pBufferData, pDrawType, pAutoDispose, pVertexBufferObjectAttributes); + + this.mVertexCount = pVertexCount; + } + + // =========================================================== + // Getter & Setter + // =========================================================== + + // =========================================================== + // Methods for/from SuperClass/Interfaces + // =========================================================== + + @Override + public void onUpdateColor(final TexturedMesh pMesh) { + final float[] bufferData = this.mBufferData; + + final float packedColor = pMesh.getColor().getABGRPackedFloat(); + + for(int i = 0; i < this.mVertexCount; i++) { + bufferData[(i * TexturedMesh.VERTEX_SIZE) + TexturedMesh.COLOR_INDEX] = packedColor; + } + + this.setDirtyOnHardware(); + } + + @Override + public void onUpdateVertices(final TexturedMesh pMesh) { + /* Since the buffer data is managed from the caller, we just mark the buffer data as dirty. */ + + this.setDirtyOnHardware(); + } + + @Override + public void onUpdateTextureCoordinates(final TexturedMesh pMesh) { + final float[] bufferData = this.mBufferData; + + final ITextureRegion textureRegion = pMesh.getTextureRegion(); // TODO Optimize with field access? + + float textureWidth = textureRegion.getWidth(); + float textureHeight = textureRegion.getHeight(); + + // x0 is mapped to u0 + // y0 is mapped to v0 + + // TODO get initial mapping + float x0 = 0; // pMesh.getX0(); + float y0 = 0; //pMesh.getY0(); + + + for(int i = 0; i < this.mVertexCount; i++) { + float x = bufferData[(i * TexturedMesh.VERTEX_SIZE) + TexturedMesh.VERTEX_INDEX_X]; + float y = bufferData[(i * TexturedMesh.VERTEX_SIZE) + TexturedMesh.VERTEX_INDEX_Y]; + + float u = (x - x0) / textureWidth; + float v = (y - y0) / textureHeight; + + Debug.d("u = " + u ); + Debug.d("v = " + v ); + + Debug.d("x = " + x ); + Debug.d("y = " + y ); + + bufferData[(i * TexturedMesh.VERTEX_SIZE) + TexturedMesh.TEXTURECOORDINATES_INDEX_U] = u; + bufferData[(i * TexturedMesh.VERTEX_SIZE) + TexturedMesh.TEXTURECOORDINATES_INDEX_V] = v; + } + + Debug.d("v ---" ); + + this.setDirtyOnHardware(); + } + + // =========================================================== + // Methods + // =========================================================== + + // =========================================================== + // Inner and Anonymous Classes + // =========================================================== + } + + public static enum DrawMode { + // =========================================================== + // Elements + // =========================================================== + + POINTS(GLES20.GL_POINTS), + LINE_STRIP(GLES20.GL_LINE_STRIP), + LINE_LOOP(GLES20.GL_LINE_LOOP), + LINES(GLES20.GL_LINES), + TRIANGLE_STRIP(GLES20.GL_TRIANGLE_STRIP), + TRIANGLE_FAN(GLES20.GL_TRIANGLE_FAN), + TRIANGLES(GLES20.GL_TRIANGLES); + + // =========================================================== + // Constants + // =========================================================== + + public final int mDrawMode; + + // =========================================================== + // Fields + // =========================================================== + + // =========================================================== + // Constructors + // =========================================================== + + private DrawMode(final int pDrawMode) { + this.mDrawMode = pDrawMode; + } + + // =========================================================== + // Getter & Setter + // =========================================================== + + public int getDrawMode() { + return this.mDrawMode; + } + + // =========================================================== + // Methods for/from SuperClass/Interfaces + // =========================================================== + + // =========================================================== + // Methods + // =========================================================== + + // =========================================================== + // Inner and Anonymous Classes + // =========================================================== + } +} diff --git a/src/org/andengine/entity/primitive/TexturedPolygon.java b/src/org/andengine/entity/primitive/TexturedPolygon.java new file mode 100644 index 000000000..37c7dd887 --- /dev/null +++ b/src/org/andengine/entity/primitive/TexturedPolygon.java @@ -0,0 +1,154 @@ +package org.andengine.entity.primitive; + +import java.util.ArrayList; +import java.util.List; + +import org.andengine.extension.physics.box2d.util.triangulation.EarClippingTriangulator; +import org.andengine.opengl.texture.region.ITextureRegion; +import org.andengine.opengl.vbo.VertexBufferObject.DrawType; +import org.andengine.opengl.vbo.VertexBufferObjectManager; +import org.andengine.opengl.vbo.attribute.VertexBufferObjectAttribute; + +import android.renderscript.Mesh; +import android.util.Log; + +import com.badlogic.gdx.math.Vector2; + +/** + * + * @author Rodrigo Castro + * @since 22:10:11 - 28.01.2012 + */ +public class TexturedPolygon extends TexturedMesh { + // =========================================================== + // Constants + // =========================================================== + + private static final float VERTEX_SIZE_DEFAULT_RATIO = 1.f; + + // =========================================================== + // Fields + // =========================================================== + + protected float[] mVertexX; + protected float[] mVertexY; + + protected static EarClippingTriangulator mTriangulator = new EarClippingTriangulator(); + + // =========================================================== + // Constructors + // =========================================================== + + /** + * Uses a default {@link HighPerformanceTexturedMeshVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public TexturedPolygon(final float pX, final float pY, final float[] pVertexX, final float[] pVertexY, final ITextureRegion pTextureRegion, final VertexBufferObjectManager pVertexBufferObjectManager) { + this(pX, pY, pVertexX, pVertexY, pTextureRegion, pVertexBufferObjectManager, DrawType.STATIC); + } + + /** + * Uses a default {@link HighPerformanceTexturedMeshVertexBufferObject} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public TexturedPolygon(final float pX, final float pY, final float[] pVertexX, float[] pVertexY, final ITextureRegion pTextureRegion, final VertexBufferObjectManager pVertexBufferObjectManager, final DrawType pDrawType) { + this(pX, pY, buildVertexList(mTriangulator.computeTriangles(buildListOfVector2(pVertexX, pVertexY))), VERTEX_SIZE_DEFAULT_RATIO, pTextureRegion, pVertexBufferObjectManager, pDrawType ); + + assert( mVertexX.length == mVertexY.length ); + mVertexX = pVertexX; + mVertexY = pVertexY; + } + + + /** + * Uses a default {@link HighPerformanceTexturedMeshVertexBufferObject} with the {@link VertexBufferObjectAttribute}s: {@link Mesh#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}. + */ + public TexturedPolygon(final float pX, final float pY, final float[] pBufferData, final float sizeRatio, final ITextureRegion pTextureRegion, final VertexBufferObjectManager pVertexBufferObjectManager, final DrawType pDrawType) { + super(pX, pY, (int) ((pBufferData.length / VERTEX_SIZE)* sizeRatio), DrawMode.TRIANGLES, + pTextureRegion, new HighPerformanceTexturedMeshVertexBufferObject(pVertexBufferObjectManager, pBufferData, (int) ((pBufferData.length / VERTEX_SIZE )*sizeRatio), pDrawType, true, TexturedMesh.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT)); + } + + // =========================================================== + // Getter & Setter + // =========================================================== + + public float[] getVertexX() + { + return mVertexX; + } + + public float[] getVertexY() + { + return mVertexY; + } + + /** + * + * @param pVertexX + * @param pVertexY + * @return true if vertices were correctly updated + * false otherwise + */ + public boolean updateVertices( float[] pVertexX, float[] pVertexY ) + { + mVertexX = pVertexX; + mVertexY = pVertexY; + assert( mVertexX.length == mVertexY.length ); + + List verticesVectors = mTriangulator.computeTriangles(buildListOfVector2(pVertexX, pVertexY)); + if( verticesVectors.size() == 0 ) + { + Log.e("AndEngine", "Error: Polygon - Polygon can't be triangulated. Will not update vertices"); + return false; + } + + updateVertices(verticesVectors, getBufferData()); + onUpdateVertices(); + + return true; + } + + // =========================================================== + // Methods for/from SuperClass/Interfaces + // =========================================================== + + // =========================================================== + // Methods + // =========================================================== + + protected static List buildListOfVector2(float[] pX, float [] pY ) + { + assert(pX.length == pY.length ); + ArrayList vectors = new ArrayList( pX.length ); + + for( int i = 0; i < pX.length; i++ ) + { + // TODO avoid using new + Vector2 v = new Vector2( pX[i], pY[i]); + vectors.add(v); + } + + return vectors; + } + + protected static float[] buildVertexList(List vertices ) + { + + float[] bufferData = new float[VERTEX_SIZE * vertices.size()]; + updateVertices( vertices, bufferData ); + return bufferData; + } + + protected static void updateVertices(List vertices, float[] pBufferData) { + int i = 0; + for( Vector2 vertex : vertices ) + { + pBufferData[(i * TexturedMesh.VERTEX_SIZE) + TexturedMesh.VERTEX_INDEX_X] = vertex.x; + pBufferData[(i * TexturedMesh.VERTEX_SIZE) + TexturedMesh.VERTEX_INDEX_Y] = vertex.y; + i++; + } + } + + // =========================================================== + // Inner and Anonymous Classes + // =========================================================== + +}