diff --git a/java/libraries/opengl/.classpath b/java/libraries/opengl/.classpath index 32bff8c73..d5a1ed1b8 100644 --- a/java/libraries/opengl/.classpath +++ b/java/libraries/opengl/.classpath @@ -5,6 +5,5 @@ - diff --git a/java/libraries/opengl/build.xml b/java/libraries/opengl/build.xml index 0ae6c8f28..e9cf977a9 100644 --- a/java/libraries/opengl/build.xml +++ b/java/libraries/opengl/build.xml @@ -17,7 +17,7 @@ srcdir="src" destdir="bin" encoding="UTF-8" includeAntRuntime="false" - classpath="../../../core/core.jar; library/jogl.all.jar; library/gluegen-rt.jar; library/nativewindow.all.jar" /> + classpath="../../../core/core.jar; library/jogl.all.jar; library/gluegen-rt.jar" /> diff --git a/java/libraries/opengl/examples/Image/SmoothChange/SmoothChange.pde b/java/libraries/opengl/examples/Image/SmoothChange/SmoothChange.pde deleted file mode 100644 index 286adb1bf..000000000 --- a/java/libraries/opengl/examples/Image/SmoothChange/SmoothChange.pde +++ /dev/null @@ -1,26 +0,0 @@ -PImage img; -int level = 2; - -public void setup() { - size(200, 200, P3D); - frameRate(90); - smooth(level); - - img = loadImage("milan_rubbish.jpg"); -} - -public void draw () { - background(0); - - tint(255, 150); - image(img, 0, 0, width, height); - - fill(255); - text("current smooth: " + level, mouseX, mouseY); -} - -void keyPressed() { - level = 4; - smooth(level); -} - diff --git a/java/libraries/opengl/examples/Performance/CubicGridImmediate/CubicGridImmediate.pde b/java/libraries/opengl/examples/Performance/CubicGridImmediate/CubicGridImmediate.pde index e505c1f0d..c6089cd3e 100644 --- a/java/libraries/opengl/examples/Performance/CubicGridImmediate/CubicGridImmediate.pde +++ b/java/libraries/opengl/examples/Performance/CubicGridImmediate/CubicGridImmediate.pde @@ -17,7 +17,8 @@ int fint = 3; void setup() { size(640, 360, P3D); - frameRate(120); + frameRate(60); + noSmooth(); noStroke(); } @@ -49,6 +50,8 @@ void draw() { } popMatrix(); + hint(ENABLE_DEPTH_TEST); + fcount += 1; int m = millis(); if (m - lastm > 1000 * fint) { diff --git a/java/libraries/opengl/examples/Performance/CubicGridRetained/CubicGridRetained.pde b/java/libraries/opengl/examples/Performance/CubicGridRetained/CubicGridRetained.pde index eaea9de87..e431860cd 100644 --- a/java/libraries/opengl/examples/Performance/CubicGridRetained/CubicGridRetained.pde +++ b/java/libraries/opengl/examples/Performance/CubicGridRetained/CubicGridRetained.pde @@ -11,7 +11,8 @@ int fint = 3; void setup() { size(640, 360, P3D); - frameRate(120); + frameRate(60); + noSmooth(); noStroke(); grid = createShape(PShape.GROUP); @@ -98,6 +99,8 @@ void draw() { shape(grid); popMatrix(); + hint(ENABLE_DEPTH_TEST); + fcount += 1; int m = millis(); if (m - lastm > 1000 * fint) { diff --git a/java/libraries/opengl/examples/Performance/DynamicParticlesImmediate/DynamicParticlesImmediate.pde b/java/libraries/opengl/examples/Performance/DynamicParticlesImmediate/DynamicParticlesImmediate.pde index 418a9947d..edc5d15c9 100644 --- a/java/libraries/opengl/examples/Performance/DynamicParticlesImmediate/DynamicParticlesImmediate.pde +++ b/java/libraries/opengl/examples/Performance/DynamicParticlesImmediate/DynamicParticlesImmediate.pde @@ -17,7 +17,7 @@ int fint = 3; void setup() { size(640, 480, P3D); - frameRate(240); + frameRate(120); sprite = loadImage("sprite.png"); diff --git a/java/libraries/opengl/examples/Performance/DynamicParticlesRetained/DynamicParticlesRetained.pde b/java/libraries/opengl/examples/Performance/DynamicParticlesRetained/DynamicParticlesRetained.pde index 4eb633fd7..42f8f659e 100644 --- a/java/libraries/opengl/examples/Performance/DynamicParticlesRetained/DynamicParticlesRetained.pde +++ b/java/libraries/opengl/examples/Performance/DynamicParticlesRetained/DynamicParticlesRetained.pde @@ -17,7 +17,7 @@ int fint = 3; void setup() { size(640, 480, P3D); - frameRate(240); + frameRate(120); particles = createShape(PShape.GROUP); sprite = loadImage("sprite.png"); diff --git a/java/libraries/opengl/examples/Performance/Esfera/Esfera.pde b/java/libraries/opengl/examples/Performance/Esfera/Esfera.pde index f418792c2..329af409b 100755 --- a/java/libraries/opengl/examples/Performance/Esfera/Esfera.pde +++ b/java/libraries/opengl/examples/Performance/Esfera/Esfera.pde @@ -16,6 +16,8 @@ float ry =0; void setup() { size(1024, 768, P3D); + noSmooth(); + frameRate(120); radio = height/3.5; lista = new pelo[cuantos]; diff --git a/java/libraries/opengl/examples/Performance/StaticParticlesImmediate/StaticParticlesImmediate.pde b/java/libraries/opengl/examples/Performance/StaticParticlesImmediate/StaticParticlesImmediate.pde index 2f1d76a90..366f9f7ad 100644 --- a/java/libraries/opengl/examples/Performance/StaticParticlesImmediate/StaticParticlesImmediate.pde +++ b/java/libraries/opengl/examples/Performance/StaticParticlesImmediate/StaticParticlesImmediate.pde @@ -11,7 +11,7 @@ int fint = 3; void setup() { size(800, 600, P3D); - frameRate(240); + frameRate(60); sprite = loadImage("sprite.png"); diff --git a/java/libraries/opengl/examples/Performance/StaticParticlesRetained/StaticParticlesRetained.pde b/java/libraries/opengl/examples/Performance/StaticParticlesRetained/StaticParticlesRetained.pde index ccb67ed5d..8b63c6943 100644 --- a/java/libraries/opengl/examples/Performance/StaticParticlesRetained/StaticParticlesRetained.pde +++ b/java/libraries/opengl/examples/Performance/StaticParticlesRetained/StaticParticlesRetained.pde @@ -10,7 +10,7 @@ int fint = 3; void setup() { size(800, 600, P3D); - frameRate(240); + frameRate(60); particles = createShape(PShape.GROUP); sprite = loadImage("sprite.png"); diff --git a/java/libraries/opengl/examples/Tests/RedrawTest/RedrawTest.pde b/java/libraries/opengl/examples/Tests/RedrawTest/RedrawTest.pde new file mode 100644 index 000000000..7cd352736 --- /dev/null +++ b/java/libraries/opengl/examples/Tests/RedrawTest/RedrawTest.pde @@ -0,0 +1,14 @@ +void setup() { + size(400, 400, P3D); + noLoop(); +} + +void draw() { + background(255, 0, 0); + ellipse(mouseX, mouseY, 100, 50); + println("draw"); +} + +void keyPressed() { + redraw(); +} diff --git a/java/libraries/opengl/examples/Tests/ResizeTest/ResizeTest.pde b/java/libraries/opengl/examples/Tests/ResizeTest/ResizeTest.pde new file mode 100644 index 000000000..5e6fe68bf --- /dev/null +++ b/java/libraries/opengl/examples/Tests/ResizeTest/ResizeTest.pde @@ -0,0 +1,10 @@ +void setup() { + size(400, 400, P3D); + frame.setResizable(true); +} + +void draw() { + background(255, 0, 0); + ellipse(width/2, height/2, 100, 50); +} + diff --git a/java/libraries/opengl/examples/Tests/SmoothTest/SmoothTest.pde b/java/libraries/opengl/examples/Tests/SmoothTest/SmoothTest.pde new file mode 100644 index 000000000..dfefb30a4 --- /dev/null +++ b/java/libraries/opengl/examples/Tests/SmoothTest/SmoothTest.pde @@ -0,0 +1,19 @@ +void setup() { + size(400, 400, P3D); + smooth(2); +} + +void draw() { + background(255, 0, 0); + ellipse(mouseX, mouseY, 100, 100); +} + +void keyPressed() { + if (key == '1') smooth(1); + else if (key == '2') smooth(2); + else if (key == '3') smooth(4); + else if (key == '4') smooth(8); + else if (key == '5') smooth(16); + else if (key == '6') smooth(32); +} + diff --git a/java/libraries/opengl/library/export.txt b/java/libraries/opengl/library/export.txt index bbbdbad5f..7d127f6b1 100644 --- a/java/libraries/opengl/library/export.txt +++ b/java/libraries/opengl/library/export.txt @@ -8,3 +8,9 @@ name = OpenGL # on the user's computer, rather than increasing the download size with # the versions for each platform. applet = opengl.jar + +application.macosx=opengl.jar,jogl.all.jar,gluegen-rt.jar,jogl-all-natives-macosx-universal.jar,gluegen-rt-natives-macosx-universal.jar +application.windows32=opengl.jar,jogl.all.jar,gluegen-rt.jar,jogl-all-natives-windows-i586.jar,gluegen-rt-natives-windows-i586.jar +application.windows64=opengl.jar,jogl.all.jar,gluegen-rt.jar,jogl-all-natives-windows-amd64.jar,gluegen-rt-natives-windows-amd64.jar +application.linux32=opengl.jar,jogl.all.jar,gluegen-rt.jar,jogl-all-natives-linux-i586.jar,gluegen-rt-natives-linux-i586.jar +application.linux64=opengl.jar,jogl.all.jar,gluegen-rt.jar,jogl-all-natives-linux-amd64.jar,gluegen-rt-natives-linux-amd64.jar \ No newline at end of file diff --git a/java/libraries/opengl/src/processing/opengl/PFontTexture.java b/java/libraries/opengl/src/processing/opengl/PFontTexture.java index 423ef5f80..ff4cccb21 100644 --- a/java/libraries/opengl/src/processing/opengl/PFontTexture.java +++ b/java/libraries/opengl/src/processing/opengl/PFontTexture.java @@ -51,8 +51,7 @@ import java.util.HashMap; class PFontTexture implements PConstants { protected PApplet parent; protected PGraphicsOpenGL pg; - protected PGL pgl; - protected PGL.Context context; + protected PGL pgl; protected PFont font; protected int maxTexWidth; @@ -72,7 +71,6 @@ class PFontTexture implements PConstants { this.font = font; pg = (PGraphicsOpenGL)parent.g; pgl = pg.pgl; - context = pgl.getContext(); initTexture(maxw, maxh); } @@ -220,6 +218,21 @@ class PFontTexture implements PConstants { } + public boolean contextIsOutdated() { + boolean outdated = false; + for (int i = 0; i < textures.length; i++) { + if (textures[i].contextIsOutdated()) { + outdated = true; + } + } + if (outdated) { + for (int i = 0; i < textures.length; i++) { + textures[i].glID = 0; + } + } + return outdated; + } + // Adds this glyph to the opengl texture in PFont. protected void addToTexture(int idx, PFont.Glyph glyph) { // We add one pixel to avoid issues when sampling the font texture at fractional diff --git a/java/libraries/opengl/src/processing/opengl/PFramebuffer.java b/java/libraries/opengl/src/processing/opengl/PFramebuffer.java index 59a9ffa2a..2b3b74b13 100644 --- a/java/libraries/opengl/src/processing/opengl/PFramebuffer.java +++ b/java/libraries/opengl/src/processing/opengl/PFramebuffer.java @@ -38,10 +38,14 @@ import java.nio.IntBuffer; * * By Andres Colubri. */ + +// TODO: restart framebuffer when context changes + public class PFramebuffer implements PConstants { protected PApplet parent; protected PGraphicsOpenGL pg; protected PGL pgl; + protected PGL.Context context; // The context that created this framebuffer. public int glFboID; public int glDepthBufferID; @@ -187,6 +191,9 @@ public class PFramebuffer implements PConstants { } public void bind() { + // if context is outdated ?? + + if (screenFb) { if (PGraphicsOpenGL.fboSupported) { pgl.glBindFramebuffer(PGL.GL_FRAMEBUFFER, 0); @@ -341,10 +348,11 @@ public class PFramebuffer implements PConstants { protected void allocate() { release(); // Just in the case this object is being re-allocated. + context = pgl.getContext(); + if (screenFb) { glFboID = 0; - } else if (fboMode) { - //glFboID = ogl.createGLResource(PGraphicsAndroid3D.GL_FRAME_BUFFER); + } else if (fboMode) { glFboID = pg.createFrameBufferObject(); } else { glFboID = 0; diff --git a/java/libraries/opengl/src/processing/opengl/PGL.java b/java/libraries/opengl/src/processing/opengl/PGL.java index c58f76d32..3884e9728 100644 --- a/java/libraries/opengl/src/processing/opengl/PGL.java +++ b/java/libraries/opengl/src/processing/opengl/PGL.java @@ -23,37 +23,43 @@ package processing.opengl; +import java.awt.BorderLayout; +import java.awt.Canvas; import java.nio.Buffer; import java.nio.ByteBuffer; -import java.nio.FloatBuffer; import java.nio.IntBuffer; +import java.util.Timer; +import java.util.TimerTask; -import javax.media.nativewindow.GraphicsConfigurationFactory; -import javax.media.nativewindow.NativeWindow; -import javax.media.nativewindow.NativeWindowFactory; -import javax.media.nativewindow.awt.AWTGraphicsConfiguration; -import javax.media.nativewindow.awt.AWTGraphicsDevice; -import javax.media.nativewindow.awt.AWTGraphicsScreen; import javax.media.opengl.GL; import javax.media.opengl.GL2; +import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; import javax.media.opengl.glu.GLU; import javax.media.opengl.glu.GLUtessellator; import javax.media.opengl.glu.GLUtessellatorCallbackAdapter; -import processing.core.PApplet; -import processing.core.PConstants; +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.AnimatorBase; /** * Processing-OpenGL abstraction layer. * */ public class PGL { + // The two windowing toolkits available to use in JOGL: + public static int AWT = 0; // http://jogamp.org/wiki/index.php/Using_JOGL_in_AWT_SWT_and_Swing + public static int NEWT = 1; // http://jogamp.org/jogl/doc/NEWT-Overview.html + + public static int toolkit = AWT; + /** Size of a short (in bytes). */ static final int SIZEOF_SHORT = Short.SIZE / 8; @@ -82,7 +88,7 @@ public class PGL { /** Maximum lights by default is 8, the minimum defined by OpenGL. */ public static final int MAX_LIGHTS = 8; - /** Maximum number of tessellated vertices, using 2^20 for Mac/PC. */ + /** Maximum number of tessellated vertices, using 2^19 for Mac/PC. */ public static final int MAX_TESS_VERTICES = 524288; /** Maximum number of indices. 2 times the max number of @@ -229,6 +235,12 @@ public class PGL { /** GLU interface **/ public GLU glu; + /** The PGraphics object using this interface */ + public PGraphicsOpenGL pg; + + /** Whether OpenGL has been initialized or not */ + public boolean initialized; + /** Selected GL profile */ public GLProfile profile; @@ -241,51 +253,67 @@ public class PGL { /** The rendering context (holds rendering state info) */ public GLContext context; - public PGraphicsOpenGL pg; + /** The AWT canvas where OpenGL rendering takes place */ + public Canvas canvas; - public boolean initialized; + /** The AWT-OpenGL canvas */ + protected GLCanvas canvasAWT; + + /** The NEWT-OpenGL canvas */ + protected NewtCanvasAWT canvasNEWT; + + /** The NEWT window */ + protected GLWindow window; + + /** The listener that fires the frame rendering in Processing */ + protected PGLListener listener; + + /** Animator to drive the rendering thread in NEWT */ + protected NEWTAnimator animator; + + /** Desired target framerate */ + protected float targetFramerate = 60; + protected boolean setFramerate = false; /////////////////////////////////////////////////////////////////////////////////// // Intialization, finalization + public PGL(PGraphicsOpenGL pg) { this.pg = pg; glu = new GLU(); 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) { - try { - GLProfile.initSingleton(beforeUI); - } catch (Exception e) { - e.printStackTrace(); - } + public void setFramerate(float framerate) { + if (60 < framerate) { + // Disables v-sync + gl.setSwapInterval(0); + } else if (30 < framerate) { + gl.setSwapInterval(1); + } else { + gl.setSwapInterval(2); + } + if ((60 < framerate && targetFramerate <= 60) || + (framerate <= 60 && 60 < targetFramerate)) { + // Enabling/disabling v-sync, we force a + // surface reinitialization to avoid screen + // no-paint issue observed on MacOSX. + initialized = false; + } + targetFramerate = framerate; + setFramerate = true; } - static public void shutdown() { - GLProfile.shutdown(); - } public void updatePrimary() { - gl = context.getGL(); - gl2 = gl.getGL2(); - - // disables vsync (framerate cap) on windows - gl.setSwapInterval(0); + if (!setFramerate) { + setFramerate(targetFramerate); + } } + public void updateOffscreen(PGL primary) { gl = primary.gl; @@ -294,32 +322,24 @@ public class PGL { public void initPrimarySurface(int antialias) { - if (pg.parent.online) { - // RCP Application (Applet's, Webstart, Netbeans, ..) using JOGL may not - // be able to initialize JOGL before the first UI action, so initSingleton() - // is called with its argument set to false. - GLProfile.initSingleton(false); - } else { - if (PApplet.platform == PConstants.LINUX) { - // Special case for Linux, since the multithreading issues described for - // example here: - // http://forum.jogamp.org/QtJambi-JOGL-Ubuntu-Lucid-td909554.html - // have not been solved yet (at least for stable release b32 of JOGL2). - GLProfile.initSingleton(false); - } else { - GLProfile.initSingleton(true); - } - } - - // 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(); - if (profile == null) { - pg.parent.die("Cannot get a valid OpenGL profile"); + profile = GLProfile.getDefault(); + } else { + // Restarting... + if (toolkit == AWT) { + canvasAWT.removeGLEventListener(listener); + pg.parent.removeListeners(canvasAWT); + pg.parent.remove(canvasAWT); + } else if (toolkit == NEWT) { + animator.stop(); + animator.remove(window); + window.removeGLEventListener(listener); + pg.parent.removeListeners(canvasNEWT); + pg.parent.remove(canvasNEWT); + } + setFramerate = false; } - + capabilities = new GLCapabilities(profile); if (1 < antialias) { capabilities.setSampleBuffers(true); @@ -327,168 +347,170 @@ public class PGL { } else { capabilities.setSampleBuffers(false); } - - // Getting the native window: - // http://www.java-gaming.org/index.php/topic,21559.0.html - AWTGraphicsScreen screen = (AWTGraphicsScreen)AWTGraphicsScreen.createDefault(); - AWTGraphicsConfiguration config = (AWTGraphicsConfiguration)GraphicsConfigurationFactory - .getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capabilities, capabilities, null, screen); - NativeWindow win = NativeWindowFactory.getNativeWindow(pg.parent, config); - // With the native window we get the drawable and context: - GLDrawableFactory factory = GLDrawableFactory.getFactory(profile); - drawable = factory.createGLDrawable(win); - context = drawable.createContext(null); + if (toolkit == AWT) { + canvasAWT = new GLCanvas(capabilities); + canvasAWT.setBounds(0, 0, pg.width, pg.height); + + pg.parent.setLayout(new BorderLayout()); + pg.parent.add(canvasAWT, BorderLayout.CENTER); + pg.parent.removeListeners(); + pg.parent.addListeners(canvasAWT); + + listener = new PGLListener(); + canvasAWT.addGLEventListener(listener); + + canvas = canvasAWT; + } else if (toolkit == NEWT) { + window = GLWindow.create(capabilities); + canvasNEWT = new NewtCanvasAWT(window); + + pg.parent.setLayout(new BorderLayout()); + pg.parent.add(canvasNEWT, BorderLayout.CENTER); + pg.parent.removeListeners(); + pg.parent.addListeners(canvasNEWT); + + listener = new PGLListener(); + window.addGLEventListener(listener); + animator = new NEWTAnimator(window); + animator.start(); + + canvas = canvasNEWT; + } initialized = true; } + public void initOffscreenSurface(PGL primary) { context = primary.context; capabilities = primary.capabilities; drawable = null; initialized = true; } - - public void updateOffscreenSurface(PGL primary) { - context = primary.context; - capabilities = primary.capabilities; - drawable = null; - } - - /** - * Make the OpenGL rendering context current for this thread. - */ - protected void detainContext() { - try { - while (context.makeCurrent() == GLContext.CONTEXT_NOT_CURRENT) { - Thread.sleep(10); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - /** - * Release the context, otherwise the AWT lock on X11 will not be released - */ - public void releaseContext() { - context.release(); - } - - public void destroyContext() { - context.destroy(); - context = null; - } + /////////////////////////////////////////////////////////////////////////////////// // Frame rendering - public boolean initOnscreenDraw() { - if (drawable != null) { - // Call setRealized() after addNotify() has been called - drawable.setRealized(pg.parent.isDisplayable()); - if (pg.parent.isDisplayable()) { - drawable.setRealized(true); - return true; - } else { - return false; // Should have called canDraw() anyway - } - } - return false; - } public void beginOnscreenDraw(boolean clear, int frame) { } + public void endOnscreenDraw(boolean clear0) { - if (drawable != null) { - drawable.swapBuffers(); - } } + public void beginOffscreenDraw(boolean clear, int frame) { } + public void endOffscreenDraw(boolean clear0) { } + public boolean canDraw() { - return pg.parent.isDisplayable(); + return initialized && pg.parent.isDisplayable(); } - public void requestDraw() { + + public void requestDraw() { + if (initialized) { + if (toolkit == AWT) { + canvasAWT.display(); + } else if (toolkit == NEWT) { + animator.requestDisplay(); + } + } } + /////////////////////////////////////////////////////////////////////////////////// // Caps query + public String glGetString(int name) { return gl.glGetString(name); } - public void glGetIntegerv(int name, IntBuffer values) { - gl.glGetIntegerv(name, values); + + public void glGetIntegerv(int name, int[] values, int offset) { + gl.glGetIntegerv(name, values, offset); } + /////////////////////////////////////////////////////////////////////////////////// // Enable/disable caps + public void glEnable(int cap) { if (-1 < cap) { gl.glEnable(cap); } } + public void glDisable(int cap) { if (-1 < cap) { gl.glDisable(cap); } } + /////////////////////////////////////////////////////////////////////////////////// // Render control + public void glFlush() { gl.glFlush(); } + public void glFinish() { gl.glFinish(); } + ///////////////////////////////////////////////////////////////////////////////// // Error handling + public int glGetError() { return gl.glGetError(); } + public String glErrorString(int err) { return glu.gluErrorString(err); } + public String gluErrorString(int err) { return glu.gluErrorString(err); } + ///////////////////////////////////////////////////////////////////////////////// // Rendering options + public void glFrontFace(int mode) { gl.glFrontFace(mode); } - + + public void glDepthMask(boolean flag) { gl.glDepthMask(flag); } - + + public void glDepthFunc(int func) { gl.glDepthFunc(func); } @@ -498,62 +520,72 @@ public class PGL { // Textures - public void glGenTextures(int n, IntBuffer ids) { - ids.limit(n); - gl.glGenTextures(n, ids); + + public void glGenTextures(int n, int[] ids, int offset) { + gl.glGenTextures(n, ids, offset); } - public void glDeleteTextures(int n, IntBuffer ids) { - ids.limit(n); - gl.glDeleteTextures(n, ids); + + public void glDeleteTextures(int n, int[] ids, int offset) { + gl.glDeleteTextures(n, ids, offset); } + public void glActiveTexture(int unit) { gl.glActiveTexture(unit); } + public void glBindTexture(int target, int id) { gl.glBindTexture(target, id); } - + + public void glTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, Buffer data) { gl.glTexImage2D(target, level, internalFormat, width, height, border, format, type, data); } + public void glTexSubImage2D(int target, int level, int xOffset, int yOffset, int width, int height, int format, int type, Buffer data) { gl.glTexSubImage2D(target, level, xOffset, yOffset, width, height, format, type, data); } + public void glTexParameterf(int target, int param, int value) { gl.glTexParameterf(target, param, value); } + public void glGenerateMipmap(int target) { gl.glGenerateMipmap(target); } + ///////////////////////////////////////////////////////////////////////////////// // Vertex Buffers - public void glGenBuffers(int n, IntBuffer ids) { - ids.limit(n); - gl.glGenBuffers(n, ids); + + public void glGenBuffers(int n, int[] ids, int offset) { + gl.glGenBuffers(n, ids, offset); } - public void glDeleteBuffers(int n, IntBuffer ids) { - ids.limit(n); - gl.glDeleteBuffers(n, ids); + + public void glDeleteBuffers(int n, int[] ids, int offset) { + gl.glDeleteBuffers(n, ids, offset); } + public void glBindBuffer(int target, int id) { gl.glBindBuffer(target, id); } + public void glBufferData(int target, int size, Buffer data, int usage) { gl.glBufferData(target, size, data, usage); } + public void glBufferSubData(int target, int offset, int size, Buffer data) { gl.glBufferSubData(target, offset, size, data); } @@ -568,10 +600,12 @@ public class PGL { gl2.glEnableVertexAttribArray(loc); } + public void glDisableVertexAttribArray(int loc) { gl2.glDisableVertexAttribArray(loc); } + public void glVertexAttribPointer(int loc, int size, int type, boolean normalized, int stride, int offset) { gl2.glVertexAttribPointer(loc, size, type, normalized, stride, offset); } @@ -581,186 +615,227 @@ public class PGL { return gl2.glMapBuffer(target, access); } + public ByteBuffer glMapBufferRange(int target, int offset, int length, int access) { return gl2.glMapBufferRange(target, offset, length, access); } + public void glUnmapBuffer(int target) { gl2.glUnmapBuffer(target); } + ///////////////////////////////////////////////////////////////////////////////// // Framebuffers, renderbuffers - public void glGenFramebuffers(int n, IntBuffer ids) { - ids.limit(n); - gl.glGenFramebuffers(n, ids); + + public void glGenFramebuffers(int n, int[] ids, int offset) { + gl.glGenFramebuffers(n, ids, offset); } - public void glDeleteFramebuffers(int n, IntBuffer ids) { - ids.limit(n); - gl.glDeleteFramebuffers(n, ids); + + public void glDeleteFramebuffers(int n, int[] ids, int offset) { + gl.glDeleteFramebuffers(n, ids, offset); } - public void glGenRenderbuffers(int n, IntBuffer ids) { - ids.limit(n); - gl.glGenRenderbuffers(n, ids); + + public void glGenRenderbuffers(int n, int[] ids, int offset) { + gl.glGenRenderbuffers(n, ids, offset); } - public void glDeleteRenderbuffers(int n, IntBuffer ids) { - ids.limit(n); - gl.glDeleteRenderbuffers(n, ids); + + public void glDeleteRenderbuffers(int n, int[] ids, int offset) { + gl.glDeleteRenderbuffers(n, ids, offset); } + public void glBindFramebuffer(int target, int id) { gl.glBindFramebuffer(target, id); } + public void glBlitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) { gl2.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } + public void glFramebufferTexture2D(int target, int attachment, int texTarget, int texId, int level) { gl.glFramebufferTexture2D(target, attachment, texTarget, texId, level); } + public void glBindRenderbuffer(int target, int id) { gl.glBindRenderbuffer(target, id); } - + + public void glRenderbufferStorageMultisample(int target, int samples, int format, int width, int height) { gl2.glRenderbufferStorageMultisample(target, samples, format, width, height); } + public void glRenderbufferStorage(int target, int format, int width, int height) { gl.glRenderbufferStorage(target, format, width, height); } + public void glFramebufferRenderbuffer(int target, int attachment, int rendbufTarget, int rendbufId) { gl.glFramebufferRenderbuffer(target, attachment, rendbufTarget, rendbufId); } + public int glCheckFramebufferStatus(int target) { return gl.glCheckFramebufferStatus(target); } + ///////////////////////////////////////////////////////////////////////////////// // Shaders + public int glCreateProgram() { return gl2.glCreateProgram(); } + public void glDeleteProgram(int id) { gl2.glDeleteProgram(id); } + public int glCreateShader(int type) { return gl2.glCreateShader(type); } + public void glDeleteShader(int id) { gl2.glDeleteShader(id); } - + + public void glLinkProgram(int prog) { gl2.glLinkProgram(prog); } + public void glValidateProgram(int prog) { gl2.glValidateProgram(prog); } + public void glUseProgram(int prog) { gl2.glUseProgram(prog); } + public int glGetAttribLocation(int prog, String name) { return gl2.glGetAttribLocation(prog, name); } + public int glGetUniformLocation(int prog, String name) { return gl2.glGetUniformLocation(prog, name); } + public void glUniform1i(int loc, int value) { gl2.glUniform1i(loc, value); } + public void glUniform1f(int loc, float value) { gl2.glUniform1f(loc, value); } + public void glUniform2f(int loc, float value0, float value1) { gl2.glUniform2f(loc, value0, value1); } + public void glUniform3f(int loc, float value0, float value1, float value2) { gl2.glUniform3f(loc, value0, value1, value2); } + public void glUniform4f(int loc, float value0, float value1, float value2, float value3) { gl2.glUniform4f(loc, value0, value1, value2, value3); } - public void glUniform1fv(int loc, int count, FloatBuffer v) { - gl2.glUniform1fv(loc, count, v); + + public void glUniform1fv(int loc, int count, float[] v, int offset) { + gl2.glUniform1fv(loc, count, v, offset); } - public void glUniform2fv(int loc, int count, FloatBuffer v) { - gl2.glUniform2fv(loc, count, v); + + public void glUniform2fv(int loc, int count, float[] v, int offset) { + gl2.glUniform2fv(loc, count, v, offset); } - public void glUniform3fv(int loc, int count, FloatBuffer v) { - gl2.glUniform3fv(loc, count, v); + + public void glUniform3fv(int loc, int count, float[] v, int offset) { + gl2.glUniform3fv(loc, count, v, offset); } - public void glUniform4fv(int loc, int count, FloatBuffer v) { - gl2.glUniform4fv(loc, count, v); + + public void glUniform4fv(int loc, int count, float[] v, int offset) { + gl2.glUniform4fv(loc, count, v, offset); } - public void glUniformMatrix2fv(int loc, int count, boolean transpose, FloatBuffer mat) { - gl2.glUniformMatrix2fv(loc, count, transpose, mat); + + public void glUniformMatrix2fv(int loc, int count, boolean transpose, float[] mat, int offset) { + gl2.glUniformMatrix2fv(loc, count, transpose, mat, offset); } - public void glUniformMatrix3fv(int loc, int count, boolean transpose, FloatBuffer mat) { - gl2.glUniformMatrix3fv(loc, count, transpose, mat); + + public void glUniformMatrix3fv(int loc, int count, boolean transpose, float[] mat, int offset) { + gl2.glUniformMatrix3fv(loc, count, transpose, mat, offset); } - public void glUniformMatrix4fv(int loc, int count, boolean transpose, FloatBuffer mat) { - gl2.glUniformMatrix4fv(loc, count, transpose, mat); + + public void glUniformMatrix4fv(int loc, int count, boolean transpose, float[] mat, int offset) { + gl2.glUniformMatrix4fv(loc, count, transpose, mat, offset); } + public void glVertexAttrib1f(int loc, float value) { gl2.glVertexAttrib1f(loc, value); } + public void glVertexAttrib2f(int loc, float value0, float value1) { gl2.glVertexAttrib2f(loc, value0, value1); } + public void glVertexAttrib3f(int loc, float value0, float value1, float value2) { gl2.glVertexAttrib3f(loc, value0, value1, value2); } + public void glVertexAttrib4f(int loc, float value0, float value1, float value2, float value3) { gl2.glVertexAttrib4f(loc, value0, value1, value2, value3); } + public void glShaderSource(int id, String source) { gl2.glShaderSource(id, 1, new String[] { source }, (int[]) null, 0); } + public void glCompileShader(int id) { gl2.glCompileShader(id); } + public void glAttachShader(int prog, int shader) { gl2.glAttachShader(prog, shader); } + ///////////////////////////////////////////////////////////////////////////////// // Viewport @@ -770,6 +845,7 @@ public class PGL { gl.glViewport(x, y, width, height); } + ///////////////////////////////////////////////////////////////////////////////// // Clipping (scissor test) @@ -799,30 +875,37 @@ public class PGL { // Pixels + public void setReadBuffer(int buf) { gl2.glReadBuffer(buf); } + public void glReadPixels(int x, int y, int width, int height, int format, int type, Buffer buffer) { gl.glReadPixels(x, y, width, height, format, type, buffer); } + public void setDrawBuffer(int buf) { gl2.glDrawBuffer(buf); } + public void glClearColor(float r, float g, float b, float a) { gl.glClearColor(r, g, b, a); } + public void glClear(int mask) { gl.glClear(mask); } - + + ///////////////////////////////////////////////////////////////////////////////// // Context interface + public Context getContext() { return new Context(context); } @@ -839,14 +922,17 @@ public class PGL { } } + ///////////////////////////////////////////////////////////////////////////////// // Tessellator interface - + + public Tessellator createTessellator(TessellatorCallback callback) { return new Tessellator(callback); } + public class Tessellator { protected GLUtessellator tess; protected TessellatorCallback callback; @@ -912,6 +998,7 @@ public class PGL { } } + public interface TessellatorCallback { public void begin(int type); public void end(); @@ -921,39 +1008,38 @@ public class PGL { public void error(int errnum); } + /////////////////////////////////////////////////////////////////////////////////// // Utility functions - public FloatBuffer createFloatBuffer(int size) { - return FloatBuffer.allocate(size); + + public boolean contextIsCurrent(Context other) { + return other != null && other.same(context); } - public IntBuffer createIntBuffer(int size) { - return IntBuffer.allocate(size); - } - - 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) { - IntBuffer texels = createIntBuffer(width * height); - gl.glTexSubImage2D(target, 0, 0, 0, width, height, format, type, texels); + 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); @@ -973,5 +1059,158 @@ public class PGL { byte[] infoBytes = new byte[length]; infoLog.get(infoBytes); return new String(infoBytes); - } + } + + + /////////////////////////////////////////////////////////////////////////////////// + + // Java specific stuff + + + protected class PGLListener implements GLEventListener { + @Override + public void display(GLAutoDrawable adrawable) { + drawable = adrawable; + context = adrawable.getContext(); + gl = context.getGL(); + gl2 = gl.getGL2(); + pg.parent.handleDraw(); + } + + @Override + public void dispose(GLAutoDrawable adrawable) { + } + + @Override + public void init(GLAutoDrawable adrawable) { + drawable = adrawable; + context = adrawable.getContext(); + } + + @Override + public void reshape(GLAutoDrawable adrawable, int x, int y, int w, int h) { + drawable = adrawable; + context = adrawable.getContext(); + } + } + + + /** Animator subclass to drive render loop when using NEWT. + **/ + protected static class NEWTAnimator extends AnimatorBase { + private static int count = 0; + private Timer timer = null; + private TimerTask task = null; + private volatile boolean shouldRun; + + protected String getBaseName(String prefix) { + return prefix + "PGLAnimator" ; + } + + /** Creates an CustomAnimator with an initial drawable to + * animate. + */ + public NEWTAnimator(GLAutoDrawable drawable) { + if (drawable != null) { + add(drawable); + } + } + + public synchronized void requestDisplay() { + shouldRun = true; + } + + public final boolean isStarted() { + stateSync.lock(); + try { + return (timer != null); + } finally { + stateSync.unlock(); + } + } + + public final boolean isAnimating() { + stateSync.lock(); + try { + return (timer != null) && (task != null); + } finally { + stateSync.unlock(); + } + } + + private void startTask() { + if(null != task) { + return; + } + + task = new TimerTask() { + private boolean firstRun = true; + public void run() { + if (firstRun) { + Thread.currentThread().setName("NEWT-RenderQueue-" + count); + firstRun = false; + count++; + } + if (NEWTAnimator.this.shouldRun) { + NEWTAnimator.this.animThread = Thread.currentThread(); + // display impl. uses synchronized block on the animator instance + display(); + synchronized (this) { + // done with current frame. + shouldRun = false; + } + } + } + }; + + fpsCounter.resetFPSCounter(); + shouldRun = false; + + timer.schedule(task, 0, 1); + } + + public synchronized boolean start() { + if (timer != null) { + return false; + } + stateSync.lock(); + try { + timer = new Timer(); + startTask(); + } finally { + stateSync.unlock(); + } + return true; + } + + /** Stops this CustomAnimator. */ + public synchronized boolean stop() { + if (timer == null) { + return false; + } + stateSync.lock(); + try { + shouldRun = false; + if(null != task) { + task.cancel(); + task = null; + } + if(null != timer) { + timer.cancel(); + timer = null; + } + animThread = null; + try { + Thread.sleep(20); // ~ 1/60 hz wait, since we can't ctrl stopped threads + } catch (InterruptedException e) { } + } finally { + stateSync.unlock(); + } + return true; + } + + public final boolean isPaused() { return false; } + public synchronized boolean resume() { return false; } + public synchronized boolean pause() { return false; } + } } diff --git a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java index bbeb324f5..24a614f75 100644 --- a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java +++ b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java @@ -311,8 +311,8 @@ public class PGraphicsOpenGL extends PGraphics { protected boolean resized = false; /** Stores previous viewport dimensions. */ - protected IntBuffer savedViewport; - protected IntBuffer viewport; + protected int[] savedViewport = {0, 0, 0, 0}; + protected int[] viewport = {0, 0, 0, 0}; /** Used to register calls to glClear. */ protected boolean clearColorBuffer; @@ -323,9 +323,6 @@ public class PGraphicsOpenGL extends PGraphics { protected boolean defaultEdges = false; protected PImage textureImage0; - /** To get data from OpenGL. */ - protected IntBuffer getBuffer; - // ........................................................ // Drawing surface: @@ -378,7 +375,8 @@ public class PGraphicsOpenGL extends PGraphics { // Constants - protected static int flushMode = FLUSH_WHEN_FULL; + protected static int flushMode = FLUSH_WHEN_FULL; + protected static final int MIN_ARRAYCOPY_SIZE = 2; protected int vboMode = PGL.GL_STATIC_DRAW; static public float FLOAT_EPS = Float.MIN_VALUE; @@ -400,17 +398,16 @@ public class PGraphicsOpenGL extends PGraphics { */ static public boolean BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; - ////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////// // INIT/ALLOCATE/FINISH + public PGraphicsOpenGL() { pgl = new PGL(this); + pg = null; - getBuffer = pgl.createIntBuffer(16); - viewport = pgl.createIntBuffer(16); - savedViewport = pgl.createIntBuffer(16); tessellator = new Tessellator(); inGeo = newInGeometry(IMMEDIATE); @@ -438,6 +435,7 @@ public class PGraphicsOpenGL extends PGraphics { glPointIndexBufferID = 0; } + //public void setParent(PApplet parent) // PGraphics @@ -448,7 +446,16 @@ public class PGraphicsOpenGL extends PGraphics { //public void setPath(String path) // PGraphics - + + + //public void setAntiAlias(int samples) // PGraphics + + + public void setFrameRate(float framerate) { + pgl.setFramerate(framerate); + } + + public void setSize(int iwidth, int iheight) { resized = (0 < width && width != iwidth) || (0 < height && height != iwidth); @@ -460,8 +467,6 @@ public class PGraphicsOpenGL extends PGraphics { allocate(); reapplySettings(); - vertexCheck(); - // init perspective projection based on new dimensions cameraFOV = 60 * DEG_TO_RAD; // at least for now cameraX = width / 2.0f; @@ -473,7 +478,10 @@ public class PGraphicsOpenGL extends PGraphics { cameraDepth = cameraZ; // eye is at (cameraX, cameraY, cameraZ), aiming at (cameraX, cameraY, 0) // set this flag so that beginDraw() will do an update to the camera. - sizeChanged = true; + sizeChanged = true; + + // Forces a restart of OpenGL so the canvas has the right size. + pgl.initialized = false; } @@ -508,41 +516,12 @@ public class PGraphicsOpenGL extends PGraphics { currentLightSpecular = new float[3]; lightsAllocated = true; } - - if (primarySurface) { - // Allocation of the main renderer, which mainly involves initializing OpenGL. -// if (context == null) { -// initPrimary(); -// } else { -// reapplySettings(); -// } - if (pgl.initialized) { - reapplySettings(); - } - } else { - // Allocation of an offscreen renderer. -// if (context == null) { -// initOffscreen(); -// } else { -// // Updating OpenGL context associated to this offscreen -// // surface, to take into account a context recreation situation. -// updateOffscreenContext(); -// reapplySettings(); -// } - if (pgl.initialized) { - updateOffscreenContext(); - reapplySettings(); - } - } } public void dispose() { // PGraphics super.dispose(); - pgl.detainContext(); - deleteFinalizedGLResources(); - pgl.releaseContext(); - PGL.shutdown(); + deleteFinalizedGLResources(); } @@ -556,13 +535,15 @@ public class PGraphicsOpenGL extends PGraphics { // RESOURCE HANDLING + // Texture Objects ------------------------------------------- protected int createTextureObject() { deleteFinalizedTextureObjects(); - pgl.glGenTextures(1, getBuffer); - int id = getBuffer.get(0); + int[] temp = new int[1]; + pgl.glGenTextures(1, temp, 0); + int id = temp[0]; if (glTextureObjects.containsKey(id)) { showWarning("Adding same texture twice"); @@ -575,16 +556,16 @@ public class PGraphicsOpenGL extends PGraphics { protected void deleteTextureObject(int id) { if (glTextureObjects.containsKey(id)) { - getBuffer.put(0, id); - pgl.glDeleteTextures(1, getBuffer); + int[] temp = { id }; + pgl.glDeleteTextures(1, temp, 0); glTextureObjects.remove(id); } } protected void deleteAllTextureObjects() { for (Integer id : glTextureObjects.keySet()) { - getBuffer.put(0, id.intValue()); - pgl.glDeleteTextures(1, getBuffer); + int[] temp = { id.intValue() }; + pgl.glDeleteTextures(1, temp, 0); } glTextureObjects.clear(); } @@ -604,8 +585,8 @@ public class PGraphicsOpenGL extends PGraphics { for (Integer id : glTextureObjects.keySet()) { if (glTextureObjects.get(id)) { finalized.add(id); - getBuffer.put(0, id.intValue()); - pgl.glDeleteTextures(1, getBuffer); + int[] temp = { id.intValue() }; + pgl.glDeleteTextures(1, temp, 0); } } @@ -614,13 +595,15 @@ public class PGraphicsOpenGL extends PGraphics { } } + // Vertex Buffer Objects ---------------------------------------------- protected int createVertexBufferObject() { deleteFinalizedVertexBufferObjects(); - pgl.glGenBuffers(1, getBuffer); - int id = getBuffer.get(0); + int[] temp = new int[1]; + pgl.glGenBuffers(1, temp, 0); + int id = temp[0]; if (glVertexBuffers.containsKey(id)) { showWarning("Adding same VBO twice"); @@ -633,16 +616,16 @@ public class PGraphicsOpenGL extends PGraphics { protected void deleteVertexBufferObject(int id) { if (glVertexBuffers.containsKey(id)) { - getBuffer.put(0, id); - pgl.glDeleteBuffers(1, getBuffer); + int[] temp = { id }; + pgl.glDeleteBuffers(1, temp, 0); glVertexBuffers.remove(id); } } protected void deleteAllVertexBufferObjects() { for (Integer id : glVertexBuffers.keySet()) { - getBuffer.put(0, id.intValue()); - pgl.glDeleteBuffers(1, getBuffer); + int[] temp = { id.intValue() }; + pgl.glDeleteBuffers(1, temp, 0); } glVertexBuffers.clear(); } @@ -662,8 +645,8 @@ public class PGraphicsOpenGL extends PGraphics { for (Integer id : glVertexBuffers.keySet()) { if (glVertexBuffers.get(id)) { finalized.add(id); - getBuffer.put(0, id.intValue()); - pgl.glDeleteBuffers(1, getBuffer); + int[] temp = { id.intValue() }; + pgl.glDeleteBuffers(1, temp, 0); } } @@ -672,13 +655,15 @@ public class PGraphicsOpenGL extends PGraphics { } } + // FrameBuffer Objects ----------------------------------------- protected int createFrameBufferObject() { deleteFinalizedFrameBufferObjects(); - pgl.glGenFramebuffers(1, getBuffer); - int id = getBuffer.get(0); + int[] temp = new int[1]; + pgl.glGenFramebuffers(1, temp, 0); + int id = temp[0]; if (glFrameBuffers.containsKey(id)) { showWarning("Adding same FBO twice"); @@ -691,16 +676,16 @@ public class PGraphicsOpenGL extends PGraphics { protected void deleteFrameBufferObject(int id) { if (glFrameBuffers.containsKey(id)) { - getBuffer.put(0, id); - pgl.glDeleteFramebuffers(1, getBuffer); + int[] temp = { id }; + pgl.glDeleteFramebuffers(1, temp, 0); glFrameBuffers.remove(id); } } protected void deleteAllFrameBufferObjects() { for (Integer id : glFrameBuffers.keySet()) { - getBuffer.put(0, id.intValue()); - pgl.glDeleteFramebuffers(1, getBuffer); + int[] temp = { id.intValue() }; + pgl.glDeleteFramebuffers(1, temp, 0); } glFrameBuffers.clear(); } @@ -720,8 +705,8 @@ public class PGraphicsOpenGL extends PGraphics { for (Integer id : glFrameBuffers.keySet()) { if (glFrameBuffers.get(id)) { finalized.add(id); - getBuffer.put(0, id.intValue()); - pgl.glDeleteFramebuffers(1, getBuffer); + int[] temp = { id.intValue() }; + pgl.glDeleteFramebuffers(1, temp, 0); } } @@ -730,13 +715,15 @@ public class PGraphicsOpenGL extends PGraphics { } } + // RenderBuffer Objects ----------------------------------------------- protected int createRenderBufferObject() { deleteFinalizedRenderBufferObjects(); - pgl.glDeleteRenderbuffers(1, getBuffer); - int id = getBuffer.get(0); + int[] temp = new int[1]; + pgl.glDeleteRenderbuffers(1, temp, 0); + int id = temp[0]; if (glRenderBuffers.containsKey(id)) { showWarning("Adding same renderbuffer twice"); @@ -749,16 +736,16 @@ public class PGraphicsOpenGL extends PGraphics { protected void deleteRenderBufferObject(int id) { if (glRenderBuffers.containsKey(id)) { - getBuffer.put(0, id); - pgl.glGenRenderbuffers(1, getBuffer); + int[] temp = { id }; + pgl.glGenRenderbuffers(1, temp, 0); glRenderBuffers.remove(id); } } protected void deleteAllRenderBufferObjects() { for (Integer id : glRenderBuffers.keySet()) { - getBuffer.put(0, id.intValue()); - pgl.glDeleteRenderbuffers(1, getBuffer); + int[] temp = { id.intValue() }; + pgl.glDeleteRenderbuffers(1, temp, 0); } glRenderBuffers.clear(); } @@ -778,8 +765,8 @@ public class PGraphicsOpenGL extends PGraphics { for (Integer id : glRenderBuffers.keySet()) { if (glRenderBuffers.get(id)) { finalized.add(id); - getBuffer.put(0, id.intValue()); - pgl.glDeleteRenderbuffers(1, getBuffer); + int[] temp = { id.intValue() }; + pgl.glDeleteRenderbuffers(1, temp, 0); } } @@ -788,6 +775,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + // GLSL Program Objects ----------------------------------------------- protected int createGLSLProgramObject() { @@ -842,6 +830,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + // GLSL Vertex Shader Objects ----------------------------------------------- protected int createGLSLVertShaderObject() { @@ -896,8 +885,8 @@ public class PGraphicsOpenGL extends PGraphics { } } - // GLSL Fragment Shader Objects ----------------------------------------------- - + + // GLSL Fragment Shader Objects ----------------------------------------------- protected int createGLSLFragShaderObject() { deleteFinalizedGLSLFragShaderObjects(); @@ -961,7 +950,8 @@ public class PGraphicsOpenGL extends PGraphics { deleteFinalizedGLSLVertShaderObjects(); deleteFinalizedGLSLFragShaderObjects(); } - + + protected void deleteAllGLResources() { deleteAllTextureObjects(); deleteAllVertexBufferObjects(); @@ -972,10 +962,12 @@ public class PGraphicsOpenGL extends PGraphics { deleteAllGLSLFragShaderObjects(); } + ////////////////////////////////////////////////////////////// // FRAMEBUFFERS + public void pushFramebuffer() { fbStack.push(currentFramebuffer); } @@ -997,25 +989,12 @@ public class PGraphicsOpenGL extends PGraphics { } } + ////////////////////////////////////////////////////////////// // FRAME RENDERING + -// public GLContext getContext() { -// return context; -// } -// public GLCapabilities getCapabilities() { -// return capabilities; -// } -// public GLProfile getProfile() { -// return profile; -// } -// public GLDrawable getDrawable() { -// return drawable; -// } - - - protected void releaseResources() { // First, releasing the resources used by // the renderer itself. @@ -1052,6 +1031,36 @@ public class PGraphicsOpenGL extends PGraphics { if (defPointShader != null) { defPointShader.release(); defPointShader = null; + } + + if (fillShaderSimple != null) { + fillShaderSimple.release(); + fillShaderSimple = null; + } + + if (fillShaderTex != null) { + fillShaderTex.release(); + fillShaderTex = null; + } + + if (fillShaderLit != null) { + fillShaderLit.release(); + fillShaderLit = null; + } + + if (fillShaderFull != null) { + fillShaderFull.release(); + fillShaderFull = null; + } + + if (lineShader != null) { + lineShader.release(); + lineShader = null; + } + + if (pointShader != null) { + pointShader.release(); + pointShader = null; } if (fillVBOsCreated) { @@ -1073,21 +1082,8 @@ public class PGraphicsOpenGL extends PGraphics { // (from user's objects). deleteAllGLResources(); } - - /** - * Destroys current OpenGL context and creates a new one, making sure that all - * the current OpenGL objects remain valid afterward. - */ - public void restartContext() { - releaseResources(); - - pgl.releaseContext(); - pgl.destroyContext(); - restartSurface(); - pgl.detainContext(); - updatePGL(); - } + protected void createFillBuffers() { int sizef = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_FLOAT; int sizei = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_INT; @@ -1134,52 +1130,52 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); } + protected void updateFillBuffers(boolean lit, boolean tex) { int size = tessGeo.fillVertexCount; int sizef = size * PGL.SIZEOF_FLOAT; int sizei = size * PGL.SIZEOF_INT; - tessGeo.prepareFillVerticesForCopy(); - pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillVertexBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, tessGeo.fillVertices, vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, FloatBuffer.wrap(tessGeo.fillVertices, 0, 3 * size), vboMode); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillColorBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, tessGeo.fillColors, vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, IntBuffer.wrap(tessGeo.fillColors, 0, size), vboMode); if (lit) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillNormalBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, tessGeo.fillNormals, vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, FloatBuffer.wrap(tessGeo.fillNormals, 0, 3 * size), vboMode); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillAmbientBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, tessGeo.fillAmbient, vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, IntBuffer.wrap(tessGeo.fillAmbient, 0, size), vboMode); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillSpecularBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, tessGeo.fillSpecular, vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, IntBuffer.wrap(tessGeo.fillSpecular, 0, size), vboMode); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillEmissiveBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, tessGeo.fillEmissive, vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, IntBuffer.wrap(tessGeo.fillEmissive, 0, size), vboMode); + pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillShininessBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizef, tessGeo.fillShininess, vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizef, FloatBuffer.wrap(tessGeo.fillShininess, 0, size), vboMode); } if (tex) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillTexCoordBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 2 * sizef, tessGeo.fillTexcoords, vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 2 * sizef, FloatBuffer.wrap(tessGeo.fillTexcoords, 0, 2 * size), vboMode); } - tessGeo.prepareFillIndicesForCopy(); - pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glFillIndexBufferID); pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, tessGeo.fillIndexCount * PGL.SIZEOF_INDEX, - tessGeo.fillIndices, vboMode); + IntBuffer.wrap(tessGeo.fillIndices, 0, tessGeo.fillIndexCount), vboMode); } - protected void unbindFillBuffers(boolean lit, boolean tex) { + + protected void unbindFillBuffers() { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); - } + } + protected void releaseFillBuffers() { deleteVertexBufferObject(glFillVertexBufferID); @@ -1210,6 +1206,7 @@ public class PGraphicsOpenGL extends PGraphics { glFillIndexBufferID = 0; } + protected void createLineBuffers() { int sizef = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_FLOAT; int sizex = PGL.MAX_TESS_INDICES * PGL.SIZEOF_INDEX; @@ -1237,33 +1234,32 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); } + protected void updateLineBuffers() { int size = tessGeo.lineVertexCount; int sizef = size * PGL.SIZEOF_FLOAT; int sizei = size * PGL.SIZEOF_INT; - tessGeo.prepareLineVerticesForCopy(); - pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineVertexBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, tessGeo.lineVertices, vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, FloatBuffer.wrap(tessGeo.lineVertices, 0, 3 * size), vboMode); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineColorBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, tessGeo.lineColors, vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, IntBuffer.wrap(tessGeo.lineColors, 0, size), vboMode); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineDirWidthBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 4 * sizef, tessGeo.lineDirWidths, vboMode); - - tessGeo.prepareLineIndicesForCopy(); - + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 4 * sizef, FloatBuffer.wrap(tessGeo.lineDirWidths, 0, 4 * size), vboMode); + pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glLineIndexBufferID); pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, tessGeo.lineIndexCount * PGL.SIZEOF_INDEX, - tessGeo.lineIndices, vboMode); + IntBuffer.wrap(tessGeo.lineIndices, 0, tessGeo.lineIndexCount), vboMode); } + protected void unbindLineBuffers() { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); - } + } + protected void releaseLineBuffers() { deleteVertexBufferObject(glLineVertexBufferID); @@ -1279,6 +1275,7 @@ public class PGraphicsOpenGL extends PGraphics { glLineIndexBufferID = 0; } + protected void createPointBuffers() { int sizef = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_FLOAT; int sizex = PGL.MAX_TESS_INDICES * PGL.SIZEOF_INDEX; @@ -1305,33 +1302,32 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); } + protected void updatePointBuffers() { int size = tessGeo.pointVertexCount; int sizef = size * PGL.SIZEOF_FLOAT; int sizei = size * PGL.SIZEOF_INT; - tessGeo.preparePointVerticesForCopy(); - pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointVertexBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, tessGeo.pointVertices, vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, FloatBuffer.wrap(tessGeo.pointVertices, 0, 3 * size), vboMode); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointColorBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, tessGeo.pointColors, vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, IntBuffer.wrap(tessGeo.pointColors, 0, size), vboMode); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointSizeBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 2 * sizef, tessGeo.pointSizes, vboMode); - - tessGeo.preparePointIndicesForCopy(); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 2 * sizef, FloatBuffer.wrap(tessGeo.pointSizes, 0, 2 * size), vboMode); pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glPointIndexBufferID); pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, tessGeo.pointIndexCount * PGL.SIZEOF_INDEX, - tessGeo.pointIndices, vboMode); + IntBuffer.wrap(tessGeo.pointIndices, 0, tessGeo.pointIndexCount), vboMode); } + protected void unbindPointBuffers() { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); - pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); - } + pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); + } + protected void releasePointBuffers() { deleteVertexBufferObject(glPointVertexBufferID); @@ -1358,8 +1354,14 @@ public class PGraphicsOpenGL extends PGraphics { public void requestDraw() { - pgl.requestDraw(); - } + if (primarySurface) { + if (pgl.initialized) { + pgl.requestDraw(); + } else { + initPrimary(); + } + } + } public void beginDraw() { @@ -1369,14 +1371,7 @@ public class PGraphicsOpenGL extends PGraphics { } if (primarySurface) { - if (!pgl.initialized) { - initPrimary(); - } - - if (!pgl.initOnscreenDraw()) { - return; - } - pgl.detainContext(); + pgl.updatePrimary(); } else { if (!pgl.initialized) { initOffscreen(); @@ -1388,10 +1383,10 @@ public class PGraphicsOpenGL extends PGraphics { pgl.setDrawBuffer(0); } else { setFramebuffer(offscreenFramebuffer); - } - } + } - updatePGL(); + pgl.updateOffscreen(pg.pgl); + } if (!glParamsRead) { getGLParameters(); @@ -1403,16 +1398,7 @@ public class PGraphicsOpenGL extends PGraphics { // We are ready to go! - report("top beginDraw()"); - - if (!primarySurface) { - pg.saveGLState(); - - // Disabling all lights, so the offscreen renderer can set completely - // new light configuration (otherwise some light configuration from the - // primary renderer might stay). - //pg.disableLights(); - } + report("top beginDraw()"); inGeo.clear(); tessGeo.clear(); @@ -1435,12 +1421,6 @@ public class PGraphicsOpenGL extends PGraphics { } // use <= since that's what processing.core does pgl.glDepthFunc(PGL.GL_LEQUAL); - - if (hints[DISABLE_DEPTH_MASK]) { - pgl.glDepthMask(false); - } else { - pgl.glDepthMask(true); - } if (hints[ENABLE_ACCURATE_2D]) { flushMode = FLUSH_CONTINUOUSLY; @@ -1448,10 +1428,28 @@ public class PGraphicsOpenGL extends PGraphics { flushMode = FLUSH_WHEN_FULL; } + int[] temp = { 0 }; + pgl.glGetIntegerv(PGL.GL_SAMPLES, temp, 0); + if (antialias != temp[0]) { + PGraphics.showWarning("Smooth level " + antialias + " not supported. Using " + temp[0] + " instead."); + antialias = temp[0]; + } + if (antialias < 2) { + pgl.glDisable(PGL.GL_MULTISAMPLE); + pgl.glEnable(PGL.GL_POINT_SMOOTH); + pgl.glEnable(PGL.GL_LINE_SMOOTH); + pgl.glEnable(PGL.GL_POLYGON_SMOOTH); + } else { + pgl.glEnable(PGL.GL_MULTISAMPLE); + pgl.glDisable(PGL.GL_POINT_SMOOTH); + pgl.glDisable(PGL.GL_LINE_SMOOTH); + pgl.glDisable(PGL.GL_POLYGON_SMOOTH); + } + // setup opengl viewport. - pgl.glGetIntegerv(PGL.GL_VIEWPORT, savedViewport); - viewport.put(0, 0); viewport.put(1, 0); viewport.put(2, width); viewport.put(3, height); - pgl.glViewport(viewport.get(0), viewport.get(1), viewport.get(2), viewport.get(3)); + pgl.glGetIntegerv(PGL.GL_VIEWPORT, savedViewport, 0); + viewport[0] = 0; viewport[1] = 0; viewport[2] = width; viewport[3] = height; + pgl.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); if (resized) { // To avoid having garbage in the screen after a resize, // in the case background is not called in draw(). @@ -1502,9 +1500,16 @@ public class PGraphicsOpenGL extends PGraphics { normalX = normalY = normalZ = 0; // Clear depth and stencil buffers. + pgl.glDepthMask(true); pgl.glClearColor(0, 0, 0, 0); pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT | PGL.GL_STENCIL_BUFFER_BIT); + if (hints[DISABLE_DEPTH_MASK]) { + pgl.glDepthMask(false); + } else { + pgl.glDepthMask(true); + } + if (primarySurface) { pgl.beginOnscreenDraw(clearColorBuffer, parent.frameCount); } else { @@ -1538,12 +1543,11 @@ public class PGraphicsOpenGL extends PGraphics { } // Restoring previous viewport. - pgl.glViewport(savedViewport.get(0), savedViewport.get(1), savedViewport.get(2), savedViewport.get(3)); + pgl.glViewport(savedViewport[0], savedViewport[1], savedViewport[2], savedViewport[3]); if (primarySurface) { pgl.glFlush(); pgl.endOnscreenDraw(clearColorBuffer0); - pgl.releaseContext(); } else { if (offscreenMultisample) { offscreenFramebufferMultisample.copy(offscreenFramebuffer); @@ -1552,7 +1556,7 @@ public class PGraphicsOpenGL extends PGraphics { pgl.endOffscreenDraw(clearColorBuffer0); - pg.restoreGLState(); + pg.restoreGL(); } drawing = false; @@ -1562,73 +1566,68 @@ public class PGraphicsOpenGL extends PGraphics { public PGL beginPGL() { - saveGLState(); return pgl; } public void endPGL() { - restoreGLState(); + restoreGL(); } - public void updatePGL() { - if (primarySurface) { - pgl.updatePrimary(); - } else { - pgl.updateOffscreen(pg.pgl); - } + public void restartPGL() { + pgl.initialized = false; } - protected void saveGLState() { - } - - - protected void restoreGLState() { - // Restoring viewport. - pgl.glViewport(viewport.get(0), viewport.get(1), viewport.get(2), viewport.get(3)); + protected void restoreGL() { + blendMode(blendMode); - // Restoring hints. if (hints[DISABLE_DEPTH_TEST]) { pgl.glDisable(PGL.GL_DEPTH_TEST); - pgl.glClearColor(0, 0, 0, 0); - pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT); } else { pgl.glEnable(PGL.GL_DEPTH_TEST); } + pgl.glDepthFunc(PGL.GL_LEQUAL); + + if (antialias < 2) { + pgl.glDisable(PGL.GL_MULTISAMPLE); + pgl.glEnable(PGL.GL_POINT_SMOOTH); + pgl.glEnable(PGL.GL_LINE_SMOOTH); + pgl.glEnable(PGL.GL_POLYGON_SMOOTH); + } else { + pgl.glEnable(PGL.GL_MULTISAMPLE); + pgl.glDisable(PGL.GL_POINT_SMOOTH); + pgl.glDisable(PGL.GL_LINE_SMOOTH); + pgl.glDisable(PGL.GL_POLYGON_SMOOTH); + } + + pgl.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + + pgl.glFrontFace(PGL.GL_CW); + + pgl.glActiveTexture(PGL.GL_TEXTURE0); if (hints[DISABLE_DEPTH_MASK]) { pgl.glDepthMask(false); } else { pgl.glDepthMask(true); - } - - // Restoring blending. - blendMode(blendMode); - - // Some things the user might have changed from OpenGL, - // 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.glFrontFace(PGL.GL_CW); - pgl.glDepthFunc(PGL.GL_LEQUAL); - } - + } + } + // Utility function to get ready OpenGL for a specific // operation, such as grabbing the contents of the color // buffer. protected void beginGLOp() { - pgl.detainContext(); - updatePGL(); + pgl.updateOffscreen(pg.pgl); } // Pairs-up with beginGLOp(). protected void endGLOp() { - pgl.releaseContext(); } + protected void updateGLProjection() { if (glProjection == null) { @@ -1656,6 +1655,7 @@ public class PGraphicsOpenGL extends PGraphics { glProjection[15] = projection.m33; } + protected void updateGLModelview() { if (glModelview == null) { glModelview = new float[16]; @@ -1682,11 +1682,13 @@ public class PGraphicsOpenGL extends PGraphics { glModelview[15] = modelview.m33; } + protected void calcProjmodelview() { projmodelview.set(projection); projmodelview.apply(modelview); } + protected void updateGLProjmodelview() { if (glProjmodelview == null) { glProjmodelview = new float[16]; @@ -1713,6 +1715,7 @@ public class PGraphicsOpenGL extends PGraphics { glProjmodelview[15] = projmodelview.m33; } + protected void updateGLNormal() { if (glNormal == null) { glNormal = new float[9]; @@ -1735,6 +1738,7 @@ public class PGraphicsOpenGL extends PGraphics { glNormal[8] = modelviewInv.m22; } + ////////////////////////////////////////////////////////////// // SETTINGS @@ -1774,12 +1778,14 @@ public class PGraphicsOpenGL extends PGraphics { shininess(1); } + // reapplySettings ////////////////////////////////////////////////////////////// // HINTS + public void hint(int which) { boolean oldValue = hints[PApplet.abs(which)]; super.hint(which); @@ -1792,46 +1798,35 @@ public class PGraphicsOpenGL extends PGraphics { if (which == DISABLE_DEPTH_TEST) { flush(); pgl.glDisable(PGL.GL_DEPTH_TEST); - pgl.glClearColor(0, 0, 0, 0); - pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT); - } else if (which == ENABLE_DEPTH_TEST) { flush(); pgl.glEnable(PGL.GL_DEPTH_TEST); - } else if (which == DISABLE_DEPTH_MASK) { flush(); pgl.glDepthMask(false); - } else if (which == ENABLE_DEPTH_MASK) { flush(); - pgl.glDepthMask(true); - + pgl.glDepthMask(true); } else if (which == DISABLE_ACCURATE_2D) { flush(); - setFlushMode(FLUSH_WHEN_FULL); - + setFlushMode(FLUSH_WHEN_FULL); } else if (which == ENABLE_ACCURATE_2D) { flush(); - setFlushMode(FLUSH_CONTINUOUSLY); - + setFlushMode(FLUSH_CONTINUOUSLY); } else if (which == DISABLE_TEXTURE_CACHE) { - flush(); - + flush(); } else if (which == DISABLE_PERSPECTIVE_CORRECTED_LINES) { if (0 < tessGeo.lineVertexCount && 0 < tessGeo.lineIndexCount) { flush(); - } - + } } else if (which == ENABLE_PERSPECTIVE_CORRECTED_LINES) { if (0 < tessGeo.lineVertexCount && 0 < tessGeo.lineIndexCount) { flush(); - } - + } } - } + ////////////////////////////////////////////////////////////// // SHAPE CREATORS @@ -1841,6 +1836,7 @@ public class PGraphicsOpenGL extends PGraphics { return createShape(POLYGON); } + public PShape createShape(int type) { PShape3D shape = null; if (type == PShape.GROUP) { @@ -1873,6 +1869,7 @@ public class PGraphicsOpenGL extends PGraphics { return shape; } + public PShape createShape(int kind, float... p) { PShape3D shape = null; int len = p.length; @@ -1949,10 +1946,12 @@ public class PGraphicsOpenGL extends PGraphics { return shape; } + ////////////////////////////////////////////////////////////// // VERTEX SHAPES + public void beginShape(int kind) { shape = kind; @@ -2167,6 +2166,7 @@ public class PGraphicsOpenGL extends PGraphics { // protected void sort() + protected void tessellate(int mode) { tessellator.setInGeometry(inGeo); tessellator.setTessGeometry(tessGeo); @@ -2210,10 +2210,12 @@ public class PGraphicsOpenGL extends PGraphics { setLastTexIndex(tessGeo.lastFillIndex); } + protected void setFirstTexIndex(int first) { firstTexIndex = first; } + protected void setLastTexIndex(int last) { if (textureImage0 != textureImage || texCache.count == 0) { texCache.addTexture(textureImage, firstTexIndex, last); @@ -2222,6 +2224,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + public void flush() { boolean hasPoints = 0 < tessGeo.pointVertexCount && 0 < tessGeo.pointIndexCount; boolean hasLines = 0 < tessGeo.lineVertexCount && 0 < tessGeo.lineIndexCount; @@ -2271,32 +2274,33 @@ public class PGraphicsOpenGL extends PGraphics { shader.setVertexAttribute(glPointVertexBufferID, 3, PGL.GL_FLOAT, 0, 0); shader.setColorAttribute(glPointColorBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); shader.setSizeAttribute(glPointSizeBufferID, 2, PGL.GL_FLOAT, 0, 0); - - pgl.glDrawElements(PGL.GL_TRIANGLES, tessGeo.pointIndexCount, PGL.INDEX_TYPE, 0); + + pgl.glDrawElements(PGL.GL_TRIANGLES, tessGeo.pointIndexCount, PGL.INDEX_TYPE, 0); shader.stop(); unbindPointBuffers(); } + protected void renderLines() { if (!lineVBOsCreated) { createLineBuffers(); - lineVBOsCreated = true; + lineVBOsCreated = true; } - updateLineBuffers(); LineShader shader = getLineShader(); shader.start(); + shader.setVertexAttribute(glLineVertexBufferID, 3, PGL.GL_FLOAT, 0, 0); shader.setColorAttribute(glLineColorBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); - shader.setDirWidthAttribute(glLineDirWidthBufferID, 4, PGL.GL_FLOAT, 0, 0); + shader.setDirWidthAttribute(glLineDirWidthBufferID, 4, PGL.GL_FLOAT, 0, 0); + report("renderLines: attribs set"); pgl.glDrawElements(PGL.GL_TRIANGLES, tessGeo.lineIndexCount, PGL.INDEX_TYPE, 0); shader.stop(); - - unbindLineBuffers(); + unbindLineBuffers(); } @@ -2304,7 +2308,7 @@ public class PGraphicsOpenGL extends PGraphics { if (!fillVBOsCreated) { createFillBuffers(); fillVBOsCreated = true; - } + } updateFillBuffers(lights, texCache.hasTexture); texCache.beginRender(); @@ -2336,8 +2340,8 @@ public class PGraphicsOpenGL extends PGraphics { shader.stop(); } - texCache.endRender(); - unbindFillBuffers(lights, texCache.hasTexture); + texCache.endRender(); + unbindFillBuffers(); } @@ -2369,17 +2373,19 @@ public class PGraphicsOpenGL extends PGraphics { int size = tessGeo.fillIndexCount; int sizex = size * PGL.SIZEOF_INDEX; pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glFillIndexBufferID); - pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, sizex, tessGeo.fillIndices, vboMode); + pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, sizex, IntBuffer.wrap(tessGeo.fillIndices, 0, size), vboMode); pgl.glDrawElements(PGL.GL_TRIANGLES, size, PGL.INDEX_TYPE, 0); pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); shader.stop(); } + ////////////////////////////////////////////////////////////// // PSHAPE RENDERING IN 3D + public void shape(PShape shape, float x, float y, float z) { if (shape.isVisible()) { // don't do expensive matrix ops if invisible pushMatrix(); @@ -2397,6 +2403,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + public void shape(PShape shape, float x, float y, float z, float c, float d, float e) { if (shape.isVisible()) { // don't do expensive matrix ops if invisible @@ -2425,11 +2432,13 @@ public class PGraphicsOpenGL extends PGraphics { popMatrix(); } } + ////////////////////////////////////////////////////////////// // BEZIER CURVE VERTICES + public void bezierDetail(int detail) { bezierDetail = detail; @@ -2445,6 +2454,7 @@ public class PGraphicsOpenGL extends PGraphics { bezierDrawMatrix.apply(pg.bezierBasisMatrix); } + public void bezierVertex(float x2, float y2, float x3, float y3, float x4, float y4) { @@ -2453,6 +2463,7 @@ public class PGraphicsOpenGL extends PGraphics { x4, y4, 0); } + public void bezierVertex(float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4) { @@ -2484,12 +2495,14 @@ public class PGraphicsOpenGL extends PGraphics { } } + public void quadraticVertex(float cx, float cy, float x3, float y3) { quadraticVertex(cx, cy, 0, x3, y3, 0); } + public void quadraticVertex(float cx, float cy, float cz, float x3, float y3, float z3) { float x1 = inGeo.getLastVertexX(); @@ -2501,18 +2514,21 @@ public class PGraphicsOpenGL extends PGraphics { x3, y3, z3); } + protected void bezierInitCheck() { if (!bezierInited) { bezierInit(); } } + protected void bezierInit() { // overkill to be broken out, but better parity with the curve stuff below bezierDetail(bezierDetail); bezierInited = true; } + protected void bezierVertexCheck() { if (shape != POLYGON) { throw new RuntimeException("beginShape() or beginShape(POLYGON) " + @@ -2524,24 +2540,29 @@ public class PGraphicsOpenGL extends PGraphics { } } + ////////////////////////////////////////////////////////////// // CATMULL-ROM CURVE VERTICES + public void curveDetail(int detail) { curveDetail = detail; curveInit(); } + public void curveTightness(float tightness) { curveTightness = tightness; curveInit(); } + public void curveVertex(float x, float y) { curveVertex(x, y, 0); } + public void curveVertex(float x, float y, float z) { curveVertexCheck(); float[] vertex = curveVertices[curveVertexCount]; @@ -2589,12 +2610,14 @@ public class PGraphicsOpenGL extends PGraphics { curveInitCheck(); } + protected void curveInitCheck() { if (!curveInited) { curveInit(); } } + protected void curveInit() { // allocate only if/when used to save startup time if (curveDrawMatrix == null) { @@ -2628,6 +2651,7 @@ public class PGraphicsOpenGL extends PGraphics { curveDrawMatrix.apply(curveBasisMatrix); } + /** * Handle emitting a specific segment of Catmull-Rom curve. This can be * overridden by subclasses that need more efficient rendering options. @@ -2663,10 +2687,12 @@ public class PGraphicsOpenGL extends PGraphics { } } + ////////////////////////////////////////////////////////////// // SPLINE UTILITY FUNCTIONS (used by both Bezier and Catmull-Rom) + /** * Setup forward-differencing matrix to be used for speedy * curve rendering. It's based on using a specific number @@ -2746,7 +2772,8 @@ public class PGraphicsOpenGL extends PGraphics { ////////////////////////////////////////////////////////////// // ARC - + + protected void arcImpl(float x, float y, float w, float h, float start, float stop) { float hr = w / 2f; @@ -2808,6 +2835,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + ////////////////////////////////////////////////////////////// // BOX @@ -2895,6 +2923,8 @@ public class PGraphicsOpenGL extends PGraphics { ////////////////////////////////////////////////////////////// // SMOOTH + + public void smooth() { smooth(2); } @@ -2903,29 +2933,15 @@ public class PGraphicsOpenGL extends PGraphics { public void smooth(int level) { smooth = true; - if (antialias != level) { + if (antialias != level) { antialias = level; - if (primarySurface) { - restartContext(); -// throw new PApplet.RendererChangeException(); - } else { - initOffscreen(); + if (antialias == 1) { + antialias = 0; } + // This will trigger a surface restart next time + // requestDraw() is called. + pgl.initialized = false; } - - pgl.glGetIntegerv(PGL.GL_SAMPLES, getBuffer); - int newAntialias = getBuffer.get(0); - if (antialias != newAntialias) { - antialias = newAntialias; - PApplet.println("Effective multisampling level: " + antialias); - } - - if (antialias < 2) { - pgl.glEnable(PGL.GL_MULTISAMPLE); - pgl.glEnable(PGL.GL_POINT_SMOOTH); - pgl.glEnable(PGL.GL_LINE_SMOOTH); - pgl.glEnable(PGL.GL_POLYGON_SMOOTH); - } } @@ -2934,34 +2950,30 @@ public class PGraphicsOpenGL extends PGraphics { if (1 < antialias) { antialias = 0; - if (primarySurface) { - restartContext(); - //throw new PApplet.RendererChangeException(); - } else { - initOffscreen(); - } + // This will trigger a surface restart next time + // requestDraw() is called. + pgl.initialized = false; } - - pgl.glDisable(PGL.GL_MULTISAMPLE); - pgl.glDisable(PGL.GL_POINT_SMOOTH); - pgl.glDisable(PGL.GL_LINE_SMOOTH); - pgl.glDisable(PGL.GL_POLYGON_SMOOTH); } + ////////////////////////////////////////////////////////////// // SHAPE // public void shapeMode(int mode) + public void shape(PShape3D shape) { shape.draw(this); } + public void shape(PShape3D shape, float x, float y) { shape(shape, x, y, 0); } + public void shape(PShape3D shape, float x, float y, float z) { pushMatrix(); translate(x, y, z); @@ -2969,6 +2981,7 @@ public class PGraphicsOpenGL extends PGraphics { popMatrix(); } + // public void shape(PShape shape, float x, float y, float c, float d) ////////////////////////////////////////////////////////////// @@ -3008,6 +3021,7 @@ public class PGraphicsOpenGL extends PGraphics { // TEXT IMPL + // protected void textLineAlignImpl(char buffer[], int start, int stop, // float x, float y) @@ -3020,11 +3034,7 @@ public class PGraphicsOpenGL extends PGraphics { textTex = new PFontTexture(parent, textFont, maxTextureSize, maxTextureSize); textFont.setCache(this, textTex); } else { - if (!pgl.contextIsCurrent(textTex.context)) { - for (int i = 0; i < textTex.textures.length; i++) { - textTex.textures[i].glID = 0; // To avoid finalization (texture objects were already deleted when context changed). - textTex.textures[i] = null; - } + if (textTex.contextIsOutdated()) { textTex = new PFontTexture(parent, textFont, PApplet.min(PGL.MAX_FONT_TEX_SIZE, maxTextureSize), PApplet.min(PGL.MAX_FONT_TEX_SIZE, maxTextureSize)); textFont.setCache(this, textTex); @@ -3071,6 +3081,7 @@ public class PGraphicsOpenGL extends PGraphics { blendMode(savedBlendMode); } + protected void textCharImpl(char ch, float x, float y) { PFont.Glyph glyph = textFont.getGlyph(ch); @@ -3100,7 +3111,7 @@ public class PGraphicsOpenGL extends PGraphics { protected void textCharModelImpl(PFontTexture.TextureInfo info, float x0, float y0, - float x1, float y1) { + float x1, float y1) { if (textTex.currentTex != info.texIndex) { textTex.setTexture(info.texIndex); } @@ -3336,12 +3347,15 @@ public class PGraphicsOpenGL extends PGraphics { // MATRIX GET/SET/PRINT + public PMatrix getMatrix() { return modelview.get(); } + // public PMatrix2D getMatrix(PMatrix2D target) + public PMatrix3D getMatrix(PMatrix3D target) { if (target == null) { target = new PMatrix3D(); @@ -3350,13 +3364,16 @@ public class PGraphicsOpenGL extends PGraphics { return target; } + // public void setMatrix(PMatrix source) + public void setMatrix(PMatrix2D source) { resetMatrix(); applyMatrix(source); } + /** * Set the current transformation to the contents of the specified source. */ @@ -3365,6 +3382,7 @@ public class PGraphicsOpenGL extends PGraphics { applyMatrix(source); } + /** * Print the current model (or "transformation") matrix. */ @@ -3372,6 +3390,7 @@ public class PGraphicsOpenGL extends PGraphics { modelview.print(); } + ////////////////////////////////////////////////////////////// // PROJECTION @@ -3933,14 +3952,17 @@ public class PGraphicsOpenGL extends PGraphics { // STROKE CAP/JOIN/WEIGHT + public void strokeWeight(float weight) { this.strokeWeight = weight; } + public void strokeJoin(int join) { this.strokeJoin = join; } + public void strokeCap(int cap) { this.strokeCap = cap; } @@ -4065,6 +4087,7 @@ public class PGraphicsOpenGL extends PGraphics { colorMode = colorModeSaved; } + /** * Disables lighting. */ @@ -4073,6 +4096,7 @@ public class PGraphicsOpenGL extends PGraphics { lightCount = 0; } + /** * Add an ambient light based on the current color mode. */ @@ -4080,6 +4104,7 @@ public class PGraphicsOpenGL extends PGraphics { ambientLight(r, g, b, 0, 0, 0); } + /** * Add an ambient light based on the current color mode. This version includes * an (x, y, z) position for situations where the falloff distance is used. @@ -4105,6 +4130,7 @@ public class PGraphicsOpenGL extends PGraphics { lightCount++; } + public void directionalLight(float r, float g, float b, float dx, float dy, float dz) { @@ -4129,6 +4155,7 @@ public class PGraphicsOpenGL extends PGraphics { lightCount++; } + public void pointLight(float r, float g, float b, float x, float y, float z) { enableLighting(); @@ -4154,6 +4181,7 @@ public class PGraphicsOpenGL extends PGraphics { lightCount++; } + public void spotLight(float r, float g, float b, float x, float y, float z, float dx, float dy, float dz, @@ -4181,6 +4209,7 @@ public class PGraphicsOpenGL extends PGraphics { lightCount++; } + /** * Set the light falloff rates for the last light that was created. Default is * lightFalloff(1, 0, 0). @@ -4191,6 +4220,7 @@ public class PGraphicsOpenGL extends PGraphics { currentLightFalloffQuadratic = quadratic; } + /** * Set the specular color of the last light created. */ @@ -4201,12 +4231,14 @@ public class PGraphicsOpenGL extends PGraphics { currentLightSpecular[2] = calcB; } + protected void enableLighting() { if (!lights) { flush(); // Flushing non-lit geometry. lights = true; } } + protected void disableLighting() { if (lights) { @@ -4215,6 +4247,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + protected void lightPosition(int num, float x, float y, float z, boolean dir) { lightPosition[4 * num + 0] = x * modelview.m00 + y * modelview.m01 + z * modelview.m02 + modelview.m03; lightPosition[4 * num + 1] = x * modelview.m10 + y * modelview.m11 + z * modelview.m12 + modelview.m13; @@ -4224,6 +4257,7 @@ public class PGraphicsOpenGL extends PGraphics { lightPosition[4 * num + 3] = dir ? 1: 0; } + protected void lightNormal(int num, float dx, float dy, float dz) { // Applying normal matrix to the light direction vector, which is the transpose of the inverse of the // modelview. @@ -4237,12 +4271,14 @@ public class PGraphicsOpenGL extends PGraphics { lightNormal[3 * num + 2] = invn * nz; } + protected void lightAmbient(int num, float r, float g, float b) { colorCalc(r, g, b); lightAmbient[3 * num + 0] = calcR; lightAmbient[3 * num + 1] = calcG; lightAmbient[3 * num + 2] = calcB; } + protected void noLightAmbient(int num) { lightAmbient[3 * num + 0] = 0; @@ -4250,12 +4286,14 @@ public class PGraphicsOpenGL extends PGraphics { lightAmbient[3 * num + 2] = 0; } + protected void lightDiffuse(int num, float r, float g, float b) { colorCalc(r, g, b); lightDiffuse[3 * num + 0] = calcR; lightDiffuse[3 * num + 1] = calcG; lightDiffuse[3 * num + 2] = calcB; } + protected void noLightDiffuse(int num) { lightDiffuse[3 * num + 0] = 0; @@ -4263,35 +4301,41 @@ public class PGraphicsOpenGL extends PGraphics { lightDiffuse[3 * num + 2] = 0; } + protected void lightSpecular(int num, float r, float g, float b) { lightSpecular[3 * num + 0] = r; lightSpecular[3 * num + 1] = g; lightSpecular[3 * num + 2] = b; } + protected void noLightSpecular(int num) { lightSpecular[3 * num + 0] = 0; lightSpecular[3 * num + 1] = 0; lightSpecular[3 * num + 2] = 0; } + protected void lightFalloff(int num, float c0, float c1, float c2) { lightFalloffCoefficients[3 * num + 0] = c0; lightFalloffCoefficients[3 * num + 1] = c1; lightFalloffCoefficients[3 * num + 2] = c2; } + protected void noLightFalloff(int num) { lightFalloffCoefficients[3 * num + 0] = 1; lightFalloffCoefficients[3 * num + 1] = 0; lightFalloffCoefficients[3 * num + 2] = 0; } + protected void lightSpot(int num, float angle, float exponent) { lightSpotParameters[2 * num + 0] = Math.max(0, PApplet.cos(angle)); lightSpotParameters[2 * num + 1] = exponent; } + protected void noLightSpot(int num) { lightSpotParameters[2 * num + 0] = 0; lightSpotParameters[2 * num + 1] = 0; @@ -4302,24 +4346,33 @@ public class PGraphicsOpenGL extends PGraphics { // BACKGROUND + protected void backgroundImpl(PImage image) { backgroundImpl(); set(0, 0, image); clearColorBuffer = true; } + protected void backgroundImpl() { tessGeo.clear(); texCache.clear(); + pgl.glDepthMask(true); pgl.glClearColor(0, 0, 0, 0); - pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT); - + pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT); + if (hints[DISABLE_DEPTH_MASK]) { + pgl.glDepthMask(false); + } else { + pgl.glDepthMask(true); + } + pgl.glClearColor(backgroundR, backgroundG, backgroundB, 1); pgl.glClear(PGL.GL_COLOR_BUFFER_BIT); clearColorBuffer = true; } + ////////////////////////////////////////////////////////////// // COLOR MODE @@ -4375,6 +4428,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + ////////////////////////////////////////////////////////////// // RENDERER SUPPORT QUERIES @@ -4417,6 +4471,7 @@ public class PGraphicsOpenGL extends PGraphics { // LOAD/UPDATE PIXELS + public void loadPixels() { flush(); @@ -4512,6 +4567,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + /** * Convert native OpenGL format into palatable ARGB format. This function * leaves alone (ignores) the alpha component. Also flips the image @@ -4551,6 +4607,7 @@ public class PGraphicsOpenGL extends PGraphics { yindex -= image.width * 2; } } + /** * Convert native OpenGL format into palatable ARGB format. This function @@ -4594,6 +4651,7 @@ public class PGraphicsOpenGL extends PGraphics { yindex -= image.width * 2; } } + /** * Convert ARGB (Java/Processing) data to native OpenGL format. This function @@ -4643,6 +4701,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + /** * Convert Java ARGB to native OpenGL format. Also flips the image vertically, * since images are upside-down in GL. @@ -4688,6 +4747,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + public void updatePixels() { // flip vertically (opengl stores images upside down), @@ -4757,11 +4817,13 @@ public class PGraphicsOpenGL extends PGraphics { endGLOp(); } } + ////////////////////////////////////////////////////////////// // LOAD/UPDATE TEXTURE + public void loadTexture() { if (primarySurface) { if (!drawing) { @@ -4778,6 +4840,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + protected void loadTextureImpl(int sampling) { if (width == 0 || height == 0) return; if (texture == null) { @@ -4795,6 +4858,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + // Draws wherever it is in the screen texture right now to the screen. public void updateTexture() { flush(); @@ -4821,14 +4885,17 @@ public class PGraphicsOpenGL extends PGraphics { } } + protected void drawTexture() { drawTexture(texture, texCrop, 0, 0, width, height); } + protected void copyToTexture(IntBuffer buffer) { copyToTexture(texture, buffer, 0, 0, width, height); } + protected void copyFrameToTexture() { // Make sure that the execution off all the openGL commands is // finished before loading the texture. @@ -4836,26 +4903,32 @@ public class PGraphicsOpenGL extends PGraphics { loadTexture(); } + protected void pixelsToTexture() { texture.set(pixels); } + protected void textureToPixels() { texture.get(pixels); } + ////////////////////////////////////////////////////////////// // RESIZE + public void resize(int wide, int high) { PGraphics.showMethodWarning("resize"); } + ////////////////////////////////////////////////////////////// // GET/SET + public int get(int x, int y) { flush(); @@ -4902,9 +4975,11 @@ public class PGraphicsOpenGL extends PGraphics { | ((getset >> 16) & 0xff); } } + // public PImage get(int x, int y, int w, int h) + protected PImage getImpl(int x, int y, int w, int h) { flush(); @@ -4935,10 +5010,12 @@ public class PGraphicsOpenGL extends PGraphics { return newbie; } + public PImage get() { return get(0, 0, width, height); } + // TODO: doesn't appear to work public void set(int x, int y, int argb) { flush(); @@ -4990,6 +5067,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + /** * Set an image directly to the screen. * @@ -5026,11 +5104,13 @@ public class PGraphicsOpenGL extends PGraphics { } } } - + + ////////////////////////////////////////////////////////////// // MASK + public void mask(int alpha[]) { PGraphics.showMethodWarning("mask"); } @@ -5040,10 +5120,12 @@ public class PGraphicsOpenGL extends PGraphics { PGraphics.showMethodWarning("mask"); } + ////////////////////////////////////////////////////////////// // FILTER + /** * This is really inefficient and not a good idea in OpenGL. Use get() and * set() with a smaller image area, or call the filter on an image instead, @@ -5055,6 +5137,7 @@ public class PGraphicsOpenGL extends PGraphics { set(0, 0, temp); } + /** * This is really inefficient and not a good idea in OpenGL. Use get() and * set() with a smaller image area, or call the filter on an image instead, @@ -5066,6 +5149,7 @@ public class PGraphicsOpenGL extends PGraphics { set(0, 0, temp); } + ////////////////////////////////////////////////////////////// /** @@ -5084,6 +5168,7 @@ public class PGraphicsOpenGL extends PGraphics { // int sx1, int sy1, int sx2, int sy2, // int dx1, int dy1, int dx2, int dy2) + ////////////////////////////////////////////////////////////// // BLEND @@ -5095,6 +5180,7 @@ public class PGraphicsOpenGL extends PGraphics { // set(dx, dy, PImage.blendColor(src.get(sx, sy), get(dx, dy), mode)); // } + /** * Extremely slow and not optimized, should use GL methods instead. Currently * calls a beginPixels() on the whole canvas, then does the copy, then it @@ -5117,6 +5203,7 @@ public class PGraphicsOpenGL extends PGraphics { // updatePixels(); // } + /** * Allows to set custom blend modes for the entire scene, using openGL. * Reference article about blending modes: @@ -5197,6 +5284,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + protected void setDefaultBlend() { blendMode = BLEND; pgl.glEnable(PGL.GL_BLEND); @@ -5213,10 +5301,12 @@ public class PGraphicsOpenGL extends PGraphics { // public void save(String filename) // PImage calls loadPixels() + ////////////////////////////////////////////////////////////// // SHAPE I/O + protected String[] getSupportedShapeFormats() { return new String[] { "obj" }; } @@ -5238,6 +5328,7 @@ public class PGraphicsOpenGL extends PGraphics { // TEXTURE UTILS + /** * This utility method returns the texture associated to the renderer's. * drawing surface, making sure is updated to reflect the current contents @@ -5248,6 +5339,7 @@ public class PGraphicsOpenGL extends PGraphics { return texture; } + /** * This utility method returns the texture associated to the image. * creating and/or updating it if needed. @@ -5258,16 +5350,8 @@ public class PGraphicsOpenGL extends PGraphics { if (tex == null) { tex = addTexture(img); } else { - if (!pgl.contextIsCurrent(tex.context)) { - // The texture was created with a different context. We need - // to recreate it. First, we make sure that the old GL id - // is not used to delete the texture object (it was already - // deleted when the context changed). - tex.glID = 0; + if (tex.contextIsOutdated()) { tex = addTexture(img); - // TODO: apply this mechanism to all the Processing objects using - // GL resources (PShape, PShader, PFramebuffer). They will probably - // need the cache thingy as well. } if (img.isModified()) { @@ -5314,6 +5398,7 @@ public class PGraphicsOpenGL extends PGraphics { return tex; } + protected PImage wrapTexture(PTexture tex) { // We don't use the PImage(int width, int height, int mode) constructor to // avoid initializing the pixels array. @@ -5326,6 +5411,7 @@ public class PGraphicsOpenGL extends PGraphics { return img; } + protected void updateTexture(PImage img, PTexture tex) { if (tex != null) { int x = img.getModifiedX1(); @@ -5381,11 +5467,13 @@ public class PGraphicsOpenGL extends PGraphics { blendMode(savedBlendMode); } + protected void drawTexture(int w, int h, int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) { int[] crop = {x1, y1, w1, h1}; drawTexture(w, h, crop, x2, y2, w2, h2); } + /** * Utility function to render currently bound texture using current blend mode. * Equivalent to: @@ -5438,6 +5526,7 @@ public class PGraphicsOpenGL extends PGraphics { drawTexQuad(0, 0, 1, 1); } + /** * Pushes a normalized (1x1) textured quad to the GPU. */ @@ -5472,34 +5561,23 @@ public class PGraphicsOpenGL extends PGraphics { // INITIALIZATION ROUTINES - static public void init() { - PGL.startup(true); - } - - static public void init(boolean beforeUI) { - PGL.startup(beforeUI); - } - - protected void restartSurface() { - if (primarySurface) { - initPrimary(); - } else { - initOffscreen(); - } - } - protected void initPrimary() { + if (pg != null) { + releaseResources(); + } + pgl.initPrimarySurface(antialias); pg = this; } + protected void initOffscreen() { // Getting the context and capabilities from the main renderer. pg = (PGraphicsOpenGL)parent.g; pgl.initOffscreenSurface(pg.pgl); - updatePGL(); + pgl.updateOffscreen(pg.pgl);; loadTextureImpl(BILINEAR); // In case of reinitialization (for example, when the smooth level @@ -5540,11 +5618,7 @@ public class PGraphicsOpenGL extends PGraphics { offscreenFramebuffer.setColorBuffer(texture); offscreenFramebuffer.clear(); } - - protected void updateOffscreenContext() { - pgl.updateOffscreenSurface(pg.pgl); - updatePGL(); - } + protected void getGLParameters() { OPENGL_VENDOR = pgl.glGetString(PGL.GL_VENDOR); @@ -5565,24 +5639,26 @@ public class PGraphicsOpenGL extends PGraphics { blendEqSupported = false; } -// int temp[] = new int[2]; + int temp[] = new int[2]; - pgl.glGetIntegerv(PGL.GL_MAX_TEXTURE_SIZE, getBuffer); - maxTextureSize = getBuffer.get(0); + pgl.glGetIntegerv(PGL.GL_MAX_TEXTURE_SIZE, temp, 0); + maxTextureSize = temp[0]; - pgl.glGetIntegerv(PGL.GL_ALIASED_LINE_WIDTH_RANGE, getBuffer); - maxLineWidth = getBuffer.get(0); + pgl.glGetIntegerv(PGL.GL_ALIASED_LINE_WIDTH_RANGE, temp, 0); + maxLineWidth = temp[1]; - pgl.glGetIntegerv(PGL.GL_ALIASED_POINT_SIZE_RANGE, getBuffer); - maxPointSize = getBuffer.get(0); + pgl.glGetIntegerv(PGL.GL_ALIASED_POINT_SIZE_RANGE, temp, 0); + maxPointSize = temp[1]; glParamsRead = true; } + ////////////////////////////////////////////////////////////// // SHADER HANDLING + public PShader loadShader(String vertFilename, String fragFilename, int kind) { if (kind == FILL_SHADER_SIMPLE) { return new FillShaderSimple(parent, vertFilename, fragFilename); @@ -5602,6 +5678,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + public PShader loadShader(String fragFilename, int kind) { PShader shader; if (kind == FILL_SHADER_SIMPLE) { @@ -5629,6 +5706,7 @@ public class PGraphicsOpenGL extends PGraphics { shader.setFragmentShader(fragFilename); return shader; } + public void setShader(PShader shader, int kind) { if (kind == FILL_SHADER_SIMPLE) { @@ -5648,6 +5726,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + public void resetShader(int kind) { if (kind == FILL_SHADER_SIMPLE) { if (defFillShaderSimple == null) { @@ -5684,6 +5763,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + protected FillShader getFillShader(boolean lit, boolean tex) { FillShader shader; if (lit) { @@ -5728,6 +5808,7 @@ public class PGraphicsOpenGL extends PGraphics { return shader; } + protected LineShader getLineShader() { if (defLineShader == null) { defLineShader = new LineShader(parent, defLineShaderVertURL, defLineShaderFragURL); @@ -5740,6 +5821,7 @@ public class PGraphicsOpenGL extends PGraphics { return lineShader; } + protected PointShader getPointShader() { if (defPointShader == null) { defPointShader = new PointShader(parent, defPointShaderVertURL, defPointShaderFragURL); @@ -5752,6 +5834,7 @@ public class PGraphicsOpenGL extends PGraphics { return pointShader; } + protected class FillShader extends PShader { public FillShader(PApplet parent) { super(parent); @@ -5786,6 +5869,7 @@ public class PGraphicsOpenGL extends PGraphics { public void setTexture(PTexture tex) { } } + protected class FillShaderSimple extends FillShader { protected int projmodelviewMatrixLoc; @@ -5841,6 +5925,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + protected class FillShaderLit extends FillShader { protected int projmodelviewMatrixLoc; protected int modelviewMatrixLoc; @@ -5977,6 +6062,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + protected class FillShaderTex extends FillShaderSimple { protected int inTexcoordLoc; @@ -6051,6 +6137,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + protected class FillShaderFull extends FillShaderLit { protected int inTexcoordLoc; @@ -6125,6 +6212,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + protected class LineShader extends PShader { protected int projectionMatrixLoc; protected int modelviewMatrixLoc; @@ -6192,7 +6280,7 @@ public class PGraphicsOpenGL extends PGraphics { updateGLModelview(); set4x4MatUniform(modelviewMatrixLoc, glModelview); - set4FloatUniform(viewportLoc, viewport.get(0), viewport.get(1), viewport.get(2), viewport.get(3)); + set4FloatUniform(viewportLoc, viewport[0], viewport[1], viewport[2], viewport[3]); if (hints[ENABLE_PERSPECTIVE_CORRECTED_LINES]) { setIntUniform(perspectiveLoc, 1); @@ -6212,6 +6300,7 @@ public class PGraphicsOpenGL extends PGraphics { } } + protected class PointShader extends PShader { protected int projectionMatrixLoc; protected int modelviewMatrixLoc; @@ -6285,22 +6374,27 @@ public class PGraphicsOpenGL extends PGraphics { } } + ////////////////////////////////////////////////////////////// // Input (raw) and Tessellated geometry, tessellator. + public InGeometry newInGeometry(int mode) { return new InGeometry(mode); } + protected TessGeometry newTessGeometry(int mode) { return new TessGeometry(mode); } + protected TexCache newTexCache() { return new TexCache(); } + // Holds an array of textures and the range of vertex // indices each texture applies to. public class TexCache { @@ -7149,48 +7243,48 @@ public class PGraphicsOpenGL extends PGraphics { public int fillVertexCount; public int firstFillVertex; public int lastFillVertex; - public FloatBuffer fillVertices; - public IntBuffer fillColors; - public FloatBuffer fillNormals; - public FloatBuffer fillTexcoords; + public float[] fillVertices; + public int[] fillColors; + public float[] fillNormals; + public float[] fillTexcoords; // Fill material properties (fillColor is used // as the diffuse color when lighting is enabled) - public IntBuffer fillAmbient; - public IntBuffer fillSpecular; - public IntBuffer fillEmissive; - public FloatBuffer fillShininess; + public int[] fillAmbient; + public int[] fillSpecular; + public int[] fillEmissive; + public float[] fillShininess; public int fillIndexCount; public int firstFillIndex; public int lastFillIndex; - public IntBuffer fillIndices; + public int[] fillIndices; // Tessellated line data public int lineVertexCount; public int firstLineVertex; public int lastLineVertex; - public FloatBuffer lineVertices; - public IntBuffer lineColors; - public FloatBuffer lineDirWidths; + public float[] lineVertices; + public int[] lineColors; + public float[] lineDirWidths; public int lineIndexCount; public int firstLineIndex; public int lastLineIndex; - public IntBuffer lineIndices; + public int[] lineIndices; // Tessellated point data public int pointVertexCount; public int firstPointVertex; public int lastPointVertex; - public FloatBuffer pointVertices; - public IntBuffer pointColors; - public FloatBuffer pointSizes; + public float[] pointVertices; + public int[] pointColors; + public float[] pointSizes; public int pointIndexCount; public int firstPointIndex; public int lastPointIndex; - public IntBuffer pointIndices; + public int[] pointIndices; public boolean isStroked; @@ -7208,57 +7302,36 @@ public class PGraphicsOpenGL extends PGraphics { firstPointVertex = lastPointVertex = pointVertexCount = 0; firstPointIndex = lastPointIndex = pointIndexCount = 0; - - fillVertices.clear(); - fillColors.clear(); - fillNormals.clear(); - fillTexcoords.clear(); - fillAmbient.clear(); - fillSpecular.clear(); - fillEmissive.clear(); - fillShininess.clear(); - fillIndices.clear(); - - lineVertices.clear(); - lineColors.clear(); - lineDirWidths.clear(); - lineIndices.clear(); - - pointVertices.clear(); - pointColors.clear(); - pointSizes.clear(); - pointIndices.clear(); isStroked = false; } public void allocate() { - fillVertices = pgl.createFloatBuffer(3 * PGL.DEFAULT_TESS_VERTICES); - fillColors = pgl.createIntBuffer(PGL.DEFAULT_TESS_VERTICES); - fillNormals = pgl.createFloatBuffer(3 * PGL.DEFAULT_TESS_VERTICES); - fillTexcoords = pgl.createFloatBuffer(2 * PGL.DEFAULT_TESS_VERTICES); - fillAmbient = pgl.createIntBuffer(PGL.DEFAULT_TESS_VERTICES); - fillSpecular = pgl.createIntBuffer(PGL.DEFAULT_TESS_VERTICES); - fillEmissive = pgl.createIntBuffer(PGL.DEFAULT_TESS_VERTICES); - fillShininess = pgl.createFloatBuffer(PGL.DEFAULT_TESS_VERTICES); - fillIndices = pgl.createIntBuffer(PGL.DEFAULT_TESS_VERTICES); + fillVertices = new float[3 * PGL.DEFAULT_TESS_VERTICES]; + fillColors = new int[PGL.DEFAULT_TESS_VERTICES]; + fillNormals = new float[3 * PGL.DEFAULT_TESS_VERTICES]; + fillTexcoords = new float[2 * PGL.DEFAULT_TESS_VERTICES]; + fillAmbient = new int[PGL.DEFAULT_TESS_VERTICES]; + fillSpecular = new int[PGL.DEFAULT_TESS_VERTICES]; + fillEmissive = new int[PGL.DEFAULT_TESS_VERTICES]; + fillShininess = new float[PGL.DEFAULT_TESS_VERTICES]; + fillIndices = new int[PGL.DEFAULT_TESS_VERTICES]; - lineVertices = pgl.createFloatBuffer(3 * PGL.DEFAULT_TESS_VERTICES); - lineColors = pgl.createIntBuffer(PGL.DEFAULT_TESS_VERTICES); - lineDirWidths = pgl.createFloatBuffer(4 * PGL.DEFAULT_TESS_VERTICES); - lineIndices = pgl.createIntBuffer(PGL.DEFAULT_TESS_VERTICES); + lineVertices = new float[3 * PGL.DEFAULT_TESS_VERTICES]; + lineColors = new int[PGL.DEFAULT_TESS_VERTICES]; + lineDirWidths = new float[4 * PGL.DEFAULT_TESS_VERTICES]; + lineIndices = new int[PGL.DEFAULT_TESS_VERTICES]; - pointVertices = pgl.createFloatBuffer(3 * PGL.DEFAULT_TESS_VERTICES); - pointColors = pgl.createIntBuffer(PGL.DEFAULT_TESS_VERTICES); - pointSizes = pgl.createFloatBuffer(2 * PGL.DEFAULT_TESS_VERTICES); - pointIndices = pgl.createIntBuffer(PGL.DEFAULT_TESS_VERTICES); + pointVertices = new float[3 * PGL.DEFAULT_TESS_VERTICES]; + pointColors = new int[PGL.DEFAULT_TESS_VERTICES]; + pointSizes = new float[2 * PGL.DEFAULT_TESS_VERTICES]; + pointIndices = new int[PGL.DEFAULT_TESS_VERTICES]; clear(); } public void trim() { - if (0 < fillVertexCount && fillVertexCount < fillVertices.capacity() / 3) { - prepareFillVerticesForCopy(); + if (0 < fillVertexCount && fillVertexCount < fillVertices.length / 3) { trimFillVertices(); trimFillColors(); trimFillNormals(); @@ -7269,136 +7342,131 @@ public class PGraphicsOpenGL extends PGraphics { trimFillShininess(); } - if (0 < fillIndexCount && fillIndexCount < fillIndices.capacity()) { - prepareFillIndicesForCopy(); + if (0 < fillIndexCount && fillIndexCount < fillIndices.length) { trimFillIndices(); } - if (0 < lineVertexCount && lineVertexCount < lineVertices.capacity() / 3) { - prepareLineVerticesForCopy(); + if (0 < lineVertexCount && lineVertexCount < lineVertices.length / 3) { trimLineVertices(); trimLineColors(); trimLineAttributes(); } - if (0 < lineIndexCount && lineIndexCount < lineIndices.capacity()) { - prepareLineIndicesForCopy(); + if (0 < lineIndexCount && lineIndexCount < lineIndices.length) { trimLineIndices(); } - if (0 < pointVertexCount && pointVertexCount < pointVertices.capacity() / 3) { - preparePointVerticesForCopy(); + if (0 < pointVertexCount && pointVertexCount < pointVertices.length / 3) { trimPointVertices(); trimPointColors(); trimPointAttributes(); } - if (0 < pointIndexCount && pointIndexCount < pointIndices.capacity()) { - preparePointIndicesForCopy(); + if (0 < pointIndexCount && pointIndexCount < pointIndices.length) { trimPointIndices(); } } protected void trimFillVertices() { - FloatBuffer temp = pgl.createFloatBuffer(3 * fillVertexCount); - temp.put(fillVertices); - fillVertices = temp; + float temp[] = new float[3 * fillVertexCount]; + PApplet.arrayCopy(fillVertices, 0, temp, 0, 3 * fillVertexCount); + fillVertices = temp; } protected void trimFillColors() { - IntBuffer temp = pgl.createIntBuffer(fillVertexCount); - temp.put(fillColors); - fillColors = temp; + int temp[] = new int[fillVertexCount]; + PApplet.arrayCopy(fillColors, 0, temp, 0, fillVertexCount); + fillColors = temp; } protected void trimFillNormals() { - FloatBuffer temp = pgl.createFloatBuffer(3 * fillVertexCount); - temp.put(fillNormals); - fillNormals = temp; + float temp[] = new float[3 * fillVertexCount]; + PApplet.arrayCopy(fillNormals, 0, temp, 0, 3 * fillVertexCount); + fillNormals = temp; } protected void trimFillTexcoords() { - FloatBuffer temp = pgl.createFloatBuffer(2 * fillVertexCount); - temp.put(fillTexcoords); - fillTexcoords = temp; + float temp[] = new float[2 * fillVertexCount]; + PApplet.arrayCopy(fillTexcoords, 0, temp, 0, 2 * fillVertexCount); + fillTexcoords = temp; } protected void trimFillAmbient() { - IntBuffer temp = pgl.createIntBuffer(fillVertexCount); - temp.put(fillAmbient); - fillAmbient = temp; + int temp[] = new int[fillVertexCount]; + PApplet.arrayCopy(fillAmbient, 0, temp, 0, fillVertexCount); + fillAmbient = temp; } protected void trimFillSpecular() { - IntBuffer temp = pgl.createIntBuffer(fillVertexCount); - temp.put(fillSpecular); - fillSpecular = temp; + int temp[] = new int[fillVertexCount]; + PApplet.arrayCopy(fillSpecular, 0, temp, 0, fillVertexCount); + fillSpecular = temp; } protected void trimFillEmissive() { - IntBuffer temp = pgl.createIntBuffer(fillVertexCount); - temp.put(fillEmissive); - fillEmissive = temp; + int temp[] = new int[fillVertexCount]; + PApplet.arrayCopy(fillEmissive, 0, temp, 0, fillVertexCount); + fillEmissive = temp; } protected void trimFillShininess() { - FloatBuffer temp = pgl.createFloatBuffer(fillVertexCount); - temp.put(fillShininess); - fillShininess = temp; + float temp[] = new float[fillVertexCount]; + PApplet.arrayCopy(fillShininess, 0, temp, 0, fillVertexCount); + fillShininess = temp; } public void trimFillIndices() { - IntBuffer temp = pgl.createIntBuffer(fillIndexCount); - temp.put(fillIndices); - fillIndices = temp; + int temp[] = new int[fillIndexCount]; + PApplet.arrayCopy(fillIndices, 0, temp, 0, fillIndexCount); + fillIndices = temp; } protected void trimLineVertices() { - FloatBuffer temp = pgl.createFloatBuffer(3 * lineVertexCount); - temp.put(lineVertices); - lineVertices = temp; + float temp[] = new float[3 * lineVertexCount]; + PApplet.arrayCopy(lineVertices, 0, temp, 0, 3 * lineVertexCount); + lineVertices = temp; } protected void trimLineColors() { - IntBuffer temp = pgl.createIntBuffer(lineVertexCount); - temp.put(lineColors); - lineColors = temp; + int temp[] = new int[lineVertexCount]; + PApplet.arrayCopy(lineColors, 0, temp, 0, lineVertexCount); + lineColors = temp; } protected void trimLineAttributes() { - FloatBuffer temp = pgl.createFloatBuffer(4 * lineVertexCount); - temp.put(lineDirWidths); - lineDirWidths = temp; + float temp[] = new float[4 * lineVertexCount]; + PApplet.arrayCopy(lineDirWidths, 0, temp, 0, 4 * lineVertexCount); + lineDirWidths = temp; } protected void trimLineIndices() { - IntBuffer temp = pgl.createIntBuffer(lineIndexCount); - temp.put(lineIndices); + int temp[] = new int[lineIndexCount]; + PApplet.arrayCopy(lineIndices, 0, temp, 0, lineIndexCount); lineIndices = temp; } protected void trimPointVertices() { - FloatBuffer temp = pgl.createFloatBuffer(3 * pointVertexCount); - temp.put(pointVertices); - pointVertices = temp; + float temp[] = new float[3 * pointVertexCount]; + PApplet.arrayCopy(pointVertices, 0, temp, 0, 3 * pointVertexCount); + pointVertices = temp; } protected void trimPointColors() { - IntBuffer temp = pgl.createIntBuffer(pointVertexCount); - temp.put(pointColors); - pointColors = temp; + int temp[] = new int[pointVertexCount]; + PApplet.arrayCopy(pointColors, 0, temp, 0, pointVertexCount); + pointColors = temp; } protected void trimPointAttributes() { - FloatBuffer temp = pgl.createFloatBuffer(2 * pointVertexCount); - temp.put(pointSizes); - pointSizes = temp; + float temp[] = new float[2 * pointVertexCount]; + PApplet.arrayCopy(pointSizes, 0, temp, 0, 2 * pointVertexCount); + pointSizes = temp; } protected void trimPointIndices() { - IntBuffer temp = pgl.createIntBuffer(pointIndexCount); - temp.put(pointIndices); - pointIndices = temp; + int temp[] = new int[pointIndexCount]; + PApplet.arrayCopy(pointIndices, 0, temp, 0, pointIndexCount); + pointIndices = temp; } public void dipose() { @@ -7502,8 +7570,7 @@ public class PGraphicsOpenGL extends PGraphics { // shapes in the hierarchy, as the entire geometry will be stored // contiguously in a single VBO in the root node. for (int i = 0; i < fillIndexCount; i++) { - fillIndices.position(i); - fillIndices.put(fillIndices.get(i) + voffset); + fillIndices[i] += voffset; } } @@ -7531,8 +7598,7 @@ public class PGraphicsOpenGL extends PGraphics { // shapes in the hierarchy, as the entire geometry will be stored // contiguously in a single VBO in the root node. for (int i = 0; i < lineIndexCount; i++) { - lineIndices.position(i); - lineIndices.put(lineIndices.get(i) + voffset); + lineIndices[i] += voffset; } } @@ -7560,8 +7626,7 @@ public class PGraphicsOpenGL extends PGraphics { // shapes in the hierarchy, as the entire geometry will be stored // contiguously in a single VBO in the root node. for (int i = 0; i < pointIndexCount; i++) { - pointIndices.position(i); - pointIndices.put(pointIndices.get(i) + voffset); + pointIndices[i] += voffset; } } @@ -7570,70 +7635,80 @@ public class PGraphicsOpenGL extends PGraphics { } public void fillIndexCheck() { - if (fillIndexCount == fillIndices.capacity()) { + if (fillIndexCount == fillIndices.length) { int newSize = fillIndexCount << 1; expandFillIndices(newSize); } - } + } public void expandFillIndices(int n) { - IntBuffer temp = pgl.createIntBuffer(n); - temp.put(fillIndices); + int temp[] = new int[n]; + PApplet.arrayCopy(fillIndices, 0, temp, 0, fillIndexCount); fillIndices = temp; } public void addFillIndex(int idx) { fillIndexCheck(); - fillIndices.put(fillIndexCount, PGL.makeIndex(idx)); + fillIndices[fillIndexCount] = PGL.makeIndex(idx); fillIndexCount++; lastFillIndex = fillIndexCount - 1; } public void calcFillNormal(int i0, int i1, int i2) { - float[] v0 = new float[3]; - float[] v1 = new float[3]; - float[] v2 = new float[3]; - float[] normal = new float[3]; + int index; - fillVertices.position(3 * i0); - fillVertices.get(v0); + index = 3 * i0; + float x0 = fillVertices[index++]; + float y0 = fillVertices[index++]; + float z0 = fillVertices[index ]; - fillVertices.position(3 * i1); - fillVertices.get(v1); - - fillVertices.position(3 * i2); - fillVertices.get(v2); + index = 3 * i1; + float x1 = fillVertices[index++]; + float y1 = fillVertices[index++]; + float z1 = fillVertices[index ]; + + index = 3 * i2; + float x2 = fillVertices[index++]; + float y2 = fillVertices[index++]; + float z2 = fillVertices[index ]; - float v12x = v2[0] - v1[0]; - float v12y = v2[1] - v1[1]; - float v12z = v2[2] - v1[2]; - - float v10x = v0[0] - v1[0]; - float v10y = v0[1] - v1[1]; - float v10z = v0[2] - v1[2]; - - normal[0] = v12y * v10z - v10y * v12z; - normal[1] = v12z * v10x - v10z * v12x; - normal[2] = v12x * v10y - v10x * v12y; - float d = PApplet.sqrt(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]); - normal[0] /= d; - normal[1] /= d; - normal[2] /= d; + float v12x = x2 - x1; + float v12y = y2 - y1; + float v12z = z2 - z1; - fillNormals.position(3 * i0); - fillNormals.put(normal); + float v10x = x0 - x1; + float v10y = y0 - y1; + float v10z = z0 - z1; + + float nx = v12y * v10z - v10y * v12z; + float ny = v12z * v10x - v10z * v12x; + float nz = v12x * v10y - v10x * v12y; + float d = PApplet.sqrt(nx * nx + ny * ny + nz * nz); + nx /= d; + ny /= d; + nz /= d; + + index = 3 * i0; + fillNormals[index++] = nx; + fillNormals[index++] = ny; + fillNormals[index ] = nz; - fillNormals.position(3 * i1); - fillNormals.put(normal); + index = 3 * i1; + fillNormals[index++] = nx; + fillNormals[index++] = ny; + fillNormals[index ] = nz; - fillNormals.position(3 * i2); - fillNormals.put(normal); + index = 3 * i2; + fillNormals[index++] = nx; + fillNormals[index++] = ny; + fillNormals[index ] = nz; + } public void fillVertexCheck() { - if (fillVertexCount == fillVertices.capacity() / 3) { + if (fillVertexCount == fillVertices.length / 3) { int newSize = fillVertexCount << 1; - prepareFillVerticesForCopy(); + expandFillVertices(newSize); expandFillColors(newSize); expandFillNormals(newSize); @@ -7646,10 +7721,10 @@ public class PGraphicsOpenGL extends PGraphics { } public void addFillVertices(int count) { - int oldSize = fillVertices.capacity() / 3; + int oldSize = fillVertices.length / 3; if (fillVertexCount + count > oldSize) { int newSize = expandVertSize(oldSize, fillVertexCount + count); - prepareFillVerticesForCopy(); + expandFillVertices(newSize); expandFillColors(newSize); expandFillNormals(newSize); @@ -7666,10 +7741,10 @@ public class PGraphicsOpenGL extends PGraphics { } public void addFillIndices(int count) { - int oldSize = fillIndices.capacity(); + int oldSize = fillIndices.length; if (fillIndexCount + count > oldSize) { int newSize = expandIndSize(oldSize, fillIndexCount + count); - prepareFillIndicesForCopy(); + expandFillIndices(newSize); } @@ -7678,147 +7753,59 @@ public class PGraphicsOpenGL extends PGraphics { lastFillIndex = fillIndexCount - 1; } - protected void prepareFillVerticesForCopy() { - prepareFillVerticesForCopy(0, fillVertexCount); - } - - protected void prepareFillIndicesForCopy() { - prepareFillIndicesForCopy(0, fillIndexCount); - } - - protected void prepareFillVerticesForCopy(int start, int count) { - fillVertices.position(3 * start); - fillVertices.limit(3 * count); - - fillColors.position(start); - fillColors.limit(count); - - fillNormals.position(3 * start); - fillNormals.limit(3 * count); - - fillTexcoords.position(2 * start); - fillTexcoords.limit(2 * count); - - fillAmbient.position(start); - fillAmbient.limit(count); - - fillSpecular.position(start); - fillSpecular.limit(count); - - fillEmissive.position(start); - fillEmissive.limit(count); - - fillShininess.position(start); - fillShininess.limit(count); - } - - protected void prepareFillIndicesForCopy(int start, int count) { - fillIndices.position(start); - fillIndices.limit(count); - } - - protected void prepareLineVerticesForCopy() { - prepareLineVerticesForCopy(0, lineVertexCount); - } - - protected void prepareLineIndicesForCopy() { - prepareLineIndicesForCopy(0, lineIndexCount); - } - - protected void prepareLineVerticesForCopy(int start, int count) { - lineVertices.position(3 * start); - lineVertices.limit(3 * count); - - lineColors.position(start); - lineColors.limit(count); - - lineDirWidths.position(4 * start); - lineDirWidths.limit(4 * count); - } - - protected void prepareLineIndicesForCopy(int start, int count) { - lineIndices.position(start); - lineIndices.limit(count); - } - - protected void preparePointVerticesForCopy() { - preparePointVerticesForCopy(0, pointVertexCount); - } - - protected void preparePointIndicesForCopy() { - preparePointIndicesForCopy(0, pointIndexCount); - } - - protected void preparePointVerticesForCopy(int start, int count) { - pointVertices.position(3 * start); - pointVertices.limit(3 * count); - - pointColors.position(start); - pointColors.limit(count); - - pointSizes.position(2 * start); - pointSizes.limit(2 * count); - } - - protected void preparePointIndicesForCopy(int start, int count) { - pointIndices.position(start); - pointIndices.limit(count); - } - - protected void expandFillVertices(int n) { - FloatBuffer temp = pgl.createFloatBuffer(3 * n); - temp.put(fillVertices); - fillVertices = temp; + float temp[] = new float[3 * n]; + PApplet.arrayCopy(fillVertices, 0, temp, 0, 3 * fillVertexCount); + fillVertices = temp; } protected void expandFillColors(int n) { - IntBuffer temp = pgl.createIntBuffer(n); - temp.put(fillColors); - fillColors = temp; + int temp[] = new int[n]; + PApplet.arrayCopy(fillColors, 0, temp, 0, fillVertexCount); + fillColors = temp; } protected void expandFillNormals(int n) { - FloatBuffer temp = pgl.createFloatBuffer(3 * n); - temp.put(fillNormals); - fillNormals = temp; + float temp[] = new float[3 * n]; + PApplet.arrayCopy(fillNormals, 0, temp, 0, 3 * fillVertexCount); + fillNormals = temp; } protected void expandFillTexcoords(int n) { - FloatBuffer temp = pgl.createFloatBuffer(2 * n); - temp.put(fillTexcoords); - fillTexcoords = temp; + float temp[] = new float[2 * n]; + PApplet.arrayCopy(fillTexcoords, 0, temp, 0, 2 * fillVertexCount); + fillTexcoords = temp; } protected void expandFillAmbient(int n) { - IntBuffer temp = pgl.createIntBuffer(n); - temp.put(fillAmbient); - fillAmbient = temp; + int temp[] = new int[n]; + PApplet.arrayCopy(fillAmbient, 0, temp, 0, fillVertexCount); + fillAmbient = temp; } protected void expandFillSpecular(int n) { - IntBuffer temp = pgl.createIntBuffer(n); - temp.put(fillSpecular); - fillSpecular = temp; + int temp[] = new int[n]; + PApplet.arrayCopy(fillSpecular, 0, temp, 0, fillVertexCount); + fillSpecular = temp; } protected void expandFillEmissive(int n) { - IntBuffer temp = pgl.createIntBuffer(n); - temp.put(fillEmissive); - fillEmissive = temp; + int temp[] = new int[n]; + PApplet.arrayCopy(fillEmissive, 0, temp, 0, fillVertexCount); + fillEmissive = temp; } protected void expandFillShininess(int n) { - FloatBuffer temp = pgl.createFloatBuffer(n); - temp.put(fillShininess); - fillShininess = temp; + float temp[] = new float[n]; + PApplet.arrayCopy(fillShininess, 0, temp, 0, fillVertexCount); + fillShininess = temp; } public void addLineVertices(int count) { - int oldSize = lineVertices.capacity() / 3; + int oldSize = lineVertices.length / 3; if (lineVertexCount + count > oldSize) { int newSize = expandVertSize(oldSize, lineVertexCount + count); - prepareLineVerticesForCopy(); + expandLineVertices(newSize); expandLineColors(newSize); expandLineAttributes(newSize); @@ -7830,28 +7817,28 @@ public class PGraphicsOpenGL extends PGraphics { } protected void expandLineVertices(int n) { - FloatBuffer temp = pgl.createFloatBuffer(3 * n); - temp.put(lineVertices); - lineVertices = temp; + float temp[] = new float[3 * n]; + PApplet.arrayCopy(lineVertices, 0, temp, 0, 3 * lineVertexCount); + lineVertices = temp; } protected void expandLineColors(int n) { - IntBuffer temp = pgl.createIntBuffer(n); - temp.put(lineColors); - lineColors = temp; + int temp[] = new int[n]; + PApplet.arrayCopy(lineColors, 0, temp, 0, lineVertexCount); + lineColors = temp; } protected void expandLineAttributes(int n) { - FloatBuffer temp = pgl.createFloatBuffer(4 * n); - temp.put(lineDirWidths); - lineDirWidths = temp; + float temp[] = new float[4 * n]; + PApplet.arrayCopy(lineDirWidths, 0, temp, 0, 4 * lineVertexCount); + lineDirWidths = temp; } public void addLineIndices(int count) { - int oldSize = lineIndices.capacity(); + int oldSize = lineIndices.length; if (lineIndexCount + count > oldSize) { int newSize = expandIndSize(oldSize, lineIndexCount + count); - prepareLineIndicesForCopy(); + expandLineIndices(newSize); } @@ -7861,16 +7848,16 @@ public class PGraphicsOpenGL extends PGraphics { } protected void expandLineIndices(int n) { - IntBuffer temp = pgl.createIntBuffer(n); - temp.put(lineIndices); - lineIndices = temp; + int temp[] = new int[n]; + PApplet.arrayCopy(lineIndices, 0, temp, 0, lineIndexCount); + lineIndices = temp; } public void addPointVertices(int count) { - int oldSize = pointVertices.capacity() / 3; + int oldSize = pointVertices.length / 3; if (pointVertexCount + count > oldSize) { int newSize = expandVertSize(oldSize, pointVertexCount + count); - preparePointVerticesForCopy(); + expandPointVertices(newSize); expandPointColors(newSize); expandPointAttributes(newSize); @@ -7882,28 +7869,28 @@ public class PGraphicsOpenGL extends PGraphics { } protected void expandPointVertices(int n) { - FloatBuffer temp = pgl.createFloatBuffer(3 * n); - temp.put(pointVertices); - pointVertices = temp; + float temp[] = new float[3 * n]; + PApplet.arrayCopy(pointVertices, 0, temp, 0, 3 * pointVertexCount); + pointVertices = temp; } protected void expandPointColors(int n) { - IntBuffer temp = pgl.createIntBuffer(n); - temp.put(pointColors); - pointColors = temp; + int temp[] = new int[n]; + PApplet.arrayCopy(pointColors, 0, temp, 0, pointVertexCount); + pointColors = temp; } protected void expandPointAttributes(int n) { - FloatBuffer temp = pgl.createFloatBuffer(2 * n); - temp.put(pointSizes); - pointSizes = temp; + float temp[] = new float[2 * n]; + PApplet.arrayCopy(pointSizes, 0, temp, 0, 2 * pointVertexCount); + pointSizes = temp; } public void addPointIndices(int count) { - int oldSize = pointIndices.capacity(); + int oldSize = pointIndices.length; if (pointIndexCount + count > oldSize) { int newSize = expandIndSize(oldSize, pointIndexCount + count); - preparePointIndicesForCopy(); + expandPointIndices(newSize); } @@ -7913,9 +7900,9 @@ public class PGraphicsOpenGL extends PGraphics { } protected void expandPointIndices(int n) { - IntBuffer temp = pgl.createIntBuffer(n); - temp.put(pointIndices); - pointIndices = temp; + int temp[] = new int[n]; + PApplet.arrayCopy(pointIndices, 0, temp, 0, pointIndexCount); + pointIndices = temp; } public void addFillVertex(float x, float y, float z, @@ -7924,50 +7911,43 @@ public class PGraphicsOpenGL extends PGraphics { float u, float v, int am, int sp, int em, float shine) { fillVertexCheck(); + int index; - float[] vert = new float[3]; - float[] norm = new float[3]; - float[] tcoord = {u, v}; if (renderMode == IMMEDIATE && flushMode == FLUSH_WHEN_FULL && !hints[DISABLE_TRANSFORM_CACHE]) { PMatrix3D mm = modelview; PMatrix3D nm = modelviewInv; - vert[0] = x * mm.m00 + y * mm.m01 + z * mm.m02 + mm.m03; - vert[1] = x * mm.m10 + y * mm.m11 + z * mm.m12 + mm.m13; - vert[2] = x * mm.m20 + y * mm.m21 + z * mm.m22 + mm.m23; + index = 3 * fillVertexCount; + fillVertices[index++] = x * mm.m00 + y * mm.m01 + z * mm.m02 + mm.m03; + fillVertices[index++] = x * mm.m10 + y * mm.m11 + z * mm.m12 + mm.m13; + fillVertices[index ] = x * mm.m20 + y * mm.m21 + z * mm.m22 + mm.m23; - norm[0] = nx * nm.m00 + ny * nm.m10 + nz * nm.m20; - norm[1] = nx * nm.m01 + ny * nm.m11 + nz * nm.m21; - norm[2] = nx * nm.m02 + ny * nm.m12 + nz * nm.m22; + index = 3 * fillVertexCount; + fillNormals[index++] = nx * nm.m00 + ny * nm.m10 + nz * nm.m20; + fillNormals[index++] = nx * nm.m01 + ny * nm.m11 + nz * nm.m21; + fillNormals[index ] = nx * nm.m02 + ny * nm.m12 + nz * nm.m22; } else { - vert[0] = x; - vert[1] = y; - vert[2] = z; - - norm[0] = nx; - norm[1] = ny; - norm[2] = nz; + index = 3 * fillVertexCount; + fillVertices[index++] = x; + fillVertices[index++] = y; + fillVertices[index ] = z; + + index = 3 * fillVertexCount; + fillNormals[index++] = nx; + fillNormals[index++] = ny; + fillNormals[index ] = nz; } - fillVertices.position(3 * fillVertexCount); - fillVertices.put(vert); - fillColors.position(fillVertexCount); - fillColors.put(rgba); + fillColors[fillVertexCount] = rgba; - fillNormals.position(3 * fillVertexCount); - fillNormals.put(norm); - - fillTexcoords.position(2 * fillVertexCount); - fillTexcoords.put(tcoord); + index = 2 * fillVertexCount; + fillTexcoords[index++] = u; + fillTexcoords[index ] = v; - fillAmbient.position(fillVertexCount); - fillAmbient.put(am); - fillSpecular.position(fillVertexCount); - fillSpecular.put(sp); - fillEmissive.position(fillVertexCount); - fillEmissive.put(em); - fillShininess.position(fillVertexCount); - fillShininess.put(shine); + fillAmbient[fillVertexCount] = am; + fillSpecular[fillVertexCount] = sp; + fillEmissive[fillVertexCount] = em; + fillShininess[fillVertexCount] = shine; fillVertexCount++; } @@ -7980,8 +7960,6 @@ public class PGraphicsOpenGL extends PGraphics { addFillVertices(nvert); - float[] vert = new float[3]; - float[] norm = new float[3]; if (renderMode == IMMEDIATE && flushMode == FLUSH_WHEN_FULL && !hints[DISABLE_TRANSFORM_CACHE]) { PMatrix3D mm = modelview; PMatrix3D nm = modelviewInv; @@ -8000,49 +7978,78 @@ public class PGraphicsOpenGL extends PGraphics { float ny = in.normals[index++]; float nz = in.normals[index ]; - vert[0] = x * mm.m00 + y * mm.m01 + z * mm.m02 + mm.m03; - vert[1] = x * mm.m10 + y * mm.m11 + z * mm.m12 + mm.m13; - vert[2] = x * mm.m20 + y * mm.m21 + z * mm.m22 + mm.m23; - - norm[0] = nx * nm.m00 + ny * nm.m10 + nz * nm.m20; - norm[1] = nx * nm.m01 + ny * nm.m11 + nz * nm.m21; - norm[2] = nx * nm.m02 + ny * nm.m12 + nz * nm.m22; - - fillVertices.position(3 * tessIdx); - try { - fillVertices.put(vert); - } catch (java.nio.BufferOverflowException e) { - PApplet.println("mama mia " + 3 * tessIdx + " " + fillVertices.position() + " " + fillVertices.limit() + " " + fillVertices.capacity() + " " + 3 * fillVertexCount); - } + index = 3 * tessIdx; + fillVertices[index++] = x * mm.m00 + y * mm.m01 + z * mm.m02 + mm.m03; + fillVertices[index++] = x * mm.m10 + y * mm.m11 + z * mm.m12 + mm.m13; + fillVertices[index ] = x * mm.m20 + y * mm.m21 + z * mm.m22 + mm.m23; - fillNormals.position(3 * tessIdx); - fillNormals.put(norm); + index = 3 * tessIdx; + fillNormals[index++] = nx * nm.m00 + ny * nm.m10 + nz * nm.m20; + fillNormals[index++] = nx * nm.m01 + ny * nm.m11 + nz * nm.m21; + fillNormals[index ] = nx * nm.m02 + ny * nm.m12 + nz * nm.m22; } - } else { - fillVertices.position(3 * firstFillVertex); - fillVertices.put(in.vertices, 3 * i0, 3 * nvert); - - fillNormals.position(3 * firstFillVertex); - fillNormals.put(in.normals, 3 * i0, 3 * nvert); + } else { + if (nvert <= MIN_ARRAYCOPY_SIZE) { + // Copying elements one by one instead of using arrayCopy is more efficient for + // few vertices... + for (int i = 0; i < nvert; i++) { + int inIdx = i0 + i; + int tessIdx = firstFillVertex + i; + + index = 3 * inIdx; + float x = in.vertices[index++]; + float y = in.vertices[index++]; + float z = in.vertices[index ]; + + index = 3 * inIdx; + float nx = in.normals[index++]; + float ny = in.normals[index++]; + float nz = in.normals[index ]; + + index = 3 * tessIdx; + fillVertices[index++] = x; + fillVertices[index++] = y; + fillVertices[index ] = z; + + index = 3 * tessIdx; + fillNormals[index++] = nx; + fillNormals[index++] = ny; + fillNormals[index ] = nz; + } + } else { + PApplet.arrayCopy(in.vertices, 3 * i0, fillVertices, 3 * firstFillVertex, 3 * nvert); + PApplet.arrayCopy(in.normals, 3 * i0, fillNormals, 3 * firstFillVertex, 3 * nvert); + } + } + + if (nvert <= MIN_ARRAYCOPY_SIZE) { + for (int i = 0; i < nvert; i++) { + int inIdx = i0 + i; + int tessIdx = firstFillVertex + i; + + index = 2 * inIdx; + float u = in.texcoords[index++]; + float v = in.texcoords[index ]; + + fillColors[tessIdx] = in.colors[inIdx]; + + index = 2 * tessIdx; + fillTexcoords[index++] = u; + fillTexcoords[index ] = v; + + fillAmbient[tessIdx] = in.ambient[inIdx]; + fillSpecular[tessIdx] = in.specular[inIdx]; + fillEmissive[tessIdx] = in.emissive[inIdx]; + fillShininess[tessIdx] = in.shininess[inIdx]; + } + } else { + PApplet.arrayCopy(in.colors, i0, fillColors, firstFillVertex, nvert); + PApplet.arrayCopy(in.texcoords, 2 * i0, fillTexcoords, 2 * firstFillVertex, 2 * nvert); + PApplet.arrayCopy(in.ambient, i0, fillAmbient, firstFillVertex, nvert); + PApplet.arrayCopy(in.specular, i0, fillSpecular, firstFillVertex, nvert); + PApplet.arrayCopy(in.emissive, i0, fillEmissive, firstFillVertex, nvert); + PApplet.arrayCopy(in.shininess, i0, fillShininess, firstFillVertex, nvert); } - - fillColors.position(firstFillVertex); - fillColors.put(in.colors, i0, nvert); - - fillTexcoords.position(2 * firstFillVertex); - fillTexcoords.put(in.texcoords, 2 * i0, 2 * nvert); - - fillAmbient.position(firstFillVertex); - fillAmbient.put(in.ambient, i0, nvert); - - fillSpecular.position(firstFillVertex); - fillSpecular.put(in.specular, i0, nvert); - - fillEmissive.position(firstFillVertex); - fillEmissive.put(in.emissive, i0, nvert); - - fillShininess.position(firstFillVertex); - fillShininess.put(in.shininess, i0, nvert); } public void putLineVertex(InGeometry in, int inIdx0, int inIdx1, int tessIdx, int rgba) { @@ -8061,41 +8068,39 @@ public class PGraphicsOpenGL extends PGraphics { if (renderMode == IMMEDIATE && flushMode == FLUSH_WHEN_FULL && !hints[DISABLE_TRANSFORM_CACHE]) { PMatrix3D mm = modelview; - float[] vert = { - x0 * mm.m00 + y0 * mm.m01 + z0 * mm.m02 + mm.m03, - x0 * mm.m10 + y0 * mm.m11 + z0 * mm.m12 + mm.m13, - x0 * mm.m20 + y0 * mm.m21 + z0 * mm.m22 + mm.m23 - }; + index = 3 * tessIdx; + lineVertices[index++] = x0 * mm.m00 + y0 * mm.m01 + z0 * mm.m02 + mm.m03; + lineVertices[index++] = x0 * mm.m10 + y0 * mm.m11 + z0 * mm.m12 + mm.m13; + lineVertices[index ] = x0 * mm.m20 + y0 * mm.m21 + z0 * mm.m22 + mm.m23; - float[] attr = { - x1 * mm.m00 + y1 * mm.m01 + z1 * mm.m02 + mm.m03, - x1 * mm.m10 + y1 * mm.m11 + z1 * mm.m12 + mm.m13, - x1 * mm.m20 + y1 * mm.m21 + z1 * mm.m22 + mm.m23 - }; - - lineVertices.position(3 * tessIdx); - lineVertices.put(vert); - - lineDirWidths.position(4 * tessIdx); - lineDirWidths.put(attr); + index = 4 * tessIdx; + lineDirWidths[index++] = x1 * mm.m00 + y1 * mm.m01 + z1 * mm.m02 + mm.m03; + lineDirWidths[index++] = x1 * mm.m10 + y1 * mm.m11 + z1 * mm.m12 + mm.m13; + lineDirWidths[index ] = x1 * mm.m20 + y1 * mm.m21 + z1 * mm.m22 + mm.m23; } else { - lineVertices.position(3 * tessIdx); - lineVertices.put(in.vertices, 3 * inIdx0, 3); + index = 3 * tessIdx; + lineVertices[index++] = x0; + lineVertices[index++] = y0; + lineVertices[index ] = z0; - lineDirWidths.position(4 * tessIdx); - lineDirWidths.put(in.vertices, 3 * inIdx1, 3); + index = 4 * tessIdx; + lineDirWidths[index++] = x1; + lineDirWidths[index++] = y1; + lineDirWidths[index ] = z1; } - lineColors.position(tessIdx); - lineColors.put(rgba); + lineColors[tessIdx] = rgba; } public void putLineVertex(InGeometry in, int inIdx0, int inIdx1, int tessIdx) { putLineVertex(in, inIdx0, inIdx1, tessIdx, in.scolors[inIdx0]); } - + + public void putPointVertex(InGeometry in, int inIdx, int tessIdx) { - int index = 3 * inIdx; + int index; + + index = 3 * inIdx; float x = in.vertices[index++]; float y = in.vertices[index++]; float z = in.vertices[index ]; @@ -8103,22 +8108,18 @@ public class PGraphicsOpenGL extends PGraphics { if (renderMode == IMMEDIATE && flushMode == FLUSH_WHEN_FULL && !hints[DISABLE_TRANSFORM_CACHE]) { PMatrix3D mm = modelview; - float[] vert = { - x * mm.m00 + y * mm.m01 + z * mm.m02 + mm.m03, - x * mm.m10 + y * mm.m11 + z * mm.m12 + mm.m13, - x * mm.m20 + y * mm.m21 + z * mm.m22 + mm.m23 - }; - - pointVertices.position(3 * tessIdx); - pointVertices.put(vert, 0, 3); + index = 3 * tessIdx; + pointVertices[index++] = x * mm.m00 + y * mm.m01 + z * mm.m02 + mm.m03; + pointVertices[index++] = x * mm.m10 + y * mm.m11 + z * mm.m12 + mm.m13; + pointVertices[index ] = x * mm.m20 + y * mm.m21 + z * mm.m22 + mm.m23; } else { index = 3 * tessIdx; - pointVertices.position(3 * tessIdx); - pointVertices.put(in.vertices, 3 * inIdx, 3); + pointVertices[index++] = x; + pointVertices[index++] = y; + pointVertices[index ] = z; } - pointColors.position(tessIdx); - pointColors.put(in.scolors[inIdx]); + pointColors[tessIdx] = in.scolors[inIdx]; } public int expandVertSize(int currSize, int newMinSize) { @@ -8145,18 +8146,18 @@ public class PGraphicsOpenGL extends PGraphics { float cy0 = 0; for (int i = 0; i < fillVertexCount; i++) { index = 3 * i; - cx0 += fillVertices.get(index++); - cy0 += fillVertices.get(index ); - } + cx0 += fillVertices[index++]; + cy0 += fillVertices[index ]; + } for (int i = 0; i < lineVertexCount; i++) { index = 3 * i; - cx0 += lineVertices.get(index++); - cy0 += lineVertices.get(index ); + cx0 += lineVertices[index++]; + cy0 += lineVertices[index ]; } for (int i = 0; i < pointVertexCount; i++) { index = 3 * i; - cx0 += pointVertices.get(index++); - cy0 += pointVertices.get(index ); + cx0 += pointVertices[index++]; + cy0 += pointVertices[index ]; } int nt = fillVertexCount + lineVertexCount + pointVertexCount; if (0 < nt) { @@ -8164,43 +8165,34 @@ public class PGraphicsOpenGL extends PGraphics { cy0 /= nt; } - float[] tvect = { cx - cx0, cy - cy0 }; + float tx = cx - cx0; + float ty = cy - cy0; if (0 < fillVertexCount) { for (int i = 0; i < fillVertexCount; i++) { index = 3 * i; - for (int j = 0; j < 2; j++) { - float v = fillVertices.get(index + j); - - fillVertices.position(index + j); - //fillVertices.put(v + tvect[j]); - fillVertices.put(v + 100); - } + fillVertices[index++] += tx; + fillVertices[index ] += ty; } } if (0 < lineVertexCount) { for (int i = 0; i < lineVertexCount; i++) { index = 3 * i; - for (int j = 0; j < 2; j++) { - lineVertices.position(index + j); - lineVertices.put(lineVertices.get(index + j) + tvect[j]); - } + lineVertices[index++] += tx; + lineVertices[index ] += ty; + index = 4 * i; - for (int j = 0; j < 2; j++) { - lineDirWidths.position(index + j); - lineDirWidths.put(lineDirWidths.get(index + j) + tvect[j]); - } + lineDirWidths[index++] += tx; + lineDirWidths[index ] += ty; } } if (0 < pointVertexCount) { for (int i = 0; i < pointVertexCount; i++) { index = 3 * i; - for (int j = 0; j < 2; j++) { - pointVertices.position(index + j); - pointVertices.put(pointVertices.get(index + j) + tvect[j]); - } + pointVertices[index++] += tx; + pointVertices[index ] += ty; } } } @@ -8214,21 +8206,21 @@ public class PGraphicsOpenGL extends PGraphics { float cz0 = 0; for (int i = 0; i < fillVertexCount; i++) { index = 3 * i; - cx0 += fillVertices.get(index++); - cy0 += fillVertices.get(index++); - cz0 += fillVertices.get(index ); + cx0 += fillVertices[index++]; + cy0 += fillVertices[index++]; + cz0 += fillVertices[index ]; } for (int i = 0; i < lineVertexCount; i++) { - index = 3 * i; - cx0 += lineVertices.get(index++); - cy0 += lineVertices.get(index++); - cz0 += lineVertices.get(index ); + index = 3 * i; + cx0 += lineVertices[index++]; + cy0 += lineVertices[index++]; + cz0 += lineVertices[index ]; } for (int i = 0; i < pointVertexCount; i++) { - index = 3 * i; - cx0 += pointVertices.get(index++); - cy0 += pointVertices.get(index++); - cz0 += pointVertices.get(index ); + index = 3 * i; + cx0 += pointVertices[index++]; + cy0 += pointVertices[index++]; + cz0 += pointVertices[index ]; } int nt = fillVertexCount + lineVertexCount + pointVertexCount; if (0 < nt) { @@ -8237,174 +8229,192 @@ public class PGraphicsOpenGL extends PGraphics { cz0 /= nt; } - float[] tvec = {cx - cx0, cy - cy0, cz - cz0}; + float tx = cx - cx0; + float ty = cy - cy0; + float tz = cz - cz0; if (0 < fillVertexCount) { for (int i = 0; i < fillVertexCount; i++) { index = 3 * i; - for (int j = 0; j < 3; j++) { - fillVertices.position(index + j); - fillVertices.put(fillVertices.get(index + j) + tvec[j]); - } + fillVertices[index++] += tx; + fillVertices[index++] += ty; + fillVertices[index ] += tz; } } if (0 < lineVertexCount) { for (int i = 0; i < lineVertexCount; i++) { index = 3 * i; - for (int j = 0; j < 3; j++) { - lineVertices.position(index + j); - lineVertices.put(lineVertices.get(index + j) + tvec[j]); - } + lineVertices[index++] += tx; + lineVertices[index++] += ty; + lineVertices[index ] += tz; + index = 4 * i; - for (int j = 0; j < 3; j++) { - lineDirWidths.position(index + j); - lineDirWidths.put(lineDirWidths.get(index + j) + tvec[j]); - } + lineDirWidths[index++] += tx; + lineDirWidths[index++] += ty; + lineDirWidths[index ] += tz; } } if (0 < pointVertexCount) { for (int i = 0; i < pointVertexCount; i++) { index = 3 * i; - for (int j = 0; j < 3; j++) { - pointVertices.position(index + j); - pointVertices.put(pointVertices.get(index + j) + tvec[j]); - } + pointVertices[index++] += tx; + pointVertices[index++] += ty; + pointVertices[index ] += tz; } } } - public int sumVertices(PVector v) { + public int getCenter(PVector v) { int index; for (int i = 0; i < fillVertexCount; i++) { - index = 3 * i; - v.x += fillVertices.get(index++); - v.y += fillVertices.get(index++); - v.z += fillVertices.get(index ); + index = 3 * i; + v.x += fillVertices[index++]; + v.y += fillVertices[index++]; + v.z += fillVertices[index ]; } for (int i = 0; i < lineVertexCount; i++) { index = 3 * i; - v.x += lineVertices.get(index++); - v.y += lineVertices.get(index++); - v.z += lineVertices.get(index ); + v.x += lineVertices[index++]; + v.y += lineVertices[index++]; + v.z += lineVertices[index ]; } for (int i = 0; i < pointVertexCount; i++) { index = 3 * i; - v.x += pointVertices.get(index++); - v.y += pointVertices.get(index++); - v.z += pointVertices.get(index ); + v.x += pointVertices[index++]; + v.y += pointVertices[index++]; + v.z += pointVertices[index ]; } - int ntot = fillVertexCount + lineVertexCount + pointVertexCount; - return ntot; - } - + return fillVertexCount + lineVertexCount + pointVertexCount; + } public void applyMatrix(PMatrix2D tr) { - float[] vec0 = new float[2]; - float[] vec1 = new float[2]; - if (0 < fillVertexCount) { - for (int i = 0; i < fillVertexCount; i++) { - fillVertices.position(3 * i); - fillVertices.get(vec0); - vec1[0] = vec0[0] * tr.m00 + vec0[1] * tr.m01 + tr.m02; - vec1[1] = vec0[0] * tr.m10 + vec0[1] * tr.m11 + tr.m12; - fillVertices.position(3 * i); - fillVertices.put(vec1); + int index; - fillNormals.position(3 * i); - fillNormals.get(vec0); - vec1[0] = vec0[0] * tr.m00 + vec0[1] * tr.m01 + tr.m02; - vec1[1] = vec0[0] * tr.m10 + vec0[1] * tr.m11 + tr.m12; - fillNormals.position(3 * i); - fillNormals.put(vec1); + for (int i = 0; i < fillVertexCount; i++) { + index = 3 * i; + float x = fillVertices[index++]; + float y = fillVertices[index ]; + + index = 3 * i; + float nx = fillNormals[index++]; + float ny = fillNormals[index ]; + + index = 3 * i; + fillVertices[index++] = x * tr.m00 + y * tr.m01 + tr.m02; + fillVertices[index ] = x * tr.m10 + y * tr.m11 + tr.m12; + + index = 3 * i; + fillNormals[index++] = nx * tr.m00 + ny * tr.m01; + fillNormals[index ] = nx * tr.m10 + ny * tr.m11; } } if (0 < lineVertexCount) { + int index; + for (int i = 0; i < lineVertexCount; i++) { - lineVertices.position(3 * i); - lineVertices.get(vec0); - vec1[0] = vec0[0] * tr.m00 + vec0[1] * tr.m01 + tr.m02; - vec1[1] = vec0[0] * tr.m10 + vec0[1] * tr.m11 + tr.m12; - lineVertices.position(3 * i); - lineVertices.put(vec1); + index = 3 * i; + float x = lineVertices[index++]; + float y = lineVertices[index ]; + + index = 4 * i; + float xa = lineDirWidths[index++]; + float ya = lineDirWidths[index ]; - lineDirWidths.position(4 * i); - lineDirWidths.get(vec0); - vec1[0] = vec0[0] * tr.m00 + vec0[1] * tr.m01 + tr.m02; - vec1[1] = vec0[0] * tr.m10 + vec0[1] * tr.m11 + tr.m12; - lineDirWidths.position(4 * i); - lineDirWidths.put(vec1, 0, 2); + index = 3 * i; + lineVertices[index++] = x * tr.m00 + y * tr.m01 + tr.m02; + lineVertices[index ] = x * tr.m10 + y * tr.m11 + tr.m12; + + index = 4 * i; + lineDirWidths[index++] = xa * tr.m00 + ya * tr.m01 + tr.m02; + lineDirWidths[index ] = xa * tr.m10 + ya * tr.m11 + tr.m12; } } if (0 < pointVertexCount) { + int index; + for (int i = 0; i < pointVertexCount; i++) { - pointVertices.position(3 * i); - pointVertices.get(vec0); - vec1[0] = vec0[0] * tr.m00 + vec0[1] * tr.m01 + tr.m02; - vec1[1] = vec0[0] * tr.m10 + vec0[1] * tr.m11 + tr.m12; - pointVertices.position(3 * i); - pointVertices.put(vec1, 0, 2); + index = 3 * i; + float x = pointVertices[index++]; + float y = pointVertices[index ]; + + index = 3 * i; + pointVertices[index++] = x * tr.m00 + y * tr.m01 + tr.m02; + pointVertices[index ] = x * tr.m10 + y * tr.m11 + tr.m12; } } } public void applyMatrix(PMatrix3D tr) { - float[] vec0 = new float[3]; - float[] vec1 = new float[3]; - if (0 < fillVertexCount) { - for (int i = 0; i < fillVertexCount; i++) { - fillVertices.position(3 * i); - fillVertices.get(vec0); - vec1[0] = vec0[0] * tr.m00 + vec0[1] * tr.m01 + vec0[2] * tr.m02 + tr.m03; - vec1[1] = vec0[0] * tr.m10 + vec0[1] * tr.m11 + vec0[2] * tr.m12 + tr.m13; - vec1[2] = vec0[0] * tr.m20 + vec0[1] * tr.m21 + vec0[2] * tr.m22 + tr.m23; - fillVertices.position(3 * i); - fillVertices.put(vec1); + int index; - fillNormals.position(3 * i); - fillNormals.get(vec0); - vec1[0] = vec0[0] * tr.m00 + vec0[1] * tr.m01 + vec0[2] * tr.m02; - vec1[1] = vec0[0] * tr.m10 + vec0[1] * tr.m11 + vec0[2] * tr.m12; - vec1[2] = vec0[0] * tr.m20 + vec0[1] * tr.m21 + vec0[2] * tr.m22; - fillNormals.position(3 * i); - fillNormals.put(vec1); + for (int i = 0; i < fillVertexCount; i++) { + index = 3 * i; + float x = fillVertices[index++]; + float y = fillVertices[index++]; + float z = fillVertices[index ]; + + index = 3 * i; + float nx = fillNormals[index++]; + float ny = fillNormals[index++]; + float nz = fillNormals[index ]; + + index = 3 * i; + fillVertices[index++] = x * tr.m00 + y * tr.m01 + z * tr.m02 + tr.m03; + fillVertices[index++] = x * tr.m10 + y * tr.m11 + z * tr.m12 + tr.m13; + fillVertices[index ] = x * tr.m20 + y * tr.m21 + z * tr.m22 + tr.m23; + + index = 3 * i; + fillNormals[index++] = nx * tr.m00 + ny * tr.m01 + nz * tr.m02; + fillNormals[index++] = nx * tr.m10 + ny * tr.m11 + nz * tr.m12; + fillNormals[index ] = nx * tr.m20 + ny * tr.m21 + nz * tr.m22; } } if (0 < lineVertexCount) { + int index; + for (int i = 0; i < lineVertexCount; i++) { - lineVertices.position(3 * i); - lineVertices.get(vec0); - vec1[0] = vec0[0] * tr.m00 + vec0[1] * tr.m01 + vec0[2] * tr.m02; - vec1[1] = vec0[0] * tr.m10 + vec0[1] * tr.m11 + vec0[2] * tr.m12; - vec1[2] = vec0[0] * tr.m20 + vec0[1] * tr.m21 + vec0[2] * tr.m22; - lineVertices.position(3 * i); - lineVertices.put(vec1); - - lineDirWidths.position(4 * i); - lineDirWidths.get(vec0); - vec1[0] = vec0[0] * tr.m00 + vec0[1] * tr.m01 + vec0[2] * tr.m02; - vec1[1] = vec0[0] * tr.m10 + vec0[1] * tr.m11 + vec0[2] * tr.m12; - vec1[2] = vec0[0] * tr.m20 + vec0[1] * tr.m21 + vec0[2] * tr.m22; - lineDirWidths.position(4 * i); - lineDirWidths.put(vec1, 0, 3); + index = 3 * i; + float x = lineVertices[index++]; + float y = lineVertices[index++]; + float z = lineVertices[index ]; + + index = 4 * i; + float xa = lineDirWidths[index++]; + float ya = lineDirWidths[index++]; + float za = lineDirWidths[index ]; + + index = 3 * i; + lineVertices[index++] = x * tr.m00 + y * tr.m01 + z * tr.m02 + tr.m03; + lineVertices[index++] = x * tr.m10 + y * tr.m11 + z * tr.m12 + tr.m13; + lineVertices[index ] = x * tr.m20 + y * tr.m21 + z * tr.m22 + tr.m23; + + index = 4 * i; + lineDirWidths[index++] = xa * tr.m00 + ya * tr.m01 + za * tr.m02 + tr.m03; + lineDirWidths[index++] = xa * tr.m10 + ya * tr.m11 + za * tr.m12 + tr.m13; + lineDirWidths[index ] = xa * tr.m20 + ya * tr.m21 + za * tr.m22 + tr.m23; } } if (0 < pointVertexCount) { + int index; + for (int i = 0; i < pointVertexCount; i++) { - pointVertices.position(3 * i); - pointVertices.get(vec0); - vec1[0] = vec0[0] * tr.m00 + vec0[1] * tr.m01 + vec0[2] * tr.m02; - vec1[1] = vec0[0] * tr.m10 + vec0[1] * tr.m11 + vec0[2] * tr.m12; - vec1[2] = vec0[0] * tr.m20 + vec0[1] * tr.m21 + vec0[2] * tr.m22; - pointVertices.position(3 * i); - pointVertices.put(vec1); + index = 3 * i; + float x = pointVertices[index++]; + float y = pointVertices[index++]; + float z = pointVertices[index ]; + + index = 3 * i; + pointVertices[index++] = x * tr.m00 + y * tr.m01 + z * tr.m02 + tr.m03; + pointVertices[index++] = x * tr.m10 + y * tr.m11 + z * tr.m12 + tr.m13; + pointVertices[index ] = x * tr.m20 + y * tr.m21 + z * tr.m22 + tr.m23; } } } @@ -8523,14 +8533,14 @@ public class PGraphicsOpenGL extends PGraphics { // the circle perimeter. The point shader will read these attributes and // displace the vertices in screen coordinates so the circles are always // camera facing (bilboards) - tess.pointSizes.put(2 * attribIdx + 0, 0); - tess.pointSizes.put(2 * attribIdx + 1, 0); + tess.pointSizes[2 * attribIdx + 0] = 0; + tess.pointSizes[2 * attribIdx + 1] = 0; attribIdx++; float val = 0; float inc = (float) SINCOS_LENGTH / perim; for (int k = 0; k < perim; k++) { - tess.pointSizes.put(2 * attribIdx + 0, 0.5f * cosLUT[(int) val] * strokeWeight); - tess.pointSizes.put(2 * attribIdx + 1, 0.5f * sinLUT[(int) val] * strokeWeight); + tess.pointSizes[2 * attribIdx + 0] = 0.5f * cosLUT[(int) val] * strokeWeight; + tess.pointSizes[2 * attribIdx + 1] = 0.5f * sinLUT[(int) val] * strokeWeight; val = (val + inc) % SINCOS_LENGTH; attribIdx++; } @@ -8538,14 +8548,15 @@ public class PGraphicsOpenGL extends PGraphics { // Adding vert0 to take into account the triangles of all // the preceding points. for (int k = 1; k < nvert - 1; k++) { - tess.pointIndices.put(indIdx++, PGL.makeIndex(firstVert + 0)); - tess.pointIndices.put(indIdx++, PGL.makeIndex(firstVert + k)); - tess.pointIndices.put(indIdx++, PGL.makeIndex(firstVert + k + 1)); + tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + 0); + tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + k); + tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + k + 1); } // Final triangle between the last and first point: - tess.pointIndices.put(indIdx++, PGL.makeIndex(firstVert + 0)); - tess.pointIndices.put(indIdx++, PGL.makeIndex(firstVert + 1)); - tess.pointIndices.put(indIdx++, PGL.makeIndex(firstVert + nvert - 1)); + tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + 0); + tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + 1); + tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + nvert - 1); + firstVert = vertIdx; } } @@ -8588,26 +8599,27 @@ public class PGraphicsOpenGL extends PGraphics { // the quad corners. The point shader will read these attributes and // displace the vertices in screen coordinates so the quads are always // camera facing (bilboards) - tess.pointSizes.put(2 * attribIdx + 0, 0); - tess.pointSizes.put(2 * attribIdx + 1, 0); + tess.pointSizes[2 * attribIdx + 0] = 0; + tess.pointSizes[2 * attribIdx + 1] = 0; attribIdx++; for (int k = 0; k < 4; k++) { - tess.pointSizes.put(2 * attribIdx + 0, 0.5f * QUAD_SIGNS[k][0] * strokeWeight); - tess.pointSizes.put(2 * attribIdx + 1, 0.5f * QUAD_SIGNS[k][1] * strokeWeight); + tess.pointSizes[2 * attribIdx + 0] = 0.5f * QUAD_SIGNS[k][0] * strokeWeight; + tess.pointSizes[2 * attribIdx + 1] = 0.5f * QUAD_SIGNS[k][1] * strokeWeight; attribIdx++; } // Adding firstVert to take into account the triangles of all // the preceding points. for (int k = 1; k < nvert - 1; k++) { - tess.pointIndices.put(indIdx++, PGL.makeIndex(firstVert + 0)); - tess.pointIndices.put(indIdx++, PGL.makeIndex(firstVert + k)); - tess.pointIndices.put(indIdx++, PGL.makeIndex(firstVert + k + 1)); + tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + 0); + tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + k); + tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + k + 1); } // Final triangle between the last and first point: - tess.pointIndices.put(indIdx++, PGL.makeIndex(firstVert + 0)); - tess.pointIndices.put(indIdx++, PGL.makeIndex(firstVert + 1)); - tess.pointIndices.put(indIdx++, PGL.makeIndex(firstVert + nvert - 1)); + tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + 0); + tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + 1); + tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + nvert - 1); + firstVert = vertIdx; } } @@ -8656,7 +8668,7 @@ public class PGraphicsOpenGL extends PGraphics { int idx0 = tess.firstFillIndex; int offset = tess.firstFillVertex; for (int i = in.firstVertex; i <= in.lastVertex; i++) { - tess.fillIndices.put(idx0 + i, PGL.makeIndex(offset + i)); + tess.fillIndices[idx0 + i] = PGL.makeIndex(offset + i); } } @@ -8679,9 +8691,9 @@ public class PGraphicsOpenGL extends PGraphics { int idx = tess.firstFillIndex; int offset = tess.firstFillVertex; for (int i = in.firstVertex + 1; i < in.lastVertex; i++) { - tess.fillIndices.put(idx++, PGL.makeIndex(offset + in.firstVertex)); - tess.fillIndices.put(idx++, PGL.makeIndex(offset + i)); - tess.fillIndices.put(idx++, PGL.makeIndex(offset + i + 1)); + tess.fillIndices[idx++] = PGL.makeIndex(offset + in.firstVertex); + tess.fillIndices[idx++] = PGL.makeIndex(offset + i); + tess.fillIndices[idx++] = PGL.makeIndex(offset + i + 1); } } @@ -8707,13 +8719,13 @@ public class PGraphicsOpenGL extends PGraphics { int idx = tess.firstFillIndex; int offset = tess.firstFillVertex; for (int i = in.firstVertex + 1; i < in.lastVertex; i++) { - tess.fillIndices.put(idx++, PGL.makeIndex(offset + i)); + tess.fillIndices[idx++] = PGL.makeIndex(offset + i); if (i % 2 == 0) { - tess.fillIndices.put(idx++, PGL.makeIndex(offset + i - 1)); - tess.fillIndices.put(idx++, PGL.makeIndex(offset + i + 1)); + tess.fillIndices[idx++] = PGL.makeIndex(offset + i - 1); + tess.fillIndices[idx++] = PGL.makeIndex(offset + i + 1); } else { - tess.fillIndices.put(idx++, PGL.makeIndex(offset + i + 1)); - tess.fillIndices.put(idx++, PGL.makeIndex(offset + i - 1)); + tess.fillIndices[idx++] = PGL.makeIndex(offset + i + 1); + tess.fillIndices[idx++] = PGL.makeIndex(offset + i - 1); } } } @@ -8743,13 +8755,13 @@ public class PGraphicsOpenGL extends PGraphics { int i2 = offset + 4 * qd + 2; int i3 = offset + 4 * qd + 3; - tess.fillIndices.put(idx++, PGL.makeIndex(i0)); - tess.fillIndices.put(idx++, PGL.makeIndex(i1)); - tess.fillIndices.put(idx++, PGL.makeIndex(i3)); + tess.fillIndices[idx++] = PGL.makeIndex(i0); + tess.fillIndices[idx++] = PGL.makeIndex(i1); + tess.fillIndices[idx++] = PGL.makeIndex(i3); - tess.fillIndices.put(idx++, PGL.makeIndex(i1)); - tess.fillIndices.put(idx++, PGL.makeIndex(i2)); - tess.fillIndices.put(idx++, PGL.makeIndex(i3)); + tess.fillIndices[idx++] = PGL.makeIndex(i1); + tess.fillIndices[idx++] = PGL.makeIndex(i2); + tess.fillIndices[idx++] = PGL.makeIndex(i3); } } @@ -8779,13 +8791,13 @@ public class PGraphicsOpenGL extends PGraphics { int i2 = offset + 2 * qd + 1; int i3 = offset + 2 * qd; - tess.fillIndices.put(idx++, PGL.makeIndex(i0)); - tess.fillIndices.put(idx++, PGL.makeIndex(i1)); - tess.fillIndices.put(idx++, PGL.makeIndex(i3)); + tess.fillIndices[idx++] = PGL.makeIndex(i0); + tess.fillIndices[idx++] = PGL.makeIndex(i1); + tess.fillIndices[idx++] = PGL.makeIndex(i3); - tess.fillIndices.put(idx++, PGL.makeIndex(i1)); - tess.fillIndices.put(idx++, PGL.makeIndex(i2)); - tess.fillIndices.put(idx++, PGL.makeIndex(i3)); + tess.fillIndices[idx++] = PGL.makeIndex(i1); + tess.fillIndices[idx++] = PGL.makeIndex(i2); + tess.fillIndices[idx++] = PGL.makeIndex(i3); } } @@ -8870,27 +8882,27 @@ public class PGraphicsOpenGL extends PGraphics { protected void addLine(int i0, int i1, int vcount, int icount) { tess.putLineVertex(in, i0, i1, vcount); - tess.lineDirWidths.put(4 * vcount + 3, +strokeWeight); - tess.lineIndices.put(icount++, PGL.makeIndex(vcount)); + tess.lineDirWidths[4 * vcount + 3] = +strokeWeight; + tess.lineIndices[icount++] = PGL.makeIndex(vcount); vcount++; tess.putLineVertex(in, i0, i1, vcount); - tess.lineDirWidths.put(4 * vcount + 3, -strokeWeight); - tess.lineIndices.put(icount++, PGL.makeIndex(vcount)); + tess.lineDirWidths[4 * vcount + 3] = -strokeWeight; + tess.lineIndices[icount++] = PGL.makeIndex(vcount); vcount++; tess.putLineVertex(in, i1, i0, vcount); - tess.lineDirWidths.put(4 * vcount + 3, -strokeWeight); - tess.lineIndices.put(icount++, PGL.makeIndex(vcount)); + tess.lineDirWidths[4 * vcount + 3] = -strokeWeight; + tess.lineIndices[icount++] = PGL.makeIndex(vcount); // Starting a new triangle re-using prev vertices. - tess.lineIndices.put(icount++, PGL.makeIndex(vcount)); - tess.lineIndices.put(icount++, PGL.makeIndex(vcount - 1)); + tess.lineIndices[icount++] = PGL.makeIndex(vcount); + tess.lineIndices[icount++] = PGL.makeIndex(vcount - 1); vcount++; tess.putLineVertex(in, i1, i0, vcount); - tess.lineDirWidths.put(4 * vcount + 3, +strokeWeight); - tess.lineIndices.put(icount++, PGL.makeIndex(vcount)); + tess.lineDirWidths[4 * vcount + 3] = +strokeWeight; + tess.lineIndices[icount++] = PGL.makeIndex(vcount); } public void tessellateEdges() { diff --git a/java/libraries/opengl/src/processing/opengl/PShader.java b/java/libraries/opengl/src/processing/opengl/PShader.java index 3622eb454..325e35a5f 100644 --- a/java/libraries/opengl/src/processing/opengl/PShader.java +++ b/java/libraries/opengl/src/processing/opengl/PShader.java @@ -26,7 +26,6 @@ package processing.opengl; import processing.core.*; import java.io.IOException; import java.net.URL; -import java.nio.FloatBuffer; /** * This class encapsulates a GLSL shader program, including a vertex @@ -37,6 +36,7 @@ public class PShader { protected PApplet parent; protected PGraphicsOpenGL pg; protected PGL pgl; + protected PGL.Context context; // The context that created this shader. protected URL vertexURL; protected URL fragmentURL; @@ -48,14 +48,6 @@ public class PShader { protected int vertexShader; protected int fragmentShader; - protected FloatBuffer vec1f; - protected FloatBuffer vec2f; - protected FloatBuffer vec3f; - protected FloatBuffer vec4f; - protected FloatBuffer mat2x2; - protected FloatBuffer mat3x3; - protected FloatBuffer mat4x4; - public PShader() { parent = null; pg = null; @@ -226,91 +218,49 @@ public class PShader { public void set1FloatVecUniform(int loc, float[] vec) { if (-1 < loc) { - if (vec1f == null || vec1f.capacity() != vec.length) { - vec1f = pgl.createFloatBuffer(vec.length); - } - vec1f.rewind(); - vec1f.put(vec); - vec1f.flip(); - pgl.glUniform1fv(loc, vec.length, vec1f); + pgl.glUniform1fv(loc, vec.length, vec, 0); } } public void set2FloatVecUniform(int loc, float[] vec) { if (-1 < loc) { - if (vec2f == null || vec2f.capacity() != vec.length) { - vec2f = pgl.createFloatBuffer(vec.length); - } - vec2f.rewind(); - vec2f.put(vec); - vec2f.flip(); - pgl.glUniform2fv(loc, vec.length / 2, vec2f); + pgl.glUniform2fv(loc, vec.length / 2, vec, 0); } } public void set3FloatVecUniform(int loc, float[] vec) { if (-1 < loc) { - if (vec3f == null || vec3f.capacity() != vec.length) { - vec3f = pgl.createFloatBuffer(vec.length); - } - vec3f.rewind(); - vec3f.put(vec); - vec3f.flip(); - pgl.glUniform3fv(loc, vec.length / 3, vec3f); + pgl.glUniform3fv(loc, vec.length / 3, vec, 0); } } public void set4FloatVecUniform(int loc, float[] vec) { if (-1 < loc) { - if (vec4f == null || vec4f.capacity() != vec.length) { - vec4f = pgl.createFloatBuffer(vec.length); - } - vec4f.rewind(); - vec4f.put(vec); - vec4f.flip(); - pgl.glUniform4fv(loc, vec.length / 4, vec4f); + pgl.glUniform4fv(loc, vec.length / 4, vec, 0); } } public void set2x2MatUniform(int loc, float[] mat) { if (-1 < loc) { - if (mat2x2 == null) { - mat2x2 = pgl.createFloatBuffer(2 * 2); - } - mat2x2.rewind(); - mat2x2.put(mat); - mat2x2.flip(); - pgl.glUniformMatrix2fv(loc, 1, false, mat2x2); + pgl.glUniformMatrix2fv(loc, 1, false, mat, 0); } } public void set3x3MatUniform(int loc, float[] mat) { if (-1 < loc) { - if (mat3x3 == null) { - mat3x3 = pgl.createFloatBuffer(3 * 3); - } - mat3x3.rewind(); - mat3x3.put(mat); - mat3x3.flip(); - pgl.glUniformMatrix3fv(loc, 1, false, mat3x3); + pgl.glUniformMatrix3fv(loc, 1, false, mat, 0); } } public void set4x4MatUniform(int loc, float[] mat) { if (-1 < loc) { - if (mat4x4 == null) { - mat4x4 = pgl.createFloatBuffer(4 * 4); - } - mat4x4.rewind(); - mat4x4.put(mat); - mat4x4.flip(); - pgl.glUniformMatrix4fv(loc, 1, false, mat4x4); + pgl.glUniformMatrix4fv(loc, 1, false, mat, 0); } } @@ -343,7 +293,9 @@ public class PShader { } protected void init() { - if (programObject == 0) { + if (programObject == 0 || contextIsOutdated()) { + + context = pgl.getContext(); programObject = pg.createGLSLProgramObject(); if (vertexFilename != null) { @@ -371,6 +323,17 @@ public class PShader { } + protected boolean contextIsOutdated() { + boolean outdated = !pgl.contextIsCurrent(context); + if (outdated) { + programObject = 0; + vertexShader = 0; + fragmentShader = 0; + } + return outdated; + } + + /** * Loads and compiles the vertex shader contained in file. * @@ -473,4 +436,3 @@ public class PShader { } } } - diff --git a/java/libraries/opengl/src/processing/opengl/PShape3D.java b/java/libraries/opengl/src/processing/opengl/PShape3D.java index 5ddb0d087..582e3b48a 100644 --- a/java/libraries/opengl/src/processing/opengl/PShape3D.java +++ b/java/libraries/opengl/src/processing/opengl/PShape3D.java @@ -75,6 +75,7 @@ import java.util.Hashtable; public class PShape3D extends PShape { protected PGraphicsOpenGL pg; protected PGL pgl; + protected PGL.Context context; // The context that created this shape. protected PShape3D root; protected int glMode; @@ -864,15 +865,13 @@ public class PShape3D extends PShape { updateTesselation(); - int[] temp = new int[tess.fillVertexCount]; - Arrays.fill(temp, 0, tess.fillVertexCount, fillColor); - tess.fillColors.rewind(); - tess.fillColors.put(temp); - + Arrays.fill(tess.fillColors, 0, tess.fillVertexCount, fillColor); + modifiedFillColors = true; modified(); } - + + ////////////////////////////////////////////////////////////// // STROKE COLOR @@ -982,19 +981,13 @@ public class PShape3D extends PShape { updateTesselation(); if (0 < tess.lineVertexCount) { - int[] temp = new int[tess.lineVertexCount]; - Arrays.fill(temp, 0, tess.lineVertexCount, strokeColor); - tess.lineColors.rewind(); - tess.lineColors.put(temp); + Arrays.fill(tess.lineColors, 0, tess.lineVertexCount, strokeColor); modifiedLineColors = true; modified(); } if (0 < tess.pointVertexCount) { - int[] temp = new int[tess.pointVertexCount]; - Arrays.fill(temp, 0, tess.pointVertexCount, strokeColor); - tess.pointColors.rewind(); - tess.pointColors.put(temp); + Arrays.fill(tess.pointColors, 0, tess.pointVertexCount, strokeColor); modifiedPointColors = true; modified(); } @@ -1113,11 +1106,8 @@ public class PShape3D extends PShape { updateTesselation(); - int[] temp = new int[tess.fillVertexCount]; - Arrays.fill(temp, 0, tess.fillVertexCount, tintColor); - tess.fillColors.rewind(); - tess.fillColors.put(temp); - + Arrays.fill(tess.fillColors, 0, tess.pointVertexCount, tintColor); + modifiedFillColors = true; modified(); } @@ -1175,11 +1165,8 @@ public class PShape3D extends PShape { } updateTesselation(); - - int[] temp = new int[tess.fillVertexCount]; - Arrays.fill(temp, 0, tess.fillVertexCount, ambientColor); - tess.fillAmbient.rewind(); - tess.fillAmbient.put(temp); + + Arrays.fill(tess.fillAmbient, 0, tess.fillVertexCount, ambientColor); modifiedFillAmbient = true; modified(); @@ -1240,10 +1227,7 @@ public class PShape3D extends PShape { updateTesselation(); - int[] temp = new int[tess.fillVertexCount]; - Arrays.fill(temp, 0, tess.fillVertexCount, specularColor); - tess.fillSpecular.rewind(); - tess.fillSpecular.put(temp); + Arrays.fill(tess.fillSpecular, 0, tess.fillVertexCount, specularColor); modifiedFillSpecular = true; modified(); @@ -1304,10 +1288,7 @@ public class PShape3D extends PShape { updateTesselation(); - int[] temp = new int[tess.fillVertexCount]; - Arrays.fill(temp, 0, tess.fillVertexCount, emissiveColor); - tess.fillEmissive.rewind(); - tess.fillEmissive.put(temp); + Arrays.fill(tess.fillEmissive, 0, tess.fillVertexCount, emissiveColor); modifiedFillEmissive = true; modified(); @@ -1338,10 +1319,7 @@ public class PShape3D extends PShape { updateTesselation(); - float[] temp = new float[tess.fillVertexCount]; - Arrays.fill(temp, 0, tess.fillVertexCount, shininess); - tess.fillShininess.rewind(); - tess.fillShininess.put(temp); + Arrays.fill(tess.fillShininess, 0, tess.fillVertexCount, shininess); modifiedFillShininess = true; modified(); @@ -1358,7 +1336,7 @@ public class PShape3D extends PShape { if (family == GROUP) { count = updateCenter(vec, count); } else { - count += tess.sumVertices(vec); + count += tess.getCenter(vec); } return count; } @@ -1380,7 +1358,7 @@ public class PShape3D extends PShape { super.translate(tx, ty); } else { PVector vec = new PVector(); - int count = tess.sumVertices(vec); + int count = tess.getCenter(vec); vec.x /= count; vec.y /= count; @@ -1409,7 +1387,7 @@ public class PShape3D extends PShape { super.translate(tx, ty, tz); } else { PVector vec = new PVector(); - int count = tess.sumVertices(vec); + int count = tess.getCenter(vec); vec.x /= count; vec.y /= count; vec.z /= count; @@ -2071,92 +2049,83 @@ public class PShape3D extends PShape { public float[] fillVertices(float[] vertices) { updateTesselation(); - if (vertices == null || vertices.length != tess.fillVertices.capacity()) { - vertices = new float[tess.fillVertices.capacity()]; + if (vertices == null || vertices.length != tess.fillVertices.length) { + vertices = new float[tess.fillVertices.length]; } - tess.fillVertices.rewind(); - tess.fillVertices.get(vertices); + PApplet.arrayCopy(tess.fillVertices, vertices); return vertices; } public int[] fillColors(int[] colors) { updateTesselation(); - if (colors == null || colors.length != tess.fillColors.capacity()) { - colors = new int[tess.fillVertices.capacity()]; + if (colors == null || colors.length != tess.fillColors.length) { + colors = new int[tess.fillColors.length]; } - tess.fillColors.rewind(); - tess.fillColors.get(colors); - return colors; + PApplet.arrayCopy(tess.fillColors, colors); + return colors; } public float[] fillNormals(float[] normals) { updateTesselation(); - if (normals == null || normals.length != tess.fillNormals.capacity()) { - normals = new float[tess.fillNormals.capacity()]; + if (normals == null || normals.length != tess.fillNormals.length) { + normals = new float[tess.fillNormals.length]; } - tess.fillNormals.rewind(); - tess.fillNormals.get(normals); - return normals; + PApplet.arrayCopy(tess.fillNormals, normals); + return normals; } public float[] fillTexCoords(float[] texcoords) { updateTesselation(); - if (texcoords == null || texcoords.length != tess.fillTexcoords.capacity()) { - texcoords = new float[tess.fillTexcoords.capacity()]; + if (texcoords == null || texcoords.length != tess.fillTexcoords.length) { + texcoords = new float[tess.fillTexcoords.length]; } - tess.fillTexcoords.rewind(); - tess.fillTexcoords.get(texcoords); - return texcoords; + PApplet.arrayCopy(tess.fillTexcoords, texcoords); + return texcoords; } public int[] fillAmbient(int[] ambient) { updateTesselation(); - if (ambient == null || ambient.length != tess.fillAmbient.capacity()) { - ambient = new int[tess.fillAmbient.capacity()]; + if (ambient == null || ambient.length != tess.fillAmbient.length) { + ambient = new int[tess.fillAmbient.length]; } - tess.fillAmbient.rewind(); - tess.fillAmbient.get(ambient); - return ambient; + PApplet.arrayCopy(tess.fillAmbient, ambient); + return ambient; } public int[] fillSpecular(int[] specular) { updateTesselation(); - if (specular == null || specular.length != tess.fillSpecular.capacity()) { - specular = new int[tess.fillSpecular.capacity()]; + if (specular == null || specular.length != tess.fillSpecular.length) { + specular = new int[tess.fillSpecular.length]; } - tess.fillSpecular.rewind(); - tess.fillSpecular.get(specular); - return specular; + PApplet.arrayCopy(tess.fillSpecular, specular); + return specular; } public int[] fillEmissive(int[] emissive) { updateTesselation(); - if (emissive == null || emissive.length != tess.fillEmissive.capacity()) { - emissive = new int[tess.fillEmissive.capacity()]; + if (emissive == null || emissive.length != tess.fillEmissive.length) { + emissive = new int[tess.fillEmissive.length]; } - tess.fillEmissive.rewind(); - tess.fillEmissive.get(emissive); - return emissive; + PApplet.arrayCopy(tess.fillEmissive, emissive); + return emissive; } public float[] fillShininess(float[] shininess) { updateTesselation(); - if (shininess == null || shininess.length != tess.fillShininess.capacity()) { - shininess = new float[tess.fillShininess.capacity()]; + if (shininess == null || shininess.length != tess.fillShininess.length) { + shininess = new float[tess.fillShininess.length]; } - tess.fillShininess.rewind(); - tess.fillShininess.get(shininess); - return shininess; + PApplet.arrayCopy(tess.fillShininess, shininess); + return shininess; } public int[] fillIndices(int[] indices) { - updateTesselation(); - if (indices == null || indices.length != tess.fillIndices.capacity()) { - indices = new int[tess.fillIndices.capacity()]; + updateTesselation(); + if (indices == null || indices.length != tess.fillIndices.length) { + indices = new int[tess.fillIndices.length]; } - tess.fillIndices.rewind(); - tess.fillIndices.get(indices); - return indices; + PApplet.arrayCopy(tess.fillIndexCount, indices); + return indices; } public int firstLineVertex() { @@ -2191,42 +2160,38 @@ public class PShape3D extends PShape { public float[] lineVertices(float[] vertices) { updateTesselation(); - if (vertices == null || vertices.length != tess.lineVertices.capacity()) { - vertices = new float[tess.lineVertices.capacity()]; + if (vertices == null || vertices.length != tess.lineVertices.length) { + vertices = new float[tess.lineVertices.length]; } - tess.lineVertices.rewind(); - tess.lineVertices.get(vertices); - return vertices; + PApplet.arrayCopy(tess.lineVertices, vertices); + return vertices; } public int[] lineColors(int[] colors) { updateTesselation(); - if (colors == null || colors.length != tess.lineColors.capacity()) { - colors = new int[tess.lineColors.capacity()]; + if (colors == null || colors.length != tess.lineColors.length) { + colors = new int[tess.lineColors.length]; } - tess.lineColors.rewind(); - tess.lineColors.get(colors); - return colors; + PApplet.arrayCopy(tess.lineColors, colors); + return colors; } public float[] lineAttributes(float[] attribs) { updateTesselation(); - if (attribs == null || attribs.length != tess.lineDirWidths.capacity()) { - attribs = new float[tess.lineDirWidths.capacity()]; + if (attribs == null || attribs.length != tess.lineDirWidths.length) { + attribs = new float[tess.lineDirWidths.length]; } - tess.lineDirWidths.rewind(); - tess.lineDirWidths.get(attribs); - return attribs; + PApplet.arrayCopy(tess.lineDirWidths, attribs); + return attribs; } public int[] lineIndices(int[] indices) { updateTesselation(); - if (indices == null || indices.length != tess.lineIndices.capacity()) { - indices = new int[tess.lineIndices.capacity()]; + if (indices == null || indices.length != tess.lineIndices.length) { + indices = new int[tess.lineIndices.length]; } - tess.lineIndices.rewind(); - tess.lineIndices.get(indices); - return indices; + PApplet.arrayCopy(tess.lineIndices, indices); + return indices; } public int firstPointVertex() { @@ -2261,42 +2226,38 @@ public class PShape3D extends PShape { public float[] pointVertices(float[] vertices) { updateTesselation(); - if (vertices == null || vertices.length != tess.pointVertices.capacity()) { - vertices = new float[tess.pointVertices.capacity()]; + if (vertices == null || vertices.length != tess.pointVertices.length) { + vertices = new float[tess.pointVertices.length]; } - tess.pointVertices.rewind(); - tess.pointVertices.get(vertices); - return vertices; + PApplet.arrayCopy(tess.pointVertices, vertices); + return vertices; } public int[] pointColors(int[] colors) { updateTesselation(); - if (colors == null || colors.length != tess.pointColors.capacity()) { - colors = new int[tess.pointColors.capacity()]; + if (colors == null || colors.length != tess.pointColors.length) { + colors = new int[tess.pointColors.length]; } - tess.pointColors.rewind(); - tess.pointColors.get(colors); - return colors; + PApplet.arrayCopy(tess.pointColors, colors); + return colors; } public float[] pointAttributes(float[] attribs) { updateTesselation(); - if (attribs == null || attribs.length != tess.pointSizes.capacity()) { - attribs = new float[tess.pointSizes.capacity()]; + if (attribs == null || attribs.length != tess.pointSizes.length) { + attribs = new float[tess.pointSizes.length]; } - tess.pointSizes.rewind(); - tess.pointSizes.get(attribs); - return attribs; + PApplet.arrayCopy(tess.pointSizes, attribs); + return attribs; } public int[] pointIndices(int[] indices) { updateTesselation(); - if (indices == null || indices.length != tess.pointIndices.capacity()) { - indices = new int[tess.pointIndices.capacity()]; + if (indices == null || indices.length != tess.pointIndices.length) { + indices = new int[tess.pointIndices.length]; } - tess.pointIndices.rewind(); - tess.pointIndices.get(indices); - return indices; + PApplet.arrayCopy(tess.pointIndices, indices); + return indices; } public FloatBuffer mapFillVertices() { @@ -2486,7 +2447,7 @@ public class PShape3D extends PShape { protected void updateTesselation() { - if (!root.tessellated) { + if (!root.tessellated || root.contextIsOutdated()) { root.tessellate(); root.aggregate(); } @@ -2500,8 +2461,11 @@ public class PShape3D extends PShape { child.tessellate(); } } else { - if (!tessellated && shapeEnded) { - tess.clear(); + if (shapeEnded) { + if (tessellated) { + tess.clear(); + } + tessellator.setInGeometry(in); tessellator.setTessGeometry(tess); tessellator.setFill(fill || texture != null); @@ -2770,87 +2734,73 @@ public class PShape3D extends PShape { // Copying any data remaining in the caches if (root.fillVerticesCache != null && root.fillVerticesCache.hasData()) { - root.fillVerticesCache.prepareForCopy(); root.copyFillVertices(root.fillVerticesCache.offset, root.fillVerticesCache.size, root.fillVerticesCache.floatData); - root.fillVerticesCache.reset(); + root.fillVerticesCache.clear(); } if (root.fillColorsCache != null && root.fillColorsCache.hasData()) { - root.fillColorsCache.prepareForCopy(); root.copyFillColors(root.fillColorsCache.offset, root.fillColorsCache.size, root.fillColorsCache.intData); - root.fillColorsCache.reset(); + root.fillColorsCache.clear(); } if (root.fillNormalsCache != null && root.fillNormalsCache.hasData()) { - root.fillNormalsCache.prepareForCopy(); root.copyFillNormals(root.fillNormalsCache.offset, root.fillNormalsCache.size, root.fillNormalsCache.floatData); - root.fillNormalsCache.reset(); + root.fillNormalsCache.clear(); } if (root.fillTexCoordsCache != null && root.fillTexCoordsCache.hasData()) { - root.fillTexCoordsCache.prepareForCopy(); root.copyFillTexCoords(root.fillTexCoordsCache.offset, root.fillTexCoordsCache.size, root.fillTexCoordsCache.floatData); - root.fillTexCoordsCache.reset(); + root.fillTexCoordsCache.clear(); } if (root.fillAmbientCache != null && root.fillAmbientCache.hasData()) { - root.fillAmbientCache.prepareForCopy(); root.copyFillAmbient(root.fillAmbientCache.offset, root.fillAmbientCache.size, root.fillAmbientCache.intData); - root.fillAmbientCache.reset(); - } + root.fillAmbientCache.clear(); + } if (root.fillSpecularCache != null && root.fillSpecularCache.hasData()) { - root.fillSpecularCache.prepareForCopy(); - root.copyfillSpecular(root.fillSpecularCache.offset, root.fillSpecularCache.size, root.fillSpecularCache.intData); - root.fillSpecularCache.reset(); - } - - if (root.fillEmissiveCache != null && root.fillEmissiveCache.hasData()) { - root.fillEmissiveCache.prepareForCopy(); - root.copyFillEmissive(root.fillEmissiveCache.offset, root.fillEmissiveCache.size, root.fillEmissiveCache.intData); - root.fillEmissiveCache.reset(); - } - - if (root.fillShininessCache != null && root.fillShininessCache.hasData()) { - root.fillShininessCache.prepareForCopy(); - root.copyFillShininess(root.fillShininessCache.offset, root.fillShininessCache.size, root.fillShininessCache.floatData); - root.fillShininessCache.reset(); + root.copyFillSpecular(root.fillSpecularCache.offset, root.fillSpecularCache.size, root.fillSpecularCache.intData); + root.fillSpecularCache.clear(); } + if (root.fillEmissiveCache != null && root.fillEmissiveCache.hasData()) { + root.copyFillEmissive(root.fillEmissiveCache.offset, root.fillEmissiveCache.size, root.fillEmissiveCache.intData); + root.fillEmissiveCache.clear(); + } + + if (root.fillShininessCache != null && root.fillShininessCache.hasData()) { + root.copyFillShininess(root.fillShininessCache.offset, root.fillShininessCache.size, root.fillShininessCache.floatData); + root.fillShininessCache.clear(); + } + if (root.lineVerticesCache != null && root.lineVerticesCache.hasData()) { - root.lineVerticesCache.prepareForCopy(); root.copyLineVertices(root.lineVerticesCache.offset, root.lineVerticesCache.size, root.lineVerticesCache.floatData); - root.lineVerticesCache.reset(); + root.lineVerticesCache.clear(); } if (root.lineColorsCache != null && root.lineColorsCache.hasData()) { - root.lineColorsCache.prepareForCopy(); root.copyLineColors(root.lineColorsCache.offset, root.lineColorsCache.size, root.lineColorsCache.intData); - root.lineColorsCache.reset(); + root.lineColorsCache.clear(); } if (root.lineAttributesCache != null && root.lineAttributesCache.hasData()) { - root.lineAttributesCache.prepareForCopy(); root.copyLineAttributes(root.lineAttributesCache.offset, root.lineAttributesCache.size, root.lineAttributesCache.floatData); - root.lineAttributesCache.reset(); + root.lineAttributesCache.clear(); } if (root.pointVerticesCache != null && root.pointVerticesCache.hasData()) { - root.pointVerticesCache.prepareForCopy(); root.copyPointVertices(root.pointVerticesCache.offset, root.pointVerticesCache.size, root.pointVerticesCache.floatData); - root.pointVerticesCache.reset(); + root.pointVerticesCache.clear(); } if (root.pointColorsCache != null && root.pointColorsCache.hasData()) { - root.pointColorsCache.prepareForCopy(); root.copyPointColors(root.pointColorsCache.offset, root.pointColorsCache.size, root.pointColorsCache.intData); - root.pointColorsCache.reset(); + root.pointColorsCache.clear(); } if (root.pointAttributesCache != null && root.pointAttributesCache.hasData()) { - root.pointAttributesCache.prepareForCopy(); root.copyPointAttributes(root.pointAttributesCache.offset, root.pointAttributesCache.size, root.pointAttributesCache.floatData); - root.pointAttributesCache.reset(); + root.pointAttributesCache.clear(); } } } @@ -2964,6 +2914,7 @@ public class PShape3D extends PShape { } root.lastLineVertexOffset = tess.setLineVertex(root.lastLineVertexOffset); root.lastLineIndexOffset = tess.setLineIndex(root.firstLineVertexRel, root.lastLineIndexOffset); + root.firstLineVertexRel += tess.lineVertexCount; addLineIndexData(root.firstLineVertexAbs, tess.firstLineIndex, tess.lastLineIndex - tess.firstLineIndex + 1); } @@ -2974,6 +2925,7 @@ public class PShape3D extends PShape { } root.lastPointVertexOffset = tess.setPointVertex(root.lastPointVertexOffset); root.lastPointIndexOffset = tess.setPointIndex(root.firstPointVertexRel, root.lastPointIndexOffset); + root.firstPointVertexRel += tess.pointVertexCount; addPointIndexData(root.firstPointVertexAbs, tess.firstPointIndex, tess.lastPointIndex - tess.firstPointIndex + 1); } } @@ -3085,11 +3037,45 @@ public class PShape3D extends PShape { } } + + protected boolean contextIsOutdated() { + boolean outdated = !pgl.contextIsCurrent(context); + if (outdated) { + // The OpenGL resources have been already deleted + // when the context changed. We only need to zero + // them to avoid deleting them again when the GC + // runs the finalizers of the disposed object. + glFillVertexBufferID = 0; + glFillColorBufferID = 0; + glFillNormalBufferID = 0; + glFillTexCoordBufferID = 0; + glFillAmbientBufferID = 0; + glFillSpecularBufferID = 0; + glFillEmissiveBufferID = 0; + glFillShininessBufferID = 0; + glFillIndexBufferID = 0; + + glLineVertexBufferID = 0; + glLineColorBufferID = 0; + glLineDirWidthBufferID = 0; + glLineIndexBufferID = 0; + + glPointVertexBufferID = 0; + glPointColorBufferID = 0; + glPointSizeBufferID = 0; + glPointIndexBufferID = 0; + } + return outdated; + } + + protected void initFillBuffers(int nvert, int nind) { int sizef = nvert * PGL.SIZEOF_FLOAT; int sizei = nvert * PGL.SIZEOF_INT; int sizex = nind * PGL.SIZEOF_INDEX; + context = pgl.getContext(); + glFillVertexBufferID = pg.createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillVertexBufferID); pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, null, glMode); @@ -3139,14 +3125,12 @@ public class PShape3D extends PShape { child.copyFillGeometryToRoot(); } } else { - if (0 < tess.fillVertexCount && 0 < tess.fillIndexCount) { - tess.prepareFillVerticesForCopy(); + if (0 < tess.fillVertexCount && 0 < tess.fillIndexCount) { root.copyFillGeometry(root.fillVertCopyOffset, tess.fillVertexCount, tess.fillVertices, tess.fillColors, tess.fillNormals, tess.fillTexcoords, tess.fillAmbient, tess.fillSpecular, tess.fillEmissive, tess.fillShininess); root.fillVertCopyOffset += tess.fillVertexCount; - tess.prepareFillIndicesForCopy(); root.copyFillIndices(root.fillIndCopyOffset, tess.fillIndexCount, tess.fillIndices); root.fillIndCopyOffset += tess.fillIndexCount; } @@ -3162,19 +3146,17 @@ public class PShape3D extends PShape { } } else { - if (0 < tess.fillVertexCount) { - tess.prepareFillVerticesForCopy(); - + if (0 < tess.fillVertexCount) { if (modifiedFillVertices) { if (root.fillVerticesCache == null) { root.fillVerticesCache = new VertexCache(3, true); - } + } + root.fillVerticesCache.add(root.fillVertCopyOffset, tess.fillVertexCount, tess.fillVertices); modifiedFillVertices = false; } else if (root.fillVerticesCache != null && root.fillVerticesCache.hasData()) { - root.fillVerticesCache.prepareForCopy(); root.copyFillVertices(root.fillVerticesCache.offset, root.fillVerticesCache.size, root.fillVerticesCache.floatData); - root.fillVerticesCache.reset(); + root.fillVerticesCache.clear(); } if (modifiedFillColors) { @@ -3184,9 +3166,8 @@ public class PShape3D extends PShape { root.fillColorsCache.add(root.fillVertCopyOffset, tess.fillVertexCount, tess.fillColors); modifiedFillColors = false; } else if (root.fillColorsCache != null && root.fillColorsCache.hasData()) { - root.fillColorsCache.prepareForCopy(); root.copyFillColors(root.fillColorsCache.offset, root.fillColorsCache.size, root.fillColorsCache.intData); - root.fillColorsCache.reset(); + root.fillColorsCache.clear(); } if (modifiedFillNormals) { @@ -3196,9 +3177,8 @@ public class PShape3D extends PShape { root.fillNormalsCache.add(root.fillVertCopyOffset, tess.fillVertexCount, tess.fillNormals); modifiedFillNormals = false; } else if (root.fillNormalsCache != null && root.fillNormalsCache.hasData()) { - root.fillNormalsCache.prepareForCopy(); root.copyFillNormals(root.fillNormalsCache.offset, root.fillNormalsCache.size, root.fillNormalsCache.floatData); - root.fillNormalsCache.reset(); + root.fillNormalsCache.clear(); } if (modifiedFillTexCoords) { @@ -3208,9 +3188,8 @@ public class PShape3D extends PShape { root.fillTexCoordsCache.add(root.fillVertCopyOffset, tess.fillVertexCount, tess.fillTexcoords); modifiedFillTexCoords = false; } else if (root.fillTexCoordsCache != null && root.fillTexCoordsCache.hasData()) { - root.fillTexCoordsCache.prepareForCopy(); root.copyFillTexCoords(root.fillTexCoordsCache.offset, root.fillTexCoordsCache.size, root.fillTexCoordsCache.floatData); - root.fillTexCoordsCache.reset(); + root.fillTexCoordsCache.clear(); } if (modifiedFillAmbient) { @@ -3220,9 +3199,8 @@ public class PShape3D extends PShape { root.fillAmbientCache.add(root.fillVertCopyOffset, tess.fillVertexCount, tess.fillAmbient); modifiedFillAmbient = false; } else if (root.fillAmbientCache != null && root.fillAmbientCache.hasData()) { - root.fillAmbientCache.prepareForCopy(); root.copyFillAmbient(root.fillAmbientCache.offset, root.fillAmbientCache.size, root.fillAmbientCache.intData); - root.fillAmbientCache.reset(); + root.fillAmbientCache.clear(); } if (modifiedFillSpecular) { @@ -3232,9 +3210,8 @@ public class PShape3D extends PShape { root.fillSpecularCache.add(root.fillVertCopyOffset, tess.fillVertexCount, tess.fillSpecular); modifiedFillSpecular = false; } else if (root.fillSpecularCache != null && root.fillSpecularCache.hasData()) { - root.fillSpecularCache.prepareForCopy(); - root.copyfillSpecular(root.fillSpecularCache.offset, root.fillSpecularCache.size, root.fillSpecularCache.intData); - root.fillSpecularCache.reset(); + root.copyFillSpecular(root.fillSpecularCache.offset, root.fillSpecularCache.size, root.fillSpecularCache.intData); + root.fillSpecularCache.clear(); } if (modifiedFillEmissive) { @@ -3244,9 +3221,8 @@ public class PShape3D extends PShape { root.fillEmissiveCache.add(root.fillVertCopyOffset, tess.fillVertexCount, tess.fillEmissive); modifiedFillEmissive = false; } else if (root.fillEmissiveCache != null && root.fillEmissiveCache.hasData()) { - root.fillEmissiveCache.prepareForCopy(); root.copyFillEmissive(root.fillEmissiveCache.offset, root.fillEmissiveCache.size, root.fillEmissiveCache.intData); - root.fillEmissiveCache.reset(); + root.fillEmissiveCache.clear(); } if (modifiedFillShininess) { @@ -3256,15 +3232,12 @@ public class PShape3D extends PShape { root.fillShininessCache.add(root.fillVertCopyOffset, tess.fillVertexCount, tess.fillShininess); modifiedFillShininess = false; } else if (root.fillShininessCache != null && root.fillShininessCache.hasData()) { - root.fillShininessCache.prepareForCopy(); root.copyFillShininess(root.fillShininessCache.offset, root.fillShininessCache.size, root.fillShininessCache.floatData); - root.fillShininessCache.reset(); + root.fillShininessCache.clear(); } } if (0 < tess.lineVertexCount) { - tess.prepareLineVerticesForCopy(); - if (modifiedLineVertices) { if (root.lineVerticesCache == null) { root.lineVerticesCache = new VertexCache(3, true); @@ -3272,9 +3245,8 @@ public class PShape3D extends PShape { root.lineVerticesCache.add(root.lineVertCopyOffset, tess.lineVertexCount, tess.lineVertices); modifiedLineVertices = false; } else if (root.lineVerticesCache != null && root.lineVerticesCache.hasData()) { - root.lineVerticesCache.prepareForCopy(); root.copyLineVertices(root.lineVerticesCache.offset, root.lineVerticesCache.size, root.lineVerticesCache.floatData); - root.lineVerticesCache.reset(); + root.lineVerticesCache.clear(); } if (modifiedLineColors) { @@ -3284,9 +3256,8 @@ public class PShape3D extends PShape { root.lineColorsCache.add(root.lineVertCopyOffset, tess.lineVertexCount, tess.lineColors); modifiedLineColors = false; } else if (root.lineColorsCache != null && root.lineColorsCache.hasData()) { - root.lineColorsCache.prepareForCopy(); root.copyLineColors(root.lineColorsCache.offset, root.lineColorsCache.size, root.lineColorsCache.intData); - root.lineColorsCache.reset(); + root.lineColorsCache.clear(); } if (modifiedLineAttributes) { @@ -3296,15 +3267,12 @@ public class PShape3D extends PShape { root.lineAttributesCache.add(root.lineVertCopyOffset, tess.lineVertexCount, tess.lineDirWidths); modifiedLineAttributes = false; } else if (root.lineAttributesCache != null && root.lineAttributesCache.hasData()) { - root.lineAttributesCache.prepareForCopy(); root.copyLineAttributes(root.lineAttributesCache.offset, root.lineAttributesCache.size, root.lineAttributesCache.floatData); - root.lineAttributesCache.reset(); + root.lineAttributesCache.clear(); } } if (0 < tess.pointVertexCount) { - tess.preparePointVerticesForCopy(); - if (modifiedPointVertices) { if (root.pointVerticesCache == null) { root.pointVerticesCache = new VertexCache(3, true); @@ -3312,9 +3280,8 @@ public class PShape3D extends PShape { root.pointVerticesCache.add(root.pointVertCopyOffset, tess.pointVertexCount, tess.pointVertices); modifiedPointVertices = false; } else if (root.pointVerticesCache != null && root.pointVerticesCache.hasData()) { - root.pointVerticesCache.prepareForCopy(); root.copyPointVertices(root.pointVerticesCache.offset, root.pointVerticesCache.size, root.pointVerticesCache.floatData); - root.pointVerticesCache.reset(); + root.pointVerticesCache.clear(); } if (modifiedPointColors) { @@ -3324,9 +3291,8 @@ public class PShape3D extends PShape { root.pointColorsCache.add(root.pointVertCopyOffset, tess.pointVertexCount, tess.pointColors); modifiedPointColors = false; } else if (root.pointColorsCache != null && root.pointColorsCache.hasData()) { - root.pointColorsCache.prepareForCopy(); root.copyPointColors(root.pointColorsCache.offset, root.pointColorsCache.size, root.pointColorsCache.intData); - root.pointColorsCache.reset(); + root.pointColorsCache.clear(); } if (modifiedPointAttributes) { @@ -3336,9 +3302,8 @@ public class PShape3D extends PShape { root.pointAttributesCache.add(root.pointVertCopyOffset, tess.pointVertexCount, tess.pointSizes); modifiedPointAttributes = false; } else if (root.pointAttributesCache != null && root.pointAttributesCache.hasData()) { - root.pointAttributesCache.prepareForCopy(); root.copyPointAttributes(root.pointAttributesCache.offset, root.pointAttributesCache.size, root.pointAttributesCache.floatData); - root.pointAttributesCache.reset(); + root.pointAttributesCache.clear(); } } @@ -3352,101 +3317,101 @@ public class PShape3D extends PShape { protected void copyFillGeometry(int offset, int size, - FloatBuffer vertices, IntBuffer colors, - FloatBuffer normals, FloatBuffer texcoords, - IntBuffer ambient, IntBuffer specular, IntBuffer emissive, FloatBuffer shininess) { + float[] vertices, int[] colors, + float[] normals, float[] texcoords, + int[] ambient, int[] specular, int[] emissive, float[] shininess) { int offsetf = offset * PGL.SIZEOF_FLOAT; int offseti = offset * PGL.SIZEOF_INT; int sizef = size * PGL.SIZEOF_FLOAT; int sizei = size * PGL.SIZEOF_INT; pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillVertexBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offsetf, 3 * sizef, vertices); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offsetf, 3 * sizef, FloatBuffer.wrap(vertices, 0, 3 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillColorBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offseti, sizei, colors); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offseti, sizei, IntBuffer.wrap(colors, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillNormalBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offsetf, 3 * sizef, normals); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offsetf, 3 * sizef, FloatBuffer.wrap(normals, 0, 3 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillTexCoordBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 2 * offsetf, 2 * sizef, texcoords); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 2 * offsetf, 2 * sizef, FloatBuffer.wrap(texcoords, 0, 2 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillAmbientBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offseti, sizei, ambient); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offseti, sizei, IntBuffer.wrap(ambient, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillSpecularBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offseti, sizei, specular); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offseti, sizei, IntBuffer.wrap(specular, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillEmissiveBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offseti, sizei, emissive); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offseti, sizei, IntBuffer.wrap(emissive, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillShininessBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offsetf, sizef, shininess); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offsetf, sizef, FloatBuffer.wrap(shininess, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyFillVertices(int offset, int size, FloatBuffer vertices) { + protected void copyFillVertices(int offset, int size, float[] vertices) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillVertexBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offset * PGL.SIZEOF_FLOAT, 3 * size * PGL.SIZEOF_FLOAT, vertices); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offset * PGL.SIZEOF_FLOAT, 3 * size * PGL.SIZEOF_FLOAT, FloatBuffer.wrap(vertices, 0, 3 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyFillColors(int offset, int size, IntBuffer colors) { + protected void copyFillColors(int offset, int size, int[] colors) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillColorBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, colors); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, IntBuffer.wrap(colors, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyFillNormals(int offset, int size, FloatBuffer normals) { + protected void copyFillNormals(int offset, int size, float[] normals) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillNormalBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offset * PGL.SIZEOF_FLOAT, 3 * size * PGL.SIZEOF_FLOAT, normals); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offset * PGL.SIZEOF_FLOAT, 3 * size * PGL.SIZEOF_FLOAT, FloatBuffer.wrap(normals, 0, 3 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyFillTexCoords(int offset, int size, FloatBuffer texcoords) { + protected void copyFillTexCoords(int offset, int size, float[] texcoords) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillTexCoordBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 2 * offset * PGL.SIZEOF_FLOAT, 2 * size * PGL.SIZEOF_FLOAT, texcoords); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 2 * offset * PGL.SIZEOF_FLOAT, 2 * size * PGL.SIZEOF_FLOAT, FloatBuffer.wrap(texcoords, 0, 2 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyFillAmbient(int offset, int size, IntBuffer ambient) { + protected void copyFillAmbient(int offset, int size, int[] ambient) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillAmbientBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, ambient); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, IntBuffer.wrap(ambient, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyfillSpecular(int offset, int size, IntBuffer specular) { + protected void copyFillSpecular(int offset, int size, int[] specular) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillSpecularBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, specular); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, IntBuffer.wrap(specular, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyFillEmissive(int offset, int size, IntBuffer emissive) { + protected void copyFillEmissive(int offset, int size, int[] emissive) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillEmissiveBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, emissive); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, IntBuffer.wrap(emissive, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyFillShininess(int offset, int size, FloatBuffer shininess) { + protected void copyFillShininess(int offset, int size, float[] shininess) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillShininessBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_FLOAT, size * PGL.SIZEOF_FLOAT, shininess); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_FLOAT, size * PGL.SIZEOF_FLOAT, FloatBuffer.wrap(shininess, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyFillIndices(int offset, int size, IntBuffer indices) { + protected void copyFillIndices(int offset, int size, int[] indices) { pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glFillIndexBufferID); - pgl.glBufferSubData(PGL.GL_ELEMENT_ARRAY_BUFFER, offset * PGL.SIZEOF_INDEX, size * PGL.SIZEOF_INDEX, indices); + pgl.glBufferSubData(PGL.GL_ELEMENT_ARRAY_BUFFER, offset * PGL.SIZEOF_INDEX, size * PGL.SIZEOF_INDEX, IntBuffer.wrap(indices, 0, size)); pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); } @@ -3486,12 +3451,10 @@ public class PShape3D extends PShape { } } else { if (hasLines) { - tess.prepareLineVerticesForCopy(); root.copyLineGeometry(root.lineVertCopyOffset, tess.lineVertexCount, tess.lineVertices, tess.lineColors, tess.lineDirWidths); root.lineVertCopyOffset += tess.lineVertexCount; - tess.prepareLineIndicesForCopy(); root.copyLineIndices(root.lineIndCopyOffset, tess.lineIndexCount, tess.lineIndices); root.lineIndCopyOffset += tess.lineIndexCount; } @@ -3500,49 +3463,49 @@ public class PShape3D extends PShape { protected void copyLineGeometry(int offset, int size, - FloatBuffer vertices, IntBuffer colors, FloatBuffer attribs) { + float[] vertices, int[] colors, float[] attribs) { int offsetf = offset * PGL.SIZEOF_FLOAT; int sizef = size * PGL.SIZEOF_FLOAT; int offseti = offset * PGL.SIZEOF_INT; int sizei = size * PGL.SIZEOF_INT; pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineVertexBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offsetf, 3 * sizef, vertices); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offsetf, 3 * sizef, FloatBuffer.wrap(vertices, 0, 3 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineColorBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offseti, sizei, colors); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offseti, sizei, IntBuffer.wrap(colors, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineDirWidthBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 4 * offsetf, 4 * sizef, attribs); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 4 * offsetf, 4 * sizef, FloatBuffer.wrap(attribs, 0, 4 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyLineVertices(int offset, int size, FloatBuffer vertices) { + protected void copyLineVertices(int offset, int size, float[] vertices) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineVertexBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offset * PGL.SIZEOF_FLOAT, 3 * size * PGL.SIZEOF_FLOAT, vertices); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offset * PGL.SIZEOF_FLOAT, 3 * size * PGL.SIZEOF_FLOAT, FloatBuffer.wrap(vertices, 0, 3 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyLineColors(int offset, int size, IntBuffer colors) { + protected void copyLineColors(int offset, int size, int[] colors) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineColorBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, colors); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, IntBuffer.wrap(colors, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyLineAttributes(int offset, int size, FloatBuffer attribs) { + protected void copyLineAttributes(int offset, int size, float[] attribs) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineDirWidthBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 4 * offset * PGL.SIZEOF_FLOAT, 4 * size * PGL.SIZEOF_FLOAT, attribs); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 4 * offset * PGL.SIZEOF_FLOAT, 4 * size * PGL.SIZEOF_FLOAT, FloatBuffer.wrap(attribs, 0, 4 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyLineIndices(int offset, int size, IntBuffer indices) { + protected void copyLineIndices(int offset, int size, int[] indices) { pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glLineIndexBufferID); - pgl.glBufferSubData(PGL.GL_ELEMENT_ARRAY_BUFFER, offset * PGL.SIZEOF_INDEX, size * PGL.SIZEOF_INDEX, indices); + pgl.glBufferSubData(PGL.GL_ELEMENT_ARRAY_BUFFER, offset * PGL.SIZEOF_INDEX, size * PGL.SIZEOF_INDEX, IntBuffer.wrap(indices, 0, size)); pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); } @@ -3582,12 +3545,10 @@ public class PShape3D extends PShape { } } else { if (hasPoints) { - tess.preparePointVerticesForCopy(); root.copyPointGeometry(root.pointVertCopyOffset, tess.pointVertexCount, tess.pointVertices, tess.pointColors, tess.pointSizes); root.pointVertCopyOffset += tess.pointVertexCount; - tess.preparePointIndicesForCopy(); root.copyPointIndices(root.pointIndCopyOffset, tess.pointIndexCount, tess.pointIndices); root.pointIndCopyOffset += tess.pointIndexCount; } @@ -3596,49 +3557,49 @@ public class PShape3D extends PShape { protected void copyPointGeometry(int offset, int size, - FloatBuffer vertices, IntBuffer colors, FloatBuffer attribs) { + float[] vertices, int[] colors, float[] attribs) { int offsetf = offset * PGL.SIZEOF_FLOAT; int sizef = size * PGL.SIZEOF_FLOAT; int offseti = offset * PGL.SIZEOF_INT; int sizei = size * PGL.SIZEOF_INT; pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointVertexBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offsetf, 3 * sizef, vertices); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offsetf, 3 * sizef, FloatBuffer.wrap(vertices, 0, 3 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointColorBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offseti, sizei, colors); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offseti, sizei, IntBuffer.wrap(colors, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointSizeBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 2 * offsetf, 2 * sizef, attribs); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 2 * offsetf, 2 * sizef, FloatBuffer.wrap(attribs, 0, 2 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyPointVertices(int offset, int size, FloatBuffer vertices) { + protected void copyPointVertices(int offset, int size, float[] vertices) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointVertexBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offset * PGL.SIZEOF_FLOAT, 3 * size * PGL.SIZEOF_FLOAT, vertices); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 3 * offset * PGL.SIZEOF_FLOAT, 3 * size * PGL.SIZEOF_FLOAT, FloatBuffer.wrap(vertices, 0, 3 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyPointColors(int offset, int size, IntBuffer colors) { + protected void copyPointColors(int offset, int size, int[] colors) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointColorBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, colors); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, offset * PGL.SIZEOF_INT, size * PGL.SIZEOF_INT, IntBuffer.wrap(colors, 0, size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyPointAttributes(int offset, int size, FloatBuffer attribs) { + protected void copyPointAttributes(int offset, int size, float[] attribs) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointSizeBufferID); - pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 2 * offset * PGL.SIZEOF_FLOAT, 2 * size * PGL.SIZEOF_FLOAT, attribs); + pgl.glBufferSubData(PGL.GL_ARRAY_BUFFER, 2 * offset * PGL.SIZEOF_FLOAT, 2 * size * PGL.SIZEOF_FLOAT, FloatBuffer.wrap(attribs, 0, 2 * size)); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); } - protected void copyPointIndices(int offset, int size, IntBuffer indices) { + protected void copyPointIndices(int offset, int size, int[] indices) { pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glPointIndexBufferID); - pgl.glBufferSubData(PGL.GL_ELEMENT_ARRAY_BUFFER, offset * PGL.SIZEOF_INDEX, size * PGL.SIZEOF_INDEX, indices); + pgl.glBufferSubData(PGL.GL_ELEMENT_ARRAY_BUFFER, offset * PGL.SIZEOF_INDEX, size * PGL.SIZEOF_INDEX, IntBuffer.wrap(indices, 0, size)); pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); } @@ -3952,71 +3913,117 @@ public class PShape3D extends PShape { // to the VBOs with fewer calls. protected class VertexCache { boolean isFloat; - int ncoords; // Number of components per data element - int offset; // Offset (in the dest VBO) to start copying this data to - int size; // Total number of data elements - FloatBuffer floatData; - IntBuffer intData; + int ncoords; + int offset; + int size; + float[] floatData; + int[] intData; VertexCache(int ncoords, boolean isFloat) { this.ncoords = ncoords; this.isFloat = isFloat; if (isFloat) { - this.floatData = pgl.createFloatBuffer(ncoords * PGL.DEFAULT_VERTEX_CACHE_SIZE); + this.floatData = new float[ncoords * PGL.DEFAULT_VERTEX_CACHE_SIZE]; } else { - this.intData = pgl.createIntBuffer(ncoords * PGL.DEFAULT_VERTEX_CACHE_SIZE); + this.intData = new int[ncoords * PGL.DEFAULT_VERTEX_CACHE_SIZE]; } this.offset = 0; this.size = 0; } - void reset() { + void clear() { offset = 0; size = 0; - if (isFloat) { - floatData.clear(); + } + + void add(int dataOffset, int dataSize, float[] newData) { + if (size == 0) { + offset = dataOffset; + } + + int oldSize = floatData.length / ncoords; + if (size + dataSize >= oldSize) { + int newSize = expandSize(oldSize, size + dataSize); + expand(newSize); + } + + if (dataSize <= PGraphicsOpenGL.MIN_ARRAYCOPY_SIZE) { + // Copying elements one by one instead of using arrayCopy is more efficient for + // few vertices... + for (int i = 0; i < dataSize; i++) { + int srcIndex = ncoords * i; + int destIndex = ncoords * (size + i); + + if (ncoords == 2) { + floatData[destIndex++] = newData[srcIndex++]; + floatData[destIndex ] = newData[srcIndex ]; + } else if (ncoords == 3) { + floatData[destIndex++] = newData[srcIndex++]; + floatData[destIndex++] = newData[srcIndex++]; + floatData[destIndex ] = newData[srcIndex ]; + } else if (ncoords == 4) { + floatData[destIndex++] = newData[srcIndex++]; + floatData[destIndex++] = newData[srcIndex++]; + floatData[destIndex++] = newData[srcIndex++]; + floatData[destIndex ] = newData[srcIndex ]; + } else { + for (int j = 0; j < ncoords; j++) { + floatData[destIndex++] = newData[srcIndex++]; + } + } + } } else { - intData.clear(); + PApplet.arrayCopy(newData, 0, floatData, ncoords * size, ncoords * dataSize); } - } - - void add(int dataOffset, int dataSize, FloatBuffer newData) { - if (size == 0) { - offset = dataOffset; - } - - int oldSize = floatData.capacity() / ncoords; - if (size + dataSize >= oldSize) { - int newSize = expandSize(oldSize, size + dataSize); - prepareFloatDataForCopy(); - expand(newSize); - } - - floatData.position(ncoords * size); - floatData.put(newData); size += dataSize; } - void add(int dataOffset, int dataSize, IntBuffer newData) { + void add(int dataOffset, int dataSize, int[] newData) { if (size == 0) { offset = dataOffset; } - int oldSize = intData.capacity() / ncoords; + int oldSize = intData.length / ncoords; if (size + dataSize >= oldSize) { - int newSize = expandSize(oldSize, size + dataSize); - prepareIntDataForCopy(); + int newSize = expandSize(oldSize, size + dataSize); expand(newSize); } - intData.position(ncoords * size); - intData.put(newData); + if (dataSize <= PGraphicsOpenGL.MIN_ARRAYCOPY_SIZE) { + // Copying elements one by one instead of using arrayCopy is more efficient for + // few vertices... + for (int i = 0; i < dataSize; i++) { + int srcIndex = ncoords * i; + int destIndex = ncoords * (size + i); + + if (ncoords == 2) { + intData[destIndex++] = newData[srcIndex++]; + intData[destIndex ] = newData[srcIndex ]; + } else if (ncoords == 3) { + intData[destIndex++] = newData[srcIndex++]; + intData[destIndex++] = newData[srcIndex++]; + intData[destIndex ] = newData[srcIndex ]; + } else if (ncoords == 4) { + intData[destIndex++] = newData[srcIndex++]; + intData[destIndex++] = newData[srcIndex++]; + intData[destIndex++] = newData[srcIndex++]; + intData[destIndex ] = newData[srcIndex ]; + } else { + for (int j = 0; j < ncoords; j++) { + intData[destIndex++] = newData[srcIndex++]; + } + } + } + } else { + PApplet.arrayCopy(newData, 0, intData, ncoords * size, ncoords * dataSize); + } size += dataSize; } - void add(int dataOffset, int dataSize, float[] newData, PMatrix tr) { + void add(int dataOffset, int dataSize, float[] newData, PMatrix tr) { + if (tr instanceof PMatrix2D) { add(dataOffset, dataSize, newData, (PMatrix2D)tr); } else if (tr instanceof PMatrix3D) { @@ -4024,82 +4031,60 @@ public class PShape3D extends PShape { } } - void add(int dataOffset, int dataSize, FloatBuffer newData, PMatrix2D tr) { + void add(int dataOffset, int dataSize, float[] newData, PMatrix2D tr) { if (size == 0) { offset = dataOffset; } - int oldSize = floatData.capacity() / ncoords; + int oldSize = floatData.length / ncoords; if (size + dataSize >= oldSize) { - int newSize = expandSize(oldSize, size + dataSize); - prepareFloatDataForCopy(); + int newSize = expandSize(oldSize, size + dataSize); expand(newSize); } if (2 <= ncoords) { - float[] data0 = new float[2]; - float[] data1 = new float[2]; for (int i = 0; i < dataSize; i++) { - newData.get(data0); + int srcIndex = ncoords * i; + float x = newData[srcIndex++]; + float y = newData[srcIndex ]; - data1[0] = data0[0] * tr.m00 + data0[1] * tr.m01 + tr.m02; - data1[1] = data0[0] * tr.m10 + data0[1] * tr.m11 + tr.m12; - floatData.position(ncoords * (size + i)); - floatData.put(data1, 0, 2); + int destIndex = ncoords * (size + i); + floatData[destIndex++] = x * tr.m00 + y * tr.m01 + tr.m02; + floatData[destIndex ] = x * tr.m10 + y * tr.m11 + tr.m12; } } size += dataSize; } - void add(int dataOffset, int dataSize, FloatBuffer newData, PMatrix3D tr) { + void add(int dataOffset, int dataSize, float[] newData, PMatrix3D tr) { if (size == 0) { offset = dataOffset; } - int oldSize = floatData.capacity() / ncoords; + int oldSize = floatData.length / ncoords; if (size + dataSize >= oldSize) { - int newSize = expandSize(oldSize, size + dataSize); - prepareIntDataForCopy(); + int newSize = expandSize(oldSize, size + dataSize); expand(newSize); } if (3 <= ncoords) { - float[] data0 = new float[3]; - float[] data1 = new float[3]; for (int i = 0; i < dataSize; i++) { - newData.get(data0); - - data1[0] = data0[0] * tr.m00 + data0[1] * tr.m01 + data0[2] * tr.m02 + tr.m03; - data1[1] = data0[0] * tr.m10 + data0[1] * tr.m11 + data0[2] * tr.m12 + tr.m13; - data1[2] = data0[0] * tr.m20 + data0[1] * tr.m21 + data0[2] * tr.m22 + tr.m23; - - floatData.position(ncoords * (size + i)); - floatData.put(data1); + int srcIndex = ncoords * i; + float x = newData[srcIndex++]; + float y = newData[srcIndex++]; + float z = newData[srcIndex++]; + + int destIndex = ncoords * (size + i); + floatData[destIndex++] = x * tr.m00 + y * tr.m01 + z * tr.m02 + tr.m03; + floatData[destIndex++] = x * tr.m10 + y * tr.m11 + z * tr.m12 + tr.m13; + floatData[destIndex ] = x * tr.m20 + y * tr.m21 + z * tr.m22 + tr.m23; } } size += dataSize; } - void prepareForCopy() { - if (isFloat) { - prepareFloatDataForCopy(); - } else { - prepareIntDataForCopy(); - } - } - - void prepareFloatDataForCopy() { - floatData.position(0); - floatData.limit(ncoords * size); - } - - void prepareIntDataForCopy() { - intData.position(0); - intData.limit(ncoords * size); - } - void expand(int n) { if (isFloat) { expandFloat(n); @@ -4109,15 +4094,15 @@ public class PShape3D extends PShape { } void expandFloat(int n) { - FloatBuffer temp = pgl.createFloatBuffer(ncoords * n); - temp.put(floatData); + float temp[] = new float[ncoords * n]; + PApplet.arrayCopy(floatData, 0, temp, 0, ncoords * size); floatData = temp; } void expandInt(int n) { - IntBuffer temp = pgl.createIntBuffer(ncoords * n); - temp.put(intData); - intData = temp; + int temp[] = new int[ncoords * n]; + PApplet.arrayCopy(intData, 0, temp, 0, ncoords * size); + intData = temp; } int expandSize(int currSize, int newMinSize) { @@ -4130,7 +4115,8 @@ public class PShape3D extends PShape { boolean hasData() { return 0 < size; - } + } + } diff --git a/java/libraries/opengl/src/processing/opengl/PTexture.java b/java/libraries/opengl/src/processing/opengl/PTexture.java index 1a1bc2a39..957a26db8 100644 --- a/java/libraries/opengl/src/processing/opengl/PTexture.java +++ b/java/libraries/opengl/src/processing/opengl/PTexture.java @@ -42,7 +42,7 @@ public class PTexture implements PConstants { public int width, height; protected PApplet parent; // The Processing applet - protected PGraphicsOpenGL pg; // The main renderer + protected PGraphicsOpenGL pg; // The main renderer protected PGL pgl; // The interface between Processing and OpenGL. protected PGL.Context context; // The context that created this texture. @@ -67,8 +67,6 @@ public class PTexture implements PConstants { protected int[] tempPixels = null; protected PFramebuffer tempFbo = null; - protected IntBuffer texels; - protected Object bufferSource; protected LinkedList bufferCache = null; protected Method disposeBufferMethod; @@ -103,8 +101,7 @@ public class PTexture implements PConstants { this.parent = parent; pg = (PGraphicsOpenGL)parent.g; - pgl = pg.pgl; - context = pgl.getContext(); + pgl = pg.pgl; glID = 0; @@ -120,8 +117,7 @@ public class PTexture implements PConstants { } finally { super.finalize(); } - } - + } //////////////////////////////////////////////////////////// @@ -777,6 +773,7 @@ public class PTexture implements PConstants { pgl.enableTexturing(glTarget); + context = pgl.getContext(); glID = pg.createTextureObject(); pgl.glBindTexture(glTarget, glID); @@ -808,6 +805,14 @@ public class PTexture implements PConstants { } + protected boolean contextIsOutdated() { + boolean outdated = !pgl.contextIsCurrent(context); + if (outdated) { + glID = 0; + } + return outdated; + } + /////////////////////////////////////////////////////////// // Utilities. @@ -846,21 +851,14 @@ public class PTexture implements PConstants { protected void setTexels(int[] pix, int x, int y, int w, int h) { setTexels(pix, 0, x, y, w, h); } + + protected void setTexels(int[] pix, int level, int x, int y, int w, int h) { + pgl.glTexSubImage2D(glTarget, level, x, y, w, h, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, IntBuffer.wrap(pix)); + } protected void setTexels(IntBuffer buffer, int x, int y, int w, int h) { setTexels(buffer, 0, x, y, w, h); - } - - protected void setTexels(int[] pix, int level, int x, int y, int w, int h) { - if (texels == null || texels.capacity() != width * height) { - texels = pgl.createIntBuffer(width * height); - } - texels.position(0); - texels.limit(pix.length); - texels.put(pix); - texels.flip(); - pgl.glTexSubImage2D(glTarget, level, x, y, w, h, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, texels); - } + } protected void setTexels(IntBuffer buffer, int level, int x, int y, int w, int h) { pgl.glTexSubImage2D(glTarget, level, x, y, w, h, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, buffer);