From 929e9229c950b756291f720fee186d3928869aa3 Mon Sep 17 00:00:00 2001 From: codeanticode Date: Mon, 13 Feb 2012 21:29:17 +0000 Subject: [PATCH] GLU tessellator for Android, some corrections in examples --- android/core/src/processing/core/PApplet.java | 10 + android/core/src/processing/core/PGL.java | 264 +++++++----------- .../core/src/processing/core/PGraphics.java | 12 +- .../processing/core/PGraphicsAndroid3D.java | 112 ++++---- .../opengl/src/processing/opengl/PGL.java | 158 ++++------- .../processing/opengl/PGraphicsOpenGL.java | 121 ++++---- 6 files changed, 306 insertions(+), 371 deletions(-) diff --git a/android/core/src/processing/core/PApplet.java b/android/core/src/processing/core/PApplet.java index 60aff8f69..22229e086 100644 --- a/android/core/src/processing/core/PApplet.java +++ b/android/core/src/processing/core/PApplet.java @@ -7318,6 +7318,16 @@ public class PApplet extends Activity implements PConstants, Runnable { } + public void beginContour() { + g.beginContour(); + } + + + public void endContour() { + g.endContour(); + } + + public void endShape() { g.endShape(); } diff --git a/android/core/src/processing/core/PGL.java b/android/core/src/processing/core/PGL.java index faed9f0d1..9a34238e2 100644 --- a/android/core/src/processing/core/PGL.java +++ b/android/core/src/processing/core/PGL.java @@ -27,6 +27,9 @@ import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.IntBuffer; +import processing.glu.PGLU; +import processing.glu.PGLUtessellator; +import processing.glu.PGLUtessellatorCallbackAdapter; import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLContext; @@ -170,8 +173,8 @@ public class PGL { public static final int GL_ALIASED_POINT_SIZE_RANGE = GLES20.GL_ALIASED_POINT_SIZE_RANGE; public static final int GL_SAMPLES = GLES20.GL_SAMPLES; - public static final int GLU_TESS_WINDING_NONZERO = -1; - public static final int GLU_TESS_WINDING_ODD = -1; + public static final int GLU_TESS_WINDING_NONZERO = PGLU.GLU_TESS_WINDING_NONZERO; + public static final int GLU_TESS_WINDING_ODD = PGLU.GLU_TESS_WINDING_ODD; public static final int GL_TEXTURE0 = GLES20.GL_TEXTURE0; public static final int GL_TEXTURE1 = GLES20.GL_TEXTURE1; @@ -216,11 +219,8 @@ public class PGL { public static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; public static final int EGL_OPENGL_ES2_BIT = 0x0004; - /** Pipeline mode: FIXED, PROG_GL2, PROG_GL3 or PROG_GL4 */ - public int pipeline; - public GL10 gl; - public GLU glu; + public PGLU glu; public AndroidRenderer renderer; @@ -237,22 +237,10 @@ public class PGL { public PGL(PGraphicsAndroid3D pg) { this.pg = pg; renderer = new AndroidRenderer(); - glu = new GLU(); + glu = new PGLU(); initialized = false; } - /** - * This static method can be called by applications that use - * Processing+P3D inside their own GUI, so they can initialize - * JOGL2 before anything else. - * According to the JOGL2 documentation, applications shall call - * GLProfile.initSingleton() ASAP, before any other UI invocation. - * In case applications are able to initialize JOGL before any other - * UI action, hey shall invoke this method with beforeUI=true and - * benefit from fast native multithreading support on all platforms - * if possible. - * - */ static public void startup(boolean beforeUI) { } @@ -265,9 +253,6 @@ public class PGL { public void updateOffscreen(PGL primary) { gl = primary.gl; -// gl11 = primary.gl11; -// gl11x = primary.gl11x; -// gl11xp = primary.gl11xp; } @@ -370,56 +355,7 @@ public class PGL { } public void destroyContext() { - } - - /////////////////////////////////////////////////////////////////////////////////// - - // Utilities - - public boolean contextIsCurrent(Context other) { - return other.same(/*context*/); - } - - static public short makeIndex(int intIdx) { - // When the index value is greater than 32767, subtracting 65536 - // will make it (as a short) to wrap around to the negative range, which - // is all we need to later pass these numbers to opengl (which will - // interpret them as unsigned shorts). See discussion here: - // http://stackoverflow.com/questions/4331021/java-opengl-gldrawelements-with-32767-vertices - return 32767 < intIdx ? (short)(intIdx - 65536) : (short)intIdx; - } - - public void enableTexturing(int target) { - //gl.glEnable(target); - } - - public void disableTexturing(int target) { - //gl.glDisable(target); - } - - public void initTexture(int target, int width, int height, int format, int type) { - // Doing in patches of 16x16 pixels to avoid creating a (potentially) - // very large transient array which in certain situations (memory- - // constrained android devices) might lead to an out-of-memory error. - int[] texels = new int[16 * 16]; - for (int y = 0; y < height; y += 16) { - int h = PApplet.min(16, height - y); - for (int x = 0; x < width; x += 16) { - int w = PApplet.min(16, width - x); - GLES20.glTexSubImage2D(target, 0, x, y, w, h, format, type, IntBuffer.wrap(texels)); - } - } - } - - public String getShaderLog(int id) { - int[] compiled = new int[1]; - GLES20.glGetShaderiv(id, GLES20.GL_COMPILE_STATUS, compiled, 0); - if (compiled[0] == 0) { - return GLES20.glGetShaderInfoLog(id); - } else { - return ""; - } - } + } /////////////////////////////////////////////////////////////////////////////////// @@ -429,12 +365,12 @@ public class PGL { return true; } - public void beginOnscreenDraw() { + public void beginOnscreenDraw(boolean clear, int frame) { GLES20.glClearColor(0, 0, 0, 0); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); /* - if (clearColorBuffer) { + if (clear) { // Simplest scenario: clear mode means we clear both the color and depth buffers. // No need for saving front color buffer, etc. gl.glClearColor(0, 0, 0, 0); @@ -453,7 +389,7 @@ public class PGL { // Drawing contents of back color buffer as background. gl.glClearColor(0, 0, 0, 0); - if (parent.frameCount == 0) { + if (frame == 0) { // No need to draw back color buffer because we are in the first frame ever. gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); } else { @@ -466,7 +402,7 @@ public class PGL { if (texture != null) { gl.glClearColor(0, 0, 0, 0); gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); - if (0 < parent.frameCount) { + if (0 < frame) { drawTexture(); } } @@ -475,9 +411,9 @@ public class PGL { */ } - public void endOnscreenDraw() { + public void endOnscreenDraw(boolean clear0) { /* - if (!clearColorBuffer0) { + if (!clear0) { // We are in the primary surface, and no clear mode, this means that the current // contents of the front buffer needs to be used in the next frame as the background // for incremental rendering. Depending on whether or not FBOs are supported, @@ -507,22 +443,22 @@ public class PGL { } - public void beginOffscreenDraw() { + public void beginOffscreenDraw(boolean clear, int frame) { /* // Drawing contents of back color buffer as background. gl.glClearColor(0, 0, 0, 0); - if (clearColorBuffer || parent.frameCount == 0) { + if (clear || frame == 0) { // No need to draw back color buffer. - gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); } else { - gl.glClear(GL10.GL_DEPTH_BUFFER_BIT); + GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT); // Render previous draw texture as background. drawOffscreenTexture((offscreenIndex + 1) % 2); } - */ + */ } - public void endOffscreenDraw() { + public void endOffscreenDraw(boolean clear0) { //swapOffscreenIndex(); } @@ -536,7 +472,7 @@ public class PGL { } } - + /////////////////////////////////////////////////////////////////////////////////// // Caps query @@ -581,13 +517,17 @@ public class PGL { // Error handling - public int getError() { + public int glGetError() { return GLES20.glGetError(); } - public String getErrorString(int err) { + public String glErrorString(int err) { return GLU.gluErrorString(err); } + + public String gluErrorString(int err) { + return PGLU.gluErrorString(err); + } ///////////////////////////////////////////////////////////////////////////////// @@ -951,57 +891,52 @@ public class PGL { // Tessellator interface - // TODO: Implement. Options: - // 1) Port Java GLU tessellator implementation from JOGL. - // 2) Compile GLUES (http://code.google.com/p/glues/) in native code and access through JNI. - public Tessellator createTessellator(TessellatorCallback callback) { return new Tessellator(callback); } public class Tessellator { - //protected GLUtessellator tess; + protected PGLUtessellator tess; protected TessellatorCallback callback; - //protected GLUCallback gluCallback; + protected GLUCallback gluCallback; public Tessellator(TessellatorCallback callback) { this.callback = callback; - //tess = GLU.gluNewTess(); - //gluCallback = new GLUCallback(); + tess = PGLU.gluNewTess(); + gluCallback = new GLUCallback(); - //GLU.gluTessCallback(tess, GLU.GLU_TESS_BEGIN, gluCallback); - //GLU.gluTessCallback(tess, GLU.GLU_TESS_END, gluCallback); - //GLU.gluTessCallback(tess, GLU.GLU_TESS_VERTEX, gluCallback); - //GLU.gluTessCallback(tess, GLU.GLU_TESS_COMBINE, gluCallback); - //GLU.gluTessCallback(tess, GLU.GLU_TESS_ERROR, gluCallback); + PGLU.gluTessCallback(tess, PGLU.GLU_TESS_BEGIN, gluCallback); + PGLU.gluTessCallback(tess, PGLU.GLU_TESS_END, gluCallback); + PGLU.gluTessCallback(tess, PGLU.GLU_TESS_VERTEX, gluCallback); + PGLU.gluTessCallback(tess, PGLU.GLU_TESS_COMBINE, gluCallback); + PGLU.gluTessCallback(tess, PGLU.GLU_TESS_ERROR, gluCallback); } public void beginPolygon() { - //GLU.gluTessBeginPolygon(tess, null); + PGLU.gluTessBeginPolygon(tess, null); } public void endPolygon() { - //GLU.gluTessEndPolygon(tess); + PGLU.gluTessEndPolygon(tess); } public void setWindingRule(int rule) { - //GLU.gluTessProperty(tess, GLU.GLU_TESS_WINDING_RULE, rule); + PGLU.gluTessProperty(tess, PGLU.GLU_TESS_WINDING_RULE, rule); } public void beginContour() { - //GLU.gluTessBeginContour(tess); + PGLU.gluTessBeginContour(tess); } public void endContour() { - //GLU.gluTessEndContour(tess); + PGLU.gluTessEndContour(tess); } public void addVertex(double[] v) { - //GLU.gluTessVertex(tess, v, 0, v); + PGLU.gluTessVertex(tess, v, 0, v); } - /* - protected class GLUCallback extends GLUtessellatorCallbackAdapter { + protected class GLUCallback extends PGLUtessellatorCallbackAdapter { public void begin(int type) { callback.begin(type); } @@ -1023,7 +958,6 @@ public class PGL { callback.error(errnum); } } - */ } public interface TessellatorCallback { @@ -1033,7 +967,56 @@ public class PGL { public void combine(double[] coords, Object[] data, float[] weight, Object[] outData); public void error(int errnum); - } + } + + /////////////////////////////////////////////////////////////////////////////////// + + // Utility functions + + public boolean contextIsCurrent(Context other) { + return other.same(/*context*/); + } + + static public short makeIndex(int intIdx) { + // When the index value is greater than 32767, subtracting 65536 + // will make it (as a short) to wrap around to the negative range, which + // is all we need to later pass these numbers to opengl (which will + // interpret them as unsigned shorts). See discussion here: + // http://stackoverflow.com/questions/4331021/java-opengl-gldrawelements-with-32767-vertices + return 32767 < intIdx ? (short)(intIdx - 65536) : (short)intIdx; + } + + public void enableTexturing(int target) { + //gl.glEnable(target); + } + + public void disableTexturing(int target) { + //gl.glDisable(target); + } + + public void initTexture(int target, int width, int height, int format, int type) { + // Doing in patches of 16x16 pixels to avoid creating a (potentially) + // very large transient array which in certain situations (memory- + // constrained android devices) might lead to an out-of-memory error. + int[] texels = new int[16 * 16]; + for (int y = 0; y < height; y += 16) { + int h = PApplet.min(16, height - y); + for (int x = 0; x < width; x += 16) { + int w = PApplet.min(16, width - x); + GLES20.glTexSubImage2D(target, 0, x, y, w, h, format, type, IntBuffer.wrap(texels)); + } + } + } + + public String getShaderLog(int id) { + int[] compiled = new int[1]; + GLES20.glGetShaderiv(id, GLES20.GL_COMPILE_STATUS, compiled, 0); + if (compiled[0] == 0) { + return GLES20.glGetShaderInfoLog(id); + } else { + return ""; + } + } ///////////////////////////////////////////////////////////////////////////////// @@ -1057,26 +1040,6 @@ public class PGL { public void onDrawFrame(GL10 igl) { gl = igl; - - /* - try { - gl11 = (GL11) gl; - } catch (ClassCastException cce) { - gl11 = null; - } - - try { - gl11x = (GL11Ext) gl; - } catch (ClassCastException cce) { - gl11x = null; - } - - try { - gl11xp = (GL11ExtensionPack) gl; - } catch (ClassCastException cce) { - gl11xp = null; - } - */ pg.parent.handleDraw(); } @@ -1084,52 +1047,13 @@ public class PGL { gl = igl; // Here is where we should initialize native libs... - // PGL2JNILib.init(iwidth, iheight); + // lib.init(iwidth, iheight); - /* - try { - gl11 = (GL11) gl; - } catch (ClassCastException cce) { - gl11 = null; - } - - try { - gl11x = (GL11Ext) gl; - } catch (ClassCastException cce) { - gl11x = null; - } - - try { - gl11xp = (GL11ExtensionPack) gl; - } catch (ClassCastException cce) { - gl11xp = null; - } - */ pg.setSize(iwidth, iheight); } public void onSurfaceCreated(GL10 igl, EGLConfig config) { gl = igl; - - /* - try { - gl11 = (GL11) gl; - } catch (ClassCastException cce) { - gl11 = null; - } - - try { - gl11x = (GL11Ext) gl; - } catch (ClassCastException cce) { - gl11x = null; - } - - try { - gl11xp = (GL11ExtensionPack) gl; - } catch (ClassCastException cce) { - gl11xp = null; - } - */ } } diff --git a/android/core/src/processing/core/PGraphics.java b/android/core/src/processing/core/PGraphics.java index e3a4a7675..3ee5a53e8 100644 --- a/android/core/src/processing/core/PGraphics.java +++ b/android/core/src/processing/core/PGraphics.java @@ -1203,7 +1203,17 @@ public class PGraphics extends PImage implements PConstants { "or shapes with holes."); } - + + public void beginContour() { + showMissingWarning("beginContour"); + } + + + public void endContour() { + showMissingWarning("endContour"); + } + + public void endShape() { endShape(OPEN); } diff --git a/android/core/src/processing/core/PGraphicsAndroid3D.java b/android/core/src/processing/core/PGraphicsAndroid3D.java index 05588414f..b498b93ad 100644 --- a/android/core/src/processing/core/PGraphicsAndroid3D.java +++ b/android/core/src/processing/core/PGraphicsAndroid3D.java @@ -307,6 +307,10 @@ public class PGraphicsAndroid3D extends PGraphics { protected int[] savedViewport = {0, 0, 0, 0}; protected int[] viewport = {0, 0, 0, 0}; + /** Used to register calls to glClear. */ + protected boolean clearColorBuffer; + protected boolean clearColorBuffer0; + protected boolean openContour = false; protected boolean breakShape = false; protected boolean defaultEdges = false; @@ -1456,13 +1460,16 @@ public class PGraphicsAndroid3D extends PGraphics { pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT | PGL.GL_STENCIL_BUFFER_BIT); if (primarySurface) { - pgl.beginOnscreenDraw(); + pgl.beginOnscreenDraw(clearColorBuffer, parent.frameCount); } else { - pgl.beginOffscreenDraw(); + pgl.beginOffscreenDraw(clearColorBuffer, parent.frameCount); } drawing = true; + clearColorBuffer0 = clearColorBuffer; + clearColorBuffer = false; + report("bot beginDraw()"); } @@ -1492,7 +1499,7 @@ public class PGraphicsAndroid3D extends PGraphics { // operation. Thus, only the main renderer (the primary surface) // should call it at the end of draw, and none of the offscreen // renderers... - pgl.endOnscreenDraw(); + pgl.endOnscreenDraw(clearColorBuffer0); pgl.glFlush(); pgl.releaseContext(); } else { @@ -1501,7 +1508,7 @@ public class PGraphicsAndroid3D extends PGraphics { } popFramebuffer(); - pgl.endOffscreenDraw(); + pgl.endOffscreenDraw(clearColorBuffer0); pg.restoreGLState(); } @@ -2038,7 +2045,7 @@ public class PGraphicsAndroid3D extends PGraphics { } if (breakShape) { - code = BREAK; + code = PShape.BREAK; breakShape = false; } @@ -4266,6 +4273,7 @@ public class PGraphicsAndroid3D extends PGraphics { protected void backgroundImpl(PImage image) { backgroundImpl(); set(0, 0, image); + clearColorBuffer = true; } protected void backgroundImpl() { @@ -4276,7 +4284,8 @@ public class PGraphicsAndroid3D extends PGraphics { pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT); pgl.glClearColor(backgroundR, backgroundG, backgroundB, 1); - pgl.glClear(PGL.GL_COLOR_BUFFER_BIT); + pgl.glClear(PGL.GL_COLOR_BUFFER_BIT); + clearColorBuffer = true; } ////////////////////////////////////////////////////////////// @@ -4325,10 +4334,9 @@ public class PGraphicsAndroid3D extends PGraphics { */ public void report(String where) { if (!hints[DISABLE_OPENGL_ERROR_REPORT]) { - int err = pgl.getError(); + int err = pgl.glGetError(); if (err != 0) { - //String errString = glu.gluErrorString(err); - String errString = pgl.getErrorString(err); + String errString = pgl.glErrorString(err); String msg = "OpenGL error " + err + " at " + where + ": " + errString; PGraphics.showWarning(msg); } @@ -5483,8 +5491,6 @@ public class PGraphicsAndroid3D extends PGraphics { offscreenFramebufferMultisample.clear(); offscreenMultisample = true; - pg.report("after cleaning fbm"); - // The offscreen framebuffer where the multisampled image is finally drawn to doesn't // need depth and stencil buffers since they are part of the multisampled framebuffer. offscreenFramebuffer = new PFramebuffer(parent, texture.glWidth, texture.glHeight, 1, 1, @@ -8703,12 +8709,34 @@ public class PGraphicsAndroid3D extends PGraphics { gluTess.beginContour(); } + // Separting colors into individual rgba components for interpolation. + int fa = (in.colors[i] >> 24) & 0xFF; + int fr = (in.colors[i] >> 16) & 0xFF; + int fg = (in.colors[i] >> 8) & 0xFF; + int fb = (in.colors[i] >> 0) & 0xFF; + + int aa = (in.ambient[i] >> 24) & 0xFF; + int ar = (in.ambient[i] >> 16) & 0xFF; + int ag = (in.ambient[i] >> 8) & 0xFF; + int ab = (in.ambient[i] >> 0) & 0xFF; + + int sa = (in.specular[i] >> 24) & 0xFF; + int sr = (in.specular[i] >> 16) & 0xFF; + int sg = (in.specular[i] >> 8) & 0xFF; + int sb = (in.specular[i] >> 0) & 0xFF; + + int ea = (in.emissive[i] >> 24) & 0xFF; + int er = (in.emissive[i] >> 16) & 0xFF; + int eg = (in.emissive[i] >> 8) & 0xFF; + int eb = (in.emissive[i] >> 0) & 0xFF; + // Vertex data includes coordinates, colors, normals, texture coordinates, and material properties. double[] vertex = new double[] { in.vertices [3 * i + 0], in.vertices [3 * i + 1], in.vertices[3 * i + 2], - in.colors [i], + fa, fr, fg, fb, in.normals [3 * i + 0], in.normals [3 * i + 1], in.normals [3 * i + 2], in.texcoords[2 * i + 0], in.texcoords[2 * i + 1], - in.ambient[i], in.specular[i], in.emissive[i], in.shininess[i] }; + aa, ar, ag, ab, sa, sr, sg, sb, ea, er, eg, eb, + in.shininess[i] }; gluTess.addVertex(vertex); } @@ -8870,19 +8898,26 @@ public class PGraphicsAndroid3D extends PGraphics { public void vertex(Object data) { if (data instanceof double[]) { double[] d = (double[]) data; - if (d.length < 13) { - throw new RuntimeException("TessCallback vertex() data is not of length 13"); + if (d.length < 25) { + throw new RuntimeException("TessCallback vertex() data is not of length 25"); } - // We need to use separate rgba components for correct interpolation... - if (tess.fillVertexCount < PGL.MAX_TESS_VERTICES) { - tess.addFillVertex((float) d[0], (float) d[ 1], (float) d[ 2], - (int) d[3], - (float) d[4], (float) d[ 5], (float) d[ 6], - (float) d[7], (float) d[ 8], - (int) d[9], (int) d[10], (int) d[11], (float) d[12]); - tessCount++; + + // Combining individual rgba components back into int color values + int fcolor = ((int) d[ 3] << 24) | ((int) d[ 4] << 16) | ((int) d[ 5] << 8) | (int) d[ 6]; + int acolor = ((int) d[12] << 24) | ((int) d[13] << 16) | ((int) d[14] << 8) | (int) d[15]; + int scolor = ((int) d[16] << 24) | ((int) d[17] << 16) | ((int) d[18] << 8) | (int) d[19]; + int ecolor = ((int) d[20] << 24) | ((int) d[21] << 16) | ((int) d[22] << 8) | (int) d[23]; + + tess.addFillVertex((float) d[ 0], (float) d[ 1], (float) d[ 2], + fcolor, + (float) d[ 7], (float) d[ 8], (float) d[ 9], + (float) d[10], (float) d[11], + acolor, scolor, ecolor, + (float) d[24]); + + tessCount++; } else { throw new RuntimeException("P3D: the tessellator is generating too many vertices, reduce complexity of shape."); } @@ -8893,7 +8928,7 @@ public class PGraphicsAndroid3D extends PGraphics { } public void error(int errnum) { - String estring = pgl.getErrorString(errnum); + String estring = pgl.gluErrorString(errnum); PGraphics.showWarning("Tessellation Error: " + estring); } @@ -8912,7 +8947,7 @@ public class PGraphicsAndroid3D extends PGraphics { */ public void combine(double[] coords, Object[] data, float[] weight, Object[] outData) { - double[] vertex = new double[13]; + double[] vertex = new double[25]; vertex[0] = coords[0]; vertex[1] = coords[1]; vertex[2] = coords[2]; @@ -8922,35 +8957,12 @@ public class PGraphicsAndroid3D extends PGraphics { // Calculating the rest of the vertex parameters (color, // normal, texcoords) as the linear combination of the // combined vertices. - for (int i = 3; i < 13; i++) { + for (int i = 3; i < 25; i++) { vertex[i] = 0; for (int j = 0; j < 4; j++) { double[] vertData = (double[])data[j]; if (vertData != null) { - if (i == 3 || 8 < i) { - // Color data, needs to be split into rgba components - // for interpolation. - int colorj = (int) vertData[i]; - int xj = (colorj >> 24) & 0xFF; - int yj = (colorj >> 16) & 0xFF; - int zj = (colorj >> 8) & 0xFF; - int wj = (colorj >> 0) & 0xFF; - - int colori = (int) vertex[i]; - int xi = (colori >> 24) & 0xFF; - int yi = (colori >> 16) & 0xFF; - int zi = (colori >> 8) & 0xFF; - int wi = (colori >> 0) & 0xFF; - - xi += weight[j] * xj; - yi += weight[j] * yj; - zi += weight[j] * zj; - wi += weight[j] * wj; - - vertex[i] = (xi << 24) | (yi << 16) | (zi << 8) | wi; - } else { - vertex[i] += weight[j] * vertData[i]; - } + vertex[i] += weight[j] * vertData[i]; } } } diff --git a/java/libraries/opengl/src/processing/opengl/PGL.java b/java/libraries/opengl/src/processing/opengl/PGL.java index c355b40bc..43fbff4fe 100644 --- a/java/libraries/opengl/src/processing/opengl/PGL.java +++ b/java/libraries/opengl/src/processing/opengl/PGL.java @@ -219,9 +219,6 @@ public class PGL { public static final int GL_LINE_SMOOTH = GL.GL_LINE_SMOOTH; public static final int GL_POLYGON_SMOOTH = GL2.GL_POLYGON_SMOOTH; - /** Pipeline mode: FIXED, PROG_GL2, PROG_GL3 or PROG_GL4 */ - public int pipeline; - /** Basic GL functionality, common to all profiles */ public GL gl; @@ -310,46 +307,11 @@ public class PGL { } } - profile = null; - - //profile = GLProfile.getDefault(); + // For the time being we use the fixed function profile + // because GL3 is not supported in MacOSX Snow Leopard. profile = GLProfile.getMaxFixedFunc(); + //profile = GLProfile.getMaxProgrammable(); - //profile = GLProfile.get(GLProfile.GL2ES1); - //profile = GLProfile.get(GLProfile.GL4bc); - //profile = GLProfile.getMaxProgrammable(); - //pipeline = PGL.FIXED; - - /* - // Profile auto-selection disabled for the time being. - // TODO: Implement programmable pipeline :-) - try { - profile = GLProfile.get(GLProfile.GL4); - pipeline = PROG_GL4; - } catch (GLException e) {} - - if (profile == null) { - try { - profile = GLProfile.get(GLProfile.GL3); - pipeline = PROG_GL3; - } catch (GLException e) {} - } - - if (profile == null) { - try { - profile = GLProfile.get(GLProfile.GL2ES2); - pipeline = PROG_GL2; - } catch (GLException e) {} - } - - if (profile == null) { - try { - profile = GLProfile.get(GLProfile.GL2ES1); - pipeline = FIXED; - } catch (GLException e) {} - } - */ - if (profile == null) { pg.parent.die("Cannot get a valid OpenGL profile"); } @@ -413,52 +375,6 @@ public class PGL { public void destroyContext() { context.destroy(); context = null; - } - - /////////////////////////////////////////////////////////////////////////////////// - - // Utilities - - public boolean contextIsCurrent(Context other) { - return other.same(context); - } - - static public int makeIndex(int intIdx) { - return intIdx; - } - - public void enableTexturing(int target) { - gl.glEnable(target); - } - - public void disableTexturing(int target) { - gl.glDisable(target); - } - - public void initTexture(int target, int width, int height, int format, int type) { - int[] texels = new int[width * height]; - gl.glTexSubImage2D(target, 0, 0, 0, width, height, format, type, IntBuffer.wrap(texels)); - } - - public String getShaderLog(int id) { - IntBuffer val = IntBuffer.allocate(1); - gl2.glGetObjectParameterivARB(id, GL2.GL_OBJECT_INFO_LOG_LENGTH_ARB, val); - - int length = val.get(); - - if (length <= 1) { - return ""; - } - - // Some error occurred... - ByteBuffer infoLog = ByteBuffer.allocate(length); - val.flip(); - - gl2.glGetInfoLogARB(id, length, val, infoLog); - - byte[] infoBytes = new byte[length]; - infoLog.get(infoBytes); - return new String(infoBytes); } /////////////////////////////////////////////////////////////////////////////////// @@ -479,19 +395,19 @@ public class PGL { return false; } - public void beginOnscreenDraw() { + public void beginOnscreenDraw(boolean clear, int frame) { } - public void endOnscreenDraw() { + public void endOnscreenDraw(boolean clear0) { if (drawable != null) { drawable.swapBuffers(); } } - public void beginOffscreenDraw() { + public void beginOffscreenDraw(boolean clear, int frame) { } - public void endOffscreenDraw() { + public void endOffscreenDraw(boolean clear0) { } public boolean canDraw() { @@ -545,11 +461,15 @@ public class PGL { // Error handling - public int getError() { + public int glGetError() { return gl.glGetError(); } + + public String glErrorString(int err) { + return glu.gluErrorString(err); + } - public String getErrorString(int err) { + public String gluErrorString(int err) { return glu.gluErrorString(err); } @@ -557,7 +477,7 @@ public class PGL { // Rendering options - public void setFrontFace(int mode) { + public void glFrontFace(int mode) { gl.glFrontFace(mode); } @@ -565,7 +485,7 @@ public class PGL { gl.glDepthMask(flag); } - public void setDepthFunc(int func) { + public void glDepthFunc(int func) { gl.glDepthFunc(func); } @@ -987,5 +907,51 @@ public class PGL { public void combine(double[] coords, Object[] data, float[] weight, Object[] outData); public void error(int errnum); - } + } + + /////////////////////////////////////////////////////////////////////////////////// + + // Utility functions + + public boolean contextIsCurrent(Context other) { + return other.same(context); + } + + static public int makeIndex(int intIdx) { + return intIdx; + } + + public void enableTexturing(int target) { + gl.glEnable(target); + } + + public void disableTexturing(int target) { + gl.glDisable(target); + } + + public void initTexture(int target, int width, int height, int format, int type) { + int[] texels = new int[width * height]; + gl.glTexSubImage2D(target, 0, 0, 0, width, height, format, type, IntBuffer.wrap(texels)); + } + + public String getShaderLog(int id) { + IntBuffer val = IntBuffer.allocate(1); + gl2.glGetObjectParameterivARB(id, GL2.GL_OBJECT_INFO_LOG_LENGTH_ARB, val); + + int length = val.get(); + + if (length <= 1) { + return ""; + } + + // Some error occurred... + ByteBuffer infoLog = ByteBuffer.allocate(length); + val.flip(); + + gl2.glGetInfoLogARB(id, length, val, infoLog); + + byte[] infoBytes = new byte[length]; + infoLog.get(infoBytes); + return new String(infoBytes); + } } diff --git a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java index 172c4a05b..618bfbb9f 100644 --- a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java +++ b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java @@ -314,6 +314,10 @@ public class PGraphicsOpenGL extends PGraphics { protected int[] savedViewport = {0, 0, 0, 0}; protected int[] viewport = {0, 0, 0, 0}; + /** Used to register calls to glClear. */ + protected boolean clearColorBuffer; + protected boolean clearColorBuffer0; + protected boolean openContour = false; protected boolean breakShape = false; protected boolean defaultEdges = false; @@ -1391,7 +1395,7 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glEnable(PGL.GL_DEPTH_TEST); } // use <= since that's what processing.core does - pgl.setDepthFunc(PGL.GL_LEQUAL); + pgl.glDepthFunc(PGL.GL_LEQUAL); if (hints[DISABLE_DEPTH_MASK]) { pgl.glDepthMask(false); @@ -1450,7 +1454,7 @@ public class PGraphicsOpenGL extends PGraphics { lightSpecular(0, 0, 0); // because y is flipped - pgl.setFrontFace(PGL.GL_CW); + pgl.glFrontFace(PGL.GL_CW); // Processing uses only one texture unit. pgl.glActiveTexture(PGL.GL_TEXTURE0); @@ -1463,13 +1467,16 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT | PGL.GL_STENCIL_BUFFER_BIT); if (primarySurface) { - pgl.beginOnscreenDraw(); + pgl.beginOnscreenDraw(clearColorBuffer, parent.frameCount); } else { - pgl.beginOffscreenDraw(); + pgl.beginOffscreenDraw(clearColorBuffer, parent.frameCount); } drawing = true; + clearColorBuffer0 = clearColorBuffer; + clearColorBuffer = false; + report("bot beginDraw()"); } @@ -1499,7 +1506,7 @@ public class PGraphicsOpenGL extends PGraphics { // operation. Thus, only the main renderer (the primary surface) // should call it at the end of draw, and none of the offscreen // renderers... - pgl.endOnscreenDraw(); + pgl.endOnscreenDraw(clearColorBuffer0); pgl.glFlush(); pgl.releaseContext(); } else { @@ -1508,7 +1515,7 @@ public class PGraphicsOpenGL extends PGraphics { } popFramebuffer(); - pgl.endOffscreenDraw(); + pgl.endOffscreenDraw(clearColorBuffer0); pg.restoreGLState(); } @@ -1569,8 +1576,8 @@ public class PGraphicsOpenGL extends PGraphics { // but we want to make sure they return to the Processing // defaults (plus these cannot be changed through the API // so they should remain constant anyways): - pgl.setFrontFace(PGL.GL_CW); - pgl.setDepthFunc(PGL.GL_LEQUAL); + pgl.glFrontFace(PGL.GL_CW); + pgl.glDepthFunc(PGL.GL_LEQUAL); } @@ -2045,7 +2052,7 @@ public class PGraphicsOpenGL extends PGraphics { } if (breakShape) { - code = BREAK; + code = PShape.BREAK; breakShape = false; } @@ -4273,6 +4280,7 @@ public class PGraphicsOpenGL extends PGraphics { protected void backgroundImpl(PImage image) { backgroundImpl(); set(0, 0, image); + clearColorBuffer = true; } protected void backgroundImpl() { @@ -4283,7 +4291,8 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT); pgl.glClearColor(backgroundR, backgroundG, backgroundB, 1); - pgl.glClear(PGL.GL_COLOR_BUFFER_BIT); + pgl.glClear(PGL.GL_COLOR_BUFFER_BIT); + clearColorBuffer = true; } ////////////////////////////////////////////////////////////// @@ -4332,10 +4341,9 @@ public class PGraphicsOpenGL extends PGraphics { */ public void report(String where) { if (!hints[DISABLE_OPENGL_ERROR_REPORT]) { - int err = pgl.getError(); + int err = pgl.glGetError(); if (err != 0) { - //String errString = glu.gluErrorString(err); - String errString = pgl.getErrorString(err); + String errString = pgl.glErrorString(err); String msg = "OpenGL error " + err + " at " + where + ": " + errString; PGraphics.showWarning(msg); } @@ -5490,8 +5498,6 @@ public class PGraphicsOpenGL extends PGraphics { offscreenFramebufferMultisample.clear(); offscreenMultisample = true; - pg.report("after cleaning fbm"); - // The offscreen framebuffer where the multisampled image is finally drawn to doesn't // need depth and stencil buffers since they are part of the multisampled framebuffer. offscreenFramebuffer = new PFramebuffer(parent, texture.glWidth, texture.glHeight, 1, 1, @@ -8710,12 +8716,35 @@ public class PGraphicsOpenGL extends PGraphics { gluTess.beginContour(); } + // Separting colors into individual rgba components for interpolation. + int fa = (in.colors[i] >> 24) & 0xFF; + int fr = (in.colors[i] >> 16) & 0xFF; + int fg = (in.colors[i] >> 8) & 0xFF; + int fb = (in.colors[i] >> 0) & 0xFF; + + int aa = (in.ambient[i] >> 24) & 0xFF; + int ar = (in.ambient[i] >> 16) & 0xFF; + int ag = (in.ambient[i] >> 8) & 0xFF; + int ab = (in.ambient[i] >> 0) & 0xFF; + + int sa = (in.specular[i] >> 24) & 0xFF; + int sr = (in.specular[i] >> 16) & 0xFF; + int sg = (in.specular[i] >> 8) & 0xFF; + int sb = (in.specular[i] >> 0) & 0xFF; + + int ea = (in.emissive[i] >> 24) & 0xFF; + int er = (in.emissive[i] >> 16) & 0xFF; + int eg = (in.emissive[i] >> 8) & 0xFF; + int eb = (in.emissive[i] >> 0) & 0xFF; + // Vertex data includes coordinates, colors, normals, texture coordinates, and material properties. double[] vertex = new double[] { in.vertices [3 * i + 0], in.vertices [3 * i + 1], in.vertices[3 * i + 2], - in.colors [i], + fa, fr, fg, fb, in.normals [3 * i + 0], in.normals [3 * i + 1], in.normals [3 * i + 2], in.texcoords[2 * i + 0], in.texcoords[2 * i + 1], - in.ambient[i], in.specular[i], in.emissive[i], in.shininess[i] }; + aa, ar, ag, ab, sa, sr, sg, sb, ea, er, eg, eb, + in.shininess[i] }; + gluTess.addVertex(vertex); } gluTess.endContour(); @@ -8876,19 +8905,26 @@ public class PGraphicsOpenGL extends PGraphics { public void vertex(Object data) { if (data instanceof double[]) { double[] d = (double[]) data; - if (d.length < 13) { - throw new RuntimeException("TessCallback vertex() data is not of length 13"); + if (d.length < 25) { + throw new RuntimeException("TessCallback vertex() data is not of length 25"); } - // We need to use separate rgba components for correct interpolation... - if (tess.fillVertexCount < PGL.MAX_TESS_VERTICES) { - tess.addFillVertex((float) d[0], (float) d[ 1], (float) d[ 2], - (int) d[3], - (float) d[4], (float) d[ 5], (float) d[ 6], - (float) d[7], (float) d[ 8], - (int) d[9], (int) d[10], (int) d[11], (float) d[12]); - tessCount++; + + // Combining individual rgba components back into int color values + int fcolor = ((int) d[ 3] << 24) | ((int) d[ 4] << 16) | ((int) d[ 5] << 8) | (int) d[ 6]; + int acolor = ((int) d[12] << 24) | ((int) d[13] << 16) | ((int) d[14] << 8) | (int) d[15]; + int scolor = ((int) d[16] << 24) | ((int) d[17] << 16) | ((int) d[18] << 8) | (int) d[19]; + int ecolor = ((int) d[20] << 24) | ((int) d[21] << 16) | ((int) d[22] << 8) | (int) d[23]; + + tess.addFillVertex((float) d[ 0], (float) d[ 1], (float) d[ 2], + fcolor, + (float) d[ 7], (float) d[ 8], (float) d[ 9], + (float) d[10], (float) d[11], + acolor, scolor, ecolor, + (float) d[24]); + + tessCount++; } else { throw new RuntimeException("P3D: the tessellator is generating too many vertices, reduce complexity of shape."); } @@ -8899,7 +8935,7 @@ public class PGraphicsOpenGL extends PGraphics { } public void error(int errnum) { - String estring = pgl.getErrorString(errnum); + String estring = pgl.gluErrorString(errnum); PGraphics.showWarning("Tessellation Error: " + estring); } @@ -8918,7 +8954,7 @@ public class PGraphicsOpenGL extends PGraphics { */ public void combine(double[] coords, Object[] data, float[] weight, Object[] outData) { - double[] vertex = new double[13]; + double[] vertex = new double[25]; vertex[0] = coords[0]; vertex[1] = coords[1]; vertex[2] = coords[2]; @@ -8928,35 +8964,12 @@ public class PGraphicsOpenGL extends PGraphics { // Calculating the rest of the vertex parameters (color, // normal, texcoords) as the linear combination of the // combined vertices. - for (int i = 3; i < 13; i++) { + for (int i = 3; i < 25; i++) { vertex[i] = 0; for (int j = 0; j < 4; j++) { double[] vertData = (double[])data[j]; if (vertData != null) { - if (i == 3 || 8 < i) { - // Color data, needs to be split into rgba components - // for interpolation. - int colorj = (int) vertData[i]; - int xj = (colorj >> 24) & 0xFF; - int yj = (colorj >> 16) & 0xFF; - int zj = (colorj >> 8) & 0xFF; - int wj = (colorj >> 0) & 0xFF; - - int colori = (int) vertex[i]; - int xi = (colori >> 24) & 0xFF; - int yi = (colori >> 16) & 0xFF; - int zi = (colori >> 8) & 0xFF; - int wi = (colori >> 0) & 0xFF; - - xi += weight[j] * xj; - yi += weight[j] * yj; - zi += weight[j] * zj; - wi += weight[j] * wj; - - vertex[i] = (xi << 24) | (yi << 16) | (zi << 8) | wi; - } else { - vertex[i] += weight[j] * vertData[i]; - } + vertex[i] += weight[j] * vertData[i]; } } }