mirror of
https://github.com/processing/processing4.git
synced 2026-02-10 09:09:26 +01:00
on the road to hell
This commit is contained in:
@@ -60,11 +60,7 @@ public interface PConstants {
|
||||
// for better parity between c++ version (at no speed cost)
|
||||
|
||||
static final float EPSILON = 0.0001f;
|
||||
static final float TWO = 2.0f;
|
||||
static final float ONE = 1.0f;
|
||||
static final float HALF = 0.5f;
|
||||
static final float TFF = 255.0f;
|
||||
static final float MAX_FLOAT = Float.MAX_VALUE;
|
||||
|
||||
|
||||
// useful goodness
|
||||
|
||||
@@ -236,8 +236,8 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
-3, 3, 0, 0,
|
||||
1, 0, 0, 0);
|
||||
|
||||
protected float bezier_forward[][]; // = new float[4][4];
|
||||
protected float bezier_draw[][]; // = new float[4][4];
|
||||
protected float bezierForwardMatrix[][]; // = new float[4][4];
|
||||
protected float bezierDrawMatrix[][]; // = new float[4][4];
|
||||
|
||||
// ........................................................
|
||||
|
||||
@@ -598,8 +598,8 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
public void defaults() { // ignore
|
||||
//System.out.println("PGraphics.defaults() " + width + " " + height);
|
||||
|
||||
colorMode(RGB, TFF);
|
||||
fill(TFF);
|
||||
colorMode(RGB, 255);
|
||||
fill(255);
|
||||
stroke(0);
|
||||
// other stroke attributes are set in the initializers
|
||||
// inside the class (see above, strokeWeight = 1 et al)
|
||||
@@ -993,6 +993,14 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of generic spline vertex, will add coords to
|
||||
* the splineVertices[] array and emit calls to draw segments
|
||||
* as needed (every fourth point for bezier or every point starting
|
||||
* with the fourth for catmull-rom).
|
||||
* @param z z-coordinate, set to MAX_VALUE if it's 2D
|
||||
* @param bezier true if it's a bezier instead of catmull-rom
|
||||
*/
|
||||
protected void splineVertex(float x, float y, float z, boolean bezier) {
|
||||
// to improve processing applet load times, don't allocate
|
||||
// space for the vertex data until actual use
|
||||
@@ -1053,10 +1061,10 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
if (splineVertexCount > 3) {
|
||||
if (bezier) {
|
||||
if ((splineVertexCount % 4) == 0) {
|
||||
if (!bezierInited) bezier_init();
|
||||
if (!bezierInited) bezierInit();
|
||||
splineSegment(splineVertexCount-4,
|
||||
splineVertexCount-4,
|
||||
bezier_draw, dimensions,
|
||||
bezierDrawMatrix, dimensions,
|
||||
bezierDetail);
|
||||
}
|
||||
} else { // catmull-rom curve (!bezier)
|
||||
@@ -1070,103 +1078,9 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
protected void bezier_vertex(float x, float y) {
|
||||
vertexCount = 0;
|
||||
|
||||
if (splineVertices == null) {
|
||||
splineVertices = new float[DEFAULT_SPLINE_VERTICES][VERTEX_FIELD_COUNT];
|
||||
}
|
||||
|
||||
// if more than 128 points, shift everything back to the beginning
|
||||
if (splineVertexCount == DEFAULT_SPLINE_VERTICES) {
|
||||
System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES - 3], 0,
|
||||
splineVertices[0], 0, VERTEX_FIELD_COUNT);
|
||||
System.arraycopy(splineVertices[DEFAULT_SPLINE_VERTICES - 2], 0,
|
||||
splineVertices[1], 0, VERTEX_FIELD_COUNT);
|
||||
splineVertexCount = 3;
|
||||
}
|
||||
splineVertices[splineVertexCount][MX] = x;
|
||||
splineVertices[splineVertexCount][MY] = y;
|
||||
splineVertexCount++;
|
||||
|
||||
switch (shape) {
|
||||
case LINE_LOOP:
|
||||
case LINE_STRIP:
|
||||
case POLYGON:
|
||||
if (splineVertexCount == 1) {
|
||||
path.moveTo(x, y);
|
||||
|
||||
} else if (splineVertexCount >= 4) {
|
||||
path.curveTo(splineVertices[splineVertexCount-3][MX],
|
||||
splineVertices[splineVertexCount-3][MY],
|
||||
splineVertices[splineVertexCount-2][MX],
|
||||
splineVertices[splineVertexCount-2][MY],
|
||||
x, y);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("bezierVertex() can only be used with " +
|
||||
"LINE_LOOP and POLYGON shapes");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
public void bezierVertex(float x1, float y1, float z1,
|
||||
float x2, float y2, float z2,
|
||||
float x3, float y3, float z3) {
|
||||
depthErrorXYZ("bezierVertex");
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* See notes with the curve() function.
|
||||
*/
|
||||
/*
|
||||
public void curveVertex(float x, float y) {
|
||||
//throw new RuntimeException("curveVertex() temporarily disabled");
|
||||
// TODO get matrix setup happening
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* See notes with the curve() function.
|
||||
*/
|
||||
/*
|
||||
public void curveVertex(float x, float y, float z) {
|
||||
depthErrorXYZ("curveVertex");
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
abstract public void endShape();
|
||||
/*
|
||||
shape = 0;
|
||||
|
||||
switch (shape) {
|
||||
case LINE_STRIP:
|
||||
stroke_shape(path);
|
||||
break;
|
||||
|
||||
case LINE_LOOP:
|
||||
path.closePath();
|
||||
stroke_shape(path);
|
||||
break;
|
||||
|
||||
case POLYGON:
|
||||
path.closePath();
|
||||
draw_shape(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1210,43 +1124,6 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// STROKE/FILL/DRAW
|
||||
|
||||
|
||||
/*
|
||||
//protected void fill_shape(Shape s) {
|
||||
protected void fill_shape(Path s) {
|
||||
if (fill) {
|
||||
//graphics.setColor(fillColorObject);
|
||||
//graphics.fill(s);
|
||||
}
|
||||
}
|
||||
|
||||
//protected void stroke_shape(Shape s) {
|
||||
protected void stroke_shape(Path s) {
|
||||
if (stroke) {
|
||||
//graphics.setColor(strokeColorObject);
|
||||
//graphics.draw(s);
|
||||
}
|
||||
}
|
||||
|
||||
//protected void draw_shape(Shape s) {
|
||||
protected void draw_shape(Path s) {
|
||||
if (fill) {
|
||||
//graphics.setColor(fillColorObject);
|
||||
//graphics.fill(s);
|
||||
}
|
||||
if (stroke) {
|
||||
//graphics.setColor(strokeColorObject);
|
||||
//graphics.draw(s);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// SIMPLE SHAPES WITH ANALOGUES IN beginShape()
|
||||
@@ -1353,12 +1230,7 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
|
||||
|
||||
protected void rectImpl(float x1, float y1, float x2, float y2) {
|
||||
beginShape(QUADS);
|
||||
vertex(x1, y1);
|
||||
vertex(x2, y1);
|
||||
vertex(x2, y2);
|
||||
vertex(x1, y2);
|
||||
endShape();
|
||||
quad(x1, y1, x2, y1, x2, y2, x1, y2);
|
||||
}
|
||||
|
||||
|
||||
@@ -1408,8 +1280,76 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
}
|
||||
|
||||
|
||||
protected void ellipseImpl(float x, float y, float w, float h) {
|
||||
// TODO draw an ellipse
|
||||
protected void ellipseImpl(float x1, float y1, float w, float h) {
|
||||
float hradius = w / 2f;
|
||||
float vradius = h / 2f;
|
||||
|
||||
float centerX = x1 + hradius;
|
||||
float centerY = y1 + 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 accuracy = (int)(4+Math.sqrt(hradius+vradius)*3);
|
||||
|
||||
// [toxi031031] adapted to use new lookup tables
|
||||
float inc = (float)SINCOS_LENGTH / accuracy;
|
||||
|
||||
float val = 0;
|
||||
/*
|
||||
beginShape(POLYGON);
|
||||
for (int i = 0; i < cAccuracy; i++) {
|
||||
vertex(centerX + cosLUT[(int) val] * hradius,
|
||||
centerY + sinLUT[(int) val] * vradius);
|
||||
val += inc;
|
||||
}
|
||||
endShape();
|
||||
*/
|
||||
|
||||
if (fill) {
|
||||
boolean savedStroke = stroke;
|
||||
stroke = false;
|
||||
|
||||
beginShape(TRIANGLE_FAN);
|
||||
normal(0, 0, 1);
|
||||
vertex(centerX, centerY);
|
||||
for (int i = 0; i < accuracy; i++) {
|
||||
vertex(centerX + cosLUT[(int) val] * hradius,
|
||||
centerY + sinLUT[(int) val] * vradius);
|
||||
val += inc;
|
||||
}
|
||||
// back to the beginning
|
||||
vertex(centerX + cosLUT[0] * hradius,
|
||||
centerY + sinLUT[0] * vradius);
|
||||
endShape();
|
||||
|
||||
stroke = savedStroke;
|
||||
}
|
||||
|
||||
if (stroke) {
|
||||
boolean savedFill = fill;
|
||||
fill = false;
|
||||
|
||||
val = 0;
|
||||
beginShape(LINE_LOOP);
|
||||
for (int i = 0; i < accuracy; i++) {
|
||||
vertex(centerX + cosLUT[(int) val] * hradius,
|
||||
centerY + sinLUT[(int) val] * vradius);
|
||||
val += inc;
|
||||
}
|
||||
endShape();
|
||||
|
||||
fill = savedFill;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1457,15 +1397,75 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
}
|
||||
|
||||
|
||||
protected void arcImpl(float x, float y, float w, float h,
|
||||
/**
|
||||
* 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 arcImpl(float x1, float y1, float w, float h,
|
||||
float start, float stop) {
|
||||
float hr = w / 2f;
|
||||
float vr = h / 2f;
|
||||
|
||||
float centerX = x1 + hr;
|
||||
float centerY = y1 + vr;
|
||||
|
||||
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(centerX, centerY);
|
||||
int increment = 1; // what's a good algorithm? stopLUT - startLUT;
|
||||
for (int i = startLUT; i < stopLUT; i += increment) {
|
||||
int ii = i % SINCOS_LENGTH;
|
||||
vertex(centerX + cosLUT[ii] * hr,
|
||||
centerY + sinLUT[ii] * vr);
|
||||
}
|
||||
// draw last point explicitly for accuracy
|
||||
vertex(centerX + cosLUT[stopLUT % SINCOS_LENGTH] * hr,
|
||||
centerY + 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(centerX + cosLUT[ii] * hr,
|
||||
centerY + sinLUT[ii] * vr);
|
||||
}
|
||||
// draw last point explicitly for accuracy
|
||||
vertex(centerX + cosLUT[stopLUT % SINCOS_LENGTH] * hr,
|
||||
centerY + sinLUT[stopLUT % SINCOS_LENGTH] * vr);
|
||||
endShape();
|
||||
|
||||
fill = savedFill;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// 3D SHAPES
|
||||
// BOX & SPHERE
|
||||
|
||||
|
||||
public void box(float size) {
|
||||
@@ -1488,7 +1488,7 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// CURVES
|
||||
// BEZIER
|
||||
|
||||
|
||||
/**
|
||||
@@ -1538,25 +1538,25 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
}
|
||||
|
||||
|
||||
protected void bezier_init() {
|
||||
protected void bezierInit() {
|
||||
bezierDetail(bezierDetail);
|
||||
}
|
||||
|
||||
|
||||
public void bezierDetail(int detail) {
|
||||
if (bezier_forward == null) {
|
||||
bezier_forward = new float[4][4];
|
||||
bezier_draw = new float[4][4];
|
||||
if (bezierForwardMatrix == null) {
|
||||
bezierForwardMatrix = new float[4][4];
|
||||
bezierDrawMatrix = new float[4][4];
|
||||
}
|
||||
bezierDetail = detail;
|
||||
bezierInited = true;
|
||||
|
||||
// setup matrix for forward differencing to speed up drawing
|
||||
setup_spline_forward(detail, bezier_forward);
|
||||
setup_spline_forward(detail, bezierForwardMatrix);
|
||||
|
||||
// multiply the basis and forward diff matrices together
|
||||
// saves much time since this needn't be done for each curve
|
||||
mult_spline_matrix(bezier_forward, bezier_basis, bezier_draw, 4);
|
||||
mult_spline_matrix(bezierForwardMatrix, bezier_basis, bezierDrawMatrix, 4);
|
||||
}
|
||||
|
||||
|
||||
@@ -1598,12 +1598,20 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
float x2, float y2, float z2,
|
||||
float x3, float y3, float z3,
|
||||
float x4, float y4, float z4) {
|
||||
depthErrorXYZ("bezier");
|
||||
beginShape(LINE_STRIP);
|
||||
vertex(x1, y1, z1);
|
||||
bezierVertex(x2, y2, z2,
|
||||
x3, y3, z3,
|
||||
x4, y4, z4);
|
||||
endShape();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// CATMULL-ROM CURVE
|
||||
|
||||
|
||||
/**
|
||||
* Get a location along a catmull-rom curve segment.
|
||||
@@ -1733,12 +1741,20 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
float x2, float y2, float z2,
|
||||
float x3, float y3, float z3,
|
||||
float x4, float y4, float z4) {
|
||||
depthErrorXYZ("curve");
|
||||
beginShape(LINE_STRIP);
|
||||
curveVertex(x1, y1, z1);
|
||||
curveVertex(x2, y2, z2);
|
||||
curveVertex(x3, y3, z3);
|
||||
curveVertex(x4, y4, z4);
|
||||
endShape();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// SPLINE UTILITY FUNCTIONS (used by both Bezier and Catmull-Rom)
|
||||
|
||||
|
||||
/**
|
||||
* Setup forward-differencing matrix to be used for speedy
|
||||
@@ -1988,12 +2004,57 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
/**
|
||||
* Expects x1, y1, x2, y2 coordinates where (x2 >= x1) and (y2 >= y1).
|
||||
* If tint() has been called, the image will be colored.
|
||||
* <p/>
|
||||
* The default implementation draws an image as a textured quad.
|
||||
* The (u, v) coordinates are in image space (they're ints, after all..)
|
||||
*/
|
||||
protected void imageImpl(PImage image,
|
||||
float x1, float y1, float x2, float y2,
|
||||
int u1, int v1, int u2, int v2) {
|
||||
// TODO blit an image to the screen
|
||||
System.err.println("unimplemented imageImpl() in PGraphics");
|
||||
boolean savedStroke = stroke;
|
||||
boolean savedFill = fill;
|
||||
int savedTextureMode = textureMode;
|
||||
|
||||
stroke = false;
|
||||
fill = true;
|
||||
textureMode = IMAGE;
|
||||
|
||||
float savedFillR = fillR;
|
||||
float savedFillG = fillG;
|
||||
float savedFillB = fillB;
|
||||
float savedFillA = fillA;
|
||||
|
||||
if (tint) {
|
||||
fillR = tintR;
|
||||
fillG = tintG;
|
||||
fillB = tintB;
|
||||
fillA = tintA;
|
||||
|
||||
} else {
|
||||
fillR = 1;
|
||||
fillG = 1;
|
||||
fillB = 1;
|
||||
fillA = 1;
|
||||
}
|
||||
|
||||
//System.out.println(fill + " " + fillR + " " + fillG + " " + fillB);
|
||||
|
||||
beginShape(QUADS);
|
||||
texture(image);
|
||||
vertex(x1, y1, u1, v1);
|
||||
vertex(x1, y2, u1, v2);
|
||||
vertex(x2, y2, u2, v2);
|
||||
vertex(x2, y1, u2, v1);
|
||||
endShape();
|
||||
|
||||
stroke = savedStroke;
|
||||
fill = savedFill;
|
||||
textureMode = savedTextureMode;
|
||||
|
||||
fillR = savedFillR;
|
||||
fillG = savedFillG;
|
||||
fillB = savedFillB;
|
||||
fillA = savedFillA;
|
||||
}
|
||||
|
||||
|
||||
@@ -2531,11 +2592,13 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
}
|
||||
|
||||
|
||||
// ........................................................
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
// what was this for?
|
||||
//font.getStringBounds(text, g2.getFontRenderContext()).getWidth();
|
||||
|
||||
|
||||
protected void textCharImpl(char ch, float x, float y) { //, float z) {
|
||||
int index = textFont.index(ch);
|
||||
if (index == -1) return;
|
||||
|
||||
@@ -47,7 +47,7 @@ public class PGraphics2D extends PGraphics {
|
||||
|
||||
PLine line;
|
||||
|
||||
boolean untransformed;
|
||||
//boolean untransformed;
|
||||
boolean strokeChanged = true;
|
||||
boolean fillChanged = true;
|
||||
|
||||
@@ -217,7 +217,7 @@ public class PGraphics2D extends PGraphics {
|
||||
int vertexCount = polygon.vertexCount;
|
||||
float vertices[][] = polygon.vertices;
|
||||
|
||||
if (untransformed) {
|
||||
if (untransformed()) {
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
vertices[i][X] = vertices[i][MX];
|
||||
vertices[i][Y] = vertices[i][MY];
|
||||
@@ -255,7 +255,7 @@ public class PGraphics2D extends PGraphics {
|
||||
|
||||
switch (shape) {
|
||||
case POINTS:
|
||||
if (untransformed && (strokeWeight == 1)) {
|
||||
if (untransformed() && (strokeWeight == 1)) {
|
||||
if (!strokeChanged) {
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
thin_point((int) vertices[i][X], (int) vertices[i][Y],
|
||||
@@ -697,7 +697,7 @@ public class PGraphics2D extends PGraphics {
|
||||
int x2 = (int) x2f;
|
||||
int y2 = (int) y2f;
|
||||
|
||||
rectImplFillUnRGB(x1, y1, x2, y2);
|
||||
rectImplFillUntranSolidRGB(x1, y1, x2, y2);
|
||||
|
||||
if (stroke) {
|
||||
if (strokeWeight == 1) {
|
||||
@@ -732,7 +732,7 @@ public class PGraphics2D extends PGraphics {
|
||||
/**
|
||||
* Draw an untransformed rectangle with no alpha.
|
||||
*/
|
||||
private void rectImplFillUnRGB(int x1, int y1, int x2, int y2) {
|
||||
private void rectImplFillUntranSolidRGB(int x1, int y1, int x2, int y2) {
|
||||
//System.out.println("flat quad");
|
||||
if (y2 < y1) {
|
||||
int temp = y1; y1 = y2; y2 = temp;
|
||||
@@ -744,50 +744,409 @@ public class PGraphics2D extends PGraphics {
|
||||
if ((x1 > width1) || (x2 < 0) ||
|
||||
(y1 > height1) || (y2 < 0)) return;
|
||||
|
||||
if (fill) {
|
||||
int fx1 = x1;
|
||||
int fy1 = y1;
|
||||
int fx2 = x2;
|
||||
int fy2 = y2;
|
||||
|
||||
// these only affect the fill, not the stroke
|
||||
// (otherwise strange boogers at edges b/c frame changes shape)
|
||||
if (fx1 < 0) fx1 = 0;
|
||||
if (fx2 > width) fx2 = width;
|
||||
if (fy1 < 0) fy1 = 0;
|
||||
if (fy2 > height) fy2 = height;
|
||||
|
||||
// [toxi 031223]
|
||||
// on avg. 20-25% faster fill routine using System.arraycopy()
|
||||
int ww = fx2 - fx1;
|
||||
int hh = fy2 - fy1;
|
||||
int[] row = new int[ww];
|
||||
for (int i = 0; i < ww; i++) row[i] = fillColor;
|
||||
int idx = fy1 * width + fx1;
|
||||
for (int y = 0; y < hh; y++) {
|
||||
System.arraycopy(row, 0, pixels, idx, ww);
|
||||
idx += width;
|
||||
}
|
||||
row = null;
|
||||
//if (fill) {
|
||||
int fx1 = x1;
|
||||
int fy1 = y1;
|
||||
int fx2 = x2;
|
||||
int fy2 = y2;
|
||||
|
||||
// these only affect the fill, not the stroke
|
||||
// (otherwise strange boogers at edges b/c frame changes shape)
|
||||
if (fx1 < 0) fx1 = 0;
|
||||
if (fx2 > width) fx2 = width;
|
||||
if (fy1 < 0) fy1 = 0;
|
||||
if (fy2 > height) fy2 = height;
|
||||
|
||||
// [toxi 031223]
|
||||
// on avg. 20-25% faster fill routine using System.arraycopy()
|
||||
int ww = fx2 - fx1;
|
||||
int hh = fy2 - fy1;
|
||||
int[] row = new int[ww];
|
||||
for (int i = 0; i < ww; i++) row[i] = fillColor;
|
||||
int idx = fy1 * width + fx1;
|
||||
for (int y = 0; y < hh; y++) {
|
||||
System.arraycopy(row, 0, pixels, idx, ww);
|
||||
idx += width;
|
||||
}
|
||||
row = null;
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// RECT
|
||||
// ELLIPSE AND ARC
|
||||
|
||||
|
||||
public void ellipseImpl(float x1, float y1, float w, float h) {
|
||||
if (!smooth && (strokeWeight == 1) &&
|
||||
!fillAlpha && !strokeAlpha && untransformed()) {
|
||||
float hradius = w / 2f;
|
||||
float vradius = h / 2f;
|
||||
|
||||
int centerX = (int) (x1 + hradius);
|
||||
int centerY = (int) (y1 + vradius);
|
||||
|
||||
if (hradius == vradius) {
|
||||
flat_circle(centerX, centerY, (int)hradius);
|
||||
|
||||
} else {
|
||||
flat_ellipse(centerX, centerY, (int)hradius, (int)vradius);
|
||||
}
|
||||
} else {
|
||||
super.ellipseImpl(x1, y1, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void flat_circle(int centerX, int centerY, int radius) {
|
||||
if (unwarped()) {
|
||||
float x = m00*centerX + m01*centerY + m02;
|
||||
float y = m10*centerX + m11*centerY + m12;
|
||||
centerX = (int)x;
|
||||
centerY = (int)y;
|
||||
}
|
||||
if (fill) flat_circle_fill(centerX, centerY, radius);
|
||||
if (stroke) flat_circle_stroke(centerX, centerY, radius);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw the outline around a flat circle using a bresenham-style
|
||||
* algorithm. Adapted from drawCircle function in "Computer Graphics
|
||||
* for Java Programmers" by Leen Ammeraal, p. 110.
|
||||
* <P/>
|
||||
* This function is included because the quality is so much better,
|
||||
* and the drawing significantly faster than with adaptive ellipses
|
||||
* drawn using the sine/cosine tables.
|
||||
* <P/>
|
||||
* Circle quadrants break down like so:
|
||||
* <PRE>
|
||||
* |
|
||||
* \ NNW | NNE /
|
||||
* \ | /
|
||||
* WNW \ | / ENE
|
||||
* -------------------
|
||||
* WSW / | \ ESE
|
||||
* / | \
|
||||
* / SSW | SSE \
|
||||
* |
|
||||
* </PRE>
|
||||
* @param xc x center
|
||||
* @param yc y center
|
||||
* @param r radius
|
||||
*/
|
||||
private void flat_circle_stroke(int xC, int yC, int r) {
|
||||
int x = 0, y = r, u = 1, v = 2 * r - 1, E = 0;
|
||||
while (x < y) {
|
||||
thin_point(xC + x, yC + y, 0, strokeColor); // NNE
|
||||
thin_point(xC + y, yC - x, 0, strokeColor); // ESE
|
||||
thin_point(xC - x, yC - y, 0, strokeColor); // SSW
|
||||
thin_point(xC - y, yC + x, 0, strokeColor); // WNW
|
||||
|
||||
x++; E += u; u += 2;
|
||||
if (v < 2 * E) {
|
||||
y--; E -= v; v -= 2;
|
||||
}
|
||||
if (x > y) break;
|
||||
|
||||
thin_point(xC + y, yC + x, 0, strokeColor); // ENE
|
||||
thin_point(xC + x, yC - y, 0, strokeColor); // SSE
|
||||
thin_point(xC - y, yC - x, 0, strokeColor); // WSW
|
||||
thin_point(xC - x, yC + y, 0, strokeColor); // NNW
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Heavily adapted version of the above algorithm that handles
|
||||
* filling the ellipse. Works by drawing from the center and
|
||||
* outwards to the points themselves. Has to be done this way
|
||||
* because the values for the points are changed halfway through
|
||||
* the function, making it impossible to just store a series of
|
||||
* left and right edges to be drawn more quickly.
|
||||
*
|
||||
* @param xc x center
|
||||
* @param yc y center
|
||||
* @param r radius
|
||||
*/
|
||||
private void flat_circle_fill(int xc, int yc, int r) {
|
||||
int x = 0, y = r, u = 1, v = 2 * r - 1, E = 0;
|
||||
while (x < y) {
|
||||
for (int xx = xc; xx < xc + x; xx++) { // NNE
|
||||
thin_point(xx, yc + y, 0, fillColor);
|
||||
}
|
||||
for (int xx = xc; xx < xc + y; xx++) { // ESE
|
||||
thin_point(xx, yc - x, 0, fillColor);
|
||||
}
|
||||
for (int xx = xc - x; xx < xc; xx++) { // SSW
|
||||
thin_point(xx, yc - y, 0, fillColor);
|
||||
}
|
||||
for (int xx = xc - y; xx < xc; xx++) { // WNW
|
||||
thin_point(xx, yc + x, 0, fillColor);
|
||||
}
|
||||
|
||||
x++; E += u; u += 2;
|
||||
if (v < 2 * E) {
|
||||
y--; E -= v; v -= 2;
|
||||
}
|
||||
if (x > y) break;
|
||||
|
||||
for (int xx = xc; xx < xc + y; xx++) { // ENE
|
||||
thin_point(xx, yc + x, 0, fillColor);
|
||||
}
|
||||
for (int xx = xc; xx < xc + x; xx++) { // SSE
|
||||
thin_point(xx, yc - y, 0, fillColor);
|
||||
}
|
||||
for (int xx = xc - y; xx < xc; xx++) { // WSW
|
||||
thin_point(xx, yc - x, 0, fillColor);
|
||||
}
|
||||
for (int xx = xc - x; xx < xc; xx++) { // NNW
|
||||
thin_point(xx, yc + y, 0, fillColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unfortunately this can't handle fill and stroke simultaneously,
|
||||
// because the fill will later replace some of the stroke points
|
||||
|
||||
private final void flat_ellipse_symmetry(int centerX, int centerY,
|
||||
int ellipseX, int ellipseY,
|
||||
boolean filling) {
|
||||
if (filling) {
|
||||
for (int i = centerX - ellipseX + 1; i < centerX + ellipseX; i++) {
|
||||
thin_point(i, centerY - ellipseY, 0, fillColor);
|
||||
thin_point(i, centerY + ellipseY, 0, fillColor);
|
||||
}
|
||||
} else {
|
||||
thin_point(centerX - ellipseX, centerY + ellipseY, 0, strokeColor);
|
||||
thin_point(centerX + ellipseX, centerY + ellipseY, 0, strokeColor);
|
||||
thin_point(centerX - ellipseX, centerY - ellipseY, 0, strokeColor);
|
||||
thin_point(centerX + ellipseX, centerY - ellipseY, 0, strokeColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bresenham-style ellipse drawing function, adapted from a posting to
|
||||
* comp.graphics.algortihms.
|
||||
*
|
||||
* This function is included because the quality is so much better,
|
||||
* and the drawing significantly faster than with adaptive ellipses
|
||||
* drawn using the sine/cosine tables.
|
||||
*
|
||||
* @param centerX x coordinate of the center
|
||||
* @param centerY y coordinate of the center
|
||||
* @param a horizontal radius
|
||||
* @param b vertical radius
|
||||
*/
|
||||
private void flat_ellipse_internal(int centerX, int centerY,
|
||||
int a, int b, boolean filling) {
|
||||
int x, y, a2, b2, s, t;
|
||||
|
||||
a2 = a*a;
|
||||
b2 = b*b;
|
||||
x = 0;
|
||||
y = b;
|
||||
s = a2*(1-2*b) + 2*b2;
|
||||
t = b2 - 2*a2*(2*b-1);
|
||||
flat_ellipse_symmetry(centerX, centerY, x, y, filling);
|
||||
|
||||
do {
|
||||
if (s < 0) {
|
||||
s += 2*b2*(2*x+3);
|
||||
t += 4*b2*(x+1);
|
||||
x++;
|
||||
} else if (t < 0) {
|
||||
s += 2*b2*(2*x+3) - 4*a2*(y-1);
|
||||
t += 4*b2*(x+1) - 2*a2*(2*y-3);
|
||||
x++;
|
||||
y--;
|
||||
} else {
|
||||
s -= 4*a2*(y-1);
|
||||
t -= 2*a2*(2*y-3);
|
||||
y--;
|
||||
}
|
||||
flat_ellipse_symmetry(centerX, centerY, x, y, filling);
|
||||
|
||||
} while (y > 0);
|
||||
}
|
||||
|
||||
|
||||
private void flat_ellipse(int centerX, int centerY, int a, int b) {
|
||||
if (unwarped()) {
|
||||
float x = m00*centerX + m01*centerY + m02;
|
||||
float y = m10*centerX + m11*centerY + m12;
|
||||
centerX = (int)x;
|
||||
centerY = (int)y;
|
||||
}
|
||||
if (fill) flat_ellipse_internal(centerX, centerY, a, b, true);
|
||||
if (stroke) flat_ellipse_internal(centerX, centerY, a, b, false);
|
||||
}
|
||||
|
||||
|
||||
// TODO really need a decent arc function in here..
|
||||
|
||||
//protected void arcImpl(float x1, float y1, float w, float h,
|
||||
// float start, float stop)
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// RENDERING
|
||||
// BOX & SPHERE
|
||||
|
||||
|
||||
// The PGraphics superclass will throw errors for these fellas
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// BEZIER & CURVE
|
||||
|
||||
|
||||
public void bezier(float x1, float y1, float z1,
|
||||
float x2, float y2, float z2,
|
||||
float x3, float y3, float z3,
|
||||
float x4, float y4, float z4) {
|
||||
depthErrorXYZ("bezier");
|
||||
}
|
||||
|
||||
|
||||
public void curve(float x1, float y1, float z1,
|
||||
float x2, float y2, float z2,
|
||||
float x3, float y3, float z3,
|
||||
float x4, float y4, float z4) {
|
||||
depthErrorXYZ("curve");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// IMAGE
|
||||
|
||||
|
||||
protected void imageImpl(PImage image,
|
||||
float x1, float y1, float x2, float y2,
|
||||
int u1, int v1, int u2, int v2) {
|
||||
if ((x2 - x1 == image.width) &&
|
||||
(y2 - y1 == image.height) &&
|
||||
!tint && unwarped()) {
|
||||
flat_image(image, (int) (x1 + m02), (int) (y1 + m12), u1, v1, u2, v2);
|
||||
|
||||
} else {
|
||||
super.imageImpl(image, x1, y1, x2, y2, u1, v1, u2, v2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Image drawn in flat "screen space", with no scaling or warping.
|
||||
* this is so common that a special routine is included for it,
|
||||
* because the alternative is much slower.
|
||||
*
|
||||
* @param image image to be drawn
|
||||
* @param sx1 x coordinate of upper-lefthand corner in screen space
|
||||
* @param sy1 y coordinate of upper-lefthand corner in screen space
|
||||
*/
|
||||
private void flat_image(PImage image, int sx1, int sy1,
|
||||
int ix1, int iy1, int ix2, int iy2) {
|
||||
/*
|
||||
int ix1 = 0;
|
||||
int iy1 = 0;
|
||||
int ix2 = image.width;
|
||||
int iy2 = image.height;
|
||||
*/
|
||||
|
||||
if (imageMode == CENTER) {
|
||||
sx1 -= image.width / 2;
|
||||
sy1 -= image.height / 2;
|
||||
}
|
||||
|
||||
int sx2 = sx1 + image.width;
|
||||
int sy2 = sy1 + image.height;
|
||||
|
||||
// don't draw if completely offscreen
|
||||
// (without this check, ArrayIndexOutOfBoundsException)
|
||||
if ((sx1 > width1) || (sx2 < 0) ||
|
||||
(sy1 > height1) || (sy2 < 0)) return;
|
||||
|
||||
if (sx1 < 0) { // off left edge
|
||||
ix1 -= sx1;
|
||||
sx1 = 0;
|
||||
}
|
||||
if (sy1 < 0) { // off top edge
|
||||
iy1 -= sy1;
|
||||
sy1 = 0;
|
||||
}
|
||||
if (sx2 > width) { // off right edge
|
||||
ix2 -= sx2 - width;
|
||||
sx2 = width;
|
||||
}
|
||||
if (sy2 > height) { // off bottom edge
|
||||
iy2 -= sy2 - height;
|
||||
sy2 = height;
|
||||
}
|
||||
|
||||
int source = iy1 * image.width + ix1;
|
||||
int target = sy1 * width;
|
||||
|
||||
if (image.format == ARGB) {
|
||||
for (int y = sy1; y < sy2; y++) {
|
||||
int tx = 0;
|
||||
|
||||
for (int x = sx1; x < sx2; x++) {
|
||||
pixels[target + x] =
|
||||
_blend(pixels[target + x],
|
||||
image.pixels[source + tx],
|
||||
image.pixels[source + tx++] >>> 24);
|
||||
}
|
||||
source += image.width;
|
||||
target += width;
|
||||
}
|
||||
} else if (image.format == ALPHA) {
|
||||
for (int y = sy1; y < sy2; y++) {
|
||||
int tx = 0;
|
||||
|
||||
for (int x = sx1; x < sx2; x++) {
|
||||
pixels[target + x] =
|
||||
_blend(pixels[target + x],
|
||||
fillColor,
|
||||
image.pixels[source + tx++]);
|
||||
}
|
||||
source += image.width;
|
||||
target += width;
|
||||
}
|
||||
|
||||
} else if (image.format == RGB) {
|
||||
target += sx1;
|
||||
int tw = sx2 - sx1;
|
||||
for (int y = sy1; y < sy2; y++) {
|
||||
System.arraycopy(image.pixels, source, pixels, target, tw);
|
||||
// should set z coordinate in here
|
||||
// or maybe not, since dims=0, meaning no relevant z
|
||||
source += image.width;
|
||||
target += width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// TEXT/FONTS
|
||||
|
||||
|
||||
// These will be handled entirely by PGraphics.
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// expects properly clipped coords, hence does
|
||||
// expects properly clipped coords, hence does
|
||||
// NOT check if x/y are in bounds [toxi]
|
||||
private void thin_pointAt(int x, int y, float z, int color) {
|
||||
int index = y*width+x; // offset values are pre-calced in constructor
|
||||
@@ -1158,7 +1517,7 @@ public class PGraphics2D extends PGraphics {
|
||||
|
||||
} else { // use old line code for thickness > 1
|
||||
|
||||
if ((strokeWeight < TWO) && !strokeChanged) {
|
||||
if ((strokeWeight < 2) && !strokeChanged) {
|
||||
// need to set color at least once?
|
||||
|
||||
// THIS PARTICULAR CASE SHOULD NO LONGER BE REACHABLE
|
||||
@@ -1231,277 +1590,8 @@ public class PGraphics2D extends PGraphics {
|
||||
zbuffer[index] = z;
|
||||
}
|
||||
|
||||
|
||||
private void flat_circle(int centerX, int centerY, int radius) {
|
||||
if (translateNoScale()) {
|
||||
centerX = (int) screenX(centerX, centerY, 0);
|
||||
centerY = (int) screenY(centerX, centerY, 0);
|
||||
}
|
||||
if (fill) flat_circle_fill(centerX, centerY, radius);
|
||||
if (stroke) flat_circle_stroke(centerX, centerY, radius);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw the outline around a flat circle using a bresenham-style
|
||||
* algorithm. Adapted from drawCircle function in "Computer Graphics
|
||||
* for Java Programmers" by Leen Ammeraal, p. 110
|
||||
*
|
||||
* This function is included because the quality is so much better,
|
||||
* and the drawing significantly faster than with adaptive ellipses
|
||||
* drawn using the sine/cosine tables.
|
||||
*
|
||||
* Circle quadrants break down like so:
|
||||
* |
|
||||
* \ NNW | NNE /
|
||||
* \ | /
|
||||
* WNW \ | / ENE
|
||||
* -------------------
|
||||
* WSW / | \ ESE
|
||||
* / | \
|
||||
* / SSW | SSE \
|
||||
* |
|
||||
*
|
||||
* @param xc x center
|
||||
* @param yc y center
|
||||
* @param r radius
|
||||
*/
|
||||
private void flat_circle_stroke(int xC, int yC, int r) {
|
||||
int x = 0, y = r, u = 1, v = 2 * r - 1, E = 0;
|
||||
while (x < y) {
|
||||
thin_point(xC + x, yC + y, 0, strokeColor); // NNE
|
||||
thin_point(xC + y, yC - x, 0, strokeColor); // ESE
|
||||
thin_point(xC - x, yC - y, 0, strokeColor); // SSW
|
||||
thin_point(xC - y, yC + x, 0, strokeColor); // WNW
|
||||
|
||||
x++; E += u; u += 2;
|
||||
if (v < 2 * E) {
|
||||
y--; E -= v; v -= 2;
|
||||
}
|
||||
if (x > y) break;
|
||||
|
||||
thin_point(xC + y, yC + x, 0, strokeColor); // ENE
|
||||
thin_point(xC + x, yC - y, 0, strokeColor); // SSE
|
||||
thin_point(xC - y, yC - x, 0, strokeColor); // WSW
|
||||
thin_point(xC - x, yC + y, 0, strokeColor); // NNW
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Heavily adapted version of the above algorithm that handles
|
||||
* filling the ellipse. Works by drawing from the center and
|
||||
* outwards to the points themselves. Has to be done this way
|
||||
* because the values for the points are changed halfway through
|
||||
* the function, making it impossible to just store a series of
|
||||
* left and right edges to be drawn more quickly.
|
||||
*
|
||||
* @param xc x center
|
||||
* @param yc y center
|
||||
* @param r radius
|
||||
*/
|
||||
private void flat_circle_fill(int xc, int yc, int r) {
|
||||
int x = 0, y = r, u = 1, v = 2 * r - 1, E = 0;
|
||||
while (x < y) {
|
||||
for (int xx = xc; xx < xc + x; xx++) { // NNE
|
||||
thin_point(xx, yc + y, 0, fillColor);
|
||||
}
|
||||
for (int xx = xc; xx < xc + y; xx++) { // ESE
|
||||
thin_point(xx, yc - x, 0, fillColor);
|
||||
}
|
||||
for (int xx = xc - x; xx < xc; xx++) { // SSW
|
||||
thin_point(xx, yc - y, 0, fillColor);
|
||||
}
|
||||
for (int xx = xc - y; xx < xc; xx++) { // WNW
|
||||
thin_point(xx, yc + x, 0, fillColor);
|
||||
}
|
||||
|
||||
x++; E += u; u += 2;
|
||||
if (v < 2 * E) {
|
||||
y--; E -= v; v -= 2;
|
||||
}
|
||||
if (x > y) break;
|
||||
|
||||
for (int xx = xc; xx < xc + y; xx++) { // ENE
|
||||
thin_point(xx, yc + x, 0, fillColor);
|
||||
}
|
||||
for (int xx = xc; xx < xc + x; xx++) { // SSE
|
||||
thin_point(xx, yc - y, 0, fillColor);
|
||||
}
|
||||
for (int xx = xc - y; xx < xc; xx++) { // WSW
|
||||
thin_point(xx, yc - x, 0, fillColor);
|
||||
}
|
||||
for (int xx = xc - x; xx < xc; xx++) { // NNW
|
||||
thin_point(xx, yc + y, 0, fillColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unfortunately this can't handle fill and stroke simultaneously,
|
||||
// because the fill will later replace some of the stroke points
|
||||
|
||||
private final void flat_ellipse_symmetry(int centerX, int centerY,
|
||||
int ellipseX, int ellipseY,
|
||||
boolean filling) {
|
||||
if (filling) {
|
||||
for (int i = centerX - ellipseX + 1; i < centerX + ellipseX; i++) {
|
||||
thin_point(i, centerY - ellipseY, 0, fillColor);
|
||||
thin_point(i, centerY + ellipseY, 0, fillColor);
|
||||
}
|
||||
} else {
|
||||
thin_point(centerX - ellipseX, centerY + ellipseY, 0, strokeColor);
|
||||
thin_point(centerX + ellipseX, centerY + ellipseY, 0, strokeColor);
|
||||
thin_point(centerX - ellipseX, centerY - ellipseY, 0, strokeColor);
|
||||
thin_point(centerX + ellipseX, centerY - ellipseY, 0, strokeColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bresenham-style ellipse drawing function, adapted from a posting to
|
||||
* comp.graphics.algortihms.
|
||||
*
|
||||
* This function is included because the quality is so much better,
|
||||
* and the drawing significantly faster than with adaptive ellipses
|
||||
* drawn using the sine/cosine tables.
|
||||
*
|
||||
* @param centerX x coordinate of the center
|
||||
* @param centerY y coordinate of the center
|
||||
* @param a horizontal radius
|
||||
* @param b vertical radius
|
||||
*/
|
||||
private void flat_ellipse_internal(int centerX, int centerY,
|
||||
int a, int b, boolean filling) {
|
||||
int x, y, a2, b2, s, t;
|
||||
|
||||
a2 = a*a;
|
||||
b2 = b*b;
|
||||
x = 0;
|
||||
y = b;
|
||||
s = a2*(1-2*b) + 2*b2;
|
||||
t = b2 - 2*a2*(2*b-1);
|
||||
flat_ellipse_symmetry(centerX, centerY, x, y, filling);
|
||||
|
||||
do {
|
||||
if (s < 0) {
|
||||
s += 2*b2*(2*x+3);
|
||||
t += 4*b2*(x+1);
|
||||
x++;
|
||||
} else if (t < 0) {
|
||||
s += 2*b2*(2*x+3) - 4*a2*(y-1);
|
||||
t += 4*b2*(x+1) - 2*a2*(2*y-3);
|
||||
x++;
|
||||
y--;
|
||||
} else {
|
||||
s -= 4*a2*(y-1);
|
||||
t -= 2*a2*(2*y-3);
|
||||
y--;
|
||||
}
|
||||
flat_ellipse_symmetry(centerX, centerY, x, y, filling);
|
||||
|
||||
} while (y > 0);
|
||||
}
|
||||
|
||||
|
||||
private void flat_ellipse(int centerX, int centerY, int a, int b) {
|
||||
if (translateNoScale()) {
|
||||
centerX = (int) screenX(centerX, centerY, 0);
|
||||
centerY = (int) screenY(centerX, centerY, 0);
|
||||
}
|
||||
if (fill) flat_ellipse_internal(centerX, centerY, a, b, true);
|
||||
if (stroke) flat_ellipse_internal(centerX, centerY, a, b, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Image drawn in flat "screen space", with no scaling or warping.
|
||||
* this is so common that a special routine is included for it,
|
||||
* because the alternative is much slower.
|
||||
*
|
||||
* @param image image to be drawn
|
||||
* @param sx1 x coordinate of upper-lefthand corner in screen space
|
||||
* @param sy1 y coordinate of upper-lefthand corner in screen space
|
||||
*/
|
||||
public void flat_image(PImage image, int sx1, int sy1) {
|
||||
int ix1 = 0;
|
||||
int iy1 = 0;
|
||||
int ix2 = image.width;
|
||||
int iy2 = image.height;
|
||||
|
||||
if (imageMode == CENTER) {
|
||||
sx1 -= image.width / 2;
|
||||
sy1 -= image.height / 2;
|
||||
}
|
||||
|
||||
int sx2 = sx1 + image.width;
|
||||
int sy2 = sy1 + image.height;
|
||||
|
||||
// don't draw if completely offscreen
|
||||
// (without this check, ArrayIndexOutOfBoundsException)
|
||||
if ((sx1 > width1) || (sx2 < 0) ||
|
||||
(sy1 > height1) || (sy2 < 0)) return;
|
||||
|
||||
if (sx1 < 0) { // off left edge
|
||||
ix1 -= sx1;
|
||||
sx1 = 0;
|
||||
}
|
||||
if (sy1 < 0) { // off top edge
|
||||
iy1 -= sy1;
|
||||
sy1 = 0;
|
||||
}
|
||||
if (sx2 > width) { // off right edge
|
||||
ix2 -= sx2 - width;
|
||||
sx2 = width;
|
||||
}
|
||||
if (sy2 > height) { // off bottom edge
|
||||
iy2 -= sy2 - height;
|
||||
sy2 = height;
|
||||
}
|
||||
|
||||
int source = iy1 * image.width + ix1;
|
||||
int target = sy1 * width;
|
||||
|
||||
if (image.format == ARGB) {
|
||||
for (int y = sy1; y < sy2; y++) {
|
||||
int tx = 0;
|
||||
|
||||
for (int x = sx1; x < sx2; x++) {
|
||||
pixels[target + x] =
|
||||
_blend(pixels[target + x],
|
||||
image.pixels[source + tx],
|
||||
image.pixels[source + tx++] >>> 24);
|
||||
}
|
||||
source += image.width;
|
||||
target += width;
|
||||
}
|
||||
} else if (image.format == ALPHA) {
|
||||
for (int y = sy1; y < sy2; y++) {
|
||||
int tx = 0;
|
||||
|
||||
for (int x = sx1; x < sx2; x++) {
|
||||
pixels[target + x] =
|
||||
_blend(pixels[target + x],
|
||||
fillColor,
|
||||
image.pixels[source + tx++]);
|
||||
}
|
||||
source += image.width;
|
||||
target += width;
|
||||
}
|
||||
|
||||
} else if (image.format == RGB) {
|
||||
target += sx1;
|
||||
int tw = sx2 - sx1;
|
||||
for (int y = sy1; y < sy2; y++) {
|
||||
System.arraycopy(image.pixels, source, pixels, target, tw);
|
||||
// should set z coordinate in here
|
||||
// or maybe not, since dims=0, meaning no relevant z
|
||||
source += image.width;
|
||||
target += width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// INTERNAL SCHIZZLE
|
||||
@@ -1512,7 +1602,8 @@ public class PGraphics2D extends PGraphics {
|
||||
(m10 == 0) && (m11 == 1) && (m12 == 0));
|
||||
}
|
||||
|
||||
private boolean translateNoScale() {
|
||||
|
||||
private boolean unwarped() {
|
||||
return ((m00 == 1) && (m01 == 0) && (m10 == 0) && (m11 == 1));
|
||||
}
|
||||
|
||||
|
||||
@@ -2105,20 +2105,9 @@ public class PGraphics3D extends PGraphics {
|
||||
*/
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compared to the implementation in PGraphics, this adds normal().
|
||||
*/
|
||||
public void triangle(float x1, float y1, float x2, float y2,
|
||||
float x3, float y3) {
|
||||
beginShape(TRIANGLES);
|
||||
@@ -2130,6 +2119,9 @@ public class PGraphics3D extends PGraphics {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compared to the implementation in PGraphics, this adds normal().
|
||||
*/
|
||||
public void quad(float x1, float y1, float x2, float y2,
|
||||
float x3, float y3, float x4, float y4) {
|
||||
beginShape(QUADS);
|
||||
@@ -2145,156 +2137,7 @@ public class PGraphics3D extends PGraphics {
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// PLACED SHAPES
|
||||
|
||||
|
||||
protected void rectImpl(float x1, float y1, float x2, float y2) {
|
||||
quad(x1, y1, x2, y1, x2, y2, x1, y2);
|
||||
}
|
||||
|
||||
|
||||
protected void ellipseImpl(float x1, float y1, float w, float h) {
|
||||
float hradius = w / 2f;
|
||||
float vradius = h / 2f;
|
||||
|
||||
float centerX = x1 + hradius;
|
||||
float centerY = y1 + 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(centerX + cosLUT[(int) val] * hradius,
|
||||
centerY + sinLUT[(int) val] * vradius);
|
||||
val += inc;
|
||||
}
|
||||
endShape();
|
||||
*/
|
||||
|
||||
if (fill) {
|
||||
boolean savedStroke = stroke;
|
||||
stroke = false;
|
||||
|
||||
beginShape(TRIANGLE_FAN);
|
||||
normal(0, 0, 1);
|
||||
vertex(centerX, centerY);
|
||||
for (int i = 0; i < cAccuracy; i++) {
|
||||
vertex(centerX + cosLUT[(int) val] * hradius,
|
||||
centerY + sinLUT[(int) val] * vradius);
|
||||
val += inc;
|
||||
}
|
||||
// back to the beginning
|
||||
vertex(centerX + cosLUT[0] * hradius,
|
||||
centerY + sinLUT[0] * vradius);
|
||||
endShape();
|
||||
|
||||
stroke = savedStroke;
|
||||
}
|
||||
|
||||
if (stroke) {
|
||||
boolean savedFill = fill;
|
||||
fill = false;
|
||||
|
||||
val = 0;
|
||||
beginShape(LINE_LOOP);
|
||||
for (int i = 0; i < cAccuracy; i++) {
|
||||
vertex(centerX + cosLUT[(int) val] * hradius,
|
||||
centerY + sinLUT[(int) val] * vradius);
|
||||
val += inc;
|
||||
}
|
||||
endShape();
|
||||
|
||||
fill = savedFill;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 arcImpl(float x1, float y1, float w, float h,
|
||||
float start, float stop) {
|
||||
float hr = w / 2f;
|
||||
float vr = h / 2f;
|
||||
|
||||
float centerX = x1 + hr;
|
||||
float centerY = y1 + vr;
|
||||
|
||||
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(centerX, centerY);
|
||||
int increment = 1; // what's a good algorithm? stopLUT - startLUT;
|
||||
for (int i = startLUT; i < stopLUT; i += increment) {
|
||||
int ii = i % SINCOS_LENGTH;
|
||||
vertex(centerX + cosLUT[ii] * hr,
|
||||
centerY + sinLUT[ii] * vr);
|
||||
}
|
||||
// draw last point explicitly for accuracy
|
||||
vertex(centerX + cosLUT[stopLUT % SINCOS_LENGTH] * hr,
|
||||
centerY + 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(centerX + cosLUT[ii] * hr,
|
||||
centerY + sinLUT[ii] * vr);
|
||||
}
|
||||
// draw last point explicitly for accuracy
|
||||
vertex(centerX + cosLUT[stopLUT % SINCOS_LENGTH] * hr,
|
||||
centerY + sinLUT[stopLUT % SINCOS_LENGTH] * vr);
|
||||
endShape();
|
||||
|
||||
fill = savedFill;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// 3D BOX
|
||||
// BOX
|
||||
|
||||
|
||||
public void box(float size) {
|
||||
@@ -2369,7 +2212,7 @@ public class PGraphics3D extends PGraphics {
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// 3D SPHERE
|
||||
// SPHERE
|
||||
|
||||
|
||||
// [toxi031031] used by the new sphere code below
|
||||
@@ -2517,6 +2360,7 @@ public class PGraphics3D extends PGraphics {
|
||||
|
||||
// CURVES
|
||||
|
||||
/*
|
||||
|
||||
public void bezier(float x1, float y1,
|
||||
float x2, float y2,
|
||||
@@ -2564,63 +2408,8 @@ public class PGraphics3D extends PGraphics {
|
||||
curveVertex(x4, y4, z4);
|
||||
endShape();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
protected void imageImpl(PImage image,
|
||||
float x1, float y1, float x2, float y2,
|
||||
int u1, int v1, int u2, int v2) {
|
||||
|
||||
//float x2 = x1 + w;
|
||||
//float y2 = y1 + h;
|
||||
|
||||
boolean savedStroke = stroke;
|
||||
boolean savedFill = fill;
|
||||
int savedTextureMode = textureMode;
|
||||
|
||||
stroke = false;
|
||||
fill = true;
|
||||
textureMode = IMAGE;
|
||||
|
||||
float savedFillR = fillR;
|
||||
float savedFillG = fillG;
|
||||
float savedFillB = fillB;
|
||||
float savedFillA = fillA;
|
||||
|
||||
if (tint) {
|
||||
fillR = tintR;
|
||||
fillG = tintG;
|
||||
fillB = tintB;
|
||||
fillA = tintA;
|
||||
|
||||
} else {
|
||||
fillR = 1;
|
||||
fillG = 1;
|
||||
fillB = 1;
|
||||
fillA = 1;
|
||||
}
|
||||
|
||||
//System.out.println(fill + " " + fillR + " " + fillG + " " + fillB);
|
||||
|
||||
beginShape(QUADS);
|
||||
texture(image);
|
||||
vertex(x1, y1, u1, v1);
|
||||
vertex(x1, y2, u1, v2);
|
||||
vertex(x2, y2, u2, v2);
|
||||
vertex(x2, y1, u2, v1);
|
||||
endShape();
|
||||
|
||||
stroke = savedStroke;
|
||||
fill = savedFill;
|
||||
textureMode = savedTextureMode;
|
||||
|
||||
fillR = savedFillR;
|
||||
fillG = savedFillG;
|
||||
fillB = savedFillB;
|
||||
fillA = savedFillA;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -3782,7 +3571,7 @@ public class PGraphics3D extends PGraphics {
|
||||
super.background(image);
|
||||
|
||||
for (int i = 0; i < pixelCount; i++) {
|
||||
zbuffer[i] = MAX_FLOAT;
|
||||
zbuffer[i] = Float.MAX_VALUE;
|
||||
stencil[i] = 0;
|
||||
}
|
||||
}
|
||||
@@ -3798,7 +3587,7 @@ public class PGraphics3D extends PGraphics {
|
||||
// PApplet.hex(backgroundColor) + ")");
|
||||
for (int i = 0; i < pixelCount; i++) {
|
||||
pixels[i] = backgroundColor;
|
||||
zbuffer[i] = MAX_FLOAT;
|
||||
zbuffer[i] = Float.MAX_VALUE;
|
||||
stencil[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -644,7 +644,7 @@ public class PPolygon implements PConstants {
|
||||
float p[], float dp[], int y) {
|
||||
float delta = p2[Y] - p1[Y];
|
||||
if (delta == 0) delta = ONE;
|
||||
float fraction = y + HALF - p1[Y];
|
||||
float fraction = y + 0.5f - p1[Y];
|
||||
|
||||
if (interpX) {
|
||||
dp[X] = (p2[X] - p1[X]) / delta;
|
||||
@@ -687,7 +687,7 @@ public class PPolygon implements PConstants {
|
||||
float p[], float dp[], int x) {
|
||||
float delta = p2[X] - p1[X];
|
||||
if (delta == 0) delta = ONE;
|
||||
float fraction = x + HALF - p1[X];
|
||||
float fraction = x + 0.5f - p1[X];
|
||||
if (smooth) {
|
||||
delta /= SUBXRES;
|
||||
fraction /= SUBXRES;
|
||||
|
||||
Reference in New Issue
Block a user