diff --git a/android/core/src/processing/data/Table.java b/android/core/src/processing/data/Table.java index 8318b5a5c..10493f838 100644 --- a/android/core/src/processing/data/Table.java +++ b/android/core/src/processing/data/Table.java @@ -3,8 +3,8 @@ /* Part of the Processing project - http://processing.org - Copyright (c) 2011- Ben Fry and Casey Reas - Copyright (c) 2006-2011 Ben Fry + Copyright (c) 2011-12 Ben Fry and Casey Reas + Copyright (c) 2006-11 Ben Fry This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public diff --git a/app/src/processing/app/Sketch.java b/app/src/processing/app/Sketch.java index e01adcaad..1265b630e 100644 --- a/app/src/processing/app/Sketch.java +++ b/app/src/processing/app/Sketch.java @@ -87,13 +87,13 @@ public class Sketch { // private ArrayList importedLibraries; // //private ArrayList importedLibraries; - /** + /** * Most recent, default build path. This will contain the .java files that - * have been preprocessed, as well as any .class files that were compiled. + * have been preprocessed, as well as any .class files that were compiled. */ // private File buildFolder; - - + + /** * path is location of the main .pde file, because this is also * simplest to use when opening the file from the finder/explorer. @@ -134,7 +134,7 @@ public class Sketch { load(); } - + /** * Build the list of files. @@ -215,8 +215,8 @@ public class Sketch { } - /** - * Reload the current sketch. Used to update the text area when + /** + * Reload the current sketch. Used to update the text area when * an external editor is in use. */ public void reload() { @@ -432,7 +432,7 @@ public class Sketch { "\"" + newName + "\" already exists.", null); return; } - + // renaming the containing sketch folder boolean success = folder.renameTo(newFolder); if (!success) { @@ -632,7 +632,7 @@ public class Sketch { public void setModified(boolean state) { //System.out.println("setting modified to " + state); //new Exception().printStackTrace(System.out); - if (current.isModified() != state) { + if (current.isModified() != state) { current.setModified(state); calcModified(); } @@ -792,7 +792,7 @@ public class Sketch { } } catch (IOException e) { } - // if the new folder already exists, then first remove its contents before + // if the new folder already exists, then first remove its contents before // copying everything over (user will have already been warned) if (newFolder.exists()) { Base.removeDir(newFolder); @@ -828,7 +828,7 @@ public class Sketch { return false; } } - // don't do screen captures, since there might be thousands. kind of + // don't do screen captures, since there might be thousands. kind of // a hack, but seems harmless. hm, where have i heard that before... if (name.startsWith("screen-")) { return false; @@ -839,7 +839,7 @@ public class Sketch { // now copy over the items that make sense for (File copyable : copyItems) { if (copyable.isDirectory()) { - Base.copyDir(copyable, new File(newFolder, copyable.getName())); + Base.copyDir(copyable, new File(newFolder, copyable.getName())); } else { Base.copyFile(copyable, new File(newFolder, copyable.getName())); } @@ -863,19 +863,19 @@ public class Sketch { // let Editor know that the save was successful return true; } - - - /** + + + /** * Update internal state for new sketch name or folder location. */ protected void updateInternal(String sketchName, File sketchFolder) { - // reset all the state information for the sketch object + // reset all the state information for the sketch object primaryFile = code[0].getFile(); name = sketchName; folder = sketchFolder; codeFolder = new File(folder, "code"); dataFolder = new File(folder, "data"); - + // set the main file to be the current tab //setCurrentCode(0); // nah, this might just annoy people @@ -1067,7 +1067,7 @@ public class Sketch { * */ public void setCurrentCode(int which) { -// // for the tab sizing +// // for the tab sizing // if (current != null) { // current.visited = System.currentTimeMillis(); // System.out.println(current.visited); @@ -1110,7 +1110,7 @@ public class Sketch { } - /** + /** * Create a temporary folder that includes the sketch's name in its title. */ public File makeTempFolder() { @@ -1120,11 +1120,11 @@ public class Sketch { return buildFolder; // } else { -// Base.showWarning("Build folder bad", +// Base.showWarning("Build folder bad", // "Could not create a place to build the sketch.", null); // } } catch (IOException e) { - Base.showWarning("Build folder bad", + Base.showWarning("Build folder bad", "Could not find a place to build the sketch.", e); } return null; @@ -1281,7 +1281,7 @@ public class Sketch { return dataFolder; } - + public boolean hasDataFolder() { return dataFolder.exists(); } @@ -1364,6 +1364,11 @@ public class Sketch { } + public String getMainProgram() { + return getCode(0).getProgram(); + } + + public void setUntitled(boolean u) { editor.untitled = u; } @@ -1448,8 +1453,8 @@ public class Sketch { } return buffer.toString(); } - - + + public Mode getMode() { return mode; } diff --git a/app/src/processing/mode/android/AndroidBuild.java b/app/src/processing/mode/android/AndroidBuild.java index c832d5adf..0a08befa3 100644 --- a/app/src/processing/mode/android/AndroidBuild.java +++ b/app/src/processing/mode/android/AndroidBuild.java @@ -120,9 +120,12 @@ class AndroidBuild extends JavaBuild { // build the preproc and get to work AndroidPreprocessor preproc = new AndroidPreprocessor(sketch, getPackageName()); - if (!preproc.parseSketchSize()) { - throw new SketchException("Could not parse the size() command."); - } +// if (!preproc.parseSketchSize()) { +// String[] sizeInfo = PdePreprocessor.parseSketchSize(sketch.getMainProgram()); +// if (sizeInfo == null) { +// throw new SketchException("Could not parse the size() command."); +// } + preproc.initSketchSize(sketch.getMainProgram()); sketchClassName = preprocess(srcFolder, manifest.getPackageName(), preproc); if (sketchClassName != null) { File tempManifest = new File(tmpFolder, "AndroidManifest.xml"); diff --git a/app/src/processing/mode/android/AndroidPreprocessor.java b/app/src/processing/mode/android/AndroidPreprocessor.java index 927b485b1..490c1e17f 100644 --- a/app/src/processing/mode/android/AndroidPreprocessor.java +++ b/app/src/processing/mode/android/AndroidPreprocessor.java @@ -26,10 +26,7 @@ import java.io.PrintWriter; import java.io.Writer; import java.util.List; -import processing.app.Base; -import processing.app.Preferences; -import processing.app.Sketch; -import processing.app.SketchException; +import processing.app.*; import processing.core.PApplet; import processing.mode.java.preproc.PdePreprocessor; import processing.mode.java.preproc.PreprocessorResult; @@ -41,11 +38,6 @@ public class AndroidPreprocessor extends PdePreprocessor { Sketch sketch; String packageName; - String sizeStatement; - String sketchWidth; - String sketchHeight; - String sketchRenderer; - public AndroidPreprocessor(final Sketch sketch, final String packageName) throws IOException { @@ -55,8 +47,21 @@ public class AndroidPreprocessor extends PdePreprocessor { } - // TODO this needs to be a generic function inside Sketch or elsewhere + public String[] initSketchSize(String code) throws SketchException { + String[] info = parseSketchSize(code, true); + if (info == null) { + System.err.println("More about the size() command on Android can be"); + System.err.println("found here: http://wiki.processing.org/w/Android"); + throw new SketchException("Could not parse the size() command."); + } + sizeStatement = info[0]; + sketchWidth = info[1]; + sketchHeight = info[2]; + sketchRenderer = info[3]; + return info; + } + /* protected boolean parseSketchSize() { // This matches against any uses of the size() function, whether numbers // or variables or whatever. This way, no warning is shown if size() isn't @@ -121,6 +126,7 @@ public class AndroidPreprocessor extends PdePreprocessor { } return true; } + */ public PreprocessorResult write(Writer out, String program, String[] codeFolderPackages) diff --git a/app/src/processing/mode/java/JavaBuild.java b/app/src/processing/mode/java/JavaBuild.java index d18e171ec..052ed1ab0 100644 --- a/app/src/processing/mode/java/JavaBuild.java +++ b/app/src/processing/mode/java/JavaBuild.java @@ -3,7 +3,7 @@ /* Part of the Processing project - http://processing.org -Copyright (c) 2004-11 Ben Fry and Casey Reas +Copyright (c) 2004-12 Ben Fry and Casey Reas Copyright (c) 2001-04 Massachusetts Institute of Technology This program is free software; you can redistribute it and/or modify @@ -34,16 +34,6 @@ import processing.mode.java.preproc.*; public class JavaBuild { - /** - * Regular expression for parsing the size() method. This should match - * against any uses of the size() function, whether numbers or variables - * or whatever. This way, no warning is shown if size() isn't actually used - * in the sketch, which is the case especially for anyone who is cutting - * and pasting from the reference. - */ - public static final String SIZE_REGEX = - "(?:^|\\s|;)size\\s*\\(\\s*([^\\s,]+)\\s*,\\s*([^\\s,\\)]+),?\\s*([^\\)]*)\\s*\\)\\s*\\;"; - //"(?:^|\\s|;)size\\s*\\(\\s*(\\S+)\\s*,\\s*([^\\s,\\)]+),?\\s*([^\\)]*)\\s*\\)\\s*\\;"; public static final String PACKAGE_REGEX = "(?:^|\\s|;)package\\s+(\\S+)\\;"; @@ -249,20 +239,24 @@ public class JavaBuild { } } - // Automatically insert the OpenGL import line if P3D is used. Do this by - // modifying the code here instead of - String scrubbed = scrubComments(sketch.getCode(0).getProgram()); - String[] matches = PApplet.match(scrubbed, SIZE_REGEX); - String renderer = ""; - if (matches != null) { - // Adding back the trim() for 0136 to handle Bug #769 - if (matches.length == 4) renderer = matches[3].trim(); - // Actually, matches.length should always be 4... - } - // OpenGL import time! Really, this is for P3D, but may as well do it - // for OpenGL as well. - if (renderer.equals("P3D") || renderer.equals("OPENGL")) { - bigCode.insert(0, "import processing.opengl.*; "); + // initSketchSize() sets the internal sketchWidth/Height/Renderer vars + // in the preprocessor. Those are used in preproc.write() so that they + // can be turned into sketchXxxx() methods. + // This also returns the size info as an array so that we can figure out + // if this fella is OpenGL, and if so, to add the import. It's messy and + // gross and someday we'll just always include OpenGL. + String[] sizeInfo = + preprocessor.initSketchSize(sketch.getMainProgram()); + //PdePreprocessor.parseSketchSize(sketch.getMainProgram(), false); + if (sizeInfo != null) { + String sketchRenderer = sizeInfo[3]; + if (sketchRenderer != null) { + if (sketchRenderer.equals("P2D") || + sketchRenderer.equals("P3D") || + sketchRenderer.equals("OPENGL")) { + bigCode.insert(0, "import processing.opengl.*; "); + } + } } PreprocessorResult result; @@ -298,7 +292,7 @@ public class JavaBuild { // System.out.println(errorLine + " " + errorFile + " " + code[errorFile].getPreprocOffset()); String msg = re.getMessage(); - + //System.out.println(java.getAbsolutePath()); System.out.println(bigCode); @@ -313,7 +307,7 @@ public class JavaBuild { "without a } to match it.", errorFile, errorLine, re.getColumn(), false); } - + if (msg.contains("expecting LCURLY")) { System.err.println(msg); String suffix = "."; @@ -321,7 +315,7 @@ public class JavaBuild { if (m != null) { suffix = ", not " + m[1] + "."; } - throw new SketchException("Was expecting a { character" + suffix, + throw new SketchException("Was expecting a { character" + suffix, errorFile, errorLine, re.getColumn(), false); } @@ -365,7 +359,7 @@ public class JavaBuild { // TODO not tested since removing ORO matcher.. ^ could be a problem String mess = "^line (\\d+):(\\d+):\\s"; - matches = PApplet.match(tsre.toString(), mess); + String[] matches = PApplet.match(tsre.toString(), mess); if (matches != null) { int errorLine = Integer.parseInt(matches[1]) - 1; int errorColumn = Integer.parseInt(matches[2]); @@ -503,7 +497,7 @@ public class JavaBuild { sc.addPreprocOffset(result.headerOffset); } } - foundMain = preprocessor.getFoundMain(); + foundMain = preprocessor.hasMethod("main"); return result.className; } @@ -730,12 +724,57 @@ public class JavaBuild { return false; } + String[] sizeInfo = + PdePreprocessor.parseSketchSize(sketch.getMainProgram(), false); + int sketchWidth = PApplet.DEFAULT_WIDTH; + int sketchHeight = PApplet.DEFAULT_HEIGHT; + boolean openglApplet = false; + boolean foundSize = false; + if (sizeInfo != null) { + try { + if (sizeInfo[1] != null && sizeInfo[2] != null) { + sketchWidth = Integer.parseInt(sizeInfo[1]); + sketchHeight = Integer.parseInt(sizeInfo[2]); + foundSize = true; + } + } catch (Exception e) { + e.printStackTrace(); + // parsing errors, whatever; ignored + } + + String sketchRenderer = sizeInfo[3]; + if (sketchRenderer != null) { + if (sketchRenderer.equals("P2D") || + sketchRenderer.equals("P3D") || + sketchRenderer.equals("OPENGL")) { + openglApplet = true; + } + } + } + if (!foundSize) { + final String message = + "The size of this applet could not automatically be\n" + + "determined from your code. You'll have to edit the\n" + + "HTML file to set the size of the applet.\n" + + "Use only numeric values (not variables) for the size()\n" + + "command. See the size() reference for an explanation."; + Base.showWarning("Could not find applet size", message, null); + } + +// // If the renderer is set to the built-in OpenGL library, +// // then it's definitely an OpenGL applet. +// if (sketchRenderer.equals("P3D") || sketchRenderer.equals("OPENGL")) { +// openglApplet = true; +// } + + + /* int wide = PApplet.DEFAULT_WIDTH; int high = PApplet.DEFAULT_HEIGHT; String renderer = ""; - String scrubbed = scrubComments(sketch.getCode(0).getProgram()); - String[] matches = PApplet.match(scrubbed, SIZE_REGEX); + String scrubbed = PdePreprocessor.scrubComments(sketch.getCode(0).getProgram()); + String[] matches = PApplet.match(scrubbed, PdePreprocessor.SIZE_REGEX); if (matches != null) { try { @@ -759,6 +798,7 @@ public class JavaBuild { Base.showWarning("Could not find applet size", message, null); } } // else no size() command found + */ // Grab the Javadoc-style description from the main code. String description = ""; @@ -847,7 +887,7 @@ public class JavaBuild { // File openglLibraryFolder = // new File(editor.getMode().getLibrariesFolder(), "opengl/library"); // String openglLibraryPath = openglLibraryFolder.getAbsolutePath(); - boolean openglApplet = false; +// boolean openglApplet = false; HashMap zipFileContents = new HashMap(); @@ -942,11 +982,6 @@ public class JavaBuild { // for (File libraryFolder : importedLibraries) { // System.out.println(libraryFolder + " " + libraryFolder.getAbsolutePath()); // } - // If the renderer is set to the built-in OpenGL library, - // then it's definitely an OpenGL applet. - if (renderer.equals("P3D") || renderer.equals("OPENGL")) { - openglApplet = true; - } if (is == null) { if (openglApplet) { is = mode.getContentStream("applet/template-opengl.html"); @@ -975,11 +1010,11 @@ public class JavaBuild { } while ((index = sb.indexOf("@@width@@")) != -1) { sb.replace(index, index + "@@width@@".length(), - String.valueOf(wide)); + String.valueOf(sketchWidth)); } while ((index = sb.indexOf("@@height@@")) != -1) { sb.replace(index, index + "@@height@@".length(), - String.valueOf(high)); + String.valueOf(sketchHeight)); } while ((index = sb.indexOf("@@description@@")) != -1) { sb.replace(index, index + "@@description@@".length(), @@ -998,58 +1033,6 @@ public class JavaBuild { } - /** - * Replace all commented portions of a given String as spaces. - * Utility function used here and in the preprocessor. - */ - static public String scrubComments(String what) { - char p[] = what.toCharArray(); - - int index = 0; - while (index < p.length) { - // for any double slash comments, ignore until the end of the line - if ((p[index] == '/') && - (index < p.length - 1) && - (p[index+1] == '/')) { - p[index++] = ' '; - p[index++] = ' '; - while ((index < p.length) && - (p[index] != '\n')) { - p[index++] = ' '; - } - - // check to see if this is the start of a new multiline comment. - // if it is, then make sure it's actually terminated somewhere. - } else if ((p[index] == '/') && - (index < p.length - 1) && - (p[index+1] == '*')) { - p[index++] = ' '; - p[index++] = ' '; - boolean endOfRainbow = false; - while (index < p.length - 1) { - if ((p[index] == '*') && (p[index+1] == '/')) { - p[index++] = ' '; - p[index++] = ' '; - endOfRainbow = true; - break; - - } else { - // continue blanking this area - p[index++] = ' '; - } - } - if (!endOfRainbow) { - throw new RuntimeException("Missing the */ from the end of a " + - "/* comment */"); - } - } else { // any old character, move along - index++; - } - } - return new String(p); - } - - /** * Export to application via GUI. */ diff --git a/app/src/processing/mode/java/preproc/PdeEmitter.java b/app/src/processing/mode/java/preproc/PdeEmitter.java index 58b022971..95d767e86 100644 --- a/app/src/processing/mode/java/preproc/PdeEmitter.java +++ b/app/src/processing/mode/java/preproc/PdeEmitter.java @@ -24,7 +24,7 @@ import antlr.collections.AST; * other than System.out, and then call print(), passing the * AST. Typically, the AST node that you pass would be the root of a * tree - the ROOT_ID node that represents a Java file. - * + * * Modified March 2010 to support Java 5 type arguments and for loops by * @author Jonathan Feinberg <jdf@pobox.com> */ @@ -239,10 +239,11 @@ public class PdeEmitter implements PdeTokenTypes { type = modifiers.getNextSibling(); } final AST methodName = type.getNextSibling(); - if (methodName.getText().equals("main")) { - pdePreprocessor.setFoundMain(true); - } - printChildren(ast); +// if (methodName.getText().equals("main")) { +// pdePreprocessor.setFoundMain(true); +// } + pdePreprocessor.addMethod(methodName.getText()); + printChildren(ast); } private void printIfThenElse(final AST literalIf) throws SketchException { @@ -265,10 +266,10 @@ public class PdeEmitter implements PdeTokenTypes { dumpHiddenBefore(bestPrintableNode); final CommonHiddenStreamToken hiddenBefore = ((CommonASTWithHiddenTokens) elsePath).getHiddenBefore(); - if (elsePath.getType() == PdeTokenTypes.SLIST && elsePath.getNumberOfChildren() == 0 && + if (elsePath.getType() == PdeTokenTypes.SLIST && elsePath.getNumberOfChildren() == 0 && hiddenBefore == null) { out.print("{"); - final CommonHiddenStreamToken hiddenAfter = + final CommonHiddenStreamToken hiddenAfter = ((CommonASTWithHiddenTokens) elsePath).getHiddenAfter(); if (hiddenAfter == null) { out.print("}"); @@ -742,11 +743,11 @@ public class PdeEmitter implements PdeTokenTypes { out.print("@"); printChildren(ast); break; - + case ANNOTATION_ARRAY_INIT: printChildren(ast); break; - + case ANNOTATION_MEMBER_VALUE_PAIR: print(ast.getFirstChild()); out.print("="); diff --git a/app/src/processing/mode/java/preproc/PdePreprocessor.java b/app/src/processing/mode/java/preproc/PdePreprocessor.java index d9aece7cd..11f0746fa 100644 --- a/app/src/processing/mode/java/preproc/PdePreprocessor.java +++ b/app/src/processing/mode/java/preproc/PdePreprocessor.java @@ -4,7 +4,7 @@ PdePreprocessor - wrapper for default ANTLR-generated parser Part of the Processing project - http://processing.org - Copyright (c) 2004-10 Ben Fry and Casey Reas + Copyright (c) 2004-12 Ben Fry and Casey Reas Copyright (c) 2001-04 Massachusetts Institute of Technology ANTLR-generated parser and several supporting classes written @@ -30,6 +30,8 @@ package processing.mode.java.preproc; import java.io.*; import java.util.*; import java.util.regex.Pattern; + +import processing.app.Base; import processing.app.Preferences; import processing.app.SketchException; import processing.core.PApplet; @@ -146,33 +148,33 @@ public class PdePreprocessor { private TokenStreamCopyingHiddenTokenFilter filter; - private boolean foundMain; - - public void setFoundMain(boolean foundMain) { - this.foundMain = foundMain; - } - - public boolean getFoundMain() { - return foundMain; - } - +// private boolean foundMain; private String advClassName = ""; - - public void setAdvClassName(final String advClassName) { - this.advClassName = advClassName; - } - protected Mode mode; + HashMap foundMethods; + + protected String sizeStatement; + protected String sketchWidth; + protected String sketchHeight; + protected String sketchRenderer; + + /** + * Regular expression for parsing the size() method. This should match + * against any uses of the size() function, whether numbers or variables + * or whatever. This way, no warning is shown if size() isn't actually used + * in the sketch, which is the case especially for anyone who is cutting + * and pasting from the reference. + */ + public static final String SIZE_REGEX = + "(?:^|\\s|;)size\\s*\\(\\s*([^\\s,]+)\\s*,\\s*([^\\s,\\)]+),?\\s*([^\\)]*)\\s*\\)\\s*\\;"; + //"(?:^|\\s|;)size\\s*\\(\\s*(\\S+)\\s*,\\s*([^\\s,\\)]+),?\\s*([^\\)]*)\\s*\\)\\s*\\;"; - public void setMode(final Mode mode) { - // System.err.println("Setting mode to " + mode); - this.mode = mode; - } public PdePreprocessor(final String sketchName) { this(sketchName, Preferences.getInteger("editor.tabs.size")); } + public PdePreprocessor(final String sketchName, final int tabSize) { this.name = sketchName; final char[] indentChars = new char[tabSize]; @@ -180,14 +182,176 @@ public class PdePreprocessor { indent = new String(indentChars); } + + public String[] initSketchSize(String code) throws SketchException { + String[] info = parseSketchSize(code, true); + if (info != null) { + sizeStatement = info[0]; + sketchWidth = info[1]; + sketchHeight = info[2]; + sketchRenderer = info[3]; + } + return info; + } + + + /** + * Parse a chunk of code and extract the size() command and its contents. + * @param code Usually the code from the main tab in the sketch + * @param fussy true if it should show an error message if bad size() + * @return null if there was an error, otherwise an array (might contain some/all nulls) + */ + static public String[] parseSketchSize(String code, boolean fussy) { + // This matches against any uses of the size() function, whether numbers + // or variables or whatever. This way, no warning is shown if size() isn't + // actually used in the applet, which is the case especially for anyone + // who is cutting/pasting from the reference. + +// String scrubbed = scrubComments(sketch.getCode(0).getProgram()); +// String[] matches = PApplet.match(scrubbed, SIZE_REGEX); + String[] matches = PApplet.match(scrubComments(code), SIZE_REGEX); + + if (matches != null) { + boolean badSize = false; + + if (matches[1].equals("screenWidth") || + matches[1].equals("screenHeight") || + matches[2].equals("screenWidth") || + matches[2].equals("screenHeight")) { + final String message = + "The screenWidth and screenHeight variables\n" + + "are named displayWidth and displayHeight\n" + + "in this release of Processing."; + Base.showWarning("Time for a quick update", message, null); + return null; + } + + if (!matches[1].equals("displayWidth") && + !matches[1].equals("displayHeight") && + PApplet.parseInt(matches[1], -1) == -1) { + badSize = true; + } + if (!matches[2].equals("displayWidth") && + !matches[2].equals("displayHeight") && + PApplet.parseInt(matches[2], -1) == -1) { + badSize = true; + } + + if (badSize && fussy) { + // found a reference to size, but it didn't seem to contain numbers + final String message = + "The size of this applet could not automatically\n" + + "be determined from your code. Use only numeric\n" + + "values (not variables) for the size() command.\n" + + "See the size() reference for an explanation."; + Base.showWarning("Could not find sketch size", message, null); + new Exception().printStackTrace(System.out); + return null; + } + + // if the renderer entry is empty, set it to null + if (matches[3].trim().length() == 0) { + matches[3] = null; + } + return matches; + } + return new String[] { null, null, null, null }; // not an error, just empty + } + + + /** + * Replace all commented portions of a given String as spaces. + * Utility function used here and in the preprocessor. + */ + static public String scrubComments(String what) { + char p[] = what.toCharArray(); + + int index = 0; + while (index < p.length) { + // for any double slash comments, ignore until the end of the line + if ((p[index] == '/') && + (index < p.length - 1) && + (p[index+1] == '/')) { + p[index++] = ' '; + p[index++] = ' '; + while ((index < p.length) && + (p[index] != '\n')) { + p[index++] = ' '; + } + + // check to see if this is the start of a new multiline comment. + // if it is, then make sure it's actually terminated somewhere. + } else if ((p[index] == '/') && + (index < p.length - 1) && + (p[index+1] == '*')) { + p[index++] = ' '; + p[index++] = ' '; + boolean endOfRainbow = false; + while (index < p.length - 1) { + if ((p[index] == '*') && (p[index+1] == '/')) { + p[index++] = ' '; + p[index++] = ' '; + endOfRainbow = true; + break; + + } else { + // continue blanking this area + p[index++] = ' '; + } + } + if (!endOfRainbow) { + throw new RuntimeException("Missing the */ from the end of a " + + "/* comment */"); + } + } else { // any old character, move along + index++; + } + } + return new String(p); + } + + + public void addMethod(String methodName) { + foundMethods.put(methodName, new Object()); + } + + + public boolean hasMethod(String methodName) { + return foundMethods.containsKey(methodName); + } + + +// public void setFoundMain(boolean foundMain) { +// this.foundMain = foundMain; +// } + + +// public boolean getFoundMain() { +// return foundMain; +// } + + + public void setAdvClassName(final String advClassName) { + this.advClassName = advClassName; + } + + + public void setMode(final Mode mode) { + // System.err.println("Setting mode to " + mode); + this.mode = mode; + } + + CommonHiddenStreamToken getHiddenAfter(final CommonHiddenStreamToken t) { return filter.getHiddenAfter(t); } + CommonHiddenStreamToken getInitialHiddenToken() { return filter.getInitialHiddenToken(); } + private static int countNewlines(final String s) { int count = 0; for (int pos = s.indexOf('\n', 0); pos >= 0; pos = s.indexOf('\n', pos + 1)) @@ -195,6 +359,7 @@ public class PdePreprocessor { return count; } + private static void checkForUnterminatedMultilineComment(final String program) throws SketchException { final int length = program.length(); @@ -291,11 +456,13 @@ public class PdePreprocessor { } } + public PreprocessorResult write(final Writer out, String program) throws SketchException, RecognitionException, TokenStreamException { return write(out, program, null); } + public PreprocessorResult write(Writer out, String program, String codeFolderPackages[]) throws SketchException, RecognitionException, TokenStreamException { @@ -310,9 +477,10 @@ public class PdePreprocessor { final ArrayList codeFolderImports = new ArrayList(); // need to reset whether or not this has a main() - foundMain = false; +// foundMain = false; + foundMethods = new HashMap(); - // bug #5 + // http://processing.org/bugs/bugzilla/5.html if (!program.endsWith("\n")) program += "\n"; @@ -663,7 +831,17 @@ public class PdePreprocessor { } if ((mode == Mode.STATIC) || (mode == Mode.ACTIVE)) { - if (!foundMain) { + if (sketchWidth != null && !hasMethod("sketchWidth")) { + out.println(indent + "public int sketchWidth() { return " + sketchWidth + "; }"); + } + if (sketchHeight != null && !hasMethod("sketchHeight")) { + out.println(indent + "public int sketchHeight() { return " + sketchHeight + "; }"); + } + if (sketchRenderer != null && !hasMethod("sketchRenderer")) { + out.println(indent + "public String sketchRenderer() { return " + sketchRenderer + "; }"); + } + + if (!hasMethod("main")) { out.println(indent + "static public void main(String args[]) {"); out.print(indent + indent + "PApplet.main(new String[] { "); diff --git a/app/src/processing/mode/javascript/JavaScriptBuild.java b/app/src/processing/mode/javascript/JavaScriptBuild.java index 42fb31cdd..2d76ed2c7 100644 --- a/app/src/processing/mode/javascript/JavaScriptBuild.java +++ b/app/src/processing/mode/javascript/JavaScriptBuild.java @@ -20,27 +20,27 @@ import processing.app.Library; import processing.core.PApplet; -import processing.mode.java.JavaBuild; import processing.mode.java.preproc.PdePreprocessor; + public class JavaScriptBuild { public final static String TEMPLATE_FOLDER_NAME = "template"; public final static String EXPORTED_FOLDER_NAME = "web-export"; public final static String TEMPLATE_FILE_NAME = "template.html"; - - public final static String IMPORT_REGEX = + + public final static String IMPORT_REGEX = "^[\\s]*import[\\s]+([^\\s]+)[\\s]*"; - + /** * Answers with the first java doc style comment in the string, * or an empty string if no such comment can be found. */ - public static String getDocString ( String s ) + public static String getDocString ( String s ) { String[] javadoc = PApplet.match(s, "/\\*{2,}(.*?)\\*+/"); - if (javadoc != null) + if (javadoc != null) { StringBuffer dbuffer = new StringBuffer(); String[] pieces = PApplet.split(javadoc[1], '\n'); @@ -56,21 +56,21 @@ public class JavaScriptBuild return ""; } - + /** * Reads in a simple template file, with fields of the form '@@somekey@@' * and replaces each field with the value in the map for 'somekey', writing * the output to the output file. - * + * * Keys not in the map will be replaced with empty strings. - * + * * @param template File object mapping to the template * @param output File object handle to the output * @param args template keys, data values to replace them * @throws IOException when there are problems writing to or from the files */ public static void writeTemplate ( File template, File output, Map fields ) - throws IOException + throws IOException { BufferedReader reader = PApplet.createReader(template); PrintWriter writer = PApplet.createWriter(output); @@ -97,11 +97,11 @@ public class JavaScriptBuild } writer.close(); } - - // ----------------------------------------------------- - - /** + // ----------------------------------------------------- + + + /** * The sketch this builder is working on. *

* Each builder instance should only work on a single sketch, so if @@ -110,16 +110,16 @@ public class JavaScriptBuild protected Sketch sketch; protected Mode mode; - + protected File binFolder; - - public JavaScriptBuild ( Sketch sketch ) + + public JavaScriptBuild ( Sketch sketch ) { this.sketch = sketch; this.mode = sketch.getMode(); } - - + + /** * Builds the sketch *

@@ -128,9 +128,9 @@ public class JavaScriptBuild * 2. cat *.pde > bin/sketchname.pde * 3. cp -r sketch/data/* bin/ (p.js doesn't recognize the data folder) * 4. series of greps to find height, width, name, desc - * 5. cat template.html | sed 's/@@sketch@@/[name]/g' ... [many sed filters] > bin/index.html + * 5. cat template.html | sed 's/@@sketch@@/[name]/g' ... [many sed filters] > bin/index.html *

- * + * * @param bin the output folder for the built sketch * @return boolean whether the build was successful */ @@ -138,38 +138,38 @@ public class JavaScriptBuild { // make sure the user isn't playing "hide-the-sketch-folder" again sketch.ensureExistence(); - + this.binFolder = bin; // we need these .. // JavaScriptMode jsMode = (JavaScriptMode)mode; // JavaScriptEditor jsEditor = (JavaScriptEditor)jsMode.getEditor(); // BasicServer jsServer = jsEditor.getServer(); - - if ( bin.exists() ) - { + + if ( bin.exists() ) + { Base.removeDescendants(bin); } //else will be created during preprocesss - + // pass through preprocessor to catch syntax errors // .. exceptions bubble up. preprocess(bin); // move the data files, copies contents of sketch/data/ to web-export/ - if (sketch.hasDataFolder()) + if (sketch.hasDataFolder()) { try { Base.copyDir(sketch.getDataFolder(), bin); } catch (IOException e) { - final String msg = "An exception occured while trying to copy the data folder. " + + final String msg = "An exception occured while trying to copy the data folder. " + "You may have to manually move the contents of sketch/data to " + "the web-export/ folder. Processing.js doesn't look for a data " + "folder, so lump them together."; Base.showWarning("Problem building the sketch", msg, e); } } - + // as .js files are allowed now include these into the mix, // first find 'em .. String[] sketchFolderFilesRaw = sketch.getFolder().list(); @@ -198,18 +198,18 @@ public class JavaScriptBuild } // TODO - // Really scrub comments from code? + // Really scrub comments from code? // Con: larger files, PJS needs to do it later // Pro: being literate as we are in a script language. - String scrubbed = JavaBuild.scrubComments(sketch.getCode(0).getProgram()); + String scrubbed = PdePreprocessor.scrubComments(sketch.getCode(0).getProgram()); // get width and height int wide = PApplet.DEFAULT_WIDTH; int high = PApplet.DEFAULT_HEIGHT; - String[] matches = PApplet.match(scrubbed, JavaBuild.SIZE_REGEX); - if (matches != null) + String[] matches = PApplet.match(scrubbed, PdePreprocessor.SIZE_REGEX); + if (matches != null) { - try + try { wide = Integer.parseInt(matches[1]); high = Integer.parseInt(matches[2]); @@ -234,7 +234,7 @@ public class JavaScriptBuild // try resolve imports ArrayList importPackages = new ArrayList(); String[] lines = scrubbed.split( "\n" ); - for ( String l : lines ) + for ( String l : lines ) { int iIndex = l.indexOf( "import" ); if ( iIndex != -1 ) @@ -247,7 +247,7 @@ public class JavaScriptBuild { String iPackage = matches[1]; iPackage = iPackage.trim(); - + if ( iPackage.indexOf(".*") != -1 ) { // de.bezier.tutto.* iPackage = iPackage.replace( ".*", "" ); @@ -273,10 +273,10 @@ public class JavaScriptBuild return false; } } - for ( String pack : importPackages ) + for ( String pack : importPackages ) { Library lib = mode.getLibrary( pack ); - if ( lib != null ) + if ( lib != null ) { String libPath = lib.getJarPath(); File libJar = new File( libPath ); @@ -284,20 +284,20 @@ public class JavaScriptBuild { File libJS = new File( libJar.getParent(), libJar.getName().replace(".jar",".js") ); //System.out.println( libJS.getPath() ); - if ( libJS.exists() ) + if ( libJS.exists() ) { String libJSDest = "libs" + File.separator + libJS.getName(); File libJSDestFile = new File( bin, libJSDest ); - if ( libJSDestFile.exists() ) + if ( libJSDestFile.exists() ) { System.out.println( "Duplicate import!" ); } - try + try { - Base.copyFile( libJS, + Base.copyFile( libJS, libJSDestFile ); jsImports.add( libJSDest ); - + } catch ( Exception se ) { se.printStackTrace(); } @@ -305,13 +305,13 @@ public class JavaScriptBuild } } } - + // final prep and write to template. // getTemplateFile() is very important as it looks and preps // any custom templates present in the sketch folder. File templateFile = getTemplateFile(); File htmlOutputFile = new File(bin, "index.html"); - + Map templateFields = new HashMap(); templateFields.put( "width", String.valueOf(wide) ); templateFields.put( "height", String.valueOf(high) ); @@ -320,23 +320,23 @@ public class JavaScriptBuild // generate an ID for the sketch to use with String sketchID = sketch.getName().replaceAll("[^a-zA-Z0-9]+", "").replaceAll("^[^a-zA-Z]+",""); - + // add a handy method to read the generated sketchID String scriptFiles = "\n"; // add imports if any ... @@ -346,9 +346,9 @@ public class JavaScriptBuild } // main .pde file first - String sourceFiles = "" + + String sourceFiles = "" + sketch.getName() + " "; - + // add all other files (both types: .pde and .js) if ( sketchFolderFiles != null ) { @@ -373,14 +373,14 @@ public class JavaScriptBuild Base.showWarning("A problem occured during the build", msg, ioe); return false; } - + // finally, add files processing.js String[] defaultJSFiles = new String[]{ "processing.js" /*, "qrcode.js"*/ }; for ( String defaultJSFile : defaultJSFiles ) { - try + try { Base.copyFile( sketch.getMode().getContentFile( TEMPLATE_FOLDER_NAME + File.separator + defaultJSFile @@ -390,11 +390,11 @@ public class JavaScriptBuild } catch (IOException ioe) { final String msg = "There was a problem copying " +defaultJSFile+ " to the " + - "build folder. You will have to manually add " + + "build folder. You will have to manually add " + defaultJSFile +" to the build folder before the sketch " + "will run."; Base.showWarning( "There was a problem writing to the build folder", msg, ioe); - //return false; + //return false; } } @@ -411,21 +411,21 @@ public class JavaScriptBuild { File sketchFolder = sketch.getFolder(); File customTemplateFolder = new File( sketchFolder, TEMPLATE_FOLDER_NAME ); - if ( customTemplateFolder.exists() && - customTemplateFolder.isDirectory() && + if ( customTemplateFolder.exists() && + customTemplateFolder.isDirectory() && customTemplateFolder.canRead() ) { File appletJsFolder = new File( sketchFolder, EXPORTED_FOLDER_NAME ); - + try { - //TODO: this is potentially dangerous as it might override files in "web-export" + //TODO: this is potentially dangerous as it might override files in "web-export" Base.copyDir( customTemplateFolder, appletJsFolder ); if ( !(new File( appletJsFolder, TEMPLATE_FILE_NAME )).delete() ) { // ignore? } return new File( customTemplateFolder, TEMPLATE_FILE_NAME ); - } catch ( Exception e ) { + } catch ( Exception e ) { String msg = ""; Base.showWarning("There was a problem copying your custom template folder", msg, e); return sketch.getMode().getContentFile( @@ -438,9 +438,9 @@ public class JavaScriptBuild TEMPLATE_FOLDER_NAME + File.separator + TEMPLATE_FILE_NAME ); } - - - /** + + + /** * Collects the sketch code and runs it by the Java-mode preprocessor * to fish for errors. * @@ -460,7 +460,7 @@ public class JavaScriptBuild bigCode.append("\n"); } } - + if (!bin.exists()) { bin.mkdirs(); } @@ -475,8 +475,8 @@ public class JavaScriptBuild PdePreprocessor preprocessor = new PdePreprocessor( sketch.getName() ); //PreprocessorResult result; - - try + + try { File outputFolder = sketch.makeTempFolder(); final File java = new File( outputFolder, sketch.getName() + ".java" ); @@ -596,12 +596,12 @@ public class JavaScriptBuild * Copied from JavaBuild as it is protected there. * @see processing.mode.java.JavaBuild#findErrorFile(int) */ - protected int findErrorFile ( int errorLine ) + protected int findErrorFile ( int errorLine ) { - for (int i = 1; i < sketch.getCodeCount(); i++) + for (int i = 1; i < sketch.getCodeCount(); i++) { SketchCode sc = sketch.getCode(i); - if (sc.isExtension("pde") && (sc.getPreprocOffset() < errorLine)) + if (sc.isExtension("pde") && (sc.getPreprocOffset() < errorLine)) { // keep looping until the errorLine is past the offset return i; @@ -609,9 +609,9 @@ public class JavaScriptBuild } return 0; // i give up } - + /** - * Parse the sketch to retrieve it's description. Answers with the first + * Parse the sketch to retrieve it's description. Answers with the first * java doc style comment in the main sketch file, or an empty string if * no such comment exists. */ @@ -623,10 +623,10 @@ public class JavaScriptBuild // ----------------------------------------------------- // Export - - /** - * Export the sketch to the default "web-export" folder. - * @return success of the operation + + /** + * Export the sketch to the default "web-export" folder. + * @return success of the operation */ public boolean export() throws IOException, SketchException { diff --git a/core/src/processing/core/PApplet.java b/core/src/processing/core/PApplet.java index be803a3ee..02affb4c5 100644 --- a/core/src/processing/core/PApplet.java +++ b/core/src/processing/core/PApplet.java @@ -10252,15 +10252,15 @@ public class PApplet extends Applet /** * ( begin auto-generated from line.xml ) - * - * Draws a line (a direct path between two points) to the screen. The - * version of line() with four parameters draws the line in 2D. To - * color a line, use the stroke() function. A line cannot be filled, - * therefore the fill() function will not affect the color of a - * line. 2D lines are drawn with a width of one pixel by default, but this - * can be changed with the strokeWeight() function. The version with - * six parameters allows the line to be placed anywhere within XYZ space. - * Drawing this shape in 3D with the z parameter requires the P3D + * + * Draws a line (a direct path between two points) to the screen. The + * version of line() with four parameters draws the line in 2D. To + * color a line, use the stroke() function. A line cannot be filled, + * therefore the fill() function will not affect the color of a + * line. 2D lines are drawn with a width of one pixel by default, but this + * can be changed with the strokeWeight() function. The version with + * six parameters allows the line to be placed anywhere within XYZ space. + * Drawing this shape in 3D with the z parameter requires the P3D * parameter in combination with size() as shown in the above example. * * ( end auto-generated ) @@ -10382,7 +10382,7 @@ public class PApplet extends Applet * rectMode() function. * * ( end auto-generated ) - * + * * @webref shape:2d_primitives * @param a x-coordinate of the rectangle by default * @param b y-coordinate of the rectangle by default @@ -10421,16 +10421,16 @@ public class PApplet extends Applet /** * ( begin auto-generated from ellipseMode.xml ) - * - * The origin of the ellipse is modified by the ellipseMode() - * function. The default configuration is ellipseMode(CENTER), which - * specifies the location of the ellipse as the center of the shape. The - * RADIUS mode is the same, but the width and height parameters to - * ellipse() specify the radius of the ellipse, rather than the - * diameter. The CORNER mode draws the shape from the upper-left - * corner of its bounding box. The CORNERS mode uses the four - * parameters to ellipse() to set two opposing corners of the - * ellipse's bounding box. The parameter must be written in ALL CAPS + * + * The origin of the ellipse is modified by the ellipseMode() + * function. The default configuration is ellipseMode(CENTER), which + * specifies the location of the ellipse as the center of the shape. The + * RADIUS mode is the same, but the width and height parameters to + * ellipse() specify the radius of the ellipse, rather than the + * diameter. The CORNER mode draws the shape from the upper-left + * corner of its bounding box. The CORNERS mode uses the four + * parameters to ellipse() to set two opposing corners of the + * ellipse's bounding box. The parameter must be written in ALL CAPS * because Processing is a case-sensitive language. * * ( end auto-generated ) @@ -10541,7 +10541,7 @@ public class PApplet extends Applet * with two parameters. * * ( end auto-generated ) - * + * *

Advanced

* Code for sphereDetail() submitted by toxi [031031]. * Code for enhanced u/v version from davbol [080801]. @@ -10572,7 +10572,7 @@ public class PApplet extends Applet * A sphere is a hollow ball made from tessellated triangles. * * ( end auto-generated ) - * + * *

Advanced

*

* Implementation notes: @@ -10614,7 +10614,7 @@ public class PApplet extends Applet * at t. * * ( end auto-generated ) - * + * *

Advanced

* For instance, to convert the following example:
    * stroke(255, 102, 0);
@@ -10659,7 +10659,7 @@ public class PApplet extends Applet
    * target="new">tangent on Wikipedia.
    *
    * ( end auto-generated )
-   *
+   * 
    * 

Advanced

* Code submitted by Dave Bollinger (davol) for release 0136. * @@ -10686,7 +10686,7 @@ public class PApplet extends Applet * P2D renderer does not use this information. * * ( end auto-generated ) - * + * * @webref shape:curves * @param detail resolution of the curves * @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float) @@ -10720,7 +10720,7 @@ public class PApplet extends Applet * Environment reference for more information). * * ( end auto-generated ) - * + * *

Advanced

* Draw a cubic bezier curve. The first and last points are * the on-curve points. The middle two are the 'control' points, @@ -10831,7 +10831,7 @@ public class PApplet extends Applet * P2D renderer does not use this information. * * ( end auto-generated ) - * + * * @webref shape:curves * @param detail resolution of the curves * @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float) @@ -10856,7 +10856,7 @@ public class PApplet extends Applet * recognizable and as values increase in magnitude, they will continue to deform. * * ( end auto-generated ) - * + * * @webref shape:curves * @param tightness amount of deformation from the original vertices * @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float) @@ -10944,7 +10944,7 @@ public class PApplet extends Applet * smoothing altogether. * * ( end auto-generated ) - * + * * @webref shape:attributes * @see PGraphics#noSmooth() * @see PGraphics#hint(int) @@ -10994,7 +10994,7 @@ public class PApplet extends Applet * Processing is a case-sensitive language. * * ( end auto-generated ) - * + * * @webref image:loading_displaying * @param mode either CORNER, CORNERS, or CENTER * @see PApplet#loadImage(String, String) @@ -11035,7 +11035,7 @@ public class PApplet extends Applet * This function will maintain transparency for GIF and PNG images. * * ( end auto-generated ) - * + * *

Advanced

* Starting with release 0124, when using the default (JAVA2D) renderer, * smooth() will also improve image quality of resized images. @@ -11090,7 +11090,7 @@ public class PApplet extends Applet * Processing is a case sensitive language. * * ( end auto-generated ) - * + * * @webref shape:loading_displaying * @param mode either CORNER, CORNERS, CENTER * @see PGraphics#shape(PShape) @@ -11136,7 +11136,7 @@ public class PApplet extends Applet * yet support shapes that have holes or complicated breaks. * * ( end auto-generated ) - * + * * @webref shape:loading_displaying * @param shape the shape to display * @param x x-coordinate of the shape @@ -11188,7 +11188,7 @@ public class PApplet extends Applet * if you change the size of the font. * * ( end auto-generated ) - * + * * @webref typography:attributes * @param alignX horizontal alignment, either LEFT, CENTER, or RIGHT * @param alignY vertical alignment, either TOP, BOTTOM, CENTER, or BASELINE @@ -11211,7 +11211,7 @@ public class PApplet extends Applet * will give you the total height of the line. * * ( end auto-generated ) - * + * * @webref typography:metrics * @see PGraphics#textDescent() */ @@ -11229,7 +11229,7 @@ public class PApplet extends Applet * textDescent() values will give you the total height of the line. * * ( end auto-generated ) - * + * * @webref typography:metrics * @see PGraphics#textAscent() */ @@ -11288,7 +11288,7 @@ public class PApplet extends Applet * will be used in all subsequent calls to the text() function. * * ( end auto-generated ) - * + * * @webref typography:attributes * @param leading the size in pixels for spacing between lines * @see PApplet#loadFont(String) @@ -11304,23 +11304,23 @@ public class PApplet extends Applet /** * ( begin auto-generated from textMode.xml ) - * - * Sets the way text draws to the screen. In the default configuration, the - * MODEL mode, it's possible to rotate, scale, and place letters in + * + * Sets the way text draws to the screen. In the default configuration, the + * MODEL mode, it's possible to rotate, scale, and place letters in * two and three dimensional space.
*
- * The SHAPE mode draws text using the the glyph outlines of - * individual characters rather than as textures. This mode is only - * supported with the PDF and P3D renderer settings. With the - * PDF renderer, you must call textMode(SHAPE) before any - * other drawing occurs. If the outlines are not available, then - * textMode(SHAPE) will be ignored and textMode(MODEL) will + * The SHAPE mode draws text using the the glyph outlines of + * individual characters rather than as textures. This mode is only + * supported with the PDF and P3D renderer settings. With the + * PDF renderer, you must call textMode(SHAPE) before any + * other drawing occurs. If the outlines are not available, then + * textMode(SHAPE) will be ignored and textMode(MODEL) will * be used instead.
*
- * The textMode(SHAPE) option in P3D can be combined with - * beginRaw() to write vector-accurate text to 2D and 3D output - * files, for instance DXF or PDF. The SHAPE mode is - * not currently optimized for P3D, so if recording shape data, use + * The textMode(SHAPE) option in P3D can be combined with + * beginRaw() to write vector-accurate text to 2D and 3D output + * files, for instance DXF or PDF. The SHAPE mode is + * not currently optimized for P3D, so if recording shape data, use * textMode(MODEL) until you're ready to capture the geometry with beginRaw(). * * ( end auto-generated ) @@ -11347,7 +11347,7 @@ public class PApplet extends Applet * calls to the text() function. Font size is measured in units of pixels. * * ( end auto-generated ) - * + * * @webref typography:attributes * @param size the size of the letters in units of pixels * @see PApplet#loadFont(String) @@ -11572,18 +11572,18 @@ public class PApplet extends Applet /** * ( begin auto-generated from pushMatrix.xml ) - * - * Pushes the current transformation matrix onto the matrix stack. - * Understanding pushMatrix() and popMatrix() requires - * understanding the concept of a matrix stack. The pushMatrix() - * function saves the current coordinate system to the stack and - * popMatrix() restores the prior coordinate system. - * pushMatrix() and popMatrix() are used in conjuction with - * the other transformation functions and may be embedded to control the + * + * Pushes the current transformation matrix onto the matrix stack. + * Understanding pushMatrix() and popMatrix() requires + * understanding the concept of a matrix stack. The pushMatrix() + * function saves the current coordinate system to the stack and + * popMatrix() restores the prior coordinate system. + * pushMatrix() and popMatrix() are used in conjuction with + * the other transformation functions and may be embedded to control the * scope of the transformations. * * ( end auto-generated ) - * + * * @webref transform * @see PGraphics#popMatrix() * @see PGraphics#translate(float, float, float) @@ -11600,17 +11600,17 @@ public class PApplet extends Applet /** * ( begin auto-generated from popMatrix.xml ) - * - * Pops the current transformation matrix off the matrix stack. - * Understanding pushing and popping requires understanding the concept of - * a matrix stack. The pushMatrix() function saves the current - * coordinate system to the stack and popMatrix() restores the prior - * coordinate system. pushMatrix() and popMatrix() are used - * in conjuction with the other transformation functions and may be + * + * Pops the current transformation matrix off the matrix stack. + * Understanding pushing and popping requires understanding the concept of + * a matrix stack. The pushMatrix() function saves the current + * coordinate system to the stack and popMatrix() restores the prior + * coordinate system. pushMatrix() and popMatrix() are used + * in conjuction with the other transformation functions and may be * embedded to control the scope of the transformations. * * ( end auto-generated ) - * + * * @webref transform * @see PGraphics#pushMatrix() */ @@ -11637,7 +11637,7 @@ public class PApplet extends Applet * further controlled by the pushMatrix() and popMatrix(). * * ( end auto-generated ) - * + * * @webref transform * @param tx left/right translation * @param ty up/down translation @@ -11684,7 +11684,7 @@ public class PApplet extends Applet * the pushMatrix() and popMatrix(). * * ( end auto-generated ) - * + * * @webref transform * @param angle angle of rotation specified in radians * @see PGraphics#popMatrix() @@ -11718,7 +11718,7 @@ public class PApplet extends Applet * as shown in the example above. * * ( end auto-generated ) - * + * * @webref transform * @param angle angle of rotation specified in radians * @see PGraphics#popMatrix() @@ -11752,7 +11752,7 @@ public class PApplet extends Applet * as shown in the examples above. * * ( end auto-generated ) - * + * * @webref transform * @param angle angle of rotation specified in radians * @see PGraphics#popMatrix() @@ -11786,7 +11786,7 @@ public class PApplet extends Applet * as shown in the examples above. * * ( end auto-generated ) - * + * * @webref transform * @param angle angle of rotation specified in radians * @see PGraphics#popMatrix() @@ -11806,9 +11806,9 @@ public class PApplet extends Applet /** *

Advanced

* Rotate about a vector in space. Same as the glRotatef() function. - * @param vx - * @param vy - * @param vz + * @param vx + * @param vy + * @param vz */ public void rotate(float angle, float vx, float vy, float vz) { if (recorder != null) recorder.rotate(angle, vx, vy, vz); @@ -11833,7 +11833,7 @@ public class PApplet extends Applet * can be further controlled by pushMatrix() and popMatrix(). * * ( end auto-generated ) - * + * * @webref transform * @param s percentage to scale the object * @see PGraphics#popMatrix() @@ -11896,7 +11896,7 @@ public class PApplet extends Applet * the pushMatrix() and popMatrix() functions. * * ( end auto-generated ) - * + * * @webref transform * @param angle angle of shear specified in radians * @see PGraphics#popMatrix() @@ -11931,7 +11931,7 @@ public class PApplet extends Applet * the pushMatrix() and popMatrix() functions. * * ( end auto-generated ) - * + * * @webref transform * @param angle angle of shear specified in radians * @see PGraphics#popMatrix() @@ -11954,7 +11954,7 @@ public class PApplet extends Applet * function in OpenGL is glLoadIdentity(). * * ( end auto-generated ) - * + * * @webref transform * @see PGraphics#pushMatrix() * @see PGraphics#popMatrix() @@ -11976,7 +11976,7 @@ public class PApplet extends Applet * function in OpenGL is glMultMatrix(). * * ( end auto-generated ) - * + * * @webref transform * @source * @see PGraphics#pushMatrix() @@ -12094,7 +12094,7 @@ public class PApplet extends Applet * of Processing). * * ( end auto-generated ) - * + * * @webref transform * @see PGraphics#pushMatrix() * @see PGraphics#popMatrix() @@ -12128,7 +12128,7 @@ public class PApplet extends Applet * endCamera() cannot be nested. * * ( end auto-generated ) - * + * * @webref lights_camera:camera * @see PGraphics#camera() * @see PGraphics#endCamera() @@ -12151,7 +12151,7 @@ public class PApplet extends Applet * beginCamera() for a description of how the functions are used. * * ( end auto-generated ) - * + * * @webref lights_camera:camera * @see PGraphics#camera(float, float, float, float, float, float, float, float, float) */ @@ -12163,19 +12163,19 @@ public class PApplet extends Applet /** * ( begin auto-generated from camera.xml ) - * - * Sets the position of the camera through setting the eye position, the - * center of the scene, and which axis is facing upward. Moving the eye - * position and the direction it is pointing (the center of the scene) - * allows the images to be seen from different angles. The version without - * any parameters sets the camera to the default position, pointing to the - * center of the display window with the Y axis as up. The default values - * are camera(width/2.0, height/2.0, (height/2.0) / tan(PI*30.0 / - * 180.0), width/2.0, height/2.0, 0, 0, 1, 0). This function is similar + * + * Sets the position of the camera through setting the eye position, the + * center of the scene, and which axis is facing upward. Moving the eye + * position and the direction it is pointing (the center of the scene) + * allows the images to be seen from different angles. The version without + * any parameters sets the camera to the default position, pointing to the + * center of the display window with the Y axis as up. The default values + * are camera(width/2.0, height/2.0, (height/2.0) / tan(PI*30.0 / + * 180.0), width/2.0, height/2.0, 0, 0, 1, 0). This function is similar * to gluLookAt() in OpenGL, but it first clears the current camera settings. * * ( end auto-generated ) - * + * * @webref lights_camera:camera * @see PGraphics#endCamera() * @see PGraphics#frustum(float, float, float, float, float, float) @@ -12234,7 +12234,7 @@ public class PApplet extends Applet * -10, 10). * * ( end auto-generated ) - * + * * @webref lights_camera:camera */ public void ortho() { @@ -12283,7 +12283,7 @@ public class PApplet extends Applet * cameraZ*10.0) where cameraZ is ((height/2.0) / tan(PI*60.0/360.0)); * * ( end auto-generated ) - * + * * @webref lights_camera:camera */ public void perspective() { @@ -12312,7 +12312,7 @@ public class PApplet extends Applet * than muliplying itself with it. * * ( end auto-generated ) - * + * * @webref lights_camera:camera * @param left left coordinate of the clipping plane * @param right right coordinate of the clipping plane @@ -12339,7 +12339,7 @@ public class PApplet extends Applet * the bottom of Processing). * * ( end auto-generated ) - * + * * @webref lights_camera:camera * @see PGraphics#camera(float, float, float, float, float, float, float, float, float) */ @@ -12356,7 +12356,7 @@ public class PApplet extends Applet * where it will appear on a (two-dimensional) screen. * * ( end auto-generated ) - * + * * @webref lights_camera:coordinates * @param x 3D x-coordinate to be mapped * @param y 3D y-coordinate to be mapped @@ -12375,7 +12375,7 @@ public class PApplet extends Applet * where it will appear on a (two-dimensional) screen. * * ( end auto-generated ) - * + * * @webref lights_camera:coordinates * @param x 3D x-coordinate to be mapped * @param y 3D y-coordinate to be mapped @@ -12410,7 +12410,7 @@ public class PApplet extends Applet * where it will appear on a (two-dimensional) screen. * * ( end auto-generated ) - * + * * @webref lights_camera:coordinates * @param x 3D x-coordinate to be mapped * @param y 3D y-coordinate to be mapped @@ -12432,15 +12432,15 @@ public class PApplet extends Applet * to place an object in space relative to the location of the original * point once the transformations are no longer in use. *

- * In the example, the modelX(), modelY(), and - * modelZ() functions record the location of a box in space after - * being placed using a series of translate and rotate commands. After - * popMatrix() is called, those transformations no longer apply, but the - * (x, y, z) coordinate returned by the model functions is used to place + * In the example, the modelX(), modelY(), and + * modelZ() functions record the location of a box in space after + * being placed using a series of translate and rotate commands. After + * popMatrix() is called, those transformations no longer apply, but the + * (x, y, z) coordinate returned by the model functions is used to place * another box in the same location. * * ( end auto-generated ) - * + * * @webref lights_camera:coordinates * @param x 3D x-coordinate to be mapped * @param y 3D y-coordinate to be mapped @@ -12455,22 +12455,22 @@ public class PApplet extends Applet /** * ( begin auto-generated from modelY.xml ) - * - * Returns the three-dimensional X, Y, Z position in model space. This - * returns the Y value for a given coordinate based on the current set of - * transformations (scale, rotate, translate, etc.) The Y value can be used - * to place an object in space relative to the location of the original - * point once the transformations are no longer in use.
+ * + * Returns the three-dimensional X, Y, Z position in model space. This + * returns the Y value for a given coordinate based on the current set of + * transformations (scale, rotate, translate, etc.) The Y value can be used + * to place an object in space relative to the location of the original + * point once the transformations are no longer in use.
*
- * In the example, the modelX(), modelY(), and - * modelZ() functions record the location of a box in space after - * being placed using a series of translate and rotate commands. After - * popMatrix() is called, those transformations no longer apply, but the - * (x, y, z) coordinate returned by the model functions is used to place + * In the example, the modelX(), modelY(), and + * modelZ() functions record the location of a box in space after + * being placed using a series of translate and rotate commands. After + * popMatrix() is called, those transformations no longer apply, but the + * (x, y, z) coordinate returned by the model functions is used to place * another box in the same location. * * ( end auto-generated ) - * + * * @webref lights_camera:coordinates * @param x 3D x-coordinate to be mapped * @param y 3D y-coordinate to be mapped @@ -12485,22 +12485,22 @@ public class PApplet extends Applet /** * ( begin auto-generated from modelZ.xml ) - * - * Returns the three-dimensional X, Y, Z position in model space. This - * returns the Z value for a given coordinate based on the current set of - * transformations (scale, rotate, translate, etc.) The Z value can be used - * to place an object in space relative to the location of the original + * + * Returns the three-dimensional X, Y, Z position in model space. This + * returns the Z value for a given coordinate based on the current set of + * transformations (scale, rotate, translate, etc.) The Z value can be used + * to place an object in space relative to the location of the original * point once the transformations are no longer in use.
*
- * In the example, the modelX(), modelY(), and - * modelZ() functions record the location of a box in space after - * being placed using a series of translate and rotate commands. After - * popMatrix() is called, those transformations no longer apply, but the - * (x, y, z) coordinate returned by the model functions is used to place + * In the example, the modelX(), modelY(), and + * modelZ() functions record the location of a box in space after + * being placed using a series of translate and rotate commands. After + * popMatrix() is called, those transformations no longer apply, but the + * (x, y, z) coordinate returned by the model functions is used to place * another box in the same location. * * ( end auto-generated ) - * + * * @webref lights_camera:coordinates * @param x 3D x-coordinate to be mapped * @param y 3D y-coordinate to be mapped @@ -12532,7 +12532,7 @@ public class PApplet extends Applet * emissive(), specular(), shininess(), ambient() * * ( end auto-generated ) - * + * * @webref structure * @see PGraphics#popStyle() */ @@ -12554,7 +12554,7 @@ public class PApplet extends Applet * provide more control (see the second example above for a demonstration.) * * ( end auto-generated ) - * + * * @webref structure * @see PGraphics#pushStyle() */ @@ -12586,7 +12586,7 @@ public class PApplet extends Applet * may not go higher than 10 pixels. * * ( end auto-generated ) - * + * * @webref shape:attributes * @param weight the weight (in pixels) of the stroke * @see PGraphics#stroke(int, float) @@ -12613,7 +12613,7 @@ public class PApplet extends Applet * size() reference. * * ( end auto-generated ) - * + * * @webref shape:attributes * @param join either MITER, BEVEL, ROUND * @see PGraphics#stroke(int, float) @@ -12691,7 +12691,7 @@ public class PApplet extends Applet * maximum value is 255. * * ( end auto-generated ) - * + * * @param rgb color value in hexadecimal notation * @see PGraphics#noStroke() * @see PGraphics#fill(int, float) @@ -12754,7 +12754,7 @@ public class PApplet extends Applet * displaying images with their original hues. * * ( end auto-generated ) - * + * * @webref image:loading_displaying * @usage web_application * @see PGraphics#tint(float, float, float, float) @@ -12770,30 +12770,30 @@ public class PApplet extends Applet * ( begin auto-generated from tint.xml ) * * Sets the fill value for displaying images. Images can be tinted to - * specified colors or made transparent by setting the alpha.
+ * specified colors or made transparent by setting the alpha.
*
* To make an image transparent, but not change it's color, use white as * the tint color and specify an alpha value. For instance, tint(255, 128) - * will make an image 50% transparent (unless colorMode() has been + * will make an image 50% transparent (unless colorMode() has been * used).
*
- * When using hexadecimal notation to specify a color, use "#" or "0x" - * before the values (e.g. #CCFFAA, 0xFFCCFFAA). The # syntax uses six - * digits to specify a color (the way colors are specified in HTML and - * CSS). When using the hexadecimal notation starting with "0x", the - * hexadecimal value must be specified with eight characters; the first two - * characters define the alpha component and the remainder the red, green, + * When using hexadecimal notation to specify a color, use "#" or "0x" + * before the values (e.g. #CCFFAA, 0xFFCCFFAA). The # syntax uses six + * digits to specify a color (the way colors are specified in HTML and + * CSS). When using the hexadecimal notation starting with "0x", the + * hexadecimal value must be specified with eight characters; the first two + * characters define the alpha component and the remainder the red, green, * and blue components.
*
* The value for the parameter "gray" must be less than or equal to the * current maximum value as specified by colorMode(). The default - * maximum value is 255.
+ * maximum value is 255.
*
- * The tint() function is also used to control the coloring of - * textures in 3D. - * + * The tint() function is also used to control the coloring of + * textures in 3D. + * * ( end auto-generated ) - * + * * @webref image:loading_displaying * @usage web_application * @param rgb color value in hexadecimal notation @@ -12858,7 +12858,7 @@ public class PApplet extends Applet * are called, nothing will be drawn to the screen. * * ( end auto-generated ) - * + * * @webref color:setting * @usage web_application * @see PGraphics#fill(float, float, float, float) @@ -12960,7 +12960,7 @@ public class PApplet extends Applet * and shininess() in setting the material properties of shapes. * * ( end auto-generated ) - * + * * @webref lights_camera:material_properties * @usage web_application * @param rgb any value of the color datatype @@ -13005,7 +13005,7 @@ public class PApplet extends Applet * setting the material properties of shapes. * * ( end auto-generated ) - * + * * @webref lights_camera:material_properties * @usage web_application * @param rgb color to set @@ -13048,7 +13048,7 @@ public class PApplet extends Applet * setting the material properties of shapes. * * ( end auto-generated ) - * + * * @webref lights_camera:material_properties * @usage web_application * @param shine degree of shininess @@ -13071,7 +13071,7 @@ public class PApplet extends Applet * properties of shapes. * * ( end auto-generated ) - * + * * @webref lights_camera:material_properties * @usage web_application * @param rgb color to set @@ -13117,7 +13117,7 @@ public class PApplet extends Applet * through the loop. * * ( end auto-generated ) - * + * * @webref lights_camera:lights * @usage web_application * @see PGraphics#ambientLight(float, float, float, float, float, float) @@ -13134,14 +13134,14 @@ public class PApplet extends Applet /** * ( begin auto-generated from noLights.xml ) - * - * Disable all lighting. Lighting is turned off by default and enabled with - * the lights() function. This function can be used to disable - * lighting so that 2D geometry (which does not require lighting) can be + * + * Disable all lighting. Lighting is turned off by default and enabled with + * the lights() function. This function can be used to disable + * lighting so that 2D geometry (which does not require lighting) can be * drawn after a set of lighted 3D geometry. * * ( end auto-generated ) - * + * * @webref lights_camera:lights * @usage web_application * @see PGraphics#lights() @@ -13165,7 +13165,7 @@ public class PApplet extends Applet * parameters is determined by the current color mode. * * ( end auto-generated ) - * + * * @webref lights_camera:lights * @usage web_application * @param red red or hue value (depending on current color mode) @@ -13389,7 +13389,7 @@ public class PApplet extends Applet * the main drawing surface, however they will work properly with createGraphics(). * * ( end auto-generated ) - * + * *

Advanced

*

Clear the background with a color that includes an alpha value. This can * only be used with objects created by createGraphics(), because the main @@ -13569,7 +13569,7 @@ public class PApplet extends Applet * & 0xFF;

* * ( end auto-generated ) - * + * * @webref color:creating_reading * @usage web_application * @param what any value of the color datatype @@ -13600,7 +13600,7 @@ public class PApplet extends Applet * myColor >> 8 & 0xFF; * * ( end auto-generated ) - * + * * @webref color:creating_reading * @usage web_application * @param what any value of the color datatype @@ -13631,7 +13631,7 @@ public class PApplet extends Applet * & 0xFF; * * ( end auto-generated ) - * + * * @webref color:creating_reading * @usage web_application * @param what any value of the color datatype @@ -13696,7 +13696,7 @@ public class PApplet extends Applet * Extracts the brightness value from a color. * * ( end auto-generated ) - * + * * @webref color:creating_reading * @usage web_application * @param what any value of the color datatype @@ -13721,7 +13721,7 @@ public class PApplet extends Applet * point, 0.5 is half-way in between, etc. * * ( end auto-generated ) - * + * * @webref color:creating_reading * @usage web_application * @param c1 interpolate from this color @@ -13807,7 +13807,7 @@ public class PApplet extends Applet /** * Return true if this renderer does rendering through OpenGL. Defaults to false. - */ + */ public boolean isGL() { return g.isGL(); } @@ -13847,7 +13847,7 @@ public class PApplet extends Applet * PGraphicsJava2D, or resized image data and OpenGL texture indices for * PGraphicsOpenGL. * @param renderer The PGraphics renderer associated to the image - * @param storage The metadata required by the renderer + * @param storage The metadata required by the renderer */ public void setCache(PGraphics renderer, Object storage) { if (recorder != null) recorder.setCache(renderer, storage); @@ -13882,7 +13882,7 @@ public class PApplet extends Applet * Store parameters for a renderer that requires extra metadata of * some kind. * @param renderer The PGraphics renderer associated to the image - * @param storage The parameters required by the renderer + * @param storage The parameters required by the renderer */ public void setParams(PGraphics renderer, Object params) { if (recorder != null) recorder.setParams(renderer, params); @@ -13912,26 +13912,26 @@ public class PApplet extends Applet /** * ( begin auto-generated from PImage_get.xml ) - * - * Reads the color of any pixel or grabs a section of an image. If no - * parameters are specified, the entire image is returned. Use the x - * and y parameters to get the value of one pixel. Get a section of - * the display window by specifying an additional width and - * height parameter. When getting an image, the x and - * y parameters define the coordinates for the upper-left corner of + * + * Reads the color of any pixel or grabs a section of an image. If no + * parameters are specified, the entire image is returned. Use the x + * and y parameters to get the value of one pixel. Get a section of + * the display window by specifying an additional width and + * height parameter. When getting an image, the x and + * y parameters define the coordinates for the upper-left corner of * the image, regardless of the current imageMode().
*
- * If the pixel requested is outside of the image window, black is - * returned. The numbers returned are scaled according to the current color - * ranges, but only RGB values are returned by this function. For example, - * even though you may have drawn a shape with colorMode(HSB), the + * If the pixel requested is outside of the image window, black is + * returned. The numbers returned are scaled according to the current color + * ranges, but only RGB values are returned by this function. For example, + * even though you may have drawn a shape with colorMode(HSB), the * numbers returned will be in RGB format.
*
- * Getting the color of a single pixel with get(x, y) is easy, but - * not as fast as grabbing the data directly from pixels[]. The - * equivalent statement to get(x, y) using pixels[] is + * Getting the color of a single pixel with get(x, y) is easy, but + * not as fast as grabbing the data directly from pixels[]. The + * equivalent statement to get(x, y) using pixels[] is * pixels[y*width+x]. See the reference for pixels[] for more information. - * + * * ( end auto-generated ) * *

Advanced

@@ -13951,7 +13951,7 @@ public class PApplet extends Applet * is inside the bounds, and then has to check to see what image * type it is. If you want things to be more efficient, access the * pixels[] array directly. - * + * * @webref image:pixels * @brief Reads the color of any pixel or grabs a rectangle of pixels * @usage web_application @@ -13985,25 +13985,25 @@ public class PApplet extends Applet /** * ( begin auto-generated from PImage_set.xml ) - * - * Changes the color of any pixel or writes an image directly into the + * + * Changes the color of any pixel or writes an image directly into the * display window.
*
- * The x and y parameters specify the pixel to change and the - * color parameter specifies the color value. The color parameter is - * affected by the current color mode (the default is RGB values from 0 to - * 255). When setting an image, the x and y parameters define - * the coordinates for the upper-left corner of the image, regardless of + * The x and y parameters specify the pixel to change and the + * color parameter specifies the color value. The color parameter is + * affected by the current color mode (the default is RGB values from 0 to + * 255). When setting an image, the x and y parameters define + * the coordinates for the upper-left corner of the image, regardless of * the current imageMode(). *

- * Setting the color of a single pixel with set(x, y) is easy, but - * not as fast as putting the data directly into pixels[]. The - * equivalent statement to set(x, y, #000000) using pixels[] - * is pixels[y*width+x] = #000000. See the reference for + * Setting the color of a single pixel with set(x, y) is easy, but + * not as fast as putting the data directly into pixels[]. The + * equivalent statement to set(x, y, #000000) using pixels[] + * is pixels[y*width+x] = #000000. See the reference for * pixels[] for more information. - * + * * ( end auto-generated ) - * + * * @webref image:pixels * @brief writes a color to any pixel or writes an image into another * @usage web_application @@ -14036,18 +14036,18 @@ public class PApplet extends Applet /** * ( begin auto-generated from PImage_mask.xml ) - * - * Masks part of an image from displaying by loading another image and - * using it as an alpha channel. This mask image should only contain - * grayscale data, but only the blue color channel is used. The mask image + * + * Masks part of an image from displaying by loading another image and + * using it as an alpha channel. This mask image should only contain + * grayscale data, but only the blue color channel is used. The mask image * needs to be the same size as the image to which it is applied.
*
- * In addition to using a mask image, an integer array containing the alpha - * channel data can be specified directly. This method is useful for - * creating dynamically generated alpha masks. This array must be of the - * same length as the target image's pixels array and should contain only + * In addition to using a mask image, an integer array containing the alpha + * channel data can be specified directly. This method is useful for + * creating dynamically generated alpha masks. This array must be of the + * same length as the target image's pixels array and should contain only * grayscale data of values between 0-255. - * + * * ( end auto-generated ) * *

Advanced

@@ -14092,31 +14092,31 @@ public class PApplet extends Applet /** * ( begin auto-generated from PImage_filter.xml ) - * - * Filters an image as defined by one of the following modes:

THRESHOLD - converts the image to black and white pixels depending if - * they are above or below the threshold defined by the level parameter. - * The level must be between 0.0 (black) and 1.0(white). If no level is + * + * Filters an image as defined by one of the following modes:

THRESHOLD - converts the image to black and white pixels depending if + * they are above or below the threshold defined by the level parameter. + * The level must be between 0.0 (black) and 1.0(white). If no level is * specified, 0.5 is used.
*
* GRAY - converts any colors in the image to grayscale equivalents
*
* INVERT - sets each pixel to its inverse value
*
- * POSTERIZE - limits each channel of the image to the number of colors + * POSTERIZE - limits each channel of the image to the number of colors * specified as the level parameter
*
- * BLUR - executes a Guassian blur with the level parameter specifying the - * extent of the blurring. If no level parameter is used, the blur is + * BLUR - executes a Guassian blur with the level parameter specifying the + * extent of the blurring. If no level parameter is used, the blur is * equivalent to Guassian blur of radius 1
*
* OPAQUE - sets the alpha channel to entirely opaque
*
- * ERODE - reduces the light areas with the amount defined by the level + * ERODE - reduces the light areas with the amount defined by the level * parameter
*
* DILATE - increases the light areas with the amount defined by the level parameter - * + * * ( end auto-generated ) * *

Advanced

@@ -14151,17 +14151,17 @@ public class PApplet extends Applet /** * ( begin auto-generated from PImage_copy.xml ) - * - * Copies a region of pixels from one image into another. If the source and - * destination regions aren't the same size, it will automatically resize - * source pixels to fit the specified target region. No alpha information - * is used in the process, however if the source image has an alpha channel + * + * Copies a region of pixels from one image into another. If the source and + * destination regions aren't the same size, it will automatically resize + * source pixels to fit the specified target region. No alpha information + * is used in the process, however if the source image has an alpha channel * set, it will be copied as well. *

* As of release 0149, this function ignores imageMode(). - * + * * ( end auto-generated ) - * + * * @webref image:pixels * @brief Copies the entire image * @usage web_application @@ -14196,11 +14196,11 @@ public class PApplet extends Applet /** * ( begin auto-generated from blendColor.xml ) - * - * Blends two color values together based on the blending mode given as the - * MODE parameter. The possible modes are described in the reference + * + * Blends two color values together based on the blending mode given as the + * MODE parameter. The possible modes are described in the reference * for the blend() function. - * + * * ( end auto-generated ) *

Advanced

*
    @@ -14287,17 +14287,17 @@ public class PApplet extends Applet /** * ( begin auto-generated from PImage_blend.xml ) - * - * Blends a region of pixels into the image specified by the img - * parameter. These copies utilize full alpha channel support and a choice - * of the following modes to blend the colors of source pixels (A) with the + * + * Blends a region of pixels into the image specified by the img + * parameter. These copies utilize full alpha channel support and a choice + * of the following modes to blend the colors of source pixels (A) with the * ones of pixels in the destination image (B):
    *
    * BLEND - linear interpolation of colours: C = A*factor + B
    *
    * ADD - additive blending with white clip: C = min(A*factor + B, 255)
    *
    - * SUBTRACT - subtractive blending with black clip: C = max(B - A*factor, + * SUBTRACT - subtractive blending with black clip: C = max(B - A*factor, * 0)
    *
    * DARKEST - only the darkest colour succeeds: C = min(A*factor, B)
    @@ -14317,7 +14317,7 @@ public class PApplet extends Applet *
    * HARD_LIGHT - SCREEN when greater than 50% gray, MULTIPLY when lower.
    *
    - * SOFT_LIGHT - Mix of DARKEST and LIGHTEST. + * SOFT_LIGHT - Mix of DARKEST and LIGHTEST. * Works like OVERLAY, but not as harsh.
    *
    * DODGE - Lightens light tones and increases contrast, ignores darks. @@ -14326,14 +14326,14 @@ public class PApplet extends Applet * BURN - Darker areas are applied, increasing contrast, ignores lights. * Called "Color Burn" in Illustrator and Photoshop.
    *
    - * All modes use the alpha information (highest byte) of source image - * pixels as the blending factor. If the source and destination regions are - * different sizes, the image will be automatically resized to match the - * destination size. If the srcImg parameter is not used, the + * All modes use the alpha information (highest byte) of source image + * pixels as the blending factor. If the source and destination regions are + * different sizes, the image will be automatically resized to match the + * destination size. If the srcImg parameter is not used, the * display window is used as the source image.
    *
    * As of release 0149, this function ignores imageMode(). - * + * * ( end auto-generated ) * * @webref image:pixels diff --git a/core/src/processing/core/PConstants.java b/core/src/processing/core/PConstants.java index cb1d98215..1706f44b5 100644 --- a/core/src/processing/core/PConstants.java +++ b/core/src/processing/core/PConstants.java @@ -39,24 +39,24 @@ import java.awt.event.KeyEvent; */ public interface PConstants { // render & flush modes (in P3D) - + static public final int IMMEDIATE = 0; - static public final int RETAINED = 1; - + static public final int RETAINED = 1; + static public final int FLUSH_CONTINUOUSLY = 0; - static public final int FLUSH_WHEN_FULL = 1; - + static public final int FLUSH_WHEN_FULL = 1; + // shaders - + static public final int FILL_SHADER_SIMPLE = 0; static public final int FILL_SHADER_LIT = 1; static public final int FILL_SHADER_TEX = 2; static public final int FILL_SHADER_FULL = 3; static public final int LINE_SHADER = 4; - static public final int POINT_SHADER = 5; - + static public final int POINT_SHADER = 5; + // vertex fields - + static public final int X = 0; // model coords xyz (formerly MX/MY/MZ) static public final int Y = 1; static public final int Z = 2; @@ -134,15 +134,15 @@ public interface PConstants { // renderers known to processing.core - static final String P2D = "processing.core.PGraphicsJava2D"; - static final String P3D = "processing.opengl.PGraphicsOpenGL"; static final String JAVA2D = "processing.core.PGraphicsJava2D"; + static final String P2D = "processing.opengl.PGraphics2D"; + static final String P3D = "processing.opengl.PGraphics3D"; static final String OPENGL = "processing.opengl.PGraphicsOpenGL"; static final String PDF = "processing.pdf.PGraphicsPDF"; static final String DXF = "processing.dxf.RawDXF"; static final String LWJGL = "processing.lwjgl.PGraphicsLWJGL"; - + // platform IDs for PApplet.platform static final int OTHER = 0; @@ -178,23 +178,23 @@ public interface PConstants { static final int MIN_INT = Integer.MIN_VALUE; // shapes - - static public final int VERTEX = 0; - static public final int BEZIER_VERTEX = 1; - static public final int QUAD_BEZIER_VERTEX = 2; + + static public final int VERTEX = 0; + static public final int BEZIER_VERTEX = 1; + static public final int QUAD_BEZIER_VERTEX = 2; static public final int CURVE_VERTEX = 3; - static public final int BREAK = 4; - + static public final int BREAK = 4; + // useful goodness /** * ( begin auto-generated from PI.xml ) - * - * PI is a mathematical constant with the value 3.14159265358979323846. It - * is the ratio of the circumference of a circle to its diameter. It is - * useful in combination with the trigonometric functions sin() and - * cos(). - * + * + * PI is a mathematical constant with the value 3.14159265358979323846. It + * is the ratio of the circumference of a circle to its diameter. It is + * useful in combination with the trigonometric functions sin() and + * cos(). + * * ( end auto-generated ) * @webref constants * @see PConstants#HALF_PI @@ -205,12 +205,12 @@ public interface PConstants { static final float PI = (float) Math.PI; /** * ( begin auto-generated from HALF_PI.xml ) - * - * HALF_PI is a mathematical constant with the value - * 1.57079632679489661923. It is half the ratio of the circumference of a - * circle to its diameter. It is useful in combination with the - * trigonometric functions sin() and cos(). - * + * + * HALF_PI is a mathematical constant with the value + * 1.57079632679489661923. It is half the ratio of the circumference of a + * circle to its diameter. It is useful in combination with the + * trigonometric functions sin() and cos(). + * * ( end auto-generated ) * @webref constants * @see PConstants#PI @@ -221,12 +221,12 @@ public interface PConstants { static final float THIRD_PI = PI / 3.0f; /** * ( begin auto-generated from QUARTER_PI.xml ) - * - * QUARTER_PI is a mathematical constant with the value 0.7853982. It is - * one quarter the ratio of the circumference of a circle to its diameter. - * It is useful in combination with the trigonometric functions - * sin() and cos(). - * + * + * QUARTER_PI is a mathematical constant with the value 0.7853982. It is + * one quarter the ratio of the circumference of a circle to its diameter. + * It is useful in combination with the trigonometric functions + * sin() and cos(). + * * ( end auto-generated ) * @webref constants * @see PConstants#PI @@ -236,12 +236,12 @@ public interface PConstants { static final float QUARTER_PI = PI / 4.0f; /** * ( begin auto-generated from TWO_PI.xml ) - * - * TWO_PI is a mathematical constant with the value 6.28318530717958647693. - * It is twice the ratio of the circumference of a circle to its diameter. - * It is useful in combination with the trigonometric functions - * sin() and cos(). - * + * + * TWO_PI is a mathematical constant with the value 6.28318530717958647693. + * It is twice the ratio of the circumference of a circle to its diameter. + * It is useful in combination with the trigonometric functions + * sin() and cos(). + * * ( end auto-generated ) * @webref constants * @see PConstants#PI @@ -379,8 +379,8 @@ public interface PConstants { static public final int NON_STROKED_SHAPE = 60; static public final int STROKED_SHAPE = 61; - - + + // shape closing modes static final int OPEN = 1; @@ -560,16 +560,16 @@ public interface PConstants { static final int ENABLE_NATIVE_FONTS = 1; static final int DISABLE_NATIVE_FONTS = -1; - + static final int DISABLE_DEPTH_TEST = 2; static final int ENABLE_DEPTH_TEST = -2; - + static final int ENABLE_DEPTH_SORT = 3; static final int DISABLE_DEPTH_SORT = -3; - + static final int DISABLE_OPENGL_ERROR_REPORT = 4; static final int ENABLE_OPENGL_ERROR_REPORT = -4; - + static final int ENABLE_ACCURATE_TEXTURES = 5; static final int DISABLE_ACCURATE_TEXTURES = -5; @@ -583,11 +583,11 @@ public interface PConstants { static final int ENABLE_TEXTURE_CACHE = -8; static final int DISABLE_TRANSFORM_CACHE = 9; - static final int ENABLE_TRANSFORM_CACHE = -9; + static final int ENABLE_TRANSFORM_CACHE = -9; static final int ENABLE_PERSPECTIVE_CORRECTED_LINES = 10; - static final int DISABLE_PERSPECTIVE_CORRECTED_LINES = -10; - + static final int DISABLE_PERSPECTIVE_CORRECTED_LINES = -10; + static final int HINT_COUNT = 11; // error messages diff --git a/core/todo.txt b/core/todo.txt index bc1f4ac5d..6e1aff735 100644 --- a/core/todo.txt +++ b/core/todo.txt @@ -13,6 +13,8 @@ o http://code.google.com/p/processing/issues/detail?id=715 X change screenWidth/Height to displayWidth/Height _ update wiki.processing.org/w/Window_Size_and_Full_Screen +_ add createGraphics() with no renderer param to point to JAVA2D + fixed in 2.0a5 A OpenGL noSmooth() does not work A http://code.google.com/p/processing/issues/detail?id=328 diff --git a/java/libraries/opengl/src/processing/opengl/PGraphics2D.java b/java/libraries/opengl/src/processing/opengl/PGraphics2D.java new file mode 100644 index 000000000..26deab87b --- /dev/null +++ b/java/libraries/opengl/src/processing/opengl/PGraphics2D.java @@ -0,0 +1,27 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2012 Ben Fry and Casey Reas + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + */ + +package processing.opengl; + + +public class PGraphics2D extends PGraphicsOpenGL { +} \ No newline at end of file diff --git a/java/libraries/opengl/src/processing/opengl/PGraphics3D.java b/java/libraries/opengl/src/processing/opengl/PGraphics3D.java new file mode 100644 index 000000000..ca925692e --- /dev/null +++ b/java/libraries/opengl/src/processing/opengl/PGraphics3D.java @@ -0,0 +1,27 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2012 Ben Fry and Casey Reas + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + */ + +package processing.opengl; + + +public class PGraphics3D extends PGraphicsOpenGL { +} \ No newline at end of file diff --git a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java index b942ba9d4..bc56ee427 100644 --- a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java +++ b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java @@ -3,13 +3,11 @@ /* Part of the Processing project - http://processing.org - Copyright (c) 2011 Andres Colubri - Copyright (c) 2004-10 Ben Fry and Casey Reas + Copyright (c) 2004-12 Ben Fry and Casey Reas This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. + License version 2.1 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,7 +18,7 @@ Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ + */ package processing.opengl; @@ -44,26 +42,26 @@ import java.util.Stack; /** * OpenGL renderer. - * + * */ public class PGraphicsOpenGL extends PGraphics { /** Interface between Processing and OpenGL */ public PGL pgl; - + /** The PApplet renderer. For the primary surface, pg == this. */ protected PGraphicsOpenGL pg; - // ........................................................ - - // Basic rendering parameters: - - protected int flushMode = FLUSH_WHEN_FULL; - protected int vboMode = PGL.GL_STATIC_DRAW; - - // ........................................................ - - // VBOs for immediate rendering: - + // ........................................................ + + // Basic rendering parameters: + + protected int flushMode = FLUSH_WHEN_FULL; + protected int vboMode = PGL.GL_STATIC_DRAW; + + // ........................................................ + + // VBOs for immediate rendering: + public int glFillVertexBufferID; public int glFillColorBufferID; public int glFillNormalBufferID; @@ -71,83 +69,83 @@ public class PGraphicsOpenGL extends PGraphics { public int glFillAmbientBufferID; public int glFillSpecularBufferID; public int glFillEmissiveBufferID; - public int glFillShininessBufferID; - public int glFillIndexBufferID; + public int glFillShininessBufferID; + public int glFillIndexBufferID; protected boolean fillVBOsCreated = false; - + public int glLineVertexBufferID; public int glLineColorBufferID; public int glLineDirWidthBufferID; - public int glLineIndexBufferID; + public int glLineIndexBufferID; protected boolean lineVBOsCreated = false; - + public int glPointVertexBufferID; public int glPointColorBufferID; public int glPointSizeBufferID; - public int glPointIndexBufferID; + public int glPointIndexBufferID; protected boolean pointVBOsCreated = false; - - // ........................................................ - + + // ........................................................ + // GL parameters - + static protected boolean glParamsRead = false; - + /** Extensions used by Processing */ static public boolean npotTexSupported; static public boolean mipmapGeneration; static public boolean fboMultisampleSupported; static public boolean packedDepthStencilSupported; - static public boolean blendEqSupported; - - /** Some hardware limits */ + static public boolean blendEqSupported; + + /** Some hardware limits */ static public int maxTextureSize; static public int maxSamples; static public float maxPointSize; static public float maxLineWidth; static public int depthBits; static public int stencilBits; - + /** OpenGL information strings */ static public String OPENGL_VENDOR; static public String OPENGL_RENDERER; - static public String OPENGL_VERSION; + static public String OPENGL_VERSION; static public String OPENGL_EXTENSIONS; - - // ........................................................ - + + // ........................................................ + // GL objects: - + static protected HashMap glTextureObjects = new HashMap(); static protected HashMap glVertexBuffers = new HashMap(); static protected HashMap glFrameBuffers = new HashMap(); - static protected HashMap glRenderBuffers = new HashMap(); + static protected HashMap glRenderBuffers = new HashMap(); static protected HashMap glslPrograms = new HashMap(); static protected HashMap glslVertexShaders = new HashMap(); static protected HashMap glslFragmentShaders = new HashMap(); - + // ........................................................ - - // Shaders - + + // Shaders + static protected URL defFillShaderVertSimpleURL = PGraphicsOpenGL.class.getResource("FillShaderVertSimple.glsl"); static protected URL defFillShaderVertTexURL = PGraphicsOpenGL.class.getResource("FillShaderVertTex.glsl"); static protected URL defFillShaderVertLitURL = PGraphicsOpenGL.class.getResource("FillShaderVertLit.glsl"); - static protected URL defFillShaderVertFullURL = PGraphicsOpenGL.class.getResource("FillShaderVertFull.glsl"); + static protected URL defFillShaderVertFullURL = PGraphicsOpenGL.class.getResource("FillShaderVertFull.glsl"); static protected URL defFillShaderFragNoTexURL = PGraphicsOpenGL.class.getResource("FillShaderFragNoTex.glsl"); - static protected URL defFillShaderFragTexURL = PGraphicsOpenGL.class.getResource("FillShaderFragTex.glsl"); + static protected URL defFillShaderFragTexURL = PGraphicsOpenGL.class.getResource("FillShaderFragTex.glsl"); static protected URL defLineShaderVertURL = PGraphicsOpenGL.class.getResource("LineShaderVert.glsl"); static protected URL defLineShaderFragURL = PGraphicsOpenGL.class.getResource("LineShaderFrag.glsl"); static protected URL defPointShaderVertURL = PGraphicsOpenGL.class.getResource("PointShaderVert.glsl"); static protected URL defPointShaderFragURL = PGraphicsOpenGL.class.getResource("PointShaderFrag.glsl"); - + static protected FillShaderSimple defFillShaderSimple; static protected FillShaderTex defFillShaderTex; static protected FillShaderLit defFillShaderLit; static protected FillShaderFull defFillShaderFull; static protected LineShader defLineShader; static protected PointShader defPointShader; - + protected FillShaderSimple fillShaderSimple; protected FillShaderTex fillShaderTex; protected FillShaderLit fillShaderLit; @@ -156,19 +154,19 @@ public class PGraphicsOpenGL extends PGraphics { protected PointShader pointShader; // ........................................................ - - // Tessellator, geometry - + + // Tessellator, geometry + protected InGeometry inGeo; protected TessGeometry tessGeo; protected int firstTexIndex; protected TexCache texCache; - protected Tessellator tessellator; - - // ........................................................ + protected Tessellator tessellator; + + // ........................................................ // Camera: - + /** Camera field of view. */ public float cameraFOV; @@ -178,53 +176,53 @@ public class PGraphicsOpenGL extends PGraphics { public float cameraNear, cameraFar; /** Aspect ratio of camera's view. */ public float cameraAspect; - + /** Distance between the camera eye and aim point. */ - protected float cameraDepth; - + protected float cameraDepth; + /** Actual position of the camera. */ - protected float cameraEyeX, cameraEyeY, cameraEyeZ; - + protected float cameraEyeX, cameraEyeY, cameraEyeZ; + /** Flag to indicate that we are inside beginCamera/endCamera block. */ protected boolean manipulatingCamera; - + // ........................................................ // All the matrices required for camera and geometry transformations. - public PMatrix3D projection; + public PMatrix3D projection; public PMatrix3D camera; - public PMatrix3D cameraInv; + public PMatrix3D cameraInv; public PMatrix3D modelview; public PMatrix3D modelviewInv; - public PMatrix3D projmodelview; - + public PMatrix3D projmodelview; + // To pass to shaders protected float[] glProjection; protected float[] glModelview; protected float[] glProjmodelview; protected float[] glNormal; - + protected boolean matricesAllocated = false; - - /** - * Marks when changes to the size have occurred, so that the camera + + /** + * Marks when changes to the size have occurred, so that the camera * will be reset in beginDraw(). */ - protected boolean sizeChanged; - + protected boolean sizeChanged; + /** Modelview matrix stack **/ - protected Stack modelviewStack; + protected Stack modelviewStack; /** Inverse modelview matrix stack **/ - protected Stack modelviewInvStack; - + protected Stack modelviewInvStack; + /** Projection matrix stack **/ protected Stack projectionStack; // ........................................................ - // Lights: - + // Lights: + public boolean lights; public int lightCount = 0; @@ -240,23 +238,23 @@ public class PGraphicsOpenGL extends PGraphics { /** * Ambient colors for lights. */ - public float[] lightAmbient; - + public float[] lightAmbient; + /** * Diffuse colors for lights. */ - public float[] lightDiffuse; - + public float[] lightDiffuse; + /** * Specular colors for lights. Internally these are stored as numbers between * 0 and 1. */ public float[] lightSpecular; - + /** Light falloff */ public float[] lightFalloffCoefficients; - /** Light spot parameters: Cosine of light spot angle + /** Light spot parameters: Cosine of light spot angle * and concentration */ public float[] lightSpotParameters; @@ -268,75 +266,75 @@ public class PGraphicsOpenGL extends PGraphics { public float currentLightFalloffLinear; public float currentLightFalloffQuadratic; - protected boolean lightsAllocated = false; - + protected boolean lightsAllocated = false; + // ........................................................ - + // Blending: - - protected int blendMode; - + + protected int blendMode; + // ........................................................ - - // Clipping - - protected boolean clip = false; - + + // Clipping + + protected boolean clip = false; + // ........................................................ // Text: - + /** Font texture of currently selected font. */ PFontTexture textTex; - + // ....................................................... - + // Framebuffer stack: - + static protected Stack fbStack; static protected PFramebuffer screenFramebuffer; - static protected PFramebuffer currentFramebuffer; - + static protected PFramebuffer currentFramebuffer; + // ....................................................... - + // Offscreen rendering: - + protected PFramebuffer offscreenFramebuffer; protected PFramebuffer offscreenFramebufferMultisample; protected boolean offscreenMultisample; - - protected boolean offscreenNotCurrent; - + + protected boolean offscreenNotCurrent; + // ........................................................ - + // Screen surface: - /** A handy reference to the PTexture bound to the drawing surface + /** A handy reference to the PTexture bound to the drawing surface * (off or on-screen) */ protected PTexture texture; - + /** IntBuffer wrapping the pixels array. */ protected IntBuffer pixelBuffer; - + /** Array to store pixels in OpenGL format. */ protected int[] rgbaPixels; - - /** Flag to indicate if the user is manipulating the + + /** Flag to indicate if the user is manipulating the * pixels array through the set()/get() methods */ protected boolean setgetPixels; - + // ........................................................ - - // Bezier and Catmull-Rom curves + + // Bezier and Catmull-Rom curves protected boolean bezierInited = false; public int bezierDetail = 20; - protected PMatrix3D bezierDrawMatrix; + protected PMatrix3D bezierDrawMatrix; protected boolean curveInited = false; protected int curveDetail = 20; public float curveTightness = 0; - + // catmull-rom basis matrix, perhaps with optional s parameter protected PMatrix3D curveBasisMatrix; protected PMatrix3D curveDrawMatrix; @@ -345,7 +343,7 @@ public class PGraphicsOpenGL extends PGraphics { protected PMatrix3D curveToBezierMatrix; protected float curveVertices[][]; - protected int curveVertexCount; + protected int curveVertexCount; // used by both curve and bezier, so just init here protected PMatrix3D bezierBasisMatrix = @@ -353,52 +351,52 @@ public class PGraphicsOpenGL extends PGraphics { 3, -6, 3, 0, -3, 3, 0, 0, 1, 0, 0, 0); - - // ........................................................ - + + // ........................................................ + // Utility variables: - + /** True if we are inside a beginDraw()/endDraw() block. */ - protected boolean drawing = false; - + protected boolean drawing = false; + /** Type of pixels operation. */ static protected final int OP_NONE = 0; static protected final int OP_READ = 1; static protected final int OP_WRITE = 2; protected int pixelsOp = OP_NONE; - + /** Used to detect the occurrence of a frame resize event. */ protected boolean resized = false; - + /** Viewport dimensions. */ protected int[] viewport = {0, 0, 0, 0}; - + /** Used to register calls to glClear. */ - protected boolean clearColorBuffer; - protected boolean clearColorBuffer0; - + protected boolean clearColorBuffer; + protected boolean clearColorBuffer0; + protected boolean openContour = false; protected boolean breakShape = false; protected boolean defaultEdges = false; - protected PImage textureImage0; - - protected boolean perspectiveCorrectedLines = false; - - ////////////////////////////////////////////////////////////// - + protected PImage textureImage0; + + protected boolean perspectiveCorrectedLines = false; + + ////////////////////////////////////////////////////////////// + // INIT/ALLOCATE/FINISH - - + + public PGraphicsOpenGL() { pgl = new PGL(this); pg = null; - + tessellator = new Tessellator(); - + inGeo = newInGeometry(IMMEDIATE); tessGeo = newTessGeometry(IMMEDIATE); texCache = newTexCache(); - + glFillVertexBufferID = 0; glFillColorBufferID = 0; glFillNormalBufferID = 0; @@ -406,52 +404,52 @@ public class PGraphicsOpenGL extends PGraphics { glFillAmbientBufferID = 0; glFillSpecularBufferID = 0; glFillEmissiveBufferID = 0; - glFillShininessBufferID = 0; + glFillShininessBufferID = 0; glFillIndexBufferID = 0; - + glLineVertexBufferID = 0; glLineColorBufferID = 0; glLineDirWidthBufferID = 0; glLineIndexBufferID = 0; - + glPointVertexBufferID = 0; glPointColorBufferID = 0; glPointSizeBufferID = 0; glPointIndexBufferID = 0; - } + } + - //public void setParent(PApplet parent) // PGraphics public void setPrimary(boolean primary) { super.setPrimary(primary); - format = ARGB; - } + format = ARGB; + } //public void setPath(String path) // PGraphics - - + + //public void setAntiAlias(int samples) // PGraphics - - - public void setFrameRate(float framerate) { - pgl.setFramerate(framerate); + + + public void setFrameRate(float framerate) { + pgl.setFramerate(framerate); } - - + + public void setSize(int iwidth, int iheight) { resized = (0 < width && width != iwidth) || (0 < height && height != iwidth); - + width = iwidth; height = iheight; width1 = width - 1; height1 = height - 1; - + allocate(); reapplySettings(); - + // init perspective projection based on new dimensions cameraFOV = 60 * DEG_TO_RAD; // at least for now cameraX = width / 2.0f; @@ -461,10 +459,10 @@ public class PGraphicsOpenGL extends PGraphics { cameraFar = cameraZ * 10.0f; cameraAspect = (float) width / (float) height; 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; } @@ -478,7 +476,7 @@ public class PGraphicsOpenGL extends PGraphics { */ protected void allocate() { super.allocate(); - + if (!matricesAllocated) { projection = new PMatrix3D(); camera = new PMatrix3D(); @@ -503,50 +501,50 @@ public class PGraphicsOpenGL extends PGraphics { } } - - public void dispose() { // PGraphics + + public void dispose() { // PGraphics super.dispose(); - deleteFinalizedGLResources(); + deleteFinalizedGLResources(); } - + // Only for debugging purposes. public void setFlushMode(int mode) { - flushMode = mode; + flushMode = mode; } - - + + ////////////////////////////////////////////////////////////// // RESOURCE HANDLING - - + + // Texture Objects ------------------------------------------- - + protected int createTextureObject() { deleteFinalizedTextureObjects(); - + int[] temp = new int[1]; pgl.glGenTextures(1, temp, 0); int id = temp[0]; - + if (glTextureObjects.containsKey(id)) { showWarning("Adding same texture twice"); - } else { + } else { glTextureObjects.put(id, false); } - + return id; } - + protected void deleteTextureObject(int id) { if (glTextureObjects.containsKey(id)) { int[] temp = { id }; pgl.glDeleteTextures(1, temp, 0); - glTextureObjects.remove(id); + glTextureObjects.remove(id); } - } - + } + protected void deleteAllTextureObjects() { for (Integer id : glTextureObjects.keySet()) { int[] temp = { id.intValue() }; @@ -554,7 +552,7 @@ public class PGraphicsOpenGL extends PGraphics { } glTextureObjects.clear(); } - + // This is synchronized because it is called from the GC thread. synchronized protected void finalizeTextureObject(int id) { if (glTextureObjects.containsKey(id)) { @@ -563,10 +561,10 @@ public class PGraphicsOpenGL extends PGraphics { showWarning("Trying to finalize non-existing texture"); } } - + protected void deleteFinalizedTextureObjects() { Set finalized = new HashSet(); - + for (Integer id : glTextureObjects.keySet()) { if (glTextureObjects.get(id)) { finalized.add(id); @@ -574,47 +572,47 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glDeleteTextures(1, temp, 0); } } - + for (Integer id : finalized) { - glTextureObjects.remove(id); + glTextureObjects.remove(id); } } - - + + // Vertex Buffer Objects ---------------------------------------------- - + protected int createVertexBufferObject() { deleteFinalizedVertexBufferObjects(); - + int[] temp = new int[1]; pgl.glGenBuffers(1, temp, 0); int id = temp[0]; - + if (glVertexBuffers.containsKey(id)) { showWarning("Adding same VBO twice"); - } else { + } else { glVertexBuffers.put(id, false); } - + return id; } - + protected void deleteVertexBufferObject(int id) { if (glVertexBuffers.containsKey(id)) { int[] temp = { id }; pgl.glDeleteBuffers(1, temp, 0); - glVertexBuffers.remove(id); + glVertexBuffers.remove(id); } } - + protected void deleteAllVertexBufferObjects() { for (Integer id : glVertexBuffers.keySet()) { int[] temp = { id.intValue() }; pgl.glDeleteBuffers(1, temp, 0); } glVertexBuffers.clear(); - } - + } + // This is synchronized because it is called from the GC thread. synchronized protected void finalizeVertexBufferObject(int id) { if (glVertexBuffers.containsKey(id)) { @@ -623,10 +621,10 @@ public class PGraphicsOpenGL extends PGraphics { showWarning("Trying to finalize non-existing VBO"); } } - + protected void deleteFinalizedVertexBufferObjects() { Set finalized = new HashSet(); - + for (Integer id : glVertexBuffers.keySet()) { if (glVertexBuffers.get(id)) { finalized.add(id); @@ -634,47 +632,47 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glDeleteBuffers(1, temp, 0); } } - + for (Integer id : finalized) { - glVertexBuffers.remove(id); + glVertexBuffers.remove(id); } } - - + + // FrameBuffer Objects ----------------------------------------- protected int createFrameBufferObject() { deleteFinalizedFrameBufferObjects(); - + int[] temp = new int[1]; pgl.glGenFramebuffers(1, temp, 0); int id = temp[0]; - + if (glFrameBuffers.containsKey(id)) { showWarning("Adding same FBO twice"); - } else { + } else { glFrameBuffers.put(id, false); } - + return id; } - + protected void deleteFrameBufferObject(int id) { if (glFrameBuffers.containsKey(id)) { int[] temp = { id }; pgl.glDeleteFramebuffers(1, temp, 0); - glFrameBuffers.remove(id); + glFrameBuffers.remove(id); } - } - + } + protected void deleteAllFrameBufferObjects() { for (Integer id : glFrameBuffers.keySet()) { int[] temp = { id.intValue() }; pgl.glDeleteFramebuffers(1, temp, 0); } glFrameBuffers.clear(); - } - + } + // This is synchronized because it is called from the GC thread. synchronized protected void finalizeFrameBufferObject(int id) { if (glFrameBuffers.containsKey(id)) { @@ -683,10 +681,10 @@ public class PGraphicsOpenGL extends PGraphics { showWarning("Trying to finalize non-existing FBO"); } } - + protected void deleteFinalizedFrameBufferObjects() { Set finalized = new HashSet(); - + for (Integer id : glFrameBuffers.keySet()) { if (glFrameBuffers.get(id)) { finalized.add(id); @@ -694,47 +692,47 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glDeleteFramebuffers(1, temp, 0); } } - + for (Integer id : finalized) { - glFrameBuffers.remove(id); + glFrameBuffers.remove(id); } } - + // RenderBuffer Objects ----------------------------------------------- - + protected int createRenderBufferObject() { deleteFinalizedRenderBufferObjects(); - + int[] temp = new int[1]; pgl.glGenRenderbuffers(1, temp, 0); int id = temp[0]; - + if (glRenderBuffers.containsKey(id)) { showWarning("Adding same renderbuffer twice"); - } else { + } else { glRenderBuffers.put(id, false); } - + return id; } - + protected void deleteRenderBufferObject(int id) { if (glRenderBuffers.containsKey(id)) { - int[] temp = { id }; + int[] temp = { id }; pgl.glDeleteRenderbuffers(1, temp, 0); - glRenderBuffers.remove(id); + glRenderBuffers.remove(id); } - } - + } + protected void deleteAllRenderBufferObjects() { for (Integer id : glRenderBuffers.keySet()) { int[] temp = { id.intValue() }; pgl.glDeleteRenderbuffers(1, temp, 0); } glRenderBuffers.clear(); - } - + } + // This is synchronized because it is called from the GC thread. synchronized protected void finalizeRenderBufferObject(int id) { if (glRenderBuffers.containsKey(id)) { @@ -743,10 +741,10 @@ public class PGraphicsOpenGL extends PGraphics { showWarning("Trying to finalize non-existing renderbuffer"); } } - + protected void deleteFinalizedRenderBufferObjects() { Set finalized = new HashSet(); - + for (Integer id : glRenderBuffers.keySet()) { if (glRenderBuffers.get(id)) { finalized.add(id); @@ -754,43 +752,43 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glDeleteRenderbuffers(1, temp, 0); } } - + for (Integer id : finalized) { - glRenderBuffers.remove(id); + glRenderBuffers.remove(id); } } - - + + // GLSL Program Objects ----------------------------------------------- - + protected int createGLSLProgramObject() { deleteFinalizedGLSLProgramObjects(); - + int id = pgl.glCreateProgram(); - + if (glslPrograms.containsKey(id)) { showWarning("Adding same glsl program twice"); - } else { + } else { glslPrograms.put(id, false); } - + return id; } - + protected void deleteGLSLProgramObject(int id) { if (glslPrograms.containsKey(id)) { pgl.glDeleteProgram(id); - glslPrograms.remove(id); + glslPrograms.remove(id); } - } - + } + protected void deleteAllGLSLProgramObjects() { for (Integer id : glslPrograms.keySet()) { pgl.glDeleteProgram(id); } glslPrograms.clear(); - } - + } + // This is synchronized because it is called from the GC thread. synchronized protected void finalizeGLSLProgramObject(int id) { if (glslPrograms.containsKey(id)) { @@ -799,53 +797,53 @@ public class PGraphicsOpenGL extends PGraphics { showWarning("Trying to finalize non-existing glsl program"); } } - + protected void deleteFinalizedGLSLProgramObjects() { Set finalized = new HashSet(); - + for (Integer id : glslPrograms.keySet()) { if (glslPrograms.get(id)) { finalized.add(id); pgl.glDeleteProgram(id); } } - + for (Integer id : finalized) { - glslPrograms.remove(id); + glslPrograms.remove(id); } } - + // GLSL Vertex Shader Objects ----------------------------------------------- - + protected int createGLSLVertShaderObject() { deleteFinalizedGLSLVertShaderObjects(); - + int id = pgl.glCreateShader(PGL.GL_VERTEX_SHADER); - + if (glslVertexShaders.containsKey(id)) { showWarning("Adding same glsl vertex shader twice"); - } else { + } else { glslVertexShaders.put(id, false); } - + return id; } - + protected void deleteGLSLVertShaderObject(int id) { if (glslVertexShaders.containsKey(id)) { pgl.glDeleteShader(id); - glslVertexShaders.remove(id); + glslVertexShaders.remove(id); } - } - + } + protected void deleteAllGLSLVertShaderObjects() { for (Integer id : glslVertexShaders.keySet()) { pgl.glDeleteShader(id); } glslVertexShaders.clear(); - } - + } + // This is synchronized because it is called from the GC thread. synchronized protected void finalizeGLSLVertShaderObject(int id) { if (glslVertexShaders.containsKey(id)) { @@ -854,53 +852,53 @@ public class PGraphicsOpenGL extends PGraphics { showWarning("Trying to finalize non-existing glsl vertex shader"); } } - + protected void deleteFinalizedGLSLVertShaderObjects() { Set finalized = new HashSet(); - + for (Integer id : glslVertexShaders.keySet()) { if (glslVertexShaders.get(id)) { finalized.add(id); pgl.glDeleteShader(id); } } - + for (Integer id : finalized) { - glslVertexShaders.remove(id); + glslVertexShaders.remove(id); } } - - - // GLSL Fragment Shader Objects ----------------------------------------------- - + + + // GLSL Fragment Shader Objects ----------------------------------------------- + protected int createGLSLFragShaderObject() { deleteFinalizedGLSLFragShaderObjects(); - - int id = pgl.glCreateShader(PGL.GL_FRAGMENT_SHADER); - + + int id = pgl.glCreateShader(PGL.GL_FRAGMENT_SHADER); + if (glslFragmentShaders.containsKey(id)) { showWarning("Adding same glsl fragment shader twice"); - } else { + } else { glslFragmentShaders.put(id, false); } - + return id; } - + protected void deleteGLSLFragShaderObject(int id) { if (glslFragmentShaders.containsKey(id)) { pgl.glDeleteShader(id); - glslFragmentShaders.remove(id); + glslFragmentShaders.remove(id); } - } - + } + protected void deleteAllGLSLFragShaderObjects() { for (Integer id : glslFragmentShaders.keySet()) { pgl.glDeleteShader(id); } glslFragmentShaders.clear(); - } - + } + // This is synchronized because it is called from the GC thread. synchronized protected void finalizeGLSLFragShaderObject(int id) { if (glslFragmentShaders.containsKey(id)) { @@ -909,23 +907,23 @@ public class PGraphicsOpenGL extends PGraphics { showWarning("Trying to finalize non-existing glsl fragment shader"); } } - + protected void deleteFinalizedGLSLFragShaderObjects() { Set finalized = new HashSet(); - + for (Integer id : glslFragmentShaders.keySet()) { if (glslFragmentShaders.get(id)) { finalized.add(id); pgl.glDeleteShader(id); } } - + for (Integer id : finalized) { - glslFragmentShaders.remove(id); + glslFragmentShaders.remove(id); } - } - - + } + + protected void deleteFinalizedGLResources() { deleteFinalizedTextureObjects(); deleteFinalizedVertexBufferObjects(); @@ -935,8 +933,8 @@ public class PGraphicsOpenGL extends PGraphics { deleteFinalizedGLSLVertShaderObjects(); deleteFinalizedGLSLFragShaderObjects(); } - - + + protected void deleteAllGLResources() { deleteAllTextureObjects(); deleteAllVertexBufferObjects(); @@ -944,26 +942,26 @@ public class PGraphicsOpenGL extends PGraphics { deleteAllRenderBufferObjects(); deleteAllGLSLProgramObjects(); deleteAllGLSLVertShaderObjects(); - deleteAllGLSLFragShaderObjects(); + deleteAllGLSLFragShaderObjects(); } - - + + ////////////////////////////////////////////////////////////// // FRAMEBUFFERS - - + + public void pushFramebuffer() { fbStack.push(currentFramebuffer); } - + public void setFramebuffer(PFramebuffer fbo) { currentFramebuffer = fbo; currentFramebuffer.bind(); } - + public void popFramebuffer() { try { currentFramebuffer.finish(); @@ -973,13 +971,13 @@ public class PGraphicsOpenGL extends PGraphics { PGraphics.showWarning("P3D: Empty framebuffer stack"); } } - - + + ////////////////////////////////////////////////////////////// // FRAME RENDERING - - + + protected void releaseResources() { // First, releasing the resources used by // the renderer itself. @@ -987,7 +985,7 @@ public class PGraphicsOpenGL extends PGraphics { texture.release(); texture = null; } - + if (defFillShaderSimple != null) { defFillShaderSimple.release(); defFillShaderSimple = null; @@ -996,141 +994,141 @@ public class PGraphicsOpenGL extends PGraphics { if (defFillShaderLit != null) { defFillShaderLit.release(); defFillShaderLit = null; - } + } if (defFillShaderTex != null) { defFillShaderTex.release(); defFillShaderTex = null; - } + } if (defFillShaderFull != null) { defFillShaderFull.release(); defFillShaderFull = null; - } - + } + if (defLineShader != null) { defLineShader.release(); defLineShader = null; } - + 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) { releaseFillBuffers(); fillVBOsCreated = false; } - + if (lineVBOsCreated) { releaseLineBuffers(); lineVBOsCreated = false; } - + if (pointVBOsCreated) { releasePointBuffers(); pointVBOsCreated = false; } - - // Now, releasing the remaining resources + + // Now, releasing the remaining resources // (from user's objects). - deleteAllGLResources(); + deleteAllGLResources(); } - + protected void createFillBuffers() { int sizef = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_FLOAT; int sizei = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_INT; int sizex = PGL.MAX_TESS_INDICES * PGL.SIZEOF_INDEX; - - glFillVertexBufferID = createVertexBufferObject(); + + glFillVertexBufferID = createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillVertexBufferID); pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, null, vboMode); - + glFillColorBufferID = createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillColorBufferID); pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, null, vboMode); - + glFillNormalBufferID = createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillNormalBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, null, vboMode); - + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, null, vboMode); + glFillTexCoordBufferID = createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillTexCoordBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 2 * sizef, null, vboMode); - - glFillAmbientBufferID = pg.createVertexBufferObject(); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 2 * sizef, null, vboMode); + + glFillAmbientBufferID = pg.createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillAmbientBufferID); pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, null, vboMode); - + glFillSpecularBufferID = pg.createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillSpecularBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, null, vboMode); - + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, null, vboMode); + glFillEmissiveBufferID = pg.createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillEmissiveBufferID); pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, null, vboMode); - + glFillShininessBufferID = pg.createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillShininessBufferID); pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizef, null, vboMode); - + pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); - - glFillIndexBufferID = createVertexBufferObject(); + + glFillIndexBufferID = createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glFillIndexBufferID); pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, sizex, null, vboMode); 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; - + pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillVertexBufferID); 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, IntBuffer.wrap(tessGeo.fillColors, 0, size), 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, FloatBuffer.wrap(tessGeo.fillNormals, 0, 3 * size), 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, IntBuffer.wrap(tessGeo.fillAmbient, 0, size), vboMode); @@ -1139,87 +1137,87 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillEmissiveBufferID); 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, FloatBuffer.wrap(tessGeo.fillShininess, 0, size), vboMode); } - + if (tex) { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glFillTexCoordBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 2 * sizef, FloatBuffer.wrap(tessGeo.fillTexcoords, 0, 2 * size), vboMode); + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 2 * sizef, FloatBuffer.wrap(tessGeo.fillTexcoords, 0, 2 * size), vboMode); } - + pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glFillIndexBufferID); - pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, tessGeo.fillIndexCount * PGL.SIZEOF_INDEX, - ShortBuffer.wrap(tessGeo.fillIndices, 0, tessGeo.fillIndexCount), vboMode); - } - - + pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, tessGeo.fillIndexCount * PGL.SIZEOF_INDEX, + ShortBuffer.wrap(tessGeo.fillIndices, 0, tessGeo.fillIndexCount), vboMode); + } + + protected void unbindFillBuffers() { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); - } - - + } + + protected void releaseFillBuffers() { deleteVertexBufferObject(glFillVertexBufferID); glFillVertexBufferID = 0; - + deleteVertexBufferObject(glFillColorBufferID); glFillColorBufferID = 0; deleteVertexBufferObject(glFillNormalBufferID); - glFillNormalBufferID = 0; - + glFillNormalBufferID = 0; + deleteVertexBufferObject(glFillTexCoordBufferID); glFillTexCoordBufferID = 0; - + deleteVertexBufferObject(glFillAmbientBufferID); glFillAmbientBufferID = 0; - + deleteVertexBufferObject(glFillSpecularBufferID); glFillSpecularBufferID = 0; deleteVertexBufferObject(glFillEmissiveBufferID); - glFillEmissiveBufferID = 0; - + glFillEmissiveBufferID = 0; + deleteVertexBufferObject(glFillShininessBufferID); - glFillShininessBufferID = 0; - + glFillShininessBufferID = 0; + deleteVertexBufferObject(glFillIndexBufferID); - glFillIndexBufferID = 0; + glFillIndexBufferID = 0; } - + protected void createLineBuffers() { int sizef = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_FLOAT; int sizex = PGL.MAX_TESS_INDICES * PGL.SIZEOF_INDEX; - int sizei = PGL.MAX_TESS_INDICES * PGL.SIZEOF_INT; - + int sizei = PGL.MAX_TESS_INDICES * PGL.SIZEOF_INT; + glLineVertexBufferID = createVertexBufferObject(); - + pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineVertexBufferID); pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, null, vboMode); - + glLineColorBufferID = createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineColorBufferID); pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, null, vboMode); - + glLineDirWidthBufferID = createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineDirWidthBufferID); pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 4 * sizef, null, vboMode); - + pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); - - glLineIndexBufferID = createVertexBufferObject(); + + glLineIndexBufferID = createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glLineIndexBufferID); pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, sizex, null, vboMode); - + pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); - } - - + } + + protected void updateLineBuffers() { int size = tessGeo.lineVertexCount; int sizef = size * PGL.SIZEOF_FLOAT; @@ -1230,64 +1228,64 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glLineColorBufferID); 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, FloatBuffer.wrap(tessGeo.lineDirWidths, 0, 4 * size), vboMode); - + 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, + pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, tessGeo.lineIndexCount * PGL.SIZEOF_INDEX, ShortBuffer.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); - } - - + pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); + } + + protected void releaseLineBuffers() { deleteVertexBufferObject(glLineVertexBufferID); glLineVertexBufferID = 0; - + deleteVertexBufferObject(glLineColorBufferID); glLineColorBufferID = 0; deleteVertexBufferObject(glLineDirWidthBufferID); glLineDirWidthBufferID = 0; - + deleteVertexBufferObject(glLineIndexBufferID); - glLineIndexBufferID = 0; + glLineIndexBufferID = 0; } - + protected void createPointBuffers() { int sizef = PGL.MAX_TESS_VERTICES * PGL.SIZEOF_FLOAT; int sizex = PGL.MAX_TESS_INDICES * PGL.SIZEOF_INDEX; int sizei = PGL.MAX_TESS_INDICES * PGL.SIZEOF_INT; - - glPointVertexBufferID = createVertexBufferObject(); + + glPointVertexBufferID = createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointVertexBufferID); pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 3 * sizef, null, vboMode); - + glPointColorBufferID = createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointColorBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, null, vboMode); - + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, sizei, null, vboMode); + glPointSizeBufferID = createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointSizeBufferID); - pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 2 * sizef, null, vboMode); - + pgl.glBufferData(PGL.GL_ARRAY_BUFFER, 2 * sizef, null, vboMode); + pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0); - - glPointIndexBufferID = createVertexBufferObject(); + + glPointIndexBufferID = createVertexBufferObject(); pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glPointIndexBufferID); pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, sizex, null, vboMode); - + pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); - } - - + } + + protected void updatePointBuffers() { int size = tessGeo.pointVertexCount; int sizef = size * PGL.SIZEOF_FLOAT; @@ -1295,40 +1293,40 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointVertexBufferID); 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, IntBuffer.wrap(tessGeo.pointColors, 0, size), vboMode); - pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointSizeBufferID); + pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, glPointSizeBufferID); 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, - ShortBuffer.wrap(tessGeo.pointIndices, 0, tessGeo.pointIndexCount), vboMode); + pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, tessGeo.pointIndexCount * PGL.SIZEOF_INDEX, + ShortBuffer.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); glPointVertexBufferID = 0; - + deleteVertexBufferObject(glPointColorBufferID); - glPointColorBufferID = 0; - + glPointColorBufferID = 0; + deleteVertexBufferObject(glPointSizeBufferID); - glPointSizeBufferID = 0; - - deleteVertexBufferObject(glPointIndexBufferID); + glPointSizeBufferID = 0; + + deleteVertexBufferObject(glPointIndexBufferID); glPointIndexBufferID = 0; } - - + + /** * OpenGL cannot draw until a proper native peer is available, so this * returns the value of PApplet.isDisplayable() (inherited from Component). @@ -1337,37 +1335,37 @@ public class PGraphicsOpenGL extends PGraphics { return pgl.canDraw(); } - - public void requestDraw() { + + public void requestDraw() { if (primarySurface) { if (pgl.initialized) { - pgl.requestDraw(); + pgl.requestDraw(); } else { - initPrimary(); + initPrimary(); } } } - - + + public void beginDraw() { if (drawing) { showWarning("P3D: Already called beginDraw()."); return; - } - - if (!glParamsRead) { - getGLParameters(); } - + + if (!glParamsRead) { + getGLParameters(); + } + if (!settingsInited) { defaultSettings(); - } - + } + if (primarySurface) { pgl.updatePrimary(); } else { if (!pgl.initialized) { - initOffscreen(); + initOffscreen(); } else { boolean outdated = offscreenFramebuffer != null && offscreenFramebuffer.contextIsOutdated(); boolean outdatedMulti = offscreenFramebufferMultisample != null && offscreenFramebufferMultisample.contextIsOutdated(); @@ -1376,34 +1374,34 @@ public class PGraphicsOpenGL extends PGraphics { initOffscreen(); } } - + pushFramebuffer(); if (offscreenMultisample) { - setFramebuffer(offscreenFramebufferMultisample); + setFramebuffer(offscreenFramebufferMultisample); } else { setFramebuffer(offscreenFramebuffer); - } + } pgl.glDrawBuffer(PGL.GL_COLOR_ATTACHMENT0); pgl.updateOffscreen(pg.pgl); } - + // We are ready to go! - - report("top beginDraw()"); - + + report("top beginDraw()"); + inGeo.clear(); tessGeo.clear(); texCache.clear(); - - // Each frame starts with textures disabled. + + // Each frame starts with textures disabled. super.noTexture(); - + // Screen blend is needed for alpha (i.e. fonts) to work. // Using setDefaultBlend() instead of blendMode() because // the latter will set the blend mode only if it is different // from current. setDefaultBlend(); - + // this is necessary for 3D drawing if (hints[DISABLE_DEPTH_TEST]) { pgl.glDisable(PGL.GL_DEPTH_TEST); @@ -1414,17 +1412,17 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glDepthFunc(PGL.GL_LEQUAL); if (hints[ENABLE_ACCURATE_2D]) { - flushMode = FLUSH_CONTINUOUSLY; + flushMode = FLUSH_CONTINUOUSLY; } else { flushMode = FLUSH_WHEN_FULL; } - + if (primarySurface) { int[] temp = { 0 }; pgl.glGetIntegerv(PGL.GL_SAMPLES, temp, 0); if (antialias != temp[0] && 1 < temp[0] && 1 < antialias) { antialias = temp[0]; - } + } } if (antialias < 2) { pgl.glDisable(PGL.GL_MULTISAMPLE); @@ -1432,13 +1430,13 @@ public class PGraphicsOpenGL extends PGraphics { pgl.glEnable(PGL.GL_LINE_SMOOTH); pgl.glEnable(PGL.GL_POLYGON_SMOOTH); } else { - pgl.glEnable(PGL.GL_MULTISAMPLE); + 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.glDisable(PGL.GL_POLYGON_SMOOTH); + } + + // setup opengl viewport. viewport[0] = 0; viewport[1] = 0; viewport[2] = width; viewport[3] = height; pgl.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); if (resized) { @@ -1446,198 +1444,198 @@ public class PGraphicsOpenGL extends PGraphics { // in the case background is not called in draw(). background(0); if (texture != null) { - // The screen texture should be deleted because it + // The screen texture should be deleted because it // corresponds to the old window size. this.removeCache(pg); this.removeParams(pg); texture = null; loadTexture(); - } - resized = false; + } + resized = false; } - + if (sizeChanged) { // defaults to perspective, if the user has setup up their // own projection, they'll need to fix it after resize anyway. // this helps the people who haven't set up their own projection. perspective(); - + // set up the default camera and initializes modelview matrix. camera(); - + // clear the flag sizeChanged = false; } else { // The camera and projection matrices, saved when calling camera() and frustrum() // are set as the current modelview and projection matrices. This is done to // remove any additional modelview transformation (and less likely, projection - // transformations) applied by the user after setting the camera and/or projection + // transformations) applied by the user after setting the camera and/or projection modelview.set(camera); modelviewInv.set(cameraInv); calcProjmodelview(); } - + noLights(); lightFalloff(1, 0, 0); lightSpecular(0, 0, 0); - + // because y is flipped pgl.glFrontFace(PGL.GL_CW); - + // Processing uses only one texture unit. pgl.glActiveTexture(PGL.GL_TEXTURE0); - + // The current normal vector is set to be parallel to the Z axis. normalX = normalY = normalZ = 0; - + perspectiveCorrectedLines = hints[ENABLE_PERSPECTIVE_CORRECTED_LINES]; - + // 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 (primarySurface) { - pgl.beginOnscreenDraw(clearColorBuffer); + pgl.beginOnscreenDraw(clearColorBuffer); } else { pgl.beginOffscreenDraw(pg.clearColorBuffer); - + // Just in case the texture was recreated (in a resize event for example) - offscreenFramebuffer.setColorBuffer(texture); + offscreenFramebuffer.setColorBuffer(texture); } if (hints[DISABLE_DEPTH_MASK]) { pgl.glDepthMask(false); } else { pgl.glDepthMask(true); - } - + } + drawing = true; pixelsOp = OP_NONE; - + modified = false; setgetPixels = false; - + clearColorBuffer0 = clearColorBuffer; clearColorBuffer = false; - + report("bot beginDraw()"); } public void endDraw() { report("top endDraw()"); - + if (flushMode == FLUSH_WHEN_FULL) { // Flushing any remaining geometry. flush(); - + // if (settingPixels) { // // Drawing the pixels array. We can only get -// // here if there was no geometry to flush at +// // here if there was no geometry to flush at // // the end of draw, and the user has been -// // manipulating individual pixels. If that's -// // the case we need to update the screen with +// // manipulating individual pixels. If that's +// // the case we need to update the screen with // // the changes in the pixels array. -// updatePixels(); +// updatePixels(); // } - - // TODO: Implement depth sorting (http://code.google.com/p/processing/issues/detail?id=51) + + // TODO: Implement depth sorting (http://code.google.com/p/processing/issues/detail?id=51) //if (hints[ENABLE_DEPTH_SORT]) { // flush(); - //} + //} } - + if (!drawing) { showWarning("P3D: Cannot call endDraw() before beginDraw()."); return; } - + if (primarySurface) { - pgl.endOnscreenDraw(clearColorBuffer0); + pgl.endOnscreenDraw(clearColorBuffer0); pgl.glFlush(); } else { if (offscreenMultisample) { - offscreenFramebufferMultisample.copy(offscreenFramebuffer); + offscreenFramebufferMultisample.copy(offscreenFramebuffer); } popFramebuffer(); - + pgl.endOffscreenDraw(pg.clearColorBuffer0); - + pg.restoreGL(); - } - - drawing = false; - - report("bot endDraw()"); + } + + drawing = false; + + report("bot endDraw()"); } - + public PGL beginPGL() { return pgl; } - + public void endPGL() { restoreGL(); } - - + + public void restartPGL() { - pgl.initialized = false; + pgl.initialized = false; } - - + + protected void restoreGL() { - blendMode(blendMode); - + blendMode(blendMode); + if (hints[DISABLE_DEPTH_TEST]) { pgl.glDisable(PGL.GL_DEPTH_TEST); } else { pgl.glEnable(PGL.GL_DEPTH_TEST); } - pgl.glDepthFunc(PGL.GL_LEQUAL); - + 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); + pgl.glEnable(PGL.GL_POLYGON_SMOOTH); } else { - pgl.glEnable(PGL.GL_MULTISAMPLE); + pgl.glEnable(PGL.GL_MULTISAMPLE); pgl.glDisable(PGL.GL_POINT_SMOOTH); pgl.glDisable(PGL.GL_LINE_SMOOTH); - pgl.glDisable(PGL.GL_POLYGON_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); - } + } } - - - protected void beginPixelsOp(int op) { + + + protected void beginPixelsOp(int op) { if (primarySurface) { if (op == OP_READ) { pgl.glReadBuffer(PGL.GL_FRONT); } else { pgl.glDrawBuffer(PGL.GL_BACK); } - offscreenNotCurrent = false; + offscreenNotCurrent = false; } else { // Making sure that the offscreen FBO is current. This allows to do calls - // like loadPixels(), set() or get() without enclosing them between + // like loadPixels(), set() or get() without enclosing them between // beginDraw()/endDraw() when working with a PGraphics object. We don't // need the rest of the surface initialization/finalization, since only - // the pixels are affected. + // the pixels are affected. if (op == OP_READ) { // We always read the screen pixels from the color FBO. offscreenNotCurrent = offscreenFramebuffer != currentFramebuffer; @@ -1654,14 +1652,14 @@ public class PGraphicsOpenGL extends PGraphics { offscreenNotCurrent = offscreenFramebufferMultisample != currentFramebuffer; } else { offscreenNotCurrent = offscreenFramebuffer != currentFramebuffer; - } + } if (offscreenNotCurrent) { pushFramebuffer(); if (offscreenMultisample) { - setFramebuffer(offscreenFramebufferMultisample); + setFramebuffer(offscreenFramebufferMultisample); } else { setFramebuffer(offscreenFramebuffer); - } + } pgl.updateOffscreen(pg.pgl); } pgl.glDrawBuffer(PGL.GL_COLOR_ATTACHMENT0); @@ -1670,25 +1668,25 @@ public class PGraphicsOpenGL extends PGraphics { pixelsOp = op; } - - protected void endPixelsOp() { + + protected void endPixelsOp() { if (offscreenNotCurrent) { if (pixelsOp == OP_WRITE && offscreenMultisample) { // We were writing to the multisample FBO, so we need // to blit its contents to the color FBO. - offscreenFramebufferMultisample.copy(offscreenFramebuffer); + offscreenFramebufferMultisample.copy(offscreenFramebuffer); } popFramebuffer(); } pixelsOp = OP_NONE; - } - - + } + + protected void updateGLProjection() { if (glProjection == null) { glProjection = new float[16]; } - + glProjection[0] = projection.m00; glProjection[1] = projection.m10; glProjection[2] = projection.m20; @@ -1710,12 +1708,12 @@ public class PGraphicsOpenGL extends PGraphics { glProjection[15] = projection.m33; } - + protected void updateGLModelview() { if (glModelview == null) { glModelview = new float[16]; } - + glModelview[0] = modelview.m00; glModelview[1] = modelview.m10; glModelview[2] = modelview.m20; @@ -1734,21 +1732,21 @@ public class PGraphicsOpenGL extends PGraphics { glModelview[12] = modelview.m03; glModelview[13] = modelview.m13; glModelview[14] = modelview.m23; - glModelview[15] = modelview.m33; - } - - + glModelview[15] = modelview.m33; + } + + protected void calcProjmodelview() { projmodelview.set(projection); - projmodelview.apply(modelview); + projmodelview.apply(modelview); } - - + + protected void updateGLProjmodelview() { if (glProjmodelview == null) { glProjmodelview = new float[16]; } - + glProjmodelview[0] = projmodelview.m00; glProjmodelview[1] = projmodelview.m10; glProjmodelview[2] = projmodelview.m20; @@ -1769,80 +1767,80 @@ public class PGraphicsOpenGL extends PGraphics { glProjmodelview[14] = projmodelview.m23; glProjmodelview[15] = projmodelview.m33; } - - + + protected void updateGLNormal() { if (glNormal == null) { glNormal = new float[9]; } - + // The normal matrix is the transpose of the inverse of the - // modelview (remember that gl matrices are column-major, + // modelview (remember that gl matrices are column-major, // meaning that elements 0, 1, 2 are the first column, // 3, 4, 5 the second, etc.: - glNormal[0] = modelviewInv.m00; - glNormal[1] = modelviewInv.m01; + glNormal[0] = modelviewInv.m00; + glNormal[1] = modelviewInv.m01; glNormal[2] = modelviewInv.m02; - - glNormal[3] = modelviewInv.m10; - glNormal[4] = modelviewInv.m11; + + glNormal[3] = modelviewInv.m10; + glNormal[4] = modelviewInv.m11; glNormal[5] = modelviewInv.m12; - - glNormal[6] = modelviewInv.m20; - glNormal[7] = modelviewInv.m21; - glNormal[8] = modelviewInv.m22; + + glNormal[6] = modelviewInv.m20; + glNormal[7] = modelviewInv.m21; + glNormal[8] = modelviewInv.m22; } - - - ////////////////////////////////////////////////////////////// - + + + ////////////////////////////////////////////////////////////// + // SETTINGS // protected void checkSettings() - + protected void defaultSettings() { super.defaultSettings(); manipulatingCamera = false; - + clearColorBuffer = false; - + if (fbStack == null) { fbStack = new Stack(); screenFramebuffer = new PFramebuffer(parent, width, height, true); setFramebuffer(screenFramebuffer); - } - + } + if (modelviewStack == null) { modelviewStack = new Stack(); } if (modelviewInvStack == null) { modelviewInvStack = new Stack(); - } + } if (projectionStack == null) { projectionStack = new Stack(); } - + // easiest for beginners textureMode(IMAGE); - + // Default material properties ambient(80); specular(125); emissive(0); - shininess(1); + shininess(1); } - - + + // reapplySettings ////////////////////////////////////////////////////////////// // HINTS - + public void hint(int which) { boolean oldValue = hints[PApplet.abs(which)]; super.hint(which); @@ -1851,7 +1849,7 @@ public class PGraphicsOpenGL extends PGraphics { if (oldValue == newValue) { return; } - + if (which == DISABLE_DEPTH_TEST) { flush(); pgl.glDisable(PGL.GL_DEPTH_TEST); @@ -1863,15 +1861,15 @@ public class PGraphicsOpenGL extends PGraphics { 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) { // We flush the geometry using the previous line setting. @@ -1887,17 +1885,17 @@ public class PGraphicsOpenGL extends PGraphics { } } - + ////////////////////////////////////////////////////////////// // SHAPE CREATORS - - + + public PShape createShape() { return createShape(POLYGON); } - - + + public PShape createShape(int type) { PShape3D shape = null; if (type == PShape.GROUP) { @@ -1914,7 +1912,7 @@ public class PGraphicsOpenGL extends PGraphics { } else if (type == TRIANGLE_FAN) { shape = new PShape3D(parent, PShape.GEOMETRY); shape.setKind(TRIANGLE_FAN); - } else if (type == TRIANGLE_STRIP) { + } else if (type == TRIANGLE_STRIP) { shape = new PShape3D(parent, PShape.GEOMETRY); shape.setKind(TRIANGLE_STRIP); } else if (type == QUADS || type == QUADS) { @@ -1925,23 +1923,23 @@ public class PGraphicsOpenGL extends PGraphics { shape.setKind(QUAD_STRIP); } else if (type == POLYGON) { shape = new PShape3D(parent, PShape.GEOMETRY); - shape.setKind(POLYGON); + shape.setKind(POLYGON); } return shape; } - - + + public PShape createShape(int kind, float... p) { PShape3D shape = null; int len = p.length; - + if (kind == POINT) { if (len != 2) { showWarning("Wrong number of parameters"); return null; } shape = new PShape3D(parent, PShape.PRIMITIVE); - shape.setKind(POINT); + shape.setKind(POINT); } else if (kind == LINE) { if (len != 4) { showWarning("Wrong number of parameters"); @@ -1967,169 +1965,169 @@ public class PGraphicsOpenGL extends PGraphics { if (len != 4 && len != 5 && len != 8) { showWarning("Wrong number of parameters"); return null; - } + } shape = new PShape3D(parent, PShape.PRIMITIVE); - shape.setKind(RECT); + shape.setKind(RECT); } else if (kind == ELLIPSE) { if (len != 4) { showWarning("Wrong number of parameters"); return null; - } + } shape = new PShape3D(parent, PShape.PRIMITIVE); - shape.setKind(ELLIPSE); + shape.setKind(ELLIPSE); } else if (kind == ARC) { if (len != 6) { showWarning("Wrong number of parameters"); return null; - } + } shape = new PShape3D(parent, PShape.PRIMITIVE); shape.setKind(ARC); } else if (kind == BOX) { if (len != 1 && len != 3) { showWarning("Wrong number of parameters"); return null; - } + } shape = new PShape3D(parent, PShape.PRIMITIVE); - shape.setKind(BOX); + shape.setKind(BOX); } else if (kind == SPHERE) { if (len != 1) { showWarning("Wrong number of parameters"); return null; } shape = new PShape3D(parent, PShape.PRIMITIVE); - shape.setKind(SPHERE); + shape.setKind(SPHERE); } - + if (shape != null) { shape.setParams(p); } - + return shape; } - - + + ////////////////////////////////////////////////////////////// // VERTEX SHAPES - - + + public void beginShape(int kind) { shape = kind; - + inGeo.clear(); - - breakShape = false; + + breakShape = false; defaultEdges = true; - + textureImage0 = textureImage; // The superclass method is called to avoid an early flush. super.noTexture(); - + normalMode = NORMAL_MODE_AUTO; } - + public void endShape(int mode) { - if (flushMode == FLUSH_WHEN_FULL && hints[DISABLE_TEXTURE_CACHE] && + if (flushMode == FLUSH_WHEN_FULL && hints[DISABLE_TEXTURE_CACHE] && textureImage0 != null && textureImage == null) { // The previous shape had a texture and this one doesn't. So we need to flush // the textured geometry. textureImage = textureImage0; flush(); - textureImage = null; + textureImage = null; } - + tessellate(mode); - - if (flushMode == FLUSH_CONTINUOUSLY || + + if (flushMode == FLUSH_CONTINUOUSLY || (flushMode == FLUSH_WHEN_FULL && tessGeo.isFull())) { - + if (flushMode == FLUSH_WHEN_FULL && tessGeo.isOverflow()) { PGraphics.showWarning("P3D: tessellated arrays are overflowing"); } - + flush(); } } - + public void texture(PImage image) { - if (flushMode == FLUSH_WHEN_FULL && hints[DISABLE_TEXTURE_CACHE] && + if (flushMode == FLUSH_WHEN_FULL && hints[DISABLE_TEXTURE_CACHE] && image != textureImage0) { // Changing the texture image, so we need to flush the // tessellated geometry accumulated until now, so that // textures are not mixed. - textureImage = textureImage0; - flush(); + textureImage = textureImage0; + flush(); } super.texture(image); } - - + + public void noTexture() { if (flushMode == FLUSH_WHEN_FULL && hints[DISABLE_TEXTURE_CACHE] && null != textureImage0) { // Changing the texture image, so we need to flush the // tessellated geometry accumulated until now, so that - // textures are not mixed. + // textures are not mixed. textureImage = textureImage0; - flush(); - } + flush(); + } super.noTexture(); } - - + + public void beginContour() { if (openContour) { showWarning("P3D: Already called beginContour()."); return; - } + } openContour = true; } - - + + public void endContour() { if (!openContour) { showWarning("P3D: Need to call beginContour() first."); - return; + return; } openContour = false; breakShape = true; - } - - + } + + public void vertex(float x, float y) { vertex(x, y, 0, 0, 0); } - - public void vertex(float x, float y, float u, float v) { - vertex(x, y, 0, u, v); - } - - - public void vertex(float x, float y, float z) { - vertex(x, y, z, 0, 0); - } - + public void vertex(float x, float y, float u, float v) { + vertex(x, y, 0, u, v); + } + + + public void vertex(float x, float y, float z) { + vertex(x, y, z, 0, 0); + } + + public void vertex(float x, float y, float z, float u, float v) { - vertexImpl(x, y, z, u, v, VERTEX); - } - - + vertexImpl(x, y, z, u, v, VERTEX); + } + + protected void vertexImpl(float x, float y, float z, float u, float v, int code) { if (inGeo.isFull()) { PGraphics.showWarning("P3D: Too many vertices, try creating smaller shapes"); return; } - + boolean textured = textureImage != null; int fcolor = 0x00; if (fill || textured) { if (!textured) { fcolor = fillColor; - } else { + } else { if (tint) { fcolor = tintColor; } else { @@ -2137,35 +2135,35 @@ public class PGraphicsOpenGL extends PGraphics { } } } - + int scolor = 0x00; float sweight = 0; if (stroke) { scolor = strokeColor; sweight = strokeWeight; - } + } if (breakShape) { code = PShape.BREAK; breakShape = false; - } - + } + if (textured && textureMode == IMAGE) { u = PApplet.min(1, u / textureImage.width); v = PApplet.min(1, v / textureImage.height); } - - inGeo.addVertex(x, y, z, - fcolor, + + inGeo.addVertex(x, y, z, + fcolor, normalX, normalY, normalZ, - u, v, + u, v, scolor, sweight, ambientColor, specularColor, emissiveColor, shininess, - code); + code); } - - - public void clip(float a, float b, float c, float d) { + + + public void clip(float a, float b, float c, float d) { if (imageMode == CORNER) { if (c < 0) { // reset a negative width a += c; c = -c; @@ -2185,7 +2183,7 @@ public class PGraphicsOpenGL extends PGraphics { } clipImpl(a, b, c, d); - + } else if (imageMode == CENTER) { // c and d are width/height if (c < 0) c = -c; @@ -2194,39 +2192,39 @@ public class PGraphicsOpenGL extends PGraphics { float y1 = b - d/2; clipImpl(x1, y1, x1 + c, y1 + d); - } + } } - + protected void clipImpl(float x1, float y1, float x2, float y2) { flush(); pgl.glEnable(PGL.GL_SCISSOR_TEST); - + float h = y2 - y1; pgl.glScissor((int)x1, (int)(height - y1 - h), (int)(x2 - x1), (int)h); - + clip = true; } - + public void noClip() { if (clip) { flush(); pgl.glDisable(PGL.GL_SCISSOR_TEST); clip = false; } - } - - + } + + ////////////////////////////////////////////////////////////// // RENDERING // protected void render() - // protected void sort() - - + // protected void sort() + + protected void tessellate(int mode) { tessellator.setInGeometry(inGeo); tessellator.setTessGeometry(tessGeo); @@ -2235,13 +2233,13 @@ public class PGraphicsOpenGL extends PGraphics { tessellator.setStrokeWeight(strokeWeight); tessellator.setStrokeCap(strokeCap); tessellator.setStrokeJoin(strokeJoin); - + setFirstTexIndex(tessGeo.fillIndexCount); - + if (shape == POINTS) { - tessellator.tessellatePoints(); + tessellator.tessellatePoints(); } else if (shape == LINES) { - tessellator.tessellateLines(); + tessellator.tessellateLines(); } else if (shape == TRIANGLE || shape == TRIANGLES) { if (stroke && defaultEdges) inGeo.addTrianglesEdges(); if (normalMode == NORMAL_MODE_AUTO) inGeo.calcTrianglesNormals(); @@ -2251,8 +2249,8 @@ public class PGraphicsOpenGL extends PGraphics { if (normalMode == NORMAL_MODE_AUTO) inGeo.calcTriangleFanNormals(); tessellator.tessellateTriangleFan(); } else if (shape == TRIANGLE_STRIP) { - if (stroke && defaultEdges) inGeo.addTriangleStripEdges(); - if (normalMode == NORMAL_MODE_AUTO) inGeo.calcTriangleStripNormals(); + if (stroke && defaultEdges) inGeo.addTriangleStripEdges(); + if (normalMode == NORMAL_MODE_AUTO) inGeo.calcTriangleStripNormals(); tessellator.tessellateTriangleStrip(); } else if (shape == QUAD || shape == QUADS) { if (stroke && defaultEdges) inGeo.addQuadsEdges(); @@ -2264,71 +2262,71 @@ public class PGraphicsOpenGL extends PGraphics { tessellator.tessellateQuadStrip(); } else if (shape == POLYGON) { if (stroke && defaultEdges) inGeo.addPolygonEdges(mode == CLOSE); - tessellator.tessellatePolygon(false, mode == CLOSE, normalMode == NORMAL_MODE_AUTO); + tessellator.tessellatePolygon(false, mode == CLOSE, normalMode == NORMAL_MODE_AUTO); } - + setLastTexIndex(tessGeo.lastFillIndex); } - - + + protected void setFirstTexIndex(int first) { firstTexIndex = first; } - - - protected void setLastTexIndex(int last) { + + + protected void setLastTexIndex(int last) { if (textureImage0 != textureImage || texCache.count == 0) { texCache.addTexture(textureImage, firstTexIndex, last); } else { texCache.setLastIndex(last); - } + } } - - - public void flush() { + + + public void flush() { boolean hasPoints = 0 < tessGeo.pointVertexCount && 0 < tessGeo.pointIndexCount; boolean hasLines = 0 < tessGeo.lineVertexCount && 0 < tessGeo.lineIndexCount; boolean hasFill = 0 < tessGeo.fillVertexCount && 0 < tessGeo.fillIndexCount; boolean hasPixels = modified && pixels != null; - + if (hasPixels) { // If the user has been manipulating individual pixels, // the changes need to be copied to the screen before - // drawing any new geometry. + // drawing any new geometry. renderPixels(); setgetPixels = false; } - + if (hasPoints || hasLines || hasFill) { if (flushMode == FLUSH_WHEN_FULL && !hints[DISABLE_TRANSFORM_CACHE]) { - // The modelview transformation has been applied already to the + // The modelview transformation has been applied already to the // tessellated vertices, so we set the OpenGL modelview matrix as // the identity to avoid applying the model transformations twice. pushMatrix(); resetMatrix(); } - + if (hasFill) { renderFill(); } - + if (hasPoints) { renderPoints(); - } + } if (hasLines) { renderLines(); - } - + } + if (flushMode == FLUSH_WHEN_FULL && !hints[DISABLE_TRANSFORM_CACHE]) { popMatrix(); } } - - tessGeo.clear(); - texCache.clear(); + + tessGeo.clear(); + texCache.clear(); } - + protected void renderPixels() { int mi1 = my1 * width + mx1; @@ -2340,137 +2338,137 @@ public class PGraphicsOpenGL extends PGraphics { if (rgbaPixels == null || rgbaPixels.length < mlen) { rgbaPixels = new int[mlen]; } - + PApplet.arrayCopy(pixels, mi1, rgbaPixels, 0, mlen); PGL.javaToNativeARGB(rgbaPixels, mw, mh); - - //PApplet.arrayCopy(pixels, rgbaPixels); + + //PApplet.arrayCopy(pixels, rgbaPixels); //PGL.javaToNativeARGB(rgbaPixels, width, height); - + // Copying pixel buffer to screen texture... - pgl.copyToTexture(texture.glTarget, texture.glFormat, texture.glID, + pgl.copyToTexture(texture.glTarget, texture.glFormat, texture.glID, mx1, my1, mw, mh, IntBuffer.wrap(rgbaPixels)); - + if (primarySurface || offscreenMultisample) { // ...and drawing the texture to screen... but only - // if we are on the primary surface or we have + // if we are on the primary surface or we have // multisampled FBO. Why? Because in the case of non- // multisampled FBO, texture is actually the color buffer // used by the color FBO, so with the copy operation we - // should be done updating the (off)screen buffer. + // should be done updating the (off)screen buffer. beginPixelsOp(OP_WRITE); - drawTexture(mx1, my1, mw, mh); + drawTexture(mx1, my1, mw, mh); endPixelsOp(); } - - modified = false; + + modified = false; } - - + + protected void renderPoints() { if (!pointVBOsCreated) { createPointBuffers(); pointVBOsCreated = true; } updatePointBuffers(); - + PointShader shader = getPointShader(); - shader.start(); - shader.setVertexAttribute(glPointVertexBufferID, 3, PGL.GL_FLOAT, 0, 0); - shader.setColorAttribute(glPointColorBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); + shader.start(); + 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; } 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.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); - - pgl.glDrawElements(PGL.GL_TRIANGLES, tessGeo.lineIndexCount, PGL.INDEX_TYPE, 0); - + + pgl.glDrawElements(PGL.GL_TRIANGLES, tessGeo.lineIndexCount, PGL.INDEX_TYPE, 0); + shader.stop(); unbindLineBuffers(); - } - - + } + + protected void renderFill() { if (!fillVBOsCreated) { createFillBuffers(); fillVBOsCreated = true; - } + } updateFillBuffers(lights, texCache.hasTexture); - - texCache.beginRender(); + + texCache.beginRender(); for (int i = 0; i < texCache.count; i++) { - PTexture tex = texCache.getTexture(i); - - FillShader shader = getFillShader(lights, tex != null); + PTexture tex = texCache.getTexture(i); + + FillShader shader = getFillShader(lights, tex != null); shader.start(); - - shader.setVertexAttribute(glFillVertexBufferID, 3, PGL.GL_FLOAT, 0, 0); - shader.setColorAttribute(glFillColorBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); - + + shader.setVertexAttribute(glFillVertexBufferID, 3, PGL.GL_FLOAT, 0, 0); + shader.setColorAttribute(glFillColorBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); + if (lights) { shader.setNormalAttribute(glFillNormalBufferID, 3, PGL.GL_FLOAT, 0, 0); shader.setAmbientAttribute(glFillAmbientBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); shader.setSpecularAttribute(glFillSpecularBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); - shader.setEmissiveAttribute(glFillEmissiveBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); + shader.setEmissiveAttribute(glFillEmissiveBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); shader.setShininessAttribute(glFillShininessBufferID, 1, PGL.GL_FLOAT, 0, 0); } - + if (tex != null) { shader.setTexCoordAttribute(glFillTexCoordBufferID, 2, PGL.GL_FLOAT, 0, 0); shader.setTexture(tex); } - + int offset = texCache.firstIndex[i]; int size = texCache.lastIndex[i] - texCache.firstIndex[i] + 1; pgl.glDrawElements(PGL.GL_TRIANGLES, size, PGL.INDEX_TYPE, offset * PGL.SIZEOF_INDEX); - + shader.stop(); - } - texCache.endRender(); - unbindFillBuffers(); + } + texCache.endRender(); + unbindFillBuffers(); } - + // Utility function to render current tessellated geometry, under the assumption that // the texture is already bound. protected void renderTexFill(PTexture tex) { if (!fillVBOsCreated) { createFillBuffers(); fillVBOsCreated = true; - } + } updateFillBuffers(lights, true); - - FillShader shader = getFillShader(lights, true); + + FillShader shader = getFillShader(lights, true); shader.start(); - - shader.setVertexAttribute(glFillVertexBufferID, 3, PGL.GL_FLOAT, 0, 0); + + shader.setVertexAttribute(glFillVertexBufferID, 3, PGL.GL_FLOAT, 0, 0); shader.setColorAttribute(glFillColorBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); shader.setTexCoordAttribute(glFillTexCoordBufferID, 2, PGL.GL_FLOAT, 0, 0); shader.setTexture(tex); - + if (lights) { shader.setNormalAttribute(glFillNormalBufferID, 3, PGL.GL_FLOAT, 0, 0); shader.setAmbientAttribute(glFillAmbientBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); shader.setSpecularAttribute(glFillSpecularBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); - shader.setEmissiveAttribute(glFillEmissiveBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); + shader.setEmissiveAttribute(glFillEmissiveBufferID, 4, PGL.GL_UNSIGNED_BYTE, 0, 0); shader.setShininessAttribute(glFillShininessBufferID, 1, PGL.GL_FLOAT, 0, 0); } @@ -2478,18 +2476,18 @@ public class PGraphicsOpenGL extends PGraphics { int sizex = size * PGL.SIZEOF_INDEX; pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, glFillIndexBufferID); pgl.glBufferData(PGL.GL_ELEMENT_ARRAY_BUFFER, sizex, ShortBuffer.wrap(tessGeo.fillIndices, 0, size), vboMode); - pgl.glDrawElements(PGL.GL_TRIANGLES, size, PGL.INDEX_TYPE, 0); + pgl.glDrawElements(PGL.GL_TRIANGLES, size, PGL.INDEX_TYPE, 0); pgl.glBindBuffer(PGL.GL_ELEMENT_ARRAY_BUFFER, 0); - + shader.stop(); } - + ////////////////////////////////////////////////////////////// // BEZIER CURVE VERTICES - + public void bezierDetail(int detail) { bezierDetail = detail; @@ -2503,18 +2501,18 @@ public class PGraphicsOpenGL extends PGraphics { // multiply the basis and forward diff matrices together // saves much time since this needn't be done for each curve bezierDrawMatrix.apply(pg.bezierBasisMatrix); - } - - + } + + public void bezierVertex(float x2, float y2, float x3, float y3, float x4, float y4) { - bezierVertex(x2, y2, 0, - x3, y3, 0, - x4, y4, 0); + bezierVertex(x2, y2, 0, + x3, y3, 0, + x4, y4, 0); } - - + + public void bezierVertex(float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4) { @@ -2543,17 +2541,17 @@ public class PGraphicsOpenGL extends PGraphics { y1 += yplot1; yplot1 += yplot2; yplot2 += yplot3; z1 += zplot1; zplot1 += zplot2; zplot2 += zplot3; vertexImpl(x1, y1, z1, 0, 0, BEZIER_VERTEX); - } + } } - - + + 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(); @@ -2565,21 +2563,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) " + @@ -2589,31 +2587,31 @@ public class PGraphicsOpenGL extends PGraphics { throw new RuntimeException("vertex() must be used at least once" + "before bezierVertex() or quadraticVertex()"); } - } + } + - ////////////////////////////////////////////////////////////// - // CATMULL-ROM CURVE VERTICES + // 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]; @@ -2637,16 +2635,16 @@ public class PGraphicsOpenGL extends PGraphics { curveVertices[curveVertexCount-1][Y], curveVertices[curveVertexCount-1][Z]); } - - } - - protected void curveVertexCheck() { + } + + + protected void curveVertexCheck() { if (shape != POLYGON) { throw new RuntimeException("You must use createGeometry() or " + "createGeometry(POLYGON) before curveVertex()"); } - + // to improve code init time, allocate on first use. if (curveVertices == null) { curveVertices = new float[128][3]; @@ -2660,15 +2658,15 @@ 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) { @@ -2700,9 +2698,9 @@ public class PGraphicsOpenGL extends PGraphics { // multiply the basis and forward diff matrices together // saves much time since this needn't be done for each curve curveDrawMatrix.apply(curveBasisMatrix); - } - - + } + + /** * Handle emitting a specific segment of Catmull-Rom curve. This can be * overridden by subclasses that need more efficient rendering options. @@ -2736,14 +2734,14 @@ public class PGraphicsOpenGL extends PGraphics { z0 += zplot1; zplot1 += zplot2; zplot2 += zplot3; vertexImpl(x0, y0, z0, 0, 0, CURVE_VERTEX); } - } + } + - ////////////////////////////////////////////////////////////// // 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 @@ -2762,8 +2760,8 @@ public class PGraphicsOpenGL extends PGraphics { fff, ff, f, 0, 6*fff, 2*ff, 0, 0, 6*fff, 0, 0, 0); - } - + } + ////////////////////////////////////////////////////////////// @@ -2803,18 +2801,18 @@ public class PGraphicsOpenGL extends PGraphics { // public void ellipseMode(int mode) - + public void ellipse(float a, float b, float c, float d) { - beginShape(TRIANGLE_FAN); + beginShape(TRIANGLE_FAN); defaultEdges = false; - inGeo.generateEllipse(ellipseMode, a, b, c, d, - fill, fillColor, + inGeo.generateEllipse(ellipseMode, a, b, c, d, + fill, fillColor, stroke, strokeColor, strokeWeight, ambientColor, specularColor, emissiveColor, shininess); endShape(); } - - + + // public void ellipse(float a, float b, float c, float d) // public void arc(float a, float b, float c, float d, @@ -2823,8 +2821,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; @@ -2886,7 +2884,7 @@ public class PGraphicsOpenGL extends PGraphics { } } - + ////////////////////////////////////////////////////////////// // BOX @@ -2974,56 +2972,56 @@ public class PGraphicsOpenGL extends PGraphics { ////////////////////////////////////////////////////////////// // SMOOTH - - + + public void smooth() { smooth(2); } - - + + public void smooth(int level) { smooth = true; - + if (maxSamples < level) { PGraphics.showWarning("Smooth level " + level + " is not supported by the hardware. Using " + maxSamples + " instead."); - level = maxSamples; + level = maxSamples; } - - if (antialias != level) { + + if (antialias != level) { antialias = level; if (antialias == 1) { antialias = 0; } // This will trigger a surface restart next time // requestDraw() is called. - pgl.initialized = false; + pgl.initialized = false; } } - + public void noSmooth() { smooth = false; - + if (1 < antialias) { antialias = 0; // This will trigger a surface restart next time // requestDraw() is called. - pgl.initialized = false; + pgl.initialized = false; } - } - - + } + + ////////////////////////////////////////////////////////////// // SHAPE // public void shapeMode(int mode) - - + + public void shape(PShape shape, float x, float y, float z) { if (shape.isVisible()) { // don't do expensive matrix ops if invisible flush(); - + pushMatrix(); if (shapeMode == CENTER) { @@ -3038,12 +3036,12 @@ public class PGraphicsOpenGL extends PGraphics { popMatrix(); } } - - + + 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 flush(); - + pushMatrix(); if (shapeMode == CENTER) { @@ -3069,7 +3067,7 @@ public class PGraphicsOpenGL extends PGraphics { popMatrix(); } } - + ////////////////////////////////////////////////////////////// @@ -3103,32 +3101,32 @@ public class PGraphicsOpenGL extends PGraphics { // protected float textWidthImpl(char buffer[], int start, int stop) - + ////////////////////////////////////////////////////////////// // TEXT IMPL - + // protected void textLineAlignImpl(char buffer[], int start, int stop, // float x, float y) - + /** * Implementation of actual drawing for a line of text. */ protected void textLineImpl(char buffer[], int start, int stop, float x, float y) { - textTex = (PFontTexture)textFont.getCache(pg); + textTex = (PFontTexture)textFont.getCache(pg); if (textTex == null) { textTex = new PFontTexture(parent, textFont, maxTextureSize, maxTextureSize); - textFont.setCache(this, textTex); + textFont.setCache(this, textTex); } else { if (textTex.contextIsOutdated()) { - textTex = new PFontTexture(parent, textFont, PApplet.min(PGL.MAX_FONT_TEX_SIZE, maxTextureSize), + 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); } - } - textTex.setFirstTexture(); - + } + textTex.setFirstTexture(); + // Saving style parameters modified by text rendering. int savedTextureMode = textureMode; boolean savedStroke = stroke; @@ -3138,20 +3136,20 @@ public class PGraphicsOpenGL extends PGraphics { boolean savedTint = tint; int savedTintColor = tintColor; int savedBlendMode = blendMode; - + // Setting style used in text rendering. - textureMode = NORMAL; - stroke = false; + textureMode = NORMAL; + stroke = false; normalX = 0; normalY = 0; - normalZ = 1; + normalZ = 1; tint = true; tintColor = fillColor; - + blendMode(BLEND); - + super.textLineImpl(buffer, start, stop, x, y); - + // Restoring original style. textureMode = savedTextureMode; stroke = savedStroke; @@ -3160,7 +3158,7 @@ public class PGraphicsOpenGL extends PGraphics { normalZ = savedNormalZ; tint = savedTint; tintColor = savedTintColor; - + // Note that if the user is using a blending mode different from // BLEND, and has a bunch of continuous text rendering, the performance // won't be optimal because at the end of each text() call the geometry @@ -3168,19 +3166,19 @@ public class PGraphicsOpenGL extends PGraphics { blendMode(savedBlendMode); } - + protected void textCharImpl(char ch, float x, float y) { PFont.Glyph glyph = textFont.getGlyph(ch); - - if (glyph != null) { + + if (glyph != null) { PFontTexture.TextureInfo tinfo = textTex.getTexInfo(glyph); - + if (tinfo == null) { // Adding new glyph to the font texture. tinfo = textTex.addToTexture(glyph); } - - if (textMode == MODEL) { + + if (textMode == MODEL) { float high = glyph.height / (float) textFont.getSize(); float bwidth = glyph.width / (float) textFont.getSize(); float lextent = glyph.leftExtent / (float) textFont.getSize(); @@ -3192,7 +3190,7 @@ public class PGraphicsOpenGL extends PGraphics { float y2 = y1 + high * textSize; textCharModelImpl(tinfo, x1, y1, x2, y2); - } + } } } @@ -3201,75 +3199,75 @@ public class PGraphicsOpenGL extends PGraphics { float x1, float y1) { if (textTex.currentTex != info.texIndex) { textTex.setTexture(info.texIndex); - } + } PImage tex = textTex.getCurrentTexture(); - + beginShape(QUADS); - texture(tex); + texture(tex); vertex(x0, y0, info.u0, info.v0); vertex(x1, y0, info.u1, info.v0); vertex(x1, y1, info.u1, info.v1); vertex(x0, y1, info.u0, info.v1); - endShape(); + endShape(); } - - + + ////////////////////////////////////////////////////////////// // MATRIX STACK - + public void pushMatrix() { modelviewStack.push(new PMatrix3D(modelview)); modelviewInvStack.push(new PMatrix3D(modelviewInv)); } - + public void popMatrix() { if (hints[DISABLE_TRANSFORM_CACHE]) { - flush(); + flush(); } PMatrix3D mat; - + mat = modelviewStack.pop(); modelview.set(mat); - + mat = modelviewInvStack.pop(); modelviewInv.set(mat); - + calcProjmodelview(); } - - + + ////////////////////////////////////////////////////////////// // MATRIX TRANSFORMATIONS - + public void translate(float tx, float ty) { translate(tx, ty, 0); } - + public void translate(float tx, float ty, float tz) { if (hints[DISABLE_TRANSFORM_CACHE]) { - flush(); + flush(); } - - modelview.translate(tx, ty, tz); - invTranslate(modelviewInv, tx, ty, tz); - projmodelview.translate(tx, ty, tz); + + modelview.translate(tx, ty, tz); + invTranslate(modelviewInv, tx, ty, tz); + projmodelview.translate(tx, ty, tz); } - + static protected void invTranslate(PMatrix3D matrix, float tx, float ty, float tz) { matrix.preApply(1, 0, 0, -tx, 0, 1, 0, -ty, 0, 0, 1, -tz, 0, 0, 0, 1); } - - + + /** * Two dimensional rotation. Same as rotateZ (this is identical to a 3D * rotation along the z-axis) but included for clarity -- it'd be weird for @@ -3280,29 +3278,29 @@ public class PGraphicsOpenGL extends PGraphics { rotateZ(angle); } - + public void rotateX(float angle) { rotate(angle, 1, 0, 0); } - + public void rotateY(float angle) { rotate(angle, 0, 1, 0); } - + public void rotateZ(float angle) { rotate(angle, 0, 0, 1); } - + /** * Rotate around an arbitrary vector, similar to glRotate(), except that it * takes radians (instead of degrees). */ public void rotate(float angle, float v0, float v1, float v2) { if (hints[DISABLE_TRANSFORM_CACHE]) { - flush(); + flush(); } modelview.rotate(angle, v0, v1, v2); @@ -3310,7 +3308,7 @@ public class PGraphicsOpenGL extends PGraphics { calcProjmodelview(); // Possibly cheaper than doing projmodelview.rotate() } - + static private void invRotate(PMatrix3D matrix, float angle, float v0, float v1, float v2) { //TODO should make sure this vector is normalized @@ -3322,9 +3320,9 @@ public class PGraphicsOpenGL extends PGraphics { (t*v0*v1) + (s*v2), (t*v1*v1) + c, (t*v1*v2) - (s*v0), 0, (t*v0*v2) - (s*v1), (t*v1*v2) + (s*v0), (t*v2*v2) + c, 0, 0, 0, 0, 1); - } - - + } + + /** * Same as scale(s, s, s). */ @@ -3332,7 +3330,7 @@ public class PGraphicsOpenGL extends PGraphics { scale(s, s, s); } - + /** * Same as scale(sx, sy, 1). */ @@ -3340,89 +3338,89 @@ public class PGraphicsOpenGL extends PGraphics { scale(sx, sy, 1); } - + /** * Scale in three dimensions. */ public void scale(float sx, float sy, float sz) { if (hints[DISABLE_TRANSFORM_CACHE]) { - flush(); + flush(); } modelview.scale(sx, sy, sz); - invScale(modelviewInv, sx, sy, sz); - projmodelview.scale(sx, sy, sz); + invScale(modelviewInv, sx, sy, sz); + projmodelview.scale(sx, sy, sz); } - + static protected void invScale(PMatrix3D matrix, float x, float y, float z) { matrix.preApply(1/x, 0, 0, 0, 0, 1/y, 0, 0, 0, 0, 1/z, 0, 0, 0, 0, 1); } - + public void shearX(float angle) { float t = (float) Math.tan(angle); - applyMatrix(1, t, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, + applyMatrix(1, t, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 1); } - + public void shearY(float angle) { float t = (float) Math.tan(angle); - applyMatrix(1, 0, 0, 0, - t, 1, 0, 0, - 0, 0, 1, 0, + applyMatrix(1, 0, 0, 0, + t, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 1); } - + ////////////////////////////////////////////////////////////// // MATRIX MORE! - + public void resetMatrix() { modelview.reset(); modelviewInv.reset(); projmodelview.set(projection); } - + public void applyMatrix(PMatrix2D source) { - applyMatrix(source.m00, source.m01, source.m02, + applyMatrix(source.m00, source.m01, source.m02, source.m10, source.m11, source.m12); } - - public void applyMatrix(float n00, float n01, float n02, + + public void applyMatrix(float n00, float n01, float n02, float n10, float n11, float n12) { - applyMatrix(n00, n01, n02, 0, - n10, n11, n12, 0, - 0, 0, 1, 0, + applyMatrix(n00, n01, n02, 0, + n10, n11, n12, 0, + 0, 0, 1, 0, 0, 0, 0, 1); } - + public void applyMatrix(PMatrix3D source) { - applyMatrix(source.m00, source.m01, source.m02, source.m03, - source.m10, source.m11, source.m12, source.m13, - source.m20, source.m21, source.m22, source.m23, + applyMatrix(source.m00, source.m01, source.m02, source.m03, + source.m10, source.m11, source.m12, source.m13, + source.m20, source.m21, source.m22, source.m23, source.m30, source.m31, source.m32, source.m33); } - + /** * Apply a 4x4 transformation matrix to the modelview stack. */ public void applyMatrix(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, + float n10, float n11, float n12, float n13, + float n20, float n21, float n22, float n23, float n30, float n31, float n32, float n33) { if (hints[DISABLE_TRANSFORM_CACHE]) { - flush(); - } + flush(); + } modelview.apply(n00, n01, n02, n03, n10, n11, n12, n13, n20, n21, n22, n23, @@ -3435,41 +3433,41 @@ public class PGraphicsOpenGL extends PGraphics { /* protected void loadProjection() { - pgl.setProjectionMode(); + pgl.setProjectionMode(); loadMatrix(projection); pgl.setModelviewMode(); } - - + + protected void loadCamera() { pgl.setModelviewMode(); loadMatrix(camera); } - - + + protected void loadModelview() { pgl.setModelviewMode(); - loadMatrix(modelview); + loadMatrix(modelview); } - + protected void loadMatrix(PMatrix3D pMatrix) { - modelview.set(pMatrix); - } + modelview.set(pMatrix); + } */ - + ////////////////////////////////////////////////////////////// // MATRIX GET/SET/PRINT - + public PMatrix getMatrix() { - return modelview.get(); + return modelview.get(); } - + // public PMatrix2D getMatrix(PMatrix2D target) - + public PMatrix3D getMatrix(PMatrix3D target) { if (target == null) { target = new PMatrix3D(); @@ -3478,16 +3476,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. */ @@ -3496,41 +3494,41 @@ public class PGraphicsOpenGL extends PGraphics { applyMatrix(source); } - + /** * Print the current model (or "transformation") matrix. */ - public void printMatrix() { - modelview.print(); + public void printMatrix() { + modelview.print(); } - - + + ////////////////////////////////////////////////////////////// // PROJECTION - - + + public void pushProjection() { projectionStack.push(new PMatrix3D(projection)); } - - + + public void popProjection() { PMatrix3D mat = projectionStack.pop(); - projection.set(mat); + projection.set(mat); } - + public void applyProjection(PMatrix3D mat) { projection.apply(mat); } - + public void setProjection(PMatrix3D mat) { projection.set(mat); - } - - + } + + ////////////////////////////////////////////////////////////// // CAMERA @@ -3557,25 +3555,25 @@ public class PGraphicsOpenGL extends PGraphics { * setup(), and we expect it to hold through draw(). So we don't reset the * camera transform matrix at the top of draw(). That means that an * innocuous-looking clause like - * + * *
        * beginCamera();
        * translate(0, 0, 10);
        * endCamera();
        * 
    - * + * * at the top of draw(), will result in a runaway camera that shoots * infinitely out of the screen over time. In order to prevent this, it is * necessary to call some function that does a hard reset of the camera * transform matrix inside of begin/endCamera. Two options are - * + * *
        * camera(); // sets up the nice default camera transform
        * resetMatrix(); // sets up the identity camera transform
        * 
    - * + * * So to rotate a camera a constant amount, you might try - * + * *
        * beginCamera();
        * camera();
    @@ -3589,10 +3587,10 @@ public class PGraphicsOpenGL extends PGraphics {
               + "before endCamera()");
         } else {
           manipulatingCamera = true;
    -    }    
    +    }
       }
    -  
    -  
    +
    +
       /**
        * Record the current settings into the camera matrix, and set the matrix mode
        * back to the current transformation matrix.
    @@ -3606,10 +3604,10 @@ public class PGraphicsOpenGL extends PGraphics {
           throw new RuntimeException("Cannot call endCamera() "
               + "without first calling beginCamera()");
         }
    -    
    +
         camera.set(modelview);
         cameraInv.set(modelviewInv);
    -    
    +
         // all done
         manipulatingCamera = false;
       }
    @@ -3653,18 +3651,18 @@ public class PGraphicsOpenGL extends PGraphics {
         camera(cameraX, cameraY, cameraZ, cameraX, cameraY, 0, 0, 1, 0);
       }
     
    -  
    +
       /**
        * More flexible method for dealing with camera().
        * 

    * The actual call is like gluLookat. Here's the real skinny on what does * what: - * + * *

        * camera(); or
        * camera(ex, ey, ez, cx, cy, cz, ux, uy, uz);
        * 
    - * + * * do not need to be called from with beginCamera();/endCamera(); That's * because they always apply to the camera transformation, and they always * totally replace it. That means that any coordinate transforms done before @@ -3678,45 +3676,45 @@ public class PGraphicsOpenGL extends PGraphics { * any coordinate system transforms that occur before them in draw(), but they * will not automatically wipe out the camera transform. This means that they * should be at the top of draw(). It also means that the following: - * + * *
        * beginCamera();
        * rotateY(PI / 8);
        * endCamera();
        * 
    - * + * * will result in a camera that spins without stopping. If you want to just * rotate a small constant amount, try this: - * + * *
        * beginCamera();
        * camera(); // sets up the default view
        * rotateY(PI / 8);
        * endCamera();
        * 
    - * + * * That will rotate a little off of the default view. Note that this is * entirely equivalent to - * + * *
        * camera(); // sets up the default view
        * beginCamera();
        * rotateY(PI / 8);
        * endCamera();
        * 
    - * + * * because camera() doesn't care whether or not it's inside a begin/end * clause. Basically it's safe to use camera() or camera(ex, ey, ez, cx, cy, * cz, ux, uy, uz) as naked calls because they do all the matrix resetting * automatically. */ - public void camera(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, + public void camera(float eyeX, float eyeY, float eyeZ, + float centerX, float centerY, float centerZ, float upX, float upY, float upZ) { if (hints[DISABLE_TRANSFORM_CACHE]) { - flush(); + flush(); } - + // Calculating Z vector float z0 = eyeX - centerX; float z1 = eyeY - centerY; @@ -3731,7 +3729,7 @@ public class PGraphicsOpenGL extends PGraphics { cameraEyeY = eyeY; cameraEyeZ = eyeZ; cameraDepth = mag; - + // Calculating Y vector float y0 = upX; float y1 = upY; @@ -3767,35 +3765,35 @@ public class PGraphicsOpenGL extends PGraphics { y0, y1, y2, 0, z0, z1, z2, 0, 0, 0, 0, 1); - + float tx = -eyeX; float ty = -eyeY; float tz = -eyeZ; modelview.translate(tx, ty, tz); modelviewInv.set(modelview); - modelviewInv.invert(); - + modelviewInv.invert(); + camera.set(modelview); cameraInv.set(modelviewInv); - + calcProjmodelview(); } - - + + /** * Print the current camera matrix. */ public void printCamera() { camera.print(); } - - + + ////////////////////////////////////////////////////////////// // PROJECTION - - + + /** * Calls ortho() with the proper parameters for Processing's standard * orthographic projection. @@ -3804,17 +3802,17 @@ public class PGraphicsOpenGL extends PGraphics { ortho(0, width, 0, height, -500, 500); } - + /** * Calls ortho() with the specified size of the viewing volume along * the X and Z directions. - */ - public void ortho(float left, float right, + */ + public void ortho(float left, float right, float bottom, float top) { ortho(left, right, bottom, top, -500, 500); - } - - + } + + /** * Sets orthographic projection. The left, right, bottom and top * values refer to the top left corner of the screen, not to the @@ -3822,23 +3820,23 @@ public class PGraphicsOpenGL extends PGraphics { * it relative to the camera is not very intuitive if we think * of the perspective function, which is also independent of the * camera position. - * + * */ - public void ortho(float left, float right, + public void ortho(float left, float right, float bottom, float top, float near, float far) { // Flushing geometry with a different perspective configuration. flush(); - + left -= width/2; right -= width/2; - + bottom -= height/2; top -= height/2; - + near += cameraDepth; far += cameraDepth; - + float x = 2.0f / (right - left); float y = 2.0f / (top - bottom); float z = -2.0f / (far - near); @@ -3846,7 +3844,7 @@ public class PGraphicsOpenGL extends PGraphics { float tx = -(right + left) / (right - left); float ty = -(top + bottom) / (top - bottom); float tz = -(far + near) / (far - near); - + // The minus sign is needed to invert the Y axis. projection.set(x, 0, 0, tx, 0, -y, 0, ty, @@ -3854,7 +3852,7 @@ public class PGraphicsOpenGL extends PGraphics { 0, 0, 0, 1); } - + /** * Calls perspective() with Processing's standard coordinate projection. *

    @@ -3879,7 +3877,7 @@ public class PGraphicsOpenGL extends PGraphics { perspective(cameraFOV, cameraAspect, cameraNear, cameraFar); } - + /** * Similar to gluPerspective(). Implementation based on Mesa's glu.c */ @@ -3891,7 +3889,7 @@ public class PGraphicsOpenGL extends PGraphics { frustum(xmin, xmax, ymin, ymax, zNear, zFar); } - + /** * Same as glFrustum(), except that it wipes out (rather than multiplies * against) the current perspective matrix. @@ -3902,7 +3900,7 @@ public class PGraphicsOpenGL extends PGraphics { float znear, float zfar) { // Flushing geometry with a different perspective configuration. flush(); - + float temp, temp2, temp3, temp4; temp = 2.0f * znear; temp2 = right - left; @@ -3914,33 +3912,33 @@ public class PGraphicsOpenGL extends PGraphics { 0, -temp / temp3, (top + bottom) / temp3, 0, 0, 0, (-zfar - znear) / temp4, (-temp * zfar) / temp4, 0, 0, -1, 1); - - calcProjmodelview(); + + calcProjmodelview(); } - + /** * Print the current projection matrix. */ public void printProjection() { projection.print(); - } - - + } + + ////////////////////////////////////////////////////////////// // SCREEN AND MODEL COORDS - + public float screenX(float x, float y) { return screenX(x, y, 0); } - + public float screenY(float x, float y) { return screenY(x, y, 0); } - + public float screenX(float x, float y, float z) { float ax = modelview.m00 * x + modelview.m01 * y + modelview.m02 * z + modelview.m03; @@ -3950,7 +3948,7 @@ public class PGraphicsOpenGL extends PGraphics { float ox = projection.m00 * ax + projection.m01 * ay + projection.m02 * az + projection.m03 * aw; float ow = projection.m30 * ax + projection.m31 * ay + projection.m32 * az + projection.m33 * aw; - + if (ow != 0) { ox /= ow; } @@ -3958,34 +3956,34 @@ public class PGraphicsOpenGL extends PGraphics { return sx; } - - public float screenY(float x, float y, float z) { + + public float screenY(float x, float y, float z) { float ax = modelview.m00 * x + modelview.m01 * y + modelview.m02 * z + modelview.m03; float ay = modelview.m10 * x + modelview.m11 * y + modelview.m12 * z + modelview.m13; float az = modelview.m20 * x + modelview.m21 * y + modelview.m22 * z + modelview.m23; float aw = modelview.m30 * x + modelview.m31 * y + modelview.m32 * z + modelview.m33; - + float oy = projection.m10 * ax + projection.m11 * ay + projection.m12 * az + projection.m13 * aw; float ow = projection.m30 * ax + projection.m31 * ay + projection.m32 * az + projection.m33 * aw; - + if (ow != 0) { oy /= ow; - } + } float sy = height * (1 + oy) / 2.0f; // Turning value upside down because of Processing's inverted Y axis. sy = height - sy; return sy; } - - public float screenZ(float x, float y, float z) { + + public float screenZ(float x, float y, float z) { float ax = modelview.m00 * x + modelview.m01 * y + modelview.m02 * z + modelview.m03; float ay = modelview.m10 * x + modelview.m11 * y + modelview.m12 * z + modelview.m13; float az = modelview.m20 * x + modelview.m21 * y + modelview.m22 * z + modelview.m23; float aw = modelview.m30 * x + modelview.m31 * y + modelview.m32 * z + modelview.m33; - + float oz = projection.m20 * ax + projection.m21 * ay + projection.m22 * az + projection.m23 * aw; - float ow = projection.m30 * ax + projection.m31 * ay + projection.m32 * az + projection.m33 * aw; + float ow = projection.m30 * ax + projection.m31 * ay + projection.m32 * az + projection.m33 * aw; if (ow != 0) { oz /= ow; @@ -3994,39 +3992,39 @@ public class PGraphicsOpenGL extends PGraphics { return sz; } - + public float modelX(float x, float y, float z) { float ax = modelview.m00 * x + modelview.m01 * y + modelview.m02 * z + modelview.m03; float ay = modelview.m10 * x + modelview.m11 * y + modelview.m12 * z + modelview.m13; float az = modelview.m20 * x + modelview.m21 * y + modelview.m22 * z + modelview.m23; float aw = modelview.m30 * x + modelview.m31 * y + modelview.m32 * z + modelview.m33; - + float ox = cameraInv.m00 * ax + cameraInv.m01 * ay + cameraInv.m02 * az + cameraInv.m03 * aw; - float ow = cameraInv.m30 * ax + cameraInv.m31 * ay + cameraInv.m32 * az + cameraInv.m33 * aw; - + float ow = cameraInv.m30 * ax + cameraInv.m31 * ay + cameraInv.m32 * az + cameraInv.m33 * aw; + return (ow != 0) ? ox / ow : ox; } - + public float modelY(float x, float y, float z) { float ax = modelview.m00 * x + modelview.m01 * y + modelview.m02 * z + modelview.m03; float ay = modelview.m10 * x + modelview.m11 * y + modelview.m12 * z + modelview.m13; float az = modelview.m20 * x + modelview.m21 * y + modelview.m22 * z + modelview.m23; float aw = modelview.m30 * x + modelview.m31 * y + modelview.m32 * z + modelview.m33; - + float oy = cameraInv.m10 * ax + cameraInv.m11 * ay + cameraInv.m12 * az + cameraInv.m13 * aw; float ow = cameraInv.m30 * ax + cameraInv.m31 * ay + cameraInv.m32 * az + cameraInv.m33 * aw; return (ow != 0) ? oy / ow : oy; } - + public float modelZ(float x, float y, float z) { float ax = modelview.m00 * x + modelview.m01 * y + modelview.m02 * z + modelview.m03; float ay = modelview.m10 * x + modelview.m11 * y + modelview.m12 * z + modelview.m13; float az = modelview.m20 * x + modelview.m21 * y + modelview.m22 * z + modelview.m23; float aw = modelview.m30 * x + modelview.m31 * y + modelview.m32 * z + modelview.m33; - + float oz = cameraInv.m20 * ax + cameraInv.m21 * ay + cameraInv.m22 * az + cameraInv.m23 * aw; float ow = cameraInv.m30 * ax + cameraInv.m31 * ay + cameraInv.m32 * az + cameraInv.m33 * aw; @@ -4040,7 +4038,7 @@ public class PGraphicsOpenGL extends PGraphics { // public void style(PStyle) // public PStyle getStyle() // public void getStyle(PStyle) - + ////////////////////////////////////////////////////////////// // COLOR MODE @@ -4066,22 +4064,22 @@ 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; } - - + + ////////////////////////////////////////////////////////////// // LIGHTING @@ -4089,7 +4087,7 @@ public class PGraphicsOpenGL extends PGraphics { /** * Sets up an ambient and directional light using OpenGL. API taken from * PGraphics3D. - * + * *

        * The Lighting Skinny:
        * The way lighting works is complicated enough that it's worth
    @@ -4197,11 +4195,11 @@ public class PGraphicsOpenGL extends PGraphics {
     
         ambientLight(colorModeX * 0.5f, colorModeY * 0.5f, colorModeZ * 0.5f);
         directionalLight(colorModeX * 0.5f, colorModeY * 0.5f, colorModeZ * 0.5f, 0, 0, -1);
    -    
    +
         colorMode = colorModeSaved;
       }
     
    -  
    +
       /**
        * Disables lighting.
        */
    @@ -4210,7 +4208,7 @@ public class PGraphicsOpenGL extends PGraphics {
         lightCount = 0;
       }
     
    -  
    +
       /**
        * Add an ambient light based on the current color mode.
        */
    @@ -4218,7 +4216,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.
    @@ -4228,102 +4226,102 @@ public class PGraphicsOpenGL extends PGraphics {
         if (lightCount == PGL.MAX_LIGHTS) {
           throw new RuntimeException("can only create " + PGL.MAX_LIGHTS + " lights");
         }
    -    
    +
         lightType[lightCount] = AMBIENT;
    -    
    +
         lightPosition(lightCount, x, y, z, false);
         lightNormal(lightCount, 0, 0, 0);
    -        
    +
         lightAmbient(lightCount, r, g, b);
         noLightDiffuse(lightCount);
         noLightSpecular(lightCount);
         noLightSpot(lightCount);
    -    lightFalloff(lightCount, currentLightFalloffConstant, 
    -                             currentLightFalloffLinear, 
    +    lightFalloff(lightCount, currentLightFalloffConstant,
    +                             currentLightFalloffLinear,
                                  currentLightFalloffQuadratic);
    -    
    +
         lightCount++;
       }
    -  
     
    -  public void directionalLight(float r, float g, float b, 
    +
    +  public void directionalLight(float r, float g, float b,
                                    float dx, float dy, float dz) {
         enableLighting();
         if (lightCount == PGL.MAX_LIGHTS) {
           throw new RuntimeException("can only create " + PGL.MAX_LIGHTS + " lights");
         }
    -    
    +
         lightType[lightCount] = DIRECTIONAL;
     
         lightPosition(lightCount, 0, 0, 0, true);
         lightNormal(lightCount, dx, dy, dz);
    -        
    +
         noLightAmbient(lightCount);
         lightDiffuse(lightCount, r, g, b);
    -    lightSpecular(lightCount, currentLightSpecular[0], 
    -                              currentLightSpecular[1], 
    -                              currentLightSpecular[2]);        
    +    lightSpecular(lightCount, currentLightSpecular[0],
    +                              currentLightSpecular[1],
    +                              currentLightSpecular[2]);
         noLightSpot(lightCount);
         noLightFalloff(lightCount);
     
         lightCount++;
       }
     
    -  
    -  public void pointLight(float r, float g, float b, 
    +
    +  public void pointLight(float r, float g, float b,
                              float x, float y, float z) {
    -    enableLighting();   
    +    enableLighting();
         if (lightCount == PGL.MAX_LIGHTS) {
           throw new RuntimeException("can only create " + PGL.MAX_LIGHTS + " lights");
         }
    -    
    +
         lightType[lightCount] = POINT;
     
         lightPosition(lightCount, x, y, z, false);
         lightNormal(lightCount, 0, 0, 0);
    -    
    +
         noLightAmbient(lightCount);
         lightDiffuse(lightCount, r, g, b);
    -    lightSpecular(lightCount, currentLightSpecular[0], 
    -                              currentLightSpecular[1], 
    +    lightSpecular(lightCount, currentLightSpecular[0],
    +                              currentLightSpecular[1],
                                   currentLightSpecular[2]);
         noLightSpot(lightCount);
    -    lightFalloff(lightCount, currentLightFalloffConstant, 
    -                             currentLightFalloffLinear, 
    +    lightFalloff(lightCount, currentLightFalloffConstant,
    +                             currentLightFalloffLinear,
                                  currentLightFalloffQuadratic);
    -    
    +
         lightCount++;
       }
     
    -  
    -  public void spotLight(float r, float g, float b, 
    +
    +  public void spotLight(float r, float g, float b,
                             float x, float y, float z,
    -                        float dx, float dy, float dz, 
    +                        float dx, float dy, float dz,
                             float angle, float concentration) {
    -    enableLighting();  
    +    enableLighting();
         if (lightCount == PGL.MAX_LIGHTS) {
           throw new RuntimeException("can only create " + PGL.MAX_LIGHTS + " lights");
         }
    -    
    +
         lightType[lightCount] = SPOT;
     
         lightPosition(lightCount, x, y, z, false);
         lightNormal(lightCount, dx, dy, dz);
    -        
    +
         noLightAmbient(lightCount);
         lightDiffuse(lightCount, r, g, b);
    -    lightSpecular(lightCount, currentLightSpecular[0], 
    -                              currentLightSpecular[1], 
    +    lightSpecular(lightCount, currentLightSpecular[0],
    +                              currentLightSpecular[1],
                                   currentLightSpecular[2]);
    -    lightSpot(lightCount, angle, concentration);    
    -    lightFalloff(lightCount, currentLightFalloffConstant, 
    -                             currentLightFalloffLinear, 
    -                             currentLightFalloffQuadratic);    
    -    
    +    lightSpot(lightCount, angle, concentration);
    +    lightFalloff(lightCount, currentLightFalloffConstant,
    +                             currentLightFalloffLinear,
    +                             currentLightFalloffQuadratic);
    +
         lightCount++;
       }
     
    -  
    +
       /**
        * Set the light falloff rates for the last light that was created. Default is
        * lightFalloff(1, 0, 0).
    @@ -4334,7 +4332,7 @@ public class PGraphicsOpenGL extends PGraphics {
         currentLightFalloffQuadratic = quadratic;
       }
     
    -  
    +
       /**
        * Set the specular color of the last light created.
        */
    @@ -4345,54 +4343,54 @@ public class PGraphicsOpenGL extends PGraphics {
         currentLightSpecular[2] = calcB;
       }
     
    -  
    +
       protected void enableLighting() {
    -    if (!lights) {      
    -      flush(); // Flushing non-lit geometry.      
    +    if (!lights) {
    +      flush(); // Flushing non-lit geometry.
           lights = true;
         }
       }
    -  
    +
     
       protected void disableLighting() {
    -    if (lights) {      
    -      flush(); // Flushing lit geometry.      
    +    if (lights) {
    +      flush(); // Flushing lit geometry.
           lights = false;
         }
    -  }  
    -  
    -  
    +  }
    +
    +
       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;
         lightPosition[4 * num + 2] = x * modelview.m20 + y * modelview.m21 + z * modelview.m22 + modelview.m23;
    -    
    +
         // Used to inicate if the light is directional or not.
         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.
         float nx = dx * modelviewInv.m00 + dy * modelviewInv.m10 + dz * modelviewInv.m20;
         float ny = dx * modelviewInv.m01 + dy * modelviewInv.m11 + dz * modelviewInv.m21;
    -    float nz = dx * modelviewInv.m02 + dy * modelviewInv.m12 + dz * modelviewInv.m22;    
    -    
    +    float nz = dx * modelviewInv.m02 + dy * modelviewInv.m12 + dz * modelviewInv.m22;
    +
         float invn = 1.0f / PApplet.dist(0, 0, 0, nx, ny, nz);
         lightNormal[3 * num + 0] = invn * nx;
         lightNormal[3 * num + 1] = invn * ny;
         lightNormal[3 * num + 2] = invn * nz;
       }
    -  
    -  
    -  protected void lightAmbient(int num, float r, float g, float b) {       
    +
    +
    +  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;
    @@ -4400,14 +4398,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;
    @@ -4415,52 +4413,52 @@ 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;
       }
    -  
    -  
    +
    +
       //////////////////////////////////////////////////////////////
     
       // BACKGROUND
     
    -  
    +
       protected void backgroundImpl(PImage image) {
         backgroundImpl();
         set(0, 0, image);
    @@ -4469,28 +4467,28 @@ public class PGraphicsOpenGL extends PGraphics {
         }
       }
     
    -  
    +
       protected void backgroundImpl() {
    -    tessGeo.clear();  
    +    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);
         if (0 < parent.frameCount) {
           clearColorBuffer = true;
         }
    -  }  
    -  
    -  
    +  }
    +
    +
       //////////////////////////////////////////////////////////////
     
       // COLOR MODE
    @@ -4529,7 +4527,7 @@ public class PGraphicsOpenGL extends PGraphics {
       // WARNINGS and EXCEPTIONS
     
       // showWarning() and showException() available from PGraphics.
    -  
    +
       /**
        * Report on anything from glError().
        * Don't use this inside glBegin/glEnd otherwise it'll
    @@ -4545,8 +4543,8 @@ public class PGraphicsOpenGL extends PGraphics {
           }
         }
       }
    -  
    -  
    +
    +
       //////////////////////////////////////////////////////////////
     
       // RENDERER SUPPORT QUERIES
    @@ -4554,28 +4552,28 @@ public class PGraphicsOpenGL extends PGraphics {
       // public boolean displayable()
     
       // public boolean dimensional() // from P3D
    -  
    -  
    +
    +
       /**
        * Return true if this renderer supports 2D drawing. Defaults to true.
        */
       public boolean is2D() {
         return true;
       }
    -  
    +
     
       /**
        * Return true if this renderer supports 2D drawing. Defaults to false.
        */
       public boolean is3D() {
         return true;
    -  }  
    +  }
    +
     
    -  
       public boolean isGL() {
         return true;
    -  }  
    -  
    +  }
    +
     
       //////////////////////////////////////////////////////////////
     
    @@ -4585,190 +4583,190 @@ public class PGraphicsOpenGL extends PGraphics {
       // setCache, getCache, removeCache
       // isModified, setModified
     
    -  
    +
       //////////////////////////////////////////////////////////////
     
       // LOAD/UPDATE PIXELS
     
    -  
    +
       // Initializes the pixels array, copying the current contents of the
       // color buffer into it.
       public void loadPixels() {
         if (!setgetPixels) {
    -      // Draws any remaining geometry in case the user is still not 
    +      // Draws any remaining geometry in case the user is still not
           // setting/getting new pixels.
    -      flush();         
    +      flush();
         }
    -    
    +
         if ((pixels == null) || (pixels.length != width * height)) {
    -      pixels = new int[width * height];      
    -      pixelBuffer = IntBuffer.wrap(pixels);      
    +      pixels = new int[width * height];
    +      pixelBuffer = IntBuffer.wrap(pixels);
         }
    -    
    +
         if (!setgetPixels) {
    -      beginPixelsOp(OP_READ);        
    +      beginPixelsOp(OP_READ);
           pixelBuffer.rewind();
           pgl.glReadPixels(0, 0, width, height, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, pixelBuffer);
    -      endPixelsOp();        
    -      
    -      PGL.nativeToJavaARGB(pixels, width, height);      
    -      
    +      endPixelsOp();
    +
    +      PGL.nativeToJavaARGB(pixels, width, height);
    +
           if (primarySurface) {
             loadTextureImpl(POINT);
             pixelsToTexture();
           }
         }
       }
    -  
    +
     
       //////////////////////////////////////////////////////////////
     
       // GET/SET PIXELS
    -  
    -  
    +
    +
       public int get(int x, int y) {
         loadPixels();
         setgetPixels = true;
         return super.get(x, y);
       }
     
    -  
    +
       protected PImage getImpl(int x, int y, int w, int h) {
         loadPixels();
         setgetPixels = true;
         return super.getImpl(x, y, w, h);
       }
     
    -  
    +
       public void set(int x, int y, int argb) {
         loadPixels();
    -    setgetPixels = true;  
    +    setgetPixels = true;
         super.set(x, y, argb);
       }
     
    -  
    +
       protected void setImpl(int dx, int dy, int sx, int sy, int sw, int sh,
                              PImage src) {
         loadPixels();
         setgetPixels = true;
         super.setImpl(dx, dy, sx, sy, sw, sh, src);
    -  } 
    -    
    -  
    +  }
    +
    +
       //////////////////////////////////////////////////////////////
     
       // LOAD/UPDATE TEXTURE
    -  
    -  
    +
    +
       // Copies the contents of the color buffer into the pixels
       // array, and then the pixels array into the screen texture.
       public void loadTexture() {
         if (primarySurface) {
    -      loadTextureImpl(POINT);      
    -      loadPixels();      
    +      loadTextureImpl(POINT);
    +      loadPixels();
           pixelsToTexture();
         }
       }
    -    
    -  
    +
    +
       // Draws wherever it is in the screen texture right now to the screen.
       public void updateTexture() {
    -    flush();    
    +    flush();
         beginPixelsOp(OP_WRITE);
    -    drawTexture();    
    -    endPixelsOp();   
    +    drawTexture();
    +    endPixelsOp();
       }
    -  
    -  
    +
    +
       protected void loadTextureImpl(int sampling) {
         if (width == 0 || height == 0) return;
         if (texture == null || texture.contextIsOutdated()) {
           PTexture.Parameters params = PTexture.newParameters(ARGB, sampling);
    -      texture = new PTexture(parent, width, height, params);      
    +      texture = new PTexture(parent, width, height, params);
           texture.setFlippedY(true);
           this.setCache(pg, texture);
           this.setParams(pg, params);
         }
    -  }   
    -  
    -  
    +  }
    +
    +
       protected void drawTexture() {
    -    pgl.drawTexture(texture.glTarget, texture.glID, 
    +    pgl.drawTexture(texture.glTarget, texture.glID,
                         texture.glWidth, texture.glHeight,
                         0, 0, width, height);
       }
     
    -  
    +
       protected void drawTexture(int x, int y, int w, int h) {
    -    pgl.drawTexture(texture.glTarget, texture.glID, 
    +    pgl.drawTexture(texture.glTarget, texture.glID,
                         texture.glWidth, texture.glHeight,
                         x, y, x + w, y + h);
       }
    -  
    -  
    -  protected void pixelsToTexture() {    
    +
    +
    +  protected void pixelsToTexture() {
         texture.set(pixels);
       }
    -  
    -  
    +
    +
       protected void textureToPixels() {
         texture.get(pixels);
       }
    -  
    -  
    +
    +
       //////////////////////////////////////////////////////////////
     
       // IMAGE CONVERSION
    -  
    -  
    +
    +
       static public void nativeToJavaRGB(PImage image) {
         if (image.pixels != null) {
    -      PGL.nativeToJavaRGB(image.pixels, image.width, image.height);  
    -    }    
    +      PGL.nativeToJavaRGB(image.pixels, image.width, image.height);
    +    }
       }
     
     
       static public void nativeToJavaARGB(PImage image) {
         if (image.pixels != null) {
    -      PGL.nativeToJavaARGB(image.pixels, image.width, image.height);  
    -    }    
    +      PGL.nativeToJavaARGB(image.pixels, image.width, image.height);
    +    }
       }
    -  
    +
     
       static public void javaToNativeRGB(PImage image) {
         if (image.pixels != null) {
    -      PGL.javaToNativeRGB(image.pixels, image.width, image.height);  
    -    } 
    -  }
    -  
    -  
    -  static public void javaToNativeARGB(PImage image) {
    -    if (image.pixels != null) {
    -      PGL.javaToNativeARGB(image.pixels, image.width, image.height);  
    -    } 
    +      PGL.javaToNativeRGB(image.pixels, image.width, image.height);
    +    }
       }
     
    -  
    +
    +  static public void javaToNativeARGB(PImage image) {
    +    if (image.pixels != null) {
    +      PGL.javaToNativeARGB(image.pixels, image.width, image.height);
    +    }
    +  }
    +
    +
       //////////////////////////////////////////////////////////////
     
       // MASK
     
    -  
    +
       public void mask(int alpha[]) {
         PGraphics.showMethodWarning("mask");
       }
    -  
    +
     
       public void mask(PImage alpha) {
         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,
    @@ -4780,7 +4778,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,
    @@ -4792,7 +4790,7 @@ public class PGraphicsOpenGL extends PGraphics {
         set(0, 0, temp);
       }
     
    -  
    +
       //////////////////////////////////////////////////////////////
     
       /**
    @@ -4811,7 +4809,7 @@ public class PGraphicsOpenGL extends PGraphics {
       // int sx1, int sy1, int sx2, int sy2,
       // int dx1, int dy1, int dx2, int dy2)
     
    -  
    +
       //////////////////////////////////////////////////////////////
     
       // BLEND
    @@ -4823,7 +4821,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
    @@ -4846,7 +4844,7 @@ public class PGraphicsOpenGL extends PGraphics {
       // updatePixels();
       // }
     
    -  
    +
       /**
        * Allows to set custom blend modes for the entire scene, using openGL.
        * Reference article about blending modes:
    @@ -4857,13 +4855,13 @@ public class PGraphicsOpenGL extends PGraphics {
           // Flushing any remaining geometry that uses a different blending
           // mode.
           flush();
    -    
    +
           blendMode = mode;
           pgl.glEnable(PGL.GL_BLEND);
    -      
    +
           if (mode == REPLACE) {
    -        if (blendEqSupported) { 
    -          pgl.glBlendEquation(PGL.GL_FUNC_ADD);          
    +        if (blendEqSupported) {
    +          pgl.glBlendEquation(PGL.GL_FUNC_ADD);
             }
             pgl.glBlendFunc(PGL.GL_ONE, PGL.GL_ZERO);
           } else if (mode == BLEND) {
    @@ -4882,7 +4880,7 @@ public class PGraphicsOpenGL extends PGraphics {
             }
             pgl.glBlendFunc(PGL.GL_ONE_MINUS_DST_COLOR, PGL.GL_ZERO);
           } else if (mode == LIGHTEST) {
    -        if (blendEqSupported) { 
    +        if (blendEqSupported) {
               pgl.glBlendEquation(PGL.GL_FUNC_MAX);
             } else {
               PGraphics.showWarning("This blend mode is not supported");
    @@ -4895,7 +4893,7 @@ public class PGraphicsOpenGL extends PGraphics {
             } else {
               PGraphics.showWarning("This blend mode is not supported");
               return;
    -        }        
    +        }
             pgl.glBlendFunc(PGL.GL_SRC_ALPHA, PGL.GL_DST_ALPHA);
           } else if (mode == DIFFERENCE) {
             if (blendEqSupported) {
    @@ -4903,7 +4901,7 @@ public class PGraphicsOpenGL extends PGraphics {
             } else {
               PGraphics.showWarning("This blend mode is not supported");
               return;
    -        }        
    +        }
             pgl.glBlendFunc(PGL.GL_ONE, PGL.GL_ONE);
           } else if (mode == EXCLUSION) {
             if (blendEqSupported) {
    @@ -4920,14 +4918,14 @@ public class PGraphicsOpenGL extends PGraphics {
               pgl.glBlendEquation(PGL.GL_FUNC_ADD);
             }
             pgl.glBlendFunc(PGL.GL_ONE_MINUS_DST_COLOR, PGL.GL_ONE);
    -      }  
    +      }
           // HARD_LIGHT, SOFT_LIGHT, OVERLAY, DODGE, BURN modes cannot be implemented
           // in fixed-function pipeline because they require conditional blending and
           // non-linear blending equations.
         }
       }
     
    -  
    +
       protected void setDefaultBlend() {
         blendMode = BLEND;
         pgl.glEnable(PGL.GL_BLEND);
    @@ -4936,83 +4934,83 @@ public class PGraphicsOpenGL extends PGraphics {
         }
         pgl.glBlendFunc(PGL.GL_SRC_ALPHA, PGL.GL_ONE_MINUS_SRC_ALPHA);
       }
    -  
    -  
    +
    +
       //////////////////////////////////////////////////////////////
     
       // SAVE
     
       // public void save(String filename) // PImage calls loadPixels()
     
    -  
    +
       //////////////////////////////////////////////////////////////
    -  
    -  // SHAPE I/O  
    -  
    -  
    +
    +  // SHAPE I/O
    +
    +
       protected String[] getSupportedShapeFormats() {
         return new String[] { "obj" };
       }
    -    
    -  
    +
    +
       protected PShape loadShape(String filename, Object params) {
         return null;
         //return new PShape3D(parent, filename, (PShape3D.Parameters)params);
       }
    -  
    -  
    +
    +
       protected PShape createShape(int size, Object params) {
         return null;
         //return new PShape3D(parent, size, (PShape3D.Parameters)params);
       }
    -  
    -  
    -  //////////////////////////////////////////////////////////////
    -  
    -  // TEXTURE UTILS  
     
    -  
    +
    +  //////////////////////////////////////////////////////////////
    +
    +  // TEXTURE UTILS
    +
    +
       /**
        * This utility method returns the texture associated to the renderer's.
        * drawing surface, making sure is updated to reflect the current contents
        * off the screen (or offscreen drawing surface).
    -   */    
    -  public PTexture getTexture() {    
    +   */
    +  public PTexture getTexture() {
         loadTexture();
         return texture;
       }
    -  
    -  
    +
    +
       /**
        * This utility method returns the texture associated to the image.
        * creating and/or updating it if needed.
    -   * 
    +   *
        * @param img the image to have a texture metadata associated to it
    -   */  
    +   */
       public PTexture getTexture(PImage img) {
         PTexture tex = (PTexture)img.getCache(pg);
         if (tex == null) {
    -      tex = addTexture(img);      
    -    } else {       
    +      tex = addTexture(img);
    +    } else {
           if (tex.contextIsOutdated()) {
             tex = addTexture(img);
           }
    -      
    +
           if (img.isModified()) {
             if (img.width != tex.width || img.height != tex.height) {
               tex.init(img.width, img.height);
             }
    -        updateTexture(img, tex);        
    +        updateTexture(img, tex);
           }
    -            
    +
           if (tex.hasBuffers()) {
             tex.bufferUpdate();
    -      }      
    +      }
         }
         return tex;
       }
     
    -  
    +
       /**
        * This utility method creates a texture for the provided image, and adds it
        * to the metadata cache of the image.
    @@ -5023,73 +5021,73 @@ public class PGraphicsOpenGL extends PGraphics {
         if (params == null) {
           params = PTexture.newParameters();
           img.setParams(pg, params);
    -    }    
    -    PTexture tex = new PTexture(img.parent, img.width, img.height, params);    
    -    img.loadPixels();    
    +    }
    +    PTexture tex = new PTexture(img.parent, img.width, img.height, params);
    +    img.loadPixels();
         if (img.pixels != null) tex.set(img.pixels);
         img.setCache(pg, tex);
         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.
         PImage img = new PImage();
         img.parent = parent;
    -    img.width = tex.width; 
    +    img.width = tex.width;
         img.height = tex.height;
    -    img.format = ARGB;    
    +    img.format = ARGB;
         img.setCache(pg, tex);
         return img;
       }
    -    
    -  
    -  protected void updateTexture(PImage img, PTexture tex) {    
    +
    +
    +  protected void updateTexture(PImage img, PTexture tex) {
         if (tex != null) {
           int x = img.getModifiedX1();
           int y = img.getModifiedY1();
           int w = img.getModifiedX2() - x + 1;
    -      int h = img.getModifiedY2() - y + 1;      
    +      int h = img.getModifiedY2() - y + 1;
           tex.set(img.pixels, x, y, w, h, img.format);
         }
         img.setModified(false);
       }
    -  
    -  
    +
    +
       //////////////////////////////////////////////////////////////
     
       // RESIZE
     
    -  
    +
       public void resize(int wide, int high) {
         PGraphics.showMethodWarning("resize");
       }
    -  
    -  
    +
    +
       //////////////////////////////////////////////////////////////
    -  
    -  // INITIALIZATION ROUTINES    
    -  
    +
    +  // INITIALIZATION ROUTINES
    +
     
       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);
    -    
    +
         pgl.updateOffscreen(pg.pgl);
         loadTextureImpl(BILINEAR);
    -        
    +
         // In case of reinitialization (for example, when the smooth level
         // is changed), we make sure that all the OpenGL resources associated
         // to the surface are released by calling delete().
    @@ -5099,81 +5097,81 @@ public class PGraphicsOpenGL extends PGraphics {
         if (offscreenFramebufferMultisample != null) {
           offscreenFramebufferMultisample.release();
         }
    -    
    +
         if (PGraphicsOpenGL.fboMultisampleSupported && 1 < antialias) {
    -      offscreenFramebufferMultisample = new PFramebuffer(parent, texture.glWidth, texture.glHeight, antialias, 0, 
    -                                                         depthBits, stencilBits, 
    +      offscreenFramebufferMultisample = new PFramebuffer(parent, texture.glWidth, texture.glHeight, antialias, 0,
    +                                                         depthBits, stencilBits,
                                                              depthBits == 24 && stencilBits == 8 && packedDepthStencilSupported, false);
    -      
    +
           offscreenFramebufferMultisample.clear();
           offscreenMultisample = true;
    -      
    +
           // The offscreen framebuffer where the multisampled image is finally drawn to doesn't
           // need depth and stencil buffers since they are part of the multisampled framebuffer.
    -      offscreenFramebuffer = new PFramebuffer(parent, texture.glWidth, texture.glHeight, 1, 1, 
    +      offscreenFramebuffer = new PFramebuffer(parent, texture.glWidth, texture.glHeight, 1, 1,
                                                   0, 0,
                                                   false, false);
    -            
    +
         } else {
           antialias = 0;
    -      offscreenFramebuffer = new PFramebuffer(parent, texture.glWidth, texture.glHeight, 1, 1, 
    +      offscreenFramebuffer = new PFramebuffer(parent, texture.glWidth, texture.glHeight, 1, 1,
                                                   depthBits, stencilBits,
                                                   depthBits == 24 && stencilBits == 8 && packedDepthStencilSupported, false);
           offscreenMultisample = false;
         }
    -    
    +
         offscreenFramebuffer.setColorBuffer(texture);
    -    offscreenFramebuffer.clear(); 
    +    offscreenFramebuffer.clear();
       }
     
    -  
    +
       protected void getGLParameters() {
    -    OPENGL_VENDOR     = pgl.glGetString(PGL.GL_VENDOR);  
    +    OPENGL_VENDOR     = pgl.glGetString(PGL.GL_VENDOR);
         OPENGL_RENDERER   = pgl.glGetString(PGL.GL_RENDERER);
    -    OPENGL_VERSION    = pgl.glGetString(PGL.GL_VERSION);    
    +    OPENGL_VERSION    = pgl.glGetString(PGL.GL_VERSION);
         OPENGL_EXTENSIONS = pgl.glGetString(PGL.GL_EXTENSIONS);
    -    
    +
         npotTexSupported            = -1 < OPENGL_EXTENSIONS.indexOf("texture_non_power_of_two");
         mipmapGeneration            = -1 < OPENGL_EXTENSIONS.indexOf("generate_mipmap");
         fboMultisampleSupported     = -1 < OPENGL_EXTENSIONS.indexOf("framebuffer_multisample");
    -    packedDepthStencilSupported = -1 < OPENGL_EXTENSIONS.indexOf("packed_depth_stencil");   
    -    
    -    try {      
    +    packedDepthStencilSupported = -1 < OPENGL_EXTENSIONS.indexOf("packed_depth_stencil");
    +
    +    try {
           pgl.glBlendEquation(PGL.GL_FUNC_ADD);
           blendEqSupported = true;
         } catch (UnsupportedOperationException e) {
           blendEqSupported = false;
         }
    -    
    +
         int temp[] = new int[2];
    -    
    -    pgl.glGetIntegerv(PGL.GL_MAX_TEXTURE_SIZE, temp, 0);    
    -    maxTextureSize = temp[0];  
    +
    +    pgl.glGetIntegerv(PGL.GL_MAX_TEXTURE_SIZE, temp, 0);
    +    maxTextureSize = temp[0];
     
         pgl.glGetIntegerv(PGL.GL_MAX_SAMPLES, temp, 0);
    -    maxSamples = temp[0];    
    -    
    -    pgl.glGetIntegerv(PGL.GL_ALIASED_LINE_WIDTH_RANGE, temp, 0);    
    +    maxSamples = temp[0];
    +
    +    pgl.glGetIntegerv(PGL.GL_ALIASED_LINE_WIDTH_RANGE, temp, 0);
         maxLineWidth = temp[1];
    -    
    +
         pgl.glGetIntegerv(PGL.GL_ALIASED_POINT_SIZE_RANGE, temp, 0);
    -    maxPointSize = temp[1];        
    -    
    -    pgl.glGetIntegerv(PGL.GL_DEPTH_BITS, temp, 0);    
    +    maxPointSize = temp[1];
    +
    +    pgl.glGetIntegerv(PGL.GL_DEPTH_BITS, temp, 0);
         depthBits = temp[0];
    -    
    -    pgl.glGetIntegerv(PGL.GL_STENCIL_BITS, temp, 0);    
    +
    +    pgl.glGetIntegerv(PGL.GL_STENCIL_BITS, temp, 0);
         stencilBits = temp[0];
    -    
    +
         glParamsRead = true;
       }
    -  
    -   
    +
    +
       //////////////////////////////////////////////////////////////
    -  
    +
       // SHADER HANDLING
     
    -  
    +
       public PShader loadShader(String vertFilename, String fragFilename, int kind) {
         if (kind == FILL_SHADER_SIMPLE) {
           return new FillShaderSimple(parent, vertFilename, fragFilename);
    @@ -5185,15 +5183,15 @@ public class PGraphicsOpenGL extends PGraphics {
           return new FillShaderFull(parent, vertFilename, fragFilename);
         } else if (kind == LINE_SHADER) {
           return new LineShader(parent, vertFilename, fragFilename);
    -    } else if (kind == POINT_SHADER) {      
    +    } else if (kind == POINT_SHADER) {
           return new PointShader(parent, vertFilename, fragFilename);
         } else {
           PGraphics.showWarning("Wrong shader type");
           return null;
         }
       }
    -  
    -  
    +
    +
       public PShader loadShader(String fragFilename, int kind) {
         PShader shader;
         if (kind == FILL_SHADER_SIMPLE) {
    @@ -5219,12 +5217,12 @@ public class PGraphicsOpenGL extends PGraphics {
           return null;
         }
         shader.setFragmentShader(fragFilename);
    -    return shader;    
    -  }  
    -  
    +    return shader;
    +  }
    +
     
       public void setShader(PShader shader, int kind) {
    -    if (kind == FILL_SHADER_SIMPLE) {      
    +    if (kind == FILL_SHADER_SIMPLE) {
           fillShaderSimple = (FillShaderSimple) shader;
         } else if (kind == FILL_SHADER_LIT) {
           fillShaderLit = (FillShaderLit) shader;
    @@ -5234,67 +5232,67 @@ public class PGraphicsOpenGL extends PGraphics {
           fillShaderFull = (FillShaderFull) shader;
         } else if (kind == LINE_SHADER) {
           lineShader = (LineShader) shader;
    -    } else if (kind == POINT_SHADER) {      
    +    } else if (kind == POINT_SHADER) {
           pointShader = (PointShader) shader;
         } else {
           PGraphics.showWarning("Wrong shader type");
    -    }    
    +    }
       }
     
    -  
    +
       public void resetShader(int kind) {
         if (kind == FILL_SHADER_SIMPLE) {
           if (defFillShaderSimple == null) {
    -        defFillShaderSimple = new FillShaderSimple(parent, defFillShaderVertSimpleURL, defFillShaderFragNoTexURL);       
    -      }      
    +        defFillShaderSimple = new FillShaderSimple(parent, defFillShaderVertSimpleURL, defFillShaderFragNoTexURL);
    +      }
           fillShaderSimple = defFillShaderSimple;
         } else if (kind == FILL_SHADER_LIT) {
           if (defFillShaderLit == null) {
             defFillShaderLit = new FillShaderLit(parent, defFillShaderVertLitURL, defFillShaderFragNoTexURL);
    -      }      
    +      }
           fillShaderLit = defFillShaderLit;
         } else if (kind == FILL_SHADER_TEX) {
           if (defFillShaderTex == null) {
             defFillShaderTex = new FillShaderTex(parent, defFillShaderVertTexURL, defFillShaderFragTexURL);
    -      }      
    +      }
           fillShaderTex = defFillShaderTex;
         } else if (kind == FILL_SHADER_FULL) {
           if (defFillShaderFull == null) {
             defFillShaderFull = new FillShaderFull(parent, defFillShaderVertFullURL, defFillShaderFragTexURL);
    -      }      
    +      }
           fillShaderFull = defFillShaderFull;
         } else if (kind == LINE_SHADER) {
           if (defLineShader == null) {
    -        defLineShader = new LineShader(parent, defLineShaderVertURL, defLineShaderFragURL);        
    -      }      
    +        defLineShader = new LineShader(parent, defLineShaderVertURL, defLineShaderFragURL);
    +      }
           lineShader = defLineShader;
         } else if (kind == POINT_SHADER) {
           if (defPointShader == null) {
    -        defPointShader = new PointShader(parent, defPointShaderVertURL, defPointShaderFragURL);        
    -      }      
    +        defPointShader = new PointShader(parent, defPointShaderVertURL, defPointShaderFragURL);
    +      }
           pointShader = defPointShader;
         } else {
           PGraphics.showWarning("Wrong shader type");
    -    }     
    +    }
       }
    -  
    -  
    -  protected FillShader getFillShader(boolean lit, boolean tex) {    
    +
    +
    +  protected FillShader getFillShader(boolean lit, boolean tex) {
         FillShader shader;
         if (lit) {
           if (tex) {
             if (defFillShaderFull == null) {
               defFillShaderFull = new FillShaderFull(parent, defFillShaderVertFullURL, defFillShaderFragTexURL);
    -        }         
    +        }
             if (fillShaderFull == null) {
               fillShaderFull = defFillShaderFull;
             }
    -        shader = fillShaderFull;  
    +        shader = fillShaderFull;
           } else {
             if (defFillShaderLit == null) {
               defFillShaderLit = new FillShaderLit(parent, defFillShaderVertLitURL, defFillShaderFragNoTexURL);
             }
    -        if (fillShaderLit == null) { 
    +        if (fillShaderLit == null) {
               fillShaderLit = defFillShaderLit;
             }
             shader = fillShaderLit;
    @@ -5303,32 +5301,32 @@ public class PGraphicsOpenGL extends PGraphics {
           if (tex) {
             if (defFillShaderTex == null) {
               defFillShaderTex = new FillShaderTex(parent, defFillShaderVertTexURL, defFillShaderFragTexURL);
    -        }        
    +        }
             if (fillShaderTex == null) {
               fillShaderTex = defFillShaderTex;
             }
             shader = fillShaderTex;
           } else {
             if (defFillShaderSimple == null) {
    -          defFillShaderSimple = new FillShaderSimple(parent, defFillShaderVertSimpleURL, defFillShaderFragNoTexURL);            
    -        }          
    +          defFillShaderSimple = new FillShaderSimple(parent, defFillShaderVertSimpleURL, defFillShaderFragNoTexURL);
    +        }
             if (fillShaderSimple == null) {
               fillShaderSimple = defFillShaderSimple;
             }
             shader = fillShaderSimple;
    -      }      
    -    }    
    +      }
    +    }
         shader.setRenderer(this);
         shader.loadAttributes();
    -    shader.loadUniforms();    
    +    shader.loadUniforms();
         return shader;
       }
    -  
    -  
    +
    +
       protected LineShader getLineShader() {
         if (defLineShader == null) {
           defLineShader = new LineShader(parent, defLineShaderVertURL, defLineShaderFragURL);
    -    }    
    +    }
         if (lineShader == null) {
           lineShader = defLineShader;
         }
    @@ -5338,138 +5336,138 @@ public class PGraphicsOpenGL extends PGraphics {
         return lineShader;
       }
     
    -  
    +
       protected PointShader getPointShader() {
         if (defPointShader == null) {
           defPointShader = new PointShader(parent, defPointShaderVertURL, defPointShaderFragURL);
    -    }    
    -    if (pointShader == null) {      
    +    }
    +    if (pointShader == null) {
           pointShader = defPointShader;
    -    }    
    +    }
         pointShader.setRenderer(this);
         pointShader.loadAttributes();
         pointShader.loadUniforms();
    -    return pointShader;    
    -  }  
    -  
    -  
    +    return pointShader;
    +  }
    +
    +
       protected class FillShader extends PShader {
         // We need a reference to the renderer since a shader might
         // be called by different renderers within a single application
         // (the one corresponding to the main surface, or other offscreen
         // renderers).
         protected PGraphicsOpenGL renderer;
    -    
    +
         public FillShader(PApplet parent) {
           super(parent);
         }
    -    
    +
         public FillShader(PApplet parent, String vertFilename, String fragFilename) {
           super(parent, vertFilename, fragFilename);
         }
    -    
    +
         public FillShader(PApplet parent, URL vertURL, URL fragURL) {
           super(parent, vertURL, fragURL);
    -    }   
    -    
    +    }
    +
         public void setRenderer(PGraphicsOpenGL pg) {
           this.renderer = pg;
    -    }    
    -    
    -    public void loadAttributes() { }    
    +    }
    +
    +    public void loadAttributes() { }
         public void loadUniforms() { }
    -    
    +
         public void setAttribute(int loc, int vboId, int size, int type, boolean normalized, int stride, int offset) {
           if (-1 < loc) {
             pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, vboId);
             pgl.glVertexAttribPointer(loc, size, type, normalized, stride, offset);
           }
         }
    -    
    -    public void setVertexAttribute(int vboId, int size, int type, int stride, int offset) { }    
    +
    +    public void setVertexAttribute(int vboId, int size, int type, int stride, int offset) { }
         public void setColorAttribute(int vboId, int size, int type, int stride, int offset) { }
         public void setNormalAttribute(int vboId, int size, int type, int stride, int offset) { }
         public void setAmbientAttribute(int vboId, int size, int type, int stride, int offset) { }
         public void setSpecularAttribute(int vboId, int size, int type, int stride, int offset) { }
         public void setEmissiveAttribute(int vboId, int size, int type, int stride, int offset) { }
         public void setShininessAttribute(int vboId, int size, int type, int stride, int offset) { }
    -    public void setTexCoordAttribute(int vboId, int size, int type, int stride, int offset) { }    
    +    public void setTexCoordAttribute(int vboId, int size, int type, int stride, int offset) { }
         public void setTexture(PTexture tex) { }
       }
    -  
    -  
    +
    +
       protected class FillShaderSimple extends FillShader {
         protected int projmodelviewMatrixLoc;
    -    
    +
         protected int inVertexLoc;
         protected int inColorLoc;
    -    
    +
         public FillShaderSimple(PApplet parent) {
           super(parent);
    -    }    
    +    }
     
         public FillShaderSimple(PApplet parent, String vertFilename, String fragFilename) {
           super(parent, vertFilename, fragFilename);
         }
    -    
    +
         public FillShaderSimple(PApplet parent, URL vertURL, URL fragURL) {
           super(parent, vertURL, fragURL);
    -    }    
    -    
    +    }
    +
         public void loadAttributes() {
           inVertexLoc = getAttribLocation("inVertex");
           inColorLoc = getAttribLocation("inColor");
         }
    -    
    -    public void loadUniforms() { 
    +
    +    public void loadUniforms() {
           projmodelviewMatrixLoc = getUniformLocation("projmodelviewMatrix");
         }
    -    
    -    public void setVertexAttribute(int vboId, int size, int type, int stride, int offset) { 
    +
    +    public void setVertexAttribute(int vboId, int size, int type, int stride, int offset) {
           setAttribute(inVertexLoc, vboId, size, type, false, stride, offset);
    -    } 
    -    
    -    public void setColorAttribute(int vboId, int size, int type, int stride, int offset) { 
    -      setAttribute(inColorLoc, vboId, size, type, true, stride, offset); 
    -    }  
    -    
    +    }
    +
    +    public void setColorAttribute(int vboId, int size, int type, int stride, int offset) {
    +      setAttribute(inColorLoc, vboId, size, type, true, stride, offset);
    +    }
    +
         public void start() {
           super.start();
     
           if (-1 < inVertexLoc) pgl.glEnableVertexAttribArray(inVertexLoc);
           if (-1 < inColorLoc)  pgl.glEnableVertexAttribArray(inColorLoc);
    -      
    +
           if (renderer != null) {
             renderer.updateGLProjmodelview();
             set4x4MatUniform(projmodelviewMatrixLoc, renderer.glProjmodelview);
           }
         }
     
    -    public void stop() {      
    +    public void stop() {
           if (-1 < inVertexLoc) pgl.glDisableVertexAttribArray(inVertexLoc);
           if (-1 < inColorLoc)  pgl.glDisableVertexAttribArray(inColorLoc);
    -      
    +
           pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0);
    -      
    +
           super.stop();
         }
       }
     
    -  
    +
       protected class FillShaderLit extends FillShader {
         protected int projmodelviewMatrixLoc;
    -    protected int modelviewMatrixLoc;    
    +    protected int modelviewMatrixLoc;
         protected int normalMatrixLoc;
    -    
    -    protected int lightCountLoc;  
    +
    +    protected int lightCountLoc;
         protected int lightPositionLoc;
         protected int lightNormalLoc;
         protected int lightAmbientLoc;
         protected int lightDiffuseLoc;
         protected int lightSpecularLoc;
         protected int lightFalloffCoefficientsLoc;
    -    protected int lightSpotParametersLoc;      
    -    
    +    protected int lightSpotParametersLoc;
    +
         protected int inVertexLoc;
         protected int inColorLoc;
         protected int inNormalLoc;
    @@ -5477,36 +5475,36 @@ public class PGraphicsOpenGL extends PGraphics {
         protected int inAmbientLoc;
         protected int inSpecularLoc;
         protected int inEmissiveLoc;
    -    protected int inShineLoc;    
    -    
    +    protected int inShineLoc;
    +
         public FillShaderLit(PApplet parent) {
           super(parent);
    -    }      
    -    
    +    }
    +
         public FillShaderLit(PApplet parent, String vertFilename, String fragFilename) {
           super(parent, vertFilename, fragFilename);
         }
    -    
    +
         public FillShaderLit(PApplet parent, URL vertURL, URL fragURL) {
           super(parent, vertURL, fragURL);
    -    }    
    -    
    +    }
    +
         public void loadAttributes() {
           inVertexLoc = getAttribLocation("inVertex");
    -      inColorLoc = getAttribLocation("inColor");      
    +      inColorLoc = getAttribLocation("inColor");
           inNormalLoc = getAttribLocation("inNormal");
    -      
    +
           inAmbientLoc = getAttribLocation("inAmbient");
           inSpecularLoc = getAttribLocation("inSpecular");
           inEmissiveLoc = getAttribLocation("inEmissive");
           inShineLoc = getAttribLocation("inShine");
         }
    -    
    -    public void loadUniforms() { 
    -      projmodelviewMatrixLoc = getUniformLocation("projmodelviewMatrix");      
    +
    +    public void loadUniforms() {
    +      projmodelviewMatrixLoc = getUniformLocation("projmodelviewMatrix");
           modelviewMatrixLoc = getUniformLocation("modelviewMatrix");
           normalMatrixLoc = getUniformLocation("normalMatrix");
    -      
    +
           lightCountLoc = getUniformLocation("lightCount");
           lightPositionLoc = getUniformLocation("lightPosition");
           lightNormalLoc = getUniformLocation("lightNormal");
    @@ -5514,60 +5512,60 @@ public class PGraphicsOpenGL extends PGraphics {
           lightDiffuseLoc = getUniformLocation("lightDiffuse");
           lightSpecularLoc = getUniformLocation("lightSpecular");
           lightFalloffCoefficientsLoc = getUniformLocation("lightFalloffCoefficients");
    -      lightSpotParametersLoc = getUniformLocation("lightSpotParameters");      
    -    }    
    -    
    -    public void setVertexAttribute(int vboId, int size, int type, int stride, int offset) { 
    -      setAttribute(inVertexLoc, vboId, size, type, false, stride, offset);
    -    } 
    -    
    -    public void setColorAttribute(int vboId, int size, int type, int stride, int offset) { 
    -      setAttribute(inColorLoc, vboId, size, type, true, stride, offset); 
    -    } 
    +      lightSpotParametersLoc = getUniformLocation("lightSpotParameters");
    +    }
     
    -    public void setNormalAttribute(int vboId, int size, int type, int stride, int offset) { 
    +    public void setVertexAttribute(int vboId, int size, int type, int stride, int offset) {
    +      setAttribute(inVertexLoc, vboId, size, type, false, stride, offset);
    +    }
    +
    +    public void setColorAttribute(int vboId, int size, int type, int stride, int offset) {
    +      setAttribute(inColorLoc, vboId, size, type, true, stride, offset);
    +    }
    +
    +    public void setNormalAttribute(int vboId, int size, int type, int stride, int offset) {
           setAttribute(inNormalLoc, vboId, size, type, false, stride, offset);
         }
    -    
    -    public void setAmbientAttribute(int vboId, int size, int type, int stride, int offset) { 
    +
    +    public void setAmbientAttribute(int vboId, int size, int type, int stride, int offset) {
           setAttribute(inAmbientLoc, vboId, size, type, true, stride, offset);
         }
    -    
    -    public void setSpecularAttribute(int vboId, int size, int type, int stride, int offset) { 
    +
    +    public void setSpecularAttribute(int vboId, int size, int type, int stride, int offset) {
           setAttribute(inSpecularLoc, vboId, size, type, true, stride, offset);
         }
    -    
    -    public void setEmissiveAttribute(int vboId, int size, int type, int stride, int offset) { 
    +
    +    public void setEmissiveAttribute(int vboId, int size, int type, int stride, int offset) {
           setAttribute(inEmissiveLoc, vboId, size, type, true, stride, offset);
         }
    -    
    -    public void setShininessAttribute(int vboId, int size, int type, int stride, int offset) { 
    +
    +    public void setShininessAttribute(int vboId, int size, int type, int stride, int offset) {
           setAttribute(inShineLoc, vboId, size, type, false, stride, offset);
    -    }       
    -    
    +    }
    +
         public void start() {
           super.start();
    -      
    +
           if (-1 < inVertexLoc) pgl.glEnableVertexAttribArray(inVertexLoc);
    -      if (-1 < inColorLoc)  pgl.glEnableVertexAttribArray(inColorLoc);      
    +      if (-1 < inColorLoc)  pgl.glEnableVertexAttribArray(inColorLoc);
           if (-1 < inNormalLoc) pgl.glEnableVertexAttribArray(inNormalLoc);
    -      
    +
           if (-1 < inAmbientLoc)  pgl.glEnableVertexAttribArray(inAmbientLoc);
           if (-1 < inSpecularLoc) pgl.glEnableVertexAttribArray(inSpecularLoc);
           if (-1 < inEmissiveLoc) pgl.glEnableVertexAttribArray(inEmissiveLoc);
    -      if (-1 < inShineLoc)    pgl.glEnableVertexAttribArray(inShineLoc);         
    -      
    +      if (-1 < inShineLoc)    pgl.glEnableVertexAttribArray(inShineLoc);
    +
           if (renderer != null) {
             renderer.updateGLProjmodelview();
             set4x4MatUniform(projmodelviewMatrixLoc, renderer.glProjmodelview);
    -        
    +
             renderer.updateGLModelview();
             set4x4MatUniform(modelviewMatrixLoc, renderer.glModelview);
    -        
    +
             renderer.updateGLNormal();
             set3x3MatUniform(normalMatrixLoc, renderer.glNormal);
    -        
    -        setIntUniform(lightCountLoc, renderer.lightCount);      
    +
    +        setIntUniform(lightCountLoc, renderer.lightCount);
             set4FloatVecUniform(lightPositionLoc, renderer.lightPosition);
             set3FloatVecUniform(lightNormalLoc, renderer.lightNormal);
             set3FloatVecUniform(lightAmbientLoc, renderer.lightAmbient);
    @@ -5578,61 +5576,61 @@ public class PGraphicsOpenGL extends PGraphics {
           }
         }
     
    -    public void stop() {                  
    +    public void stop() {
           if (-1 < inVertexLoc) pgl.glDisableVertexAttribArray(inVertexLoc);
    -      if (-1 < inColorLoc)  pgl.glDisableVertexAttribArray(inColorLoc);      
    +      if (-1 < inColorLoc)  pgl.glDisableVertexAttribArray(inColorLoc);
           if (-1 < inNormalLoc) pgl.glDisableVertexAttribArray(inNormalLoc);
    -      
    +
           if (-1 < inAmbientLoc)  pgl.glDisableVertexAttribArray(inAmbientLoc);
           if (-1 < inSpecularLoc) pgl.glDisableVertexAttribArray(inSpecularLoc);
           if (-1 < inEmissiveLoc) pgl.glDisableVertexAttribArray(inEmissiveLoc);
    -      if (-1 < inShineLoc)    pgl.glDisableVertexAttribArray(inShineLoc);        
    -      
    +      if (-1 < inShineLoc)    pgl.glDisableVertexAttribArray(inShineLoc);
    +
           pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0);
    -      
    +
           super.stop();
    -    }    
    +    }
       }
    -  
    -  
    +
    +
       protected class FillShaderTex extends FillShaderSimple {
         protected int inTexcoordLoc;
    -    
    +
         protected int texcoordMatrixLoc;
         protected int texcoordOffsetLoc;
    -    
    +
         protected float[] tcmat;
    -    
    +
         public FillShaderTex(PApplet parent) {
           super(parent);
    -    }        
    -    
    -    public FillShaderTex(PApplet parent, String vertFilename, String fragFilename) {
    -      super(parent, vertFilename, fragFilename);      
         }
    -    
    +
    +    public FillShaderTex(PApplet parent, String vertFilename, String fragFilename) {
    +      super(parent, vertFilename, fragFilename);
    +    }
    +
         public FillShaderTex(PApplet parent, URL vertURL, URL fragURL) {
           super(parent, vertURL, fragURL);
    -    }        
    -    
    +    }
    +
         public void loadUniforms() {
           super.loadUniforms();
    -      
    +
           texcoordMatrixLoc = getUniformLocation("texcoordMatrix");
    -      texcoordOffsetLoc = getUniformLocation("texcoordOffset");        
    +      texcoordOffsetLoc = getUniformLocation("texcoordOffset");
         }
    -    
    +
         public void loadAttributes() {
           super.loadAttributes();
    -      
    +
           inTexcoordLoc = getAttribLocation("inTexcoord");
    -    }    
    -    
    -    public void setTexCoordAttribute(int vboId, int size, int type, int stride, int offset) { 
    +    }
    +
    +    public void setTexCoordAttribute(int vboId, int size, int type, int stride, int offset) {
           setAttribute(inTexcoordLoc, vboId, size, type, false, stride, offset);
    -    }     
    -    
    -    public void setTexture(PTexture tex) { 
    +    }
    +
    +    public void setTexture(PTexture tex) {
           float scaleu = 1;
           float scalev = 1;
           float dispu = 0;
    @@ -5641,83 +5639,83 @@ public class PGraphicsOpenGL extends PGraphics {
           if (tex.isFlippedX()) {
             scaleu = -1;
             dispu = 1;
    -      }      
    -      
    +      }
    +
           if (tex.isFlippedY()) {
             scalev = -1;
             dispv = 1;
           }
     
    -      scaleu *= tex.maxTexCoordU;      
    +      scaleu *= tex.maxTexCoordU;
           dispu *= tex.maxTexCoordU;
           scalev *= tex.maxTexCoordV;
           dispv *= tex.maxTexCoordV;
     
           if (tcmat == null) {
             tcmat = new float[16];
    -      }      
    -      
    +      }
    +
           tcmat[0] = scaleu; tcmat[4] = 0;      tcmat[ 8] = 0; tcmat[12] = dispu;
           tcmat[1] = 0;      tcmat[5] = scalev; tcmat[ 9] = 0; tcmat[13] = dispv;
           tcmat[2] = 0;      tcmat[6] = 0;      tcmat[10] = 0; tcmat[14] = 0;
    -      tcmat[3] = 0;      tcmat[7] = 0;      tcmat[11] = 0; tcmat[15] = 0;      
    -      set4x4MatUniform(texcoordMatrixLoc, tcmat);      
    -      
    +      tcmat[3] = 0;      tcmat[7] = 0;      tcmat[11] = 0; tcmat[15] = 0;
    +      set4x4MatUniform(texcoordMatrixLoc, tcmat);
    +
           set2FloatUniform(texcoordOffsetLoc, 1.0f / tex.width, 1.0f / tex.height);
         }
    -    
    +
         public void start() {
           super.start();
    -      
    +
           if (-1 < inTexcoordLoc) pgl.glEnableVertexAttribArray(inTexcoordLoc);
    -    }    
    -    
    -    public void stop() {      
    +    }
    +
    +    public void stop() {
           if (-1 < inTexcoordLoc) pgl.glDisableVertexAttribArray(inTexcoordLoc);
    -      
    +
           super.stop();
    -    }    
    -  }  
    -  
    -  
    +    }
    +  }
    +
    +
       protected class FillShaderFull extends FillShaderLit {
         protected int inTexcoordLoc;
    -    
    +
         protected int texcoordMatrixLoc;
         protected int texcoordOffsetLoc;
    -    
    +
         protected float[] tcmat;
    -    
    +
         public FillShaderFull(PApplet parent) {
           super(parent);
    -    } 
    -    
    +    }
    +
         public FillShaderFull(PApplet parent, String vertFilename, String fragFilename) {
           super(parent, vertFilename, fragFilename);
         }
    -    
    +
         public FillShaderFull(PApplet parent, URL vertURL, URL fragURL) {
           super(parent, vertURL, fragURL);
    -    }     
    +    }
     
         public void loadUniforms() {
           super.loadUniforms();
    -      
    +
           texcoordMatrixLoc = getUniformLocation("texcoordMatrix");
    -      texcoordOffsetLoc = getUniformLocation("texcoordOffset");      
    +      texcoordOffsetLoc = getUniformLocation("texcoordOffset");
         }
    -    
    +
         public void loadAttributes() {
           super.loadAttributes();
    -      
    +
           inTexcoordLoc = getAttribLocation("inTexcoord");
    -    }    
    -    
    -    public void setTexCoordAttribute(int vboId, int size, int type, int stride, int offset) { 
    +    }
    +
    +    public void setTexCoordAttribute(int vboId, int size, int type, int stride, int offset) {
           setAttribute(inTexcoordLoc, vboId, size, type, false, stride, offset);
    -    }     
    -    
    -    public void setTexture(PTexture tex) { 
    +    }
    +
    +    public void setTexture(PTexture tex) {
           float scaleu = 1;
           float scalev = 1;
           float dispu = 0;
    @@ -5726,48 +5724,48 @@ public class PGraphicsOpenGL extends PGraphics {
           if (tex.isFlippedX()) {
             scaleu = -1;
             dispu = 1;
    -      }      
    -      
    +      }
    +
           if (tex.isFlippedY()) {
             scalev = -1;
             dispv = 1;
           }
     
    -      scaleu *= tex.maxTexCoordU;      
    +      scaleu *= tex.maxTexCoordU;
           dispu *= tex.maxTexCoordU;
           scalev *= tex.maxTexCoordV;
           dispv *= tex.maxTexCoordV;
     
           if (tcmat == null) {
             tcmat = new float[16];
    -      }      
    -      
    +      }
    +
           tcmat[0] = scaleu; tcmat[4] = 0;      tcmat[ 8] = 0; tcmat[12] = dispu;
           tcmat[1] = 0;      tcmat[5] = scalev; tcmat[ 9] = 0; tcmat[13] = dispv;
           tcmat[2] = 0;      tcmat[6] = 0;      tcmat[10] = 0; tcmat[14] = 0;
    -      tcmat[3] = 0;      tcmat[7] = 0;      tcmat[11] = 0; tcmat[15] = 0;      
    -      set4x4MatUniform(texcoordMatrixLoc, tcmat);      
    -      
    +      tcmat[3] = 0;      tcmat[7] = 0;      tcmat[11] = 0; tcmat[15] = 0;
    +      set4x4MatUniform(texcoordMatrixLoc, tcmat);
    +
           set2FloatUniform(texcoordOffsetLoc, 1.0f / tex.width, 1.0f / tex.height);
         }
    -    
    +
         public void start() {
           super.start();
    -      
    +
           if (-1 < inTexcoordLoc) pgl.glEnableVertexAttribArray(inTexcoordLoc);
         }
    -    
    -    public void stop() {      
    +
    +    public void stop() {
           if (-1 < inTexcoordLoc) pgl.glDisableVertexAttribArray(inTexcoordLoc);
    -      
    +
           super.stop();
    -    }    
    -  } 
    -  
    -  
    +    }
    +  }
    +
    +
       protected class LineShader extends PShader {
         protected PGraphicsOpenGL renderer;
    -    
    +
         protected int projectionMatrixLoc;
         protected int modelviewMatrixLoc;
     
    @@ -5777,147 +5775,147 @@ public class PGraphicsOpenGL extends PGraphics {
         protected int inVertexLoc;
         protected int inColorLoc;
         protected int inDirWidthLoc;
    -    
    +
         public LineShader(PApplet parent) {
           super(parent);
         }
    -    
    +
         public LineShader(PApplet parent, String vertFilename, String fragFilename) {
           super(parent, vertFilename, fragFilename);
         }
    -    
    +
         public LineShader(PApplet parent, URL vertURL, URL fragURL) {
           super(parent, vertURL, fragURL);
    -    }       
    -    
    +    }
    +
         public void setRenderer(PGraphicsOpenGL pg) {
           this.renderer = pg;
    -    }      
    -    
    +    }
    +
         public void loadAttributes() {
           inVertexLoc = getAttribLocation("inVertex");
           inColorLoc = getAttribLocation("inColor");
    -      inDirWidthLoc = getAttribLocation("inDirWidth");      
    -    } 
    -    
    -    public void loadUniforms() { 
    -      projectionMatrixLoc = getUniformLocation("projectionMatrix");      
    +      inDirWidthLoc = getAttribLocation("inDirWidth");
    +    }
    +
    +    public void loadUniforms() {
    +      projectionMatrixLoc = getUniformLocation("projectionMatrix");
           modelviewMatrixLoc = getUniformLocation("modelviewMatrix");
    -      
    +
           viewportLoc = getUniformLocation("viewport");
           perspectiveLoc = getUniformLocation("perspective");
         }
    -    
    +
         public void setAttribute(int loc, int vboId, int size, int type, boolean normalized, int stride, int offset) {
           pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, vboId);
    -      pgl.glVertexAttribPointer(loc, size, type, normalized, stride, offset);       
    +      pgl.glVertexAttribPointer(loc, size, type, normalized, stride, offset);
         }
    -    
    -    public void setVertexAttribute(int vboId, int size, int type, int stride, int offset) { 
    -      setAttribute(inVertexLoc, vboId, size, type, false, stride, offset);
    -    } 
    -    
    -    public void setColorAttribute(int vboId, int size, int type, int stride, int offset) { 
    -      setAttribute(inColorLoc, vboId, size, type, true, stride, offset); 
    -    }  
     
    -    public void setDirWidthAttribute(int vboId, int size, int type, int stride, int offset) { 
    -      setAttribute(inDirWidthLoc, vboId, size, type, false, stride, offset); 
    +    public void setVertexAttribute(int vboId, int size, int type, int stride, int offset) {
    +      setAttribute(inVertexLoc, vboId, size, type, false, stride, offset);
         }
    -    
    +
    +    public void setColorAttribute(int vboId, int size, int type, int stride, int offset) {
    +      setAttribute(inColorLoc, vboId, size, type, true, stride, offset);
    +    }
    +
    +    public void setDirWidthAttribute(int vboId, int size, int type, int stride, int offset) {
    +      setAttribute(inDirWidthLoc, vboId, size, type, false, stride, offset);
    +    }
    +
         public void start() {
           super.start();
    -      
    +
           if (-1 < inVertexLoc)   pgl.glEnableVertexAttribArray(inVertexLoc);
           if (-1 < inColorLoc)    pgl.glEnableVertexAttribArray(inColorLoc);
    -      if (-1 < inDirWidthLoc) pgl.glEnableVertexAttribArray(inDirWidthLoc);      
    -      
    +      if (-1 < inDirWidthLoc) pgl.glEnableVertexAttribArray(inDirWidthLoc);
    +
           if (renderer != null) {
             renderer.updateGLProjection();
             set4x4MatUniform(projectionMatrixLoc, renderer.glProjection);
     
             renderer.updateGLModelview();
    -        set4x4MatUniform(modelviewMatrixLoc, renderer.glModelview);      
    -        
    +        set4x4MatUniform(modelviewMatrixLoc, renderer.glModelview);
    +
             set4FloatUniform(viewportLoc, renderer.viewport[0], renderer.viewport[1], renderer.viewport[2], renderer.viewport[3]);
           }
    -      
    +
           setIntUniform(perspectiveLoc, perspectiveCorrectedLines ? 1 : 0);
         }
     
    -    public void stop() {      
    +    public void stop() {
           if (-1 < inVertexLoc)   pgl.glDisableVertexAttribArray(inVertexLoc);
           if (-1 < inColorLoc)    pgl.glDisableVertexAttribArray(inColorLoc);
    -      if (-1 < inDirWidthLoc) pgl.glDisableVertexAttribArray(inDirWidthLoc);     
    -      
    +      if (-1 < inDirWidthLoc) pgl.glDisableVertexAttribArray(inDirWidthLoc);
    +
           pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0);
    -      
    +
           super.stop();
         }
       }
    -  
    -  
    +
    +
       protected class PointShader extends PShader {
         protected PGraphicsOpenGL renderer;
    -    
    +
         protected int projectionMatrixLoc;
         protected int modelviewMatrixLoc;
    -     
    +
         protected int inVertexLoc;
         protected int inColorLoc;
         protected int inSizeLoc;
    -    
    +
         public PointShader(PApplet parent) {
           super(parent);
    -    }    
    +    }
     
         public PointShader(PApplet parent, String vertFilename, String fragFilename) {
           super(parent, vertFilename, fragFilename);
         }
    -    
    +
         public PointShader(PApplet parent, URL vertURL, URL fragURL) {
           super(parent, vertURL, fragURL);
    -    }        
    -    
    +    }
    +
         public void setRenderer(PGraphicsOpenGL pg) {
           this.renderer = pg;
    -    }      
    -    
    +    }
    +
         public void loadAttributes() {
           inVertexLoc = getAttribLocation("inVertex");
           inColorLoc = getAttribLocation("inColor");
    -      inSizeLoc = getAttribLocation("inSize");      
    -    } 
    -    
    -    public void loadUniforms() { 
    -      projectionMatrixLoc = getUniformLocation("projectionMatrix");      
    +      inSizeLoc = getAttribLocation("inSize");
    +    }
    +
    +    public void loadUniforms() {
    +      projectionMatrixLoc = getUniformLocation("projectionMatrix");
           modelviewMatrixLoc = getUniformLocation("modelviewMatrix");
         }
    -    
    +
         public void setAttribute(int loc, int vboId, int size, int type, boolean normalized, int stride, int offset) {
           pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, vboId);
    -      pgl.glVertexAttribPointer(loc, size, type, normalized, stride, offset);       
    +      pgl.glVertexAttribPointer(loc, size, type, normalized, stride, offset);
         }
    -    
    -    public void setVertexAttribute(int vboId, int size, int type, int stride, int offset) { 
    -      setAttribute(inVertexLoc, vboId, size, type, false, stride, offset);
    -    } 
    -    
    -    public void setColorAttribute(int vboId, int size, int type, int stride, int offset) { 
    -      setAttribute(inColorLoc, vboId, size, type, true, stride, offset); 
    -    }  
     
    -    public void setSizeAttribute(int vboId, int size, int type, int stride, int offset) { 
    -      setAttribute(inSizeLoc, vboId, size, type, false, stride, offset); 
    +    public void setVertexAttribute(int vboId, int size, int type, int stride, int offset) {
    +      setAttribute(inVertexLoc, vboId, size, type, false, stride, offset);
         }
    -    
    +
    +    public void setColorAttribute(int vboId, int size, int type, int stride, int offset) {
    +      setAttribute(inColorLoc, vboId, size, type, true, stride, offset);
    +    }
    +
    +    public void setSizeAttribute(int vboId, int size, int type, int stride, int offset) {
    +      setAttribute(inSizeLoc, vboId, size, type, false, stride, offset);
    +    }
    +
         public void start() {
           super.start();
    -      
    +
           if (-1 < inVertexLoc) pgl.glEnableVertexAttribArray(inVertexLoc);
           if (-1 < inColorLoc)  pgl.glEnableVertexAttribArray(inColorLoc);
    -      if (-1 < inSizeLoc)   pgl.glEnableVertexAttribArray(inSizeLoc);      
    -      
    +      if (-1 < inSizeLoc)   pgl.glEnableVertexAttribArray(inSizeLoc);
    +
           if (renderer != null) {
             renderer.updateGLProjection();
             set4x4MatUniform(projectionMatrixLoc, renderer.glProjection);
    @@ -5927,39 +5925,39 @@ public class PGraphicsOpenGL extends PGraphics {
           }
         }
     
    -    public void stop() {      
    +    public void stop() {
           if (-1 < inVertexLoc) pgl.glDisableVertexAttribArray(inVertexLoc);
           if (-1 < inColorLoc)  pgl.glDisableVertexAttribArray(inColorLoc);
           if (-1 < inSizeLoc)   pgl.glDisableVertexAttribArray(inSizeLoc);
    -      
    +
           pgl.glBindBuffer(PGL.GL_ARRAY_BUFFER, 0);
    -      
    +
           super.stop();
    -    }    
    +    }
       }
     
    -    
    -  
    +
    +
       //////////////////////////////////////////////////////////////
    -  
    -  // Input (raw) and Tessellated geometry, tessellator.        
    -    
    -  
    +
    +  // Input (raw) and Tessellated geometry, tessellator.
    +
    +
       public InGeometry newInGeometry(int mode) {
    -    return new InGeometry(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 {
    @@ -5969,11 +5967,11 @@ public class PGraphicsOpenGL extends PGraphics {
         protected int[] lastIndex;
         protected boolean hasTexture;
         protected PTexture tex0;
    -    
    +
         public TexCache() {
           allocate();
         }
    -    
    +
         public void allocate() {
           textures = new PImage[PGL.DEFAULT_IN_TEXTURES];
           firstIndex = new int[PGL.DEFAULT_IN_TEXTURES];
    @@ -5981,19 +5979,19 @@ public class PGraphicsOpenGL extends PGraphics {
           count = 0;
           hasTexture = false;
         }
    -    
    +
         public void clear() {
           java.util.Arrays.fill(textures, 0, count, null);
           count = 0;
           hasTexture = false;
         }
    -    
    +
         public void dispose() {
           textures = null;
           firstIndex = null;
    -      lastIndex = null;      
    +      lastIndex = null;
         }
    -    
    +
         public void beginRender() {
           tex0 = null;
         }
    @@ -6001,31 +5999,31 @@ public class PGraphicsOpenGL extends PGraphics {
         public PTexture getTexture(int i) {
           PImage img = textures[i];
           PTexture tex = null;
    -      
    -      if (img != null) {        
    -        tex = pg.getTexture(img);        
    -        if (tex != null) {                   
    -          tex.bind();          
    +
    +      if (img != null) {
    +        tex = pg.getTexture(img);
    +        if (tex != null) {
    +          tex.bind();
               tex0 = tex;
             }
           }
           if (tex == null && tex0 != null) {
             tex0.unbind();
    -        pgl.disableTexturing(tex0.glTarget);        
    +        pgl.disableTexturing(tex0.glTarget);
           }
    -      
    +
           return tex;
         }
    -    
    +
         public void endRender() {
           if (hasTexture) {
    -        // Unbinding all the textures in the cache.      
    +        // Unbinding all the textures in the cache.
             for (int i = 0; i < count; i++) {
               PImage img = textures[i];
               if (img != null) {
                 PTexture tex = pg.getTexture(img);
                 if (tex != null) {
    -              tex.unbind();  
    +              tex.unbind();
                 }
               }
             }
    @@ -6037,94 +6035,94 @@ public class PGraphicsOpenGL extends PGraphics {
                 PTexture tex = pg.getTexture(img);
                 if (tex != null) {
                   pgl.disableTexturing(tex.glTarget);
    -            }          
    +            }
               }
             }
    -      }      
    -    }    
    -    
    +      }
    +    }
    +
         public void addTexture(PImage img, int first, int last) {
           textureCheck();
    -      
    +
           textures[count] = img;
           firstIndex[count] = first;
           lastIndex[count] = last;
    -      
    +
           // At least one non-null texture since last reset.
           hasTexture |= img != null;
    -      
    +
           count++;
         }
    -    
    +
         public void setLastIndex(int last) {
           lastIndex[count - 1] = last;
         }
    -    
    +
         public void textureCheck() {
           if (count == textures.length) {
    -        int newSize = count << 1;  
    +        int newSize = count << 1;
     
             expandTextures(newSize);
             expandFirstIndex(newSize);
             expandLastIndex(newSize);
           }
         }
    -    
    +
         public void expandTextures(int n) {
    -      PImage[] temp = new PImage[n];      
    +      PImage[] temp = new PImage[n];
           PApplet.arrayCopy(textures, 0, temp, 0, count);
    -      textures = temp;          
    +      textures = temp;
         }
    -        
    +
         public void expandFirstIndex(int n) {
    -      int[] temp = new int[n];      
    +      int[] temp = new int[n];
           PApplet.arrayCopy(firstIndex, 0, temp, 0, count);
    -      firstIndex = temp;      
    +      firstIndex = temp;
         }
    -    
    +
         public void expandLastIndex(int n) {
    -      int[] temp = new int[n];      
    +      int[] temp = new int[n];
           PApplet.arrayCopy(lastIndex, 0, temp, 0, count);
    -      lastIndex = temp;      
    -    }    
    +      lastIndex = temp;
    +    }
       }
    -  
    -  // Holds the input vertices: xyz coordinates, fill/tint color, 
    +
    +  // Holds the input vertices: xyz coordinates, fill/tint color,
       // normal, texture coordinates and stroke color and weight.
       public class InGeometry {
         int renderMode;
         public int vertexCount;
         public int edgeCount;
    -    
    -    // Range of vertices that will be processed by the 
    +
    +    // Range of vertices that will be processed by the
         // tessellator. They can be used in combination with the
         // edges array to have the tessellator using only a specific
         // range of vertices to generate fill geometry, while the
         // line geometry will be read from the edge vertices, which
    -    // could be completely different.    
    +    // could be completely different.
         public int firstVertex;
    -    public int lastVertex;    
    +    public int lastVertex;
     
         public int firstEdge;
    -    public int lastEdge;    
    -    
    +    public int lastEdge;
    +
         public int[] codes;
    -    public float[] vertices;  
    +    public float[] vertices;
         public int[] colors;
         public float[] normals;
         public float[] texcoords;
         public int[] scolors;
         public float[] sweights;
    -    
    +
         // Material properties
         public int[] ambient;
         public int[] specular;
         public int[] emissive;
         public float[] shininess;
    -    
    +
         // TODO: this should probably go in the TessGeometry class
         public int[][] edges;
    -    
    +
         // For later, to be used by libraries...
         //public float[][] mtexcoords;
         //public float[][] attributes;
    @@ -6132,27 +6130,27 @@ public class PGraphicsOpenGL extends PGraphics {
         public InGeometry(int mode) {
           renderMode = mode;
           allocate();
    -    }    
    -    
    +    }
    +
         public void clear() {
    -      vertexCount = firstVertex = lastVertex = 0; 
    +      vertexCount = firstVertex = lastVertex = 0;
           edgeCount = firstEdge = lastEdge = 0;
         }
    -    
    -    
    +
    +
         public void clearEdges() {
           edgeCount = firstEdge = lastEdge = 0;
         }
    -    
    -    
    -    public void allocate() {      
    +
    +
    +    public void allocate() {
           codes = new int[PGL.DEFAULT_IN_VERTICES];
           vertices = new float[3 * PGL.DEFAULT_IN_VERTICES];
    -      colors = new int[PGL.DEFAULT_IN_VERTICES];      
    +      colors = new int[PGL.DEFAULT_IN_VERTICES];
           normals = new float[3 * PGL.DEFAULT_IN_VERTICES];
           texcoords = new float[2 * PGL.DEFAULT_IN_VERTICES];
           scolors = new int[PGL.DEFAULT_IN_VERTICES];
    -      sweights = new float[PGL.DEFAULT_IN_VERTICES];      
    +      sweights = new float[PGL.DEFAULT_IN_VERTICES];
           ambient = new int[PGL.DEFAULT_IN_VERTICES];
           specular = new int[PGL.DEFAULT_IN_VERTICES];
           emissive = new int[PGL.DEFAULT_IN_VERTICES];
    @@ -6160,7 +6158,7 @@ public class PGraphicsOpenGL extends PGraphics {
           edges = new int[PGL.DEFAULT_IN_EDGES][3];
           clear();
         }
    -    
    +
         public void trim() {
           if (0 < vertexCount && vertexCount < vertices.length / 3) {
             trimVertices();
    @@ -6168,22 +6166,22 @@ public class PGraphicsOpenGL extends PGraphics {
             trimNormals();
             trimTexcoords();
             trimStrokeColors();
    -        trimStrokeWeights();        
    +        trimStrokeWeights();
             trimAmbient();
             trimSpecular();
             trimEmissive();
    -        trimShininess();        
    -      } 
    -      
    -      if (0 < edgeCount && edgeCount < edges.length) { 
    +        trimShininess();
    +      }
    +
    +      if (0 < edgeCount && edgeCount < edges.length) {
             trimEdges();
           }
         }
    -    
    +
         public void dispose() {
           codes = null;
           vertices = null;
    -      colors = null;      
    +      colors = null;
           normals = null;
           texcoords = null;
           scolors = null;
    @@ -6191,80 +6189,80 @@ public class PGraphicsOpenGL extends PGraphics {
           ambient = null;
           specular = null;
           emissive = null;
    -      shininess = null;      
    +      shininess = null;
           edges = null;
         }
     
         public float getVertexX(int idx) {
    -      return vertices[3 * idx + 0];  
    +      return vertices[3 * idx + 0];
         }
    -    
    +
         public float getVertexY(int idx) {
           return vertices[3 * idx + 1];
    -    }    
    -    
    +    }
    +
         public float getVertexZ(int idx) {
           return vertices[3 * idx + 2];
    -    }    
    -    
    -    public float getLastVertexX() {
    -      return vertices[3 * (vertexCount - 1) + 0];  
         }
    -    
    +
    +    public float getLastVertexX() {
    +      return vertices[3 * (vertexCount - 1) + 0];
    +    }
    +
         public float getLastVertexY() {
           return vertices[3 * (vertexCount - 1) + 1];
    -    }    
    -    
    +    }
    +
         public float getLastVertexZ() {
           return vertices[3 * (vertexCount - 1) + 2];
         }
    -    
    +
         public boolean isFull() {
           return PGL.MAX_TESS_VERTICES <= vertexCount;
         }
     
    -    
    -    public int addVertex(float x, float y, 
    +
    +    public int addVertex(float x, float y,
                              int fcolor,
                              float u, float v,
                              int scolor, float sweight,
                              int am, int sp, int em, float shine,
                              int code) {
    -      return addVertex(x, y, 0, 
    +      return addVertex(x, y, 0,
                            fcolor,
    -                       0, 0, 1, 
    -                       u, v, 
    -                       scolor, sweight, 
    +                       0, 0, 1,
    +                       u, v,
    +                       scolor, sweight,
                            am, sp, em, shine,
    -                       code);      
    +                       code);
         }
     
    -    public int addVertex(float x, float y, 
    +    public int addVertex(float x, float y,
                              int fcolor,
                              int scolor, float sweight,
                              int am, int sp, int em, float shine,
                              int code) {
    -      return addVertex(x, y, 0, 
    +      return addVertex(x, y, 0,
                            fcolor,
    -                       0, 0, 1, 
    -                       0, 0, 
    +                       0, 0, 1,
    +                       0, 0,
                            scolor, sweight,
                            am, sp, em, shine,
    -                       code);   
    -    }    
    -    
    -    public int addVertex(float x, float y, float z, 
    +                       code);
    +    }
    +
    +    public int addVertex(float x, float y, float z,
                              int fcolor,
                              float nx, float ny, float nz,
                              float u, float v,
    -                         int scolor, float sweight, 
    +                         int scolor, float sweight,
                              int am, int sp, int em, float shine,
                              int code) {
           vertexCheck();
           int index;
     
    -      codes[vertexCount] = code;      
    -      
    +      codes[vertexCount] = code;
    +
           index = 3 * vertexCount;
           vertices[index++] = x;
           vertices[index++] = y;
    @@ -6275,8 +6273,8 @@ public class PGraphicsOpenGL extends PGraphics {
           index = 3 * vertexCount;
           normals[index++] = nx;
           normals[index++] = ny;
    -      normals[index  ] = nz;      
    -      
    +      normals[index  ] = nz;
    +
           index = 2 * vertexCount;
           texcoords[index++] = u;
           texcoords[index  ] = v;
    @@ -6288,13 +6286,13 @@ public class PGraphicsOpenGL extends PGraphics {
           specular[vertexCount] = javaToNativeARGB(sp);
           emissive[vertexCount] = javaToNativeARGB(em);
           shininess[vertexCount] = shine;
    -      
    -      lastVertex = vertexCount; 
    +
    +      lastVertex = vertexCount;
           vertexCount++;
    -      
    -      return lastVertex; 
    +
    +      return lastVertex;
         }
    -        
    +
         public int javaToNativeARGB(int color) {
           if (PGL.BIG_ENDIAN) {
             return ((color >> 24) & 0xff) | ((color << 8) & 0xffffff00);
    @@ -6302,9 +6300,9 @@ public class PGraphicsOpenGL extends PGraphics {
             return (color & 0xff000000)
                    | ((color << 16) & 0xff0000) | (color & 0xff00)
                    | ((color >> 16) & 0xff);
    -      }     
    +      }
         }
    -    
    +
         public void vertexCheck() {
           if (vertexCount == vertices.length / 3) {
             int newSize = vertexCount << 1;
    @@ -6313,7 +6311,7 @@ public class PGraphicsOpenGL extends PGraphics {
             expandVertices(newSize);
             expandColors(newSize);
             expandNormals(newSize);
    -        expandTexcoords(newSize);      
    +        expandTexcoords(newSize);
             expandStrokeColors(newSize);
             expandStrokeWeights(newSize);
             expandAmbient(newSize);
    @@ -6321,11 +6319,11 @@ public class PGraphicsOpenGL extends PGraphics {
             expandEmissive(newSize);
             expandShininess(newSize);
           }
    -    }  
    -    
    +    }
    +
         public void calcTriangleNormal(int i0, int i1, int i2) {
           int index;
    -      
    +
           index = 3 * i0;
           float x0 = vertices[index++];
           float y0 = vertices[index++];
    @@ -6340,15 +6338,15 @@ public class PGraphicsOpenGL extends PGraphics {
           float x2 = vertices[index++];
           float y2 = vertices[index++];
           float z2 = vertices[index  ];
    -      
    +
           float v12x = x2 - x1;
           float v12y = y2 - y1;
           float v12z = z2 - z1;
    -      
    +
           float v10x = x0 - x1;
           float v10y = y0 - y1;
           float v10z = z0 - z1;
    -      
    +
           // n = v10 x v12 (so the normal points out following the
           // clockwise direction along the vertices of the triangle).
           float nx = v10y * v12z - v12y * v10z;
    @@ -6358,7 +6356,7 @@ public class PGraphicsOpenGL extends PGraphics {
           nx /= d;
           ny /= d;
           nz /= d;
    -      
    +
           index = 3 * i0;
           normals[index++] = nx;
           normals[index++] = ny;
    @@ -6372,195 +6370,195 @@ public class PGraphicsOpenGL extends PGraphics {
           index = 3 * i2;
           normals[index++] = nx;
           normals[index++] = ny;
    -      normals[index  ] = nz;      
    +      normals[index  ] = nz;
         }
    -        
    +
         public int addEdge(int i, int j, boolean start, boolean end) {
           edgeCheck();
    -      
    +
           int[] edge = edges[edgeCount];
           edge[0] = i;
           edge[1] = j;
    -      
    +
           // Possible values for state:
           // 0 = middle edge (not start, not end)
           // 1 = start edge (start, not end)
           // 2 = end edge (not start, end)
    -      // 3 = isolated edge (start, end)      
    +      // 3 = isolated edge (start, end)
           edge[2] = (start ? 1 : 0) + 2 * (end ? 1 : 0);
    -      
    -      lastEdge = edgeCount; 
    +
    +      lastEdge = edgeCount;
           edgeCount++;
    -      
    +
           return lastEdge;
         }
    -    
    +
         public void edgeCheck() {
           if (edgeCount == edges.length) {
             int newLen = edgeCount << 1;
    -        
    +
             int temp[][] = new int[newLen][3];
             PApplet.arrayCopy(edges, 0, temp, 0, edgeCount);
    -        edges = temp;        
    +        edges = temp;
           }
         }
    -    
    +
         protected void expandCodes(int n) {
    -      int temp[] = new int[n];      
    +      int temp[] = new int[n];
           PApplet.arrayCopy(codes, 0, temp, 0, vertexCount);
    -      codes = temp;    
    +      codes = temp;
         }
     
         protected void expandVertices(int n) {
    -      float temp[] = new float[3 * n];      
    +      float temp[] = new float[3 * n];
           PApplet.arrayCopy(vertices, 0, temp, 0, 3 * vertexCount);
    -      vertices = temp;    
    +      vertices = temp;
         }
     
         protected void expandColors(int n) {
    -      int temp[] = new int[n];      
    +      int temp[] = new int[n];
           PApplet.arrayCopy(colors, 0, temp, 0, vertexCount);
    -      colors = temp;  
    +      colors = temp;
         }
     
         protected void expandNormals(int n) {
    -      float temp[] = new float[3 * n];      
    +      float temp[] = new float[3 * n];
           PApplet.arrayCopy(normals, 0, temp, 0, 3 * vertexCount);
    -      normals = temp;    
    -    }    
    -    
    -    protected void expandTexcoords(int n) {
    -      float temp[] = new float[2 * n];      
    -      PApplet.arrayCopy(texcoords, 0, temp, 0, 2 * vertexCount);
    -      texcoords = temp;    
    +      normals = temp;
         }
    -        
    +
    +    protected void expandTexcoords(int n) {
    +      float temp[] = new float[2 * n];
    +      PApplet.arrayCopy(texcoords, 0, temp, 0, 2 * vertexCount);
    +      texcoords = temp;
    +    }
    +
         protected void expandStrokeColors(int n) {
    -      int temp[] = new int[n];      
    +      int temp[] = new int[n];
           PApplet.arrayCopy(scolors, 0, temp, 0, vertexCount);
           scolors = temp;
         }
     
         protected void expandStrokeWeights(int n) {
    -      float temp[] = new float[n];      
    +      float temp[] = new float[n];
           PApplet.arrayCopy(sweights, 0, temp, 0, vertexCount);
           sweights = temp;
    -    }    
    -    
    +    }
    +
         protected void expandAmbient(int n) {
    -      int temp[] = new int[n];      
    +      int temp[] = new int[n];
           PApplet.arrayCopy(ambient, 0, temp, 0, vertexCount);
    -      ambient = temp;          
    +      ambient = temp;
         }
    -    
    +
         protected void expandSpecular(int n) {
    -      int temp[] = new int[n];      
    +      int temp[] = new int[n];
           PApplet.arrayCopy(specular, 0, temp, 0, vertexCount);
    -      specular = temp;       
    +      specular = temp;
         }
    -    
    +
         protected void expandEmissive(int n) {
    -      int temp[] = new int[n];      
    +      int temp[] = new int[n];
           PApplet.arrayCopy(emissive, 0, temp, 0, vertexCount);
    -      emissive = temp;      
    +      emissive = temp;
         }
    -    
    +
         protected void expandShininess(int n) {
    -      float temp[] = new float[n];      
    +      float temp[] = new float[n];
           PApplet.arrayCopy(shininess, 0, temp, 0, vertexCount);
    -      shininess = temp;       
    +      shininess = temp;
         }
    -    
    +
         protected void trimVertices() {
    -      float temp[] = new float[3 * vertexCount];      
    +      float temp[] = new float[3 * vertexCount];
           PApplet.arrayCopy(vertices, 0, temp, 0, 3 * vertexCount);
    -      vertices = temp;      
    +      vertices = temp;
         }
    -    
    +
         protected void trimColors() {
    -      int temp[] = new int[vertexCount];      
    +      int temp[] = new int[vertexCount];
           PApplet.arrayCopy(colors, 0, temp, 0, vertexCount);
    -      colors = temp;        
    +      colors = temp;
         }
     
         protected void trimNormals() {
    -      float temp[] = new float[3 * vertexCount];      
    +      float temp[] = new float[3 * vertexCount];
           PApplet.arrayCopy(normals, 0, temp, 0, 3 * vertexCount);
    -      normals = temp;          
    +      normals = temp;
         }
    -    
    +
         protected void trimTexcoords() {
    -      float temp[] = new float[2 * vertexCount];      
    +      float temp[] = new float[2 * vertexCount];
           PApplet.arrayCopy(texcoords, 0, temp, 0, 2 * vertexCount);
    -      texcoords = temp;    
    +      texcoords = temp;
         }
    -        
    +
         protected void trimStrokeColors() {
    -      int temp[] = new int[vertexCount];      
    +      int temp[] = new int[vertexCount];
           PApplet.arrayCopy(scolors, 0, temp, 0, vertexCount);
           scolors = temp;
    -    }    
    +    }
     
         protected void trimStrokeWeights() {
    -      float temp[] = new float[vertexCount];      
    +      float temp[] = new float[vertexCount];
           PApplet.arrayCopy(sweights, 0, temp, 0, vertexCount);
           sweights = temp;
    -    }        
    -    
    +    }
    +
         protected void trimAmbient() {
           int temp[] = new int[vertexCount];
           PApplet.arrayCopy(ambient, 0, temp, 0, vertexCount);
    -      ambient = temp;      
    +      ambient = temp;
         }
    -    
    +
         protected void trimSpecular() {
           int temp[] = new int[vertexCount];
           PApplet.arrayCopy(specular, 0, temp, 0, vertexCount);
    -      specular = temp;      
    +      specular = temp;
         }
    -        
    +
         protected void trimEmissive() {
           int temp[] = new int[vertexCount];
           PApplet.arrayCopy(emissive, 0, temp, 0, vertexCount);
    -      emissive = temp; 
    +      emissive = temp;
         }
    -    
    +
         protected void trimShininess() {
           float temp[] = new float[vertexCount];
           PApplet.arrayCopy(shininess, 0, temp, 0, vertexCount);
    -      shininess = temp;      
    +      shininess = temp;
         }
     
         protected void trimEdges() {
           int temp[][] = new int[edgeCount][3];
           PApplet.arrayCopy(edges, 0, temp, 0, edgeCount);
    -      edges = temp;        
    -    }
    -        
    -    public int getNumLineVertices() {
    -      return 4 *(lastEdge - firstEdge + 1);      
    +      edges = temp;
         }
     
    -    public int getNumLineIndices() {      
    +    public int getNumLineVertices() {
    +      return 4 *(lastEdge - firstEdge + 1);
    +    }
    +
    +    public int getNumLineIndices() {
           return 6 *(lastEdge - firstEdge + 1);
    -    }    
    +    }
     
         public void calcTrianglesNormals() {
           for (int i = 0; i < (lastVertex - firstVertex + 1) / 3; i++) {
             int i0 = 3 * i + 0;
             int i1 = 3 * i + 1;
             int i2 = 3 * i + 2;
    -        
    +
             calcTriangleNormal(i0, i1, i2);
    -      }      
    -    }    
    -    
    +      }
    +    }
    +
         public void addTrianglesEdges() {
           for (int i = 0; i < (lastVertex - firstVertex + 1) / 3; i++) {
             int i0 = 3 * i + 0;
             int i1 = 3 * i + 1;
             int i2 = 3 * i + 2;
    -        
    +
             addEdge(i0, i1,  true, false);
             addEdge(i1, i2, false, false);
             addEdge(i2, i0, false,  true);
    @@ -6572,100 +6570,100 @@ public class PGraphicsOpenGL extends PGraphics {
             int i0 = firstVertex;
             int i1 = i;
             int i2 = i + 1;
    -        
    +
             calcTriangleNormal(i0, i1, i2);
           }
         }
    -    
    -    public void addTriangleFanEdges() {      
    +
    +    public void addTriangleFanEdges() {
           for (int i = firstVertex + 1; i < lastVertex; i++) {
             int i0 = firstVertex;
             int i1 = i;
             int i2 = i + 1;
    -        
    +
             addEdge(i0, i1,  true, false);
             addEdge(i1, i2, false, false);
    -        addEdge(i2, i0, false,  true);        
    +        addEdge(i2, i0, false,  true);
           }
         }
    -    
    +
         public void calcTriangleStripNormals() {
           for (int i = firstVertex + 1; i < lastVertex; i++) {
             int i1 = i;
             int i0, i2;
             if (i % 2 == 0) {
               i0 = i + 1;
    -          i2 = i - 1;                  
    +          i2 = i - 1;
             } else {
               i0 = i - 1;
    -          i2 = i + 1;             
    +          i2 = i + 1;
             }
             calcTriangleNormal(i0, i1, i2);
    -      }      
    +      }
         }
    -    
    +
         public void addTriangleStripEdges() {
           for (int i = firstVertex + 1; i < lastVertex; i++) {
             int i0 = i;
             int i1, i2;
             if (i % 2 == 0) {
               i1 = i - 1;
    -          i2 = i + 1;        
    +          i2 = i + 1;
             } else {
               i1 = i + 1;
    -          i2 = i - 1;        
    +          i2 = i - 1;
             }
    -        
    +
             addEdge(i0, i1,  true, false);
             addEdge(i1, i2, false, false);
    -        addEdge(i2, i0, false,  true);        
    +        addEdge(i2, i0, false,  true);
           }
         }
    -    
    +
         public void calcQuadsNormals() {
           for (int i = 0; i < (lastVertex - firstVertex + 1) / 4; i++) {
             int i0 = 4 * i + 0;
             int i1 = 4 * i + 1;
             int i2 = 4 * i + 2;
             int i3 = 4 * i + 3;
    -        
    +
             calcTriangleNormal(i0, i1, i2);
             calcTriangleNormal(i2, i3, i0);
           }
         }
    -    
    +
         public void addQuadsEdges() {
           for (int i = 0; i < (lastVertex - firstVertex + 1) / 4; i++) {
             int i0 = 4 * i + 0;
             int i1 = 4 * i + 1;
             int i2 = 4 * i + 2;
             int i3 = 4 * i + 3;
    -        
    +
             addEdge(i0, i1,  true, false);
             addEdge(i1, i2, false, false);
             addEdge(i2, i3, false,  false);
             addEdge(i3, i0, false,  true);
    -      }        
    -    }      
    -    
    +      }
    +    }
    +
         public void calcQuadStripNormals() {
           for (int qd = 1; qd < (lastVertex - firstVertex + 1) / 2; qd++) {
             int i0 = firstVertex + 2 * (qd - 1);
             int i1 = firstVertex + 2 * (qd - 1) + 1;
             int i2 = firstVertex + 2 * qd + 1;
    -        int i3 = firstVertex + 2 * qd;     
    +        int i3 = firstVertex + 2 * qd;
     
             calcTriangleNormal(i0, i1, i3);
             calcTriangleNormal(i3, i2, i0);
           }
         }
    -      
    +
         public void addQuadStripEdges() {
           for (int qd = 1; qd < (lastVertex - firstVertex + 1) / 2; qd++) {
             int i0 = firstVertex + 2 * (qd - 1);
             int i1 = firstVertex + 2 * (qd - 1) + 1;
             int i2 = firstVertex + 2 * qd + 1;
    -        int i3 = firstVertex + 2 * qd;     
    +        int i3 = firstVertex + 2 * qd;
     
             addEdge(i0, i1,  true, false);
             addEdge(i1, i2, false, false);
    @@ -6673,24 +6671,24 @@ public class PGraphicsOpenGL extends PGraphics {
             addEdge(i3, i0, false,  true);
           }
         }
    -    
    +
         public void addPolygonEdges(boolean closed) {
    -      // Count number of edge segments in the perimeter.      
    +      // Count number of edge segments in the perimeter.
           int edgeCount = 0;
           int lnMax = lastVertex - firstVertex + 1;
    -      int first = firstVertex;      
    +      int first = firstVertex;
           int contour0 = first;
           if (!closed) lnMax--;
           for (int ln = 0; ln < lnMax; ln++) {
             int i = first + ln + 1;
             if ((i == lnMax || codes[i] == PShape.BREAK) && closed) {
               i = first + ln;
    -        }            
    +        }
             if (codes[i] != PShape.BREAK) {
               edgeCount++;
    -        }      
    +        }
           }
    -      
    +
           if (0 < edgeCount) {
             boolean begin = true;
             contour0 = first;
    @@ -6699,31 +6697,31 @@ public class PGraphicsOpenGL extends PGraphics {
               int i1 = first + ln + 1;
               if (codes[i0] == PShape.BREAK) contour0 = i0;
               if (i1 == lnMax || codes[i1] == PShape.BREAK) {
    -            // We are at the end of a contour. 
    +            // We are at the end of a contour.
                 if (closed) {
                   // Draw line to the first vertex of the current contour,
                   // if the polygon is closed.
                   i0 = first + ln;
    -              i1 = contour0;            
    +              i1 = contour0;
                   addEdge(i0, i1, begin, true);
                 } else if (codes[i1] != PShape.BREAK) {
                   addEdge(i0, i1, begin, false);
                 }
                 // We might start a new contour in the next iteration.
    -            begin = true;            
    +            begin = true;
               } else if (codes[i1] != PShape.BREAK) {
                 addEdge(i0, i1, begin, false);
               }
    -        }    
    +        }
           }
    -    }    
    -    
    +    }
    +
         // Primitive generation
    -    
    -    public void generateEllipse(int ellipseMode, float a, float b, float c, float d, 
    -                                boolean fill, int fillColor, 
    +
    +    public void generateEllipse(int ellipseMode, float a, float b, float c, float d,
    +                                boolean fill, int fillColor,
                                     boolean stroke, int strokeColor, float strokeWeight,
    -                                int ambient, int specular, int emissive, float shininess) {      
    +                                int ambient, int specular, int emissive, float shininess) {
           float x = a;
           float y = b;
           float w = c;
    @@ -6753,7 +6751,7 @@ public class PGraphicsOpenGL extends PGraphics {
             y += h;
             h = -h;
           }
    -      
    +
           float radiusH = w / 2;
           float radiusV = h / 2;
     
    @@ -6768,11 +6766,11 @@ public class PGraphicsOpenGL extends PGraphics {
           int accuracy = (int) (TWO_PI * PApplet.dist(sx1, sy1, sx2, sy2) / 20);
           if (accuracy < 6) {
             accuracy = 6;
    -      }      
    +      }
           float inc = (float) PGraphicsOpenGL.SINCOS_LENGTH / accuracy;
    -      
    +
           if (fill) {
    -        addVertex(centerX, centerY, 
    +        addVertex(centerX, centerY,
                       fillColor, strokeColor, strokeWeight,
                       ambient, specular, emissive, shininess,
                       VERTEX);
    @@ -6781,104 +6779,104 @@ public class PGraphicsOpenGL extends PGraphics {
           idx0 = pidx = idx = 0;
           float val = 0;
           for (int i = 0; i < accuracy; i++) {
    -        idx = addVertex(centerX + PGraphicsOpenGL.cosLUT[(int) val] * radiusH, 
    -                        centerY + PGraphicsOpenGL.sinLUT[(int) val] * radiusV, 
    +        idx = addVertex(centerX + PGraphicsOpenGL.cosLUT[(int) val] * radiusH,
    +                        centerY + PGraphicsOpenGL.sinLUT[(int) val] * radiusV,
                             fillColor, strokeColor, strokeWeight,
                             ambient, specular, emissive, shininess,
                             VERTEX);
             val = (val + inc) % PGraphicsOpenGL.SINCOS_LENGTH;
    -        
    +
             if (0 < i) {
               if (stroke) addEdge(pidx, idx, i == 1, false);
             } else {
    -          idx0 = idx;  
    +          idx0 = idx;
             }
    -        
    +
             pidx = idx;
           }
           // Back to the beginning
    -      addVertex(centerX + PGraphicsOpenGL.cosLUT[0] * radiusH, 
    -                centerY + PGraphicsOpenGL.sinLUT[0] * radiusV, 
    +      addVertex(centerX + PGraphicsOpenGL.cosLUT[0] * radiusH,
    +                centerY + PGraphicsOpenGL.sinLUT[0] * radiusV,
                     fillColor, strokeColor, strokeWeight,
                     ambient, specular, emissive, shininess,
                     VERTEX);
           if (stroke) addEdge(idx, idx0, false, true);
         }
    -    
    +
       }
    -  
    +
       // Holds tessellated data for fill, line and point geometry.
       public class TessGeometry {
         int renderMode;
    -    
    +
         // Tessellated fill data
         public int fillVertexCount;
         public int firstFillVertex;
    -    public int lastFillVertex;    
    +    public int lastFillVertex;
         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 int[] fillAmbient;
         public int[] fillSpecular;
         public int[] fillEmissive;
         public float[] fillShininess;
    -        
    +
         public int fillIndexCount;
         public int firstFillIndex;
    -    public int lastFillIndex;    
    +    public int lastFillIndex;
         public short[] fillIndices;
    -    
    -    // Tessellated line data    
    +
    +    // Tessellated line data
         public int lineVertexCount;
         public int firstLineVertex;
    -    public int lastLineVertex;    
    +    public int lastLineVertex;
         public float[] lineVertices;
         public int[] lineColors;
    -    public float[] lineDirWidths;    
    -    
    +    public float[] lineDirWidths;
    +
         public int lineIndexCount;
         public int firstLineIndex;
    -    public int lastLineIndex;  
    -    public short[] lineIndices;  
    -    
    +    public int lastLineIndex;
    +    public short[] lineIndices;
    +
         // Tessellated point data
         public int pointVertexCount;
         public int firstPointVertex;
    -    public int lastPointVertex;    
    +    public int lastPointVertex;
         public float[] pointVertices;
         public int[] pointColors;
    -    public float[] pointSizes;  
    +    public float[] pointSizes;
     
         public int pointIndexCount;
         public int firstPointIndex;
    -    public int lastPointIndex;  
    +    public int lastPointIndex;
         public short[] pointIndices;
    -    
    +
         public boolean isStroked;
     
         public TessGeometry(int mode) {
           renderMode = mode;
    -      allocate();      
    -    }    
    -    
    +      allocate();
    +    }
    +
         public void clear() {
           firstFillVertex = lastFillVertex = fillVertexCount = 0;
           firstFillIndex = lastFillIndex = fillIndexCount = 0;
    -      
    +
           firstLineVertex = lastLineVertex = lineVertexCount = 0;
    -      firstLineIndex = lastLineIndex = lineIndexCount = 0;     
    -      
    +      firstLineIndex = lastLineIndex = lineIndexCount = 0;
    +
           firstPointVertex = lastPointVertex = pointVertexCount = 0;
    -      firstPointIndex = lastPointIndex = pointIndexCount = 0;  
    -      
    +      firstPointIndex = lastPointIndex = pointIndexCount = 0;
    +
           isStroked = false;
         }
    -      
    -    public void allocate() {     
    +
    +    public void allocate() {
           fillVertices = new float[3 * PGL.DEFAULT_TESS_VERTICES];
           fillColors = new int[PGL.DEFAULT_TESS_VERTICES];
           fillNormals = new float[3 * PGL.DEFAULT_TESS_VERTICES];
    @@ -6886,22 +6884,22 @@ public class PGraphicsOpenGL extends PGraphics {
           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 short[PGL.DEFAULT_TESS_VERTICES];        
    -      
    +      fillShininess = new float[PGL.DEFAULT_TESS_VERTICES];
    +      fillIndices = new short[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 short[PGL.DEFAULT_TESS_VERTICES];       
    -      
    +      lineIndices = new short[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 short[PGL.DEFAULT_TESS_VERTICES];
    -      
    +
           clear();
         }
    -    
    +
         public void trim() {
           if (0 < fillVertexCount && fillVertexCount < fillVertices.length / 3) {
             trimFillVertices();
    @@ -6913,134 +6911,134 @@ public class PGraphicsOpenGL extends PGraphics {
             trimFillEmissive();
             trimFillShininess();
           }
    -      
    +
           if (0 < fillIndexCount && fillIndexCount < fillIndices.length) {
    -        trimFillIndices();  
    +        trimFillIndices();
           }
    -            
    +
           if (0 < lineVertexCount && lineVertexCount < lineVertices.length / 3) {
             trimLineVertices();
             trimLineColors();
             trimLineAttributes();
           }
    -      
    +
           if (0 < lineIndexCount && lineIndexCount < lineIndices.length) {
    -        trimLineIndices();  
    +        trimLineIndices();
           }
    -      
    +
           if (0 < pointVertexCount && pointVertexCount < pointVertices.length / 3) {
             trimPointVertices();
             trimPointColors();
             trimPointAttributes();
           }
    -      
    +
           if (0 < pointIndexCount && pointIndexCount < pointIndices.length) {
    -        trimPointIndices();  
    -      }       
    -    }    
    -    
    +        trimPointIndices();
    +      }
    +    }
    +
         protected void trimFillVertices() {
    -      float temp[] = new float[3 * fillVertexCount];      
    +      float temp[] = new float[3 * fillVertexCount];
           PApplet.arrayCopy(fillVertices, 0, temp, 0, 3 * fillVertexCount);
    -      fillVertices = temp;       
    +      fillVertices = temp;
         }
     
         protected void trimFillColors() {
    -      int temp[] = new int[fillVertexCount];      
    +      int temp[] = new int[fillVertexCount];
           PApplet.arrayCopy(fillColors, 0, temp, 0, fillVertexCount);
           fillColors = temp;
         }
    -    
    +
         protected void trimFillNormals() {
    -      float temp[] = new float[3 * fillVertexCount];      
    +      float temp[] = new float[3 * fillVertexCount];
           PApplet.arrayCopy(fillNormals, 0, temp, 0, 3 * fillVertexCount);
    -      fillNormals = temp;       
    +      fillNormals = temp;
         }
    -    
    +
         protected void trimFillTexcoords() {
    -      float temp[] = new float[2 * fillVertexCount];      
    +      float temp[] = new float[2 * fillVertexCount];
           PApplet.arrayCopy(fillTexcoords, 0, temp, 0, 2 * fillVertexCount);
           fillTexcoords = temp;
         }
    -    
    +
         protected void trimFillAmbient() {
           int temp[] = new int[fillVertexCount];
           PApplet.arrayCopy(fillAmbient, 0, temp, 0, fillVertexCount);
    -      fillAmbient = temp;      
    +      fillAmbient = temp;
         }
    -    
    +
         protected void trimFillSpecular() {
           int temp[] = new int[fillVertexCount];
           PApplet.arrayCopy(fillSpecular, 0, temp, 0, fillVertexCount);
    -      fillSpecular = temp;      
    +      fillSpecular = temp;
         }
    -        
    +
         protected void trimFillEmissive() {
           int temp[] = new int[fillVertexCount];
           PApplet.arrayCopy(fillEmissive, 0, temp, 0, fillVertexCount);
    -      fillEmissive = temp; 
    +      fillEmissive = temp;
         }
    -    
    +
         protected void trimFillShininess() {
           float temp[] = new float[fillVertexCount];
           PApplet.arrayCopy(fillShininess, 0, temp, 0, fillVertexCount);
    -      fillShininess = temp;      
    +      fillShininess = temp;
         }
    -    
    +
         public void trimFillIndices() {
    -      short temp[] = new short[fillIndexCount];      
    +      short temp[] = new short[fillIndexCount];
           PApplet.arrayCopy(fillIndices, 0, temp, 0, fillIndexCount);
    -      fillIndices = temp;      
    -    }    
    -    
    +      fillIndices = temp;
    +    }
    +
         protected void trimLineVertices() {
    -      float temp[] = new float[3 * lineVertexCount];      
    +      float temp[] = new float[3 * lineVertexCount];
           PApplet.arrayCopy(lineVertices, 0, temp, 0, 3 * lineVertexCount);
    -      lineVertices = temp;  
    +      lineVertices = temp;
         }
    -    
    +
         protected void trimLineColors() {
    -      int temp[] = new int[lineVertexCount];      
    +      int temp[] = new int[lineVertexCount];
           PApplet.arrayCopy(lineColors, 0, temp, 0, lineVertexCount);
    -      lineColors = temp;      
    +      lineColors = temp;
         }
    -    
    +
         protected void trimLineAttributes() {
    -      float temp[] = new float[4 * lineVertexCount];      
    +      float temp[] = new float[4 * lineVertexCount];
           PApplet.arrayCopy(lineDirWidths, 0, temp, 0, 4 * lineVertexCount);
    -      lineDirWidths = temp;      
    -    }      
    -    
    +      lineDirWidths = temp;
    +    }
    +
         protected void trimLineIndices() {
    -      short temp[] = new short[lineIndexCount];      
    +      short temp[] = new short[lineIndexCount];
           PApplet.arrayCopy(lineIndices, 0, temp, 0, lineIndexCount);
    -      lineIndices = temp;        
    -    }    
    -    
    +      lineIndices = temp;
    +    }
    +
         protected void trimPointVertices() {
    -      float temp[] = new float[3 * pointVertexCount];      
    +      float temp[] = new float[3 * pointVertexCount];
           PApplet.arrayCopy(pointVertices, 0, temp, 0, 3 * pointVertexCount);
    -      pointVertices = temp;  
    +      pointVertices = temp;
         }
    -    
    +
         protected void trimPointColors() {
    -      int temp[] = new int[pointVertexCount];      
    +      int temp[] = new int[pointVertexCount];
           PApplet.arrayCopy(pointColors, 0, temp, 0, pointVertexCount);
    -      pointColors = temp;      
    +      pointColors = temp;
         }
    -    
    +
         protected void trimPointAttributes() {
    -      float temp[] = new float[2 * pointVertexCount];      
    +      float temp[] = new float[2 * pointVertexCount];
           PApplet.arrayCopy(pointSizes, 0, temp, 0, 2 * pointVertexCount);
    -      pointSizes = temp;      
    +      pointSizes = temp;
         }
    -    
    +
         protected void trimPointIndices() {
    -      short temp[] = new short[pointIndexCount];      
    +      short temp[] = new short[pointIndexCount];
           PApplet.arrayCopy(pointIndices, 0, temp, 0, pointIndexCount);
    -      pointIndices = temp;        
    -    }    
    -    
    +      pointIndices = temp;
    +    }
    +
         public void dipose() {
           fillVertices = null;
           fillColors = null;
    @@ -7049,22 +7047,22 @@ public class PGraphicsOpenGL extends PGraphics {
           fillAmbient = null;
           fillSpecular = null;
           fillEmissive = null;
    -      fillShininess = null;      
    -      fillIndices = null;        
    -      
    +      fillShininess = null;
    +      fillIndices = null;
    +
           lineVertices = null;
           lineColors = null;
           lineDirWidths = null;
    -      lineIndices = null;       
    -      
    +      lineIndices = null;
    +
           pointVertices = null;
           pointColors = null;
           pointSizes = null;
           pointIndices = null;
         }
    -    
    +
         public boolean isFull() {
    -      return PGL.MAX_TESS_VERTICES <= fillVertexCount || 
    +      return PGL.MAX_TESS_VERTICES <= fillVertexCount ||
                  PGL.MAX_TESS_VERTICES <= lineVertexCount ||
                  PGL.MAX_TESS_VERTICES <= pointVertexCount ||
                  PGL.MAX_TESS_INDICES  <= fillIndexCount ||
    @@ -7073,152 +7071,152 @@ public class PGraphicsOpenGL extends PGraphics {
         }
     
         public boolean isOverflow() {
    -      return PGL.MAX_TESS_VERTICES < fillVertexCount || 
    +      return PGL.MAX_TESS_VERTICES < fillVertexCount ||
                  PGL.MAX_TESS_VERTICES < lineVertexCount ||
                  PGL.MAX_TESS_VERTICES < pointVertexCount ||
                  PGL.MAX_TESS_INDICES  < fillIndexCount ||
                  PGL.MAX_TESS_INDICES  < fillIndexCount ||
                  PGL.MAX_TESS_INDICES  < fillIndexCount;
         }
    -    
    +
         public void addCounts(TessGeometry other) {
           fillVertexCount += other.fillVertexCount;
           fillIndexCount += other.fillIndexCount;
    -      
    +
           lineVertexCount += other.lineVertexCount;
    -      lineIndexCount += other.lineIndexCount;        
    +      lineIndexCount += other.lineIndexCount;
     
           pointVertexCount += other.pointVertexCount;
    -      pointIndexCount += other.pointIndexCount;          
    +      pointIndexCount += other.pointIndexCount;
         }
    -    
    +
         public void setFirstFill(TessGeometry other) {
           firstFillVertex = other.firstFillVertex;
           firstFillIndex = other.firstFillIndex;
         }
    -    
    +
         public void setLastFill(TessGeometry other) {
           lastFillVertex = other.lastFillVertex;
    -      lastFillIndex = other.lastFillIndex;      
    +      lastFillIndex = other.lastFillIndex;
         }
     
         public void setFirstLine(TessGeometry other) {
           firstLineVertex = other.firstLineVertex;
           firstLineIndex = other.firstLineIndex;
         }
    -    
    +
         public void setLastLine(TessGeometry other) {
           lastLineVertex = other.lastLineVertex;
    -      lastLineIndex = other.lastLineIndex;      
    -    }  
    +      lastLineIndex = other.lastLineIndex;
    +    }
     
         public void setFirstPoint(TessGeometry other) {
           firstPointVertex = other.firstPointVertex;
           firstPointIndex = other.firstPointIndex;
         }
    -    
    +
         public void setLastPoint(TessGeometry other) {
           lastPointVertex = other.lastPointVertex;
    -      lastPointIndex = other.lastPointIndex;      
    -    }    
    -    
    +      lastPointIndex = other.lastPointIndex;
    +    }
    +
         public int setFillVertex(int offset) {
           firstFillVertex = 0;
           if (0 < offset) {
    -        firstFillVertex = offset + 1; 
    +        firstFillVertex = offset + 1;
           }
    -      lastFillVertex = firstFillVertex + fillVertexCount - 1;      
    -      return lastFillVertex;         
    +      lastFillVertex = firstFillVertex + fillVertexCount - 1;
    +      return lastFillVertex;
         }
    -    
    +
         public int setFillIndex(int voffset, int ioffset) {
           firstFillIndex = 0;
           if (0 < ioffset) {
    -        firstFillIndex = ioffset + 1; 
    +        firstFillIndex = ioffset + 1;
           }
    -      
    +
           if (0 < voffset) {
    -        // The indices are update to take into account all the previous 
    +        // The indices are update to take into account all the previous
             // 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[i] += voffset;
             }
           }
    -      
    -      lastFillIndex = firstFillIndex + fillIndexCount - 1;        
    -      return lastFillIndex; 
    +
    +      lastFillIndex = firstFillIndex + fillIndexCount - 1;
    +      return lastFillIndex;
         }
    -    
    +
         public int setLineVertex(int offset) {
           firstLineVertex = 0;
           if (0 < offset) {
    -        firstLineVertex = offset + 1; 
    -      }        
    +        firstLineVertex = offset + 1;
    +      }
           lastLineVertex = firstLineVertex + lineVertexCount - 1;
    -      return lastLineVertex;      
    +      return lastLineVertex;
         }
    -    
    -    public int setLineIndex(int voffset, int ioffset) {      
    +
    +    public int setLineIndex(int voffset, int ioffset) {
           firstLineIndex = 0;
           if (0 < ioffset) {
    -        firstLineIndex = ioffset + 1; 
    -      }        
    -      
    +        firstLineIndex = ioffset + 1;
    +      }
    +
           if (0 < voffset) {
    -        // The indices are update to take into account all the previous 
    +        // The indices are update to take into account all the previous
             // 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[i] += voffset;
             }
           }
    -      
    +
           lastLineIndex = firstLineIndex + lineIndexCount - 1;
    -      return lastLineIndex;      
    +      return lastLineIndex;
         }
    -    
    +
         public int setPointVertex(int offset) {
           firstPointVertex = 0;
           if (0 < offset) {
    -        firstPointVertex = offset + 1; 
    -      }        
    +        firstPointVertex = offset + 1;
    +      }
           lastPointVertex = firstPointVertex + pointVertexCount - 1;
    -      return lastPointVertex;      
    +      return lastPointVertex;
         }
    -    
    -    public int setPointIndex(int voffset, int ioffset) { 
    +
    +    public int setPointIndex(int voffset, int ioffset) {
           firstPointIndex = 0;
           if (0 < ioffset) {
    -        firstPointIndex = ioffset + 1; 
    -      }        
    -      
    +        firstPointIndex = ioffset + 1;
    +      }
    +
           if (0 < voffset) {
    -        // The indices are update to take into account all the previous 
    +        // The indices are update to take into account all the previous
             // 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[i] += voffset;
    -        }        
    +        }
           }
     
           lastPointIndex = firstPointIndex + pointIndexCount - 1;
           return lastPointIndex;
         }
    -    
    +
         public void fillIndexCheck() {
           if (fillIndexCount == fillIndices.length) {
             int newSize = fillIndexCount << 1;
             expandFillIndices(newSize);
           }
    -    }    
    -    
    -    public void expandFillIndices(int n) {
    -      short temp[] = new short[n];      
    -      PApplet.arrayCopy(fillIndices, 0, temp, 0, fillIndexCount);
    -      fillIndices = temp;      
         }
    -    
    +
    +    public void expandFillIndices(int n) {
    +      short temp[] = new short[n];
    +      PApplet.arrayCopy(fillIndices, 0, temp, 0, fillIndexCount);
    +      fillIndices = temp;
    +    }
    +
         public void addFillIndex(int idx) {
           fillIndexCheck();
           fillIndices[fillIndexCount] = PGL.makeIndex(idx);
    @@ -7228,7 +7226,7 @@ public class PGraphicsOpenGL extends PGraphics {
     
         public void calcFillNormal(int i0, int i1, int i2) {
           int index;
    -      
    +
           index = 3 * i0;
           float x0 = fillVertices[index++];
           float y0 = fillVertices[index++];
    @@ -7243,15 +7241,15 @@ public class PGraphicsOpenGL extends PGraphics {
           float x2 = fillVertices[index++];
           float y2 = fillVertices[index++];
           float z2 = fillVertices[index  ];
    -      
    +
           float v12x = x2 - x1;
           float v12y = y2 - y1;
           float v12z = z2 - z1;
    -      
    +
           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;
    @@ -7259,7 +7257,7 @@ public class PGraphicsOpenGL extends PGraphics {
           nx /= d;
           ny /= d;
           nz /= d;
    -      
    +
           index = 3 * i0;
           fillNormals[index++] = nx;
           fillNormals[index++] = ny;
    @@ -7273,30 +7271,14 @@ public class PGraphicsOpenGL extends PGraphics {
           index = 3 * i2;
           fillNormals[index++] = nx;
           fillNormals[index++] = ny;
    -      fillNormals[index  ] = nz;      
    -      
    +      fillNormals[index  ] = nz;
    +
         }
    -    
    +
         public void fillVertexCheck() {
           if (fillVertexCount == fillVertices.length / 3) {
    -        int newSize = fillVertexCount << 1; 
    -      
    -        expandFillVertices(newSize);
    -        expandFillColors(newSize);              
    -        expandFillNormals(newSize);
    -        expandFillTexcoords(newSize);
    -        expandFillAmbient(newSize);
    -        expandFillSpecular(newSize);
    -        expandFillEmissive(newSize);
    -        expandFillShininess(newSize);
    -      }
    -    }
    -    
    -    public void addFillVertices(int count) {
    -      int oldSize = fillVertices.length / 3;
    -      if (fillVertexCount + count > oldSize) {
    -        int newSize = expandVertSize(oldSize, fillVertexCount + count); 
    -                
    +        int newSize = fillVertexCount << 1;
    +
             expandFillVertices(newSize);
             expandFillColors(newSize);
             expandFillNormals(newSize);
    @@ -7306,194 +7288,210 @@ public class PGraphicsOpenGL extends PGraphics {
             expandFillEmissive(newSize);
             expandFillShininess(newSize);
           }
    -                  
    +    }
    +
    +    public void addFillVertices(int count) {
    +      int oldSize = fillVertices.length / 3;
    +      if (fillVertexCount + count > oldSize) {
    +        int newSize = expandVertSize(oldSize, fillVertexCount + count);
    +
    +        expandFillVertices(newSize);
    +        expandFillColors(newSize);
    +        expandFillNormals(newSize);
    +        expandFillTexcoords(newSize);
    +        expandFillAmbient(newSize);
    +        expandFillSpecular(newSize);
    +        expandFillEmissive(newSize);
    +        expandFillShininess(newSize);
    +      }
    +
           firstFillVertex = fillVertexCount;
           fillVertexCount += count;
           lastFillVertex = fillVertexCount - 1;
         }
    -    
    +
         public void addFillIndices(int count) {
           int oldSize = fillIndices.length;
           if (fillIndexCount + count > oldSize) {
    -        int newSize = expandIndSize(oldSize, fillIndexCount + count);    
    -        
    +        int newSize = expandIndSize(oldSize, fillIndexCount + count);
    +
             expandFillIndices(newSize);
           }
    -     
    +
           firstFillIndex = fillIndexCount;
    -      fillIndexCount += count;            
    -      lastFillIndex = fillIndexCount - 1;   
    -    }     
    -    
    +      fillIndexCount += count;
    +      lastFillIndex = fillIndexCount - 1;
    +    }
    +
         protected void expandFillVertices(int n) {
    -      float temp[] = new float[3 * n];      
    +      float temp[] = new float[3 * n];
           PApplet.arrayCopy(fillVertices, 0, temp, 0, 3 * fillVertexCount);
    -      fillVertices = temp;       
    +      fillVertices = temp;
         }
     
         protected void expandFillColors(int n) {
    -      int temp[] = new int[n];      
    +      int temp[] = new int[n];
           PApplet.arrayCopy(fillColors, 0, temp, 0, fillVertexCount);
           fillColors = temp;
         }
    -    
    +
         protected void expandFillNormals(int n) {
    -      float temp[] = new float[3 * n];      
    +      float temp[] = new float[3 * n];
           PApplet.arrayCopy(fillNormals, 0, temp, 0, 3 * fillVertexCount);
    -      fillNormals = temp;       
    +      fillNormals = temp;
         }
    -    
    +
         protected void expandFillTexcoords(int n) {
    -      float temp[] = new float[2 * n];      
    +      float temp[] = new float[2 * n];
           PApplet.arrayCopy(fillTexcoords, 0, temp, 0, 2 * fillVertexCount);
           fillTexcoords = temp;
         }
    -    
    +
         protected void expandFillAmbient(int n) {
    -      int temp[] = new int[n];      
    +      int temp[] = new int[n];
           PApplet.arrayCopy(fillAmbient, 0, temp, 0, fillVertexCount);
    -      fillAmbient = temp;          
    +      fillAmbient = temp;
         }
    -    
    +
         protected void expandFillSpecular(int n) {
    -      int temp[] = new int[n];      
    +      int temp[] = new int[n];
           PApplet.arrayCopy(fillSpecular, 0, temp, 0, fillVertexCount);
    -      fillSpecular = temp;       
    +      fillSpecular = temp;
         }
    -    
    +
         protected void expandFillEmissive(int n) {
    -      int temp[] = new int[n];      
    +      int temp[] = new int[n];
           PApplet.arrayCopy(fillEmissive, 0, temp, 0, fillVertexCount);
    -      fillEmissive = temp;      
    +      fillEmissive = temp;
         }
    -    
    +
         protected void expandFillShininess(int n) {
    -      float temp[] = new float[n];      
    +      float temp[] = new float[n];
           PApplet.arrayCopy(fillShininess, 0, temp, 0, fillVertexCount);
    -      fillShininess = temp;       
    -    }    
    -    
    +      fillShininess = temp;
    +    }
    +
         public void addLineVertices(int count) {
           int oldSize = lineVertices.length / 3;
           if (lineVertexCount + count > oldSize) {
             int newSize = expandVertSize(oldSize, lineVertexCount + count);
    -        
    +
             expandLineVertices(newSize);
             expandLineColors(newSize);
             expandLineAttributes(newSize);
           }
    -      
    +
           firstLineVertex = lineVertexCount;
    -      lineVertexCount += count;            
    +      lineVertexCount += count;
           lastLineVertex = lineVertexCount - 1;
         }
     
         protected void expandLineVertices(int n) {
    -      float temp[] = new float[3 * n];      
    +      float temp[] = new float[3 * n];
           PApplet.arrayCopy(lineVertices, 0, temp, 0, 3 * lineVertexCount);
    -      lineVertices = temp;  
    +      lineVertices = temp;
         }
    -    
    +
         protected void expandLineColors(int n) {
    -      int temp[] = new int[n];      
    +      int temp[] = new int[n];
           PApplet.arrayCopy(lineColors, 0, temp, 0, lineVertexCount);
    -      lineColors = temp;      
    +      lineColors = temp;
         }
    -    
    +
         protected void expandLineAttributes(int n) {
    -      float temp[] = new float[4 * n];      
    +      float temp[] = new float[4 * n];
           PApplet.arrayCopy(lineDirWidths, 0, temp, 0, 4 * lineVertexCount);
    -      lineDirWidths = temp;      
    -    }      
    -    
    +      lineDirWidths = temp;
    +    }
    +
         public void addLineIndices(int count) {
           int oldSize = lineIndices.length;
           if (lineIndexCount + count > oldSize) {
             int newSize = expandIndSize(oldSize, lineIndexCount + count);
    -        
    +
             expandLineIndices(newSize);
           }
    -     
    +
           firstLineIndex = lineIndexCount;
    -      lineIndexCount += count;      
    -      lastLineIndex = lineIndexCount - 1;   
    -    }   
    -    
    -    protected void expandLineIndices(int n) {
    -      short temp[] = new short[n];      
    -      PApplet.arrayCopy(lineIndices, 0, temp, 0, lineIndexCount);
    -      lineIndices = temp;        
    +      lineIndexCount += count;
    +      lastLineIndex = lineIndexCount - 1;
         }
    -    
    +
    +    protected void expandLineIndices(int n) {
    +      short temp[] = new short[n];
    +      PApplet.arrayCopy(lineIndices, 0, temp, 0, lineIndexCount);
    +      lineIndices = temp;
    +    }
    +
         public void addPointVertices(int count) {
           int oldSize = pointVertices.length / 3;
           if (pointVertexCount + count > oldSize) {
             int newSize = expandVertSize(oldSize, pointVertexCount + count);
    -        
    +
             expandPointVertices(newSize);
             expandPointColors(newSize);
             expandPointAttributes(newSize);
           }
    -      
    +
           firstPointVertex = pointVertexCount;
    -      pointVertexCount += count;      
    +      pointVertexCount += count;
           lastPointVertex = pointVertexCount - 1;
         }
     
         protected void expandPointVertices(int n) {
    -      float temp[] = new float[3 * n];      
    +      float temp[] = new float[3 * n];
           PApplet.arrayCopy(pointVertices, 0, temp, 0, 3 * pointVertexCount);
    -      pointVertices = temp;  
    +      pointVertices = temp;
         }
    -    
    +
         protected void expandPointColors(int n) {
    -      int temp[] = new int[n];      
    +      int temp[] = new int[n];
           PApplet.arrayCopy(pointColors, 0, temp, 0, pointVertexCount);
    -      pointColors = temp;      
    +      pointColors = temp;
         }
    -    
    +
         protected void expandPointAttributes(int n) {
    -      float temp[] = new float[2 * n];      
    +      float temp[] = new float[2 * n];
           PApplet.arrayCopy(pointSizes, 0, temp, 0, 2 * pointVertexCount);
    -      pointSizes = temp;      
    +      pointSizes = temp;
         }
    -    
    +
         public void addPointIndices(int count) {
           int oldSize = pointIndices.length;
           if (pointIndexCount + count > oldSize) {
             int newSize = expandIndSize(oldSize, pointIndexCount + count);
    -        
    +
             expandPointIndices(newSize);
           }
    -     
    +
           firstPointIndex = pointIndexCount;
    -      pointIndexCount += count;      
    -      lastPointIndex = pointIndexCount - 1;   
    -    }   
    -    
    -    protected void expandPointIndices(int n) {
    -      short temp[] = new short[n];      
    -      PApplet.arrayCopy(pointIndices, 0, temp, 0, pointIndexCount);
    -      pointIndices = temp;        
    +      pointIndexCount += count;
    +      lastPointIndex = pointIndexCount - 1;
         }
    -    
    -    public void addFillVertex(float x, float y, float z, 
    +
    +    protected void expandPointIndices(int n) {
    +      short temp[] = new short[n];
    +      PApplet.arrayCopy(pointIndices, 0, temp, 0, pointIndexCount);
    +      pointIndices = temp;
    +    }
    +
    +    public void addFillVertex(float x, float y, float z,
                                   int rgba,
    -                              float nx, float ny, float nz, 
    -                              float u, float v, 
    +                              float nx, float ny, float nz,
    +                              float u, float v,
                                   int am, int sp, int em, float shine) {
           fillVertexCheck();
           int index;
    -      
    +
           if (renderMode == IMMEDIATE && flushMode == FLUSH_WHEN_FULL && !hints[DISABLE_TRANSFORM_CACHE]) {
             PMatrix3D mm = modelview;
             PMatrix3D nm = modelviewInv;
    -        
    +
             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;
    -        
    +
             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;
    @@ -7507,59 +7505,59 @@ public class PGraphicsOpenGL extends PGraphics {
             index = 3 * fillVertexCount;
             fillNormals[index++] = nx;
             fillNormals[index++] = ny;
    -        fillNormals[index  ] = nz;        
    +        fillNormals[index  ] = nz;
           }
    -      
    +
           fillColors[fillVertexCount] = rgba;
    -      
    +
           index = 2 * fillVertexCount;
           fillTexcoords[index++] = u;
    -      fillTexcoords[index  ] = v;      
    -      
    +      fillTexcoords[index  ] = v;
    +
           fillAmbient[fillVertexCount] = am;
           fillSpecular[fillVertexCount] = sp;
           fillEmissive[fillVertexCount] = em;
           fillShininess[fillVertexCount] = shine;
    -      
    +
           fillVertexCount++;
    -    }    
    +    }
     
         public void addFillVertices(InGeometry in) {
           int index;
           int i0 = in.firstVertex;
           int i1 = in.lastVertex;
           int nvert = i1 - i0 + 1;
    -      
    +
           addFillVertices(nvert);
    -      
    +
           if (renderMode == IMMEDIATE && flushMode == FLUSH_WHEN_FULL && !hints[DISABLE_TRANSFORM_CACHE]) {
             PMatrix3D mm = modelview;
             PMatrix3D nm = modelviewInv;
    -        
    +
             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 * 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;
    -          
    +
               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 {
             if (nvert <= PGL.MIN_ARRAYCOPY_SIZE) {
               // Copying elements one by one instead of using arrayCopy is more efficient for
    @@ -7572,28 +7570,28 @@ public class PGraphicsOpenGL extends PGraphics {
                 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 {          
    +          }
    +        } else {
               PApplet.arrayCopy(in.vertices, 3 * i0, fillVertices, 3 * firstFillVertex, 3 * nvert);
    -          PApplet.arrayCopy(in.normals, 3 * i0, fillNormals, 3 * firstFillVertex, 3 * nvert);                  
    +          PApplet.arrayCopy(in.normals, 3 * i0, fillNormals, 3 * firstFillVertex, 3 * nvert);
             }
           }
    -        
    +
           if (nvert <= PGL.MIN_ARRAYCOPY_SIZE) {
             for (int i = 0; i < nvert; i++) {
               int inIdx = i0 + i;
    @@ -7602,28 +7600,28 @@ public class PGraphicsOpenGL extends PGraphics {
               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];          
    +          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.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);        
    +        PApplet.arrayCopy(in.shininess, i0, fillShininess, firstFillVertex, nvert);
           }
    -    }     
    -    
    +    }
    +
         public void putLineVertex(InGeometry in, int inIdx0, int inIdx1, int tessIdx, int rgba) {
           int index;
     
    @@ -7631,44 +7629,44 @@ public class PGraphicsOpenGL extends PGraphics {
           float x0 = in.vertices[index++];
           float y0 = in.vertices[index++];
           float z0 = in.vertices[index  ];
    -      
    +
           index = 3 * inIdx1;
           float x1 = in.vertices[index++];
           float y1 = in.vertices[index++];
    -      float z1 = in.vertices[index  ];        
    -      
    +      float z1 = in.vertices[index  ];
    +
           if (renderMode == IMMEDIATE && flushMode == FLUSH_WHEN_FULL && !hints[DISABLE_TRANSFORM_CACHE]) {
             PMatrix3D mm = modelview;
    -        
    +
             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;
    -        
    +
             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;        
    +        lineDirWidths[index  ] = x1 * mm.m20 + y1 * mm.m21 + z1 * mm.m22 + mm.m23;
           } else {
             index = 3 * tessIdx;
             lineVertices[index++] = x0;
             lineVertices[index++] = y0;
             lineVertices[index  ] = z0;
    -        
    +
             index = 4 * tessIdx;
             lineDirWidths[index++] = x1;
             lineDirWidths[index++] = y1;
             lineDirWidths[index  ] = z1;
    -      }      
    -      
    +      }
    +
           lineColors[tessIdx] = rgba;
         }
     
    -    public void putLineVertex(InGeometry in, int inIdx0, int inIdx1, int tessIdx) {      
    +    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;
     
    @@ -7676,43 +7674,43 @@ public class PGraphicsOpenGL extends PGraphics {
           float x = in.vertices[index++];
           float y = in.vertices[index++];
           float z = in.vertices[index ];
    -      
    +
           if (renderMode == IMMEDIATE && flushMode == FLUSH_WHEN_FULL && !hints[DISABLE_TRANSFORM_CACHE]) {
             PMatrix3D mm = modelview;
    -        
    +
             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;        
    +        pointVertices[index  ] = x * mm.m20 + y * mm.m21 + z * mm.m22 + mm.m23;
           } else {
             index = 3 * tessIdx;
             pointVertices[index++] = x;
             pointVertices[index++] = y;
             pointVertices[index  ] = z;
    -      }      
    -      
    +      }
    +
           pointColors[tessIdx] = in.scolors[inIdx];
         }
    -    
    +
         public int expandVertSize(int currSize, int newMinSize) {
    -      int newSize = currSize; 
    +      int newSize = currSize;
           while (newSize < newMinSize) {
    -        newSize <<= 1;        
    +        newSize <<= 1;
           }
           return newSize;
         }
     
         public int expandIndSize(int currSize, int newMinSize) {
    -      int newSize = currSize; 
    +      int newSize = currSize;
           while (newSize < newMinSize) {
             newSize <<= 1;
           }
           return newSize;
    -    }    
    -    
    +    }
    +
         public void center(float cx, float cy) {
           int index;
    -      
    +
           // Computing current center
           float cx0 = 0;
           float cy0 = 0;
    @@ -7729,53 +7727,53 @@ public class PGraphicsOpenGL extends PGraphics {
           for (int i = 0; i < pointVertexCount; i++) {
             index = 3 * i;
             cx0 += pointVertices[index++];
    -        cy0 += pointVertices[index  ];          
    -      }      
    +        cy0 += pointVertices[index  ];
    +      }
           int nt = fillVertexCount + lineVertexCount + pointVertexCount;
    -      if (0 < nt) { 
    +      if (0 < nt) {
             cx0 /= nt;
             cy0 /= nt;
           }
     
           float tx = cx - cx0;
           float ty = cy - cy0;
    -      
    +
           if (0 < fillVertexCount) {
             for (int i = 0; i < fillVertexCount; i++) {
               index = 3 * i;
               fillVertices[index++] += tx;
               fillVertices[index  ] += ty;
    -        }        
    +        }
           }
    -      
    +
           if (0 < lineVertexCount) {
             for (int i = 0; i < lineVertexCount; i++) {
               index = 3 * i;
               lineVertices[index++] += tx;
               lineVertices[index  ] += ty;
    -          
    +
               index = 4 * i;
               lineDirWidths[index++] += tx;
    -          lineDirWidths[index  ] += ty;           
    +          lineDirWidths[index  ] += ty;
             }
           }
    -      
    +
           if (0 < pointVertexCount) {
             for (int i = 0; i < pointVertexCount; i++) {
               index = 3 * i;
               pointVertices[index++] += tx;
               pointVertices[index  ] += ty;
    -        }        
    -      }      
    +        }
    +      }
         }
    -    
    +
         public void center(float cx, float cy, float cz) {
           int index;
    -      
    +
           // Computing current center
           float cx0 = 0;
           float cy0 = 0;
    -      float cz0 = 0;      
    +      float cz0 = 0;
           for (int i = 0; i < fillVertexCount; i++) {
             index = 3 * i;
             cx0 += fillVertices[index++];
    @@ -7786,16 +7784,16 @@ public class PGraphicsOpenGL extends PGraphics {
             index = 3 * i;
             cx0 += lineVertices[index++];
             cy0 += lineVertices[index++];
    -        cz0 += lineVertices[index  ];        
    +        cz0 += lineVertices[index  ];
           }
           for (int i = 0; i < pointVertexCount; i++) {
             index = 3 * i;
             cx0 += pointVertices[index++];
             cy0 += pointVertices[index++];
    -        cz0 += pointVertices[index  ];          
    -      }      
    +        cz0 += pointVertices[index  ];
    +      }
           int nt = fillVertexCount + lineVertexCount + pointVertexCount;
    -      if (0 < nt) { 
    +      if (0 < nt) {
             cx0 /= nt;
             cy0 /= nt;
             cz0 /= nt;
    @@ -7803,41 +7801,41 @@ public class PGraphicsOpenGL extends PGraphics {
     
           float tx = cx - cx0;
           float ty = cy - cy0;
    -      float tz = cz - cz0;      
    -      
    +      float tz = cz - cz0;
    +
           if (0 < fillVertexCount) {
             for (int i = 0; i < fillVertexCount; i++) {
               index = 3 * i;
               fillVertices[index++] += tx;
               fillVertices[index++] += ty;
               fillVertices[index  ] += tz;
    -        }        
    +        }
           }
    -      
    +
           if (0 < lineVertexCount) {
             for (int i = 0; i < lineVertexCount; i++) {
               index = 3 * i;
               lineVertices[index++] += tx;
               lineVertices[index++] += ty;
               lineVertices[index  ] += tz;
    -          
    +
               index = 4 * i;
               lineDirWidths[index++] += tx;
               lineDirWidths[index++] += ty;
    -          lineDirWidths[index  ] += tz;           
    +          lineDirWidths[index  ] += tz;
             }
           }
    -      
    +
           if (0 < pointVertexCount) {
             for (int i = 0; i < pointVertexCount; i++) {
               index = 3 * i;
               pointVertices[index++] += tx;
               pointVertices[index++] += ty;
               pointVertices[index  ] += tz;
    -        }        
    +        }
           }
         }
    -    
    +
         public int getCenter(PVector v) {
           int index;
           for (int i = 0; i < fillVertexCount; i++) {
    @@ -7850,26 +7848,26 @@ public class PGraphicsOpenGL extends PGraphics {
             index = 3 * i;
             v.x += lineVertices[index++];
             v.y += lineVertices[index++];
    -        v.z += lineVertices[index  ];        
    +        v.z += lineVertices[index  ];
           }
           for (int i = 0; i < pointVertexCount; i++) {
             index = 3 * i;
             v.x += pointVertices[index++];
             v.y += pointVertices[index++];
    -        v.z += pointVertices[index  ];          
    -      }      
    +        v.z += pointVertices[index  ];
    +      }
           return fillVertexCount + lineVertexCount + pointVertexCount;
         }
    -    
    +
         public void applyMatrix(PMatrix2D tr) {
           if (0 < fillVertexCount) {
             int index;
    -          
    +
             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  ];
    @@ -7877,60 +7875,60 @@ public class PGraphicsOpenGL extends PGraphics {
               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;          
    +          fillNormals[index  ] = nx * tr.m10 + ny * tr.m11;
             }
           }
     
           if (0 < lineVertexCount) {
             int index;
    -        
    +
             for (int i = 0; i < lineVertexCount; i++) {
               index = 3 * i;
               float x = lineVertices[index++];
               float y = lineVertices[index  ];
    -        
    +
               index = 4 * i;
               float xa = lineDirWidths[index++];
               float ya = lineDirWidths[index  ];
    -                    
    +
               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;              
    -        }   
    -      }      
    -      
    +          lineDirWidths[index  ] = xa * tr.m10 + ya * tr.m11 + tr.m12;
    +        }
    +      }
    +
           if (0 < pointVertexCount) {
             int index;
    -       
    +
             for (int i = 0; i < pointVertexCount; i++) {
               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) {
           if (0 < fillVertexCount) {
             int index;
    -          
    +
             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++];
    @@ -7940,59 +7938,59 @@ public class PGraphicsOpenGL extends PGraphics {
               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;          
    +          fillNormals[index  ] = nx * tr.m20 + ny * tr.m21 + nz * tr.m22;
             }
           }
     
           if (0 < lineVertexCount) {
             int index;
    -        
    +
             for (int i = 0; i < lineVertexCount; i++) {
               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;              
    -        }   
    -      }      
    -      
    +          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++) {
               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;
    -        } 
    -      }      
    -    }    
    +        }
    +      }
    +    }
       }
     
    -  final static protected int MIN_ACCURACY = 6; 
    +  final static protected int MIN_ACCURACY = 6;
       final static protected float sinLUT[];
       final static protected float cosLUT[];
       final static protected float SINCOS_PRECISION = 0.5f;
    @@ -8003,24 +8001,24 @@ public class PGraphicsOpenGL extends PGraphics {
         for (int i = 0; i < SINCOS_LENGTH; i++) {
           sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION);
           cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION);
    -    }      
    -  }  
    +    }
    +  }
       final protected float[][] QUAD_SIGNS = { {-1, +1}, {-1, -1}, {+1, -1}, {+1, +1} };
    -  
    -  // Generates tessellated geometry given a batch of input vertices.  
    -  public class Tessellator {    
    -    InGeometry in; 
    +
    +  // Generates tessellated geometry given a batch of input vertices.
    +  public class Tessellator {
    +    InGeometry in;
         TessGeometry tess;
         PGL.Tessellator gluTess;
         TessellatorCallback callback;
    -    
    +
         boolean fill;
         boolean stroke;
         float strokeWeight;
         int strokeJoin;
         int strokeCap;
         int bezierDetil = 20;
    -    
    +
         public Tessellator() {
           callback = new TessellatorCallback();
           gluTess = pgl.createTessellator(callback);
    @@ -8034,42 +8032,42 @@ public class PGraphicsOpenGL extends PGraphics {
         public void setTessGeometry(TessGeometry tess) {
           this.tess = tess;
         }
    -    
    +
         public void setFill(boolean fill) {
           this.fill = fill;
    -    }    
    -    
    +    }
    +
         public void setStroke(boolean stroke) {
           this.stroke = stroke;
         }
    -    
    +
         public void setStrokeWeight(float weight) {
           this.strokeWeight = weight;
         }
    -    
    -    public void setStrokeJoin(int strokeJoin) { 
    +
    +    public void setStrokeJoin(int strokeJoin) {
           this.strokeJoin = strokeJoin;
         }
    -    
    -    public void setStrokeCap(int strokeCap) { 
    +
    +    public void setStrokeCap(int strokeCap) {
           this.strokeCap = strokeCap;
         }
    -    
    +
         public void tessellatePoints() {
           if (strokeCap == ROUND) {
             tessellateRoundPoints();
           } else {
             tessellateSquarePoints();
           }
    -    }    
    +    }
     
         protected void tessellateRoundPoints() {
           int nInVert = in.lastVertex - in.firstVertex + 1;
    -      
    +
           if (stroke && 1 <= nInVert) {
             tess.isStroked = true;
    -        
    -        // Each point generates a separate triangle fan. 
    +
    +        // Each point generates a separate triangle fan.
             // The number of triangles of each fan depends on the
             // stroke weight of the point.
             int nvertTot = 0;
    @@ -8078,29 +8076,29 @@ public class PGraphicsOpenGL extends PGraphics {
               int perim = PApplet.max(MIN_ACCURACY, (int) (TWO_PI * strokeWeight / 20));
               // Number of points along the perimeter plus the center point.
               int nvert = perim + 1;
    -          nvertTot += nvert; 
    +          nvertTot += nvert;
               nindTot += 3 * (nvert - 1);
             }
    -     
    +
             checkForFlush(tess.lineVertexCount + nvertTot, tess.lineIndexCount + nindTot);
    -        
    +
             tess.addPointVertices(nvertTot);
             tess.addPointIndices(nindTot);
             int vertIdx = tess.firstPointVertex;
             int attribIdx = tess.firstPointVertex;
    -        int indIdx = tess.firstPointIndex;      
    -        int firstVert = tess.firstPointVertex;      
    +        int indIdx = tess.firstPointIndex;
    +        int firstVert = tess.firstPointVertex;
             for (int i = in.firstVertex; i <= in.lastVertex; i++) {
               // Creating the triangle fan for each input vertex.
               int perim = PApplet.max(MIN_ACCURACY, (int) (TWO_PI * strokeWeight / 20));
               int nvert = perim + 1;
    -          
    +
               // All the tessellated vertices are identical to the center point
               for (int k = 0; k < nvert; k++) {
                 tess.putPointVertex(in, i, vertIdx);
    -            vertIdx++; 
    -          }       
    -          
    +            vertIdx++;
    +          }
    +
               // The attributes for each tessellated vertex are the displacement along
               // the circle perimeter. The point shader will read these attributes and
               // displace the vertices in screen coordinates so the circles are always
    @@ -8109,14 +8107,14 @@ public class PGraphicsOpenGL extends PGraphics {
               tess.pointSizes[2 * attribIdx + 1] = 0;
               attribIdx++;
               float val = 0;
    -          float inc = (float) SINCOS_LENGTH / perim;      
    +          float inc = (float) SINCOS_LENGTH / perim;
               for (int k = 0; k < perim; k++) {
                 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++;           
    +            val = (val + inc) % SINCOS_LENGTH;
    +            attribIdx++;
               }
    -          
    +
               // Adding vert0 to take into account the triangles of all
               // the preceding points.
               for (int k = 1; k < nvert - 1; k++) {
    @@ -8127,59 +8125,59 @@ public class PGraphicsOpenGL extends PGraphics {
               // Final triangle between the last and first point:
               tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + 0);
               tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + 1);
    -          tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + nvert - 1);      
    -          
    +          tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + nvert - 1);
    +
               firstVert = vertIdx;
    -        } 
    +        }
           }
         }
    -    
    +
         protected void tessellateSquarePoints() {
           int nInVert = in.lastVertex - in.firstVertex + 1;
    -      
    +
           if (stroke && 1 <= nInVert) {
             tess.isStroked = true;
    -        
    +
             // Each point generates a separate quad.
             int quadCount = nInVert;
    -        
    +
             // Each quad is formed by 5 vertices, the center one
    -        // is the input vertex, and the other 4 define the 
    +        // is the input vertex, and the other 4 define the
             // corners (so, a triangle fan again).
             int nvertTot = 5 * quadCount;
             // So the quad is formed by 4 triangles, each requires
             // 3 indices.
             int nindTot = 12 * quadCount;
    -        
    -        checkForFlush(tess.lineVertexCount + nvertTot, tess.lineIndexCount + nindTot);     
    -        
    +
    +        checkForFlush(tess.lineVertexCount + nvertTot, tess.lineIndexCount + nindTot);
    +
             tess.addPointVertices(nvertTot);
             tess.addPointIndices(nindTot);
             int vertIdx = tess.firstPointVertex;
             int attribIdx = tess.firstPointVertex;
    -        int indIdx = tess.firstPointIndex;      
    -        int firstVert = tess.firstPointVertex;      
    +        int indIdx = tess.firstPointIndex;
    +        int firstVert = tess.firstPointVertex;
             for (int i = in.firstVertex; i <= in.lastVertex; i++) {
               int nvert = 5;
    -          
    +
               for (int k = 0; k < nvert; k++) {
                 tess.putPointVertex(in, i, vertIdx);
    -            vertIdx++; 
    -          }       
    -          
    +            vertIdx++;
    +          }
    +
               // The attributes for each tessellated vertex are the displacement along
               // 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[2 * attribIdx + 0] = 0;
               tess.pointSizes[2 * attribIdx + 1] = 0;
    -          attribIdx++;            
    +          attribIdx++;
               for (int k = 0; k < 4; k++) {
                 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++;           
    +            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++) {
    @@ -8190,33 +8188,33 @@ public class PGraphicsOpenGL extends PGraphics {
               // Final triangle between the last and first point:
               tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + 0);
               tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + 1);
    -          tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + nvert - 1);  
    -          
    +          tess.pointIndices[indIdx++] = PGL.makeIndex(firstVert + nvert - 1);
    +
               firstVert = vertIdx;
             }
           }
         }
    -    
    +
         public void tessellateLines() {
           int nInVert = in.lastVertex - in.firstVertex + 1;
    -      
    +
           if (stroke && 2 <= nInVert) {
             tess.isStroked = true;
    -        
    +
             int lineCount = nInVert / 2;
             int first = in.firstVertex;
     
    -        // Lines are made up of 4 vertices defining the quad. 
    +        // Lines are made up of 4 vertices defining the quad.
             // Each vertex has its own offset representing the stroke weight.
             int nvert = lineCount * 4;
             // Each stroke line has 4 vertices, defining 2 triangles, which
             // require 3 indices to specify their connectivities.
             int nind = lineCount * 2 * 3;
     
    -        checkForFlush(tess.lineVertexCount + nvert, tess.lineIndexCount + nvert);        
    -        
    +        checkForFlush(tess.lineVertexCount + nvert, tess.lineIndexCount + nvert);
    +
             tess.addLineVertices(nvert);
    -        tess.addLineIndices(nind);      
    +        tess.addLineIndices(nind);
             int vcount = tess.firstLineVertex;
             int icount = tess.firstLineIndex;
             for (int ln = 0; ln < lineCount; ln++) {
    @@ -8224,68 +8222,68 @@ public class PGraphicsOpenGL extends PGraphics {
               int i1 = first + 2 * ln + 1;
               addLine(i0, i1, vcount, icount); vcount += 4; icount += 6;
             }
    -      }  
    +      }
         }
    -    
    +
         public void tessellateTriangles() {
    -      int nInVert = in.lastVertex - in.firstVertex + 1;      
    -      
    -      if (fill && 3 <= nInVert) {        
    +      int nInVert = in.lastVertex - in.firstVertex + 1;
    +
    +      if (fill && 3 <= nInVert) {
             int nInInd = nInVert;
             checkForFlush(tess.fillVertexCount + nInVert, tess.fillIndexCount + nInInd);
    -        
    +
             tess.addFillVertices(in);
    -        
    +
             tess.addFillIndices(nInVert);
             int idx0 = tess.firstFillIndex;
             int offset = tess.firstFillVertex;
             for (int i = in.firstVertex; i <= in.lastVertex; i++) {
               tess.fillIndices[idx0 + i] = PGL.makeIndex(offset + i);
    -        }        
    +        }
           }
     
           if (stroke) {
             tess.isStroked = true;
    -        tessellateEdges();        
    -      }      
    +        tessellateEdges();
    +      }
         }
    -    
    +
         public void tessellateTriangleFan() {
           int nInVert = in.lastVertex - in.firstVertex + 1;
    -            
    +
           if (fill && 3 <= nInVert) {
    -        int nInInd = 3 * (nInVert - 2); 
    +        int nInInd = 3 * (nInVert - 2);
             checkForFlush(tess.fillVertexCount + nInVert, tess.fillIndexCount + nInInd);
    -        
    +
             tess.addFillVertices(in);
     
             tess.addFillIndices(nInInd);
             int idx = tess.firstFillIndex;
    -        int offset = tess.firstFillVertex; 
    +        int offset = tess.firstFillVertex;
             for (int i = in.firstVertex + 1; i < in.lastVertex; i++) {
               tess.fillIndices[idx++] = PGL.makeIndex(offset + in.firstVertex);
               tess.fillIndices[idx++] = PGL.makeIndex(offset + i);
               tess.fillIndices[idx++] = PGL.makeIndex(offset + i + 1);
             }
           }
    -      
    +
           if (stroke) {
             tess.isStroked = true;
             tessellateEdges();
           }
         }
    -        
    +
         public void tessellateTriangleStrip() {
           int nInVert = in.lastVertex - in.firstVertex + 1;
    -      
    +
           if (fill && 3 <= nInVert) {
             int triCount = nInVert - 2;
             int nInInd = 3 * triCount;
    -        
    +
             checkForFlush(tess.fillVertexCount + nInVert, tess.fillIndexCount + nInInd);
    -        
    +
             tess.addFillVertices(in);
    -        
    +
             // Each vertex, except the first and last, defines a triangle.
             tess.addFillIndices(nInInd);
             int idx = tess.firstFillIndex;
    @@ -8293,15 +8291,15 @@ public class PGraphicsOpenGL extends PGraphics {
             for (int i = in.firstVertex + 1; i < in.lastVertex; i++) {
               tess.fillIndices[idx++] = PGL.makeIndex(offset + i);
               if (i % 2 == 0) {
    -            tess.fillIndices[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[idx++] = PGL.makeIndex(offset + i + 1);  
    +            tess.fillIndices[idx++] = PGL.makeIndex(offset + i + 1);
                 tess.fillIndices[idx++] = PGL.makeIndex(offset + i - 1);
               }
    -        }              
    -      }      
    -      
    +        }
    +      }
    +
           if (stroke) {
             tess.isStroked = true;
             tessellateEdges();
    @@ -8310,136 +8308,136 @@ public class PGraphicsOpenGL extends PGraphics {
     
         public void tessellateQuads() {
           int nInVert = in.lastVertex - in.firstVertex + 1;
    -      
    +
           if (fill && 4 <= nInVert) {
             int quadCount = nInVert / 4;
             int nInInd = 6 * quadCount;
    -        
    +
             checkForFlush(tess.fillVertexCount + nInVert, tess.fillIndexCount + nInInd);
             tess.addFillVertices(in);
    -        
    +
             tess.addFillIndices(nInInd);
             int idx = tess.firstFillIndex;
    -        int offset = tess.firstFillVertex; 
    -        for (int qd = 0; qd < quadCount; qd++) {        
    +        int offset = tess.firstFillVertex;
    +        for (int qd = 0; qd < quadCount; qd++) {
               int i0 = offset + 4 * qd + 0;
               int i1 = offset + 4 * qd + 1;
               int i2 = offset + 4 * qd + 2;
               int i3 = offset + 4 * qd + 3;
    -          
    +
               tess.fillIndices[idx++] = PGL.makeIndex(i0);
               tess.fillIndices[idx++] = PGL.makeIndex(i1);
               tess.fillIndices[idx++] = PGL.makeIndex(i3);
    -          
    +
               tess.fillIndices[idx++] = PGL.makeIndex(i1);
               tess.fillIndices[idx++] = PGL.makeIndex(i2);
               tess.fillIndices[idx++] = PGL.makeIndex(i3);
    -        }              
    +        }
           }
    -      
    +
           if (stroke) {
             tess.isStroked = true;
             tessellateEdges();
           }
         }
    -    
    -    
    +
    +
         public void tessellateQuadStrip() {
           int nInVert = in.lastVertex - in.firstVertex + 1;
    -      
    +
           if (fill && 4 <= nInVert) {
             int quadCount = nInVert / 2 - 1;
             int nInInd = 6 * quadCount;
    -        
    +
             checkForFlush(tess.fillVertexCount + nInVert, tess.fillIndexCount + nInInd);
    -        tess.addFillVertices(in);        
    -        
    +        tess.addFillVertices(in);
    +
             tess.addFillIndices(nInInd);
             int idx = tess.firstFillIndex;
    -        int offset = tess.firstFillVertex; 
    -        for (int qd = 1; qd < nInVert / 2; qd++) {        
    +        int offset = tess.firstFillVertex;
    +        for (int qd = 1; qd < nInVert / 2; qd++) {
               int i0 = offset + 2 * (qd - 1);
               int i1 = offset + 2 * (qd - 1) + 1;
               int i2 = offset + 2 * qd + 1;
    -          int i3 = offset + 2 * qd;      
    -          
    +          int i3 = offset + 2 * qd;
    +
               tess.fillIndices[idx++] = PGL.makeIndex(i0);
               tess.fillIndices[idx++] = PGL.makeIndex(i1);
               tess.fillIndices[idx++] = PGL.makeIndex(i3);
    -          
    +
               tess.fillIndices[idx++] = PGL.makeIndex(i1);
               tess.fillIndices[idx++] = PGL.makeIndex(i2);
               tess.fillIndices[idx++] = PGL.makeIndex(i3);
    -        }              
    +        }
           }
    - 
    +
           if (stroke) {
             tess.isStroked = true;
             tessellateEdges();
           }
    -    }  
    -    
    +    }
    +
         public void tessellatePolygon(boolean solid, boolean closed, boolean calcNormals) {
           int nInVert = in.lastVertex - in.firstVertex + 1;
    -      
    +
           callback.calcNormals = calcNormals;
    -      
    +
           if (fill && 3 <= nInVert) {
             checkForFlush(nInVert);
    -        
    +
             gluTess.beginPolygon();
    -        
    +
             if (solid) {
               // Using NONZERO winding rule for solid polygons.
    -          gluTess.setWindingRule(PGL.GLU_TESS_WINDING_NONZERO);          
    +          gluTess.setWindingRule(PGL.GLU_TESS_WINDING_NONZERO);
             } else {
               // Using ODD winding rule to generate polygon with holes.
               gluTess.setWindingRule(PGL.GLU_TESS_WINDING_ODD);
             }
     
    -        gluTess.beginContour();    
    -        
    +        gluTess.beginContour();
    +
             // Now, iterate over all input data and send to GLU tessellator..
             for (int i = in.firstVertex; i <= in.lastVertex; i++) {
    -          boolean breakPt = in.codes[i] == PShape.BREAK;      
    +          boolean breakPt = in.codes[i] == PShape.BREAK;
               if (breakPt) {
                 gluTess.endContour();
                 gluTess.beginContour();
               }
    -                    
    +
               // Separting colors into individual rgba components for interpolation.
               int fa = (in.colors[i] >> 24) & 0xFF;
               int fr = (in.colors[i] >> 16) & 0xFF;
    -          int fg = (in.colors[i] >>  8) & 0xFF; 
    +          int fg = (in.colors[i] >>  8) & 0xFF;
               int fb = (in.colors[i] >>  0) & 0xFF;
    -          
    +
               int aa = (in.ambient[i] >> 24) & 0xFF;
               int ar = (in.ambient[i] >> 16) & 0xFF;
    -          int ag = (in.ambient[i] >>  8) & 0xFF; 
    +          int ag = (in.ambient[i] >>  8) & 0xFF;
               int ab = (in.ambient[i] >>  0) & 0xFF;
     
               int sa = (in.specular[i] >> 24) & 0xFF;
               int sr = (in.specular[i] >> 16) & 0xFF;
    -          int sg = (in.specular[i] >>  8) & 0xFF; 
    -          int sb = (in.specular[i] >>  0) & 0xFF; 
    -          
    +          int sg = (in.specular[i] >>  8) & 0xFF;
    +          int sb = (in.specular[i] >>  0) & 0xFF;
    +
               int ea = (in.emissive[i] >> 24) & 0xFF;
               int er = (in.emissive[i] >> 16) & 0xFF;
    -          int eg = (in.emissive[i] >>  8) & 0xFF; 
    -          int eb = (in.emissive[i] >>  0) & 0xFF; 
    -          
    +          int eg = (in.emissive[i] >>  8) & 0xFF;
    +          int eb = (in.emissive[i] >>  0) & 0xFF;
    +
               // Vertex data includes coordinates, colors, normals, texture coordinates, and material properties.
               double[] vertex = new double[] { in.vertices [3 * i + 0], in.vertices [3 * i + 1], in.vertices[3 * i + 2],
                                                fa, fr, fg, fb,
                                                in.normals  [3 * i + 0], in.normals  [3 * i + 1], in.normals [3 * i + 2],
                                                in.texcoords[2 * i + 0], in.texcoords[2 * i + 1],
    -                                           aa, ar, ag, ab, sa, sr, sg, sb, ea, er, eg, eb, 
    +                                           aa, ar, ag, ab, sa, sr, sg, sb, ea, er, eg, eb,
                                                in.shininess[i] };
    -          
    +
               gluTess.addVertex(vertex);
    -        }        
    +        }
             gluTess.endContour();
    -        
    +
             gluTess.endPolygon();
           }
     
    @@ -8448,94 +8446,94 @@ public class PGraphicsOpenGL extends PGraphics {
             tessellateEdges();
           }
         }
    -    
    +
         // Adding the data that defines a quad starting at vertex i0 and
         // ending at i1.
         protected void addLine(int i0, int i1, int vcount, int icount) {
           tess.putLineVertex(in, i0, i1, vcount);
    -   
    +
           tess.lineDirWidths[4 * vcount + 3] = +strokeWeight;
           tess.lineIndices[icount++] = PGL.makeIndex(vcount);
    -      
    +
           vcount++;
           tess.putLineVertex(in, i0, i1, vcount);
           tess.lineDirWidths[4 * vcount + 3] = -strokeWeight;
           tess.lineIndices[icount++] = PGL.makeIndex(vcount);
    -      
    +
           vcount++;
           tess.putLineVertex(in, i1, i0, vcount);
           tess.lineDirWidths[4 * vcount + 3] = -strokeWeight;
           tess.lineIndices[icount++] = PGL.makeIndex(vcount);
    -      
    +
           // Starting a new triangle re-using prev vertices.
           tess.lineIndices[icount++] = PGL.makeIndex(vcount);
           tess.lineIndices[icount++] = PGL.makeIndex(vcount - 1);
    -      
    +
           vcount++;
    -      tess.putLineVertex(in, i1, i0, vcount);      
    +      tess.putLineVertex(in, i1, i0, vcount);
           tess.lineDirWidths[4 * vcount + 3] = +strokeWeight;
           tess.lineIndices[icount++] = PGL.makeIndex(vcount);
         }
    -    
    +
         public void tessellateEdges() {
           int nInVert = in.getNumLineVertices();
    -      int nInInd = in.getNumLineIndices();     
    -      
    +      int nInInd = in.getNumLineIndices();
    +
           checkForFlush(tess.lineVertexCount + nInVert, tess.lineIndexCount + nInInd);
    -      
    +
           tess.addLineVertices(nInVert);
           tess.addLineIndices(nInInd);
           int vcount = tess.firstLineVertex;
    -      int icount = tess.firstLineIndex;          
    +      int icount = tess.firstLineIndex;
           for (int i = in.firstEdge; i <= in.lastEdge; i++) {
             int[] edge = in.edges[i];
             addLine(edge[0], edge[1], vcount, icount); vcount += 4; icount += 6;
    -      }    
    +      }
         }
    -    
    +
         protected void checkForFlush(int vertCount) {
           if (tess.renderMode == IMMEDIATE && PGL.MAX_TESS_VERTICES < vertCount) {
             setLastTexIndex(tess.lastFillIndex);
             flush();
             setFirstTexIndex(0);
    -      }      
    -    }     
    -    
    +      }
    +    }
    +
         protected void checkForFlush(int vertCount, int indCount) {
    -      if (tess.renderMode == IMMEDIATE && (PGL.MAX_TESS_VERTICES < vertCount ||  
    +      if (tess.renderMode == IMMEDIATE && (PGL.MAX_TESS_VERTICES < vertCount ||
                                                PGL.MAX_TESS_INDICES  < indCount)) {
             setLastTexIndex(tess.lastFillIndex);
             flush();
             setFirstTexIndex(0);
    -      }      
    -    }    
    -        
    +      }
    +    }
    +
         protected boolean startEdge(int edge) {
           return edge % 2 != 0;
         }
    -    
    +
         protected boolean endEdge(int edge) {
           return 1 < edge;
    -    }    
    -    
    +    }
    +
         protected class TessellatorCallback implements PGL.TessellatorCallback {
           public boolean calcNormals;
           protected int tessFirst;
           protected int tessCount;
           protected int tessType;
    -      
    +
           public void begin(int type) {
             tessFirst = tess.fillVertexCount;
             tessCount = 0;
    -        
    +
             switch (type) {
    -        case PGL.GL_TRIANGLE_FAN: 
    +        case PGL.GL_TRIANGLE_FAN:
               tessType = TRIANGLE_FAN;
               break;
    -        case PGL.GL_TRIANGLE_STRIP: 
    +        case PGL.GL_TRIANGLE_STRIP:
               tessType = TRIANGLE_STRIP;
               break;
    -        case PGL.GL_TRIANGLES: 
    +        case PGL.GL_TRIANGLES:
               tessType = TRIANGLES;
               break;
             }
    @@ -8543,15 +8541,15 @@ public class PGraphicsOpenGL extends PGraphics {
     
           public void end() {
             switch (tessType) {
    -        case TRIANGLE_FAN: 
    +        case TRIANGLE_FAN:
               for (int i = 1; i < tessCount - 1; i++) {
                 addIndex(0);
                 addIndex(i);
                 addIndex(i + 1);
                 if (calcNormals) calcTriNormal(0, i, i + 1);
    -          }       
    +          }
               break;
    -        case TRIANGLE_STRIP: 
    +        case TRIANGLE_STRIP:
               for (int i = 1; i < tessCount - 1; i++) {
                 addIndex(i);
                 if (i % 2 == 0) {
    @@ -8562,12 +8560,12 @@ public class PGraphicsOpenGL extends PGraphics {
                   addIndex(i + 1);
                   addIndex(i - 1);
                   if (calcNormals) calcTriNormal(i - 1, i, i + 1);
    -            }            
    -          }        
    +            }
    +          }
               break;
    -        case TRIANGLES: 
    +        case TRIANGLES:
               for (int i = 0; i < tessCount; i++) {
    -            addIndex(i);          
    +            addIndex(i);
               }
               if (calcNormals) {
                 for (int tr = 0; tr < tessCount / 3; tr++) {
    @@ -8576,11 +8574,11 @@ public class PGraphicsOpenGL extends PGraphics {
                   int i2 = 3 * tr + 2;
                   calcTriNormal(i0, i1, i2);
                 }
    -          }            
    +          }
               break;
             }
           }
    -      
    +
           protected void addIndex(int tessIdx) {
             if (tess.fillVertexCount < PGL.MAX_TESS_INDICES) {
               tess.addFillIndex(tessFirst + tessIdx);
    @@ -8588,38 +8586,38 @@ public class PGraphicsOpenGL extends PGraphics {
               throw new RuntimeException("P3D: the tessellator is generating too many indices, reduce complexity of shape.");
             }
           }
    -      
    +
           protected void calcTriNormal(int tessIdx0, int tessIdx1, int tessIdx2) {
             tess.calcFillNormal(tessFirst + tessIdx0, tessFirst + tessIdx1, tessFirst + tessIdx2);
           }
    -      
    +
           public void vertex(Object data) {
             if (data instanceof double[]) {
               double[] d = (double[]) data;
               if (d.length < 25) {
                 throw new RuntimeException("TessCallback vertex() data is not of length 25");
               }
    -          
    +
               if (tess.fillVertexCount < PGL.MAX_TESS_VERTICES) {
     
                 // Combining individual rgba components back into int color values
    -            int fcolor = ((int) d[ 3] << 24) | ((int) d[ 4] << 16) | ((int) d[ 5] << 8) | (int) d[ 6];          
    -            int acolor = ((int) d[12] << 24) | ((int) d[13] << 16) | ((int) d[14] << 8) | (int) d[15];  
    +            int fcolor = ((int) d[ 3] << 24) | ((int) d[ 4] << 16) | ((int) d[ 5] << 8) | (int) d[ 6];
    +            int acolor = ((int) d[12] << 24) | ((int) d[13] << 16) | ((int) d[14] << 8) | (int) d[15];
                 int scolor = ((int) d[16] << 24) | ((int) d[17] << 16) | ((int) d[18] << 8) | (int) d[19];
                 int ecolor = ((int) d[20] << 24) | ((int) d[21] << 16) | ((int) d[22] << 8) | (int) d[23];
    -                    
    +
                 tess.addFillVertex((float) d[ 0],  (float) d[ 1], (float) d[ 2],
                                    fcolor,
                                    (float) d[ 7],  (float) d[ 8], (float) d[ 9],
                                    (float) d[10], (float) d[11],
    -                               acolor, scolor, ecolor, 
    +                               acolor, scolor, ecolor,
                                    (float) d[24]);
    -            
    -            tessCount++;            
    +
    +            tessCount++;
               } else {
                 throw new RuntimeException("P3D: the tessellator is generating too many vertices, reduce complexity of shape.");
    -          }          
    -          
    +          }
    +
             } else {
               throw new RuntimeException("TessCallback vertex() data not understood");
             }
    @@ -8629,7 +8627,7 @@ public class PGraphicsOpenGL extends PGraphics {
             String estring = pgl.gluErrorString(errnum);
             PGraphics.showWarning("Tessellation Error: " + estring);
           }
    -      
    +
           /**
            * Implementation of the GLU_TESS_COMBINE callback.
            * @param coords is the 3-vector of the new vertex
    @@ -8651,9 +8649,9 @@ public class PGraphicsOpenGL extends PGraphics {
             vertex[2] = coords[2];
     
             // Here w e need to use separate rgba components for correct interpolation...
    -        
    +
             // Calculating the rest of the vertex parameters (color,
    -        // normal, texcoords) as the linear combination of the 
    +        // normal, texcoords) as the linear combination of the
             // combined vertices.
             for (int i = 3; i < 25; i++) {
               vertex[i] = 0;
    @@ -8664,18 +8662,18 @@ public class PGraphicsOpenGL extends PGraphics {
                 }
               }
             }
    -        
    -        // Normalizing normal vector, since the weighted 
    -        // combination of normal vectors is not necessarily 
    +
    +        // Normalizing normal vector, since the weighted
    +        // combination of normal vectors is not necessarily
             // normal.
    -        double sum = vertex[7] * vertex[7] + 
    -                     vertex[8] * vertex[8] + 
    +        double sum = vertex[7] * vertex[7] +
    +                     vertex[8] * vertex[8] +
                          vertex[9] * vertex[9];
    -        double len = Math.sqrt(sum);      
    -        vertex[7] /= len; 
    +        double len = Math.sqrt(sum);
    +        vertex[7] /= len;
             vertex[8] /= len;
    -        vertex[9] /= len;  
    -        
    +        vertex[9] /= len;
    +
             outData[0] = vertex;
           }
         }