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