1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-08-07 00:04:36 +03:00

Merging r327:r331 of the branches/processing-sync into the trunk. This adds the Processing core, and some new features including printing, copy for discourse, better auto-format, improved keyboard shortcuts, etc.

This commit is contained in:
David A. Mellis
2007-09-25 14:04:01 +00:00
parent 413b439974
commit 616d65d32a
40 changed files with 31946 additions and 779 deletions

8334
core/PApplet.java Normal file

File diff suppressed because it is too large Load Diff

322
core/PConstants.java Normal file
View File

@@ -0,0 +1,322 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2004-06 Ben Fry and Casey Reas
Copyright (c) 2001-04 Massachusetts Institute of Technology
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.
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.core;
import java.awt.Cursor;
import java.awt.event.KeyEvent;
/**
* Numbers shared throughout processing.core.
* <P>
* An attempt is made to keep the constants as short/non-verbose
* as possible. For instance, the constant is TIFF instead of
* FILE_TYPE_TIFF. We'll do this as long as we can get away with it.
*/
public interface PConstants {
// 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 SVG = "processing.dxf.PGraphicsSVG";
// platform IDs for PApplet.platform
static final int WINDOWS = 1;
static final int MACOS9 = 2;
static final int MACOSX = 3;
static final int LINUX = 4;
static final int OTHER = 0;
// for better parity between c++ version (at no speed cost)
static final float EPSILON = 0.0001f;
// was around for auto-port to mobile version
//static final float ONE = 1.0f;
// useful goodness
static final float PI = (float) Math.PI;
static final float HALF_PI = PI / 2.0f;
static final float THIRD_PI = PI / 3.0f;
static final float QUARTER_PI = PI / 4.0f;
static final float TWO_PI = PI * 2.0f;
static final float DEG_TO_RAD = PI/180.0f;
static final float RAD_TO_DEG = 180.0f/PI;
// angle modes
//static final int RADIANS = 0;
//static final int DEGREES = 1;
// used by split, all the standard whitespace chars
// (also includes unicode nbsp, that little bostage)
static final String WHITESPACE = " \t\n\r\f\u00A0";
// for colors and/or images
static final int RGB = 1; // image & color
static final int ARGB = 2; // image
static final int HSB = 3; // color
static final int ALPHA = 4; // image
// image file types
static final int TIFF = 0;
static final int TARGA = 1;
static final int JPEG = 2;
static final int GIF = 3;
// filter/convert types
static final int BLUR = 11;
static final int GRAY = 12;
static final int INVERT = 13;
static final int OPAQUE = 14;
static final int POSTERIZE = 15;
static final int THRESHOLD = 16;
static final int ERODE = 17;
static final int DILATE = 18;
// blend mode keyword definitions
// @see processing.core.PImage#blendColor(int,int,int)
public final static int REPLACE = 0;
public final static int BLEND = 1 << 0;
public final static int ADD = 1 << 1;
public final static int SUBTRACT = 1 << 2;
public final static int LIGHTEST = 1 << 3;
public final static int DARKEST = 1 << 4;
public final static int DIFFERENCE = 1 << 5;
public final static int EXCLUSION = 1 << 6;
public final static int MULTIPLY = 1 << 7;
public final static int SCREEN = 1 << 8;
public final static int OVERLAY = 1 << 9;
public final static int HARD_LIGHT = 1 << 10;
public final static int SOFT_LIGHT = 1 << 11;
public final static int DODGE = 1 << 12;
public final static int BURN = 1 << 13;
// colour component bitmasks
public static final int ALPHA_MASK = 0xff000000;
public static final int RED_MASK = 0x00ff0000;
public static final int GREEN_MASK = 0x0000ff00;
public static final int BLUE_MASK = 0x000000ff;
// for messages
static final int CHATTER = 0;
static final int COMPLAINT = 1;
static final int PROBLEM = 2;
// types of projection matrices
static final int CUSTOM = 0; // user-specified fanciness
static final int ORTHOGRAPHIC = 2; // 2D isometric projection
static final int PERSPECTIVE = 3; // perspective matrix
// rendering settings
static final float PIXEL_CENTER = 0.5f; // for polygon aa
// shapes
// the low four bits set the variety,
// higher bits set the specific shape type
static final int POINTS = (1 << 4) | 0;
static final int LINES = (1 << 5) | 0;
//static final int LINE_STRIP = (1 << 5) | 1;
//static final int LINE_LOOP = (1 << 5) | 2;
static final int TRIANGLES = (1 << 6) | 0;
static final int TRIANGLE_STRIP = (1 << 6) | 1;
static final int TRIANGLE_FAN = (1 << 6) | 2;
static final int QUADS = (1 << 7) | 0;
static final int QUAD_STRIP = (1 << 7) | 1;
static final int POLYGON = (1 << 8) | 0;
//static final int CONCAVE_POLYGON = (1 << 8) | 1;
//static final int CONVEX_POLYGON = (1 << 8) | 2;
static final int OPEN = 1;
static final int CLOSE = 2;
// shape drawing modes
/** Draw mode convention to use (x, y) to (width, height) */
static final int CORNER = 0;
/** Draw mode convention to use (x1, y1) to (x2, y2) coordinates */
static final int CORNERS = 1;
/** @deprecated Use RADIUS instead (as of 0125) */
static final int CENTER_RADIUS = 2;
/** Draw mode from the center, and using the radius */
static final int RADIUS = 2;
/** Draw from the center, using second pair of values as the diameter.
Formerly called CENTER_DIAMETER in alpha releases */
static final int CENTER = 3;
// vertically alignment modes for text
/** Default vertical alignment for text placement */
static final int BASELINE = 0;
/** Align text to the top */
static final int TOP = 101;
/** Align text from the bottom, using the baseline. */
static final int BOTTOM = 102;
// uv texture orientation modes
static final int NORMALIZED = 1; //_SPACE = 0; // 0..1
static final int IMAGE = 2;
// text placement modes
/**
* textMode(MODEL) is the default, meaning that characters
* will be affected by transformations like any other shapes.
* <p/>
* Changed value in 0093 to not interfere with LEFT, CENTER, and RIGHT.
*/
static final int MODEL = 4;
/**
* textMode(SHAPE) draws text using the the glyph outlines of
* individual characters rather than as textures. If the outlines are
* not available, then textMode(SHAPE) will be ignored and textMode(MODEL)
* will be used instead. For this reason, be sure to call textMode()
* <EM>after</EM> calling textFont().
* <p/>
* Currently, textMode(SHAPE) is only supported by OPENGL mode.
* It also requires Java 1.2 or higher (OPENGL requires 1.4 anyway)
*/
static final int SHAPE = 5;
// text alignment modes
// are inherited from LEFT, CENTER, RIGHT
// stroke modes
static final int SQUARE = 1 << 0; // called 'butt' in the svg spec
static final int ROUND = 1 << 1;
static final int PROJECT = 1 << 2; // called 'square' in the svg spec
static final int MITER = 1 << 3;
static final int BEVEL = 1 << 5;
// lighting
static final int AMBIENT = 0;
static final int DIRECTIONAL = 1;
static final int POINT = 2;
static final int SPOT = 3;
// key constants
// only including the most-used of these guys
// if people need more esoteric keys, they can learn about
// the esoteric java KeyEvent api and of virtual keys
// both key and keyCode will equal these values
// for 0125, these were changed to 'char' values, because they
// can be upgraded to ints automatically by Java, but having them
// as ints prevented split(blah, TAB) from working
static final char BACKSPACE = 8;
static final char TAB = 9;
static final char ENTER = 10;
static final char RETURN = 13;
static final char ESC = 27;
static final char DELETE = 127;
// i.e. if ((key == CODED) && (keyCode == UP))
static final int CODED = 0xffff;
// key will be CODED and keyCode will be this value
static final int UP = KeyEvent.VK_UP;
static final int DOWN = KeyEvent.VK_DOWN;
static final int LEFT = KeyEvent.VK_LEFT;
static final int RIGHT = KeyEvent.VK_RIGHT;
// key will be CODED and keyCode will be this value
static final int ALT = KeyEvent.VK_ALT;
static final int CONTROL = KeyEvent.VK_CONTROL;
static final int SHIFT = KeyEvent.VK_SHIFT;
// cursor types
static final int ARROW = Cursor.DEFAULT_CURSOR;
static final int CROSS = Cursor.CROSSHAIR_CURSOR;
static final int HAND = Cursor.HAND_CURSOR;
static final int MOVE = Cursor.MOVE_CURSOR;
static final int TEXT = Cursor.TEXT_CURSOR;
static final int WAIT = Cursor.WAIT_CURSOR;
// hints
//static final int SCALE_STROKE_WIDTH = 0;
//static final int LIGHTING_AFFECTS_STROKE = 1;
static final int ENABLE_NATIVE_FONTS = 2;
static final int DISABLE_TEXT_SMOOTH = 3;
//static final int DISABLE_SMOOTH_HACK = 4;
static final int DISABLE_DEPTH_TEST = 5;
static final int NO_FLYING_POO = 6;
static final int ENABLE_DEPTH_SORT = 7;
static final int DISABLE_ERROR_REPORT = 8;
static final int ENABLE_ACCURATE_TEXTURES = 9;
static final int HINT_COUNT = 10;
}

1019
core/PFont.java Normal file

File diff suppressed because it is too large Load Diff

4308
core/PGraphics.java Normal file

File diff suppressed because it is too large Load Diff

1672
core/PGraphics2D.java Normal file

File diff suppressed because it is too large Load Diff

3943
core/PGraphics3D.java Normal file

File diff suppressed because it is too large Load Diff

1381
core/PGraphicsJava2D.java Normal file

File diff suppressed because it is too large Load Diff

2598
core/PImage.java Normal file

File diff suppressed because it is too large Load Diff

1295
core/PLine.java Normal file

File diff suppressed because it is too large Load Diff

640
core/PMatrix.java Normal file
View File

@@ -0,0 +1,640 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://Proce55ing.net
Copyright (c) 2005-06 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.
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.core;
/**
* 4x4 matrix implementation.
*/
public final class PMatrix implements PConstants {
public float m00, m01, m02, m03;
public float m10, m11, m12, m13;
public float m20, m21, m22, m23;
public float m30, m31, m32, m33;
final static int DEFAULT_STACK_DEPTH = 0;
int maxStackDepth;
int stackPointer = 0;
float stack[][];
// locally allocated version to avoid creating new memory
static protected PMatrix inverseCopy;
public PMatrix() {
set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
maxStackDepth = DEFAULT_STACK_DEPTH;
}
public PMatrix(int stackDepth) {
set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
stack = new float[stackDepth][16];
maxStackDepth = stackDepth;
}
public PMatrix(float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33) {
set(m00, m01, m02, m03,
m10, m11, m12, m13,
m20, m21, m22, m23,
m30, m31, m32, m33);
maxStackDepth = DEFAULT_STACK_DEPTH;
}
// Make a copy of a matrix. We copy the stack depth,
// but we don't make a copy of the stack or the stack pointer.
public PMatrix(PMatrix src) {
set(src);
maxStackDepth = src.maxStackDepth;
stack = new float[maxStackDepth][16];
}
public void reset() {
set(1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
}
public void clearStack() {
stackPointer = 0;
}
public boolean push() {
if (stackPointer == maxStackDepth) return false;
stack[stackPointer][0] = m00;
stack[stackPointer][1] = m01;
stack[stackPointer][2] = m02;
stack[stackPointer][3] = m03;
stack[stackPointer][4] = m10;
stack[stackPointer][5] = m11;
stack[stackPointer][6] = m12;
stack[stackPointer][7] = m13;
stack[stackPointer][8] = m20;
stack[stackPointer][9] = m21;
stack[stackPointer][10] = m22;
stack[stackPointer][11] = m23;
stack[stackPointer][12] = m30;
stack[stackPointer][13] = m31;
stack[stackPointer][14] = m32;
stack[stackPointer][15] = m33;
stackPointer++;
return true;
}
public boolean pop() {
if (stackPointer == 0) return false;
stackPointer--;
m00 = stack[stackPointer][0];
m01 = stack[stackPointer][1];
m02 = stack[stackPointer][2];
m03 = stack[stackPointer][3];
m10 = stack[stackPointer][4];
m11 = stack[stackPointer][5];
m12 = stack[stackPointer][6];
m13 = stack[stackPointer][7];
m20 = stack[stackPointer][8];
m21 = stack[stackPointer][9];
m22 = stack[stackPointer][10];
m23 = stack[stackPointer][11];
m30 = stack[stackPointer][12];
m31 = stack[stackPointer][13];
m32 = stack[stackPointer][14];
m33 = stack[stackPointer][15];
return true;
}
public void set(PMatrix src) {
set(src.m00, src.m01, src.m02, src.m03,
src.m10, src.m11, src.m12, src.m13,
src.m20, src.m21, src.m22, src.m23,
src.m30, src.m31, src.m32, src.m33);
}
public void set(float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33) {
this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13;
this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33;
}
public void translate(float tx, float ty) {
translate(tx, ty, 0);
}
public void invTranslate(float tx, float ty) {
invTranslate(tx, ty, 0);
}
public void translate(float tx, float ty, float tz) {
m03 += tx*m00 + ty*m01 + tz*m02;
m13 += tx*m10 + ty*m11 + tz*m12;
m23 += tx*m20 + ty*m21 + tz*m22;
m33 += tx*m30 + ty*m31 + tz*m32;
}
public void invTranslate(float tx, float ty, float tz) {
preApply(1, 0, 0, -tx,
0, 1, 0, -ty,
0, 0, 1, -tz,
0, 0, 0, 1);
}
// OPT could save several multiplies for the 0s and 1s by just
// putting the multMatrix code here and removing uneccessary terms
public void rotateX(float angle) {
float c = cos(angle);
float s = sin(angle);
apply(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1);
}
public void invRotateX(float angle) {
float c = cos(-angle);
float s = sin(-angle);
preApply(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1);
}
public void rotateY(float angle) {
float c = cos(angle);
float s = sin(angle);
apply(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1);
}
public void invRotateY(float angle) {
float c = cos(-angle);
float s = sin(-angle);
preApply(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1);
}
/**
* Just calls rotateZ because two dimensional rotation
* is the same as rotating along the z-axis.
*/
public void rotate(float angle) {
rotateZ(angle);
}
public void invRotate(float angle) {
invRotateZ(angle);
}
public void rotateZ(float angle) {
float c = cos(angle);
float s = sin(angle);
apply(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
}
public void invRotateZ(float angle) {
float c = cos(-angle);
float s = sin(-angle);
preApply(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
}
public void rotate(float angle, float v0, float v1, float v2) {
// should be in radians (i think), instead of degrees (gl uses degrees)
// based on 15-463 code, but similar to opengl ref p.443
// TODO should make sure this vector is normalized
float c = cos(angle);
float s = sin(angle);
float t = 1.0f - c;
apply((t*v0*v0) + c, (t*v0*v1) - (s*v2), (t*v0*v2) + (s*v1), 0,
(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);
}
public void invRotate(float angle, float v0, float v1, float v2) {
// TODO should make sure this vector is normalized
float c = cos(-angle);
float s = sin(-angle);
float t = 1.0f - c;
preApply((t*v0*v0) + c, (t*v0*v1) - (s*v2), (t*v0*v2) + (s*v1), 0,
(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);
}
public void scale(float s) {
apply(s, 0, 0, 0, 0, s, 0, 0, 0, 0, s, 0, 0, 0, 0, 1);
}
public void invScale(float s) {
preApply(1/s, 0, 0, 0, 0, 1/s, 0, 0, 0, 0, 1/s, 0, 0, 0, 0, 1);
}
public void scale(float sx, float sy) {
apply(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
}
public void invScale(float sx, float sy) {
preApply(1/sx, 0, 0, 0, 0, 1/sy, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
}
// OPTIMIZE: same as above
public void scale(float x, float y, float z) {
apply(x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1);
}
public void invScale(float x, float y, float z) {
preApply(1/x, 0, 0, 0, 0, 1/y, 0, 0, 0, 0, 1/z, 0, 0, 0, 0, 1);
}
/*
public void transform(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 n30, float n31, float n32, float n33) {
apply(n00, n01, n02, n03,
n10, n11, n12, n13,
n20, n21, n22, n23,
n30, n31, n32, n33);
}
*/
public void preApply(PMatrix lhs) {
preApply(lhs.m00, lhs.m01, lhs.m02, lhs.m03,
lhs.m10, lhs.m11, lhs.m12, lhs.m13,
lhs.m20, lhs.m21, lhs.m22, lhs.m23,
lhs.m30, lhs.m31, lhs.m32, lhs.m33);
}
// for inverse operations, like multiplying the matrix on the left
public void preApply(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 n30, float n31, float n32, float n33) {
float r00 = n00*m00 + n01*m10 + n02*m20 + n03*m30;
float r01 = n00*m01 + n01*m11 + n02*m21 + n03*m31;
float r02 = n00*m02 + n01*m12 + n02*m22 + n03*m32;
float r03 = n00*m03 + n01*m13 + n02*m23 + n03*m33;
float r10 = n10*m00 + n11*m10 + n12*m20 + n13*m30;
float r11 = n10*m01 + n11*m11 + n12*m21 + n13*m31;
float r12 = n10*m02 + n11*m12 + n12*m22 + n13*m32;
float r13 = n10*m03 + n11*m13 + n12*m23 + n13*m33;
float r20 = n20*m00 + n21*m10 + n22*m20 + n23*m30;
float r21 = n20*m01 + n21*m11 + n22*m21 + n23*m31;
float r22 = n20*m02 + n21*m12 + n22*m22 + n23*m32;
float r23 = n20*m03 + n21*m13 + n22*m23 + n23*m33;
float r30 = n30*m00 + n31*m10 + n32*m20 + n33*m30;
float r31 = n30*m01 + n31*m11 + n32*m21 + n33*m31;
float r32 = n30*m02 + n31*m12 + n32*m22 + n33*m32;
float r33 = n30*m03 + n31*m13 + n32*m23 + n33*m33;
m00 = r00; m01 = r01; m02 = r02; m03 = r03;
m10 = r10; m11 = r11; m12 = r12; m13 = r13;
m20 = r20; m21 = r21; m22 = r22; m23 = r23;
m30 = r30; m31 = r31; m32 = r32; m33 = r33;
}
public boolean invApply(PMatrix rhs) {
PMatrix copy = new PMatrix(rhs);
PMatrix inverse = copy.invert();
if (inverse == null) return false;
preApply(inverse);
return true;
}
public boolean invApply(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 n30, float n31, float n32, float n33) {
if (inverseCopy == null) {
inverseCopy = new PMatrix();
}
inverseCopy.set(n00, n01, n02, n03,
n10, n11, n12, n13,
n20, n21, n22, n23,
n30, n31, n32, n33);
PMatrix inverse = inverseCopy.invert();
if (inverse == null) return false;
preApply(inverse);
return true;
}
public void apply(PMatrix rhs) {
apply(rhs.m00, rhs.m01, rhs.m02, rhs.m03,
rhs.m10, rhs.m11, rhs.m12, rhs.m13,
rhs.m20, rhs.m21, rhs.m22, rhs.m23,
rhs.m30, rhs.m31, rhs.m32, rhs.m33);
}
public void apply(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 n30, float n31, float n32, float n33) {
float r00 = m00*n00 + m01*n10 + m02*n20 + m03*n30;
float r01 = m00*n01 + m01*n11 + m02*n21 + m03*n31;
float r02 = m00*n02 + m01*n12 + m02*n22 + m03*n32;
float r03 = m00*n03 + m01*n13 + m02*n23 + m03*n33;
float r10 = m10*n00 + m11*n10 + m12*n20 + m13*n30;
float r11 = m10*n01 + m11*n11 + m12*n21 + m13*n31;
float r12 = m10*n02 + m11*n12 + m12*n22 + m13*n32;
float r13 = m10*n03 + m11*n13 + m12*n23 + m13*n33;
float r20 = m20*n00 + m21*n10 + m22*n20 + m23*n30;
float r21 = m20*n01 + m21*n11 + m22*n21 + m23*n31;
float r22 = m20*n02 + m21*n12 + m22*n22 + m23*n32;
float r23 = m20*n03 + m21*n13 + m22*n23 + m23*n33;
float r30 = m30*n00 + m31*n10 + m32*n20 + m33*n30;
float r31 = m30*n01 + m31*n11 + m32*n21 + m33*n31;
float r32 = m30*n02 + m31*n12 + m32*n22 + m33*n32;
float r33 = m30*n03 + m31*n13 + m32*n23 + m33*n33;
m00 = r00; m01 = r01; m02 = r02; m03 = r03;
m10 = r10; m11 = r11; m12 = r12; m13 = r13;
m20 = r20; m21 = r21; m22 = r22; m23 = r23;
m30 = r30; m31 = r31; m32 = r32; m33 = r33;
}
public void mult3(float vec[], float out[]) {
// must use these temp vars because vec may be the same as out
float tmpx = m00*vec[0] + m01*vec[1] + m02*vec[2] + m03;
float tmpy = m10*vec[0] + m11*vec[1] + m12*vec[2] + m13;
float tmpz = m20*vec[0] + m21*vec[1] + m22*vec[2] + m23;
out[0] = tmpx;
out[1] = tmpy;
out[2] = tmpz;
}
public void mult(float vec[], float out[]) {
// must use these temp vars because vec may be the same as out
float tmpx = m00*vec[0] + m01*vec[1] + m02*vec[2] + m03*vec[3];
float tmpy = m10*vec[0] + m11*vec[1] + m12*vec[2] + m13*vec[3];
float tmpz = m20*vec[0] + m21*vec[1] + m22*vec[2] + m23*vec[3];
float tmpw = m30*vec[0] + m31*vec[1] + m32*vec[2] + m33*vec[3];
out[0] = tmpx;
out[1] = tmpy;
out[2] = tmpz;
out[3] = tmpw;
}
/**
* @return the determinant of the matrix
*/
public float determinant() {
float f =
m00
* ((m11 * m22 * m33 + m12 * m23 * m31 + m13 * m21 * m32)
- m13 * m22 * m31
- m11 * m23 * m32
- m12 * m21 * m33);
f -= m01
* ((m10 * m22 * m33 + m12 * m23 * m30 + m13 * m20 * m32)
- m13 * m22 * m30
- m10 * m23 * m32
- m12 * m20 * m33);
f += m02
* ((m10 * m21 * m33 + m11 * m23 * m30 + m13 * m20 * m31)
- m13 * m21 * m30
- m10 * m23 * m31
- m11 * m20 * m33);
f -= m03
* ((m10 * m21 * m32 + m11 * m22 * m30 + m12 * m20 * m31)
- m12 * m21 * m30
- m10 * m22 * m31
- m11 * m20 * m32);
return f;
}
/**
* Calculate the determinant of a 3x3 matrix
* @return result
*/
private float determinant3x3(float t00, float t01, float t02,
float t10, float t11, float t12,
float t20, float t21, float t22) {
return (t00 * (t11 * t22 - t12 * t21) +
t01 * (t12 * t20 - t10 * t22) +
t02 * (t10 * t21 - t11 * t20));
}
public PMatrix transpose() {
float temp;
temp = m01; m01 = m10; m10 = temp;
temp = m02; m02 = m20; m20 = temp;
temp = m03; m03 = m30; m30 = temp;
temp = m12; m12 = m21; m21 = temp;
temp = m13; m13 = m31; m31 = temp;
temp = m23; m23 = m32; m32 = temp;
return this;
}
/**
* Invert this matrix
* @return this if successful, null otherwise
*/
public PMatrix invert() {
float determinant = determinant();
if (determinant != 0) {
// m00 m01 m02 m03
// m10 m11 m12 m13
// m20 m21 m22 m23
// m30 m31 m32 m33
float determinant_inv = 1f / determinant;
// first row
float t00 = determinant3x3(m11, m12, m13, m21, m22, m23, m31, m32, m33);
float t01 = -determinant3x3(m10, m12, m13, m20, m22, m23, m30, m32, m33);
float t02 = determinant3x3(m10, m11, m13, m20, m21, m23, m30, m31, m33);
float t03 = -determinant3x3(m10, m11, m12, m20, m21, m22, m30, m31, m32);
// second row
float t10 = -determinant3x3(m01, m02, m03, m21, m22, m23, m31, m32, m33);
float t11 = determinant3x3(m00, m02, m03, m20, m22, m23, m30, m32, m33);
float t12 = -determinant3x3(m00, m01, m03, m20, m21, m23, m30, m31, m33);
float t13 = determinant3x3(m00, m01, m02, m20, m21, m22, m30, m31, m32);
// third row
float t20 = determinant3x3(m01, m02, m03, m11, m12, m13, m31, m32, m33);
float t21 = -determinant3x3(m00, m02, m03, m10, m12, m13, m30, m32, m33);
float t22 = determinant3x3(m00, m01, m03, m10, m11, m13, m30, m31, m33);
float t23 = -determinant3x3(m00, m01, m02, m10, m11, m12, m30, m31, m32);
// fourth row
float t30 = -determinant3x3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
float t31 = determinant3x3(m00, m02, m03, m10, m12, m13, m20, m22, m23);
float t32 = -determinant3x3(m00, m01, m03, m10, m11, m13, m20, m21, m23);
float t33 = determinant3x3(m00, m01, m02, m10, m11, m12, m20, m21, m22);
// transpose and divide by the determinant
m00 = t00*determinant_inv;
m11 = t11*determinant_inv;
m22 = t22*determinant_inv;
m33 = t33*determinant_inv;
m01 = t10*determinant_inv;
m10 = t01*determinant_inv;
m20 = t02*determinant_inv;
m02 = t20*determinant_inv;
m12 = t21*determinant_inv;
m21 = t12*determinant_inv;
m03 = t30*determinant_inv;
m30 = t03*determinant_inv;
m13 = t31*determinant_inv;
m31 = t13*determinant_inv;
m32 = t23*determinant_inv;
m23 = t32*determinant_inv;
return this;
}
return null;
}
//////////////////////////////////////////////////////////////
public void print() {
int big = (int) Math.abs(max(max(max(max(abs(m00), abs(m01)),
max(abs(m02), abs(m03))),
max(max(abs(m10), abs(m11)),
max(abs(m12), abs(m13)))),
max(max(max(abs(m20), abs(m21)),
max(abs(m22), abs(m23))),
max(max(abs(m30), abs(m31)),
max(abs(m32), abs(m33))))));
// avoid infinite loop
if (Float.isNaN(big) || Float.isInfinite(big)) {
big = 1000000; // set to something arbitrary
}
int d = 1;
while ((big /= 10) != 0) d++; // cheap log()
System.out.println(PApplet.nfs(m00, d, 4) + " " +
PApplet.nfs(m01, d, 4) + " " +
PApplet.nfs(m02, d, 4) + " " +
PApplet.nfs(m03, d, 4));
System.out.println(PApplet.nfs(m10, d, 4) + " " +
PApplet.nfs(m11, d, 4) + " " +
PApplet.nfs(m12, d, 4) + " " +
PApplet.nfs(m13, d, 4));
System.out.println(PApplet.nfs(m20, d, 4) + " " +
PApplet.nfs(m21, d, 4) + " " +
PApplet.nfs(m22, d, 4) + " " +
PApplet.nfs(m23, d, 4));
System.out.println(PApplet.nfs(m30, d, 4) + " " +
PApplet.nfs(m31, d, 4) + " " +
PApplet.nfs(m32, d, 4) + " " +
PApplet.nfs(m33, d, 4));
System.out.println();
}
//////////////////////////////////////////////////////////////
private final float max(float a, float b) {
return (a > b) ? a : b;
}
private final float abs(float a) {
return (a < 0) ? -a : a;
}
private final float sin(float angle) {
return (float)Math.sin(angle);
}
private final float cos(float angle) {
return (float)Math.cos(angle);
}
}

772
core/PPolygon.java Normal file
View File

@@ -0,0 +1,772 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2004-06 Ben Fry and Casey Reas
Copyright (c) 2001-04 Massachusetts Institute of Technology
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.
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.core;
/**
* zbuffer polygon rendering object for PGraphics.
* <P>
* Likely to be removed before 1.0 as it's no longer particularly used.
*/
public class PPolygon implements PConstants {
// identical to the constants from PGraphics
static final int X = 0; // transformed xyzw
static final int Y = 1; // formerly SX SY SZ
static final int Z = 2;
static final int R = 3; // actual rgb, after lighting
static final int G = 4; // fill stored here, transform in place
static final int B = 5;
static final int A = 6;
static final int U = 7; // texture
static final int V = 8;
//
static final int DEFAULT_SIZE = 64; // this is needed for spheres
float vertices[][] = new float[DEFAULT_SIZE][PGraphics.VERTEX_FIELD_COUNT];
int vertexCount;
// really this is "debug" but..
static final boolean FRY = false;
// after some fiddling, this seems to produce the best results
//static final int ZBUFFER_MIN_COVERAGE = 204;
float r[] = new float[DEFAULT_SIZE]; // storage used by incrementalize
float dr[] = new float[DEFAULT_SIZE];
float l[] = new float[DEFAULT_SIZE]; // more storage for incrementalize
float dl[] = new float[DEFAULT_SIZE];
float sp[] = new float[DEFAULT_SIZE]; // temporary storage for scanline
float sdp[] = new float[DEFAULT_SIZE];
// color and xyz are always interpolated
boolean interpX;
boolean interpZ;
boolean interpUV; // is this necessary? could just check timage != null
boolean interpARGB;
int rgba;
int r2, g2, b2, a2, a2orig;
boolean noDepthTest;
PGraphics parent;
int pixels[];
// the parent's width/height,
// or if smooth is enabled, parent's w/h scaled
// up by the smooth dimension
int width, height;
int width1, height1;
PImage timage;
int tpixels[];
int theight, twidth;
int theight1, twidth1;
int tformat;
// temp fix to behave like SMOOTH_IMAGES
boolean texture_smooth;
// for anti-aliasing
static final int SUBXRES = 8;
static final int SUBXRES1 = 7;
static final int SUBYRES = 8;
static final int SUBYRES1 = 7;
static final int MAX_COVERAGE = SUBXRES * SUBYRES;
boolean smooth;
int firstModY;
int lastModY;
int lastY;
int aaleft[] = new int[SUBYRES];
int aaright[] = new int[SUBYRES];
int aaleftmin, aarightmin;
int aaleftmax, aarightmax;
int aaleftfull, aarightfull;
final private int MODYRES(int y) {
return (y & SUBYRES1);
}
public PPolygon(PGraphics iparent) {
parent = iparent;
reset(0);
}
public void reset(int count) {
vertexCount = count;
interpX = true;
interpZ = true;
interpUV = false;
interpARGB = true;
timage = null;
}
public float[] nextVertex() {
if (vertexCount == vertices.length) {
//parent.message(CHATTER, "re-allocating for " +
// (vertexCount*2) + " vertices");
float temp[][] = new float[vertexCount<<1][PGraphics.VERTEX_FIELD_COUNT];
System.arraycopy(vertices, 0, temp, 0, vertexCount);
vertices = temp;
r = new float[vertices.length];
dr = new float[vertices.length];
l = new float[vertices.length];
dl = new float[vertices.length];
sp = new float[vertices.length];
sdp = new float[vertices.length];
}
return vertices[vertexCount++]; // returns v[0], sets vc to 1
}
/**
* Return true if this vertex is redundant. If so, will also
* decrement the vertex count.
*/
/*
public boolean redundantVertex(float x, float y, float z) {
// because vertexCount will be 2 when setting vertex[1]
if (vertexCount < 2) return false;
// vertexCount-1 is the current vertex that would be used
// vertexCount-2 would be the previous feller
if ((Math.abs(vertices[vertexCount-2][MX] - x) < EPSILON) &&
(Math.abs(vertices[vertexCount-2][MY] - y) < EPSILON) &&
(Math.abs(vertices[vertexCount-2][MZ] - z) < EPSILON)) {
vertexCount--;
return true;
}
return false;
}
*/
public void texture(PImage image) {
this.timage = image;
this.tpixels = image.pixels;
this.twidth = image.width;
this.theight = image.height;
this.tformat = image.format;
twidth1 = twidth - 1;
theight1 = theight - 1;
interpUV = true;
}
public void render() {
if (vertexCount < 3) return;
// these may have changed due to a resize()
// so they should be refreshed here
pixels = parent.pixels;
//zbuffer = parent.zbuffer;
noDepthTest = parent.hints[DISABLE_DEPTH_TEST];
smooth = parent.smooth;
// by default, text turns on smooth for the textures
// themselves. but this should be shut off if the hint
// for DISABLE_TEXT_SMOOTH is set.
texture_smooth = (//parent.drawing_text &&
!parent.hints[DISABLE_TEXT_SMOOTH]);
width = smooth ? parent.width*SUBXRES : parent.width;
height = smooth ? parent.height*SUBYRES : parent.height;
width1 = width - 1;
height1 = height - 1;
if (!interpARGB) {
r2 = (int) (vertices[0][R] * 255);
g2 = (int) (vertices[0][G] * 255);
b2 = (int) (vertices[0][B] * 255);
a2 = (int) (vertices[0][A] * 255);
a2orig = a2; // save an extra copy
rgba = 0xff000000 | (r2 << 16) | (g2 << 8) | b2;
}
for (int i = 0; i < vertexCount; i++) {
r[i] = 0; dr[i] = 0; l[i] = 0; dl[i] = 0;
}
// hack to not make polygons fly into the screen
if (parent.hints[NO_FLYING_POO]) {
float nwidth2 = -width * 2;
float nheight2 = -height * 2;
float width2 = width * 2;
float height2 = height * 2;
for (int i = 0; i < vertexCount; i++) {
if ((vertices[i][X] < nwidth2) ||
(vertices[i][X] > width2) ||
(vertices[i][Y] < nheight2) ||
(vertices[i][Y] > height2)) {
return; // this is a bad poly
}
}
}
if (smooth) {
for (int i = 0; i < vertexCount; i++) {
vertices[i][X] *= SUBXRES;
vertices[i][Y] *= SUBYRES;
}
firstModY = -1;
}
// find top vertex (y is zero at top, higher downwards)
int topi = 0;
float ymin = vertices[0][Y];
float ymax = vertices[0][Y]; // fry 031001
for (int i = 1; i < vertexCount; i++) {
if (vertices[i][Y] < ymin) {
ymin = vertices[i][Y];
topi = i;
}
if (vertices[i][Y] > ymax) ymax = vertices[i][Y];
}
// the last row is an exceptional case, because there won't
// necessarily be 8 rows of subpixel lines that will force
// the final line to render. so instead, the algo keeps track
// of the lastY (in subpixel resolution) that will be rendered
// and that will force a scanline to happen the same as
// every eighth in the other situations
//lastY = -1; // fry 031001
lastY = (int) (ymax - 0.5f); // global to class bc used by other fxns
int lefti = topi; // li, index of left vertex
int righti = topi; // ri, index of right vertex
int y = (int) (ymin + 0.5f); // current scan line
int lefty = y - 1; // lower end of left edge
int righty = y - 1; // lower end of right edge
interpX = true;
int remaining = vertexCount;
// scan in y, activating new edges on left & right
// as scan line passes over new vertices
while (remaining > 0) {
// advance left edge?
while ((lefty <= y) && (remaining > 0)) {
remaining--;
// step ccw down left side
int i = (lefti != 0) ? (lefti-1) : (vertexCount-1);
incrementalize_y(vertices[lefti], vertices[i], l, dl, y);
lefty = (int) (vertices[i][Y] + 0.5f);
lefti = i;
}
// advance right edge?
while ((righty <= y) && (remaining > 0)) {
remaining--;
// step cw down right edge
int i = (righti != vertexCount-1) ? (righti + 1) : 0;
incrementalize_y(vertices[righti], vertices[i], r, dr, y);
righty = (int) (vertices[i][Y] + 0.5f);
righti = i;
}
// do scanlines till end of l or r edge
while (y < lefty && y < righty) {
// this doesn't work because it's not always set here
//if (remaining == 0) {
//lastY = (lefty < righty) ? lefty-1 : righty-1;
//System.out.println("lastY is " + lastY);
//}
if ((y >= 0) && (y < height)) {
//try { // hopefully this bug is fixed
if (l[X] <= r[X]) scanline(y, l, r);
else scanline(y, r, l);
//} catch (ArrayIndexOutOfBoundsException e) {
//e.printStackTrace();
//}
}
y++;
// this increment probably needs to be different
// UV and RGB shouldn't be incremented until line is emitted
increment(l, dl);
increment(r, dr);
}
}
//if (smooth) {
//System.out.println("y/lasty/lastmody = " + y + " " + lastY + " " + lastModY);
//}
}
public void unexpand() {
if (smooth) {
for (int i = 0; i < vertexCount; i++) {
vertices[i][X] /= SUBXRES;
vertices[i][Y] /= SUBYRES;
}
}
}
private void scanline(int y, float l[], float r[]) {
//System.out.println("scanline " + y);
for (int i = 0; i < vertexCount; i++) { // should be moved later
sp[i] = 0; sdp[i] = 0;
}
// this rounding doesn't seem to be relevant with smooth
int lx = (int) (l[X] + 0.49999f); // ceil(l[X]-.5);
if (lx < 0) lx = 0;
int rx = (int) (r[X] - 0.5f);
if (rx > width1) rx = width1;
if (lx > rx) return;
if (smooth) {
int mody = MODYRES(y);
aaleft[mody] = lx;
aaright[mody] = rx;
if (firstModY == -1) {
firstModY = mody;
aaleftmin = lx; aaleftmax = lx;
aarightmin = rx; aarightmax = rx;
} else {
if (aaleftmin > aaleft[mody]) aaleftmin = aaleft[mody];
if (aaleftmax < aaleft[mody]) aaleftmax = aaleft[mody];
if (aarightmin > aaright[mody]) aarightmin = aaright[mody];
if (aarightmax < aaright[mody]) aarightmax = aaright[mody];
}
lastModY = mody; // moved up here (before the return) 031001
// not the eighth (or lastY) line, so not scanning this time
if ((mody != SUBYRES1) && (y != lastY)) return;
//lastModY = mody; // eeK! this was missing
//return;
//if (y == lastY) {
//System.out.println("y is lasty");
//}
//lastModY = mody;
aaleftfull = aaleftmax/SUBXRES + 1;
aarightfull = aarightmin/SUBXRES - 1;
}
// this is the setup, based on lx
incrementalize_x(l, r, sp, sdp, lx);
// scan in x, generating pixels
// using parent.width to get actual pixel index
// rather than scaled by smooth factor
int offset = smooth ? parent.width * (y / SUBYRES) : parent.width*y;
int truelx = 0, truerx = 0;
if (smooth) {
truelx = lx / SUBXRES;
truerx = (rx + SUBXRES1) / SUBXRES;
lx = aaleftmin / SUBXRES;
rx = (aarightmax + SUBXRES1) / SUBXRES;
if (lx < 0) lx = 0;
if (rx > parent.width1) rx = parent.width1;
}
interpX = false;
int tr, tg, tb, ta;
for (int x = lx; x <= rx; x++) {
// added == because things on same plane weren't replacing each other
// makes for strangeness in 3D, but totally necessary for 2D
//if (noDepthTest || (sp[Z] <= zbuffer[offset+x])) {
if (true) {
// map texture based on U, V coords in sp[U] and sp[V]
if (interpUV) {
int tu = (int)sp[U];
int tv = (int)sp[V];
if (tu > twidth1) tu = twidth1;
if (tv > theight1) tv = theight1;
if (tu < 0) tu = 0;
if (tv < 0) tv = 0;
int txy = tv*twidth + tu;
if (smooth || texture_smooth) {
//if (FRY) System.out.println("sp u v = " + sp[U] + " " + sp[V]);
//System.out.println("sp u v = " + sp[U] + " " + sp[V]);
// tuf1/tvf1 is the amount of coverage for the adjacent
// pixel, which is the decimal percentage.
int tuf1 = (int) (255f * (sp[U] - (float)tu));
int tvf1 = (int) (255f * (sp[V] - (float)tv));
// the closer sp[U or V] is to the decimal being zero
// the more coverage it should get of the original pixel
int tuf = 255 - tuf1;
int tvf = 255 - tvf1;
// this code sucks! filled with bugs and slow as hell!
int pixel00 = tpixels[txy];
int pixel01 = (tv < theight1) ?
tpixels[txy + twidth] : tpixels[txy];
int pixel10 = (tu < twidth1) ?
tpixels[txy + 1] : tpixels[txy];
int pixel11 = ((tv < theight1) && (tu < twidth1)) ?
tpixels[txy + twidth + 1] : tpixels[txy];
int p00, p01, p10, p11;
int px0, px1; //, pxy;
if (tformat == ALPHA) {
px0 = (pixel00*tuf + pixel10*tuf1) >> 8;
px1 = (pixel01*tuf + pixel11*tuf1) >> 8;
ta = (((px0*tvf + px1*tvf1) >> 8) *
(interpARGB ? ((int) (sp[A]*255)) : a2orig)) >> 8;
} else if (tformat == ARGB) {
p00 = (pixel00 >> 24) & 0xff;
p01 = (pixel01 >> 24) & 0xff;
p10 = (pixel10 >> 24) & 0xff;
p11 = (pixel11 >> 24) & 0xff;
px0 = (p00*tuf + p10*tuf1) >> 8;
px1 = (p01*tuf + p11*tuf1) >> 8;
ta = (((px0*tvf + px1*tvf1) >> 8) *
(interpARGB ? ((int) (sp[A]*255)) : a2orig)) >> 8;
} else { // RGB image, no alpha
ta = interpARGB ? ((int) (sp[A]*255)) : a2orig;
}
if ((tformat == RGB) || (tformat == ARGB)) {
p00 = (pixel00 >> 16) & 0xff; // red
p01 = (pixel01 >> 16) & 0xff;
p10 = (pixel10 >> 16) & 0xff;
p11 = (pixel11 >> 16) & 0xff;
px0 = (p00*tuf + p10*tuf1) >> 8;
px1 = (p01*tuf + p11*tuf1) >> 8;
tr = (((px0*tvf + px1*tvf1) >> 8) *
(interpARGB ? ((int) sp[R]*255) : r2)) >> 8;
p00 = (pixel00 >> 8) & 0xff; // green
p01 = (pixel01 >> 8) & 0xff;
p10 = (pixel10 >> 8) & 0xff;
p11 = (pixel11 >> 8) & 0xff;
px0 = (p00*tuf + p10*tuf1) >> 8;
px1 = (p01*tuf + p11*tuf1) >> 8;
tg = (((px0*tvf + px1*tvf1) >> 8) *
(interpARGB ? ((int) sp[G]*255) : g2)) >> 8;
p00 = pixel00 & 0xff; // blue
p01 = pixel01 & 0xff;
p10 = pixel10 & 0xff;
p11 = pixel11 & 0xff;
px0 = (p00*tuf + p10*tuf1) >> 8;
px1 = (p01*tuf + p11*tuf1) >> 8;
tb = (((px0*tvf + px1*tvf1) >> 8) *
(interpARGB ? ((int) sp[B]*255) : b2)) >> 8;
} else { // alpha image, only use current fill color
if (interpARGB) {
tr = (int) (sp[R] * 255);
tg = (int) (sp[G] * 255);
tb = (int) (sp[B] * 255);
} else {
tr = r2;
tg = g2;
tb = b2;
}
}
// get coverage for pixel if smooth
// checks smooth again here because of
// hints[SMOOTH_IMAGES] used up above
int weight = smooth ? coverage(x) : 255;
if (weight != 255) ta = ta*weight >> 8;
} else { // no smooth, just get the pixels
int tpixel = tpixels[txy];
// TODO i doubt splitting these guys really gets us
// all that much speed.. is it worth it?
if (tformat == ALPHA) {
ta = tpixel;
if (interpARGB) {
tr = (int) sp[R]*255;
tg = (int) sp[G]*255;
tb = (int) sp[B]*255;
if (sp[A] != 1) {
ta = (((int) sp[A]*255) * ta) >> 8;
}
} else {
tr = r2;
tg = g2;
tb = b2;
ta = (a2orig * ta) >> 8;
}
} else { // RGB or ARGB
ta = (tformat == RGB) ? 255 : (tpixel >> 24) & 0xff;
if (interpARGB) {
tr = (((int) sp[R]*255) * ((tpixel >> 16) & 0xff)) >> 8;
tg = (((int) sp[G]*255) * ((tpixel >> 8) & 0xff)) >> 8;
tb = (((int) sp[B]*255) * ((tpixel) & 0xff)) >> 8;
ta = (((int) sp[A]*255) * ta) >> 8;
} else {
tr = (r2 * ((tpixel >> 16) & 0xff)) >> 8;
tg = (g2 * ((tpixel >> 8) & 0xff)) >> 8;
tb = (b2 * ((tpixel) & 0xff)) >> 8;
ta = (a2orig * ta) >> 8;
}
}
}
if ((ta == 254) || (ta == 255)) { // if (ta & 0xf8) would be good
// no need to blend
pixels[offset+x] = 0xff000000 | (tr << 16) | (tg << 8) | tb;
//zbuffer[offset+x] = sp[Z];
} else {
// blend with pixel on screen
int a1 = 255-ta;
int r1 = (pixels[offset+x] >> 16) & 0xff;
int g1 = (pixels[offset+x] >> 8) & 0xff;
int b1 = (pixels[offset+x]) & 0xff;
pixels[offset+x] = 0xff000000 |
(((tr*ta + r1*a1) >> 8) << 16) |
((tg*ta + g1*a1) & 0xff00) |
((tb*ta + b1*a1) >> 8);
//if (ta > ZBUFFER_MIN_COVERAGE) zbuffer[offset+x] = sp[Z];
}
} else { // no image applied
int weight = smooth ? coverage(x) : 255;
if (interpARGB) {
r2 = (int) (sp[R] * 255);
g2 = (int) (sp[G] * 255);
b2 = (int) (sp[B] * 255);
if (sp[A] != 1) weight = (weight * ((int) (sp[A] * 255))) >> 8;
if (weight == 255) {
rgba = 0xff000000 | (r2 << 16) | (g2 << 8) | b2;
}
} else {
if (a2orig != 255) weight = (weight * a2orig) >> 8;
}
if (weight == 255) {
// no blend, no aa, just the rgba
pixels[offset+x] = rgba;
//zbuffer[offset+x] = sp[Z];
} else {
int r1 = (pixels[offset+x] >> 16) & 0xff;
int g1 = (pixels[offset+x] >> 8) & 0xff;
int b1 = (pixels[offset+x]) & 0xff;
a2 = weight;
int a1 = 255 - a2;
pixels[offset+x] = (0xff000000 |
((r1*a1 + r2*a2) >> 8) << 16 |
// use & instead of >> and << below
((g1*a1 + g2*a2) >> 8) << 8 |
((b1*a1 + b2*a2) >> 8));
//if (a2 > ZBUFFER_MIN_COVERAGE) zbuffer[offset+x] = sp[Z];
}
}
}
// if smooth enabled, don't increment values
// for the pixel in the stretch out version
// of the scanline used to get smooth edges.
if (!smooth || ((x >= truelx) && (x <= truerx))) {
increment(sp, sdp);
}
}
firstModY = -1;
interpX = true;
}
// x is in screen, not huge 8x coordinates
private int coverage(int x) {
if ((x >= aaleftfull) && (x <= aarightfull) &&
// important since not all SUBYRES lines may have been covered
(firstModY == 0) && (lastModY == SUBYRES1)) {
return 255;
}
int pixelLeft = x*SUBXRES; // huh?
int pixelRight = pixelLeft + 8;
int amt = 0;
for (int i = firstModY; i <= lastModY; i++) {
if ((aaleft[i] > pixelRight) || (aaright[i] < pixelLeft)) {
continue;
}
// does this need a +1 ?
amt += ((aaright[i] < pixelRight ? aaright[i] : pixelRight) -
(aaleft[i] > pixelLeft ? aaleft[i] : pixelLeft));
}
amt <<= 2;
return (amt == 256) ? 255 : amt;
}
private void incrementalize_y(float p1[], float p2[],
float p[], float dp[], int y) {
float delta = p2[Y] - p1[Y];
if (delta == 0) delta = 1;
float fraction = y + 0.5f - p1[Y];
if (interpX) {
dp[X] = (p2[X] - p1[X]) / delta;
p[X] = p1[X] + dp[X] * fraction;
}
if (interpZ) {
dp[Z] = (p2[Z] - p1[Z]) / delta;
p[Z] = p1[Z] + dp[Z] * fraction;
}
if (interpARGB) {
dp[R] = (p2[R] - p1[R]) / delta;
dp[G] = (p2[G] - p1[G]) / delta;
dp[B] = (p2[B] - p1[B]) / delta;
dp[A] = (p2[A] - p1[A]) / delta;
p[R] = p1[R] + dp[R] * fraction;
p[G] = p1[G] + dp[G] * fraction;
p[B] = p1[B] + dp[B] * fraction;
p[A] = p1[A] + dp[A] * fraction;
}
if (interpUV) {
dp[U] = (p2[U] - p1[U]) / delta;
dp[V] = (p2[V] - p1[V]) / delta;
//if (smooth) {
//p[U] = p1[U]; //+ dp[U] * fraction;
//p[V] = p1[V]; //+ dp[V] * fraction;
//} else {
p[U] = p1[U] + dp[U] * fraction;
p[V] = p1[V] + dp[V] * fraction;
//}
if (FRY) System.out.println("inc y p[U] p[V] = " + p[U] + " " + p[V]);
}
}
private void incrementalize_x(float p1[], float p2[],
float p[], float dp[], int x) {
float delta = p2[X] - p1[X];
if (delta == 0) delta = 1;
float fraction = x + 0.5f - p1[X];
if (smooth) {
delta /= SUBXRES;
fraction /= SUBXRES;
}
if (interpX) {
dp[X] = (p2[X] - p1[X]) / delta;
p[X] = p1[X] + dp[X] * fraction;
}
if (interpZ) {
dp[Z] = (p2[Z] - p1[Z]) / delta;
p[Z] = p1[Z] + dp[Z] * fraction;
}
if (interpARGB) {
dp[R] = (p2[R] - p1[R]) / delta;
dp[G] = (p2[G] - p1[G]) / delta;
dp[B] = (p2[B] - p1[B]) / delta;
dp[A] = (p2[A] - p1[A]) / delta;
p[R] = p1[R] + dp[R] * fraction;
p[G] = p1[G] + dp[G] * fraction;
p[B] = p1[B] + dp[B] * fraction;
p[A] = p1[A] + dp[A] * fraction;
}
if (interpUV) {
if (FRY) System.out.println("delta, frac = " + delta + ", " + fraction);
dp[U] = (p2[U] - p1[U]) / delta;
dp[V] = (p2[V] - p1[V]) / delta;
//if (smooth) {
//p[U] = p1[U];
// offset for the damage that will be done by the
// 8 consecutive calls to scanline
// agh.. this won't work b/c not always 8 calls before render
// maybe lastModY - firstModY + 1 instead?
if (FRY) System.out.println("before inc x p[V] = " + p[V] + " " + p1[V] + " " + p2[V]);
//p[V] = p1[V] - SUBXRES1 * fraction;
//} else {
p[U] = p1[U] + dp[U] * fraction;
p[V] = p1[V] + dp[V] * fraction;
//}
}
}
private void increment(float p[], float dp[]) {
if (interpX) p[X] += dp[X];
if (interpZ) p[Z] += dp[Z];
if (interpARGB) {
p[R] += dp[R];
p[G] += dp[G];
p[B] += dp[B];
p[A] += dp[A];
}
if (interpUV) {
if (FRY) System.out.println("increment() " + p[V] + " " + dp[V]);
p[U] += dp[U];
p[V] += dp[V];
}
}
}

289
core/PShape.java Normal file
View File

@@ -0,0 +1,289 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2006 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.
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.core;
// take a look at the obj loader to see how this fits with things
// PShape.line() PShape.ellipse()?
// PShape s = beginShape()
// line()
// endShape(s)
public class PShape {
int kind;
PMatrix matrix;
int[] opcode;
int opcodeCount;
// need to reorder vertex fields to make a VERTEX_SHORT_COUNT
// that puts all the non-rendering fields into later indices
float[][] data; // second param is the VERTEX_FIELD_COUNT
// should this be called vertices (consistent with PGraphics internals)
// or does that hurt flexibility?
int childCount;
PShape[] children;
// POINTS, LINES, xLINE_STRIP, xLINE_LOOP
// TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN
// QUADS, QUAD_STRIP
// xPOLYGON
static final int PATH = 1; // POLYGON, LINE_LOOP, LINE_STRIP
static final int GROUP = 2;
// how to handle rectmode/ellipsemode?
// are they bitshifted into the constant?
// CORNER, CORNERS, CENTER, (CENTER_RADIUS?)
static final int RECT = 3; // could just be QUAD, but would be x1/y1/x2/y2
static final int ELLIPSE = 4;
static final int VERTEX = 7;
static final int CURVE = 5;
static final int BEZIER = 6;
// fill and stroke functions will need a pointer to the parent
// PGraphics object.. may need some kind of createShape() fxn
// or maybe the values are stored until draw() is called?
// attaching images is very tricky.. it's a different type of data
// material parameters will be thrown out,
// except those currently supported (kinds of lights)
// setAxis -> .x and .y to move x and y coords of origin
public float x;
public float y;
// pivot point for transformations
public float px;
public float py;
public PShape() {
}
public PShape(float x, float y) {
this.x = x;
this.y = y;
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
/**
* Called by the following (the shape() command adds the g)
* PShape s = loadShapes("blah.svg");
* shape(s);
*/
public void draw(PGraphics g) {
boolean flat = g instanceof PGraphics3D;
if (matrix != null) {
g.pushMatrix();
if (flat) {
g.applyMatrix(matrix.m00, matrix.m01, matrix.m02,
matrix.m10, matrix.m11, matrix.m12);
} else {
g.applyMatrix(matrix.m00, matrix.m01, matrix.m02, matrix.m03,
matrix.m10, matrix.m11, matrix.m12, matrix.m13,
matrix.m20, matrix.m21, matrix.m22, matrix.m23,
matrix.m30, matrix.m31, matrix.m32, matrix.m33);
}
}
// if g subclasses PGraphics2, ignore all lighting stuff and z coords
// otherwise if PGraphics3, need to call diffuse() etc
// unfortunately, also a problem with no way to encode stroke/fill
// being enabled/disabled.. this quickly gets into just having opcodes
// for the entire api, to deal with things like textures and images
switch (kind) {
case PATH:
for (int i = 0; i < opcodeCount; i++) {
switch (opcode[i]) {
case VERTEX:
break;
}
}
break;
case GROUP:
break;
case RECT:
break;
}
if (matrix != null) {
g.popMatrix();
}
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
// can't be 'add' because that suggests additive geometry
public void addChild(PShape who) {
}
public PShape createGroup() {
PShape group = new PShape();
group.kind = GROUP;
addChild(group);
return group;
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
// translate, rotate, scale, apply (no push/pop)
// these each call matrix.translate, etc
// if matrix is null when one is called,
// it is created and set to identity
public void translate(float tx, float ty) {
translate(tx, ty, 0);
}
public void translate(float tx, float ty, float tz) {
checkMatrix();
matrix.translate(tx, ty, 0);
}
//
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);
}
public void rotate(float angle) {
rotateZ(angle);
}
public void rotate(float angle, float v0, float v1, float v2) {
checkMatrix();
matrix.rotate(angle, v0, v1, v2);
}
//
public void scale(float s) {
scale(s, s, s);
}
public void scale(float sx, float sy) {
scale(sx, sy, 1);
}
public void scale(float x, float y, float z) {
checkMatrix();
matrix.scale(x, y, z);
}
//
public void applyMatrix(float n00, float n01, float n02,
float n10, float n11, float n12) {
checkMatrix();
matrix.apply(n00, n01, n02, 0,
n10, n11, n12, 0,
0, 0, 1, 0,
0, 0, 0, 1);
}
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 n30, float n31, float n32, float n33) {
checkMatrix();
matrix.apply(n00, n01, n02, n03,
n10, n11, n12, n13,
n20, n21, n22, n23,
n30, n31, n32, n33);
}
//
protected void checkMatrix() {
if (matrix == null) {
matrix = new PMatrix();
}
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
/**
* Center the shape based on its bounding box. Can't assume
* that the bounding box is 0, 0, width, height. Common case will be
* opening a letter size document in Illustrator, and drawing something
* in the middle, then reading it in as an svg file.
* This will also need to flip the y axis (scale(1, -1)) in cases
* like Adobe Illustrator where the coordinates start at the bottom.
*/
public void center() {
}
/**
* Set the pivot point for all transformations.
*/
public void pivot(float x, float y) {
px = x;
py = y;
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
}

3827
core/PTriangle.java Normal file

File diff suppressed because it is too large Load Diff