From 341c74a9d623202863dddd297aac5a0e07c02f10 Mon Sep 17 00:00:00 2001 From: codeanticode Date: Tue, 6 Dec 2011 02:03:03 +0000 Subject: [PATCH] fill and stroke methods in PShape3D --- core/src/processing/core/PShape.java | 204 +++++++++ .../processing/opengl/PGraphicsOpenGL.java | 6 +- .../src/processing/opengl/PShape3D.java | 398 ++++++------------ 3 files changed, 323 insertions(+), 285 deletions(-) diff --git a/core/src/processing/core/PShape.java b/core/src/processing/core/PShape.java index 076f5f57e..2f2a5e47a 100644 --- a/core/src/processing/core/PShape.java +++ b/core/src/processing/core/PShape.java @@ -167,6 +167,38 @@ public class PShape implements PConstants { /** True if this is a closed path. */ protected boolean close; + + // ........................................................ + + // internal color for setting/calculating + protected float calcR, calcG, calcB, calcA; + protected int calcRi, calcGi, calcBi, calcAi; + protected int calcColor; + protected boolean calcAlpha; + + /** The current colorMode */ + public int colorMode; // = RGB; + + /** Max value for red (or hue) set by colorMode */ + public float colorModeX; // = 255; + + /** Max value for green (or saturation) set by colorMode */ + public float colorModeY; // = 255; + + /** Max value for blue (or value) set by colorMode */ + public float colorModeZ; // = 255; + + /** Max value for alpha set by colorMode */ + public float colorModeA; // = 255; + + /** True if colors are not in the range 0..1 */ + boolean colorModeScale; // = true; + + /** True if colorMode(RGB, 255) */ + boolean colorModeDefault; // = true; + + + // should this be called vertices (consistent with PGraphics internals) // or does that hurt flexibility? @@ -1329,4 +1361,176 @@ public class PShape implements PConstants { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + public void colorMode(int mode) { + colorMode(mode, colorModeX, colorModeY, colorModeZ, colorModeA); + } + + /** + * @param max range for all color elements + */ + public void colorMode(int mode, float max) { + colorMode(mode, max, max, max, max); + } + + + /** + * @param maxX range for the red or hue depending on the current color mode + * @param maxY range for the green or saturation depending on the current color mode + * @param maxZ range for the blue or brightness depending on the current color mode + */ + public void colorMode(int mode, float maxX, float maxY, float maxZ) { + colorMode(mode, maxX, maxY, maxZ, colorModeA); + } + +/** + * @param maxA range for the alpha + */ + public void colorMode(int mode, + float maxX, float maxY, float maxZ, float maxA) { + colorMode = mode; + + colorModeX = maxX; // still needs to be set for hsb + colorModeY = maxY; + colorModeZ = maxZ; + colorModeA = maxA; + + // if color max values are all 1, then no need to scale + colorModeScale = + ((maxA != 1) || (maxX != maxY) || (maxY != maxZ) || (maxZ != maxA)); + + // if color is rgb/0..255 this will make it easier for the + // red() green() etc functions + colorModeDefault = (colorMode == RGB) && + (colorModeA == 255) && (colorModeX == 255) && + (colorModeY == 255) && (colorModeZ == 255); + } + + + protected void colorCalc(int rgb) { + if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { + colorCalc((float) rgb); + + } else { + colorCalcARGB(rgb, colorModeA); + } + } + + + protected void colorCalc(int rgb, float alpha) { + if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { // see above + colorCalc((float) rgb, alpha); + + } else { + colorCalcARGB(rgb, alpha); + } + } + + + protected void colorCalc(float gray) { + colorCalc(gray, colorModeA); + } + + + protected void colorCalc(float gray, float alpha) { + if (gray > colorModeX) gray = colorModeX; + if (alpha > colorModeA) alpha = colorModeA; + + if (gray < 0) gray = 0; + if (alpha < 0) alpha = 0; + + calcR = colorModeScale ? (gray / colorModeX) : gray; + calcG = calcR; + calcB = calcR; + calcA = colorModeScale ? (alpha / colorModeA) : alpha; + + calcRi = (int)(calcR*255); calcGi = (int)(calcG*255); + calcBi = (int)(calcB*255); calcAi = (int)(calcA*255); + calcColor = (calcAi << 24) | (calcRi << 16) | (calcGi << 8) | calcBi; + calcAlpha = (calcAi != 255); + } + + + protected void colorCalc(float x, float y, float z) { + colorCalc(x, y, z, colorModeA); + } + + + protected void colorCalc(float x, float y, float z, float a) { + if (x > colorModeX) x = colorModeX; + if (y > colorModeY) y = colorModeY; + if (z > colorModeZ) z = colorModeZ; + if (a > colorModeA) a = colorModeA; + + if (x < 0) x = 0; + if (y < 0) y = 0; + if (z < 0) z = 0; + if (a < 0) a = 0; + + switch (colorMode) { + case RGB: + if (colorModeScale) { + calcR = x / colorModeX; + calcG = y / colorModeY; + calcB = z / colorModeZ; + calcA = a / colorModeA; + } else { + calcR = x; calcG = y; calcB = z; calcA = a; + } + break; + + case HSB: + x /= colorModeX; // h + y /= colorModeY; // s + z /= colorModeZ; // b + + calcA = colorModeScale ? (a/colorModeA) : a; + + if (y == 0) { // saturation == 0 + calcR = calcG = calcB = z; + + } else { + float which = (x - (int)x) * 6.0f; + float f = which - (int)which; + float p = z * (1.0f - y); + float q = z * (1.0f - y * f); + float t = z * (1.0f - (y * (1.0f - f))); + + switch ((int)which) { + case 0: calcR = z; calcG = t; calcB = p; break; + case 1: calcR = q; calcG = z; calcB = p; break; + case 2: calcR = p; calcG = z; calcB = t; break; + case 3: calcR = p; calcG = q; calcB = z; break; + case 4: calcR = t; calcG = p; calcB = z; break; + case 5: calcR = z; calcG = p; calcB = q; break; + } + } + break; + } + calcRi = (int)(255*calcR); calcGi = (int)(255*calcG); + calcBi = (int)(255*calcB); calcAi = (int)(255*calcA); + calcColor = (calcAi << 24) | (calcRi << 16) | (calcGi << 8) | calcBi; + calcAlpha = (calcAi != 255); + } + + + protected void colorCalcARGB(int argb, float alpha) { + if (alpha == colorModeA) { + calcAi = (argb >> 24) & 0xff; + calcColor = argb; + } else { + calcAi = (int) (((argb >> 24) & 0xff) * (alpha / colorModeA)); + calcColor = (calcAi << 24) | (argb & 0xFFFFFF); + } + calcRi = (argb >> 16) & 0xff; + calcGi = (argb >> 8) & 0xff; + calcBi = argb & 0xff; + calcA = calcAi / 255.0f; + calcR = calcRi / 255.0f; + calcG = calcGi / 255.0f; + calcB = calcBi / 255.0f; + calcAlpha = (calcAi != 255); + } + } \ No newline at end of file diff --git a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java index 3efbff900..335ddf215 100644 --- a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java +++ b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java @@ -5819,7 +5819,7 @@ public class PGraphicsOpenGL extends PGraphics { glParamsRead = true; } - + ////////////////////////////////////////////////////////////// @@ -6207,10 +6207,6 @@ public class PGraphicsOpenGL extends PGraphics { mat.m30, mat.m31, mat.m32, mat.m33); } } - - - - public InGeometry newInGeometry() { return new InGeometry(); diff --git a/java/libraries/opengl/src/processing/opengl/PShape3D.java b/java/libraries/opengl/src/processing/opengl/PShape3D.java index d6f4e24cf..fee5025a0 100644 --- a/java/libraries/opengl/src/processing/opengl/PShape3D.java +++ b/java/libraries/opengl/src/processing/opengl/PShape3D.java @@ -73,8 +73,6 @@ public class PShape3D extends PShape { protected PImage texture; - protected boolean is3D; - // ........................................................ // OpenGL buffers @@ -132,12 +130,23 @@ public class PShape3D extends PShape { // Input data - protected float[] currentVertex = { 0, 0, 0 }; - protected float[] currentColor = { 0, 0, 0, 0 }; - protected float[] currentNormal = { 0, 0, 1 }; - protected float[] currentTexcoord = { 0, 0 }; - protected float[] currentStroke = { 0, 0, 0, 1, 1 }; + protected float normalX, normalY, normalZ; + // ........................................................ + + // Fill, stroke and tint colors + + protected boolean fill; + protected float fillR, fillG, fillB, fillA; + + protected boolean stroke; + protected float strokeR, strokeG, strokeB, strokeA; + + protected boolean tint; + protected float tintR, tintG, tintB, tintA; + + protected int textureMode = IMAGE; + // ........................................................ // Bezier and Catmull-Rom curves @@ -160,21 +169,7 @@ public class PShape3D extends PShape { protected float curveVertices[][]; protected int curveVertexCount; - // ........................................................ - // Fill color - - /** true if fill() is enabled, (read-only) */ - public boolean fill; - - /** fill that was last set (read-only) */ - public int fillColor = 0xffFFFFFF; - - protected boolean fillAlpha; - protected float fillR, fillG, fillB, fillA; - protected int fillRi, fillGi, fillBi, fillAi; - - public PShape3D(PApplet parent, int family) { @@ -205,7 +200,8 @@ public class PShape3D extends PShape { this.root = this; this.parent = null; this.modified = false; - this.is3D = true; + + colorMode(RGB, 255); tess = ogl.newTessGeometry(RETAINED); if (family == GEOMETRY || family == PRIMITIVE || family == PATH) { @@ -225,17 +221,11 @@ public class PShape3D extends PShape { } } + public void setKind(int kind) { this.kind = kind; } - - public void set2D() { - is3D = false; - } - - public void set3D() { - is3D = true; - } + public void setMode(int mode) { if (mode == STATIC) { @@ -247,6 +237,7 @@ public class PShape3D extends PShape { } } + protected void finalize() throws Throwable { try { release(); @@ -267,96 +258,146 @@ public class PShape3D extends PShape { texture = tex; } + public void noTexture() { texture = null; } + public void solid(boolean solid) { isSolid = solid; } + public void closed(boolean closed) { isClosed = closed; } + public void breakShape() { breakShape = true; } + public void vertex(float x, float y) { vertex(x, y, 0, 0, 0); } + public void vertex(float x, float y, float z) { vertex(x, y, z, 0, 0); } + public void vertex(float x, float y, float z, float u, float v) { vertexImpl(x, y, z, u, v, VERTEX); } + protected void vertexImpl(float x, float y, float z, float u, float v, int code) { if (family != GEOMETRY && family != PATH) { System.err.println("Cannot add vertices to GROUP of PRIMITIVE shape"); return; } - - currentVertex[0] = x; - currentVertex[1] = y; - currentVertex[2] = z; - if (texture != null) { + boolean textured = texture != null; + float fR, fG, fB, fA; + fR = fG = fB = fA = 0; + if (fill || textured) { + if (!textured) { + fR = fillR; + fG = fillG; + fB = fillB; + fA = fillA; + } else { + if (tint) { + fR = tintR; + fG = tintG; + fB = tintB; + fA = tintA; + } else { + fR = 1; + fG = 1; + fB = 1; + fA = 1; + } + } + } + + if (texture != null && textureMode == IMAGE) { + u /= texture.width; + v /= texture.height; + PTexture tex = ogl.getTexture(texture); if (tex.isFlippedY()) { v = 1 - v; } - } - currentTexcoord[0] = u; - currentTexcoord[1] = v; + } + float sR, sG, sB, sA, sW; + sR = sG = sB = sA = sW = 0; + if (stroke) { + sR = strokeR; + sG = strokeG; + sB = strokeB; + sA = strokeA; + sW = strokeWeight; + } + if (breakShape) { code = BREAK; breakShape = false; } - in.addVertex(currentVertex, currentColor, currentNormal, currentTexcoord, currentStroke, code); + //in.addVertex(currentVertex, currentColor, currentNormal, currentTexcoord, currentStroke, code); + + in.addVertex(x, y, z, + fR, fG, fB, fA, + normalX, normalY, normalZ, + u, v, + sR, sG, sB, sA, sW, + code); root.modified = true; modified = true; } + public void normal(float nx, float ny, float nz) { - currentNormal[0] = nx; - currentNormal[1] = ny; - currentNormal[2] = nz; + normalX = nx; + normalY = ny; + normalZ = nz; } - - - - public void strokeWeight(float w) { - currentStroke[4] = w; - } - - public void strokeJoin(int join) { - strokeJoin = join; - } - - public void strokeCap(int cap) { - strokeCap = cap; - } - public void end() { // ? - } + } + ////////////////////////////////////////////////////////////// + + // STROKE CAP/JOIN/WEIGHT + + + public void strokeWeight(float weight) { + strokeWeight = weight; + } + + + public void strokeJoin(int join) { + strokeJoin = join; + } + + + public void strokeCap(int cap) { + strokeCap = cap; + } + ////////////////////////////////////////////////////////////// // FILL COLOR -/* public void noFill() { fill = false; } @@ -397,269 +438,70 @@ public class PShape3D extends PShape { fillG = calcG; fillB = calcB; fillA = calcA; - fillRi = calcRi; - fillGi = calcGi; - fillBi = calcBi; - fillAi = calcAi; fillColor = calcColor; - fillAlpha = calcAlpha; } - */ + - public void noFill() { - fill(0, 0, 0, 0); - } - - public void fill(float r, float g, float b, float a) { - currentColor[0] = r; - currentColor[1] = g; - currentColor[2] = b; - currentColor[3] = a; + public void textureMode(int mode) { + this.textureMode = mode; } - ////////////////////////////////////////////////////////////// - - // STROKE CAP/JOIN/WEIGHT - -/* - public void strokeWeight(float weight) { - strokeWeight = weight; - } - - public void strokeJoin(int join) { - strokeJoin = join; - } - - - public void strokeCap(int cap) { - strokeCap = cap; - } - - */ - ////////////////////////////////////////////////////////////// // STROKE COLOR - public void stroke(float r, float g, float b, float a) { - currentStroke[0] = r; - currentStroke[1] = g; - currentStroke[2] = b; - currentStroke[3] = a; - } - - public void noStroke() { - stroke(0, 0, 0, 0); - } - -/* public void noStroke() { stroke = false; } + public void stroke(int rgb) { colorCalc(rgb); strokeFromCalc(); } - + + public void stroke(int rgb, float alpha) { colorCalc(rgb, alpha); strokeFromCalc(); } + public void stroke(float gray) { colorCalc(gray); strokeFromCalc(); } + public void stroke(float gray, float alpha) { colorCalc(gray, alpha); strokeFromCalc(); } + public void stroke(float x, float y, float z) { colorCalc(x, y, z); strokeFromCalc(); } + public void stroke(float x, float y, float z, float alpha) { colorCalc(x, y, z, alpha); strokeFromCalc(); } + protected void strokeFromCalc() { stroke = true; strokeR = calcR; strokeG = calcG; strokeB = calcB; strokeA = calcA; - strokeRi = calcRi; - strokeGi = calcGi; - strokeBi = calcBi; - strokeAi = calcAi; strokeColor = calcColor; - strokeAlpha = calcAlpha; } -*/ - - /* - public void imageMode(int mode) { - if ((mode == CORNER) || (mode == CORNERS) || (mode == CENTER)) { - imageMode = mode; - } else { - String msg = - "imageMode() only works with CORNER, CORNERS, or CENTER"; - throw new RuntimeException(msg); - } - } - */ - - - ////////////////////////////////////////////////////////////// - - // STYLE - -/* - public void pushStyle() { - if (styleStackDepth == styleStack.length) { - styleStack = (PStyle[]) PApplet.expand(styleStack); - } - if (styleStack[styleStackDepth] == null) { - styleStack[styleStackDepth] = new PStyle(); - } - PStyle s = styleStack[styleStackDepth++]; - getStyle(s); - } - - - public void popStyle() { - if (styleStackDepth == 0) { - throw new RuntimeException("Too many popStyle() without enough pushStyle()"); - } - styleStackDepth--; - style(styleStack[styleStackDepth]); - } - - - public void style(PStyle s) { - // if (s.smooth) { - // smooth(); - // } else { - // noSmooth(); - // } - - imageMode(s.imageMode); - rectMode(s.rectMode); - ellipseMode(s.ellipseMode); - shapeMode(s.shapeMode); - - if (s.tint) { - tint(s.tintColor); - } else { - noTint(); - } - if (s.fill) { - fill(s.fillColor); - } else { - noFill(); - } - if (s.stroke) { - stroke(s.strokeColor); - } else { - noStroke(); - } - strokeWeight(s.strokeWeight); - strokeCap(s.strokeCap); - strokeJoin(s.strokeJoin); - - // Set the colorMode() for the material properties. - // TODO this is really inefficient, need to just have a material() method, - // but this has the least impact to the API. - colorMode(RGB, 1); - ambient(s.ambientR, s.ambientG, s.ambientB); - emissive(s.emissiveR, s.emissiveG, s.emissiveB); - specular(s.specularR, s.specularG, s.specularB); - shininess(s.shininess); - - // material(s.ambientR, s.ambientG, s.ambientB, - // s.emissiveR, s.emissiveG, s.emissiveB, - // s.specularR, s.specularG, s.specularB, - // s.shininess); - - // Set this after the material properties. - colorMode(s.colorMode, - s.colorModeX, s.colorModeY, s.colorModeZ, s.colorModeA); - - // This is a bit asymmetric, since there's no way to do "noFont()", - // and a null textFont will produce an error (since usually that means that - // the font couldn't load properly). So in some cases, the font won't be - // 'cleared' to null, even though that's technically correct. - if (s.textFont != null) { - textFont(s.textFont, s.textSize); - textLeading(s.textLeading); - } - // These don't require a font to be set. - textAlign(s.textAlign, s.textAlignY); - textMode(s.textMode); - } - - - public PStyle getStyle() { // ignore - return getStyle(null); - } - - - public PStyle getStyle(PStyle s) { // ignore - if (s == null) { - s = new PStyle(); - } - - s.imageMode = imageMode; - s.rectMode = rectMode; - s.ellipseMode = ellipseMode; - s.shapeMode = shapeMode; - - s.colorMode = colorMode; - s.colorModeX = colorModeX; - s.colorModeY = colorModeY; - s.colorModeZ = colorModeZ; - s.colorModeA = colorModeA; - - s.tint = tint; - s.tintColor = tintColor; - s.fill = fill; - s.fillColor = fillColor; - s.stroke = stroke; - s.strokeColor = strokeColor; - s.strokeWeight = strokeWeight; - s.strokeCap = strokeCap; - s.strokeJoin = strokeJoin; - - s.ambientR = ambientR; - s.ambientG = ambientG; - s.ambientB = ambientB; - s.specularR = specularR; - s.specularG = specularG; - s.specularB = specularB; - s.emissiveR = emissiveR; - s.emissiveG = emissiveG; - s.emissiveB = emissiveB; - s.shininess = shininess; - - s.textFont = textFont; - s.textAlign = textAlign; - s.textAlignY = textAlignY; - s.textMode = textMode; - s.textSize = textSize; - s.textLeading = textLeading; - - return s; - } -*/ - /////////////////////////////////////////////////////////// @@ -1006,8 +848,12 @@ public class PShape3D extends PShape { if (modified) { tessellator.setInGeometry(in); tessellator.setTessGeometry(tess); - - + tessellator.setFill(fill || texture != null); + tessellator.setStroke(stroke); + tessellator.setStrokeWeight(strokeWeight); + tessellator.setStrokeCap(strokeCap); + tessellator.setStrokeJoin(strokeJoin); + tessellator.setStrokeColor(strokeR, strokeG, strokeB, strokeA); if (family == GEOMETRY) { if (kind == POINTS) { @@ -1618,15 +1464,7 @@ public class PShape3D extends PShape { } } else { - if (!is3D) { - // if is stroked and textured: - // texSet.add(texture); for the textured fill - // texSet.add(null); for the stroke - // else - texSet.add(texture); - } else { - texSet.add(texture); - } + texSet.add(texture); } return texSet;