/*********************************************************************** * mt4j Copyright (c) 2008 - 2009 C.Ruff, Fraunhofer-Gesellschaft All rights reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***********************************************************************/ package org.mt4j.util.opengl; import java.util.ArrayList; import java.util.List; import javax.media.opengl.GL; import javax.media.opengl.glu.GLU; import javax.media.opengl.glu.GLUtessellator; import javax.media.opengl.glu.GLUtessellatorCallbackAdapter; import org.mt4j.util.math.Vertex; import processing.core.PApplet; /** * A wrapper class for use of the GLU-Tesselator. * The tesselator can break down a shape made of of vertices into triangles. * By providing information about the objects to tesselate, we can create * polygons with holes, for example. * Can be used to record a displaylist or to tesselate and draw in immediate mode. Opengl drawing commands * are invoked during tesselation. * Only works when using opengl renderer. * * @author C.Ruff */ @Deprecated public class GLuTesselator extends GLUtessellatorCallbackAdapter{ /** The gl. */ private GL gl; /** The glu. */ private GLU glu; /** The tesselator. */ private GLUtessellator tesselator; // private static GLuTesselator instance; /** The last color. */ private double[] lastColor; //TODO Triangle meshes zur�ckggeben!? // when you register a GLU_TESS_EDGE_FLAG (or GLU_TESS_EDGE_FLAG_DATA) callback, the // GLU library converts all triangle strips and triangle fans to simple triangle lists. /** * Creates a new tesselator object and defines callback methods, which the * tesselator will later call. These are defined in this class. * * @param gl the gl * @param glu the glu */ public GLuTesselator(GL gl, GLU glu) { this.gl = gl; this.glu = glu; lastColor = new double[]{-1,-1,-1}; tesselator = glu.gluNewTess(); glu.gluTessCallback(tesselator, GLU.GLU_TESS_VERTEX, this);// glVertex3dv); glu.gluTessCallback(tesselator, GLU.GLU_TESS_BEGIN, this);// beginCallback); glu.gluTessCallback(tesselator, GLU.GLU_TESS_END, this);// endCallback); glu.gluTessCallback(tesselator, GLU.GLU_TESS_COMBINE, this);// combineCallback); glu.gluTessCallback(tesselator, GLU.GLU_TESS_ERROR, this);// errorCallback); } // /** // * // * @param pa // * @return // */ // public static GLuTesselator getInstance(PApplet pa){ // if (instance == null){ // GL gl=((PGraphicsOpenGL)pa.g).gl; // GLU glu = ((PGraphicsOpenGL)pa.g).glu; // instance = new GLuTesselator(gl,glu); // return instance; // }else // return instance; // } /** * Delete tess. */ public void deleteTess(){ glu.gluDeleteTess(tesselator); tesselator = null; // instance = null; } /** * Tesselates the contours, draws it while recording a displaylist and returns * the id of the displaylist for later use. * * @param contours the contours * @param pa the pa * * @return the int */ public int tesselateToDisplayList(List<Vertex[]> contours, PApplet pa){ return tesselateToDisplayList(contours, pa, GLU.GLU_TESS_WINDING_ODD); } /** * Tesselates the contours, draws it while recording a displaylist and returns * the id of the displaylist for later use. * The winding rule determines how the contours are tesselated and which part of * the objects is "inside" and what is "outside". * * @param contours the contours * @param pa the pa * @param windingRule the winding rule * * @return the int */ public int tesselateToDisplayList(List<Vertex[]> contours, PApplet pa, int windingRule){ int listId = gl.glGenLists(1); gl.glNewList(listId, GL.GL_COMPILE); this.tesselate(contours, windingRule); gl.glEndList(); return listId; } /** * Tesselate. * * @param contour the contour * @param windingRule the winding rule */ public void tesselate(Vertex[] contour, int windingRule){ List<Vertex[]> v = new ArrayList<Vertex[]>(); v.add(contour); this.tesselate(v, windingRule); } /** * Tesselate. * * @param contours the contours */ public void tesselate(List<Vertex[]> contours){ this.tesselate(contours, GLU.GLU_TESS_WINDING_ODD); } /** * Tesselate. * * @param contours the contours * @param windingRule the winding rule */ public void tesselate(List<Vertex[]> contours, int windingRule){ glu.gluTessProperty(tesselator, GLU.GLU_TESS_WINDING_RULE, windingRule); // gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); //FIXME TEST! glu.gluTessNormal(tesselator, 0.0, 0.0, 1.0); glu.gluTessBeginPolygon(tesselator, null); //Go through all contours for (Vertex[] varr : contours){ /* glu.gluTessBeginContour(tesselator); //Go through all vertices of the contour for(Vertex v : varr){ double[] pv = {v.x, v.y, 0, v.getR()/255.0, v.getG()/255.0, v.getB()/255.0, v.getA()/255.0}; //{v.x,v.y,v.z}; glu.gluTessVertex(tesselator, pv, 0, pv); } glu.gluTessEndContour(tesselator); */ tesselateContour(varr, windingRule); } glu.gluTessEndPolygon(tesselator); lastColor = new double[]{-1,-1,-1}; } /** * Tesselate contour. * * @param contour the contour * @param windingRule the winding rule */ private void tesselateContour(Vertex[] contour, int windingRule){ glu.gluTessBeginContour(tesselator); for(int i = 0; i < contour.length; i++) { Vertex v = contour[i]; double[] pv = {v.x,v.y,v.z, v.getR()/255.0,v.getG()/255.0,v.getB()/255.0,v.getA()/255.0}; //{v.x,v.y,v.z}; glu.gluTessVertex(tesselator, pv, 0, pv); } glu.gluTessEndContour(tesselator); } //remove? /* (non-Javadoc) * @see javax.media.opengl.glu.GLUtessellatorCallbackAdapter#begin(int) */ public void begin(int type) { gl.glBegin(type); /* switch (type) { case GL.GL_TRIANGLE_FAN: System.out.println("GL_TRIANGLE_FAN"); break; case GL.GL_TRIANGLE_STRIP: System.out.println("GL_TRIANGLE_STRIP"); break; case GL.GL_TRIANGLES:System.out.println("GL_TRIANGLES");break; case GL.GL_POLYGON:System.out.println("GL_TRIANGLES");break; case GL.GL_POINTS: System.out.println("GL_POINTS"); break; case GL.GL_LINES: System.out.println("GL_LINES"); break; case GL.GL_LINE_LOOP: System.out.println("GL_LINE_LOOP"); break; case GL.GL_LINE_STRIP: System.out.println("GL_LINE_STRIP"); break; case GL.GL_QUADS :System.out.println("GL_QUADS");break; case GL.GL_QUAD_STRIP:System.out.println("GL_QUAD_STRIP");break; default: System.out.println("OTHER?!"); break; } */ } //TODO rather save the vertex data in a list for later use, but we //would have to remember which drawing mode the tesselator inteded //the vertices for.. /** * Callback function. * Gets called by the tesselator when a new vertex should * be drawn. * * @param vertexData the vertex data */ public void vertex(Object vertexData) { // double[] dv = (double[]) vertexData; // gl.glColor4d(dv[3], dv[4], dv[5], dv[6]); //System.out.println(((double[]) vertexData).length); // /* double[] pointer; if (vertexData instanceof double[]){ pointer = (double[]) vertexData; if (pointer.length == 7){ //Set color only if different from last set color if ( lastColor[0] != pointer[3] || lastColor[1] != pointer[4] || lastColor[2] != pointer[5]){ //Set new color gl.glColor4dv(pointer, 3); lastColor[0] = pointer[3]; lastColor[1] = pointer[4]; lastColor[2] = pointer[5]; } // gl.glColor4dv(pointer, 3); } gl.glVertex3dv(pointer, 0); } // */ } /* (non-Javadoc) * @see javax.media.opengl.glu.GLUtessellatorCallbackAdapter#vertexData(java.lang.Object, java.lang.Object) */ @Override public void vertexData(Object vertexData, Object polygonData) { /* if (polygonData instanceof Vertex){ Vertex v = (Vertex)polygonData; gl.glColor4f(v.getR()/255,v.getG()/255,v.getB()/255,v.getA()/255); } gl.glVertex3dv((double[]) vertexData, 0); */ // double[] dv = (double[]) vertexData; // gl.glVertex3d(dv[0],dv[1],dv[2]); // double[] dv = (double[]) polygonData; // gl.glColor4d(dv[4], dv[5], dv[6], dv[7]); // gl.glVertex3dv((double[]) vertexData, 0); } /** * CombineCallback is used to create a new vertex when edges intersect. * coordinate location is trivial to calculate, but weight[4] may be * used to average color, normal, or texture coordinate data. * <p> * This is called before the call to the vertex-callback method, * * @param coords the coords * @param data the data * @param weight the weight * @param outData the out data */ public void combine(double[] coords, Object[] data, float[] weight, Object[] outData) { // double[] vertex = new double[3]; // vertex[0] = coords[0]; // vertex[1] = coords[1]; // vertex[2] = coords[2]; // // outData[0] = vertex; //TODO calculate weighted normal!? //Interpolate the new vertix' color with the 4 intersecting verts double[] vertex = new double[7]; vertex[0] = coords[0]; vertex[1] = coords[1]; vertex[2] = coords[2]; vertex[3] = weight[0]*((double[]) data[0])[3] + weight[1]*((double[]) data[0])[3] + weight[2]*((double[]) data[0])[3] + weight[3]*((double[]) data[0])[3]; vertex[4] = weight[0]*((double[]) data[0])[4] + weight[1]*((double[]) data[0])[4] + weight[2]*((double[]) data[0])[4] + weight[3]*((double[]) data[0])[4]; vertex[5] = weight[0]*((double[]) data[0])[5] + weight[1]*((double[]) data[0])[5] + weight[2]*((double[]) data[0])[5] + weight[3]*((double[]) data[0])[5]; vertex[6] = weight[0]*((double[]) data[0])[6] + weight[1]*((double[]) data[0])[6] + weight[2]*((double[]) data[0])[6] + weight[3]*((double[]) data[0])[6]; outData[0] = vertex; } /* (non-Javadoc) * @see javax.media.opengl.glu.GLUtessellatorCallbackAdapter#end() */ public void end() { gl.glEnd(); } /* (non-Javadoc) * @see javax.media.opengl.glu.GLUtessellatorCallbackAdapter#error(int) */ public void error(int errnum) { System.err.println("Tessellation Error: " + glu.gluErrorString(errnum)); // System.exit(0); } /** * Gets the tesselator. * * @return the tesselator */ public GLUtessellator getTesselator(){ return this.tesselator; } }