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