How to apply color to an irregular polygon with unknown indices?

90 views Asked by At

I'm having a set of vertices (X,Y) of an irregular polygon, some having 4 vertices and some more than 4. I'm creating an array of vertices for drawing from the set of vertices I have using the getTransformedVertices() method. The indices and UV for the texture are unknown so I had to calculate tem using Triangulate() method below. I've setup the color and texture in the setColor() and setImage() methods.

However, the polygons having more than 4 vertices are not rendered properly. I've been trying for weeks now and almost the searched half of the internet. This is what I could come up with. The polygons with 4 vertices and the outlines are working properly. But I couldn't get the textures displayed properly on the polygon. Please help

The texture not rendered properly on a polygon having more than 4 vertices (BLUEBIRD POLYGON)

public class BoothRectangle
{
float angle;
float scale;
RectF base;
PointF translation;
int textureId;
int positionBufferId;
int textureBufferId;
PointF[] corners;
float[] verts;

// Geometric variables
public float vertices[];
public float colors[];
public short indices[];
public float uvs[];
public FloatBuffer vertexBuffer;
public ShortBuffer drawListBuffer;
public FloatBuffer colorBuffer;
public FloatBuffer uvBuffer;
TextPaint textPaint = new TextPaint();
String title;

public BoothRectangle(PointF[] corners, int textureId, float[] colors, String title)
{
    // Initialise our intital size around the 0,0 point
    base = new RectF(corners[1].x, corners[3].y, corners[0].x, corners[1].y);
    this.corners = corners;
    this.title = title;

    // Offset translation
    translation = new PointF(0f,0f);

    // Initial Size
    scale = 1f;

    // We start in our inital angle
    angle = 0f;

    this.textureId = textureId;
    this.colors = colors;
}

public void setColor(float[] topColor){
    List<Float> colorsList = new ArrayList<Float>();

    for(PointF point : corners){
        colorsList.add(topColor[0] / 255);
        colorsList.add(topColor[1] / 255);
        colorsList.add(topColor[2] / 255);
        colorsList.add(1f);
    }

    int i = 0;
    float[] colors = new float[colorsList.size()];
    for (Float f : colorsList) {
        colors[i++] = (f != null ? f : Float.NaN);
    }

    ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
    cbb.order(ByteOrder.nativeOrder());
    colorBuffer = cbb.asFloatBuffer();
    colorBuffer.put(colors);
    colorBuffer.position(0);

    int[] buffers = new int[1];
    GLES11.glGenBuffers(1, buffers, 0);
    GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, buffers[0]);
    GLES11.glBufferData(GLES11.GL_ARRAY_BUFFER, 4 * colors.length, colorBuffer, GLES11.GL_STATIC_DRAW);
    textureBufferId = buffers[0];
    GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, 0);   
}

public float[] getTransformedVertices()
{
    float z;
    List<Float> finalVertices = new ArrayList<Float>();

    if(textureId == 0)
        z = 0.5f;
    else
        z = 2.0f;

        finalVertices.clear();
        for(PointF point : corners){
            finalVertices.add(point.x);
            finalVertices.add(point.y);
            finalVertices.add(0.0f);
        }   

        int i = 0;
        float[] verticesArray = new float[finalVertices.size()];
        for (Float f : finalVertices) {
            verticesArray[i++] = (f != null ? f : Float.NaN);
        }
        return verticesArray;


}

public void setImage()
{

    uvs = new float[] {
        0.0f, 0.0f,
        1.0f, 0.0f,
        1.0f, 1.0f,         
        0.0f, 1.0f  
    };

    // The texture buffer
    ByteBuffer bb = ByteBuffer.allocateDirect(uvs.length * 4);
    bb.order(ByteOrder.nativeOrder());
    uvBuffer = bb.asFloatBuffer();
    uvBuffer.put(uvs);
    uvBuffer.position(0);

    int[] buffers = new int[1];
    GLES11.glGenBuffers(1, buffers, 0);
    GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, buffers[0]);
    GLES11.glBufferData(GLES11.GL_ARRAY_BUFFER, 4 * uvs.length, uvBuffer, GLES11.GL_STATIC_DRAW);
    textureBufferId = buffers[0];
    GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, 0);

}

public void initBooth()
{
    vertices = this.getTransformedVertices();

    indices = PolygonTriangulation.Process(vertices);

    if(indices==null){
        Log.d("PolygonTriangulation",title + " - failed");
        if(this.corners.length == 4){
            indices = new short[] {2, 1, 0, 2, 0, 3};
    }else{
        indices = new short[corners.length];
        for(int i=0;i<corners.length;i++){
            indices[i] = (short) i;
        }
    }
    }

    // The vertex buffer.
    ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
    bb.order(ByteOrder.nativeOrder());
    vertexBuffer = bb.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

    ByteBuffer dlb = ByteBuffer.allocateDirect(indices.length * 2);
    dlb.order(ByteOrder.nativeOrder());
    drawListBuffer = dlb.asShortBuffer();
    drawListBuffer.put(indices);
    drawListBuffer.position(0);

    int[] buffers = new int[1];
    GLES11.glGenBuffers(1, buffers, 0);
    GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, buffers[0]);
    GLES11.glBufferData(GLES11.GL_ARRAY_BUFFER, 4 * vertices.length, vertexBuffer,   GLES11.GL_STATIC_DRAW);
    positionBufferId = buffers[0];
    GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, 0);

    if(this.textureId !=0){
        setImage();
    } else {
        setColor(colors);
    }
}

public void Render(GL10 gl){

if(textureId == 0){

    GLES11.glPushMatrix();
    GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, positionBufferId);
    GLES11.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    GLES11.glVertexPointer(3, GL10.GL_FLOAT, 0, 0);
    GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, 0);

    GLES11.glFrontFace(GL10.GL_CW);
    GLES11.glColor4f(0.8f, 0.8f, 0.8f, 0.8f);
    GLES11.glLineWidth(3.0f);
    GLES11.glDrawArrays(GL10.GL_LINE_LOOP, 0, corners.length);

    GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, textureBufferId);
    gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
    GLES11.glColorPointer(4, GL10.GL_FLOAT, 0, 0);
    GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, 0);

    GLES11.glDrawElements(GL10.GL_TRIANGLES, indices.length,
            GL10.GL_UNSIGNED_SHORT, drawListBuffer);
    GLES11.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    GLES11.glDisableClientState(GL10.GL_COLOR_ARRAY);
    GLES11.glPopMatrix();

} else {
        GLES11.glPushMatrix();
        GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, positionBufferId);
        GLES11.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        GLES11.glVertexPointer(3, GL10.GL_FLOAT, 0, 0);
        GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, 0);

        GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, textureBufferId);
        GLES11.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        GLES11.glTexCoordPointer(2, GL10.GL_FLOAT, 0, 0);
        GLES11.glBindBuffer(GLES11.GL_ARRAY_BUFFER, 0);

        GLES11.glEnable(GL10.GL_TEXTURE_2D);
        GLES11.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
        GLES11.glEnable(GL10.GL_BLEND);

        GLES11.glFrontFace(GL10.GL_CW);

        GLES11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

        GLES11.glBindTexture(GL10.GL_TEXTURE_2D, textureId);

        int error = gl.glGetError();
        if (error != GL10.GL_NO_ERROR)
        { 
            Log.e("OPENGL", "GL Texture Load Error: " + GLU.gluErrorString(error));
        }

        GLES11.glDrawElements(GL10.GL_TRIANGLES, indices.length,
                GL10.GL_UNSIGNED_SHORT, drawListBuffer);

        GLES11.glDisable(GL10.GL_BLEND);
        GLES11.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        GLES11.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        GLES11.glDisable(GL10.GL_TEXTURE_2D);
        GLES11.glPopMatrix();
    }
  }
}

PolygonTriangulation.java - got from AssetFX - http://www.experts-exchange.com/Programming/Languages/Java/Q_27882746.html

public class PolygonTriangulation {

static final float EPSILON=0.0000000001f;

static public float Area(float[] contour) {
    int n = contour.length;
    float A = 0.0f;

    for(int p = n - 3, q = 0; q < n; p=q, q+=3)
    {
        A += contour[p] * contour[q+1] - contour[q] * contour[p+1];
    }
    return A * 0.5f;
}

static public boolean InsideTriangle(float Ax,float Ay,float Bx,float By,float Cx,float Cy,float Px,float Py){
    float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
    float cCROSSap, bCROSScp, aCROSSbp;

    ax = Cx - Bx;  ay = Cy - By;
    bx = Ax - Cx;  by = Ay - Cy;
    cx = Bx - Ax;  cy = By - Ay;
    apx= Px - Ax;  apy= Py - Ay;
    bpx= Px - Bx;  bpy= Py - By;
    cpx= Px - Cx;  cpy= Py - Cy;

    aCROSSbp = ax * bpy - ay * bpx;
    cCROSSap = cx * apy - cy * apx;
    bCROSScp = bx * cpy - by * cpx;

    return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
}

static public boolean Snip(float[] contour, int u, int v, int w, int n, int[] V) {
    int p;
    float Ax, Ay, Bx, By, Cx, Cy, Px, Py;

    Ax = contour[V[u]];
    Ay = contour[V[u+1]];

    Bx = contour[V[v]];
    By = contour[V[v+1]];

    Cx = contour[V[w]];
    Cy = contour[V[w+1]];

    if ( EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) ){
        return false;
    }

    for (p = 0; p < n; p++)
    {
        if( (p == u/2) || (p == v/2) || (p == w/2) ){
            continue;
        }

        Px = contour[V[p*2]];
        Py = contour[V[(p*2)+1]];

        if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)){
            return false;
        }
    }
    return true;
}

//Brings in 3D vertex float array but processes it as 2D only.
static public short[] Process(float[] contour) {
    //Pre-return list
    ArrayList<Integer> vertexArray = new ArrayList<Integer>();

    /* allocate and initialize list of Vertices in polygon */
    int n = contour.length;
    if ( n/3 < 3 )
        return null;

    //The (n/3)*2 occurs as we are removing the z coordinate from the mix
    int[] V = new int[(n/3)*2];

    /* we want a counter-clockwise polygon in V */
    if (0.0f < Area(contour)){
        for (int s = 0, v = 0; v < n-1; s+=2, v += 3){
            V[s] = v;
            V[s + 1] = v + 1;
        }
    }
    else{
        for(int s = 0, v = 0; v < n-1; s += 2, v += 3){
            V[s] = (n - 1) - (v + 2);
            V[s + 1] = (n - 1) - (v + 1);
        }
    }

    int nv = n/3;

    /*  remove nv-2 Vertices, creating 1 triangle every time */
    int count = 2 * nv;   /* error detection */

    for(int v = nv - 1; nv > 2;)
    {
        /* if we loop, it is probably a non-simple polygon */
        if (0 >= (count--))
        {
            //** Triangulate: ERROR - probable bad polygon!
            Log.e("PolygonTriangulation","Invalid Polygon");
            return null;
        }

        /* three consecutive vertices in current polygon, <u,v,w> */
        int u = v;
        if (nv <= u)
            u = 0;      /* previous */
        v = u + 1;
        if (nv <= v)
            v = 0;      /* new v    */
        int w = v + 1;
        if (nv <= w)
            w = 0;      /* next     */

        if (Snip(contour, u*2, v*2, w*2, nv, V))
        {
            vertexArray.add(V[u*2]/3);
            vertexArray.add(V[v*2]/3);
            vertexArray.add(V[w*2]/3);

            // remove v from remaining polygon
            for(int s = v * 2, t = (v * 2) + 2; t < (nv * 2); s += 2, t += 2){
                V[s] = V[t];
                V[s+1] = V[t+1];
            }
            nv--;

            // reset error detection counter
            count = 2 * nv;
        }
    }
    //Convert ArrayList into short array
    short[] index = new short[vertexArray.size()];
    for(int i = 0; i < vertexArray.size(); i++){
        index[i] = vertexArray.get(i).shortValue();
    }
    return index;
}
}
0

There are 0 answers