PageRenderTime 143ms CodeModel.GetById 53ms app.highlight 79ms RepoModel.GetById 1ms app.codeStats 1ms

/src/org/mt4j/util/math/Tools3D.java

http://mt4j.googlecode.com/
Java | 1408 lines | 637 code | 183 blank | 588 comment | 71 complexity | f4dedd5419765516ac5df65df788400b MD5 | raw file
   1/***********************************************************************
   2 * mt4j Copyright (c) 2008 - 2009 C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
   3 *  
   4 *   This program is free software: you can redistribute it and/or modify
   5 *   it under the terms of the GNU General Public License as published by
   6 *   the Free Software Foundation, either version 3 of the License, or
   7 *   (at your option) any later version.
   8 *
   9 *   This program is distributed in the hope that it will be useful,
  10 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 *   GNU General Public License for more details.
  13 *
  14 *   You should have received a copy of the GNU General Public License
  15 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16 *
  17 ***********************************************************************/
  18package org.mt4j.util.math;
  19
  20import java.nio.ByteBuffer;
  21import java.nio.ByteOrder;
  22import java.nio.DoubleBuffer;
  23import java.nio.FloatBuffer;
  24import java.nio.IntBuffer;
  25import java.util.List;
  26import java.util.StringTokenizer;
  27
  28import javax.media.opengl.GL;
  29import javax.media.opengl.glu.GLU;
  30
  31import org.mt4j.MTApplication;
  32import org.mt4j.components.interfaces.IMTComponent3D;
  33import org.mt4j.components.visibleComponents.StyleInfo;
  34import org.mt4j.components.visibleComponents.shapes.GeometryInfo;
  35import org.mt4j.input.inputData.InputCursor;
  36import org.mt4j.util.MT4jSettings;
  37import org.mt4j.util.camera.IFrustum;
  38import org.mt4j.util.camera.Icamera;
  39import org.mt4j.util.opengl.GLTexture;
  40
  41import processing.core.PApplet;
  42import processing.core.PGraphics;
  43import processing.core.PGraphics3D;
  44import processing.core.PImage;
  45import processing.core.PMatrix3D;
  46import processing.opengl.PGraphicsOpenGL;
  47
  48
  49/**
  50 * Class containing mostly static convenience utility methods.
  51 * 
  52 * @author Christopher Ruff
  53 */
  54public class Tools3D {
  55	//Declared here and static so it wont have to be initialize at every call to unproject
  56	/** The fb. */
  57	private static FloatBuffer fb = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asFloatBuffer();
  58	
  59	/** The fb un. */
  60	private static FloatBuffer fbUn = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asFloatBuffer();
  61	
  62	/** The model. */
  63	private static DoubleBuffer model;
  64	
  65	/** The proj. */
  66	private static DoubleBuffer proj;
  67	
  68	/** The view. */
  69	private static IntBuffer view;
  70	
  71	/** The win pos. */
  72	private static DoubleBuffer winPos;
  73	
  74	static{
  75		model 	= DoubleBuffer.allocate(16);
  76		proj 	= DoubleBuffer.allocate(16);
  77		view 	= IntBuffer.allocate(4);
  78		winPos 	= DoubleBuffer.allocate(3);
  79	}
  80	
  81	
  82	/**
  83	 * Unprojects screen coordinates from 2D into 3D world space and returns a point that
  84	 * can be used to construct a ray form the camera to that point and check
  85	 * for intersections with objects.
  86	 * <p><b>NOTE</b>: if using openGL mode, the openGL context has to be valid at the time of calling this method.
  87	 * 
  88	 * @param applet the applet
  89	 * @param camera the camera
  90	 * @param screenX the screen x
  91	 * @param screenY the screen y
  92	 * 
  93	 * @return the vector3d
  94	 */
  95	public static Vector3D unprojectScreenCoords(PApplet applet, Icamera camera, float screenX, float screenY ){
  96		Vector3D ret;
  97		applet.pushMatrix();
  98		camera.update();
  99		ret = Tools3D.unprojectScreenCoords(applet, screenX, screenY);
 100		applet.popMatrix();
 101		return ret;
 102	}
 103	
 104	/**
 105	 * Unprojects screen coordinates from 2D into 3D world space and returns a point that
 106	 * can be used to construct a ray form the camera to that point and check
 107	 * for intersections with objects.
 108	 * <p><b>NOTE</b>: if using openGL mode, the openGL context has to be valid at the time of calling this method.
 109	 * 
 110	 * @param applet processings PApplet object
 111	 * @param screenX x coordinate on the screen
 112	 * @param screenY y coordinate on the screen
 113	 * 
 114	 * @return a point that lies on the line from the screen coordinates
 115	 * to the 3d world coordinates
 116	 */
 117	public static Vector3D unprojectScreenCoords(PApplet applet, float screenX, float screenY ){ //FIXME MAKE PRIVATE AGAIN! 
 118		Vector3D returnVect = new Vector3D(-999,-999,-999); //null?
 119		
 120//		MT4jSettings.getInstance().setRendererMode(MT4jSettings.P3D_MODE);
 121		
 122		switch (MT4jSettings.getInstance().getRendererMode()) {
 123		case MT4jSettings.OPENGL_MODE:
 124			int viewport[] = new int[4];
 125			double[] proj  = new double[16];
 126			double[] model = new double[16];
 127			double[] mousePosArr = new double[4];
 128			
 129			try{
 130			PGraphicsOpenGL pgl = ((PGraphicsOpenGL)applet.g); 
 131			GL gl = pgl.beginGL();  
 132			GLU glu = pgl.glu;
 133			
 134				  gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
 135				  gl.glGetDoublev(GL.GL_PROJECTION_MATRIX, proj, 0);
 136				  gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, model, 0);
 137				  
 138				  /*
 139				  System.out.println("OpenGL ProjectionMatrix: ");
 140				  for (int i = 0; i < proj.length; i++) {
 141						double p = proj[i];
 142						System.out.print(p + ", ");
 143						//if (i%4 == 0 && i==3)
 144						if (i==3 || i== 7 || i== 11 || i==15) {
 145							System.out.println();
 146						}
 147					  }
 148				  */
 149				  
 150				  /*
 151				  System.out.println("OpenGL ModelviewMatrix: ");
 152				  for (int i = 0; i < model.length; i++) {
 153						double p = model[i];
 154						System.out.print(p + ", ");
 155						//if (i%4 == 0 && i==3)
 156						if (i==3 || i== 7 || i== 11 || i==15) {
 157							System.out.println();
 158						}
 159					  }
 160				  System.out.println();
 161				  System.out.println("\n");
 162				  */
 163				  
 164				  /*
 165				  fbUn.clear();
 166				  gl.glReadPixels((int)screenX, applet.height - (int)screenY, 1, 1, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT, fbUn);
 167				  fbUn.rewind();
 168				  glu.gluUnProject((double)screenX, applet.height - (double)screenY, (double)fbUn.get(0), model, 0, proj, 0, viewport, 0, mousePosArr, 0);
 169				  */
 170				  
 171				  //FIXME test not using glReadpixel to get the depth at the location
 172				  //instead we have to build a ray with the result, from the camera location going through the resulst and check for hits ourselves
 173				  glu.gluUnProject((double)screenX, applet.height - (double)screenY, 0, model, 0, proj, 0, viewport, 0, mousePosArr, 0);
 174			  pgl.endGL();
 175			  
 176			  returnVect = new Vector3D((float)mousePosArr[0], (float)mousePosArr[1], (float)mousePosArr[2]);
 177			}catch(Exception e){
 178				e.printStackTrace();
 179				//System.out.println("Use method getWorldForScreenCoords only when drawing with openGL! And dont put negative screen values in!");
 180			}
 181			break;
 182		case MT4jSettings.P3D_MODE:
 183//			/*!
 184			try{
 185				Vector3D testpoint = new Vector3D(screenX, screenY, 1); //TEST! is 1 as winZ correct? -> or read from depth buffer at that pixel!
 186				
 187//				PMatrix modelView = new PMatrix(applet.g.getmodelview);
 188//				PMatrix projectionM = new PMatrix(applet.g.projection);
 189				
 190				//projectionsmatrix mit modelview multiplizieren 
 191//				projectionM.apply(modelView);
 192				
 193				//Ergebnis invertieren
 194//				PMatrix inv = projectionM.invert();
 195				
 196				PMatrix3D modelView 	= new PMatrix3D(applet.g.getMatrix());
 197				PMatrix3D projectionM 	= new PMatrix3D(((PGraphics3D)applet.g).projection);
 198				
 199				projectionM.apply(modelView);
 200				projectionM.invert();
 201				
 202				float[] result = new float[4];
 203				float[] factor = new float[]{  ((2 * testpoint.getX())  / applet.width)  -1,
 204											   ((2 * testpoint.getY())  / applet.height) -1, //screenH - y?
 205												(2 * testpoint.getZ()) -1 ,
 206												 1,};
 207				//Matrix mit Vector multiplizieren
 208				projectionM.mult(factor, result);
 209				
 210				//System.out.println("\nResult2: ");
 211				for (int i = 0; i < result.length; i++) {
 212					//W auf 1 machen!?
 213					result[i] /= result[result.length-1]; //normalize so w(4th coord) is 1
 214					//System.out.print(result[i] + " ");
 215				}
 216				
 217				//aus Result Vector3D machen
 218				returnVect = new Vector3D(result[0],result[1],result[2]);
 219			}catch(Exception e){
 220				e.printStackTrace();
 221			}
 222			break;
 223//			*/
 224		default:
 225			break;
 226		} 
 227//		System.out.println(returnVect);
 228		return returnVect;
 229	} 
 230	
 231	
 232	/**
 233	 * Gets the ray to pick this component.
 234	 *
 235	 * @param applet the applet
 236	 * @param component the component
 237	 * @param cursor the cursor
 238	 * @return the camera pick ray
 239	 */
 240	public static Ray getCameraPickRay(PApplet applet, IMTComponent3D component, InputCursor cursor){
 241		return Tools3D.getCameraPickRay(applet, component.getViewingCamera(), cursor.getCurrentEvtPosX(), cursor.getCurrentEvtPosY());
 242	}
 243	
 244	/**
 245	 * Constructs a picking ray from the components viewing camera position
 246	 * through the specified screen coordinates.
 247	 * The viewing camera of the object may not be null!
 248	 * <p><b>NOTE</b>: the openGL context has to be valid at the time of calling this method.
 249	 * 
 250	 * @param applet the applet
 251	 * @param component the component
 252	 * @param screenX the screen x
 253	 * @param screenY the screen y
 254	 * 
 255	 * @return the pick ray
 256	 */
 257	public static Ray getCameraPickRay(PApplet applet, IMTComponent3D component, float screenX, float screenY ){
 258		return Tools3D.getCameraPickRay(applet, component.getViewingCamera(), screenX, screenY);
 259	}
 260	
 261	/**
 262	 * Constructs a picking ray from the components viewing camera position
 263	 * through the specified screen coordinates.
 264	 * <p><b>NOTE</b>: the openGL context has to be valid at the time of calling this method.
 265	 * 
 266	 * @param applet the applet
 267	 * @param screenX the screen x
 268	 * @param screenY the screen y
 269	 * @param camera the camera
 270	 * 
 271	 * @return the pick ray
 272	 */
 273	public static Ray getCameraPickRay(PApplet applet, Icamera camera, float screenX, float screenY ){
 274		Vector3D rayStartPoint 		= camera.getPosition();
 275		Vector3D newPointInRayDir 	=  Tools3D.unprojectScreenCoords(applet, camera, screenX, screenY);
 276		return new Ray(rayStartPoint, newPointInRayDir);
 277	}
 278	
 279	
 280	
 281	/**
 282	 * Projects the given point to screenspace.
 283	 * <br>Shows where on the screen the point in 3d-Space will appear according
 284	 * to the current viewport, model and projection matrices.
 285	 * <p><b>NOTE</b>: the openGL context has to be valid at the time of calling this method.
 286	 * 
 287	 * @param gl the gl
 288	 * @param glu the glu
 289	 * @param point the point to project to the screen
 290	 * 
 291	 * @return the vector3 d
 292	 */
 293	public static Vector3D projectGL(GL gl, GLU glu, Vector3D point){
 294		return projectGL(gl, glu, point, null);
 295	}
 296	
 297	/**
 298	 * Projects the given point to screenspace.
 299	 * <br>Shows where on the screen the point in 3d-Space will appear according
 300	 * to the current viewport, model and projection matrices.
 301	 * <br><strong>Note</strong>: this method has to be called between a call to <code>processingApplet.beginGL()</code>
 302	 * and <code>processingApplet.endGL()</code>
 303	 * <p><b>NOTE</b>: the openGL context has to be valid at the time of calling this method.
 304	 * 
 305	 * @param gl the gl
 306	 * @param glu the glu
 307	 * @param point the point
 308	 * @param store the store - vector to store the result in or null to get a new vector
 309	 * 
 310	 * @return the vector3 d
 311	 */
 312	public static Vector3D projectGL(GL gl, GLU glu, Vector3D point, Vector3D store){
 313		if (store == null){
 314			store = new Vector3D();
 315		}
 316		
 317		model.clear();
 318		gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, model);
 319		
 320		proj.clear();
 321		gl.glGetDoublev(GL.GL_PROJECTION_MATRIX, proj);
 322		
 323		view.clear();
 324		gl.glGetIntegerv(GL.GL_VIEWPORT, view);
 325		float viewPortHeight = (float)view.get(3);
 326		
 327		winPos.clear();
 328		glu.gluProject(point.x, point.y, point.z, model, proj, view, winPos);
 329		
 330		winPos.rewind();
 331		float x = (float) winPos.get();
 332		float y = (float) winPos.get();
 333		y = viewPortHeight - y;			// Subtract The Current Y Coordinate From The Screen Height.
 334		
 335		store.setXYZ(x, y, 0);
 336		return store;
 337//		return new Vector3D(x, y, 0);
 338	}
 339	
 340	
 341	/**
 342	 * Projects the given 3D point to screenspace.
 343	 * <br>Shows where on the screen the point in 3d-Space will appear according
 344	 * to the supplied camera, viewport, and projection matrices.
 345	 * The modelview is temporarily changed to match the supplied camera matrix.
 346	 * 
 347	 * @param applet the applet
 348	 * @param cam the cam
 349	 * @param point the point
 350	 * 
 351	 * @return the vector3 d
 352	 */
 353	public static Vector3D project(PApplet applet, Icamera cam, Vector3D point){
 354		Vector3D ret;
 355		applet.pushMatrix();
 356		cam.update();
 357		ret = Tools3D.project(applet, point);	
 358		applet.popMatrix();
 359		return ret;
 360	}
 361	
 362	
 363	/**
 364	 * Projects the given point to screenspace. Uses the current modelview, and projection matrices - so update
 365	 * them accordingly before calling!
 366	 * <br>Shows where on the screen the point in 3d-Space will appear according
 367	 * to the current viewport, model and projection matrices.
 368	 * <p><b>NOTE</b>: if using openGL mode, the openGL context has to be valid at the time of calling this method.
 369	 * 
 370	 * @param applet the applet
 371	 * @param point the point
 372	 * 
 373	 * @return a new projected vector3d
 374	 */
 375	public static Vector3D project(PApplet applet, Vector3D point){
 376		switch (MT4jSettings.getInstance().getRendererMode()) {
 377		case MT4jSettings.OPENGL_MODE:
 378			try{ 
 379				PGraphicsOpenGL pgl = ((PGraphicsOpenGL)applet.g); 
 380				GL gl 	= pgl.beginGL();  
 381				GLU glu = pgl.glu;
 382				Vector3D returnVect = projectGL(gl, glu, point);
 383				pgl.endGL();
 384				return returnVect;
 385			}catch(Exception e){
 386				e.printStackTrace();
 387				//System.out.println("Use method getWorldForScreenCoords only when drawing with openGL! And dont put negative screen values in!");
 388			}
 389			break;
 390		case MT4jSettings.P3D_MODE:
 391//			/*!
 392			try{
 393				float x = applet.screenX(point.x, point.y, point.z);
 394				float y = applet.screenY(point.x, point.y, point.z);
 395				float z = applet.screenZ(point.x, point.y, point.z);
 396				return new Vector3D(x,y,z);
 397			}catch(Exception e){
 398				e.printStackTrace();
 399			}
 400			break;
 401//			*/
 402		default:
 403			return new Vector3D(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
 404		} 
 405		return new Vector3D(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
 406	}
 407	
 408	/**
 409	 * Start drawing in on TOP of everything drawn previously,
 410	 * also resets the camera, so that something drawn at 0,0,0
 411	 * will be drawn at the top left corner of the screen regardless
 412	 * of the camera used
 413	 * 
 414	 * You could say this allows you to draw directly on the screen, and
 415	 * on top of everything else. (at the near clipping plane?)
 416	 * 
 417	 * NOTE: you have to CALL endDrawOnTopStayOnScreen() if finished!
 418	 * 
 419	 * @param pa the pa
 420	 */
 421	public static void beginDrawOnTopStayOnScreen(PApplet pa){
 422		switch (MT4jSettings.getInstance().getRendererMode()) {
 423		case MT4jSettings.OPENGL_MODE:
 424			GL gl = ((PGraphicsOpenGL)pa.g).gl; 
 425			gl.glDepthFunc(javax.media.opengl.GL.GL_ALWAYS); //turn off Z buffering
 426			//reset to the default camera
 427			pa.camera(); 
 428			break;
 429		case MT4jSettings.P3D_MODE:
 430			for(int i=0;i<((PGraphics3D)pa.g).zbuffer.length;i++){
 431			  ((PGraphics3D)pa.g).zbuffer[i]=Float.MAX_VALUE;
 432			}
 433			pa.camera();
 434			break;
 435		default:
 436			break;
 437		}
 438	}
 439	
 440	/**
 441	 * Stop drawing in 2D after calling begin2D().
 442	 * 
 443	 * @param pa the pa
 444	 * @param camera the camera
 445	 */
 446	public static void endDrawOnTopStayOnScreen(PApplet pa, Icamera camera){
 447		switch (MT4jSettings.getInstance().getRendererMode()) {
 448		case MT4jSettings.OPENGL_MODE:
 449			GL gl = ((PGraphicsOpenGL)pa.g).gl; 
 450			gl.glDepthFunc(GL.GL_LEQUAL); //This is used by standart processing..
 451			//Change camera back to current 3d camera
 452			camera.update();
 453			break;
 454		case MT4jSettings.P3D_MODE:
 455			camera.update();
 456			break;
 457		default:
 458			break;
 459		}
 460	}
 461	
 462	/**
 463	 * Allows to draw ontop of everything, regardless of the values in the z-buffer.
 464	 * To stop doing that, call <code>endDrawOnTop(PApplet pa)</code> .
 465	 * 
 466	 * @param g the g
 467	 */
 468	public static void disableDepthBuffer(PGraphics g){ 
 469		switch (MT4jSettings.getInstance().getRendererMode()) {
 470		case MT4jSettings.OPENGL_MODE:
 471//			GL gl = ((PGraphicsOpenGL)pa.g).gl;
 472			GL gl = ((PGraphicsOpenGL)g).gl;
 473			gl.glPushAttrib(GL.GL_DEPTH_BUFFER_BIT);//FIXME TEST
 474			gl.glDepthFunc(javax.media.opengl.GL.GL_ALWAYS); //turn off Z buffering
 475			break;
 476		case MT4jSettings.P3D_MODE:
 477//			/*
 478//			for(int i=0;i<((PGraphics3D)pa.g).zbuffer.length;i++){
 479//			  ((PGraphics3D)pa.g).zbuffer[i]=Float.MAX_VALUE;
 480//			}
 481			for(int i=0;i<((PGraphics3D)g).zbuffer.length;i++){
 482				  ((PGraphics3D)g).zbuffer[i]=Float.MAX_VALUE;
 483				}
 484//			*/ 
 485			break;
 486		default:
 487			break;
 488		}
 489	}
 490	
 491	/**
 492	 * End draw on top.
 493	 * 
 494	 * @param g the g
 495	 */
 496	public static void restoreDepthBuffer(PGraphics g){ 
 497		switch (MT4jSettings.getInstance().getRendererMode()) {
 498		case MT4jSettings.OPENGL_MODE:
 499			GL gl = ((PGraphicsOpenGL)g).gl;
 500//			gl.glDepthFunc(GL.GL_LEQUAL); //This is used by standart processing..
 501			//FIXME TEST
 502			gl.glPopAttrib(); 
 503			break;
 504		case MT4jSettings.P3D_MODE:
 505			break;
 506		default:
 507			break;
 508		}
 509	}
 510	
 511	
 512
 513
 514	//////////////////////////////////////////////////////////
 515	//  OPENGL STUFF										//
 516	//////////////////////////////////////////////////////////
 517	
 518	
 519	
 520	/**
 521	 * Prints some available openGL extensions to the console.
 522	 * <p><b>NOTE</b>: the openGL context has to be valid at the time of calling this method.
 523	 * 
 524	 * @param pa the pa
 525	 */
 526	public static void printGLExtensions(PApplet pa){
 527		if (!MT4jSettings.getInstance().isOpenGlMode())
 528			return;
 529		GL gl =((PGraphicsOpenGL)pa.g).beginGL();
 530		String ext = gl.glGetString(GL.GL_EXTENSIONS);
 531		StringTokenizer tok = new StringTokenizer( ext, " " );
 532		while (tok.hasMoreTokens()) {
 533			System.out.println(tok.nextToken());
 534		}
 535		 int[] redBits 		= new int[1];
 536         int[] greenBits 	= new int[1];
 537         int[] blueBits 	= new int[1];
 538         int[] alphaBits 	= new int[1];
 539         int[] stencilBits 	= new int[1];
 540         int[] depthBits 	= new int[1];
 541         gl.glGetIntegerv(GL.GL_RED_BITS, redBits,0);
 542         gl.glGetIntegerv(GL.GL_GREEN_BITS, greenBits,0);
 543         gl.glGetIntegerv(GL.GL_BLUE_BITS, blueBits,0);
 544         gl.glGetIntegerv(GL.GL_ALPHA_BITS, alphaBits,0);
 545         gl.glGetIntegerv(GL.GL_STENCIL_BITS, stencilBits,0);
 546         gl.glGetIntegerv(GL.GL_DEPTH_BITS, depthBits,0);
 547		System.out.println("Red bits: " + redBits[0]);
 548		System.out.println("Green bits: " + greenBits[0]);
 549		System.out.println("Blue bits: " + blueBits[0]);
 550		System.out.println("Alpha bits: " + blueBits[0]);
 551		System.out.println("Depth Buffer bits: " + depthBits[0]);
 552		System.out.println("Stencil Buffer bits: " + stencilBits[0]);
 553		((PGraphicsOpenGL)pa.g).endGL();
 554	}
 555	
 556		
 557		/**
 558		 * Check for gl error.
 559		 * 
 560		 * @param gl the gl
 561		 */
 562		public static int getGLError(GL gl){
 563			int error = gl.glGetError();
 564			if (error != GL.GL_NO_ERROR){
 565				System.out.println("GL Error: " + error);
 566			}else{
 567	//			System.out.println("No gl error.");
 568			}
 569			return error;
 570		}
 571
 572
 573		/**
 574		 * Gets the openGL context.
 575		 * <br>NOTE: If you want to invoke any opengl drawing commands (or other commands influencing or depending on the current modelview matrix)
 576		 * you have to call GL <code>Tools3D.beginGL(PApplet pa)</code> instead!
 577		 * <br>NOTE: the openGL context is only valid and current when the rendering thread is the current thread.
 578		 * <br>
 579		 * This only gets the opengl context if started in opengl mode using the opengl renderer.
 580		 * 
 581		 * @param pa the pa
 582		 * 
 583		 * @return the gL
 584		 */
 585		public static GL getGL(PApplet pa){
 586			return ((PGraphicsOpenGL)pa.g).gl;
 587		}
 588		
 589		
 590		public static GL getGL(PGraphics g){
 591			return ((PGraphicsOpenGL)g).gl;
 592		}
 593
 594	
 595	/**
 596	 * Begin gl.
 597	 * 
 598	 * @param pa the pa
 599	 * @return the gL
 600	 */
 601	public static GL beginGL(PApplet pa){
 602		return ((PGraphicsOpenGL)pa.g).beginGL();
 603	}
 604	
 605	/**
 606	 * Begin gl.
 607	 *
 608	 * @param g the g
 609	 * @return the gL
 610	 */
 611	public static GL beginGL(PGraphics g){
 612		return ((PGraphicsOpenGL)g).beginGL();
 613	}
 614
 615	
 616	/**
 617	 * End gl.
 618	 * 
 619	 * @param pa the pa
 620	 */
 621	public static void endGL(PApplet pa){
 622		((PGraphicsOpenGL)pa.g).endGL();
 623	}
 624	
 625	/**
 626	 * End gl.
 627	 *
 628	 * @param g the g
 629	 */
 630	public static void endGL(PGraphics g){
 631		((PGraphicsOpenGL)g).endGL();
 632	}
 633
 634
 635
 636	/**
 637	 * Checks whether the given extension is supported by the current opengl context.
 638	 * <p><b>NOTE</b>: the openGL context has to be valid at the time of calling this method.
 639	 * 
 640	 * @param pa the pa
 641	 * @param extensionName the extension name
 642	 * 
 643	 * @return true, if checks if is gl extension supported
 644	 */
 645	public static boolean isGLExtensionSupported(PApplet pa, String extensionName){
 646		if (!MT4jSettings.getInstance().isOpenGlMode())
 647			return false;
 648		
 649		GL gl =((PGraphicsOpenGL)pa.g).gl;
 650		boolean avail = gl.isExtensionAvailable(extensionName);
 651		/*
 652		String ext = gl.glGetString(GL.GL_EXTENSIONS);
 653		*/
 654		return(avail);
 655	}
 656	
 657	/**
 658	 * Checks whether non power of two texture dimensions are natively supported
 659	 * by the gfx hardware.
 660	 * 
 661	 * @param pa the pa
 662	 * 
 663	 * @return true, if supports non power of two texture
 664	 */
 665	public static boolean supportsNonPowerOfTwoTexture(PApplet pa){
 666		boolean supports = false;
 667		if (	Tools3D.isGLExtensionSupported(pa, "GL_TEXTURE_RECTANGLE_ARB")
 668			|| 	Tools3D.isGLExtensionSupported(pa, "GL_ARB_texture_non_power_of_two")
 669			|| 	Tools3D.isGLExtensionSupported(pa, "GL_ARB_texture_rectangle")
 670			|| 	Tools3D.isGLExtensionSupported(pa, "GL_NV_texture_rectangle")
 671			|| 	Tools3D.isGLExtensionSupported(pa, "GL_TEXTURE_RECTANGLE_EXT")
 672			|| 	Tools3D.isGLExtensionSupported(pa, "GL_EXT_texture_rectangle")
 673		){
 674			supports = true;
 675		}
 676			return supports;
 677	}
 678
 679
 680	/**
 681	 * Sets the opengl vertical syncing on or off.
 682	 * 
 683	 * @param pa the pa
 684	 * @param on the on
 685	 */
 686	public static void setVSyncing(PApplet pa, boolean on){
 687		if (MT4jSettings.getInstance().getRendererMode() == MT4jSettings.OPENGL_MODE){
 688			GL gl = getGL(pa); 
 689			if (on){
 690				gl.setSwapInterval(1);
 691			}else{
 692				gl.setSwapInterval(0);
 693			}
 694		}
 695	}
 696
 697
 698	public static void setLineSmoothEnabled(GL gl, boolean enable){
 699	//    	/*
 700	    	//DO this if we use multisampling and enable line_smooth from the beginning 
 701	    	//and use multisampling -> we turn off multisampling then before using line_smooth for best restult
 702	    	if (enable){
 703	    		if (MT4jSettings.getInstance().isMultiSampling()){
 704					gl.glDisable(GL.GL_MULTISAMPLE);
 705				}
 706	    		//TODO Eventually even dont do that since enabled form the beginning!
 707	    		gl.glEnable(GL.GL_LINE_SMOOTH); 
 708	    	}else{
 709	    		if (MT4jSettings.getInstance().isMultiSampling()){
 710					gl.glEnable(GL.GL_MULTISAMPLE);
 711				}
 712	//    		gl.glDisable(GL.GL_LINE_SMOOTH); //Actually never disable line smooth
 713	    	}
 714	//    	*/
 715	    	
 716	    	//DO nothing if we use Multisampling but disable line_smooth from the beginning
 717	    	// -> do all anti aliasing only through multisampling!
 718	    	//
 719	    	/*
 720	    	if (enable){
 721	    		if (MT4jSettings.getInstance().isMultiSampling()){
 722					gl.glDisable(GL.GL_MULTISAMPLE);
 723				}
 724	    		//TODO Eventually even dont do that since enabled form the beginning!
 725	    		gl.glEnable(GL.GL_LINE_SMOOTH); 
 726	    	}else{
 727	    		if (MT4jSettings.getInstance().isMultiSampling()){
 728					gl.glEnable(GL.GL_MULTISAMPLE);
 729				}
 730	//    		gl.glDisable(GL.GL_LINE_SMOOTH); //Actually never disable line smooth
 731	    	}
 732	    	*/
 733	    }
 734
 735
 736	/**
 737	 * Gen stencil display list gradient.
 738	 * <p><b>NOTE</b>: the openGL context has to be valid at the time of calling this method.
 739	 * 
 740	 * @param pa the pa
 741	 * @param vertBuff the vert buff
 742	 * @param tbuff the tbuff
 743	 * @param colorBuff the color buff
 744	 * @param strokeColBuff the stroke col buff
 745	 * @param indexBuff the index buff
 746	 * @param drawSmooth the draw smooth
 747	 * @param strokeWeight the stroke weight
 748	 * @param vertexArr the vertex arr
 749	 * @param outLines the out lines
 750	 * @param x1R the x1 r
 751	 * @param x1G the x1 g
 752	 * @param x1B the x1 b
 753	 * @param x1A the x1 a
 754	 * @param x2R the x2 r
 755	 * @param x2G the x2 g
 756	 * @param x2B the x2 b
 757	 * @param x2A the x2 a
 758	 * @param x3R the x3 r
 759	 * @param x3G the x3 g
 760	 * @param x3B the x3 b
 761	 * @param x3A the x3 a
 762	 * @param x4R the x4 r
 763	 * @param x4G the x4 g
 764	 * @param x4B the x4 b
 765	 * @param x4A the x4 a
 766	 * @param useGradient the use gradient
 767	 * 
 768	 * @return the int[]
 769	 */
 770	public static int[] genStencilDisplayListGradient(PApplet pa, FloatBuffer vertBuff, FloatBuffer tbuff, 
 771			FloatBuffer colorBuff, FloatBuffer strokeColBuff, IntBuffer indexBuff, 
 772			boolean drawSmooth, float strokeWeight, Vertex[] vertexArr, List<Vertex[]> outLines,
 773			float x1R, float x1G, float x1B, float x1A, float x2R, float x2G, float x2B, float x2A,
 774			float x3R, float x3G, float x3B, float x3A, float x4R, float x4G, float x4B, float x4A,
 775			boolean useGradient
 776		)
 777	{
 778		GL gl=((PGraphicsOpenGL)pa.g).beginGL();
 779		
 780		/*
 781		//Unbind any VBOs first
 782		gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, 0);
 783		gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
 784		*/
 785		
 786		//Generate new list IDs
 787		int[] returnVal = new int[2];
 788		int listIDFill = gl.glGenLists(1);
 789		if (listIDFill == 0){
 790			System.err.println("Failed to create display list");
 791			returnVal[0] = -1;
 792			returnVal[1] = -1;
 793			return returnVal;
 794		}
 795		int listIDOutline = gl.glGenLists(1);
 796		if (listIDOutline == 0){
 797			System.err.println("Failed to create display list");
 798			returnVal[0] = -1;
 799			returnVal[1] = -1;
 800			return returnVal;
 801		}
 802		
 803	    float[] minMax = ToolsGeometry.getMinXYMaxXY(vertexArr);
 804	    float minX = minMax[0]-10;
 805	    float minY = minMax[1]-10;
 806	    float maxX = minMax[2]+10;
 807	    float maxY = minMax[3]+10;
 808	    
 809	    gl.glColor4d (0.0, 0.0, 0.0, 1.0);
 810	    
 811	    gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
 812		gl.glEnableClientState(GL.GL_COLOR_ARRAY);
 813		
 814		gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertBuff);
 815		gl.glColorPointer(4, GL.GL_FLOAT, 0, colorBuff);
 816		
 817		//Using the strokecolor buffer strokecolor AND fill!
 818		
 819		//Generate List
 820		gl.glNewList(listIDFill, GL.GL_COMPILE);
 821			/////////////////////////////////////
 822			// Clear stencil and disable color //
 823		    // Draw with STENCIL			   //
 824		    /////////////////////////////////////
 825//			/*
 826			gl.glClearStencil(0);
 827			gl.glColorMask(false,false,false,false);
 828			gl.glDisable(GL.GL_BLEND);
 829			
 830			gl.glDepthMask(false);//remove..?
 831			
 832			//FIXME do this for non-zero rule?
 833//			gl.glColorMask(true,true,true,true);
 834//			gl.glEnable (GL.GL_BLEND);
 835//			gl.glDepthMask(true);//remove..?
 836			
 837			//Enable stencilbuffer
 838			gl.glEnable(GL.GL_STENCIL_TEST);
 839//		    gl.glStencilMask (0x01);
 840		    gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_INVERT);
 841		    gl.glStencilFunc (GL.GL_ALWAYS, 0, ~0);
 842		    
 843		    //Stecilfunc bestimmt ob in den stencil geschrieben wird oder nicht
 844		    //1.param: die vergleichsart der werte, 
 845		    //2.param: reference value, wird bei op reingeschrieben bei replace(?)
 846		    //3.prama: mask
 847		    //ref is & anded with mask and the result with the value in the stencil buffer
 848		    //mask is & with ref, mask is & stencil => vergleich
 849//		    gl.glStencilFunc(GL.GL_ALWAYS, 0x1, 0x1);
 850//		    gl.glStencilOp(GL.GL_KEEP, GL.GL_INVERT, GL.GL_INVERT);
 851		    
 852		    //TODO notice, "stencilOP" zum wert in stencilbuffer reinschreiben
 853		    //"stencilfunc" vergleicht framebuffer mit stencilbuffer und macht stencilOP wenn bedingung stimmt
 854		    
 855		    gl.glColor4d (colorBuff.get(0), colorBuff.get(1), colorBuff.get(2), colorBuff.get(3));
 856		    
 857			//DRAW //FIXME why does this not work?
 858			if (indexBuff == null){
 859				gl.glDrawArrays(GL.GL_TRIANGLE_FAN, 0, vertBuff.capacity()/3);
 860			}else{
 861				gl.glDrawElements(GL.GL_TRIANGLE_FAN, indexBuff.capacity(), GL.GL_UNSIGNED_INT, indexBuff);
 862			}
 863			
 864//		    gl.glBegin (GL.GL_TRIANGLE_FAN);
 865//		    for (int i = 0; i < vertexArr.length; i++) {
 866//				Vertex vertex = vertexArr[i];
 867//				gl.glVertex3f (vertex.getX(), vertex.getY(),  vertex.getZ());
 868//			}
 869//	    	gl.glEnd();
 870		    
 871//		    gl.glDrawArrays(GL.GL_TRIANGLE_FAN, 0, vertBuff.capacity()/3); 
 872//			*/
 873			//////////////////////////////////////
 874			gl.glDepthMask(true);
 875			
 876		    gl.glEnable (GL.GL_BLEND);
 877		    gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
 878			//////////////////////
 879			// Draw fill		//
 880		    ////////////////////// 
 881//		    /*
 882			gl.glColorMask(true, true, true, true);
 883			gl.glEnable (GL.GL_BLEND);
 884			
 885		    gl.glStencilOp (GL.GL_ZERO, GL.GL_ZERO, GL.GL_ZERO); //org
 886		    gl.glStencilFunc(GL.GL_EQUAL, 0x01, 0x01);
 887			
 888//		    gl.glStencilOp (GL.GL_KEEP, GL.GL_REPLACE, GL.GL_ZERO);
 889//		    gl.glStencilFunc(GL.GL_EQUAL, 0x01, 0x01);
 890		    
 891		    if (useGradient){
 892			    gl.glBegin (GL.GL_QUADS);
 893				    gl.glColor4f(x1R, x1G, x1B, x1A);
 894				    gl.glVertex3d (minX, minY, 0.0);
 895				    gl.glColor4f(x2R, x2G, x2B, x2A);
 896				    gl.glVertex3d (maxX, minY, 0.0); 
 897				    gl.glColor4f(x3R, x3G, x3B, x3A);
 898				    gl.glVertex3d (maxX, maxY, 0.0); 
 899				    gl.glColor4f(x4R, x4G, x4B, x4A);
 900				    gl.glVertex3d (minX, maxY, 0.0); 
 901			    gl.glEnd ();
 902		    }else{
 903			    gl.glBegin (GL.GL_QUADS);
 904				    gl.glVertex3d (minX, minY, 0.0); 
 905				    gl.glVertex3d (maxX, minY, 0.0); 
 906				    gl.glVertex3d (maxX, maxY, 0.0); 
 907				    gl.glVertex3d (minX, maxY, 0.0); 
 908			    gl.glEnd ();
 909		    }
 910//		    */
 911		    ////////////////////////////////////
 912//		    gl.glDepthMask(true); //Disabled to avoid too many state switches, 
 913		    gl.glDisable (GL.GL_STENCIL_TEST);	 //Disabled to avoid too many state switches
 914		gl.glEndList();
 915		returnVal[0] = listIDFill;
 916		    
 917		//////////////////////////////
 918		// Draw aliased outline		//
 919		//////////////////////////////
 920		gl.glColorPointer(4, GL.GL_FLOAT, 0, strokeColBuff);
 921		
 922		gl.glNewList(listIDOutline, GL.GL_COMPILE);
 923//		  	gl.glEnable(GL.GL_STENCIL_TEST); 
 924		  	
 925		  	
 926//			gl.glColorMask(true, true, true, true);
 927//			gl.glDepthMask(false); //FIXME enable? disable?
 928		  	
 929//		    // Draw aliased off-pixels to real
 930//		    gl.glEnable (GL.GL_BLEND);
 931//		    gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
 932			
 933//		    /*
 934//		    gl.glStencilOp (GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP);
 935//		    gl.glStencilFunc (GL.GL_EQUAL, 0x00, 0x01); //THIS IS THE ORIGINAL!
 936		   
 937//		  	gl.glStencilOp (GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP);
 938//		    gl.glStencilFunc (GL.GL_EQUAL, 0x00, ~1); 
 939		    
 940//		    gl.glEnable(GL.GL_LINE_SMOOTH);
 941	    	//FIXME TEST
 942			Tools3D.setLineSmoothEnabled(gl, true);
 943			
 944		    gl.glLineWidth(strokeWeight);
 945		    
 946		    //DRAW 
 947//			gl.glDrawElements(GL.GL_LINE_STRIP, indexBuff.capacity(), GL.GL_UNSIGNED_INT, indexBuff);
 948//			gl.glDrawArrays(GL.GL_LINE_STRIP, 0, vertexArr.length);
 949		    
 950		    /////TEST/// //TODO make vertex pointer arrays?
 951		    gl.glColor4d (strokeColBuff.get(0), strokeColBuff.get(1), strokeColBuff.get(2), strokeColBuff.get(3));
 952		    for (Vertex[] outline : outLines){
 953				 gl.glBegin (GL.GL_LINE_STRIP);
 954				 	for (Vertex vertex : outline){
 955				 		gl.glVertex3f (vertex.getX(), vertex.getY(), vertex.getZ());
 956				 	}
 957			    gl.glEnd();
 958			}
 959			////
 960//			gl.glDisable (GL.GL_LINE_SMOOTH);
 961	    	//FIXME TEST
 962			Tools3D.setLineSmoothEnabled(gl, false);
 963			//////////////////////////////////
 964//		*/
 965//			gl.glDisable (GL.GL_STENCIL_TEST);	
 966			
 967//		    gl.glDepthMask(true);
 968		gl.glEndList();
 969		
 970		returnVal[1] = listIDOutline;
 971		
 972		//Disable client states
 973		gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
 974		gl.glDisableClientState(GL.GL_COLOR_ARRAY);
 975		
 976		((PGraphicsOpenGL)pa.g).endGL();
 977		////////////////
 978		
 979		return returnVal;
 980	}
 981	
 982	/**
 983	 * Generate stencil display list.
 984	 * 
 985	 * @param pa the pa
 986	 * @param vertBuff the vert buff
 987	 * @param tbuff the tbuff
 988	 * @param colorBuff the color buff
 989	 * @param strokeColBuff the stroke col buff
 990	 * @param indexBuff the index buff
 991	 * @param drawSmooth the draw smooth
 992	 * @param strokeWeight the stroke weight
 993	 * @param vertexArr the vertex arr
 994	 * @param outLines the out lines
 995	 * 
 996	 * @return the int[]
 997	 */
 998	public static int[] generateStencilDisplayList(PApplet pa, FloatBuffer vertBuff, FloatBuffer tbuff, 
 999								FloatBuffer colorBuff, FloatBuffer strokeColBuff, IntBuffer indexBuff, 
1000								boolean drawSmooth, float strokeWeight, Vertex[] vertexArr, List<Vertex[]> outLines)
1001	{
1002		return Tools3D.genStencilDisplayListGradient(pa, vertBuff, tbuff, colorBuff, strokeColBuff, indexBuff, drawSmooth, strokeWeight, vertexArr, outLines, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,  1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,  1.0f, 1.0f, 1.0f, 1.0f, false);
1003	}
1004	
1005	//////////////////////////////////////////////////////
1006	// Generate Display Lists and get their IDs			//
1007	//////////////////////////////////////////////////////
1008	/**
1009	 * Creates 2 displaylists for drawing static geometry very fast.
1010	 * Returns the IDs (names) of the display lists generated with the given info.
1011	 * 
1012	 * @param pa the pa
1013	 * @param geometryInfo the geometry info
1014	 * @param useTexture the use texture
1015	 * @param texture the texture
1016	 * @param styleInfo the style info
1017	 * 
1018	 * @return the int[]
1019	 * 
1020	 * Returns the IDs (names) of the display lists generated with the given info.
1021	 */
1022	public static int[] generateDisplayLists(PApplet pa, GeometryInfo geometryInfo, boolean useTexture, PImage texture, StyleInfo styleInfo){
1023		return generateDisplayLists(pa, styleInfo.getFillDrawMode(), geometryInfo, useTexture, texture, styleInfo.isDrawSmooth(), styleInfo.getStrokeWeight());
1024	}
1025	
1026	
1027	/**
1028	 * Returns the IDs (names) of the display lists generated with the given info.
1029	 * 
1030	 * @param pa the pa
1031	 * @param fillDrawMode the fill draw mode
1032	 * @param geometryInfo the geometry info
1033	 * @param useTexture the use texture
1034	 * @param texture the texture
1035	 * @param drawSmooth the draw smooth
1036	 * @param strokeWeight the stroke weight
1037	 * 
1038	 * @return int[2] array where [0] is the list of the fill
1039	 * and [1] the list of the outline drawing list
1040	 */
1041	public static int[] generateDisplayLists(PApplet pa, int fillDrawMode, GeometryInfo geometryInfo,
1042									boolean useTexture, PImage texture, boolean drawSmooth, float strokeWeight
1043	){
1044		FloatBuffer tbuff 			= geometryInfo.getTexBuff();
1045		FloatBuffer vertBuff 		= geometryInfo.getVertBuff();
1046		FloatBuffer colorBuff 		= geometryInfo.getColorBuff();
1047		FloatBuffer strokeColBuff 	= geometryInfo.getStrokeColBuff();
1048		IntBuffer indexBuff 		= geometryInfo.getIndexBuff(); //null if not indexed
1049		
1050		GL gl;
1051		gl =((PGraphicsOpenGL)pa.g).gl;
1052		
1053		//Generate new list IDs
1054		int[] returnVal = new int[2];
1055		int listIDFill = gl.glGenLists(1);
1056		if (listIDFill == 0){
1057			System.err.println("Failed to create fill display list");
1058			returnVal[0] = -1;
1059			returnVal[1] = -1;
1060			return returnVal;
1061		}
1062		int listIDOutline = gl.glGenLists(1);
1063		if (listIDOutline == 0){
1064			System.err.println("Failed to create stroke display list");
1065			returnVal[0] = -1;
1066			returnVal[1] = -1;
1067			return returnVal;
1068		}
1069		
1070		gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
1071		gl.glEnableClientState(GL.GL_COLOR_ARRAY);
1072		
1073		gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertBuff);
1074		gl.glColorPointer(4, GL.GL_FLOAT, 0, colorBuff);
1075		
1076		//Default target
1077		int textureTarget = GL.GL_TEXTURE_2D;
1078		
1079		/////// DO FILL LIST/////////////////////////////////
1080		
1081		/////////
1082		boolean textureDrawn = false;
1083		int usedTextureID = -1;
1084		if (useTexture
1085			&& texture != null 
1086			&& texture instanceof GLTexture) //Bad for performance?
1087		{
1088			GLTexture tex = (GLTexture)texture;
1089			textureTarget = tex.getTextureTarget();
1090			
1091			//tells opengl which texture to reference in following calls from now on!
1092			//the first parameter is eigher GL.GL_TEXTURE_2D or ..1D
1093			gl.glEnable(textureTarget);
1094			usedTextureID = tex.getTextureID();
1095			gl.glBindTexture(textureTarget, tex.getTextureID());
1096			
1097			gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);
1098			gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, tbuff);
1099			textureDrawn = true;
1100		}
1101		
1102		// Normals
1103		if (geometryInfo.isContainsNormals()){
1104			gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
1105			gl.glNormalPointer(GL.GL_FLOAT, 0, geometryInfo.getNormalsBuff());
1106		}
1107		
1108		gl.glColorPointer(4, GL.GL_FLOAT, 0, colorBuff);
1109		
1110		// START recording display list and DRAW////////////////////
1111		gl.glNewList(listIDFill, GL.GL_COMPILE);
1112			if (textureDrawn){
1113				gl.glEnable(textureTarget); //muss texture in der liste gebinded werden? anscheinend JA!
1114				gl.glBindTexture(textureTarget, usedTextureID);
1115			}
1116			
1117			//DRAW with drawElements if geometry is indexed, else draw with drawArrays!
1118			if (geometryInfo.isIndexed()){
1119				gl.glDrawElements(fillDrawMode, indexBuff.capacity(), GL.GL_UNSIGNED_INT, indexBuff); //limit() oder capacity()??
1120			}else{
1121				gl.glDrawArrays(fillDrawMode, 0, vertBuff.capacity()/3);
1122			}
1123			
1124			if (textureDrawn){
1125				gl.glBindTexture(textureTarget, 0);
1126				gl.glDisable(textureTarget); 
1127			}
1128		gl.glEndList();
1129		//// STOP recording display list and DRAW////////////////////
1130		
1131		if (geometryInfo.isContainsNormals()){
1132			gl.glDisableClientState(GL.GL_NORMAL_ARRAY);
1133		}
1134
1135		if (textureDrawn){
1136			gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY);
1137		}
1138		returnVal[0] = listIDFill;
1139		
1140		/////// DO OUTLINE LIST////////////////////////////
1141		gl.glColorPointer(4, GL.GL_FLOAT, 0, strokeColBuff);
1142		//Start recording display list
1143		gl.glNewList(listIDOutline, GL.GL_COMPILE);
1144		
1145//			if (drawSmooth)
1146//				gl.glEnable(GL.GL_LINE_SMOOTH);
1147			//FIXME TEST
1148			Tools3D.setLineSmoothEnabled(gl, true);
1149			
1150			if (strokeWeight > 0)
1151				gl.glLineWidth(strokeWeight);
1152			
1153			//DRAW
1154			if (geometryInfo.isIndexed()){
1155				gl.glDrawElements(GL.GL_LINE_STRIP, indexBuff.capacity(), GL.GL_UNSIGNED_INT, indexBuff); ////indices.limit()?
1156			}else{
1157				gl.glDrawArrays(GL.GL_LINE_STRIP, 0, vertBuff.capacity()/3);
1158			}
1159			
1160//			if (drawSmooth)
1161//				gl.glDisable(GL.GL_LINE_SMOOTH);
1162			//FIXME TEST
1163			Tools3D.setLineSmoothEnabled(gl, false);
1164			
1165		gl.glEndList();
1166		returnVal[1] = listIDOutline;
1167		////////////////////////////////////////////////////
1168		
1169		//Disable client states
1170		gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
1171		gl.glDisableClientState(GL.GL_COLOR_ARRAY);
1172		return returnVal;
1173	}
1174	
1175	
1176	//TODO make only 1 function gendisplaylist mit boolean generate outline/fill
1177	/**
1178	 * Returns the ID (name) of the display list
1179	 * If you dont want to use a line stipple pattern, use '0' for the parameter.
1180	 * 
1181	 * @param pa the pa
1182	 * @param vertBuff the vert buff
1183	 * @param strokeColBuff the stroke col buff
1184	 * @param indexBuff the index buff
1185	 * @param drawSmooth the draw smooth
1186	 * @param strokeWeight the stroke weight
1187	 * @param lineStipple the line stipple
1188	 * 
1189	 * @return int id of outline drawing list
1190	 */
1191	public static int generateOutLineDisplayList(PApplet pa, FloatBuffer vertBuff, FloatBuffer strokeColBuff, IntBuffer indexBuff, 
1192												boolean drawSmooth, float strokeWeight, short lineStipple){
1193		GL gl;
1194		gl = beginGL(pa.g);
1195		
1196		//Generate new list IDs
1197		int returnVal = -1;
1198		int listIDOutline = gl.glGenLists(1);
1199		if (listIDOutline == 0){
1200			System.err.println("Failed to create display list");
1201			return returnVal;
1202		}
1203		gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
1204		gl.glEnableClientState(GL.GL_COLOR_ARRAY);
1205		gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertBuff);
1206		gl.glColorPointer(4, GL.GL_FLOAT, 0, strokeColBuff);
1207		
1208		//Start recording display list
1209		gl.glNewList(listIDOutline, GL.GL_COMPILE);
1210//			if (drawSmooth)
1211//				gl.glEnable(GL.GL_LINE_SMOOTH);
1212			//FIXME TEST for multisample
1213			Tools3D.setLineSmoothEnabled(gl, true);
1214		
1215			if (strokeWeight > 0)
1216				gl.glLineWidth(strokeWeight);
1217			if (lineStipple != 0){
1218				gl.glLineStipple(1, lineStipple);
1219				gl.glEnable(GL.GL_LINE_STIPPLE);
1220			}
1221			
1222			if (indexBuff == null){
1223				gl.glDrawArrays(GL.GL_LINE_STRIP, 0, vertBuff.capacity()/3);
1224			}else{
1225				gl.glDrawElements(GL.GL_LINE_STRIP, indexBuff.capacity(), GL.GL_UNSIGNED_INT, indexBuff); ////indices.limit()?
1226			}
1227			
1228			//RESET LINE STIPPLE
1229			if (lineStipple != 0)
1230				gl.glDisable(GL.GL_LINE_STIPPLE); 
1231			
1232//			if (drawSmooth)
1233//				gl.glDisable(GL.GL_LINE_SMOOTH);
1234			//FIXME TEST for multisample
1235			Tools3D.setLineSmoothEnabled(gl, false);
1236			
1237		gl.glEndList();
1238		returnVal = listIDOutline;
1239		
1240		//Disable client states
1241		gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
1242		gl.glDisableClientState(GL.GL_COLOR_ARRAY);
1243		((PGraphicsOpenGL)pa.g).endGL();
1244		return returnVal;
1245	}
1246	
1247	/**
1248	 * Draws a filled 2d bezier shape in immediate mode with help of
1249	 * the stencil buffer to allow concave geometry.
1250	 * Beziervertices are allowerd in the vertex array.
1251	 * 
1252	 * @param pa the pa
1253	 * @param vertexArr the vertex arr
1254	 */
1255	public static void drawFilledBezierShape(PApplet pa, Vertex[] vertexArr){
1256		GL gl=((PGraphicsOpenGL)pa.g).beginGL();
1257		float[] minMax = ToolsGeometry.getMinXYMaxXY(vertexArr);
1258//		/*
1259		 // Draw to stencil
1260		    gl.glDisable (GL.GL_BLEND);
1261		    gl.glEnable (GL.GL_STENCIL_TEST);
1262		    gl.glStencilOp (GL.GL_KEEP, GL.GL_KEEP, GL.GL_INVERT);
1263		    gl.glStencilFunc (GL.GL_ALWAYS, 0, ~0);
1264		    gl.glColorMask (false, false, false, false);
1265//		*/
1266		    //Change beziervertices to normal vertices - THIS IS EXPENSIVE!
1267		    Vertex[] allVertsBezierResolved = ToolsGeometry.createVertexArrFromBezierArr(vertexArr, 15);
1268		           
1269		   //DRAW RAW FILL 
1270		   gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1271		   //gl.glBegin (GL.GL_LINE_STRIP);
1272		     gl.glBegin (GL.GL_TRIANGLE_FAN);
1273        for (Vertex vertex : allVertsBezierResolved) {
1274            gl.glVertex3f(vertex.x, vertex.y, vertex.z);
1275        }
1276			 gl.glEnd ();
1277
1278			 //Draw aliased off-pixels to real
1279		    gl.glColorMask (true, true, true, true);
1280		    gl.glEnable (GL.GL_BLEND);
1281		    gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
1282
1283//			/*		    
1284		    gl.glStencilFunc (GL.GL_EQUAL, 0x00, 0x01);
1285		    gl.glStencilOp (GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP);
1286		    
1287		    //DRAW OUTLINE
1288		   gl.glEnable(GL.GL_LINE_SMOOTH);
1289		   gl.glLineWidth(1.0f);
1290		   gl.glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
1291		    gl.glBegin (GL.GL_LINES);
1292        for (Vertex vertex : allVertsBezierResolved) {
1293            gl.glVertex3f(vertex.x, vertex.y, vertex.z);
1294        }
1295		    gl.glEnd ();
1296		    gl.glDisable (GL.GL_LINE_SMOOTH);
1297//		*/
1298//		/*
1299		    // Draw FILL
1300		    gl.glStencilFunc (GL.GL_EQUAL, 0x01, 0x01);
1301		    gl.glStencilOp (GL.GL_ZERO, GL.GL_ZERO, GL.GL_ZERO);
1302		   
1303		    gl.glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
1304		    gl.glBegin (GL.GL_QUADS);
1305		      gl.glVertex3f (minMax[0], minMax[1], 0.0f); 
1306		      gl.glVertex3f (minMax[2], minMax[1], 0.0f); 
1307		      gl.glVertex3f (minMax[2], minMax[3], 0.0f); 
1308		      gl.glVertex3f (minMax[0],  minMax[3], 0.0f); 
1309		    gl.glEnd ();
1310
1311		    gl.glDisable(GL.GL_STENCIL_TEST);
1312//		*/
1313		    ((PGraphicsOpenGL)pa.g).endGL();
1314	}
1315	
1316	
1317	/**
1318	 * Reverses an array.
1319	 * 
1320	 * @param b the b
1321	 * @return the vector3 d[]
1322	 */
1323	public static Vector3D[] reverse(Vector3D[] b) {
1324		   int left  = 0;          // index of leftmost element
1325		   int right = b.length-1; // index of rightmost element
1326		  
1327		   while (left < right) {
1328		      // exchange the left and right elements
1329			  Vector3D temp = b[left]; 
1330		      b[left]  = b[right]; 
1331		      b[right] = temp;
1332		     
1333		      // move the bounds toward the center
1334		      left++;
1335		      right--;
1336		   }
1337		   return b;
1338		}//endmethod reverse
1339
1340
1341	/**
1342	 * Checks whether the given image is of power of 2 dimensions.
1343	 * 
1344	 * @param image the image
1345	 * 
1346	 * @return true, if checks if is power of two dimension
1347	 */
1348	public static boolean isPowerOfTwoDimension(PImage image){
1349		return ToolsMath.isPowerOfTwo(image.width) && ToolsMath.isPowerOfTwo(image.height);
1350	}
1351	
1352	/**
1353     * For non power of two textures, the texture coordinates
1354     * have to be in the range from 0..texture_width instead of from 0.0 to 1.0.
1355     * <br>So we try to scale the texture coords to the width/height of the texture
1356     * 
1357     * @param texture the texture
1358     * @param verts the verts
1359     */
1360    public static void scaleTextureCoordsForRectModeFromNormalized(PImage texture, Vertex[] verts){
1361        for (Vertex vertex : verts) {
1362            if (vertex.getTexCoordU() <= 1.0f && vertex.getTexCoordU() >= 0.0f) {
1363                vertex.setTexCoordU(vertex.getTexCoordU() * texture.width);
1364            }
1365            if (vertex.getTexCoordV() <= 1.0f && vertex.getTexCoordV() >= 0.0f) {
1366                vertex.setTexCoordV(vertex.getTexCoordV() * texture.height);
1367            }
1368        }
1369    }
1370    
1371    /**
1372	 * projects a specific point on a plane with a specific depth
1373	 * @param gl
1374	 * @param point
1375	 * @param frustum
1376	 * @param z
1377	 * @return
1378	 */
1379	public static Vector3D projectPointToPlaneInPerspectiveMode(Vector3D point,IFrustum frustum,float z,MTApplication mtApp)
1380	{
1381		float heightOfPlaneAtZ = frustum.getHeightOfPlane(z);
1382		float widthOfPlaneAtZ = frustum.getWidthOfPlane(z);
1383		
1384		float heightOfPlaneAtPoint = frustum.getHeightOfPlane(point.z);
1385		float widthOfPlaneAtPoint = frustum.getWidthOfPlane(point.z);
1386		
1387		//float centerX = mtApp.width/2;
1388		//float centerY = mtApp.height/2;
1389		
1390		Vector3D ntl = frustum.getNearTopLeft();
1391		
1392		//subtract getWidthofNearPlane, because frustum is upside down
1393		float centerX = ntl.x - frustum.getWidthOfNearPlane() + frustum.getWidthOfNearPlane()/2f;
1394		float centerY = ntl.y + frustum.getHeightOfNearPlane()/2f;
1395		
1396		float percentWidth = (point.x - (centerX-(widthOfPlaneAtPoint/2.f)))/widthOfPlaneAtPoint;
1397		float percentHeight = (point.y - (centerY-(heightOfPlaneAtPoint/2.f)))/heightOfPlaneAtPoint;
1398		
1399		Vector3D projectedPoint = new Vector3D();
1400		projectedPoint.x = (centerX - (widthOfPlaneAtZ/2.f))+widthOfPlaneAtZ*percentWidth;
1401		projectedPoint.y = (centerY - (heightOfPlaneAtZ/2.f))+heightOfPlaneAtZ*percentHeight;
1402		projectedPoint.z = z;
1403		
1404		return projectedPoint;
1405	}
1406    
1407
1408}