From 21d134a2338f9a36f3c9cf40787aaa09901010ec Mon Sep 17 00:00:00 2001
From: codeanticode
Date: Tue, 1 Feb 2011 07:51:22 +0000
Subject: [PATCH] Merged-in the changes in the core needed for the new opengl
renderer
---
core/src/processing/core/PApplet.java | 409 ++++++++++++++++--
core/src/processing/core/PConstants.java | 64 ++-
core/src/processing/core/PFont.java | 104 ++++-
core/src/processing/core/PGraphics.java | 271 +++++++++++-
core/src/processing/core/PGraphics3D.java | 145 +++++--
core/src/processing/core/PGraphicsJava2D.java | 5 +-
core/src/processing/core/PImage.java | 103 ++++-
core/src/processing/core/PMetadata.java | 41 ++
core/src/processing/core/PParameters.java | 11 +
core/src/processing/core/PShape.java | 84 +++-
10 files changed, 1110 insertions(+), 127 deletions(-)
create mode 100644 core/src/processing/core/PMetadata.java
create mode 100644 core/src/processing/core/PParameters.java
diff --git a/core/src/processing/core/PApplet.java b/core/src/processing/core/PApplet.java
index 9e9fd51fc..6f0afbc81 100644
--- a/core/src/processing/core/PApplet.java
+++ b/core/src/processing/core/PApplet.java
@@ -162,7 +162,6 @@ import processing.xml.XMLElement;
* do by hand w/ some Java code.
* @usage Web & Application
*/
-@SuppressWarnings("serial")
public class PApplet extends Applet
implements PConstants, Runnable,
MouseListener, MouseMotionListener, KeyListener, FocusListener
@@ -1380,6 +1379,14 @@ public class PApplet extends Applet
}
+ /**
+ * Creates a new PImage (the datatype for storing images). This provides a fresh buffer of pixels to play with. Set the size of the buffer with the width and height parameters. The format parameter defines how the pixels are stored. See the PImage reference for more information.
+ */
+ public PImage createImage(int wide, int high, int format) {
+ return createImage(wide, high, format, null);
+ }
+
+
/**
* Creates a new PImage (the datatype for storing images). This provides a fresh buffer of pixels to play with. Set the size of the buffer with the width and height parameters. The format parameter defines how the pixels are stored. See the PImage reference for more information.
*
Be sure to include all three parameters, specifying only the width and height (but no format) will produce a strange error.
@@ -1397,8 +1404,11 @@ public class PApplet extends Applet
* @see processing.core.PImage
* @see processing.core.PGraphics
*/
- public PImage createImage(int wide, int high, int format) {
+ public PImage createImage(int wide, int high, int format, PParameters params) {
PImage image = new PImage(wide, high, format);
+ if (params != null) {
+ image.setParams(g, params);
+ }
image.parent = this; // make save() work
return image;
}
@@ -3618,14 +3628,28 @@ public class PApplet extends Applet
* java.awt.Image to the PImage constructor that takes an AWT image.
*/
public PImage loadImage(String filename) {
- return loadImage(filename, null);
+ return loadImage(filename, null, null);
}
-
+
+ /**
+ * Load an image from the data folder or a local directory...
+ */
+ public PImage loadImage(String filename, String extension) {
+ return loadImage(filename, extension, null);
+ }
+
+
+ public PImage loadImage(String filename, PParameters params) {
+ return loadImage(filename, null, params);
+ }
+
+
/**
* Loads an image into a variable of type PImage. Four types of images ( .gif, .jpg, .tga, .png) images may be loaded. To load correctly, images must be located in the data directory of the current sketch. In most cases, load all images in setup() to preload them at the start of the program. Loading images inside draw() will reduce the speed of a program.
*
The filename parameter can also be a URL to a file found online. For security reasons, a Processing sketch found online can only download files from the same server from which it came. Getting around this restriction requires a signed applet.
*
The extension parameter is used to determine the image type in cases where the image filename does not end with a proper extension. Specify the extension as the second parameter to loadImage(), as shown in the third example on this page.
+ *
The params parameter is used to set an parameter object for the image, as might be used by specific renderers such as OPENGL2. Specify the extension as the third parameter to loadImage(), as shown in the fourth example on this page.
*
If an image is not loaded successfully, the null value is returned and an error message will be printed to the console. The error message does not halt the program, however the null value may cause a NullPointerException if your code does not check whether the value returned from loadImage() is null.
Depending on the type of error, a PImage object may still be returned, but the width and height of the image will be set to -1. This happens if bad image data is returned or cannot be decoded properly. Sometimes this happens with image URLs that produce a 403 error or that redirect to a password prompt, because loadImage() will attempt to interpret the HTML as image data.
*
* =advanced
@@ -3645,7 +3669,7 @@ public class PApplet extends Applet
* @see processing.core.PApplet#imageMode(int)
* @see processing.core.PApplet#background(float, float, float)
*/
- public PImage loadImage(String filename, String extension) {
+ public PImage loadImage(String filename, String extension, PParameters params) {
if (extension == null) {
String lower = filename.toLowerCase();
int dot = filename.lastIndexOf('.');
@@ -3667,7 +3691,11 @@ public class PApplet extends Applet
if (extension.equals("tga")) {
try {
- return loadImageTGA(filename);
+ PImage image = loadImageTGA(filename);
+ if (params != null) {
+ image.setParams(g, params);
+ }
+ return image;
} catch (IOException e) {
e.printStackTrace();
return null;
@@ -3676,7 +3704,11 @@ public class PApplet extends Applet
if (extension.equals("tif") || extension.equals("tiff")) {
byte bytes[] = loadBytes(filename);
- return (bytes == null) ? null : PImage.loadTIFF(bytes);
+ PImage image = (bytes == null) ? null : PImage.loadTIFF(bytes);
+ if (params != null) {
+ image.setParams(g, params);
+ }
+ return image;
}
// For jpeg, gif, and png, load them using createImage(),
@@ -3700,6 +3732,10 @@ public class PApplet extends Applet
if (extension.equals("gif") || extension.equals("png")) {
image.checkAlpha();
}
+
+ if (params != null) {
+ image.setParams(g, params);
+ }
return image;
}
}
@@ -3714,7 +3750,12 @@ public class PApplet extends Applet
if (loadImageFormats != null) {
for (int i = 0; i < loadImageFormats.length; i++) {
if (extension.equals(loadImageFormats[i])) {
- return loadImageIO(filename);
+ PImage image;
+ image = loadImageIO(filename);
+ if (params != null) {
+ image.setParams(g, params);
+ }
+ return image;
}
}
}
@@ -3725,10 +3766,15 @@ public class PApplet extends Applet
}
public PImage requestImage(String filename) {
- return requestImage(filename, null);
+ return requestImage(filename, null, null);
}
+
+ public PImage requestImage(String filename, String extension) {
+ return requestImage(filename, extension, null);
+ }
+
/**
* This function load images on a separate thread so that your sketch does not freeze while images load during setup(). While the image is loading, its width and height will be 0. If an error occurs while loading the image, its width and height will be set to -1. You'll know when the image has loaded properly because its width and height will be greater than 0. Asynchronous image loading (particularly when downloading from a server) can dramatically improve performance.
* The extension parameter is used to determine the image type in cases where the image filename does not end with a proper extension. Specify the extension as the second parameter to requestImage().
@@ -3740,8 +3786,8 @@ public class PApplet extends Applet
* @see processing.core.PApplet#loadImage(String, String)
* @see processing.core.PImage
*/
- public PImage requestImage(String filename, String extension) {
- PImage vessel = createImage(0, 0, ARGB);
+ public PImage requestImage(String filename, String extension, PParameters params) {
+ PImage vessel = createImage(0, 0, ARGB, params);
AsyncImageLoader ail =
new AsyncImageLoader(filename, extension, vessel);
ail.start();
@@ -3765,7 +3811,7 @@ public class PApplet extends Applet
String filename;
String extension;
PImage vessel;
-
+
public AsyncImageLoader(String filename, String extension, PImage vessel) {
this.filename = filename;
this.extension = extension;
@@ -4055,7 +4101,14 @@ public class PApplet extends Applet
// SHAPE I/O
-
+ protected String[] loadShapeFormats;
+
+
+ public PShape loadShape(String filename) {
+ return loadShape(filename, null);
+ }
+
+
/**
* Loads vector shapes into a variable of type PShape. Currently, only SVG files may be loaded.
* To load correctly, the file must be located in the data directory of the current sketch.
@@ -4073,11 +4126,27 @@ public class PApplet extends Applet
* @see PApplet#shape(PShape)
* @see PApplet#shapeMode(int)
*/
- public PShape loadShape(String filename) {
- if (filename.toLowerCase().endsWith(".svg")) {
+ public PShape loadShape(String filename, PParameters params) {
+ String extension;
+
+ String lower = filename.toLowerCase();
+ int dot = filename.lastIndexOf('.');
+ if (dot == -1) {
+ extension = "unknown"; // no extension found
+ }
+ extension = lower.substring(dot + 1);
+
+ // check for, and strip any parameters on the url, i.e.
+ // filename.jpg?blah=blah&something=that
+ int question = extension.indexOf('?');
+ if (question != -1) {
+ extension = extension.substring(0, question);
+ }
+
+ if (extension.equals("svg")) {
return new PShapeSVG(this, filename);
- } else if (filename.toLowerCase().endsWith(".svgz")) {
+ } else if (extension.equals("svgz")) {
try {
InputStream input = new GZIPInputStream(createInput(filename));
XMLElement xml = new XMLElement(createReader(input));
@@ -4085,12 +4154,33 @@ public class PApplet extends Applet
} catch (IOException e) {
e.printStackTrace();
}
+ } else {
+ // Loading the formats supported by the renderer.
+
+ loadShapeFormats = g.getSupportedShapeFormats();
+
+ if (loadShapeFormats != null) {
+ for (int i = 0; i < loadShapeFormats.length; i++) {
+ if (extension.equals(loadShapeFormats[i])) {
+ return g.loadShape(filename, params);
+ }
+ }
+ }
+
}
+
return null;
}
-
+ /**
+ * Creates an empty shape, with the specified size and parameters.
+ */
+ public PShape createShape(int size, PParameters params) {
+ return g.createShape(size, params);
+ }
+
+
//////////////////////////////////////////////////////////////
// FONT I/O
@@ -7534,6 +7624,9 @@ public class PApplet extends Applet
recorder.dispose();
recorder = null;
}
+ if (g.isRecording()) {
+ g.endRecord();
+ }
}
@@ -7576,8 +7669,16 @@ public class PApplet extends Applet
}
+ /**
+ * Starts shape recording and returns the PShape object that will
+ * contain the geometry.
+ */
+ public PShape beginRecord() {
+ return g.beginRecord();
+ }
+
//////////////////////////////////////////////////////////////
-
+
/**
* Loads the pixel data for the display window into the pixels[] array. This function must always be called before reading from or writing to pixels[].
@@ -7656,6 +7757,11 @@ public class PApplet extends Applet
}
+ public boolean hintEnabled(int which) {
+ return g.hintEnabled(which);
+ }
+
+
/**
* Start a new shape of type POLYGON
*/
@@ -7703,6 +7809,15 @@ public class PApplet extends Applet
}
+ /**
+ * Sets the automatic normal calculation mode.
+ */
+ public void autoNormal(boolean auto) {
+ if (recorder != null) recorder.autoNormal(auto);
+ g.autoNormal(auto);
+ }
+
+
/**
* Sets the current normal vector. Only applies with 3D rendering
* and inside a beginShape/endShape block.
@@ -7746,6 +7861,17 @@ public class PApplet extends Applet
}
+ /**
+ * Removes texture image for current shape.
+ * Needs to be called between @see beginShape and @see endShape
+ *
+ */
+ public void noTexture() {
+ if (recorder != null) recorder.noTexture();
+ g.noTexture();
+ }
+
+
public void vertex(float x, float y) {
if (recorder != null) recorder.vertex(x, y);
g.vertex(x, y);
@@ -8733,6 +8859,18 @@ public class PApplet extends Applet
}
+ public void beginText() {
+ if (recorder != null) recorder.beginText();
+ g.beginText();
+ }
+
+
+ public void endText() {
+ if (recorder != null) recorder.endText();
+ g.endText();
+ }
+
+
public float textWidth(char c) {
return g.textWidth(c);
}
@@ -9136,6 +9274,18 @@ public class PApplet extends Applet
}
+ public void beginProjection() {
+ if (recorder != null) recorder.beginProjection();
+ g.beginProjection();
+ }
+
+
+ public void endProjection() {
+ if (recorder != null) recorder.endProjection();
+ g.endProjection();
+ }
+
+
public void beginCamera() {
if (recorder != null) recorder.beginCamera();
g.beginCamera();
@@ -10002,6 +10152,53 @@ public class PApplet extends Applet
}
+ /**
+ * Display a warning that the specified method is only available with 3D.
+ * @param method The method name (no parentheses)
+ */
+ static public void showDepthWarning(String method) {
+ PGraphics.showDepthWarning(method);
+ }
+
+
+ /**
+ * Display a warning that the specified method that takes x, y, z parameters
+ * can only be used with x and y parameters in this renderer.
+ * @param method The method name (no parentheses)
+ */
+ static public void showDepthWarningXYZ(String method) {
+ PGraphics.showDepthWarningXYZ(method);
+ }
+
+
+ /**
+ * Display a warning that the specified method is simply unavailable.
+ */
+ static public void showMethodWarning(String method) {
+ PGraphics.showMethodWarning(method);
+ }
+
+
+ /**
+ * Error that a particular variation of a method is unavailable (even though
+ * other variations are). For instance, if vertex(x, y, u, v) is not
+ * available, but vertex(x, y) is just fine.
+ */
+ static public void showVariationWarning(String str) {
+ PGraphics.showVariationWarning(str);
+ }
+
+
+ /**
+ * Display a warning that the specified method is not implemented, meaning
+ * that it could be either a completely missing function, although other
+ * variations of it may still work properly.
+ */
+ static public void showMissingWarning(String method) {
+ PGraphics.showMissingWarning(method);
+ }
+
+
/**
* Return true if this renderer should be drawn to the screen. Defaults to
* returning true, since nearly all renderers are on-screen beasts. But can
@@ -10015,16 +10212,138 @@ public class PApplet extends Applet
}
+ public void blend(int mode) {
+ if (recorder != null) recorder.blend(mode);
+ g.blend(mode);
+ }
+
+
+ public void noBlend() {
+ if (recorder != null) recorder.noBlend();
+ g.noBlend();
+ }
+
+
+ public void textureBlend(int mode) {
+ if (recorder != null) recorder.textureBlend(mode);
+ g.textureBlend(mode);
+ }
+
+
+ public void noTextureBlend() {
+ if (recorder != null) recorder.noTextureBlend();
+ g.noTextureBlend();
+ }
+
+
+ public void mergeRecord() {
+ if (recorder != null) recorder.mergeRecord();
+ g.mergeRecord();
+ }
+
+
+ public void noMergeRecord() {
+ if (recorder != null) recorder.noMergeRecord();
+ g.noMergeRecord();
+ }
+
+
+ public void shapeName(String name) {
+ if (recorder != null) recorder.shapeName(name);
+ g.shapeName(name);
+ }
+
+
+ public void texture(PImage image0, PImage image1) {
+ if (recorder != null) recorder.texture(image0, image1);
+ g.texture(image0, image1);
+ }
+
+
+ public void texture(PImage image0, PImage image1, PImage image2) {
+ if (recorder != null) recorder.texture(image0, image1, image2);
+ g.texture(image0, image1, image2);
+ }
+
+
+ public void texture(PImage image0, PImage image1, PImage image2, PImage image3) {
+ if (recorder != null) recorder.texture(image0, image1, image2, image3);
+ g.texture(image0, image1, image2, image3);
+ }
+
+
+ public void texture(PImage[] images) {
+ if (recorder != null) recorder.texture(images);
+ g.texture(images);
+ }
+
+
+ public void vertex(float x, float y, float u0, float v0, float u1, float v1) {
+ if (recorder != null) recorder.vertex(x, y, u0, v0, u1, v1);
+ g.vertex(x, y, u0, v0, u1, v1);
+ }
+
+
+ public void vertex(float x, float y, float u0, float v0, float u1, float v1, float u2, float v2) {
+ if (recorder != null) recorder.vertex(x, y, u0, v0, u1, v1, u2, v2);
+ g.vertex(x, y, u0, v0, u1, v1, u2, v2);
+ }
+
+
+ public void vertex(float x, float y, float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3) {
+ if (recorder != null) recorder.vertex(x, y, u0, v0, u1, v1, u2, v2, u3, v3);
+ g.vertex(x, y, u0, v0, u1, v1, u2, v2, u3, v3);
+ }
+
+
+ public void vertex(float x, float y, float[] u, float[] v) {
+ if (recorder != null) recorder.vertex(x, y, u, v);
+ g.vertex(x, y, u, v);
+ }
+
+
+ public void vertex(float x, float y, float z, float u0, float v0, float u1, float v1) {
+ if (recorder != null) recorder.vertex(x, y, z, u0, v0, u1, v1);
+ g.vertex(x, y, z, u0, v0, u1, v1);
+ }
+
+
+ public void vertex(float x, float y, float z, float u0, float v0, float u1, float v1, float u2, float v2) {
+ if (recorder != null) recorder.vertex(x, y, z, u0, v0, u1, v1, u2, v2);
+ g.vertex(x, y, z, u0, v0, u1, v1, u2, v2);
+ }
+
+
+ public void vertex(float x, float y, float z, float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3) {
+ if (recorder != null) recorder.vertex(x, y, z, u0, v0, u1, v1, u2, v2, u3, v3);
+ g.vertex(x, y, z, u0, v0, u1, v1, u2, v2, u3, v3);
+ }
+
+
+ public void vertex(float x, float y, float z, float[] u, float[] v) {
+ if (recorder != null) recorder.vertex(x, y, z, u, v);
+ g.vertex(x, y, z, u, v);
+ }
+
+
+ public void delete() {
+ if (recorder != null) recorder.delete();
+ g.delete();
+ }
+
+
/**
* Store data of some kind for a renderer that requires extra metadata of
* some kind. Usually this is a renderer-specific representation of the
* image data, for instance a BufferedImage with tint() settings applied for
* 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
*/
- public void setCache(Object parent, Object storage) {
- if (recorder != null) recorder.setCache(parent, storage);
- g.setCache(parent, storage);
+ public void setCache(PGraphics renderer, PMetadata storage) {
+ if (recorder != null) recorder.setCache(renderer, storage);
+ g.setCache(renderer, storage);
}
@@ -10033,21 +10352,53 @@ public class PApplet extends Applet
* will cache data in different formats, it's necessary to store cache data
* keyed by the renderer object. Otherwise, attempting to draw the same
* image to both a PGraphicsJava2D and a PGraphicsOpenGL will cause errors.
- * @param parent The PGraphics object (or any object, really) associated
- * @return data stored for the specified parent
+ * @param renderer The PGraphics renderer associated to the image
+ * @return metadata stored for the specified renderer
*/
- public Object getCache(Object parent) {
- return g.getCache(parent);
+ public PMetadata getCache(PGraphics renderer) {
+ return g.getCache(renderer);
}
/**
* Remove information associated with this renderer from the cache, if any.
- * @param parent The PGraphics object whose cache data should be removed
+ * @param renderer The PGraphics renderer whose cache data should be removed
*/
- public void removeCache(Object parent) {
- if (recorder != null) recorder.removeCache(parent);
- g.removeCache(parent);
+ public void removeCache(PGraphics renderer) {
+ if (recorder != null) recorder.removeCache(renderer);
+ g.removeCache(renderer);
+ }
+
+
+ /**
+ * 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
+ */
+ public void setParams(PGraphics renderer, PParameters params) {
+ if (recorder != null) recorder.setParams(renderer, params);
+ g.setParams(renderer, params);
+ }
+
+
+ /**
+ * Get the parameters for the specified renderer.
+ * @param renderer The PGraphics renderer associated to the image
+ * @return parameters stored for the specified renderer
+ */
+ public PParameters getParams(PGraphics renderer) {
+ return g.getParams(renderer);
+ }
+
+
+ /**
+ * Remove information associated with this renderer from the cache, if any.
+ * @param renderer The PGraphics renderer whose parameters should be removed
+ */
+ public void removeParams(PGraphics renderer) {
+ if (recorder != null) recorder.removeParams(renderer);
+ g.removeParams(renderer);
}
diff --git a/core/src/processing/core/PConstants.java b/core/src/processing/core/PConstants.java
index 410a949b5..05a272366 100644
--- a/core/src/processing/core/PConstants.java
+++ b/core/src/processing/core/PConstants.java
@@ -111,17 +111,20 @@ public interface PConstants {
// has this vertex been lit yet
static public final int BEEN_LIT = 35;
- static public final int VERTEX_FIELD_COUNT = 36;
-
+ // has this vertex been assigned a normal yet
+ static public final int HAS_NORMAL = 36;
+
+ static public final int VERTEX_FIELD_COUNT = 37;
// renderers known to processing.core
- static final String P2D = "processing.core.PGraphics2D";
- static final String P3D = "processing.core.PGraphics3D";
- static final String JAVA2D = "processing.core.PGraphicsJava2D";
- static final String OPENGL = "processing.opengl.PGraphicsOpenGL";
- static final String PDF = "processing.pdf.PGraphicsPDF";
- static final String DXF = "processing.dxf.RawDXF";
+ static final String P2D = "processing.core.PGraphics2D";
+ static final String P3D = "processing.core.PGraphics3D";
+ static final String JAVA2D = "processing.core.PGraphicsJava2D";
+ static final String OPENGL = "processing.opengl.PGraphicsOpenGL";
+ static final String OPENGL2 = "processing.opengl2.PGraphicsOpenGL2";
+ static final String PDF = "processing.pdf.PGraphicsPDF";
+ static final String DXF = "processing.dxf.RawDXF";
// platform IDs for PApplet.platform
@@ -326,7 +329,11 @@ public interface PConstants {
static final int SPHERE = 40;
static final int BOX = 41;
+ static public final int LINE_STRIP = 50;
+ static public final int LINE_LOOP = 51;
+ static public final int POINT_SPRITES = 52;
+
// shape closing modes
static final int OPEN = 1;
@@ -403,7 +410,37 @@ public interface PConstants {
// text alignment modes
// are inherited from LEFT, CENTER, RIGHT
+ // PTexture
+
+ /** This constant identifies the texture target GL_TEXTURE_2D, that is, textures with normalized coordinates */
+ public static final int TEXTURE2D = 0;
+
+ /** This constant identifies the nearest texture filter (point sampling) */
+ //public static final int POINT = 2; // shared with shape feature
+ /** This constant identifies the linear texture filter, usually called bilinear sampling */
+ public static final int BILINEAR = 3;
+ /** This constant identifies the linear/linear function to build mipmaps */
+ public static final int TRILINEAR = 4;
+
+ /** This constant identifies the clamp-to-edge wrapping mode */
+ public static final int CLAMP = 0;
+ /** This constant identifies the repeat wrapping mode */
+ public static final int REPEAT = 1;
+ /** Point sprite distance attenuation functions */
+ public static final int LINEAR = 0;
+ public static final int QUADRATIC = 1;
+
+ // PShape3D
+
+ /** Static usage mode for PShape3D (vertices won't be updated after creation). */
+ public static final int STATIC = 0;
+ /** Dynamic usage mode for PShape3D (vertices will be updated after creation). */
+ public static final int DYNAMIC = 1;
+ /** Dynamic usage mode for PShape3D (vertices will be updated at every frame). */
+ public static final int STREAM = 2;
+
+
// stroke modes
static final int SQUARE = 1 << 0; // called 'butt' in the svg spec
@@ -485,9 +522,18 @@ public interface PConstants {
static final int ENABLE_ACCURATE_TEXTURES = 7;
static final int DISABLE_ACCURATE_TEXTURES = -7;
+ static final int DISABLE_DEPTH_MASK = 8;
+ static final int ENABLE_DEPTH_MASK = -8;
+
static final int HINT_COUNT = 10;
-
+ // Rendering pipeline modes
+
+ static final int FIXED = 0;
+ static final int PROG_GL2 = 1;
+ static final int PROG_GL3 = 2;
+ static final int PROG_GL4 = 3;
+
// error messages
static final String ERROR_BACKGROUND_IMAGE_SIZE =
diff --git a/core/src/processing/core/PFont.java b/core/src/processing/core/PFont.java
index aaf4f7cd4..fcd4bc310 100644
--- a/core/src/processing/core/PFont.java
+++ b/core/src/processing/core/PFont.java
@@ -28,6 +28,7 @@ import java.awt.image.*;
import java.io.*;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.Set;
/**
@@ -154,7 +155,11 @@ public class PFont implements PConstants {
protected FontMetrics lazyMetrics;
protected int[] lazySamples;
+
+ /** for subclasses that need to store metadata about the font */
+ protected HashMap cacheMap;
+
public PFont() { } // for subclasses
@@ -239,7 +244,8 @@ public class PFont implements PConstants {
if (glyf.value < 128) {
ascii[glyf.value] = glyphCount;
}
- glyphs[glyphCount++] = glyf;
+ glyf.index = glyphCount;
+ glyphs[glyphCount++] = glyf;
}
}
@@ -340,6 +346,7 @@ public class PFont implements PConstants {
if (glyph.value < 128) {
ascii[glyph.value] = i;
}
+ glyph.index = i;
glyphs[i] = glyph;
}
@@ -366,6 +373,19 @@ public class PFont implements PConstants {
findFont();
}
+
+ void delete() {
+ if (cacheMap != null) {
+ Set keySet = cacheMap.keySet();
+ if (!keySet.isEmpty()) {
+ Object[] keys = keySet.toArray();
+ for (int i = 0; i < keys.length; i++) {
+ PMetadata data = getCache((PGraphics)keys[i]);
+ data.delete();
+ }
+ }
+ }
+ }
/**
* Write this PFont to an OutputStream.
@@ -420,6 +440,7 @@ public class PFont implements PConstants {
glyphs = (Glyph[]) PApplet.expand(glyphs);
}
if (glyphCount == 0) {
+ glyph.index = 0;
glyphs[glyphCount] = glyph;
if (glyph.value < 128) {
ascii[glyph.value] = 0;
@@ -440,6 +461,7 @@ public class PFont implements PConstants {
ascii[glyphs[j].value] = j;
}
}
+ glyph.index = i;
glyphs[i] = glyph;
// cache locations of the ascii charset
if (c < 128) ascii[c] = i;
@@ -481,6 +503,14 @@ public class PFont implements PConstants {
return font;
}
+
+ /**
+ * Return size of this font.
+ */
+ public int getSize() {
+ return size;
+ }
+
public boolean isStream() {
return stream;
@@ -625,6 +655,59 @@ public class PFont implements PConstants {
}
+ //////////////////////////////////////////////////////////////
+
+ // METADATA REQUIRED BY THE RENDERERS
+
+
+ /**
+ * Store data of some kind for a renderer that requires extra metadata of
+ * some kind. Usually this is a renderer-specific representation of the
+ * font data, for instance a custom OpenGL texture for PGraphicsOpenGL2.
+ * @param renderer The PGraphics renderer associated to the font
+ * @param storage The metadata required by the renderer
+ */
+ public void setCache(PGraphics renderer, PMetadata storage) {
+ if (cacheMap == null) cacheMap = new HashMap();
+ cacheMap.put(renderer, storage);
+ }
+
+
+ /**
+ * Get cache storage data for the specified renderer. Because each renderer
+ * will cache data in different formats, it's necessary to store cache data
+ * keyed by the renderer object. Otherwise, attempting to draw the same
+ * image to both a PGraphicsJava2D and a PGraphicsOpenGL2 will cause errors.
+ * @param renderer The PGraphics renderer associated to the font
+ * @return metadata stored for the specified renderer
+ */
+ public PMetadata getCache(PGraphics renderer) {
+ if (cacheMap == null) return null;
+ return cacheMap.get(renderer);
+ }
+
+
+ /**
+ * Remove information associated with this renderer from the cache, if any.
+ * @param parent The PGraphics renderer whose cache data should be removed
+ */
+ public void removeCache(PGraphics renderer) {
+ if (cacheMap != null) {
+ cacheMap.remove(renderer);
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////
+
+ public int getGlyphCount() {
+ return glyphCount;
+ }
+
+ public Glyph getGlyph(int i) {
+ return glyphs[i];
+ }
+
//////////////////////////////////////////////////////////////
@@ -757,21 +840,24 @@ public class PFont implements PConstants {
* A single character, and its visage.
*/
public class Glyph {
- PImage image;
- int value;
- int height;
- int width;
- int setWidth;
- int topExtent;
- int leftExtent;
-
+ public PImage image;
+ public int value;
+ public int height;
+ public int width;
+ public int index;
+ public int setWidth;
+ public int topExtent;
+ public int leftExtent;
+
protected Glyph() {
+ index = -1;
// used when reading from a stream or for subclasses
}
protected Glyph(DataInputStream is) throws IOException {
+ index = -1;
readHeader(is);
}
diff --git a/core/src/processing/core/PGraphics.java b/core/src/processing/core/PGraphics.java
index 82a98aee7..9d7e7c3b8 100644
--- a/core/src/processing/core/PGraphics.java
+++ b/core/src/processing/core/PGraphics.java
@@ -406,7 +406,7 @@ public class PGraphics extends PImage implements PConstants {
protected int shape;
// vertices
- static final int DEFAULT_VERTICES = 512;
+ public static final int DEFAULT_VERTICES = 512;
protected float vertices[][] =
new float[DEFAULT_VERTICES][VERTEX_FIELD_COUNT];
protected int vertexCount; // total number of vertices
@@ -509,6 +509,8 @@ public class PGraphics extends PImage implements PConstants {
/// Keep track of how many calls to normal, to determine the mode.
//protected int normalCount;
+ protected boolean autoNormal;
+
/** Current normal vector. */
public float normalX, normalY, normalZ;
@@ -712,6 +714,8 @@ public class PGraphics extends PImage implements PConstants {
rectMode(CORNER);
ellipseMode(DIAMETER);
+
+ autoNormal = true;
// no current font
textFont = null;
@@ -836,6 +840,13 @@ public class PGraphics extends PImage implements PConstants {
}
}
+ public boolean hintEnabled(int which) {
+ if (which > 0) {
+ return hints[which];
+ } else {
+ return hints[-which];
+ }
+ }
//////////////////////////////////////////////////////////////
@@ -885,6 +896,14 @@ public class PGraphics extends PImage implements PConstants {
this.edge = edge;
}
+
+ /**
+ * Sets the automatic normal calculation mode.
+ */
+ public void autoNormal(boolean auto) {
+ this.autoNormal = auto;
+ }
+
/**
* Sets the current normal vector. Only applies with 3D rendering
@@ -946,7 +965,17 @@ public class PGraphics extends PImage implements PConstants {
textureImage = image;
}
+
+ /**
+ * Removes texture image for current shape.
+ * Needs to be called between @see beginShape and @see endShape
+ *
+ */
+ public void noTexture() {
+ textureImage = null;
+ }
+
protected void vertexCheck() {
if (vertexCount == vertices.length) {
float temp[][] = new float[vertexCount << 1][VERTEX_FIELD_COUNT];
@@ -973,7 +1002,8 @@ public class PGraphics extends PImage implements PConstants {
// vertex[B] = fillB;
// vertex[A] = fillA;
// }
- if (fill || textureImage != null) {
+ boolean textured = textureImage != null;
+ if (fill || textured) {
if (textureImage == null) {
vertex[R] = fillR;
vertex[G] = fillG;
@@ -1002,11 +1032,29 @@ public class PGraphics extends PImage implements PConstants {
vertex[SW] = strokeWeight;
}
- if (textureImage != null) {
+ if (textured) {
vertex[U] = textureU;
vertex[V] = textureV;
}
+ if (autoNormal) {
+ float norm2 = normalX * normalX + normalY * normalY + normalZ * normalZ;
+ if (norm2 < EPSILON) {
+ vertex[HAS_NORMAL] = 0;
+ } else {
+ if (Math.abs(norm2 - 1) > EPSILON) {
+ // The normal vector is not normalized.
+ float norm = PApplet.sqrt(norm2);
+ normalX /= norm;
+ normalY /= norm;
+ normalZ /= norm;
+ }
+ vertex[HAS_NORMAL] = 1;
+ }
+ } else {
+ vertex[HAS_NORMAL] = 1;
+ }
+
vertexCount++;
}
@@ -1043,7 +1091,8 @@ public class PGraphics extends PImage implements PConstants {
vertex[EDGE] = edge ? 1 : 0;
- if (fill || textureImage != null) {
+ boolean textured = textureImage != null;
+ if (fill || textured) {
if (textureImage == null) {
vertex[R] = fillR;
vertex[G] = fillG;
@@ -1087,10 +1136,28 @@ public class PGraphics extends PImage implements PConstants {
vertex[SW] = strokeWeight;
}
- if (textureImage != null) {
+ if (textured) {
vertex[U] = textureU;
vertex[V] = textureV;
}
+
+ if (autoNormal) {
+ float norm2 = normalX * normalX + normalY * normalY + normalZ * normalZ;
+ if (norm2 < EPSILON) {
+ vertex[HAS_NORMAL] = 0;
+ } else {
+ if (Math.abs(norm2 - 1) > EPSILON) {
+ // The normal vector is not normalized.
+ float norm = PApplet.sqrt(norm2);
+ normalX /= norm;
+ normalY /= norm;
+ normalZ /= norm;
+ }
+ vertex[HAS_NORMAL] = 1;
+ }
+ } else {
+ vertex[HAS_NORMAL] = 1;
+ }
vertex[NX] = normalX;
vertex[NY] = normalY;
@@ -2110,22 +2177,20 @@ public class PGraphics extends PImage implements PConstants {
sphereDetail(30);
}
- pushMatrix();
- scale(r);
edge(false);
// 1st ring from south pole
beginShape(TRIANGLE_STRIP);
for (int i = 0; i < sphereDetailU; i++) {
normal(0, -1, 0);
- vertex(0, -1, 0);
+ vertex(0, -r, 0);
normal(sphereX[i], sphereY[i], sphereZ[i]);
- vertex(sphereX[i], sphereY[i], sphereZ[i]);
+ vertex(r * sphereX[i], r *sphereY[i], r * sphereZ[i]);
}
//normal(0, -1, 0);
vertex(0, -1, 0);
normal(sphereX[0], sphereY[0], sphereZ[0]);
- vertex(sphereX[0], sphereY[0], sphereZ[0]);
+ vertex(r * sphereX[0], r * sphereY[0], r * sphereZ[0]);
endShape();
int v1,v11,v2;
@@ -2139,17 +2204,17 @@ public class PGraphics extends PImage implements PConstants {
beginShape(TRIANGLE_STRIP);
for (int j = 0; j < sphereDetailU; j++) {
normal(sphereX[v1], sphereY[v1], sphereZ[v1]);
- vertex(sphereX[v1], sphereY[v1], sphereZ[v1++]);
+ vertex(r * sphereX[v1], r * sphereY[v1], r * sphereZ[v1++]);
normal(sphereX[v2], sphereY[v2], sphereZ[v2]);
- vertex(sphereX[v2], sphereY[v2], sphereZ[v2++]);
+ vertex(r * sphereX[v2], r * sphereY[v2], r * sphereZ[v2++]);
}
// close each ring
v1 = v11;
v2 = voff;
normal(sphereX[v1], sphereY[v1], sphereZ[v1]);
- vertex(sphereX[v1], sphereY[v1], sphereZ[v1]);
+ vertex(r * sphereX[v1], r * sphereY[v1], sphereZ[v1]);
normal(sphereX[v2], sphereY[v2], sphereZ[v2]);
- vertex(sphereX[v2], sphereY[v2], sphereZ[v2]);
+ vertex(r * sphereX[v2], r * sphereY[v2], r * sphereZ[v2]);
endShape();
}
@@ -2158,18 +2223,17 @@ public class PGraphics extends PImage implements PConstants {
for (int i = 0; i < sphereDetailU; i++) {
v2 = voff + i;
normal(sphereX[v2], sphereY[v2], sphereZ[v2]);
- vertex(sphereX[v2], sphereY[v2], sphereZ[v2]);
+ vertex(r * sphereX[v2], r * sphereY[v2], r * sphereZ[v2]);
normal(0, 1, 0);
- vertex(0, 1, 0);
+ vertex(0, r, 0);
}
normal(sphereX[voff], sphereY[voff], sphereZ[voff]);
- vertex(sphereX[voff], sphereY[voff], sphereZ[voff]);
+ vertex(r * sphereX[voff], r * sphereY[voff], r * sphereZ[voff]);
normal(0, 1, 0);
- vertex(0, 1, 0);
+ vertex(0, r, 0);
endShape();
edge(true);
- popMatrix();
}
@@ -3151,7 +3215,14 @@ public class PGraphics extends PImage implements PConstants {
textLeading = (textAscent() + textDescent()) * 1.275f;
}
+ public void beginText() {
+ showMissingWarning("beginText");
+ }
+ public void endText() {
+ showMissingWarning("endText");
+ }
+
// ........................................................
@@ -4046,6 +4117,19 @@ public class PGraphics extends PImage implements PConstants {
}
+ //////////////////////////////////////////////////////////////
+
+ // PROJECTION
+
+ public void beginProjection() {
+ showMethodWarning("beginProjection");
+ }
+
+
+ public void endProjection() {
+ showMethodWarning("endProjection");
+ }
+
//////////////////////////////////////////////////////////////
@@ -5750,7 +5834,7 @@ public class PGraphics extends PImage implements PConstants {
* Display a warning that the specified method is only available with 3D.
* @param method The method name (no parentheses)
*/
- static protected void showDepthWarning(String method) {
+ static public void showDepthWarning(String method) {
showWarning(method + "() can only be used with a renderer that " +
"supports 3D, such as P3D or OPENGL.");
}
@@ -5761,7 +5845,7 @@ public class PGraphics extends PImage implements PConstants {
* can only be used with x and y parameters in this renderer.
* @param method The method name (no parentheses)
*/
- static protected void showDepthWarningXYZ(String method) {
+ static public void showDepthWarningXYZ(String method) {
showWarning(method + "() with x, y, and z coordinates " +
"can only be used with a renderer that " +
"supports 3D, such as P3D or OPENGL. " +
@@ -5772,7 +5856,7 @@ public class PGraphics extends PImage implements PConstants {
/**
* Display a warning that the specified method is simply unavailable.
*/
- static protected void showMethodWarning(String method) {
+ static public void showMethodWarning(String method) {
showWarning(method + "() is not available with this renderer.");
}
@@ -5782,7 +5866,7 @@ public class PGraphics extends PImage implements PConstants {
* other variations are). For instance, if vertex(x, y, u, v) is not
* available, but vertex(x, y) is just fine.
*/
- static protected void showVariationWarning(String str) {
+ static public void showVariationWarning(String str) {
showWarning(str + " is not available with this renderer.");
}
@@ -5792,7 +5876,7 @@ public class PGraphics extends PImage implements PConstants {
* that it could be either a completely missing function, although other
* variations of it may still work properly.
*/
- static protected void showMissingWarning(String method) {
+ static public void showMissingWarning(String method) {
showWarning(method + "(), or this particular variation of it, " +
"is not available with this renderer.");
}
@@ -5863,4 +5947,143 @@ public class PGraphics extends PImage implements PConstants {
public boolean is3D() {
return false;
}
+
+ //////////////////////////////////////////////////////////////
+
+ // New API:
+
+ protected String[] getSupportedShapeFormats() {
+ return null;
+ }
+
+ protected PShape loadShape(String filename, PParameters params) {
+ return null;
+ }
+
+ protected PShape createShape(int size, PParameters params) {
+ return null;
+ }
+
+ public void blend(int mode) {
+ if (!is3D()) {
+ showMissingWarning("blend");
+ }
+ }
+
+
+ public void noBlend() {
+ if (!is3D()) {
+ showMissingWarning("noBlend");
+ }
+ }
+
+
+ public void textureBlend(int mode) {
+ if (!is3D()) {
+ showMissingWarning("blend");
+ }
+ }
+
+
+ public void noTextureBlend() {
+ if (!is3D()) {
+ showMissingWarning("noBlend");
+ }
+ }
+
+ public PShape beginRecord() { // ignore
+ if (!is3D()) {
+ showMissingWarning("beginRecord");
+ }
+ return null;
+ }
+
+ public void endRecord() { // ignore
+ if (!is3D()) {
+ showMissingWarning("endShapeRecord");
+ }
+ }
+
+ public boolean isRecording() { // ignore
+ return false;
+ }
+
+ public void mergeRecord() {
+ if (!is3D()) {
+ showMissingWarning("mergeRecord");
+ }
+ }
+
+
+ public void noMergeRecord() {
+ if (!is3D()) {
+ showMissingWarning("noMergeRecord");
+ }
+ }
+
+
+ public void shapeName(String name) {
+ if (!is3D()) {
+ showMissingWarning("shapeName");
+ }
+ }
+
+
+ public void texture(PImage image0, PImage image1) {
+ showMissingWarning("multitexturing requires OPENGL2");
+ }
+
+
+ public void texture(PImage image0, PImage image1, PImage image2) {
+ showMissingWarning("multitexturing requires OPENGL2");
+ }
+
+
+ public void texture(PImage image0, PImage image1, PImage image2, PImage image3) {
+ showMissingWarning("multitexturing requires OPENGL2");
+ }
+
+
+ public void texture(PImage[] images) {
+ showMissingWarning("multitexturing requires OPENGL2");
+ }
+
+
+ public void vertex(float x, float y, float u0, float v0, float u1, float v1) {
+ showMissingWarning("multitextured vertex requires OPENGL2");
+ }
+
+
+ public void vertex(float x, float y, float u0, float v0, float u1, float v1, float u2, float v2) {
+ showMissingWarning("multitextured vertex requires OPENGL2");
+ }
+
+
+ public void vertex(float x, float y, float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3) {
+ showMissingWarning("multitextured vertex requires OPENGL2");
+ }
+
+ public void vertex(float x, float y, float[] u, float[] v) {
+ showMissingWarning("multitextured vertex requires OPENGL2");
+ }
+
+
+ public void vertex(float x, float y, float z, float u0, float v0, float u1, float v1) {
+ showMissingWarning("multitextured vertex requires OPENGL2");
+ }
+
+
+ public void vertex(float x, float y, float z, float u0, float v0, float u1, float v1, float u2, float v2) {
+ showMissingWarning("multitextured vertex requires OPENGL2");
+ }
+
+
+ public void vertex(float x, float y, float z, float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3) {
+ showMissingWarning("multitextured vertex requires OPENGL2");
+ }
+
+
+ public void vertex(float x, float y, float z, float[] u, float[] v) {
+ showMissingWarning("multitextured vertex requires OPENGL2");
+ }
}
diff --git a/core/src/processing/core/PGraphics3D.java b/core/src/processing/core/PGraphics3D.java
index d515e1ef7..870e4f91b 100644
--- a/core/src/processing/core/PGraphics3D.java
+++ b/core/src/processing/core/PGraphics3D.java
@@ -28,7 +28,6 @@ import java.awt.Toolkit;
import java.awt.image.*;
import java.util.*;
-
/**
* Subclass of PGraphics that handles 3D rendering.
* It can render 3D inside a browser window and requires no plug-ins.
@@ -175,11 +174,15 @@ public class PGraphics3D extends PGraphics {
* If we wanted to, this variable would have to become a stack.
*/
protected boolean manipulatingCamera;
-
+
float[][] matrixStack = new float[MATRIX_STACK_DEPTH][16];
float[][] matrixInvStack = new float[MATRIX_STACK_DEPTH][16];
int matrixStackDepth;
+ protected boolean projectionMode = false;
+ float[][] pmatrixStack = new float[MATRIX_STACK_DEPTH][16];
+ int pmatrixStackDepth;
+
// These two matrices always point to either the modelview
// or the modelviewInv, but they are swapped during
// when in camera manipulation mode. That way camera transforms
@@ -2991,26 +2994,41 @@ public class PGraphics3D extends PGraphics {
public void pushMatrix() {
- if (matrixStackDepth == MATRIX_STACK_DEPTH) {
- throw new RuntimeException(ERROR_PUSHMATRIX_OVERFLOW);
+ if (projectionMode) {
+ if (pmatrixStackDepth == MATRIX_STACK_DEPTH) {
+ throw new RuntimeException(ERROR_PUSHMATRIX_OVERFLOW);
+ }
+ projection.get(pmatrixStack[pmatrixStackDepth]);
+ pmatrixStackDepth++;
+ } else {
+ if (matrixStackDepth == MATRIX_STACK_DEPTH) {
+ throw new RuntimeException(ERROR_PUSHMATRIX_OVERFLOW);
+ }
+ modelview.get(matrixStack[matrixStackDepth]);
+ modelviewInv.get(matrixInvStack[matrixStackDepth]);
+ matrixStackDepth++;
}
- modelview.get(matrixStack[matrixStackDepth]);
- modelviewInv.get(matrixInvStack[matrixStackDepth]);
- matrixStackDepth++;
}
public void popMatrix() {
- if (matrixStackDepth == 0) {
- throw new RuntimeException(ERROR_PUSHMATRIX_UNDERFLOW);
+ if (projectionMode) {
+ if (pmatrixStackDepth == 0) {
+ throw new RuntimeException(ERROR_PUSHMATRIX_UNDERFLOW);
+ }
+ pmatrixStackDepth--;
+ projection.set(pmatrixStack[pmatrixStackDepth]);
+ } else {
+ if (matrixStackDepth == 0) {
+ throw new RuntimeException(ERROR_PUSHMATRIX_UNDERFLOW);
+ }
+ matrixStackDepth--;
+ modelview.set(matrixStack[matrixStackDepth]);
+ modelviewInv.set(matrixInvStack[matrixStackDepth]);
}
- matrixStackDepth--;
- modelview.set(matrixStack[matrixStackDepth]);
- modelviewInv.set(matrixInvStack[matrixStackDepth]);
}
-
//////////////////////////////////////////////////////////////
// MATRIX TRANSFORMATIONS
@@ -3022,8 +3040,12 @@ public class PGraphics3D extends PGraphics {
public void translate(float tx, float ty, float tz) {
- forwardTransform.translate(tx, ty, tz);
- reverseTransform.invTranslate(tx, ty, tz);
+ if (projectionMode) {
+ projection.translate(tx, ty, tz);
+ } else {
+ forwardTransform.translate(tx, ty, tz);
+ reverseTransform.invTranslate(tx, ty, tz);
+ }
}
@@ -3039,20 +3061,32 @@ public class PGraphics3D extends PGraphics {
public void rotateX(float angle) {
- forwardTransform.rotateX(angle);
- reverseTransform.invRotateX(angle);
+ if (projectionMode) {
+ projection.rotateX(angle);
+ } else {
+ forwardTransform.rotateX(angle);
+ reverseTransform.invRotateX(angle);
+ }
}
public void rotateY(float angle) {
- forwardTransform.rotateY(angle);
- reverseTransform.invRotateY(angle);
+ if (projectionMode) {
+ projection.rotateY(angle);
+ } else {
+ forwardTransform.rotateY(angle);
+ reverseTransform.invRotateY(angle);
+ }
}
public void rotateZ(float angle) {
- forwardTransform.rotateZ(angle);
- reverseTransform.invRotateZ(angle);
+ if (projectionMode) {
+ projection.rotateZ(angle);
+ } else {
+ forwardTransform.rotateZ(angle);
+ reverseTransform.invRotateZ(angle);
+ }
}
@@ -3061,8 +3095,12 @@ public class PGraphics3D extends PGraphics {
* except that it takes radians (instead of degrees).
*/
public void rotate(float angle, float v0, float v1, float v2) {
- forwardTransform.rotate(angle, v0, v1, v2);
- reverseTransform.invRotate(angle, v0, v1, v2);
+ if (projectionMode) {
+ projection.rotate(angle, v0, v1, v2);
+ } else {
+ forwardTransform.rotate(angle, v0, v1, v2);
+ reverseTransform.invRotate(angle, v0, v1, v2);
+ }
}
@@ -3086,8 +3124,12 @@ public class PGraphics3D extends PGraphics {
* Scale in three dimensions.
*/
public void scale(float x, float y, float z) {
- forwardTransform.scale(x, y, z);
- reverseTransform.invScale(x, y, z);
+ if (projectionMode) {
+ projection.scale(x, y, z);
+ } else {
+ forwardTransform.scale(x, y, z);
+ reverseTransform.invScale(x, y, z);
+ }
}
@@ -3116,8 +3158,12 @@ public class PGraphics3D extends PGraphics {
public void resetMatrix() {
- forwardTransform.reset();
- reverseTransform.reset();
+ if (projectionMode) {
+ projection.reset();
+ } else {
+ forwardTransform.reset();
+ reverseTransform.reset();
+ }
}
@@ -3153,16 +3199,22 @@ public class PGraphics3D extends PGraphics {
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 (projectionMode) {
+ projection.apply(n00, n01, n02, n03,
+ n10, n11, n12, n13,
+ n20, n21, n22, n23,
+ n30, n31, n32, n33);
+ } else {
+ forwardTransform.apply(n00, n01, n02, n03,
+ n10, n11, n12, n13,
+ n20, n21, n22, n23,
+ n30, n31, n32, n33);
- forwardTransform.apply(n00, n01, n02, n03,
- n10, n11, n12, n13,
- n20, n21, n22, n23,
- n30, n31, n32, n33);
-
- reverseTransform.invApply(n00, n01, n02, n03,
- n10, n11, n12, n13,
- n20, n21, n22, n23,
- n30, n31, n32, n33);
+ reverseTransform.invApply(n00, n01, n02, n03,
+ n10, n11, n12, n13,
+ n20, n21, n22, n23,
+ n30, n31, n32, n33);
+ }
}
@@ -3636,7 +3688,28 @@ public class PGraphics3D extends PGraphics {
projection.print();
}
+
+ public PMatrix getProjection() {
+ return projection.get();
+ }
+
+ /**
+ * Enables projection mode. The geometric transformations and
+ * push/pop matrix operations are applied to the projection matrix
+ * instead to the modelview.
+ */
+ public void beginProjection() {
+ projectionMode = true;
+ }
+
+ /**
+ * Disables projection mode.
+ */
+ public void endProjection() {
+ projectionMode = false;
+ }
+
//////////////////////////////////////////////////////////////
diff --git a/core/src/processing/core/PGraphicsJava2D.java b/core/src/processing/core/PGraphicsJava2D.java
index 3009bf618..22e4d0074 100644
--- a/core/src/processing/core/PGraphicsJava2D.java
+++ b/core/src/processing/core/PGraphicsJava2D.java
@@ -816,7 +816,7 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ {
}
- class ImageCache {
+ class ImageCache extends PMetadata {
PImage source;
boolean tinted;
int tintedColor;
@@ -832,6 +832,9 @@ public class PGraphicsJava2D extends PGraphics /*PGraphics2D*/ {
// image = new BufferedImage(source.width, source.height, type);
}
+ public void delete() {
+ }
+
/**
* Update the pixels of the cache image. Already determined that the tint
* has changed, or the pixels have changed, so should just go through
diff --git a/core/src/processing/core/PImage.java b/core/src/processing/core/PImage.java
index 7801eeb59..935235233 100644
--- a/core/src/processing/core/PImage.java
+++ b/core/src/processing/core/PImage.java
@@ -27,6 +27,7 @@ package processing.core;
import java.awt.image.*;
import java.io.*;
import java.util.HashMap;
+import java.util.Set;
import javax.imageio.ImageIO;
@@ -102,10 +103,11 @@ public class PImage implements PConstants, Cloneable {
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-
- /** for subclasses that need to store info about the image */
- protected HashMap