From aee3d3c49c1226d6a8c3be5c516d47c65a8d87ec Mon Sep 17 00:00:00 2001 From: Jakub Valtar Date: Sat, 5 Jul 2014 03:37:25 +0200 Subject: [PATCH 1/8] new lighting shaders --- core/src/processing/opengl/LightFrag.glsl | 31 +++++++++++++ core/src/processing/opengl/LightVert.glsl | 44 +++++++++++------- .../processing/opengl/PGraphicsOpenGL.java | 9 +++- core/src/processing/opengl/TexlightFrag.glsl | 36 +++++++++++++++ core/src/processing/opengl/TexlightVert.glsl | 46 +++++++++++-------- 5 files changed, 129 insertions(+), 37 deletions(-) create mode 100644 core/src/processing/opengl/LightFrag.glsl create mode 100644 core/src/processing/opengl/TexlightFrag.glsl diff --git a/core/src/processing/opengl/LightFrag.glsl b/core/src/processing/opengl/LightFrag.glsl new file mode 100644 index 000000000..b566c8e5b --- /dev/null +++ b/core/src/processing/opengl/LightFrag.glsl @@ -0,0 +1,31 @@ +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2011-13 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 version 2.1 as published by the Free Software Foundation. + + 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 + */ + +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + +varying vec4 vertColor; +varying vec4 backVertColor; + +void main() { + gl_FragColor = gl_FrontFacing ? vertColor : backVertColor; +} \ No newline at end of file diff --git a/core/src/processing/opengl/LightVert.glsl b/core/src/processing/opengl/LightVert.glsl index bfbb6a8d3..8d75f970a 100644 --- a/core/src/processing/opengl/LightVert.glsl +++ b/core/src/processing/opengl/LightVert.glsl @@ -43,6 +43,7 @@ attribute vec4 emissive; attribute float shininess; varying vec4 vertColor; +varying vec4 backVertColor; const float zero_float = 0.0; const float one_float = 1.0; @@ -82,17 +83,17 @@ void main() { // Normal vector in eye coordinates vec3 ecNormal = normalize(normalMatrix * normal); - - if (dot(-one_float * ecVertex, ecNormal) < zero_float) { - // If normal is away from camera, choose its opposite. - // If we add backface culling, this will be backfacing - ecNormal *= -one_float; - } + vec3 ecNormalInv = ecNormal * -one_float; // Light calculations vec3 totalAmbient = vec3(0, 0, 0); - vec3 totalDiffuse = vec3(0, 0, 0); - vec3 totalSpecular = vec3(0, 0, 0); + + vec3 totalFrontDiffuse = vec3(0, 0, 0); + vec3 totalFrontSpecular = vec3(0, 0, 0); + + vec3 totalBackDiffuse = vec3(0, 0, 0); + vec3 totalBackSpecular = vec3(0, 0, 0); + for (int i = 0; i < 8; i++) { if (lightCount == i) break; @@ -118,24 +119,33 @@ void main() { : one_float; if (any(greaterThan(lightAmbient[i], zero_vec3))) { - totalAmbient += lightAmbient[i] * falloff; + totalAmbient += lightAmbient[i] * falloff; } if (any(greaterThan(lightDiffuse[i], zero_vec3))) { - totalDiffuse += lightDiffuse[i] * falloff * spotf * - lambertFactor(lightDir, ecNormal); + totalFrontDiffuse += lightDiffuse[i] * falloff * spotf * + lambertFactor(lightDir, ecNormal); + totalBackDiffuse += lightDiffuse[i] * falloff * spotf * + lambertFactor(lightDir, ecNormalInv); } if (any(greaterThan(lightSpecular[i], zero_vec3))) { - totalSpecular += lightSpecular[i] * falloff * spotf * - blinnPhongFactor(lightDir, ecVertex, ecNormal, shininess); + totalFrontSpecular += lightSpecular[i] * falloff * spotf * + blinnPhongFactor(lightDir, ecVertex, ecNormal, shininess); + totalBackSpecular += lightSpecular[i] * falloff * spotf * + blinnPhongFactor(lightDir, ecVertex, ecNormalInv, shininess); } } // Calculating final color as result of all lights (plus emissive term). // Transparency is determined exclusively by the diffuse component. - vertColor = vec4(totalAmbient, 0) * ambient + - vec4(totalDiffuse, 1) * color + - vec4(totalSpecular, 0) * specular + - vec4(emissive.rgb, 0); + vertColor = vec4(totalAmbient, 0) * ambient + + vec4(totalFrontDiffuse, 1) * color + + vec4(totalFrontSpecular, 0) * specular + + vec4(emissive.rgb, 0); + + backVertColor = vec4(totalAmbient, 0) * ambient + + vec4(totalBackDiffuse, 1) * color + + vec4(totalBackSpecular, 0) * specular + + vec4(emissive.rgb, 0); } \ No newline at end of file diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index f177bfa67..52063719d 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -160,6 +160,11 @@ public class PGraphicsOpenGL extends PGraphics { PGraphicsOpenGL.class.getResource("ColorFrag.glsl"); static protected URL defTextureShaderFragURL = PGraphicsOpenGL.class.getResource("TextureFrag.glsl"); + static protected URL defLightShaderFragURL = + PGraphicsOpenGL.class.getResource("LightFrag.glsl"); + static protected URL defTexlightShaderFragURL = + PGraphicsOpenGL.class.getResource("TexlightFrag.glsl"); + static protected URL defLineShaderVertURL = PGraphicsOpenGL.class.getResource("LineVert.glsl"); static protected URL defLineShaderFragURL = @@ -6740,7 +6745,7 @@ public class PGraphicsOpenGL extends PGraphics { if (useDefault || !polyShader.checkPolyType(PShader.TEXLIGHT)) { if (ppg.defTexlightShader == null) { String[] vertSource = pgl.loadVertexShader(defTexlightShaderVertURL, 120); - String[] fragSource = pgl.loadFragmentShader(defTextureShaderFragURL, 120); + String[] fragSource = pgl.loadFragmentShader(defTexlightShaderFragURL, 120); ppg.defTexlightShader = new PShader(parent, vertSource, fragSource); } shader = ppg.defTexlightShader; @@ -6751,7 +6756,7 @@ public class PGraphicsOpenGL extends PGraphics { if (useDefault || !polyShader.checkPolyType(PShader.LIGHT)) { if (ppg.defLightShader == null) { String[] vertSource = pgl.loadVertexShader(defLightShaderVertURL, 120); - String[] fragSource = pgl.loadFragmentShader(defColorShaderFragURL, 120); + String[] fragSource = pgl.loadFragmentShader(defLightShaderFragURL, 120); ppg.defLightShader = new PShader(parent, vertSource, fragSource); } shader = ppg.defLightShader; diff --git a/core/src/processing/opengl/TexlightFrag.glsl b/core/src/processing/opengl/TexlightFrag.glsl new file mode 100644 index 000000000..f423e49d3 --- /dev/null +++ b/core/src/processing/opengl/TexlightFrag.glsl @@ -0,0 +1,36 @@ +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2011-13 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 version 2.1 as published by the Free Software Foundation. + + 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 + */ + +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + +uniform sampler2D texture; + +uniform vec2 texOffset; + +varying vec4 vertColor; +varying vec4 backVertColor; +varying vec4 vertTexCoord; + +void main() { + gl_FragColor = texture2D(texture, vertTexCoord.st) * (gl_FrontFacing ? vertColor : backVertColor); +} \ No newline at end of file diff --git a/core/src/processing/opengl/TexlightVert.glsl b/core/src/processing/opengl/TexlightVert.glsl index 6542bf8fb..d9f2cde3a 100644 --- a/core/src/processing/opengl/TexlightVert.glsl +++ b/core/src/processing/opengl/TexlightVert.glsl @@ -45,6 +45,7 @@ attribute vec4 emissive; attribute float shininess; varying vec4 vertColor; +varying vec4 backVertColor; varying vec4 vertTexCoord; const float zero_float = 0.0; @@ -85,17 +86,17 @@ void main() { // Normal vector in eye coordinates vec3 ecNormal = normalize(normalMatrix * normal); - - if (dot(-one_float * ecVertex, ecNormal) < zero_float) { - // If normal is away from camera, choose its opposite. - // If we add backface culling, this will be backfacing - ecNormal *= -one_float; - } + vec3 ecNormalInv = ecNormal * -one_float; // Light calculations vec3 totalAmbient = vec3(0, 0, 0); - vec3 totalDiffuse = vec3(0, 0, 0); - vec3 totalSpecular = vec3(0, 0, 0); + + vec3 totalFrontDiffuse = vec3(0, 0, 0); + vec3 totalFrontSpecular = vec3(0, 0, 0); + + vec3 totalBackDiffuse = vec3(0, 0, 0); + vec3 totalBackSpecular = vec3(0, 0, 0); + for (int i = 0; i < 8; i++) { if (lightCount == i) break; @@ -121,27 +122,36 @@ void main() { : one_float; if (any(greaterThan(lightAmbient[i], zero_vec3))) { - totalAmbient += lightAmbient[i] * falloff; + totalAmbient += lightAmbient[i] * falloff; } if (any(greaterThan(lightDiffuse[i], zero_vec3))) { - totalDiffuse += lightDiffuse[i] * falloff * spotf * - lambertFactor(lightDir, ecNormal); + totalFrontDiffuse += lightDiffuse[i] * falloff * spotf * + lambertFactor(lightDir, ecNormal); + totalBackDiffuse += lightDiffuse[i] * falloff * spotf * + lambertFactor(lightDir, ecNormalInv); } if (any(greaterThan(lightSpecular[i], zero_vec3))) { - totalSpecular += lightSpecular[i] * falloff * spotf * - blinnPhongFactor(lightDir, ecVertex, ecNormal, shininess); - } + totalFrontSpecular += lightSpecular[i] * falloff * spotf * + blinnPhongFactor(lightDir, ecVertex, ecNormal, shininess); + totalBackSpecular += lightSpecular[i] * falloff * spotf * + blinnPhongFactor(lightDir, ecVertex, ecNormalInv, shininess); + } } // Calculating final color as result of all lights (plus emissive term). // Transparency is determined exclusively by the diffuse component. - vertColor = vec4(totalAmbient, 0) * ambient + - vec4(totalDiffuse, 1) * color + - vec4(totalSpecular, 0) * specular + - vec4(emissive.rgb, 0); + vertColor = vec4(totalAmbient, 0) * ambient + + vec4(totalFrontDiffuse, 1) * color + + vec4(totalFrontSpecular, 0) * specular + + vec4(emissive.rgb, 0); + backVertColor = vec4(totalAmbient, 0) * ambient + + vec4(totalBackDiffuse, 1) * color + + vec4(totalBackSpecular, 0) * specular + + vec4(emissive.rgb, 0); + // Calculating texture coordinates, with r and q set both to one vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0); } From 280860dd1850f466ac65726db561438ca1937ad0 Mon Sep 17 00:00:00 2001 From: Jakub Valtar Date: Sat, 5 Jul 2014 03:42:41 +0200 Subject: [PATCH 2/8] corrections of normals and front faces --- core/src/processing/core/PGraphics.java | 2 +- .../processing/opengl/PGraphicsOpenGL.java | 141 +++++++++++------- 2 files changed, 88 insertions(+), 55 deletions(-) diff --git a/core/src/processing/core/PGraphics.java b/core/src/processing/core/PGraphics.java index ed29c0ee4..5151ae64d 100644 --- a/core/src/processing/core/PGraphics.java +++ b/core/src/processing/core/PGraphics.java @@ -2405,7 +2405,7 @@ public class PGraphics extends PImage implements PConstants { protected void rectImpl(float x1, float y1, float x2, float y2) { - quad(x1, y1, x2, y1, x2, y2, x1, y2); + quad(x1, y1, x1, y2, x2, y2, x2, y1); } diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index 52063719d..e824bb295 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -1827,7 +1827,7 @@ public class PGraphicsOpenGL extends PGraphics { pgl.disable(PGL.SCISSOR_TEST); } - pgl.frontFace(PGL.CW); + pgl.frontFace(PGL.CCW); pgl.disable(PGL.CULL_FACE); pgl.activeTexture(PGL.TEXTURE0); @@ -3242,7 +3242,9 @@ public class PGraphicsOpenGL extends PGraphics { normalMode = NORMAL_MODE_SHAPE; inGeo.setMaterial(fillColor, strokeColor, strokeWeight, ambientColor, specularColor, emissiveColor, shininess); - inGeo.setNormal(normalX, normalY, normalZ); + // TODO: Arc should be drawn in CCW order (left-handed) + // Temp fix: invert arc normal + inGeo.setNormal(normalX, normalY, -normalZ); inGeo.addArc(x, y, w, h, start, stop, fill, stroke, mode); endShape(); } @@ -6536,16 +6538,21 @@ public class PGraphicsOpenGL extends PGraphics { lightSpecular(0, 0, 0); } - // Because y is flipped, the vertices that should be specified by - // the user in CCW order to define a front-facing facet, end up being CW. - pgl.frontFace(PGL.CW); + // Vertices should be specified by user in CCW order (left-handed) + // That is CW order (right-handed). Vertex shader inverts + // Y-axis and outputs vertices in CCW order (right-handed). + // Culling occurs after the vertex shader, so FRONT FACE + // has to be set to CCW (right-handed) for OpenGL to correctly + // recognize FRONT and BACK faces. + pgl.frontFace(PGL.CCW); pgl.disable(PGL.CULL_FACE); // Processing uses only one texture unit. pgl.activeTexture(PGL.TEXTURE0); // The current normal vector is set to be parallel to the Z axis. - normalX = normalY = normalZ = 0; + normalX = normalY = 0; + normalZ = 1; // Clear depth and stencil buffers. pgl.depthMask(true); @@ -7830,12 +7837,14 @@ public class PGraphicsOpenGL extends PGraphics { float v10z = z0 - z1; // The automatic normal calculation in Processing assumes - // that vertices as given in CCW order so: - // n = v12 x v10 - // so that the normal outwards. - float nx = v12y * v10z - v10y * v12z; - float ny = v12z * v10x - v10z * v12x; - float nz = v12x * v10y - v10x * v12y; + // that vertices are given by user in CCW order (left-handed), + // internally in CW order (right-handed) so: + // n = v10 x v12 + // so that the normal extends outwards from the front face. + float nx = v10y * v12z - v12y * v10z; + float ny = v10z * v12x - v12z * v10x; + float nz = v10x * v12y - v12x * v10y; + float d = PApplet.sqrt(nx * nx + ny * ny + nz * nz); nx /= d; ny /= d; @@ -7881,14 +7890,14 @@ public class PGraphicsOpenGL extends PGraphics { for (int i = 1; i < vertexCount - 1; i++) { int i1 = i; int i0, i2; - if (i % 2 == 0) { - // The even triangles (0, 2, 4...) should be CW - i0 = i + 1; - i2 = i - 1; - } else { - // The even triangles (1, 3, 5...) should be CCW + if (i % 2 == 1) { + // The odd triangles (1, 3, 5...) should be CCW (left-handed) i0 = i - 1; i2 = i + 1; + } else { + // The even triangles (2, 4, 6...) should be CW (left-handed) + i0 = i + 1; + i2 = i - 1; } calcTriangleNormal(i0, i1, i2); } @@ -7913,8 +7922,14 @@ public class PGraphicsOpenGL extends PGraphics { int i2 = 2 * qd; int i3 = 2 * qd + 1; - calcTriangleNormal(i0, i3, i1); - calcTriangleNormal(i0, i2, i3); + // Vertices are ordered as: + // 0-2 ... + // |/| ... + // 1-3 ... + // thus (0, 1, 2) and (2, 1, 3) are triangles + // in CCW order (left-handed). + calcTriangleNormal(i0, i1, i2); + calcTriangleNormal(i2, i1, i3); } } @@ -7988,26 +8003,20 @@ public class PGraphicsOpenGL extends PGraphics { void addRect(float a, float b, float c, float d, boolean stroke) { addQuad(a, b, 0, - c, b, 0, - c, d, 0, a, d, 0, + c, d, 0, + c, b, 0, stroke); } void addRect(float a, float b, float c, float d, float tl, float tr, float br, float bl, boolean stroke) { - if (nonZero(tr)) { - addVertex(c-tr, b, VERTEX, true); - addQuadraticVertex(c, b, 0, c, b+tr, 0, false); + if (nonZero(tl)) { + addVertex(a, b+tl, VERTEX, false); + addQuadraticVertex(a, b, 0, a+tl, b, 0, false); } else { - addVertex(c, b, VERTEX, true); - } - if (nonZero(br)) { - addVertex(c, d-br, VERTEX, false); - addQuadraticVertex(c, d, 0, c-br, d, 0, false); - } else { - addVertex(c, d, VERTEX, false); + addVertex(a, b, VERTEX, false); } if (nonZero(bl)) { addVertex(a+bl, d, VERTEX, false); @@ -8015,11 +8024,17 @@ public class PGraphicsOpenGL extends PGraphics { } else { addVertex(a, d, VERTEX, false); } - if (nonZero(tl)) { - addVertex(a, b+tl, VERTEX, false); - addQuadraticVertex(a, b, 0, a+tl, b, 0, false); + if (nonZero(br)) { + addVertex(c, d-br, VERTEX, false); + addQuadraticVertex(c, d, 0, c-br, d, 0, false); } else { - addVertex(a, b, VERTEX, false); + addVertex(c, d, VERTEX, false); + } + if (nonZero(tr)) { + addVertex(c-tr, b, VERTEX, true); + addQuadraticVertex(c, b, 0, c, b+tr, 0, false); + } else { + addVertex(c, b, VERTEX, true); } } @@ -8051,7 +8066,7 @@ public class PGraphicsOpenGL extends PGraphics { float val = 0; for (int i = 0; i < accuracy; i++) { idx = addVertex(centerX + cosLUT[(int) val] * radiusH, - centerY + sinLUT[(int) val] * radiusV, + centerY - sinLUT[(int) val] * radiusV, VERTEX, i == 0 && !fill); val = (val + inc) % SINCOS_LENGTH; @@ -8136,6 +8151,18 @@ public class PGraphicsOpenGL extends PGraphics { void addBox(float w, float h, float d, boolean fill, boolean stroke) { + + // Correct normals if some dimensions are negative so they always + // extend from front face. We could just take absolute value + // of dimensions, but that would affect texturing. + boolean invertNormX = (h > 0) != (d > 0); + boolean invertNormY = (w > 0) != (d > 0); + boolean invertNormZ = (w > 0) != (h > 0); + + int normX = invertNormX ? -1 : 1; + int normY = invertNormY ? -1 : 1; + int normZ = invertNormZ ? -1 : 1; + float x1 = -w/2f; float x2 = w/2f; float y1 = -h/2f; float y2 = h/2f; float z1 = -d/2f; float z2 = d/2f; @@ -8143,7 +8170,7 @@ public class PGraphicsOpenGL extends PGraphics { int idx1 = 0, idx2 = 0, idx3 = 0, idx4 = 0; if (fill || stroke) { // back face - setNormal(0, 0, -1); + setNormal(0, 0, -normZ); idx1 = addVertex(x1, y1, z1, 0, 0, VERTEX, true); idx2 = addVertex(x2, y1, z1, 1, 0, VERTEX, false); idx3 = addVertex(x2, y2, z1, 1, 1, VERTEX, false); @@ -8157,7 +8184,7 @@ public class PGraphicsOpenGL extends PGraphics { } // front face - setNormal(0, 0, 1); + setNormal(0, 0, normZ); idx1 = addVertex(x2, y1, z2, 0, 0, VERTEX, false); idx2 = addVertex(x1, y1, z2, 1, 0, VERTEX, false); idx3 = addVertex(x1, y2, z2, 1, 1, VERTEX, false); @@ -8171,7 +8198,7 @@ public class PGraphicsOpenGL extends PGraphics { } // right face - setNormal(1, 0, 0); + setNormal(normX, 0, 0); idx1 = addVertex(x2, y1, z1, 0, 0, VERTEX, false); idx2 = addVertex(x2, y1, z2, 1, 0, VERTEX, false); idx3 = addVertex(x2, y2, z2, 1, 1, VERTEX, false); @@ -8185,7 +8212,7 @@ public class PGraphicsOpenGL extends PGraphics { } // left face - setNormal(-1, 0, 0); + setNormal(-normX, 0, 0); idx1 = addVertex(x1, y1, z2, 0, 0, VERTEX, false); idx2 = addVertex(x1, y1, z1, 1, 0, VERTEX, false); idx3 = addVertex(x1, y2, z1, 1, 1, VERTEX, false); @@ -8198,8 +8225,8 @@ public class PGraphicsOpenGL extends PGraphics { closeEdge(idx4, idx1); } - // bottom face - setNormal(0, -1, 0); + // top face + setNormal(0, -normY, 0); idx1 = addVertex(x1, y1, z2, 0, 0, VERTEX, false); idx2 = addVertex(x2, y1, z2, 1, 0, VERTEX, false); idx3 = addVertex(x2, y1, z1, 1, 1, VERTEX, false); @@ -8212,8 +8239,8 @@ public class PGraphicsOpenGL extends PGraphics { closeEdge(idx4, idx1); } - // top face - setNormal(0, 1, 0); + // bottom face + setNormal(0, normY, 0); idx1 = addVertex(x1, y2, z1, 0, 0, VERTEX, false); idx2 = addVertex(x2, y2, z1, 1, 0, VERTEX, false); idx3 = addVertex(x2, y2, z2, 1, 1, VERTEX, false); @@ -8274,8 +8301,8 @@ public class PGraphicsOpenGL extends PGraphics { int i1 = vert0 + i; int i0 = vert0 + i - detailU; - indices[3 * i + 0] = i1; - indices[3 * i + 1] = i0; + indices[3 * i + 0] = i0; + indices[3 * i + 1] = i1; indices[3 * i + 2] = i1 + 1; addEdge(i0, i1, true, true); @@ -8308,13 +8335,13 @@ public class PGraphicsOpenGL extends PGraphics { int i1 = vert0 + i; int i0 = vert0 + i - detailU - 1; - indices[indCount + 6 * i + 0] = i1; - indices[indCount + 6 * i + 1] = i0; + indices[indCount + 6 * i + 0] = i0; + indices[indCount + 6 * i + 1] = i1; indices[indCount + 6 * i + 2] = i0 + 1; indices[indCount + 6 * i + 3] = i1; - indices[indCount + 6 * i + 4] = i0 + 1; - indices[indCount + 6 * i + 5] = i1 + 1; + indices[indCount + 6 * i + 4] = i1 + 1; + indices[indCount + 6 * i + 5] = i0 + 1; addEdge(i0, i1, true, true); addEdge(i1, i1 + 1, true, true); @@ -9200,9 +9227,15 @@ public class PGraphicsOpenGL extends PGraphics { float v10y = y0 - y1; float v10z = z0 - z1; - float nx = v12y * v10z - v10y * v12z; - float ny = v12z * v10x - v10z * v12x; - float nz = v12x * v10y - v10x * v12y; + // The automatic normal calculation in Processing assumes + // that vertices are given by user in CCW order (left-handed), + // internally in CW order (right-handed) so: + // n = v10 x v12 + // so that the normal extends outwards from the front face. + float nx = v10y * v12z - v12y * v10z; + float ny = v10z * v12x - v12z * v10x; + float nz = v10x * v12y - v12x * v10y; + float d = PApplet.sqrt(nx * nx + ny * ny + nz * nz); nx /= d; ny /= d; From 6df349b68e9fcf9f5934e8613cb348b084284363 Mon Sep 17 00:00:00 2001 From: Jakub Valtar Date: Sun, 13 Jul 2014 22:33:37 +0200 Subject: [PATCH 3/8] new Arc implementation for OpenGL renderers --- core/src/processing/core/PGraphics.java | 4 +- .../processing/opengl/PGraphicsOpenGL.java | 109 ++++++++++++------ 2 files changed, 76 insertions(+), 37 deletions(-) diff --git a/core/src/processing/core/PGraphics.java b/core/src/processing/core/PGraphics.java index 5151ae64d..7ad1d26ba 100644 --- a/core/src/processing/core/PGraphics.java +++ b/core/src/processing/core/PGraphics.java @@ -2664,8 +2664,8 @@ public class PGraphics extends PImage implements PConstants { } if (stop - start > TWO_PI) { - start = 0; - stop = TWO_PI; + // don't change start, it is visible in PIE mode + stop = start + TWO_PI; } arcImpl(x, y, w, h, start, stop, mode); } diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index e824bb295..419c4b8fd 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -3242,9 +3242,8 @@ public class PGraphicsOpenGL extends PGraphics { normalMode = NORMAL_MODE_SHAPE; inGeo.setMaterial(fillColor, strokeColor, strokeWeight, ambientColor, specularColor, emissiveColor, shininess); - // TODO: Arc should be drawn in CCW order (left-handed) - // Temp fix: invert arc normal - inGeo.setNormal(normalX, normalY, -normalZ); + + inGeo.setNormal(normalX, normalY, normalZ); inGeo.addArc(x, y, w, h, start, stop, fill, stroke, mode); endShape(); } @@ -8101,50 +8100,90 @@ public class PGraphicsOpenGL extends PGraphics { int startLUT = (int) (0.5f + (start / TWO_PI) * SINCOS_LENGTH); int stopLUT = (int) (0.5f + (stop / TWO_PI) * SINCOS_LENGTH); - int idx0 = addVertex(centerX, centerY, VERTEX, true); + // get length before wrapping indexes so (startLUT <= stopLUT); + int length = PApplet.constrain(stopLUT - startLUT, 0, SINCOS_LENGTH); - int increment = 1; // what's a good algorithm? stopLUT - startLUT; - int pidx = 0, idx = 0; - for (int i = startLUT; i < stopLUT; i += increment) { - int ii = i % SINCOS_LENGTH; - // modulo won't make the value positive + boolean fullCircle = length == SINCOS_LENGTH; + + if (fullCircle && arcMode == CHORD) { + // get rid of overlapping vertices, + // solves problem with closing edge in P3D + length -= 1; + stopLUT -= 1; + } + + { // wrap indexes so they are safe to use in LUT + startLUT %= SINCOS_LENGTH; + if (startLUT < 0) startLUT += SINCOS_LENGTH; + + stopLUT %= SINCOS_LENGTH; + if (stopLUT < 0) stopLUT += SINCOS_LENGTH; + } + + int idx0; + if (arcMode == CHORD || arcMode == OPEN) { + // move center to the middle of flat side + // to properly display arcs smaller than PI + float relX = (cosLUT[startLUT] + cosLUT[stopLUT]) * 0.5f * hr; + float relY = (sinLUT[startLUT] + sinLUT[stopLUT]) * 0.5f * vr; + idx0 = addVertex(centerX + relX, centerY + relY, VERTEX, true); + } else { + idx0 = addVertex(centerX, centerY, VERTEX, true); + } + + int inc; + { // initializes inc the same way ellipse does + float sx1 = pg.screenX(x, y); + float sy1 = pg.screenY(x, y); + float sx2 = pg.screenX(x + w, y + h); + float sy2 = pg.screenY(x + w, y + h); + + int accuracy = + PApplet.min(MAX_POINT_ACCURACY, PApplet.max(MIN_POINT_ACCURACY, + (int) (TWO_PI * PApplet.dist(sx1, sy1, sx2, sy2) / + POINT_ACCURACY_FACTOR))); + inc = PApplet.max(1, SINCOS_LENGTH / accuracy); + } + + int idx = idx0; + int pidx; + + int i = -inc; + int ii; + + // i: (0 -> length) inclusive + // ii: (stopLUT -> startLUT) inclusive, going CCW (left-handed), + // wrapping around end of LUT + do { + i += inc; + i = PApplet.min(i, length); // clamp so last vertex won't go over + + ii = stopLUT - i; // ii is never smaller than -SINCOS_LENGTH if (ii < 0) ii += SINCOS_LENGTH; + + pidx = idx; idx = addVertex(centerX + cosLUT[ii] * hr, centerY + sinLUT[ii] * vr, - VERTEX, i == startLUT && !fill); + VERTEX, i == 0 && !fill); if (stroke) { - if (arcMode == PIE) { - addEdge(pidx, idx, i == startLUT, false); - } else if (startLUT < i) { - addEdge(pidx, idx, i == startLUT + 1, arcMode == 0 && - i == stopLUT - 1); + if (arcMode == CHORD || arcMode == PIE) { + addEdge(pidx, idx, i == 0, false); + } else if (0 < i) { + // when drawing full circle, the edge is closed later + addEdge(pidx, idx, i == inc, i == length && !fullCircle); } } + } while (i < length); + + // keeping last vertex as idx and second last vertex as pidx - pidx = idx; - } - // draw last point explicitly for accuracy - idx = addVertex(centerX + cosLUT[stopLUT % SINCOS_LENGTH] * hr, - centerY + sinLUT[stopLUT % SINCOS_LENGTH] * vr, - VERTEX, false); if (stroke) { - if (arcMode == PIE) { + if (arcMode == CHORD || arcMode == PIE) { addEdge(idx, idx0, false, false); closeEdge(idx, idx0); - } - } - if (arcMode == CHORD || arcMode == OPEN) { - // Add a last vertex coincident with the first along the perimeter - pidx = idx; - int i = startLUT; - int ii = i % SINCOS_LENGTH; - if (ii < 0) ii += SINCOS_LENGTH; - idx = addVertex(centerX + cosLUT[ii] * hr, - centerY + sinLUT[ii] * vr, - VERTEX, false); - if (stroke && arcMode == CHORD) { - addEdge(pidx, idx, false, true); + } else if (fullCircle) { + closeEdge(pidx, idx); } } } From 72b95f671131950a689f847c22f889fc00d0723d Mon Sep 17 00:00:00 2001 From: Jakub Valtar Date: Tue, 15 Jul 2014 00:38:54 +0200 Subject: [PATCH 4/8] fixes #2619 After a call to get()/set(), pixels array has been treated as up-to-date even though user has been drawing. Because of this, loadPixels() was not updating pixels array with changes. --- core/src/processing/opengl/PGraphicsOpenGL.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index f177bfa67..643e63343 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -379,8 +379,8 @@ public class PGraphicsOpenGL extends PGraphics { /** PImage that wraps filterTexture. */ protected PImage filterImage; - /** Flag to indicate if the user is manipulating the - * pixels array through the set()/get() methods */ + /** Flag to indicate that pixels array is up-to-date and + * ready to be manipulated through the set()/get() methods */ protected boolean setgetPixels; // ........................................................ @@ -2133,6 +2133,9 @@ public class PGraphicsOpenGL extends PGraphics { shape = kind; inGeo.clear(); + // We are going to draw, pixels won't be up-to-date anymore. + setgetPixels = false; + curveVertexCount = 0; breakShape = false; defaultEdges = true; @@ -5447,6 +5450,9 @@ public class PGraphicsOpenGL extends PGraphics { readPixels(); } + // Pixels are now up-to-date, set the flag. + setgetPixels = true; + if (needEndDraw) { endDraw(); } @@ -5566,7 +5572,6 @@ public class PGraphicsOpenGL extends PGraphics { @Override public int get(int x, int y) { loadPixels(); - setgetPixels = true; return super.get(x, y); } @@ -5576,7 +5581,6 @@ public class PGraphicsOpenGL extends PGraphics { int sourceWidth, int sourceHeight, PImage target, int targetX, int targetY) { loadPixels(); - setgetPixels = true; super.getImpl(sourceX, sourceY, sourceWidth, sourceHeight, target, targetX, targetY); } @@ -5585,7 +5589,6 @@ public class PGraphicsOpenGL extends PGraphics { @Override public void set(int x, int y, int argb) { loadPixels(); - setgetPixels = true; super.set(x, y, argb); } @@ -5596,7 +5599,6 @@ public class PGraphicsOpenGL extends PGraphics { int sourceWidth, int sourceHeight, int targetX, int targetY) { loadPixels(); - setgetPixels = true; super.setImpl(sourceImage, sourceX, sourceY, sourceWidth, sourceHeight, targetX, targetY); // do we need this? From b2899c63ceaa1acf9db6853baff2cd7fa0dc41d5 Mon Sep 17 00:00:00 2001 From: Jakub Valtar Date: Tue, 22 Jul 2014 16:40:09 +0200 Subject: [PATCH 5/8] Moved pixels invalidation to endShape Moved to account for a possibility that user uses get(), set() or loadPixels() inside of beginShape()/endShape() block. --- core/src/processing/opengl/PGraphicsOpenGL.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index 643e63343..38d11e2c3 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -2133,9 +2133,6 @@ public class PGraphicsOpenGL extends PGraphics { shape = kind; inGeo.clear(); - // We are going to draw, pixels won't be up-to-date anymore. - setgetPixels = false; - curveVertexCount = 0; breakShape = false; defaultEdges = true; @@ -2154,6 +2151,9 @@ public class PGraphicsOpenGL extends PGraphics { if ((flushMode == FLUSH_CONTINUOUSLY) || (flushMode == FLUSH_WHEN_FULL && tessGeo.isFull())) { flush(); + } else { + // pixels array is not up-to-date anymore + setgetPixels = false; } } @@ -2169,6 +2169,9 @@ public class PGraphicsOpenGL extends PGraphics { if (flushMode == FLUSH_CONTINUOUSLY || (flushMode == FLUSH_WHEN_FULL && tessGeo.isFull())) { flush(); + } else { + // pixels array is not up-to-date anymore + setgetPixels = false; } } From 8853ef40a96402b4583ba1d132a2c14b22935f0c Mon Sep 17 00:00:00 2001 From: Jakub Valtar Date: Tue, 22 Jul 2014 16:46:03 +0200 Subject: [PATCH 6/8] Changed setgetPixels to arePixelsUpToDate Changed the name to better reflect the purpose of the variable. --- core/src/processing/opengl/PGraphicsOpenGL.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index 38d11e2c3..1edfdc438 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -381,7 +381,7 @@ public class PGraphicsOpenGL extends PGraphics { /** Flag to indicate that pixels array is up-to-date and * ready to be manipulated through the set()/get() methods */ - protected boolean setgetPixels; + protected boolean arePixelsUpToDate; // ........................................................ @@ -2153,7 +2153,7 @@ public class PGraphicsOpenGL extends PGraphics { flush(); } else { // pixels array is not up-to-date anymore - setgetPixels = false; + arePixelsUpToDate = false; } } @@ -2171,7 +2171,7 @@ public class PGraphicsOpenGL extends PGraphics { flush(); } else { // pixels array is not up-to-date anymore - setgetPixels = false; + arePixelsUpToDate = false; } } @@ -2449,7 +2449,7 @@ public class PGraphicsOpenGL extends PGraphics { tessGeo.clear(); texCache.clear(); - setgetPixels = false; + arePixelsUpToDate = false; } @@ -5441,7 +5441,7 @@ public class PGraphicsOpenGL extends PGraphics { needEndDraw = true; } - if (!setgetPixels) { + if (!arePixelsUpToDate) { // Draws any remaining geometry in case the user is still not // setting/getting new pixels. flush(); @@ -5449,12 +5449,12 @@ public class PGraphicsOpenGL extends PGraphics { allocatePixels(); - if (!setgetPixels) { + if (!arePixelsUpToDate) { readPixels(); } // Pixels are now up-to-date, set the flag. - setgetPixels = true; + arePixelsUpToDate = true; if (needEndDraw) { endDraw(); @@ -6574,7 +6574,7 @@ public class PGraphicsOpenGL extends PGraphics { clearColorBuffer = false; modified = false; - setgetPixels = false; + arePixelsUpToDate = false; } From e93ffbbfb368033730e710775e7fe0715623e0ff Mon Sep 17 00:00:00 2001 From: Jakub Valtar Date: Tue, 22 Jul 2014 18:31:57 +0200 Subject: [PATCH 7/8] corrected expected front face orientation CCW -> CW --- core/src/processing/core/PGraphics.java | 2 +- .../processing/opengl/PGraphicsOpenGL.java | 138 +++++++++--------- 2 files changed, 69 insertions(+), 71 deletions(-) diff --git a/core/src/processing/core/PGraphics.java b/core/src/processing/core/PGraphics.java index 7ad1d26ba..7d950eecc 100644 --- a/core/src/processing/core/PGraphics.java +++ b/core/src/processing/core/PGraphics.java @@ -2405,7 +2405,7 @@ public class PGraphics extends PImage implements PConstants { protected void rectImpl(float x1, float y1, float x2, float y2) { - quad(x1, y1, x1, y2, x2, y2, x2, y1); + quad(x1, y1, x2, y1, x2, y2, x1, y2); } diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index 419c4b8fd..1e74f305d 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -1827,7 +1827,7 @@ public class PGraphicsOpenGL extends PGraphics { pgl.disable(PGL.SCISSOR_TEST); } - pgl.frontFace(PGL.CCW); + pgl.frontFace(PGL.CW); pgl.disable(PGL.CULL_FACE); pgl.activeTexture(PGL.TEXTURE0); @@ -6537,13 +6537,13 @@ public class PGraphicsOpenGL extends PGraphics { lightSpecular(0, 0, 0); } - // Vertices should be specified by user in CCW order (left-handed) - // That is CW order (right-handed). Vertex shader inverts - // Y-axis and outputs vertices in CCW order (right-handed). + // Vertices should be specified by user in CW order (left-handed) + // That is CCW order (right-handed). Vertex shader inverts + // Y-axis and outputs vertices in CW order (right-handed). // Culling occurs after the vertex shader, so FRONT FACE - // has to be set to CCW (right-handed) for OpenGL to correctly + // has to be set to CW (right-handed) for OpenGL to correctly // recognize FRONT and BACK faces. - pgl.frontFace(PGL.CCW); + pgl.frontFace(PGL.CW); pgl.disable(PGL.CULL_FACE); // Processing uses only one texture unit. @@ -7809,6 +7809,7 @@ public class PGraphicsOpenGL extends PGraphics { // // Normal calculation + // Expects vertices in CW (left-handed) order. void calcTriangleNormal(int i0, int i1, int i2) { int index; @@ -7836,14 +7837,12 @@ public class PGraphicsOpenGL extends PGraphics { float v10z = z0 - z1; // The automatic normal calculation in Processing assumes - // that vertices are given by user in CCW order (left-handed), - // internally in CW order (right-handed) so: - // n = v10 x v12 - // so that the normal extends outwards from the front face. - float nx = v10y * v12z - v12y * v10z; - float ny = v10z * v12x - v12z * v10x; - float nz = v10x * v12y - v12x * v10y; - + // that vertices as given in CCW order (right-handed) so: + // n = v12 x v10 + // so that the normal extends from the front face. + float nx = v12y * v10z - v10y * v12z; + float ny = v12z * v10x - v10z * v12x; + float nz = v12x * v10y - v10x * v12y; float d = PApplet.sqrt(nx * nx + ny * ny + nz * nz); nx /= d; ny /= d; @@ -7889,12 +7888,16 @@ public class PGraphicsOpenGL extends PGraphics { for (int i = 1; i < vertexCount - 1; i++) { int i1 = i; int i0, i2; + // Vertices are specified by user as: + // 1-3 ... + // |\|\ ... + // 0-2-4 ... if (i % 2 == 1) { - // The odd triangles (1, 3, 5...) should be CCW (left-handed) + // The odd triangles (1, 3, 5...) should be CW (left-handed) i0 = i - 1; i2 = i + 1; } else { - // The even triangles (2, 4, 6...) should be CW (left-handed) + // The even triangles (2, 4, 6...) should be CCW (left-handed) i0 = i + 1; i2 = i - 1; } @@ -7921,12 +7924,12 @@ public class PGraphicsOpenGL extends PGraphics { int i2 = 2 * qd; int i3 = 2 * qd + 1; - // Vertices are ordered as: - // 0-2 ... - // |/| ... - // 1-3 ... + // Vertices are specified by user as: + // 1-3-5 ... + // |\|\| ... + // 0-2-4 ... // thus (0, 1, 2) and (2, 1, 3) are triangles - // in CCW order (left-handed). + // in CW order (left-handed). calcTriangleNormal(i0, i1, i2); calcTriangleNormal(i2, i1, i3); } @@ -8002,26 +8005,20 @@ public class PGraphicsOpenGL extends PGraphics { void addRect(float a, float b, float c, float d, boolean stroke) { addQuad(a, b, 0, - a, d, 0, - c, d, 0, c, b, 0, + c, d, 0, + a, d, 0, stroke); } void addRect(float a, float b, float c, float d, float tl, float tr, float br, float bl, boolean stroke) { - if (nonZero(tl)) { - addVertex(a, b+tl, VERTEX, false); - addQuadraticVertex(a, b, 0, a+tl, b, 0, false); + if (nonZero(tr)) { + addVertex(c-tr, b, VERTEX, true); + addQuadraticVertex(c, b, 0, c, b+tr, 0, false); } else { - addVertex(a, b, VERTEX, false); - } - if (nonZero(bl)) { - addVertex(a+bl, d, VERTEX, false); - addQuadraticVertex(a, d, 0, a, d-bl, 0, false); - } else { - addVertex(a, d, VERTEX, false); + addVertex(c, b, VERTEX, true); } if (nonZero(br)) { addVertex(c, d-br, VERTEX, false); @@ -8029,11 +8026,17 @@ public class PGraphicsOpenGL extends PGraphics { } else { addVertex(c, d, VERTEX, false); } - if (nonZero(tr)) { - addVertex(c-tr, b, VERTEX, true); - addQuadraticVertex(c, b, 0, c, b+tr, 0, false); + if (nonZero(bl)) { + addVertex(a+bl, d, VERTEX, false); + addQuadraticVertex(a, d, 0, a, d-bl, 0, false); } else { - addVertex(c, b, VERTEX, true); + addVertex(a, d, VERTEX, false); + } + if (nonZero(tl)) { + addVertex(a, b+tl, VERTEX, false); + addQuadraticVertex(a, b, 0, a+tl, b, 0, false); + } else { + addVertex(a, b, VERTEX, false); } } @@ -8065,7 +8068,7 @@ public class PGraphicsOpenGL extends PGraphics { float val = 0; for (int i = 0; i < accuracy; i++) { idx = addVertex(centerX + cosLUT[(int) val] * radiusH, - centerY - sinLUT[(int) val] * radiusV, + centerY + sinLUT[(int) val] * radiusV, VERTEX, i == 0 && !fill); val = (val + inc) % SINCOS_LENGTH; @@ -8152,14 +8155,14 @@ public class PGraphicsOpenGL extends PGraphics { int ii; // i: (0 -> length) inclusive - // ii: (stopLUT -> startLUT) inclusive, going CCW (left-handed), + // ii: (startLUT -> stopLUT) inclusive, going CW (left-handed), // wrapping around end of LUT do { i += inc; i = PApplet.min(i, length); // clamp so last vertex won't go over - ii = stopLUT - i; // ii is never smaller than -SINCOS_LENGTH - if (ii < 0) ii += SINCOS_LENGTH; + ii = startLUT + i; // ii from 0 to (2 * SINCOS_LENGTH - 1) + if (ii >= SINCOS_LENGTH) ii -= SINCOS_LENGTH; pidx = idx; idx = addVertex(centerX + cosLUT[ii] * hr, @@ -8211,9 +8214,9 @@ public class PGraphicsOpenGL extends PGraphics { // back face setNormal(0, 0, -normZ); idx1 = addVertex(x1, y1, z1, 0, 0, VERTEX, true); - idx2 = addVertex(x2, y1, z1, 1, 0, VERTEX, false); + idx2 = addVertex(x1, y2, z1, 0, 1, VERTEX, false); idx3 = addVertex(x2, y2, z1, 1, 1, VERTEX, false); - idx4 = addVertex(x1, y2, z1, 0, 1, VERTEX, false); + idx4 = addVertex(x2, y1, z1, 1, 0, VERTEX, false); if (stroke) { addEdge(idx1, idx2, true, false); addEdge(idx2, idx3, false, false); @@ -8224,9 +8227,9 @@ public class PGraphicsOpenGL extends PGraphics { // front face setNormal(0, 0, normZ); - idx1 = addVertex(x2, y1, z2, 0, 0, VERTEX, false); + idx1 = addVertex(x1, y2, z2, 1, 1, VERTEX, false); idx2 = addVertex(x1, y1, z2, 1, 0, VERTEX, false); - idx3 = addVertex(x1, y2, z2, 1, 1, VERTEX, false); + idx3 = addVertex(x2, y1, z2, 0, 0, VERTEX, false); idx4 = addVertex(x2, y2, z2, 0, 1, VERTEX, false); if (stroke) { addEdge(idx1, idx2, true, false); @@ -8239,9 +8242,9 @@ public class PGraphicsOpenGL extends PGraphics { // right face setNormal(normX, 0, 0); idx1 = addVertex(x2, y1, z1, 0, 0, VERTEX, false); - idx2 = addVertex(x2, y1, z2, 1, 0, VERTEX, false); + idx2 = addVertex(x2, y2, z1, 0, 1, VERTEX, false); idx3 = addVertex(x2, y2, z2, 1, 1, VERTEX, false); - idx4 = addVertex(x2, y2, z1, 0, 1, VERTEX, false); + idx4 = addVertex(x2, y1, z2, 1, 0, VERTEX, false); if (stroke) { addEdge(idx1, idx2, true, false); addEdge(idx2, idx3, false, false); @@ -8252,9 +8255,9 @@ public class PGraphicsOpenGL extends PGraphics { // left face setNormal(-normX, 0, 0); - idx1 = addVertex(x1, y1, z2, 0, 0, VERTEX, false); + idx1 = addVertex(x1, y2, z1, 1, 1, VERTEX, false); idx2 = addVertex(x1, y1, z1, 1, 0, VERTEX, false); - idx3 = addVertex(x1, y2, z1, 1, 1, VERTEX, false); + idx3 = addVertex(x1, y1, z2, 0, 0, VERTEX, false); idx4 = addVertex(x1, y2, z2, 0, 1, VERTEX, false); if (stroke) { addEdge(idx1, idx2, true, false); @@ -8266,9 +8269,9 @@ public class PGraphicsOpenGL extends PGraphics { // top face setNormal(0, -normY, 0); - idx1 = addVertex(x1, y1, z2, 0, 0, VERTEX, false); + idx1 = addVertex(x2, y1, z1, 1, 1, VERTEX, false); idx2 = addVertex(x2, y1, z2, 1, 0, VERTEX, false); - idx3 = addVertex(x2, y1, z1, 1, 1, VERTEX, false); + idx3 = addVertex(x1, y1, z2, 0, 0, VERTEX, false); idx4 = addVertex(x1, y1, z1, 0, 1, VERTEX, false); if (stroke) { addEdge(idx1, idx2, true, false); @@ -8281,9 +8284,9 @@ public class PGraphicsOpenGL extends PGraphics { // bottom face setNormal(0, normY, 0); idx1 = addVertex(x1, y2, z1, 0, 0, VERTEX, false); - idx2 = addVertex(x2, y2, z1, 1, 0, VERTEX, false); + idx2 = addVertex(x1, y2, z2, 0, 1, VERTEX, false); idx3 = addVertex(x2, y2, z2, 1, 1, VERTEX, false); - idx4 = addVertex(x1, y2, z2, 0, 1, VERTEX, false); + idx4 = addVertex(x2, y2, z1, 1, 0, VERTEX, false); if (stroke) { addEdge(idx1, idx2, true, false); addEdge(idx2, idx3, false, false); @@ -8340,8 +8343,8 @@ public class PGraphicsOpenGL extends PGraphics { int i1 = vert0 + i; int i0 = vert0 + i - detailU; - indices[3 * i + 0] = i0; - indices[3 * i + 1] = i1; + indices[3 * i + 0] = i1; + indices[3 * i + 1] = i0; indices[3 * i + 2] = i1 + 1; addEdge(i0, i1, true, true); @@ -8374,13 +8377,13 @@ public class PGraphicsOpenGL extends PGraphics { int i1 = vert0 + i; int i0 = vert0 + i - detailU - 1; - indices[indCount + 6 * i + 0] = i0; - indices[indCount + 6 * i + 1] = i1; + indices[indCount + 6 * i + 0] = i1; + indices[indCount + 6 * i + 1] = i0; indices[indCount + 6 * i + 2] = i0 + 1; indices[indCount + 6 * i + 3] = i1; - indices[indCount + 6 * i + 4] = i1 + 1; - indices[indCount + 6 * i + 5] = i0 + 1; + indices[indCount + 6 * i + 4] = i0 + 1; + indices[indCount + 6 * i + 5] = i1 + 1; addEdge(i0, i1, true, true); addEdge(i1, i1 + 1, true, true); @@ -8413,8 +8416,8 @@ public class PGraphicsOpenGL extends PGraphics { int i0 = vert0 + i; int i1 = vert0 + i + detailU + 1; - indices[indCount + 3 * i + 0] = i0; - indices[indCount + 3 * i + 1] = i1; + indices[indCount + 3 * i + 0] = i1; + indices[indCount + 3 * i + 1] = i0; indices[indCount + 3 * i + 2] = i0 + 1; addEdge(i0, i0 + 1, true, true); @@ -9240,6 +9243,7 @@ public class PGraphicsOpenGL extends PGraphics { // // Normal calculation + // Expects vertices in CW (left-handed) order. void calcPolyNormal(int i0, int i1, int i2) { int index; @@ -9266,15 +9270,9 @@ public class PGraphicsOpenGL extends PGraphics { float v10y = y0 - y1; float v10z = z0 - z1; - // The automatic normal calculation in Processing assumes - // that vertices are given by user in CCW order (left-handed), - // internally in CW order (right-handed) so: - // n = v10 x v12 - // so that the normal extends outwards from the front face. - float nx = v10y * v12z - v12y * v10z; - float ny = v10z * v12x - v12z * v10x; - float nz = v10x * v12y - v12x * v10y; - + float nx = v12y * v10z - v10y * v12z; + float ny = v12z * v10x - v10z * v12x; + float nz = v12x * v10y - v10x * v12y; float d = PApplet.sqrt(nx * nx + ny * ny + nz * nz); nx /= d; ny /= d; From 90f84a3b94aa16629ff8591ceafcac4a48728042 Mon Sep 17 00:00:00 2001 From: codeanticode Date: Tue, 22 Jul 2014 17:28:05 -0400 Subject: [PATCH 8/8] should fix #2630 --- core/src/processing/opengl/PJOGL.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/processing/opengl/PJOGL.java b/core/src/processing/opengl/PJOGL.java index 9957204c8..9aa70d2d1 100644 --- a/core/src/processing/opengl/PJOGL.java +++ b/core/src/processing/opengl/PJOGL.java @@ -167,7 +167,7 @@ public class PJOGL extends PGL { /** This countdown latch is used to maintain the synchronization between * Processing's drawing thread and JOGL's rendering thread */ - protected CountDownLatch drawLatch; + protected CountDownLatch drawLatch = new CountDownLatch(0); /** Flag used to do request final display() call to make sure that the * buffers are properly swapped.