package com.android.droidgraph.primitive; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.ShortBuffer; import javax.microedition.khronos.opengles.GL10; import android.util.Log; import com.android.droidgraph.shape.GLShape; public class RegularPolygon extends GLShape { // Store the centerX,Y,Z values and radius private float cx, cy, cz, radius; private int sides; // coord arrays (x, y) vertices private float[] xarray = null; private float[] yarray = null; // texture arrays (s, t) points private float[] sarray = null; private float[] tarray = null; public RegularPolygon(float tx, float ty, float tz, float r, int numsides) { cx = tx; cy = ty; cz = tz; radius = r; sides = numsides; // allocate memory for arrays xarray = new float[sides]; yarray = new float[sides]; // allocate texture arrays sarray = new float[sides]; tarray = new float[sides]; // calculate vertex points calcArrays(); // calculate texture points calcTextureArrays(); } // ********************************************** // Get and convert the vertex coordinates // based on origin and radius. // Real logic of angles happen inside getMultiplierArray() functions // ********************************************** private void calcArrays() { // Get the vertex points assuming a circle //with a radius of "1" and // located at "origin" zero float[] xmarray = this.getXMultiplierArray(); float[] ymarray = this.getYMultiplierArray(); // calc xarray: get the vertex //by adding the "x" portion of the origin // //multiply the coordinate with radius (scale) for (int i = 0; i < sides; i++) { float curm = xmarray[i]; float xcoord = cx + radius * curm; xarray[i] = xcoord; } this.printArray(xarray, "xarray"); // calc yarray: do the same for y coordinates for(int i=0;i<sides;i++) { for (int i = 0; i < sides; i++) { float curm = ymarray[i]; float ycoord = cy + radius * curm; yarray[i] = ycoord; } this.printArray(yarray, "yarray"); } // ********************************************** // Calculate texture arrays // See Texture subsection for more discussion on this // Very similar approach. // In this case the polygon has to map into a space // that is a square // ********************************************** private void calcTextureArrays() { float[] xmarray = this.getXMultiplierArray(); float[] ymarray = this.getYMultiplierArray(); // calc xarray for (int i = 0; i < sides; i++) { float curm = xmarray[i]; float xcoord = 0.5f + 0.5f * curm; sarray[i] = xcoord; } this.printArray(sarray, "sarray"); // calc yarray for (int i = 0; i < sides; i++) { float curm = ymarray[i]; float ycoord = 0.5f + 0.5f * curm; tarray[i] = ycoord; } this.printArray(tarray, "tarray"); } // ********************************************** // Convert the java array of vertices // into an nio float buffer // ********************************************** public FloatBuffer getVertexBuffer() { int vertices = sides + 1; int coordinates = 3; int floatsize = 4; int spacePerVertex = coordinates * floatsize; ByteBuffer vbb = ByteBuffer.allocateDirect(spacePerVertex * vertices); vbb.order(ByteOrder.nativeOrder()); FloatBuffer mFVertexBuffer = vbb.asFloatBuffer(); // Put the first coordinate (x,y,z:0,0,0) mFVertexBuffer.put(cx); // x mFVertexBuffer.put(cy); // y mFVertexBuffer.put(0.0f); // z int totalPuts = 3; for (int i = 0; i < sides; i++) { mFVertexBuffer.put(xarray[i]); // x mFVertexBuffer.put(yarray[i]); // y mFVertexBuffer.put(0.0f); // z totalPuts += 3; } Log.d("total puts:", Integer.toString(totalPuts)); return mFVertexBuffer; } // ********************************************** // Convert texture buffer to an nio buffer // ********************************************** public FloatBuffer getTextureBuffer() { int vertices = sides + 1; int coordinates = 2; int floatsize = 4; int spacePerVertex = coordinates * floatsize; ByteBuffer vbb = ByteBuffer.allocateDirect(spacePerVertex * vertices); vbb.order(ByteOrder.nativeOrder()); FloatBuffer mFTextureBuffer = vbb.asFloatBuffer(); // Put the first coordinate (x,y (s,t):0,0) mFTextureBuffer.put(0.5f); // x or s mFTextureBuffer.put(0.5f); // y or t int totalPuts = 2; for (int i = 0; i < sides; i++) { mFTextureBuffer.put(sarray[i]); // x mFTextureBuffer.put(tarray[i]); // y totalPuts += 2; } Log.d("total texture puts:", Integer.toString(totalPuts)); return mFTextureBuffer; } // ********************************************** // Calculate indices forming multiple triangles. // Start with the center vertex which is at 0 // Then count them in a clockwise direction such as // 0,1,2, 0,2,3, 0,3,4..etc // ********************************************** public ShortBuffer getIndexBuffer() { short[] iarray = new short[sides * 3]; ByteBuffer ibb = ByteBuffer.allocateDirect(sides * 3 * 2); ibb.order(ByteOrder.nativeOrder()); ShortBuffer mIndexBuffer = ibb.asShortBuffer(); for (int i = 0; i < sides; i++) { short index1 = 0; short index2 = (short) (i + 1); short index3 = (short) (i + 2); if (index3 == sides + 1) { index3 = 1; } mIndexBuffer.put(index1); mIndexBuffer.put(index2); mIndexBuffer.put(index3); iarray[i * 3 + 0] = index1; iarray[i * 3 + 1] = index2; iarray[i * 3 + 2] = index3; } this.printShortArray(iarray, "index array"); return mIndexBuffer; } // ********************************************** // This is where you take the angle array // for each vertex and calculate their projection multiplier // on the x axis // ********************************************** private float[] getXMultiplierArray() { float[] angleArray = getAngleArrays(); float[] xmultiplierArray = new float[sides]; for (int i = 0; i < angleArray.length; i++) { float curAngle = angleArray[i]; float sinvalue = (float) Math.cos(Math.toRadians(curAngle)); float absSinValue = Math.abs(sinvalue); if (isXPositiveQuadrant(curAngle)) { sinvalue = absSinValue; } else { sinvalue = -absSinValue; xmultiplierArray[i] = this.getApproxValue(sinvalue); } } this.printArray(xmultiplierArray, "xmultiplierArray"); return xmultiplierArray; } // ********************************************** // This is where you take the angle array // for each vertex and calculate their projection multiplier // on the y axis // ********************************************** private float[] getYMultiplierArray() { float[] angleArray = getAngleArrays(); float[] ymultiplierArray = new float[sides]; for (int i = 0; i < angleArray.length; i++) { float curAngle = angleArray[i]; float sinvalue = (float) Math.sin(Math.toRadians(curAngle)); float absSinValue = Math.abs(sinvalue); if (isYPositiveQuadrant(curAngle)) { sinvalue = absSinValue; } else { sinvalue = -absSinValue; ymultiplierArray[i] = this.getApproxValue(sinvalue); } } this.printArray(ymultiplierArray, "ymultiplierArray"); return ymultiplierArray; } // ********************************************** // This function may not be needed // Test it yourself and discard it if you dont need // ********************************************** private boolean isXPositiveQuadrant(float angle) { if ((0 <= angle) && (angle <= 90)) { return true; } if ((angle < 0) && (angle >= -90)) { return true; } return false; } // ********************************************** // This function may not be needed // Test it yourself and discard it if you dont need // ********************************************** private boolean isYPositiveQuadrant(float angle) { if ((0 <= angle) && (angle <= 90)) { return true; } if ((angle < 180) && (angle >= 90)) { return true; } return false; } // ********************************************** // This is where you calculate angles // for each line going from center to each vertex // ********************************************** private float[] getAngleArrays() { float[] angleArray = new float[sides]; float commonAngle = 360.0f / sides; float halfAngle = commonAngle / 2.0f; float firstAngle = 360.0f - (90 + halfAngle); angleArray[0] = firstAngle; float curAngle = firstAngle; for (int i = 1; i < sides; i++) { float newAngle = curAngle - commonAngle; angleArray[i] = newAngle; curAngle = newAngle; } printArray(angleArray, "angleArray"); return angleArray; } // ********************************************** // Some rounding if needed // ********************************************** private float getApproxValue(float f) { return (Math.abs(f) < 0.001) ? 0 : f; } // ********************************************** // Return how many Indices you will need // given the number of sides // This is the count of number of triangles needed // to make the polygon multiplied by 3 // It just happens that the number of triangles is // same as the number of sides // ********************************************** public int getNumberOfIndices() { return sides * 3; } public static void test() { RegularPolygon triangle = new RegularPolygon(0, 0, 0, 1, 3); } private void printArray(float array[], String tag) { StringBuilder sb = new StringBuilder(tag); for (int i = 0; i < array.length; i++) { sb.append(";").append(array[i]); } Log.d("hh", sb.toString()); } private void printShortArray(short array[], String tag) { StringBuilder sb = new StringBuilder(tag); for (int i = 0; i < array.length; i++) { sb.append(";").append(array[i]); } Log.d(tag, sb.toString()); } public int getNumberOfSides() { return sides; } @Override public void draw(GL10 gl) { // TODO Auto-generated method stub } @Override public void loadGLTexture() { // TODO Auto-generated method stub } }