Using GLU Tesselator

The primitive structure class.

 /** * A class to store a single OpenGL primitive (ie a triangle, triangle_loop etc.) returned * from the tesselator. * * @author Quew8 */ class Primitive { /**    * The OpenGL constant defining the type of this primitive *     */    public final int type;

/**    * A list of the indices of the vertices required to draw this primitive. *     */    public final ArrayList vertices = new ArrayList<>;

public Primitive(int type) { this.type = type; }

private String getTypeString { switch(type) { case GL11.GL_TRIANGLES: return "GL_TRIANGLES"; case GL11.GL_TRIANGLE_STRIP: return "GL_TRIANGLE_STRIP"; case GL11.GL_TRIANGLE_FAN: return "GL_TRIANGLE_FAN"; default: return Integer.toString(type); }   }

@Override public String toString { String s = "New Primitive " + getTypeString; for(int i = 0; i < vertices.size; i++) { s += "\nIndex: " + vertices.get(i); }       return s;    } }

The Tessellator class.

 /** * A class to interface with the GLU tessellator. * Constructs a series of primitives to draw the complex shape. You describe to it. * * A single instance of this class can be reused as many times as desired. * * @author Quew8 */ class Tessellator extends GLUtessellatorImpl { /**    * A list of the primitives */   public ArrayList primitives = new ArrayList;

public Tessellator { GLUtessellatorCallbackAdapter callback = new GLUtessellatorCallbackAdapter { @Override public void begin(int type) { Tessellator.this.primitives.add(new Primitive(type)); }

@Override public void vertex(Object vertexData) { Integer coords = (Integer) vertexData; Tessellator.this.getLastPrimitive.vertices.add(coords); }

@Override public void error(int errnum) { throw new RuntimeException("GLU Error " + GLU.gluErrorString(errnum)); }

};       this.gluTessCallback(GLU.GLU_TESS_BEGIN, callback); this.gluTessCallback(GLU.GLU_TESS_VERTEX, callback); this.gluTessCallback(GLU.GLU_TESS_ERROR, callback); }

@Override public void gluBeginPolygon { super.gluBeginPolygon; primitives.clear; }

private Primitive getLastPrimitive { return primitives.get(primitives.size - 1); } }

An example of usage - tessellates a quad with a square whole in the middle.

 Tessellator tess = new Tessellator;

double[] verticesC1 = new double[]{ //Vertices of outer quad. 0, 0, 0,   100, 0, 0,    100, 100, 0,    0, 100, 0 }; double[] verticesC2 = new double[]{ //Vertices of inner quad 25, 25, 0,   75, 25, 0,    75, 75, 0,    25, 75, 0 };

tess.gluBeginPolygon;

tess.gluTessBeginContour; tess.gluTessVertex(verticesC1, 0, 0); //Arguments are: vertex coords array, offset into array of vertex, data (in this case vertex                                      //index). For those wishing to impl their own version, data is the vertexData parameter //passed back in the callback method. tess.gluTessVertex(verticesC1, 3, 1); tess.gluTessVertex(verticesC1, 6, 2); tess.gluTessVertex(verticesC1, 9, 3); tess.gluTessEndContour;

tess.gluTessBeginContour; tess.gluTessVertex(verticesC2, 0, 4); tess.gluTessVertex(verticesC2, 3, 5); tess.gluTessVertex(verticesC2, 6, 6); tess.gluTessVertex(verticesC2, 9, 7); tess.gluTessEndContour;

tess.gluEndPolygon; tess.gluDeleteTess; //This tessellator could just as easily be reused.

//Prints out the result of the tessellation. for(int i = 0; i < tess.primitives.size; i++) { System.out.println(tess.primitives.get(i).toString); } //To draw the shape it is now a simple matter to put the vertex data you passed in initially into a VBO, and the indices returned //into an IBO (Index VBO). You have the types of the primitives and the number of indices for each one. Drawing the result should //be a walk in the park, as long as you have read the appropriate tutorials here or elsewhere.