PageRenderTime 60ms CodeModel.GetById 33ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/src/org/mt4j/components/visibleComponents/shapes/MTStencilPolygon.java

http://mt4j.googlecode.com/
Java | 588 lines | 236 code | 96 blank | 256 comment | 24 complexity | 1d22ca07be4c659e531a341637e67544 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.components.visibleComponents.shapes;
 19
 20import java.nio.FloatBuffer;
 21import java.util.ArrayList;
 22import java.util.List;
 23
 24import javax.media.opengl.GL;
 25
 26import org.mt4j.util.math.Tools3D;
 27import org.mt4j.util.math.ToolsGeometry;
 28import org.mt4j.util.math.Vertex;
 29import org.mt4j.util.opengl.GLStencilUtil;
 30
 31import processing.core.PApplet;
 32import processing.core.PGraphics;
 33import processing.opengl.PGraphicsOpenGL;
 34
 35/**
 36 * This class can only be used with OpenGL!
 37 * <br>This class can be used to draw concave, non-simple
 38 * polygons using the stencil buffer.
 39 * 
 40 * @author Christopher Ruff
 41 */
 42public class MTStencilPolygon extends MTPolygon {
 43	
 44	/** The pa. */
 45	private PApplet pa;
 46	
 47	/** The min max. */
 48	private float[] minMax;
 49	
 50	/** The min x. */
 51	private float minX;
 52	
 53	/** The min y. */
 54	private float minY;
 55	
 56	/** The max x. */
 57	private float maxX;
 58	
 59	/** The max y. */
 60	private float maxY;
 61    
 62	/** The contours. */
 63	private List<Vertex[]> contours;
 64	
 65	//Gradient Quad points
 66	/** The x1 r. */
 67	private float x1R;
 68	
 69	/** The x1 g. */
 70	private float x1G;
 71	
 72	/** The x1 b. */
 73	private float x1B;
 74	
 75	/** The x1 a. */
 76	private float x1A;
 77	
 78	/** The x2 r. */
 79	private float x2R;
 80	
 81	/** The x2 g. */
 82	private float x2G;
 83	
 84	/** The x2 b. */
 85	private float x2B;
 86	
 87	/** The x2 a. */
 88	private float x2A;
 89	
 90	/** The x3 r. */
 91	private float x3R;
 92	
 93	/** The x3 g. */
 94	private float x3G;
 95	
 96	/** The x3 b. */
 97	private float x3B;
 98	
 99	/** The x3 a. */
100	private float x3A;
101	
102	/** The x4 r. */
103	private float x4R;
104	
105	/** The x4 g. */
106	private float x4G;
107	
108	/** The x4 b. */
109	private float x4B;
110	
111	/** The x4 a. */
112	private float x4A;
113	
114	/** The use gradient. */
115	private boolean useGradient;
116	
117	
118	/**
119	 * Instantiates a new mT stencil polygon.
120	 *
121	 * @param vertices the vertices
122	 * @param pApplet the applet
123	 * @deprecated constructor will be deleted! Please use the constructor with the PApplet instance as the first parameter.
124	 */
125	public MTStencilPolygon(Vertex[] vertices, PApplet pApplet) {
126		this(pApplet, vertices);
127	}
128	
129	/**
130	 * Instantiates a new mT stencil polygon.
131	 * @param pApplet the applet
132	 * @param vertices the vertices
133	 */
134	public MTStencilPolygon(PApplet pApplet, Vertex[] vertices) {
135		super(pApplet, vertices);
136		
137		ArrayList<Vertex[]> contours = new ArrayList<Vertex[]>();
138		contours.add(vertices);
139		this.contours = contours;
140		this.init(pa, vertices, contours);
141	}
142	
143	
144	/**
145	 * Instantiates a new mT stencil polygon.
146	 *
147	 * @param innerVertices the inner vertices
148	 * @param contours the contours
149	 * @param pApplet the applet
150	 * @deprecated constructor will be deleted! Please use the constructor with the PApplet instance as the first parameter.
151	 */
152	public MTStencilPolygon(Vertex[] innerVertices, ArrayList<Vertex[]> contours, PApplet pApplet) {
153		this(pApplet, innerVertices, contours);
154	}
155	
156	/**
157	 * The Constructor.
158	 * @param pApplet the applet
159	 * @param innerVertices the vertices used for picking and other calculations, its best to use the biggest contour for this
160	 * @param contours the contour(s) of the shape
161	 */
162	public MTStencilPolygon(PApplet pApplet, Vertex[] innerVertices, ArrayList<Vertex[]> contours) {
163		super(pApplet, innerVertices);
164		this.init(pApplet, innerVertices, contours);
165	}
166	
167	/**
168	 * Inits the.
169	 * @param pApplet the applet
170	 * @param innerVertices the inner vertices
171	 * @param contours the contours
172	 */
173	private void init(PApplet pApplet, Vertex[] innerVertices, ArrayList<Vertex[]> contours){
174		this.pa = this.getRenderer();
175		this.contours = contours;
176		
177		//This class may only be used with opengl anyway!
178		this.setUseDirectGL(true);
179		this.setDrawSmooth(true);
180		
181		//Convert BezierVertices to regular Vertices
182		//SEGMENTS CONRTOLS THE DETAIL OF THE BEZIER CURVE APPROXIMATION
183		int segments = 12; 
184		//TODO let the user do that beforehand?
185		Vertex[] allVerts = ToolsGeometry.createVertexArrFromBezierArr(innerVertices, segments);
186		this.setVertices(allVerts);
187		
188		//Replace beziervertices in the SUB-PATHS (outlines) of the glyphs with many calculated regular vertices
189		//The subpaths are used to draw the outline
190		this.contours = ToolsGeometry.createVertexArrFromBezierVertexArrays(contours, segments);
191		
192	    reCalcMinMax();
193	    
194	    //TODO handle
195	    useGradient = false;
196	    
197		this.setStrokeWeight(1.0f);
198		
199		// use?
200//		this.setEnableTesselation(true);
201	}
202	
203	/**
204	 * Re calc min max.
205	 */
206	private void reCalcMinMax(){
207		minMax = ToolsGeometry.getMinXYMaxXY(this.getVerticesLocal());
208		minX = minMax[0]-5;
209	    minY = minMax[1]-5;
210	    maxX = minMax[2]+5;
211	    maxY = minMax[3]+5;
212	}
213	
214	/**
215	 * NOTE: this also sets the contours to one and uses the new
216	 * vertices as the only contour! If you want to set other countours
217	 * use the setContours or setVerticesAndContours method!.
218	 * 
219	 * @param vertices the vertices
220	 */
221	@Override
222	public void setVertices(Vertex[] vertices) {
223		super.setVertices(vertices);
224		
225		ArrayList<Vertex[]> outlines = new ArrayList<Vertex[]>();
226		outlines.add(vertices);
227		this.contours = outlines;
228		reCalcMinMax();
229	}
230	
231	/**
232	 * Sets new outlines for this stencil polygon.
233	 * This is a separate method, because when you want
234	 * to ouline polygons with holes, you have to have separate,
235	 * not connected outline arrays.
236	 * 
237	 * @param contours the contours
238	 */
239	public void setNewContours(ArrayList<Vertex[]> contours){
240		this.contours = contours;
241		this.setMatricesDirty(true);
242	}
243	
244	/**
245	 * Sets the new vertices and contours.
246	 * 
247	 * @param vertices the vertices
248	 * @param contours the contours
249	 */
250	public void setNewVerticesAndContours(Vertex[] vertices, ArrayList<Vertex[]> contours){
251		this.contours = contours;
252		setVertices(vertices);
253	}
254
255	/**
256	 * Just draws the character without applying its own local matrix,
257	 * useful when another components want to draw this component.
258	 * 
259	 * @param gl the gl
260	 */
261	public void drawComponent(GL gl) {
262		if (isUseDirectGL()){
263			if (isUseDisplayList()){
264				int[] displayListIDs = this.getGeometryInfo().getDisplayListIDs();
265				if (!this.isNoFill() && displayListIDs[0] != -1)
266					gl.glCallList(displayListIDs[0]); //Draw fill
267				if (!this.isNoStroke()  && displayListIDs[1] != -1)
268					gl.glCallList(displayListIDs[1]); //Draw outline
269			}else{
270				drawPureGL(gl);
271			}
272		}
273	}
274	
275	@Override
276	public void drawComponent(PGraphics g) {
277		if (isUseDirectGL()){
278			GL gl=((PGraphicsOpenGL)this.getRenderer().g).beginGL();
279			drawComponent(gl);
280			((PGraphicsOpenGL)this.getRenderer().g).endGL();
281		}
282	}
283	
284	/**
285	 * Draw pure gl.
286	 * 
287	 * @param gl the gl
288	 */
289	private void drawPureGL(GL gl){
290		FloatBuffer vertBuff = this.getGeometryInfo().getVertBuff();
291		FloatBuffer colorBuff = this.getGeometryInfo().getColorBuff();
292		FloatBuffer strokeColBuff = this.getGeometryInfo().getStrokeColBuff();
293		
294	    gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
295		gl.glEnableClientState(GL.GL_COLOR_ARRAY);
296		
297		if (this.isUseVBOs()){
298			gl.glBindBuffer(GL.GL_ARRAY_BUFFER, this.getGeometryInfo().getVBOVerticesName());
299			gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
300			
301			gl.glBindBuffer(GL.GL_ARRAY_BUFFER, this.getGeometryInfo().getVBOColorName());
302			gl.glColorPointer(4, GL.GL_FLOAT, 0, 0);
303		}else{
304			gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertBuff);
305			gl.glColorPointer(4, GL.GL_FLOAT, 0, colorBuff);
306		}
307		
308		//Normals
309		if (this.getGeometryInfo().isContainsNormals()){
310			gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
311			if (this.isUseVBOs()){
312				gl.glBindBuffer(GL.GL_ARRAY_BUFFER, this.getGeometryInfo().getVBONormalsName());
313				gl.glNormalPointer(GL.GL_FLOAT, 0, 0); 
314			}else{
315				gl.glNormalPointer(GL.GL_FLOAT, 0, this.getGeometryInfo().getNormalsBuff());
316			}
317		}
318		
319//	    /*
320	    if (!this.isNoFill()){
321	    	
322	    	/*
323			///////////////////////
324			// Draw Into Stencil //
325		    ///////////////////////
326			gl.glClearStencil(0);
327			gl.glColorMask(false,false,false,false);
328			gl.glDisable(GL.GL_BLEND);
329			gl.glDepthMask(false);//remove..?
330			
331			//Enable stencilbuffer
332			gl.glEnable(GL.GL_STENCIL_TEST);
333//		    gl.glStencilMask (0x01);
334		    gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_INVERT);
335		    gl.glStencilFunc (GL.GL_ALWAYS, 0, ~0);
336		    
337		    //Draw into stencil
338		    gl.glDrawArrays(GL.GL_TRIANGLE_FAN, 0, vertBuff.capacity()/3); 
339		    
340		    if (this.getGeometryInfo().isContainsNormals()){
341				gl.glDisableClientState(GL.GL_NORMAL_ARRAY);
342			}
343		    
344			//////////////////////
345			// Draw fill Overlay//
346		    ////////////////////// 
347		    gl.glDepthMask(true);
348			gl.glColorMask(true, true, true, true);
349			gl.glEnable (GL.GL_BLEND);
350			
351		    gl.glStencilOp (GL.GL_ZERO, GL.GL_ZERO, GL.GL_ZERO);
352		    gl.glStencilFunc(GL.GL_EQUAL, 0x01, 0x01);
353		    
354		    if (useGradient){
355			    gl.glBegin (GL.GL_QUADS);
356				    gl.glColor4f(x1R, x1G, x1B, x1A);
357				    gl.glVertex3d (minX, minY, 0.0);
358				    gl.glColor4f(x2R, x2G, x2B, x2A);
359				    gl.glVertex3d (maxX, minY, 0.0); 
360				    gl.glColor4f(x3R, x3G, x3B, x3A);
361				    gl.glVertex3d (maxX, maxY, 0.0); 
362				    gl.glColor4f(x4R, x4G, x4B, x4A);
363				    gl.glVertex3d (minX, maxY, 0.0); 
364			    gl.glEnd ();
365		    }else{
366		    	gl.glColor4d (colorBuff.get(0), colorBuff.get(1), colorBuff.get(2), colorBuff.get(3));
367			    gl.glBegin (GL.GL_QUADS);
368				    gl.glVertex3d (minX, minY, 0.0); 
369				    gl.glVertex3d (maxX, minY, 0.0); 
370				    gl.glVertex3d (maxX, maxY, 0.0); 
371				    gl.glVertex3d (minX, maxY, 0.0); 
372			    gl.glEnd ();
373		    }
374		    
375		    gl.glDisable (GL.GL_STENCIL_TEST);
376		    */	
377	    	
378			///////////////////////
379			// Draw Into Stencil //
380		    ///////////////////////
381//	    	GLStencilUtil.getInstance().beginDrawClipShape(gl);
382	    	
383	    	if (GLStencilUtil.getInstance().isClipActive()){
384	    		gl.glPushAttrib(GL.GL_STENCIL_BUFFER_BIT);
385	    	}else{
386	    		//Enable stencilbuffer
387				gl.glEnable(GL.GL_STENCIL_TEST);
388		    	gl.glClearStencil(GLStencilUtil.stencilValueStack.peek());
389		    	gl.glClear(GL.GL_STENCIL_BUFFER_BIT);
390	    	}
391//	    	gl.glPushAttrib(GL.GL_STENCIL_TEST);
392//	    	gl.glDisable(GL.GL_STENCIL_TEST);
393//	    	gl.glClearStencil(GLStencilUtil.getInstance().stencilValueStack.peek());
394//			gl.glClearStencil(0);
395//	    	gl.glClear(GL.GL_STENCIL_BUFFER_BIT);
396			gl.glColorMask(false,false,false,false);
397			gl.glDisable(GL.GL_BLEND);
398			gl.glDepthMask(false);//remove..?
399			
400			
401//		    gl.glStencilMask (0x01);
402		    gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_INVERT);
403		    gl.glStencilFunc (GL.GL_ALWAYS, 0, ~0);
404//		    gl.glStencilFunc (GL.GL_ALWAYS, GLStencilUtil.getInstance().stencilValueStack.peek(), ~GLStencilUtil.getInstance().stencilValueStack.peek());
405		    
406		    //Draw into stencil
407		    gl.glDrawArrays(GL.GL_TRIANGLE_FAN, 0, vertBuff.capacity()/3); 
408		    
409		    if (this.getGeometryInfo().isContainsNormals()){
410				gl.glDisableClientState(GL.GL_NORMAL_ARRAY);
411			}
412		    
413			//////////////////////
414			// Draw fill Overlay//
415		    ////////////////////// 
416		    gl.glDepthMask(true);
417			gl.glColorMask(true, true, true, true);
418			gl.glEnable (GL.GL_BLEND);
419			
420			
421			gl.glStencilOp (GL.GL_KEEP, GL.GL_KEEP, GL.GL_REPLACE);
422//		    gl.glStencilOp (GL.GL_ZERO, GL.GL_REPLACE, GL.GL_REPLACE);
423//			gl.glStencilOp (GL.GL_KEEP, GL.GL_KEEP, GL.GL_ZERO); 
424//		     gl.glStencilOp (GL.GL_ZERO, GL.GL_ZERO, GL.GL_ZERO); //Org
425//		    gl.glStencilFunc(GL.GL_EQUAL, 0x01, 0x01); //org
426//			if (GLStencilUtil.getInstance().isClipActive()){
427				gl.glStencilFunc(GL.GL_NOTEQUAL, GLStencilUtil.stencilValueStack.peek(), GLStencilUtil.stencilValueStack.peek());
428//				gl.glStencilFunc(GL.GL_NOTEQUAL, 0x01, 0x01);
429//			}else{
430//				gl.glStencilFunc(GL.GL_EQUAL, GLStencilUtil.getInstance().stencilValueStack.peek(), GLStencilUtil.getInstance().stencilValueStack.peek());
431//			}
432		    
433		    if (useGradient){
434			    gl.glBegin (GL.GL_QUADS);
435				    gl.glColor4f(x1R, x1G, x1B, x1A);
436				    gl.glVertex3d (minX, minY, 0.0);
437				    gl.glColor4f(x2R, x2G, x2B, x2A);
438				    gl.glVertex3d (maxX, minY, 0.0); 
439				    gl.glColor4f(x3R, x3G, x3B, x3A);
440				    gl.glVertex3d (maxX, maxY, 0.0); 
441				    gl.glColor4f(x4R, x4G, x4B, x4A);
442				    gl.glVertex3d (minX, maxY, 0.0); 
443			    gl.glEnd ();
444		    }else{
445		    	gl.glColor4d (colorBuff.get(0), colorBuff.get(1), colorBuff.get(2), colorBuff.get(3));
446			    gl.glBegin (GL.GL_QUADS);
447				    gl.glVertex3d (minX, minY, 0.0); 
448				    gl.glVertex3d (maxX, minY, 0.0); 
449				    gl.glVertex3d (maxX, maxY, 0.0); 
450				    gl.glVertex3d (minX, maxY, 0.0); 
451			    gl.glEnd ();
452		    }
453		    
454		    if (GLStencilUtil.getInstance().isClipActive()){
455			    gl.glPopAttrib();
456	    	}else{
457	    		 gl.glDisable (GL.GL_STENCIL_TEST);
458	    	}
459
460	    }
461	    
462	    //////////////////////////////
463		// Draw aliased outlines	//
464		//////////////////////////////
465	    if (!isNoStroke()){
466	    	if (this.isUseVBOs()){
467				gl.glBindBuffer(GL.GL_ARRAY_BUFFER, this.getGeometryInfo().getVBOStrokeColorName());
468				gl.glColorPointer(4, GL.GL_FLOAT, 0, 0);
469			}else{
470				gl.glColorPointer(4, GL.GL_FLOAT, 0, strokeColBuff);
471			}
472			
473//		  	gl.glDepthMask(false); //FIXME enable? disable?
474//		    // Draw aliased off-pixels to real
475//		    gl.glEnable (GL.GL_BLEND);
476//		    gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
477//			
478//		    gl.glStencilOp (GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP);
479//		    gl.glStencilFunc (GL.GL_EQUAL, 0x00, 0x01); //THIS IS THE ORIGINAL!
480		    
481//		    gl.glEnable(GL.GL_LINE_SMOOTH);
482	    	//FIXME TEST
483			Tools3D.setLineSmoothEnabled(gl, true);
484	    	
485		    gl.glLineWidth(this.getStrokeWeight());
486		    
487		    short lineStipple = this.getLineStipple();
488			if (lineStipple != 0){
489				gl.glLineStipple(1, lineStipple);
490				gl.glEnable(GL.GL_LINE_STIPPLE);
491			}
492		    
493		    //DRAW 
494//			gl.glDrawElements(GL.GL_LINE_STRIP, indexBuff.capacity(), GL.GL_UNSIGNED_INT, indexBuff);
495//			gl.glDrawArrays(GL.GL_LINE_STRIP, 0, vertexArr.length);
496		    
497		    /////TEST/// //TODO make vertex pointer arrays?
498		    gl.glColor4d (strokeColBuff.get(0), strokeColBuff.get(1), strokeColBuff.get(2), strokeColBuff.get(3));
499		    for (Vertex[] outline : contours){
500				 gl.glBegin (GL.GL_LINE_STRIP);
501				 	for (Vertex vertex : outline)
502				 		gl.glVertex3f (vertex.getX(), vertex.getY(), vertex.getZ());
503			    gl.glEnd();
504			}
505		    
506//			gl.glDisable (GL.GL_LINE_SMOOTH);
507		    //FIXME TEST
508			Tools3D.setLineSmoothEnabled(gl, false);
509		    
510			gl.glDisable(GL.GL_LINE_STIPPLE); 
511	    }
512	    
513//		gl.glDisable (GL.GL_STENCIL_TEST);	
514//		gl.glDepthMask(true);
515		    
516		//Disable client states
517		gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
518		gl.glDisableClientState(GL.GL_COLOR_ARRAY);
519		
520		if (this.isUseVBOs()){
521			gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
522			gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
523		}
524	}
525	
526	
527
528	/* (non-Javadoc)
529	 * @see com.jMT.components.visibleComponents.shapes.AbstractShape#generateDisplayLists()
530	 */
531	@Override //TODO JUST COMPILE DrawPureGL() into a list!?
532	public void generateDisplayLists() {
533		this.getGeometryInfo().setDisplayListIDs(Tools3D.generateStencilDisplayList(
534								pa, this.getGeometryInfo().getVertBuff(), this.getGeometryInfo().getTexBuff(), this.getGeometryInfo().getColorBuff(), this.getGeometryInfo().getStrokeColBuff(),
535								this.getGeometryInfo().getIndexBuff(),true, this.getStrokeWeight(), this.getVerticesLocal(), contours));
536	}
537
538	/**
539	 * returns the vertex arrays which shape the outline of the character.
540	 * 
541	 * @return the contours
542	 */
543	public List<Vertex[]> getContours(){
544		return this.contours;
545	}
546	
547	/**
548	 * Gets the max x.
549	 * 
550	 * @return the max x
551	 */
552	public float getMaxX() {
553		return maxX;
554	}
555
556	/**
557	 * Gets the max y.
558	 * 
559	 * @return the max y
560	 */
561	public float getMaxY() {
562		return maxY;
563	}
564
565	/**
566	 * Gets the min x.
567	 * 
568	 * @return the min x
569	 */
570	public float getMinX() {
571		return minX;
572	}
573
574	/**
575	 * Gets the min y.
576	 * 
577	 * @return the min y
578	 */
579	public float getMinY() {
580		return minY;
581	}
582	
583
584	
585	
586	
587	
588}