diff --git a/core/PApplet.java b/core/PApplet.java index bfe56982c..af48765af 100644 --- a/core/PApplet.java +++ b/core/PApplet.java @@ -262,7 +262,15 @@ public class PApplet extends Applet public void depth() { - g = new PGraphics3(DEFAULT_WIDTH, DEFAULT_HEIGHT); + if (g.width != 0) { + g = new PGraphics3(g.width, g.height); + } else { + g = new PGraphics3(DEFAULT_WIDTH, DEFAULT_HEIGHT); + } + // it's ok to call this, because depth() is only getting called + // at least inside of setup, so things can be drawn just + // fine since it's post-beginFrame. + g.defaults(); } @@ -1949,126 +1957,19 @@ public class PApplet extends Applet // IMAGE I/O - /* - private Image gimmeImage(URL url, boolean force) { - Toolkit tk = Toolkit.getDefaultToolkit(); - - URLConnection conn = null; - try { - //conn = new URLConnection(url); - conn = url.openConnection(); - - // i don't think this does anything, - // but just set the fella for good measure - conn.setUseCaches(false); - // also had a note from zach about parent.obj.close() on url - // but that doesn't seem to be needed anymore... - - // throws an exception if it doesn't exist - conn.connect(); - - if (!force) { - // how do you close the bastard? - conn = null; - // close connection and just use regular method - return tk.getImage(url); - } - - // slurp contents of that stream - InputStream stream = conn.getInputStream(); - - BufferedInputStream bis = new BufferedInputStream(stream); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - try { - int c = bis.read(); - while (c != -1) { - out.write(c); - c = bis.read(); - } - } catch (IOException e) { - return null; - } - bis.close(); // will this help? - //byte bytes[] = out.toByteArray(); - - // build an image out of it - //return tk.createImage(bytes); - return tk.createImage(out.toByteArray()); - - } catch (Exception e) { // null pointer or i/o ex - //System.err.println("error loading image: " + url); - return null; - } - } - */ - public PImage loadImage(String filename) { if (filename.toLowerCase().endsWith(".tga")) { - return loadTargaImage(filename); + return loadImageTGA(filename); } return loadImage(filename, true); } + // returns null if no image of that name is found public PImage loadImage(String filename, boolean force) { - //Image awtimage = null; - //String randomizer = "?" + nf((int) (random()*10000), 4); - - /* - if (filename.startsWith("http://")) { - try { - URL url = new URL(filename); - awtimage = gimmeImage(url, force); - - } catch (MalformedURLException e) { - System.err.println("error loading image from " + filename); - e.printStackTrace(); - return null; - } - - } else { - //System.out.println(getClass().getName()); - //System.out.println(getClass().getResource(filename)); - awtimage = gimmeImage(getClass().getResource(filename), force); - if (awtimage == null) { - awtimage = - gimmeImage(getClass().getResource("data/" + filename), force); - } - if (awtimage == null) { - try { - //FileInputStream fis = - //new FileInputStream(folder + "data/" + filename); - String url = "file:/" + folder + "/data/" + filename; - //URL url = new URL("file:/" + folder + "data/" + filename); - awtimage = gimmeImage(new URL(url), force); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - */ - Image awtImage = Toolkit.getDefaultToolkit().createImage(loadBytes(filename)); - /* - if (awtimage == null) { - System.err.println("could not load image " + filename); - return null; - } - */ - - /* - Component component = this; //applet; - if (component == null) { - component = new Frame(); - ((Frame)component).pack(); - // now we have a peer! yay! - } - MediaTracker tracker = new MediaTracker(component); - */ - MediaTracker tracker = new MediaTracker(this); tracker.addImage(awtImage, 0); try { @@ -2089,37 +1990,7 @@ public class PApplet extends Applet } } } - return image; - - /* - int jwidth = awtimage.getWidth(null); - int jheight = awtimage.getHeight(null); - - int jpixels[] = new int[jwidth*jheight]; - PixelGrabber pg = - new PixelGrabber(awtimage, 0, 0, jwidth, jheight, jpixels, 0, jwidth); - try { - pg.grabPixels(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - //int format = RGB; - if (filename.toLowerCase().endsWith(".gif")) { - // if it's a .gif image, test to see if it has transparency - for (int i = 0; i < jpixels.length; i++) { - // since transparency is often at corners, hopefully this - // will find a non-transparent pixel quickly and exit - if ((jpixels[i] & 0xff000000) != 0xff000000) { - return new PImage(jpixels, jwidth, jheight, ARGB); - //format = RGBA; - //break; - } - } - } - return new PImage(jpixels, jwidth, jheight, RGB); - */ } @@ -2129,44 +2000,44 @@ public class PApplet extends Applet * [fry] this could be optimized to not use loadBytes * which would help out memory situations with large images */ - protected PImage loadTargaImage(String filename) { + protected PImage loadImageTGA(String filename) { // load image file as byte array byte[] buffer = loadBytes(filename); - // check if it's a TGA and has 8bits/colour channel - if (buffer[2] == 2 && buffer[17] == 8) { - // get image dimensions - //int w=(b2i(buffer[13])<<8) + b2i(buffer[12]); - int w = ((buffer[13] & 0xff) << 8) + (buffer[12] & 0xff); - //int h=(b2i(buffer[15])<<8) + b2i(buffer[14]); - int h = ((buffer[15] & 0xff) << 8) + (buffer[14] & 0xff); - // check if image has alpha - boolean hasAlpha=(buffer[16] == 32); + // check if it's a TGA and has 8bits/colour channel + if (buffer[2] == 2 && buffer[17] == 8) { + // get image dimensions + //int w=(b2i(buffer[13])<<8) + b2i(buffer[12]); + int w = ((buffer[13] & 0xff) << 8) + (buffer[12] & 0xff); + //int h=(b2i(buffer[15])<<8) + b2i(buffer[14]); + int h = ((buffer[15] & 0xff) << 8) + (buffer[14] & 0xff); + // check if image has alpha + boolean hasAlpha=(buffer[16] == 32); - // setup new image object - PImage img = new PImage(w,h); - img.format = (hasAlpha ? ARGB : RGB); + // setup new image object + PImage img = new PImage(w,h); + img.format = (hasAlpha ? ARGB : RGB); - // targa's are written upside down, so we need to parse it in reverse - int index = (h-1) * w; - // actual bitmap data starts at byte 18 - int offset = 18; + // targa's are written upside down, so we need to parse it in reverse + int index = (h-1) * w; + // actual bitmap data starts at byte 18 + int offset = 18; - // read out line by line - for (int y = h-1; y >= 0; y--) { - for (int x = 0; x < w; x++) { - img.pixels[index + x] = - (buffer[offset++] & 0xff) | - ((buffer[offset++] & 0xff) << 8) | - ((buffer[offset++] & 0xff) << 16) | - (hasAlpha ? ((buffer[offset++] & 0xff) << 24) : 0xff000000); - } - index -= w; - } - return img; - } - die("loadImage(): bad targa image format"); - return null; + // read out line by line + for (int y = h-1; y >= 0; y--) { + for (int x = 0; x < w; x++) { + img.pixels[index + x] = + (buffer[offset++] & 0xff) | + ((buffer[offset++] & 0xff) << 8) | + ((buffer[offset++] & 0xff) << 16) | + (hasAlpha ? ((buffer[offset++] & 0xff) << 24) : 0xff000000); + } + index -= w; + } + return img; + } + die("loadImage(): bad targa image format"); + return null; } @@ -4510,23 +4381,18 @@ v PApplet.this.stop(); } - public void modified() { - g.modified(); + public void updatePixels() { + g.updatePixels(); } - public void modified(int x, int y) { - g.modified(x, y); + public void updatePixels(int x1, int y1, int x2, int y2) { + g.updatePixels(x1, y1, x2, y2); } - public void modified(int x1, int y1, int x2, int y2) { - g.modified(x1, y1, x2, y2); - } - - - public void resetModified() { - g.resetModified(); + public void pixelsUpdated() { + g.pixelsUpdated(); } @@ -4778,6 +4644,12 @@ v PApplet.this.stop(); } + public void quad(float x1, float y1, float x2, float y2, + float x3, float y3, float x4, float y4) { + g.quad(x1, y1, x2, y2, x3, y3, x4, y4); + } + + public void rectMode(int mode) { g.rectMode(mode); } @@ -4788,12 +4660,6 @@ v PApplet.this.stop(); } - public void quad(float x1, float y1, float x2, float y2, - float x3, float y3, float x4, float y4) { - g.quad(x1, y1, x2, y2, x3, y3, x4, y4); - } - - public void ellipseMode(int mode) { g.ellipseMode(mode); } @@ -5001,11 +4867,6 @@ v PApplet.this.stop(); } - public void angleMode(int mode) { - g.angleMode(mode); - } - - public void translate(float tx, float ty) { g.translate(tx, ty); } @@ -5016,6 +4877,16 @@ v PApplet.this.stop(); } + public void angleMode(int mode) { + g.angleMode(mode); + } + + + public void rotate(float angle) { + g.rotate(angle); + } + + public void rotateX(float angle) { g.rotateX(angle); } @@ -5031,11 +4902,6 @@ v PApplet.this.stop(); } - public void rotate(float angle) { - g.rotate(angle); - } - - public void rotate(float angle, float vx, float vy, float vz) { g.rotate(angle, vx, vy, vz); } diff --git a/core/PGraphics.java b/core/PGraphics.java index 09dc2b71c..2adf130a3 100644 --- a/core/PGraphics.java +++ b/core/PGraphics.java @@ -279,6 +279,7 @@ public class PGraphics extends PImage implements PConstants { resize(iwidth, iheight); // init color/stroke/fill + // called instead just before setup on first frame //defaults(); // clear geometry for loading later @@ -744,12 +745,6 @@ public class PGraphics extends PImage implements PConstants { } - - ////////////////////////////////////////////////////////////// - - // LINE - - public void line(float x1, float y1, float x2, float y2) { // TODO } @@ -761,18 +756,18 @@ public class PGraphics extends PImage implements PConstants { } - - ////////////////////////////////////////////////////////////// - - // TRIANGLE - - public void triangle(float x1, float y1, float x2, float y2, float x3, float y3) { // TODO } + public void quad(float x1, float y1, float x2, float y2, + float x3, float y3, float x4, float y4) { + // TODO + } + + ////////////////////////////////////////////////////////////// @@ -809,19 +804,12 @@ public class PGraphics extends PImage implements PConstants { y1 -= vradius; } - // TODO write rect drawing function + draw_rect(x1, y1, x2, y2); } - - ////////////////////////////////////////////////////////////// - - // QUAD - - - public void quad(float x1, float y1, float x2, float y2, - float x3, float y3, float x4, float y4) { - // TODO + protected void draw_rect(float x1, float y1, float x2, float y2) { + // TODO write rect drawing function } @@ -857,6 +845,11 @@ public class PGraphics extends PImage implements PConstants { y = b - d/2f; } + draw_ellipse(x, y, w, h); + } + + + protected void draw_ellipse(float x, float y, float w, float h) { // TODO draw an ellipse } @@ -900,7 +893,12 @@ public class PGraphics extends PImage implements PConstants { while (stop < start) stop += TWO_PI; } - // TODO draw an arc + draw_arc(start, stop, x, y, w, h); + } + + + protected void draw_arc(float start, float stop, + float x, float y, float w, float h) { } @@ -1407,7 +1405,7 @@ public class PGraphics extends PImage implements PConstants { textFont.resetLeading(); } else { - System.err.println("Ignoring improperly loaded font in textFont()"); + throw new RuntimeException("a null PFont was passed to textFont()"); } } @@ -1424,7 +1422,7 @@ public class PGraphics extends PImage implements PConstants { textSize = size; } else { - System.err.println("First set a font before setting its size."); + throw new RuntimeException("use textFont() before textSize()"); } } @@ -1434,7 +1432,7 @@ public class PGraphics extends PImage implements PConstants { textFont.leading(leading); } else { - System.err.println("First set a font before setting its leading."); + throw new RuntimeException("use textFont() before textLeading()"); } } @@ -1444,7 +1442,7 @@ public class PGraphics extends PImage implements PConstants { textFont.align(mode); } else { - System.err.println("First set a font before setting its mode."); + throw new RuntimeException("use textFont() before textMode()"); } } @@ -1454,7 +1452,7 @@ public class PGraphics extends PImage implements PConstants { textFont.space(space); } else { - System.err.println("First set a font before setting the space."); + throw new RuntimeException("use textFont() before textSpace()"); } } @@ -1464,7 +1462,7 @@ public class PGraphics extends PImage implements PConstants { textFont.text(c, x, y, this); } else { - System.err.println("text(): first set a font before drawing text"); + throw new RuntimeException("use textFont() before text()"); } } @@ -1479,7 +1477,7 @@ public class PGraphics extends PImage implements PConstants { textFont.text(s, x, y, this); } else { - System.err.println("text(): first set a font before drawing text"); + throw new RuntimeException("use textFont() before text()"); } } @@ -1521,7 +1519,7 @@ public class PGraphics extends PImage implements PConstants { textFont.text(s, x1, y1, x2, y2, this); } else { - System.err.println("text(): first set a font before drawing text"); + throw new RuntimeException("use textFont() before text()"); } } @@ -1564,11 +1562,6 @@ public class PGraphics extends PImage implements PConstants { // MATRIX TRANSFORMATIONS - public void angleMode(int mode) { - angleMode = mode; - } - - public void translate(float tx, float ty) { m02 += tx*m00 + ty*m01 + m02; m12 += tx*m10 + ty*m11 + m12; @@ -1579,16 +1572,9 @@ public class PGraphics extends PImage implements PConstants { // not supported in 2D } - public void rotateX(float angle) { - // not supported in 2D - } - public void rotateY(float angle) { - // not supported in 2D - } - - public void rotateZ(float angle) { - // not supported in 2D + public void angleMode(int mode) { + angleMode = mode; } @@ -1605,6 +1591,19 @@ public class PGraphics extends PImage implements PConstants { } + public void rotateX(float angle) { + // not supported in 2D + } + + public void rotateY(float angle) { + // not supported in 2D + } + + public void rotateZ(float angle) { + // not supported in 2D + } + + public void rotate(float angle, float vx, float vy, float vz) { // not supported in 2D } diff --git a/core/PGraphics2.java b/core/PGraphics2.java index 166e5d54e..ef434165e 100644 --- a/core/PGraphics2.java +++ b/core/PGraphics2.java @@ -561,20 +561,21 @@ public class PGraphics2 extends PGraphics { if (who.cache == null) { who.cache = new BufferedImage(who.width, who.height, BufferedImage.TYPE_INT_ARGB); - who.modified(); // mark the whole thing for update + who.updatePixels(); // mark the whole thing for update } if (who.modified) { // update the sub-portion of the image as necessary BufferedImage bi = (BufferedImage) who.cache; - bi.setRGB(who.mx1, who.my1, - who.mx2 - who.mx1 + 1, - who.my2 - who.my1 + 1, + bi.setRGB(who.mx1, + who.my1, + who.mx2 - who.mx1, + who.my2 - who.my1, who.pixels, who.my1*who.width + who.mx1, // offset for copy who.width); // scan size - who.resetModified(); + who.pixelsUpdated(); } } @@ -843,7 +844,7 @@ public class PGraphics2 extends PGraphics { public void copy(PImage src, int dx, int dy) { - // TODO if this image is not RGB, needs to behave differently + // TODO if this image is not ARGB or RGB, needs to behave differently // (if it's gray, need to copy gray pixels) // for alpha, just leave it be.. copy() doesn't composite ((BufferedImage) image).setRGB(dx, dy, src.width, src.height, diff --git a/core/PGraphics3.java b/core/PGraphics3.java index 8552c27b0..55c3dc05b 100644 --- a/core/PGraphics3.java +++ b/core/PGraphics3.java @@ -4,7 +4,7 @@ PGraphics - main graphics and rendering context Part of the Processing project - http://processing.org - Copyright (c) 2004- Ben Fry and Casey Reas + Copyright (c) 2004-05 Ben Fry and Casey Reas Copyright (c) 2001-04 Massachusetts Institute of Technology This library is free software; you can redistribute it and/or @@ -25,11 +25,9 @@ package processing.core; -//import java.applet.*; import java.awt.*; -//import java.awt.event.*; import java.awt.image.*; -//import java.io.*; + public class PGraphics3 extends PGraphics { @@ -207,7 +205,7 @@ public class PGraphics3 extends PGraphics { allocate(); // clear the screen with the old background color - background(backgroundColor); + //background(backgroundColor); // init perspective projection based on new dimensions cameraFOV = 60; // at least for now @@ -246,7 +244,9 @@ public class PGraphics3 extends PGraphics { // because of a java 1.1 bug, pixels must be registered as // opaque before their first run, the memimgsrc will flicker // and run very slowly. - for (int i = 0; i < pixelCount; i++) pixels[i] = 0xffffffff; + backgroundColor |= 0xff000000; // just for good measure + for (int i = 0; i < pixelCount; i++) pixels[i] = backgroundColor; + //for (int i = 0; i < pixelCount; i++) pixels[i] = 0xffffffff; cm = new DirectColorModel(32, 0x00ff0000, 0x0000ff00, 0x000000ff);; mis = new MemoryImageSource(width, height, pixels, 0, width); @@ -254,7 +254,6 @@ public class PGraphics3 extends PGraphics { mis.setAnimated(true); image = Toolkit.getDefaultToolkit().createImage(mis); - // TODO don't allocate these until depth() is called zbuffer = new float[pixelCount]; stencil = new int[pixelCount]; @@ -266,6 +265,9 @@ public class PGraphics3 extends PGraphics { public void defaults() { super.defaults(); + cameraMode(PERSPECTIVE); + + //System.out.println("PGraphics3.defaults()"); // easiest for beginners textureMode(IMAGE_SPACE); @@ -1394,6 +1396,24 @@ public class PGraphics3 extends PGraphics { } + + ////////////////////////////////////////////////////////////// + + // BASIC SHAPES + + + public void point(float x, float y) { + point(x, y, 0); + } + + + public void point(float x, float y, float z) { + beginShape(POINTS); + vertex(x, y, z); + endShape(); + } + + /* private void point3(float x, float y, float z, int color) { // need to get scaled version of the stroke float x1 = screenX(x - 0.5f, y - 0.5f, z); @@ -1414,59 +1434,145 @@ public class PGraphics3 extends PGraphics { // these will be } } + */ - - ////////////////////////////////////////////////////////////// - - // SHAPES - - public void point(float x, float y) { - point(x, y, 0); - } - - public void point(float x, float y, float z) { - } - public void line(float x1, float y1, float x2, float y2) { line(x1, y1, 0, x2, y2, 0); } + public void line(float x1, float y1, float z1, float x2, float y2, float z2) { + beginShape(LINES); + vertex(x1, y1, z1); + vertex(x2, y2, z2); + endShape(); } + public void triangle(float x1, float y1, float x2, float y2, float x3, float y3) { + beginShape(TRIANGLES); + vertex(x1, y1); + vertex(x2, y2); + vertex(x3, y3); + endShape(); } - //public void rectMode(int mode) - - public void rect(float x1, float y1, float x2, float y2) { - } public void quad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { + beginShape(QUADS); + vertex(x1, y1); + vertex(x2, y2); + vertex(x3, y3); + vertex(x4, y4); + endShape(); } - public void circle(float x, float y, float radius) { + + + ////////////////////////////////////////////////////////////// + + // PLACED SHAPES + + + public void draw_rect(float x1, float y1, float x2, float y2) { + quad(x1, y1, x2, y1, x2, y2, x1, y2); } - public void ellipseMode(int mode) { + + protected void draw_ellipse(float x, float y, float hradius, float vradius) { + // adapt accuracy to radii used w/ a minimum of 4 segments [toxi] + // now uses current scale factors to determine "real" transformed radius + + //int cAccuracy = (int)(4+Math.sqrt(hradius*abs(m00)+vradius*abs(m11))*2); + //int cAccuracy = (int)(4+Math.sqrt(hradius+vradius)*2); + + // notched this up to *3 instead of *2 because things were + // looking a little rough, i.e. the calculate->arctangent example [fry] + + // also removed the m00 and m11 because those were causing weirdness + // need an actual measure of magnitude in there [fry] + + int cAccuracy = (int)(4+Math.sqrt(hradius+vradius)*3); + + // [toxi031031] adapted to use new lookup tables + float inc = (float)SINCOS_LENGTH / cAccuracy; + + float val = 0; + beginShape(POLYGON); + for (int i = 0; i < cAccuracy; i++) { + vertex(x + cosLUT[(int) val] * hradius, + y + sinLUT[(int) val] * vradius); + val += inc; + } + endShape(); } - public void ellipse(float x, float y, float hradius, float vradius) { + + /** + * Start and stop are in radians, converted by the parent function. + * Note that the radians can be greater (or less) than TWO_PI. + * This is so that an arc can be drawn that crosses zero mark, + * and the user will still collect $200. + */ + protected void draw_arc(float start, float stop, + float x, float y, float w, float h) { + float hr = w / 2f; + float vr = h / 2f; + + if (fill) { + // shut off stroke for a minute + boolean savedStroke = stroke; + stroke = false; + + int startLUT = (int) (0.5f + (start / TWO_PI) * SINCOS_LENGTH); + int stopLUT = (int) (0.5f + (stop / TWO_PI) * SINCOS_LENGTH); + + beginShape(TRIANGLE_FAN); + vertex(x, y); + int increment = 1; // what's a good algorithm? stopLUT - startLUT; + for (int i = startLUT; i < stopLUT; i += increment) { + int ii = i % SINCOS_LENGTH; + vertex(x + cosLUT[ii] * hr, + y + sinLUT[ii] * vr); + } + // draw last point explicitly for accuracy + vertex(x + cosLUT[stopLUT % SINCOS_LENGTH] * hr, + y + sinLUT[stopLUT % SINCOS_LENGTH] * vr); + endShape(); + + stroke = savedStroke; + } + + if (stroke) { + // Almost identical to above, but this uses a LINE_STRIP + // and doesn't include the first (center) vertex. + + boolean savedFill = fill; + fill = false; + + int startLUT = (int) (0.5f + (start / TWO_PI) * SINCOS_LENGTH); + int stopLUT = (int) (0.5f + (stop / TWO_PI) * SINCOS_LENGTH); + + beginShape(LINE_STRIP); + int increment = 1; // what's a good algorithm? stopLUT - startLUT; + for (int i = startLUT; i < stopLUT; i += increment) { + int ii = i % SINCOS_LENGTH; + vertex(x + cosLUT[ii] * hr, + y + sinLUT[ii] * vr); + } + // draw last point explicitly for accuracy + vertex(x + cosLUT[stopLUT % SINCOS_LENGTH] * hr, + y + sinLUT[stopLUT % SINCOS_LENGTH] * vr); + endShape(); + + fill = savedFill; + } } - //public void arcMode(int mode) - - public void arc(float start, float stop, - float x, float y, float radius) { - } - - public void arc(float start, float stop, - float x, float y, float hr, float vr) { - } ////////////////////////////////////////////////////////////// @@ -1493,12 +1599,7 @@ public class PGraphics3 extends PGraphics { // 3D BOX - // solid or wire depends on settings for stroke and fill - // slices/stacks can be set by an advanced option - - //public void cube(float size) { public void box(float size) { - //box(-size/2, -size/2, -size/2, size/2, size/2, size/2); box(size, size, size); } @@ -1506,15 +1607,14 @@ public class PGraphics3 extends PGraphics { // OPT this isn't the least bit efficient // because it redraws lines along the vertices // ugly ugly ugly! - //public void box(float x1, float y1, float z1, - // float x2, float y2, float z2) { public void box(float w, float h, float d) { float x1 = -w/2f; float x2 = w/2f; float y1 = -h/2f; float y2 = h/2f; float z1 = -d/2f; float z2 = d/2f; - //if (hints[NEW_GRAPHICS]) triangle.setCulling(true); - triangle.setCulling(true); + if (triangle != null) { // triangle is null in gl + triangle.setCulling(true); + } beginShape(QUADS); @@ -1556,8 +1656,9 @@ public class PGraphics3 extends PGraphics { endShape(); - //if (hints[NEW_GRAPHICS]) triangle.setCulling(false); - triangle.setCulling(false); + if (triangle != null) { // triangle is null in gl + triangle.setCulling(false); + } } @@ -1637,8 +1738,9 @@ public class PGraphics3 extends PGraphics { if (x!=0f && y!=0f && z!=0f) translate(x,y,z); scale(r); - //if (hints[NEW_GRAPHICS]) triangle.setCulling(true); - triangle.setCulling(true); + if (triangle != null) { // triangle is null in gl + triangle.setCulling(true); + } // 1st ring from south pole beginShape(TRIANGLE_STRIP); @@ -1681,8 +1783,9 @@ public class PGraphics3 extends PGraphics { endShape(); pop(); - //if (hints[NEW_GRAPHICS]) triangle.setCulling(false); - triangle.setCulling(false); + if (triangle != null) { // triangle is null in gl + triangle.setCulling(false); + } } @@ -2236,6 +2339,8 @@ public class PGraphics3 extends PGraphics { * even if noDepth() was called before draw() exited. */ public void clear() { + //System.out.println("PGraphics3.clear(" + + // PApplet.hex(backgroundColor) + ")"); for (int i = 0; i < pixelCount; i++) { pixels[i] = backgroundColor; zbuffer[i] = MAX_FLOAT; diff --git a/core/PImage.java b/core/PImage.java index ee5c3aba9..7320b3a2c 100644 --- a/core/PImage.java +++ b/core/PImage.java @@ -4,7 +4,7 @@ PImage - storage class for pixel data Part of the Processing project - http://Proce55ing.net - Copyright (c) 2001-03 + Copyright (c) 2001-05 Ben Fry, Massachusetts Institute of Technology and Casey Reas, Interaction Design Institute Ivrea @@ -28,6 +28,7 @@ package processing.core; import java.awt.*; import java.awt.image.*; +import java.lang.reflect.*; import java.io.*; @@ -84,6 +85,9 @@ public class PImage implements PConstants, Cloneable { public int imageMode = CORNER; public boolean smooth = false; + /** native storage for java 1.3 image object */ + //public Object image; + /** for subclasses that need to store info about the image */ public Object cache; @@ -186,10 +190,15 @@ public class PImage implements PConstants, Cloneable { /** - * mode is one of CORNERS, CORNER, CENTER + * mode is one of CORNERS or CORNER, because the others are + * just too weird for the other functions */ public void imageMode(int mode) { - imageMode = mode; + if ((imageMode == CORNER) || (imageMode == CORNERS)) { + imageMode = mode; + } else { + throw new RuntimeException("imageMode() only works with CORNER or CORNERS"); + } } @@ -216,41 +225,124 @@ public class PImage implements PConstants, Cloneable { // MARKING IMAGE AS MODIFIED / FOR USE w/ GET/SET - public void modified() { - mx1 = 0; - my1 = 0; - mx2 = width - 1; - my2 = height - 1; - modified = true; + /* + public int[] loadPixels() { + return getPixels(0, 0, width, height); + } + */ + + + /** + * Note that when using imageMode(CORNERS), + * the x2 and y2 positions are non-inclusive. + */ + /* + public int[] loadPixels(int x1, int y1, int x2, int y2) { + if (modified) { + // have to set the modified region to include the min/max + // of the coordinates coming in. + // also, mustn't get the pixels for the section that's + // already been marked as modified. gah. + // too complicated, just throw an error + String msg = + "getPixels(x, y, w, h) cannot be used multiple times. " + + "Use getPixels() once to get the entire image instead."; + throw new RuntimeException(msg); + } + + if (imageMode == CORNER) { // x2, y2 are w/h + x2 += x1; + y2 += y1; + } + + if (pixels == null) { // this is a java 1.3 buffered image + if (image == null) { // this is just an error + throw new RuntimeException("PImage not properly setup for getPixels()"); + } else { + pixels = new int[width*height]; + } + } + + if (image == null) { + // this happens when using just the 1.1 library + // no need to do anything, since the pixels have already been grabbed + + } else { + // copy the contents of the buffered image to pixels[] + //((BufferedImage) image).getRGB(x, y, w, h, output.pixels, 0, width); + try { + //System.out.println("running getrgb..."); + Class bufferedImageClass = + Class.forName("java.awt.image.BufferedImage"); + // getRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize) + Method getRgbMethod = + bufferedImageClass.getMethod("getRGB", new Class[] { + Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE, + int[].class, Integer.TYPE, Integer.TYPE + }); + getRgbMethod.invoke(image, new Object[] { + new Integer(x1), new Integer(y1), + new Integer(x2 - x1 + 1), new Integer(y2 - y1 + 1), + pixels, new Integer(0), new Integer(width) + }); + + } catch (Exception e) { + e.printStackTrace(); + } + } + return pixels; // just to be nice + } + */ + + + /** + * Mark all pixels as needing update. + */ + public void updatePixels() { + updatePixels(0, 0, width, height); } - public void modified(int x, int y) { - if (x < mx1) mx1 = x; - if (x > mx2) mx2 = x; - if (y < my1) my1 = y; - if (y > my2) my2 = y; - modified = true; + + /** + * Note that when using imageMode(CORNERS), + * the x2 and y2 positions are non-inclusive. + */ + public void updatePixels(int x1, int y1, int x2, int y2) { + //if (!modified) { // could just set directly, but.. + //} + + if (imageMode == CORNER) { // x2, y2 are w/h + x2 += x1; + y2 += y1; + } + + if (!modified) { + mx1 = x1; + mx2 = x2; + my1 = y1; + my2 = y2; + modified = true; + + } else { + if (x1 < mx1) mx1 = x1; + if (x1 > mx2) mx2 = x1; + if (y1 < my1) my1 = y1; + if (y1 > my2) my2 = y1; + + if (x2 < mx1) mx1 = x2; + if (x2 > mx2) mx2 = x2; + if (y2 < my1) my1 = y2; + if (y2 > my2) my2 = y2; + } } - public void modified(int x1, int y1, int x2, int y2) { - if (x1 < mx1) mx1 = x1; - if (x1 > mx2) mx2 = x1; - if (y1 < my1) my1 = y1; - if (y1 > my2) my2 = y1; - if (x2 < mx1) mx1 = x2; - if (x2 > mx2) mx2 = x2; - if (y2 < my1) my1 = y2; - if (y2 > my2) my2 = y2; - - modified = true; - } - - public void resetModified() { - mx1 = -Integer.MAX_VALUE; - my1 = -Integer.MAX_VALUE; - mx2 = Integer.MAX_VALUE; - my2 = Integer.MAX_VALUE; + public void pixelsUpdated() { + //mx1 = Integer.MAX_VALUE; + //my1 = Integer.MAX_VALUE; + //mx2 = -Integer.MAX_VALUE; + //my2 = -Integer.MAX_VALUE; + modified = false; } @@ -283,10 +375,10 @@ public class PImage implements PConstants, Cloneable { w = (w - x); h = (h - x); - } else if (imageMode == CENTER) { + //} else if (imageMode == CENTER) { // w/h are the proper w/h, but x/y need to be moved - x -= w/2; - y -= h/2; + //x -= w/2; + //y -= h/2; } if (x < 0) x = 0; @@ -506,9 +598,9 @@ public class PImage implements PConstants, Cloneable { sx2 += sx1; sy2 += sy1; dx2 += dx1; dy2 += dy1; - } else if (imageMode == CENTER) { - sx2 /= 2f; sy2 /= 2f; - dx2 /= 2f; dy2 /= 2f; + //} else if (imageMode == CENTER) { + //sx2 /= 2f; sy2 /= 2f; + //dx2 /= 2f; dy2 /= 2f; } if ((src == this) && @@ -585,9 +677,9 @@ public class PImage implements PConstants, Cloneable { sx2 += sx1; sy2 += sy1; dx2 += dx1; dy2 += dy1; - } else if (imageMode == CENTER) { - sx2 /= 2f; sy2 /= 2f; - dx2 /= 2f; dy2 /= 2f; + //} else if (imageMode == CENTER) { + //sx2 /= 2f; sy2 /= 2f; + //dx2 /= 2f; dy2 /= 2f; } if ((src == this) && diff --git a/core/PMethods.java b/core/PMethods.java index 9e01bbec1..5ced29dea 100755 --- a/core/PMethods.java +++ b/core/PMethods.java @@ -140,27 +140,36 @@ public interface PMethods { public void triangle(float x1, float y1, float x2, float y2, float x3, float y3); + public void quad(float x1, float y1, float x2, float y2, + float x3, float y3, float x4, float y4); + + // + public void rectMode(int mode); public void rect(float x1, float y1, float x2, float y2); - public void quad(float x1, float y1, float x2, float y2, - float x3, float y3, float x4, float y4); + //protected void draw_rect(float x1, float y1, float x2, float y2); - //public void circle(float x, float y, float radius); + // REMOVED public void circle(float x, float y, float radius); public void ellipseMode(int mode); public void ellipse(float x, float y, float hradius, float vradius); - //public void arcMode(int mode); + //protected void draw_ellipse(float x, float y, float hradius, float vradius); - //public void arc(float start, float stop, - // float x, float y, float radius); + // REMOVED public void arcMode(int mode); + + // REMOVED public void arc(float start, float stop, + // float x, float y, float radius); public void arc(float start, float stop, float x, float y, float hr, float vr); + //protected void draw_arc(float start, float stop, + // float x, float y, float hr, float vr); + // public void box(float size); @@ -263,20 +272,20 @@ public interface PMethods { // - public void angleMode(int mode); - public void translate(float tx, float ty); public void translate(float tx, float ty, float tz); + public void angleMode(int mode); + + public void rotate(float angle); + public void rotateX(float angle); public void rotateY(float angle); public void rotateZ(float angle); - public void rotate(float angle); - public void rotate(float angle, float v0, float v1, float v2); public void scale(float s); diff --git a/core/todo.txt b/core/todo.txt index 31a5fcb52..357be7065 100644 --- a/core/todo.txt +++ b/core/todo.txt @@ -29,11 +29,71 @@ o saveFrame gets called at the beginning of loop() o or is just a message to save the next frame (problem for anim) X vertices max out at 512.. make it grow X add gzipInput and gzipOutput +X light(x, y, z, c1, c2, c3, TYPE) +X also BLight with same constructor, and on() and off() fxn + +image stuff +o could also do PImage2, which would need a getPixels() before messing w/ it +o bad idea, distinction not clear +o even in java 1.1, could use regular java.awt.Image and require getPixels() +o -> 1.1 wouldn't help anything, because needs pixels to render, oops api changes X removed circle.. it's dumb when ellipse() is in there X (it's not like we have square() in the api) X arcMode is gone.. just uses ellipseMode() +X save tga and tif methods are static and public +X imageMode(CORNER) and CORNERS are the only usable versions + +_ sphere x,y,z,r or box w,h,d.. need to make them consistent + +_ the updatePixels() in PGraphics has to be overridden (from PImage) +_ to make itself actually update on-screen +_ actually, should be no different than the check_image function +_ PGraphics2 and PGraphicsGL will need loadPixels() to be called +_ in order to read pixels from the buffer +_ loadPixels() and updatePixels() prolly should be shut off in opengl +_ make people use get() instead to grab sub-images +_ PGraphicsGL.copy() needs to be overridden.. use glDrawBitmap + +o loadImage() needs to handle 1.1 vs 1.3 loading +o set image.format to be BUFFERED? no.. just use RGBA always +o have a flag to always use the cache, i.e. with BufferedImage +o turn that off when someone modifies it (nope, no need to) +X PImage.getPixels(), updatePixels(), updatePixels(x, y, w, h), +o PImage.setPixels(int another[]); + +readPixels/writePixels? +has to happen, since this is so fundamental to gl as well +loadImage in 1.3 leaves pixels[] null (not in 1.1) + 1.3 plus gl is a problem, since conflicting caches + gl has no need for a bufferedimage tho + so maybe checks to see if the cache is a BufferedImage + if it is, calls getPixels to set the int array + then replaces cache with glimageache + pappletgl loadimage could take care of this instead + calls super.loadImage(), if cache != null, proceed.. + this is prolly a mess +PImage.getPixels() and PImage.getPixels(x, y, w, h) -> + (the xywh version still allocates the entire array, but only updates those) + only needed for java2d + not (necessarily) needed when loading images, + but definitely needed when setting pixels on PGraphics +PImage.updatePixels() and PImage.updatePixels(x, y, w, h) + (this is actually just setModified) + in opengl, marks all or some as modified + so next time it's drawn, the texture is updated PGraphicsGL.image() + in java2d, updates the BufferedImage on next draw +can't use regular getPixels() on PGraphics, because its image isn't 'cache' + also, the cache may be used to draw the whole surface as a gl texture (?) + not a problem for the main PGraphics, but for any others created to draw on + +_ imageMode(CENTER) is weird for copy() and updatePixels() +_ perhaps copy() and get() ignore imageMode and use xywh or x1y1x2y2? +_ or disallow imageMode(CENTER) altogether? + +_ in java 1.3, getPixels() can call getRGB() via reflection +_ cache.getClass().getName().equals("BufferedImage") _ beginShape() _ don't allow you to draw stroked items unless stroke() is called @@ -50,32 +110,35 @@ _ get regular graphics engine working again _ smooth is no longer working _ ellipses aren't handled -_ look for size() method to determine default size of applet -_ (same as applet exporter function) -_ when using core graphics, don't show applet frame until first frame -_ (in opengl, open frame early, make sure this isn't inhibited) - _ default to single byte input from serial port _ and add serial.setBuffer() for message length as alternative _ or serial.setDelimiter() to fire message on delim _ move textMode and textSpace back out of PFont _ use die() to fail in font situations +_ can't, just use a RuntimeException _ die() may need to throw a RuntimeException -_ light(x, y, z, c1, c2, c3, TYPE) -_ also BLight with same constructor, and on() and off() fxn +_ make light() functions actually do something in PGraphicsGL +_ make lights half do something in PGraphics3 too + +_ bring in materials for opengl as well? +_ don't include a class, just make it similar to the light functions _ be consistent about getXxx() methods -// +_ on start, mouseX is 0.. how to avoid? +_ use firstMouse variable.. figure out naming + +// _ basic sample audio playback needed for p5 _ make separate java 1.1 and java 1.3 classes -_ on start, mouseX is 0.. how to avoid? -_ use firstMouse variable.. figure out naming +_ microphone input for java 1.3 +_ this may be reason to move sound classes out into a lib? +_ or maybe just microphone goes into its own library? _ image loading bug is huge _ figure out how to handle cached images, multiple images diff --git a/todo.txt b/todo.txt index cf427c645..daa1821dc 100644 --- a/todo.txt +++ b/todo.txt @@ -8,6 +8,45 @@ X make sure that fink is not in the path when building X what are the args to configure a release version? X update linux version of jikes +create a new sketch +create a new tab named "a" +create a new tab named "a_2" +hide tab named "a_2" +hide "a" +unhide "a_2" +unhide "a" +where did "a_2" go ? + +(v74) if a project folder is made (with save as), and then deleted while processing is still open, there is an error (of course). but the error ('file/folder not found') is not displayed to the user, and the drop-downs don't go away / the IDE doesn't refresh. + +(74) "save as" not actually saving properly +File>New +edit file... +File>Save As +File>Open some other file +File>Open original file +file is empty. +the only way to make File>Save As actually save new files, as far as i +can tell, is to Save As once, make at least one change, then Save. + +what happens if folder already exists on save as? + +_ look for size() method to determine default size of applet +_ (same as applet exporter function) +_ when using core graphics, don't show applet frame until first frame +_ (in opengl, open frame early, make sure this isn't inhibited) + +_ add tool to hit 'next' to go through examples +_ just make it "next file in folder" since examples are all over +_ also need to copy examples locally +_ add tool for running in jview +_ only available after export (or when an applet dir exists) +_ warn user that applet html will be over-written +_ add tool to "Add custom html to sketch" +_ that copies applet.html, +_ opens sketch folder, +_ and gives info about what to do next (how to edit) + _ examples need to be updated // @@ -77,15 +116,23 @@ _ underscoring everything is kinda nasty PROBLEMS FOR NEW USERS _ making it easier to draw shapes _ missing semicolons - better error message +_ missing brackets, unmatched brackets _ "unexpected token void" -> "You're mixing dynamic and static mode" _ forgetting the quotes around strings _ separate reference for /dev version +_ loadImage() mixed case problems +_ loadImage() using spaces in the name +_ if loadImage() when online(), throw an error +_ files not in the data folder (works in env, not in sketch) _ angleMode(DEGREES) -> mistyped keywords, caps being wrong _ NullPointerException on unterminated comment at end of code _ (and OutOfMemoryError and weird lockup) _ not enough args for triangle (or args in general) _ throws out bizarre message - +_ document for new users: +_ what's a NullPointerException +_ use of strings +_ println() for debugging TALK TO CASEY ABOUT... _ must call depth() for 3D applications @@ -121,6 +168,8 @@ _ implement and remove PdeEditorStatus stuff _ beginShape() defaults to beginShape(POLYGON) _ needs to be noted for the reference _ make a note that u/v coordinates clamp at 0 and 1 +_ no transformations before background() is called +_ implementation specific, may cause trouble _ different name for 'lib' folder because of libraries folder? _ avoid some confusion for when describing the libraries folder to users