diff --git a/core/src/processing/core/PShape.java b/core/src/processing/core/PShape.java index 415904433..a9317776c 100644 --- a/core/src/processing/core/PShape.java +++ b/core/src/processing/core/PShape.java @@ -205,6 +205,8 @@ public class PShape implements PConstants { /** True if colorMode(RGB, 255) */ boolean colorModeDefault; // = true; + /** True if contains 3D data */ + protected boolean is3D = false; // should this be called vertices (consistent with PGraphics internals) // or does that hurt flexibility? @@ -430,7 +432,7 @@ public class PShape implements PConstants { * Return true if this shape is 2D. Defaults to true. */ public boolean is2D() { - return true; + return !is3D; } @@ -438,7 +440,12 @@ public class PShape implements PConstants { * Return true if this shape is 3D. Defaults to false. */ public boolean is3D() { - return false; + return is3D; + } + + + public void is3D(boolean val) { + is3D = val; } @@ -840,9 +847,13 @@ public class PShape implements PConstants { // s.emissive(vert[ER] * 255, vert[EG] * 255, vert[EB] * 255); // s.shininess(vert[SHINE]); - dest.normal(vert[PGraphics.NX], - vert[PGraphics.NY], - vert[PGraphics.NZ]); + if (0 < PApplet.dist(vert[PGraphics.NX], + vert[PGraphics.NY], + vert[PGraphics.NZ], 0, 0, 0)) { + dest.normal(vert[PGraphics.NX], + vert[PGraphics.NY], + vert[PGraphics.NZ]); + } dest.vertex(vert[X], vert[Y], vert[Z], vert[PGraphics.U], vert[PGraphics.V]); diff --git a/core/src/processing/core/PShapeOBJ.java b/core/src/processing/core/PShapeOBJ.java new file mode 100644 index 000000000..b9be8db68 --- /dev/null +++ b/core/src/processing/core/PShapeOBJ.java @@ -0,0 +1,409 @@ +package processing.core; + +import java.io.BufferedReader; +import java.util.ArrayList; +import java.util.Hashtable; + +/** + * OBJ loading implemented using code from Saito's OBJLoader library: + * http://code.google.com/p/saitoobjloader/ + * and OBJReader from Ahmet Kizilay + * http://www.openprocessing.org/visuals/?visualID=191 + * + */ +public class PShapeOBJ extends PShape { + + /** + * Initializes a new OBJ Object with the given filename. + */ + public PShapeOBJ(PApplet parent, String filename) { + this(parent, parent.createReader(filename)); + } + + + public PShapeOBJ(PApplet parent, BufferedReader reader) { + ArrayList faces = new ArrayList(); + ArrayList materials = new ArrayList(); + ArrayList coords = new ArrayList(); + ArrayList normals = new ArrayList(); + ArrayList texcoords = new ArrayList(); + parseOBJ(parent, reader, faces, materials, coords, normals, texcoords); + + // The OBJ geometry is stored with each face in a separate child shape. + parent = null; + family = GROUP; + addChildren(faces, materials, coords, normals, texcoords); + } + + + protected PShapeOBJ(OBJFace face, OBJMaterial mtl, + ArrayList coords, + ArrayList normals, + ArrayList texcoords) { + family = GEOMETRY; + if (face.vertIdx.size() == 3) { + kind = TRIANGLES; + } else if (face.vertIdx.size() == 4) { + kind = QUADS; + } else { + kind = POLYGON; + } + + // Setting material properties for the new face + fillColor = rgbaValue(mtl.kd); + ambientColor = rgbaValue(mtl.ka); + specularColor = rgbaValue(mtl.ks); + shininess = mtl.ns; + if (mtl.kdMap != null) { + // If current material is textured, then tinting the texture using the + // diffuse color. + tintColor = rgbaValue(mtl.kd, mtl.d); + } + + vertexCount = face.vertIdx.size(); + vertices = new float[vertexCount][12]; + for (int j = 0; j < face.vertIdx.size(); j++){ + int vertIdx, normIdx; + PVector vert, norms; + + vert = norms = null; + + vertIdx = face.vertIdx.get(j).intValue() - 1; + vert = coords.get(vertIdx); + + if (j < face.normIdx.size()) { + normIdx = face.normIdx.get(j).intValue() - 1; + if (-1 < normIdx) { + norms = normals.get(normIdx); + } + } + + vertices[j][X] = vert.x; + vertices[j][Y] = vert.y; + vertices[j][Z] = vert.z; + + vertices[j][PGraphics.R] = mtl.kd.x; + vertices[j][PGraphics.B] = mtl.kd.y; + vertices[j][PGraphics.G] = mtl.kd.z; + vertices[j][PGraphics.A] = 1; + + if (norms != null) { + vertices[j][PGraphics.NX] = norms.x; + vertices[j][PGraphics.NY] = norms.y; + vertices[j][PGraphics.NZ] = norms.z; + } + + if (mtl != null && mtl.kdMap != null) { + // This face is textured. + int texIdx; + PVector tex = null; + + if (j < face.texIdx.size()) { + texIdx = face.texIdx.get(j).intValue() - 1; + if (-1 < texIdx) { + tex = texcoords.get(texIdx); + } + } + + image = mtl.kdMap; + if (tex != null) { + vertices[j][PGraphics.U] = tex.x; + vertices[j][PGraphics.V] = tex.y; + } + } + } + } + + + protected void addChildren(ArrayList faces, + ArrayList materials, + ArrayList coords, + ArrayList normals, + ArrayList texcoords) { + int mtlIdxCur = -1; + OBJMaterial mtl = null; + for (int i = 0; i < faces.size(); i++) { + OBJFace face = faces.get(i); + + // Getting current material. + if (mtlIdxCur != face.matIdx) { + // To make sure that at least we get the default material + mtlIdxCur = PApplet.max(0, face.matIdx); + mtl = materials.get(mtlIdxCur); + } + + // Creating child shape for current face. + PShape child = new PShapeOBJ(face, mtl, coords, normals, texcoords); + addChild(child); + } + } + + + static protected void parseOBJ(PApplet parent, + BufferedReader reader, + ArrayList faces, + ArrayList materials, + ArrayList coords, + ArrayList normals, + ArrayList texcoords) { + Hashtable mtlTable = new Hashtable(); + int mtlIdxCur = -1; + boolean readv, readvn, readvt; + try { + + readv = readvn = readvt = false; + String line; + String gname = "object"; + while ((line = reader.readLine()) != null) { + // Parse the line. + + // The below patch/hack comes from Carlos Tomas Marti and is a + // fix for single backslashes in Rhino obj files + + // BEGINNING OF RHINO OBJ FILES HACK + // Statements can be broken in multiple lines using '\' at the + // end of a line. + // In regular expressions, the backslash is also an escape + // character. + // The regular expression \\ matches a single backslash. This + // regular expression as a Java string, becomes "\\\\". + // That's right: 4 backslashes to match a single one. + while (line.contains("\\")) { + line = line.split("\\\\")[0]; + final String s = reader.readLine(); + if (s != null) + line += s; + } + // END OF RHINO OBJ FILES HACK + + String[] parts = line.split("\\s+"); + // if not a blank line, process the line. + if (parts.length > 0) { + if (parts[0].equals("v")) { + // vertex + PVector tempv = new PVector(Float.valueOf(parts[1]).floatValue(), + Float.valueOf(parts[2]).floatValue(), + Float.valueOf(parts[3]).floatValue()); + coords.add(tempv); + readv = true; + } else if (parts[0].equals("vn")) { + // normal + PVector tempn = new PVector(Float.valueOf(parts[1]).floatValue(), + Float.valueOf(parts[2]).floatValue(), + Float.valueOf(parts[3]).floatValue()); + normals.add(tempn); + readvn = true; + } else if (parts[0].equals("vt")) { + // uv, inverting v to take into account Processing's inverted Y axis + // with respect to OpenGL. + PVector tempv = new PVector(Float.valueOf(parts[1]).floatValue(), + 1 - Float.valueOf(parts[2]). + floatValue()); + texcoords.add(tempv); + readvt = true; + } else if (parts[0].equals("o")) { + // Object name is ignored, for now. + } else if (parts[0].equals("mtllib")) { + if (parts[1] != null) { + BufferedReader mreader = parent.createReader(parts[1]); + if (mreader != null) { + parseMTL(parent, mreader, materials, mtlTable); + } + } + } else if (parts[0].equals("g")) { + gname = 1 < parts.length ? parts[1] : ""; + } else if (parts[0].equals("usemtl")) { + // Getting index of current active material (will be applied on + // all subsequent faces). + if (parts[1] != null) { + String mtlname = parts[1]; + if (mtlTable.containsKey(mtlname)) { + Integer tempInt = mtlTable.get(mtlname); + mtlIdxCur = tempInt.intValue(); + } else { + mtlIdxCur = -1; + } + } + } else if (parts[0].equals("f")) { + // Face setting + OBJFace face = new OBJFace(); + face.matIdx = mtlIdxCur; + face.name = gname; + + for (int i = 1; i < parts.length; i++) { + String seg = parts[i]; + + if (seg.indexOf("/") > 0) { + String[] forder = seg.split("/"); + + if (forder.length > 2) { + // Getting vertex and texture and normal indexes. + if (forder[0].length() > 0 && readv) { + face.vertIdx.add(Integer.valueOf(forder[0])); + } + + if (forder[1].length() > 0 && readvt) { + face.texIdx.add(Integer.valueOf(forder[1])); + } + + if (forder[2].length() > 0 && readvn) { + face.normIdx.add(Integer.valueOf(forder[2])); + } + } else if (forder.length > 1) { + // Getting vertex and texture/normal indexes. + if (forder[0].length() > 0 && readv) { + face.vertIdx.add(Integer.valueOf(forder[0])); + } + + if (forder[1].length() > 0) { + if (readvt) { + face.texIdx.add(Integer.valueOf(forder[1])); + } else if (readvn) { + face.normIdx.add(Integer.valueOf(forder[1])); + } + + } + + } else if (forder.length > 0) { + // Getting vertex index only. + if (forder[0].length() > 0 && readv) { + face.vertIdx.add(Integer.valueOf(forder[0])); + } + } + } else { + // Getting vertex index only. + if (seg.length() > 0 && readv) { + face.vertIdx.add(Integer.valueOf(seg)); + } + } + } + + faces.add(face); + } + } + } + + if (materials.size() == 0) { + // No materials definition so far. Adding one default material. + OBJMaterial defMtl = new OBJMaterial(); + materials.add(defMtl); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + + static protected void parseMTL(PApplet parent, + BufferedReader reader, + ArrayList materials, + Hashtable materialsHash) { + try { + String line; + OBJMaterial currentMtl = null; + while ((line = reader.readLine()) != null) { + // Parse the line + line = line.trim(); + String parts[] = line.split("\\s+"); + if (parts.length > 0) { + // Extract the material data. + if (parts[0].equals("newmtl")) { + // Starting new material. + String mtlname = parts[1]; + currentMtl = new OBJMaterial(mtlname); + materialsHash.put(mtlname, new Integer(materials.size())); + materials.add(currentMtl); + } else if (parts[0].equals("map_Kd") && parts.length > 1) { + // Loading texture map. + String texname = parts[1]; + currentMtl.kdMap = parent.loadImage(texname); + } else if (parts[0].equals("Ka") && parts.length > 3) { + // The ambient color of the material + currentMtl.ka.x = Float.valueOf(parts[1]).floatValue(); + currentMtl.ka.y = Float.valueOf(parts[2]).floatValue(); + currentMtl.ka.z = Float.valueOf(parts[3]).floatValue(); + } else if (parts[0].equals("Kd") && parts.length > 3) { + // The diffuse color of the material + currentMtl.kd.x = Float.valueOf(parts[1]).floatValue(); + currentMtl.kd.y = Float.valueOf(parts[2]).floatValue(); + currentMtl.kd.z = Float.valueOf(parts[3]).floatValue(); + } else if (parts[0].equals("Ks") && parts.length > 3) { + // The specular color weighted by the specular coefficient + currentMtl.ks.x = Float.valueOf(parts[1]).floatValue(); + currentMtl.ks.y = Float.valueOf(parts[2]).floatValue(); + currentMtl.ks.z = Float.valueOf(parts[3]).floatValue(); + } else if ((parts[0].equals("d") || + parts[0].equals("Tr")) && parts.length > 1) { + // Reading the alpha transparency. + currentMtl.d = Float.valueOf(parts[1]).floatValue(); + } else if (parts[0].equals("Ns") && parts.length > 1) { + // The specular component of the Phong shading model + currentMtl.ns = Float.valueOf(parts[1]).floatValue(); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + + protected static int rgbaValue(PVector color) { + return 0xFF000000 | ((int)(color.x * 255) << 16) | + ((int)(color.y * 255) << 8) | + (int)(color.z * 255); + } + + + protected static int rgbaValue(PVector color, float alpha) { + return ((int)(alpha * 255) << 24) | + ((int)(color.x * 255) << 16) | + ((int)(color.y * 255) << 8) | + (int)(color.z * 255); + } + + + // Stores a face from an OBJ file + static protected class OBJFace { + ArrayList vertIdx; + ArrayList texIdx; + ArrayList normIdx; + int matIdx; + String name; + + OBJFace() { + vertIdx = new ArrayList(); + texIdx = new ArrayList(); + normIdx = new ArrayList(); + matIdx = -1; + name = ""; + } + } + + + // Stores a material defined in an MTL file. + static protected class OBJMaterial { + String name; + PVector ka; + PVector kd; + PVector ks; + float d; + float ns; + PImage kdMap; + + OBJMaterial() { + this("default"); + } + + OBJMaterial(String name) { + this.name = name; + ka = new PVector(0.5f, 0.5f, 0.5f); + kd = new PVector(0.5f, 0.5f, 0.5f); + ks = new PVector(0.5f, 0.5f, 0.5f); + d = 1.0f; + ns = 0.0f; + kdMap = null; + } + } +} diff --git a/core/src/processing/opengl/PGraphics2D.java b/core/src/processing/opengl/PGraphics2D.java index 737fae02d..27aa13172 100644 --- a/core/src/processing/opengl/PGraphics2D.java +++ b/core/src/processing/opengl/PGraphics2D.java @@ -243,8 +243,8 @@ public class PGraphics2D extends PGraphicsOpenGL { } - static protected PShape2D loadShapeImpl(PGraphics pg, String filename, - String extension) { + static protected PShape loadShapeImpl(PGraphics pg, String filename, + String extension) { PShapeSVG svg = null; if (extension.equals("svg")) { @@ -262,7 +262,7 @@ public class PGraphics2D extends PGraphicsOpenGL { } if (svg != null) { - PShape2D p2d = PShape2D.createShape(pg.parent, svg); + PShapeOpenGL p2d = PShapeOpenGL.createShape2D(pg.parent, svg); return p2d; } else { return null; @@ -277,7 +277,7 @@ public class PGraphics2D extends PGraphicsOpenGL { @Override public PShape createShape(PShape source) { - return PShape2D.createShape(parent, source); + return PShapeOpenGL.createShape2D(parent, source); } @@ -299,44 +299,45 @@ public class PGraphics2D extends PGraphicsOpenGL { } - static protected PShape2D createShapeImpl(PApplet parent, int type) { - PShape2D shape = null; + static protected PShapeOpenGL createShapeImpl(PApplet parent, int type) { + PShapeOpenGL shape = null; if (type == PConstants.GROUP) { - shape = new PShape2D(parent, PConstants.GROUP); + shape = new PShapeOpenGL(parent, PConstants.GROUP); } else if (type == PShape.PATH) { - shape = new PShape2D(parent, PShape.PATH); + shape = new PShapeOpenGL(parent, PShape.PATH); } else if (type == POINTS) { - shape = new PShape2D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(POINTS); } else if (type == LINES) { - shape = new PShape2D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(LINES); } else if (type == TRIANGLE || type == TRIANGLES) { - shape = new PShape2D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(TRIANGLES); } else if (type == TRIANGLE_FAN) { - shape = new PShape2D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(TRIANGLE_FAN); } else if (type == TRIANGLE_STRIP) { - shape = new PShape2D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(TRIANGLE_STRIP); } else if (type == QUAD || type == QUADS) { - shape = new PShape2D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(QUADS); } else if (type == QUAD_STRIP) { - shape = new PShape2D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(QUAD_STRIP); } else if (type == POLYGON) { - shape = new PShape2D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(POLYGON); } + shape.is3D(false); return shape; } - static protected PShape2D createShapeImpl(PApplet parent, int kind, - float... p) { - PShape2D shape = null; + static protected PShapeOpenGL createShapeImpl(PApplet parent, + int kind, float... p) { + PShapeOpenGL shape = null; int len = p.length; if (kind == POINT) { @@ -344,49 +345,49 @@ public class PGraphics2D extends PGraphicsOpenGL { showWarning("Wrong number of parameters"); return null; } - shape = new PShape2D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(POINT); } else if (kind == LINE) { if (len != 4) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape2D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(LINE); } else if (kind == TRIANGLE) { if (len != 6) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape2D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(TRIANGLE); } else if (kind == QUAD) { if (len != 8) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape2D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(QUAD); } else if (kind == RECT) { if (len != 4 && len != 5 && len != 8) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape2D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(RECT); } else if (kind == ELLIPSE) { if (len != 4) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape2D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(ELLIPSE); } else if (kind == ARC) { if (len != 6) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape2D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(ARC); } else if (kind == BOX) { showWarning("Primitive not supported in 2D"); @@ -400,6 +401,7 @@ public class PGraphics2D extends PGraphicsOpenGL { shape.setParams(p); } + shape.is3D(false); return shape; } diff --git a/core/src/processing/opengl/PGraphics3D.java b/core/src/processing/opengl/PGraphics3D.java index ba24f1f10..a521164e1 100644 --- a/core/src/processing/opengl/PGraphics3D.java +++ b/core/src/processing/opengl/PGraphics3D.java @@ -22,16 +22,14 @@ package processing.opengl; -import java.io.BufferedReader; -import java.util.ArrayList; -import java.util.Hashtable; +import java.io.InputStream; +import java.util.zip.GZIPInputStream; import processing.core.PApplet; import processing.core.PConstants; import processing.core.PGraphics; -import processing.core.PImage; import processing.core.PShape; -import processing.core.PVector; +import processing.core.PShapeOBJ; public class PGraphics3D extends PGraphicsOpenGL { @@ -111,119 +109,34 @@ public class PGraphics3D extends PGraphicsOpenGL { static protected PShape loadShapeImpl(PGraphics pg, String filename, - String ext) { - ArrayList vertices = new ArrayList(); - ArrayList normals = new ArrayList(); - ArrayList textures = new ArrayList(); - ArrayList faces = new ArrayList(); - ArrayList materials = new ArrayList(); + String extension) { + PShapeOBJ obj = null; - BufferedReader reader = pg.parent.createReader(filename); - parseOBJ(pg.parent, reader, vertices, normals, textures, faces, materials); + if (extension.equals("obj")) { + obj = new PShapeOBJ(pg.parent, filename); - int prevColorMode = pg.colorMode; - float prevColorModeX = pg.colorModeX; - float prevColorModeY = pg.colorModeY; - float prevColorModeZ = pg.colorModeZ; - float prevColorModeA = pg.colorModeA; - boolean prevStroke = pg.stroke; - int prevTextureMode = pg.textureMode; - pg.colorMode(RGB, 1); - pg.stroke = false; - pg.textureMode = NORMAL; - - // The OBJ geometry is stored in a group shape, - // with each face in a separate child geometry - // shape. - PShape root = createShapeImpl(pg.parent, GROUP); - - int mtlIdxCur = -1; - OBJMaterial mtl = null; - for (int i = 0; i < faces.size(); i++) { - OBJFace face = faces.get(i); - - // Getting current material. - if (mtlIdxCur != face.matIdx) { - mtlIdxCur = PApplet.max(0, face.matIdx); // To make sure that at least we get the default material. - mtl = materials.get(mtlIdxCur); + } else if (extension.equals("objz")) { + try { + InputStream input = + new GZIPInputStream(pg.parent.createInput(filename)); + obj = new PShapeOBJ(pg.parent, PApplet.createReader(input)); + } catch (Exception e) { + e.printStackTrace(); } - - // Creating child shape for current face. - PShape child; - if (face.vertIdx.size() == 3) { - child = createShapeImpl(pg.parent, TRIANGLES); // Face is a triangle, so using appropriate shape kind. - } else if (face.vertIdx.size() == 4) { - child = createShapeImpl(pg.parent, QUADS); // Face is a quad, so using appropriate shape kind. - } else { - child = createShapeImpl(pg.parent, POLYGON); // Face is a general polygon - } - - // Setting material properties for the new face - child.fill(mtl.kd.x, mtl.kd.y, mtl.kd.z); - child.ambient(mtl.ka.x, mtl.ka.y, mtl.ka.z); - child.specular(mtl.ks.x, mtl.ks.y, mtl.ks.z); - child.shininess(mtl.ns); - if (mtl.kdMap != null) { - // If current material is textured, then tinting the texture using the diffuse color. - child.tint(mtl.kd.x, mtl.kd.y, mtl.kd.z, mtl.d); - } - - for (int j = 0; j < face.vertIdx.size(); j++){ - int vertIdx, normIdx; - PVector vert, norms; - - vert = norms = null; - - vertIdx = face.vertIdx.get(j).intValue() - 1; - vert = vertices.get(vertIdx); - - if (j < face.normIdx.size()) { - normIdx = face.normIdx.get(j).intValue() - 1; - if (-1 < normIdx) { - norms = normals.get(normIdx); - } - } - - if (mtl != null && mtl.kdMap != null) { - // This face is textured. - int texIdx; - PVector tex = null; - - if (j < face.texIdx.size()) { - texIdx = face.texIdx.get(j).intValue() - 1; - if (-1 < texIdx) { - tex = textures.get(texIdx); - } - } - - child.texture(mtl.kdMap); - if (norms != null) { - child.normal(norms.x, norms.y, norms.z); - } - if (tex != null) { - child.vertex(vert.x, vert.y, vert.z, tex.x, tex.y); - } else { - child.vertex(vert.x, vert.y, vert.z); - } - } else { - // This face is not textured. - if (norms != null) { - child.normal(norms.x, norms.y, norms.z); - } - child.vertex(vert.x, vert.y, vert.z); - } - } - - child.end(CLOSE); - root.addChild(child); } - pg.colorMode(prevColorMode, prevColorModeX, prevColorModeY, prevColorModeZ, - prevColorModeA); - pg.stroke = prevStroke; - pg.textureMode = prevTextureMode; - - return root; + if (obj != null) { + boolean prevStroke = pg.stroke; + int prevTextureMode = pg.textureMode; + pg.stroke = false; + pg.textureMode = NORMAL; + PShapeOpenGL p3d = PShapeOpenGL.createShape3D(pg.parent, obj); + pg.stroke = prevStroke; + pg.textureMode = prevTextureMode; + return p3d; + } else { + return null; + } } @@ -234,7 +147,7 @@ public class PGraphics3D extends PGraphicsOpenGL { @Override public PShape createShape(PShape source) { - return PShape3D.createShape(parent, source); + return PShapeOpenGL.createShape3D(parent, source); } @@ -256,43 +169,45 @@ public class PGraphics3D extends PGraphicsOpenGL { } - static protected PShape3D createShapeImpl(PApplet parent, int type) { - PShape3D shape = null; + static protected PShapeOpenGL createShapeImpl(PApplet parent, int type) { + PShapeOpenGL shape = null; if (type == PConstants.GROUP) { - shape = new PShape3D(parent, PConstants.GROUP); + shape = new PShapeOpenGL(parent, PConstants.GROUP); } else if (type == PShape.PATH) { - shape = new PShape3D(parent, PShape.PATH); + shape = new PShapeOpenGL(parent, PShape.PATH); } else if (type == POINTS) { - shape = new PShape3D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(POINTS); } else if (type == LINES) { - shape = new PShape3D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(LINES); } else if (type == TRIANGLE || type == TRIANGLES) { - shape = new PShape3D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(TRIANGLES); } else if (type == TRIANGLE_FAN) { - shape = new PShape3D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(TRIANGLE_FAN); } else if (type == TRIANGLE_STRIP) { - shape = new PShape3D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(TRIANGLE_STRIP); } else if (type == QUAD || type == QUADS) { - shape = new PShape3D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(QUADS); } else if (type == QUAD_STRIP) { - shape = new PShape3D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(QUAD_STRIP); } else if (type == POLYGON) { - shape = new PShape3D(parent, PShape.GEOMETRY); + shape = new PShapeOpenGL(parent, PShape.GEOMETRY); shape.setKind(POLYGON); } + shape.is3D(true); return shape; } - static protected PShape3D createShapeImpl(PApplet parent, int kind, float... p) { - PShape3D shape = null; + static protected PShapeOpenGL createShapeImpl(PApplet parent, + int kind, float... p) { + PShapeOpenGL shape = null; int len = p.length; if (kind == POINT) { @@ -300,63 +215,63 @@ public class PGraphics3D extends PGraphicsOpenGL { showWarning("Wrong number of parameters"); return null; } - shape = new PShape3D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(POINT); } else if (kind == LINE) { if (len != 4 && len != 6) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape3D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(LINE); } else if (kind == TRIANGLE) { if (len != 6) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape3D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(TRIANGLE); } else if (kind == QUAD) { if (len != 8) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape3D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(QUAD); } else if (kind == RECT) { if (len != 4 && len != 5 && len != 8) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape3D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(RECT); } else if (kind == ELLIPSE) { if (len != 4) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape3D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(ELLIPSE); } else if (kind == ARC) { if (len != 6) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape3D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(ARC); } else if (kind == BOX) { if (len != 1 && len != 3) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape3D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(BOX); } else if (kind == SPHERE) { if (len != 1) { showWarning("Wrong number of parameters"); return null; } - shape = new PShape3D(parent, PShape.PRIMITIVE); + shape = new PShapeOpenGL(parent, PShape.PRIMITIVE); shape.setKind(SPHERE); } else { showWarning("Unrecognized primitive type"); @@ -366,267 +281,7 @@ public class PGraphics3D extends PGraphicsOpenGL { shape.setParams(p); } + shape.is3D(true); return shape; } - - - ////////////////////////////////////////////////////////////// - - // OBJ LOADING - - - static protected void parseOBJ(PApplet parent, - BufferedReader reader, - ArrayList vertices, - ArrayList normals, - ArrayList textures, - ArrayList faces, - ArrayList materials) { - Hashtable mtlTable = new Hashtable(); - int mtlIdxCur = -1; - boolean readv, readvn, readvt; - try { - - readv = readvn = readvt = false; - String line; - String gname = "object"; - while ((line = reader.readLine()) != null) { - // Parse the line. - - // The below patch/hack comes from Carlos Tomas Marti and is a - // fix for single backslashes in Rhino obj files - - // BEGINNING OF RHINO OBJ FILES HACK - // Statements can be broken in multiple lines using '\' at the - // end of a line. - // In regular expressions, the backslash is also an escape - // character. - // The regular expression \\ matches a single backslash. This - // regular expression as a Java string, becomes "\\\\". - // That's right: 4 backslashes to match a single one. - while (line.contains("\\")) { - line = line.split("\\\\")[0]; - final String s = reader.readLine(); - if (s != null) - line += s; - } - // END OF RHINO OBJ FILES HACK - - String[] elements = line.split("\\s+"); - // if not a blank line, process the line. - if (elements.length > 0) { - if (elements[0].equals("v")) { - // vertex - PVector tempv = new PVector(Float.valueOf(elements[1]).floatValue(), - Float.valueOf(elements[2]).floatValue(), - Float.valueOf(elements[3]).floatValue()); - vertices.add(tempv); - readv = true; - } else if (elements[0].equals("vn")) { - // normal - PVector tempn = new PVector(Float.valueOf(elements[1]).floatValue(), - Float.valueOf(elements[2]).floatValue(), - Float.valueOf(elements[3]).floatValue()); - normals.add(tempn); - readvn = true; - } else if (elements[0].equals("vt")) { - // uv, inverting v to take into account Processing's invertex Y axis - // with respect to OpenGL. - PVector tempv = new PVector(Float.valueOf(elements[1]).floatValue(), - 1 - Float.valueOf(elements[2]). - floatValue()); - textures.add(tempv); - readvt = true; - } else if (elements[0].equals("o")) { - // Object name is ignored, for now. - } else if (elements[0].equals("mtllib")) { - if (elements[1] != null) { - BufferedReader mreader = parent.createReader(elements[1]); - if (mreader != null) { - parseMTL(parent, mreader, materials, mtlTable); - } - } - } else if (elements[0].equals("g")) { - gname = 1 < elements.length ? elements[1] : ""; - } else if (elements[0].equals("usemtl")) { - // Getting index of current active material (will be applied on all subsequent faces). - if (elements[1] != null) { - String mtlname = elements[1]; - if (mtlTable.containsKey(mtlname)) { - Integer tempInt = mtlTable.get(mtlname); - mtlIdxCur = tempInt.intValue(); - } else { - mtlIdxCur = -1; - } - } - } else if (elements[0].equals("f")) { - // Face setting - OBJFace face = new OBJFace(); - face.matIdx = mtlIdxCur; - face.name = gname; - - for (int i = 1; i < elements.length; i++) { - String seg = elements[i]; - - if (seg.indexOf("/") > 0) { - String[] forder = seg.split("/"); - - if (forder.length > 2) { - // Getting vertex and texture and normal indexes. - if (forder[0].length() > 0 && readv) { - face.vertIdx.add(Integer.valueOf(forder[0])); - } - - if (forder[1].length() > 0 && readvt) { - face.texIdx.add(Integer.valueOf(forder[1])); - } - - if (forder[2].length() > 0 && readvn) { - face.normIdx.add(Integer.valueOf(forder[2])); - } - } else if (forder.length > 1) { - // Getting vertex and texture/normal indexes. - if (forder[0].length() > 0 && readv) { - face.vertIdx.add(Integer.valueOf(forder[0])); - } - - if (forder[1].length() > 0) { - if (readvt) { - face.texIdx.add(Integer.valueOf(forder[1])); - } else if (readvn) { - face.normIdx.add(Integer.valueOf(forder[1])); - } - - } - - } else if (forder.length > 0) { - // Getting vertex index only. - if (forder[0].length() > 0 && readv) { - face.vertIdx.add(Integer.valueOf(forder[0])); - } - } - } else { - // Getting vertex index only. - if (seg.length() > 0 && readv) { - face.vertIdx.add(Integer.valueOf(seg)); - } - } - } - - faces.add(face); - } - } - } - - if (materials.size() == 0) { - // No materials definition so far. Adding one default material. - OBJMaterial defMtl = new OBJMaterial(); - materials.add(defMtl); - } - - } catch (Exception e) { - e.printStackTrace(); - } - } - - - static protected void parseMTL(PApplet parent, - BufferedReader reader, - ArrayList materials, - Hashtable materialsHash) { - try { - String line; - OBJMaterial currentMtl = null; - while ((line = reader.readLine()) != null) { - // Parse the line - line = line.trim(); - - String elements[] = line.split("\\s+"); - - if (elements.length > 0) { - // Extract the material data. - - if (elements[0].equals("newmtl")) { - // Starting new material. - String mtlname = elements[1]; - currentMtl = new OBJMaterial(mtlname); - materialsHash.put(mtlname, new Integer(materials.size())); - materials.add(currentMtl); - } else if (elements[0].equals("map_Kd") && elements.length > 1) { - // Loading texture map. - String texname = elements[1]; - currentMtl.kdMap = parent.loadImage(texname); - } else if (elements[0].equals("Ka") && elements.length > 3) { - // The ambient color of the material - currentMtl.ka.x = Float.valueOf(elements[1]).floatValue(); - currentMtl.ka.y = Float.valueOf(elements[2]).floatValue(); - currentMtl.ka.z = Float.valueOf(elements[3]).floatValue(); - } else if (elements[0].equals("Kd") && elements.length > 3) { - // The diffuse color of the material - currentMtl.kd.x = Float.valueOf(elements[1]).floatValue(); - currentMtl.kd.y = Float.valueOf(elements[2]).floatValue(); - currentMtl.kd.z = Float.valueOf(elements[3]).floatValue(); - } else if (elements[0].equals("Ks") && elements.length > 3) { - // The specular color weighted by the specular coefficient - currentMtl.ks.x = Float.valueOf(elements[1]).floatValue(); - currentMtl.ks.y = Float.valueOf(elements[2]).floatValue(); - currentMtl.ks.z = Float.valueOf(elements[3]).floatValue(); - } else if ((elements[0].equals("d") || - elements[0].equals("Tr")) && elements.length > 1) { - // Reading the alpha transparency. - currentMtl.d = Float.valueOf(elements[1]).floatValue(); - } else if (elements[0].equals("Ns") && elements.length > 1) { - // The specular component of the Phong shading model - currentMtl.ns = Float.valueOf(elements[1]).floatValue(); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - - // Stores a face from an OBJ file - static protected class OBJFace { - ArrayList vertIdx; - ArrayList texIdx; - ArrayList normIdx; - int matIdx; - String name; - - OBJFace() { - vertIdx = new ArrayList(); - texIdx = new ArrayList(); - normIdx = new ArrayList(); - matIdx = -1; - name = ""; - } - } - - - // Stores a material defined in an MTL file. - static protected class OBJMaterial { - String name; - PVector ka; - PVector kd; - PVector ks; - float d; - float ns; - PImage kdMap; - - OBJMaterial() { - this("default"); - } - - OBJMaterial(String name) { - this.name = name; - ka = new PVector(0.5f, 0.5f, 0.5f); - kd = new PVector(0.5f, 0.5f, 0.5f); - ks = new PVector(0.5f, 0.5f, 0.5f); - d = 1.0f; - ns = 0.0f; - kdMap = null; - } - } } \ No newline at end of file diff --git a/core/src/processing/opengl/PShape2D.java b/core/src/processing/opengl/PShape2D.java deleted file mode 100644 index 2b3e75055..000000000 --- a/core/src/processing/opengl/PShape2D.java +++ /dev/null @@ -1,189 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012 Ben Fry and Casey Reas - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import processing.core.PApplet; -import processing.core.PGraphics; -import processing.core.PShape; - -public class PShape2D extends PShapeOpenGL { - - public PShape2D(PApplet parent, int family) { - super(parent, family); - } - - @Override - public boolean is2D() { - return true; - } - - @Override - public boolean is3D() { - return false; - } - - - //////////////////////////////////////////////////////////////////////// - // - // Shape copy - - - static public PShape2D createShape(PApplet parent, PShape src) { - PShape2D dest = null; - if (src.getFamily() == GROUP) { - dest = PGraphics2D.createShapeImpl(parent, GROUP); - PShape2D.copyGroup(parent, src, dest); - } else if (src.getFamily() == PRIMITIVE) { - dest = PGraphics2D.createShapeImpl(parent, src.getKind(), - src.getParams()); - PShape.copyPrimitive(src, dest); - } else if (src.getFamily() == GEOMETRY) { - dest = PGraphics2D.createShapeImpl(parent, src.getKind()); - PShape.copyGeometry(src, dest); - } else if (src.getFamily() == PATH) { - dest = PGraphics2D.createShapeImpl(parent, PATH); - PShape.copyPath(src, dest); - } - dest.setName(src.getName()); - return dest; - } - - - static public void copyGroup(PApplet parent, PShape src, PShape dest) { - copyMatrix(src, dest); - copyStyles(src, dest); - copyImage(src, dest); - - for (int i = 0; i < src.getChildCount(); i++) { - PShape c = PShape2D.createShape(parent, src.getChild(i)); - dest.addChild(c); - } - } - - - /////////////////////////////////////////////////////////// - - // - - // Drawing methods - - @Override - public void vertex(float x, float y, float z) { - PGraphics.showDepthWarningXYZ("vertex"); - } - - @Override - public void vertex(float x, float y, float z, float u, float v) { - PGraphics.showDepthWarningXYZ("vertex"); - } - - /////////////////////////////////////////////////////////// - - // - - // Bezier curves - - @Override - public void bezierVertex(float x2, float y2, float z2, - float x3, float y3, float z3, - float x4, float y4, float z4) { - PGraphics.showDepthWarningXYZ("bezierVertex"); - } - - @Override - public void quadraticVertex(float x2, float y2, float z2, - float x4, float y4, float z4) { - PGraphics.showDepthWarningXYZ("quadVertex"); - } - - @Override - public void curveVertex(float x, float y, float z) { - PGraphics.showDepthWarningXYZ("curveVertex"); - } - - /////////////////////////////////////////////////////////// - - // - - // Geometric transformations - - @Override - public void translate(float tx, float ty, float tz) { - PGraphics.showVariationWarning("translate"); - } - - @Override - public void rotateX(float angle) { - PGraphics.showDepthWarning("rotateX"); - } - - @Override - public void rotateY(float angle) { - PGraphics.showDepthWarning("rotateY"); - } - - @Override - public void rotateZ(float angle) { - PGraphics.showDepthWarning("rotateZ"); - } - - @Override - public void rotate(float angle, float vx, float vy, float vz) { - PGraphics.showVariationWarning("rotate"); - } - - @Override - public void applyMatrix(float n00, float n01, float n02, float n03, - float n10, float n11, float n12, float n13, - float n20, float n21, float n22, float n23, - float n30, float n31, float n32, float n33) { - PGraphics.showVariationWarning("applyMatrix"); - } - - @Override - public void scale(float sx, float sy, float sz) { - PGraphics.showDepthWarningXYZ("scale"); - } - - /////////////////////////////////////////////////////////// - - // - - // Setters/getters of individual vertices - - @Override - public float getVertexZ(int index) { - PGraphics.showDepthWarningXYZ("getVertexZ"); - return 0; - } - - @Override - public void setVertex(int index, float x, float y) { - super.setVertex(index, x, y, 0); - } - - @Override - public void setVertex(int index, float x, float y, float z) { - PGraphics.showDepthWarningXYZ("setVertex"); - } -} diff --git a/core/src/processing/opengl/PShape3D.java b/core/src/processing/opengl/PShape3D.java deleted file mode 100644 index df169eaa1..000000000 --- a/core/src/processing/opengl/PShape3D.java +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2012 Ben Fry and Casey Reas - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.opengl; - -import processing.core.PApplet; -import processing.core.PShape; - -public class PShape3D extends PShapeOpenGL { - - public PShape3D(PApplet parent, int family) { - super(parent, family); - } - - @Override - public boolean is2D() { - return false; - } - - @Override - public boolean is3D() { - return true; - } - - - //////////////////////////////////////////////////////////////////////// - // - // Shape copy - - - static public PShape3D createShape(PApplet parent, PShape src) { - PShape3D dest = null; - if (src.getFamily() == GROUP) { - dest = PGraphics3D.createShapeImpl(parent, GROUP); - PShape3D.copyGroup(parent, src, dest); - } else if (src.getFamily() == PRIMITIVE) { - dest = PGraphics3D.createShapeImpl(parent, src.getKind(), - src.getParams()); - PShape.copyPrimitive(src, dest); - } else if (src.getFamily() == GEOMETRY) { - dest = PGraphics3D.createShapeImpl(parent, src.getKind()); - PShape.copyGeometry(src, dest); - } else if (src.getFamily() == PATH) { - dest = PGraphics3D.createShapeImpl(parent, PATH); - PShape.copyPath(src, dest); - } - dest.setName(src.getName()); - return dest; - } - - - static public void copyGroup(PApplet parent, PShape src, PShape dest) { - copyMatrix(src, dest); - copyStyles(src, dest); - copyImage(src, dest); - - for (int i = 0; i < src.getChildCount(); i++) { - PShape c = PShape3D.createShape(parent, src.getChild(i)); - dest.addChild(c); - } - } -} diff --git a/core/src/processing/opengl/PShapeOpenGL.java b/core/src/processing/opengl/PShapeOpenGL.java index 8048a4854..01f198ea1 100644 --- a/core/src/processing/opengl/PShapeOpenGL.java +++ b/core/src/processing/opengl/PShapeOpenGL.java @@ -87,7 +87,6 @@ public class PShapeOpenGL extends PShape { // Texturing protected HashSet textures; - protected PImage texture; protected boolean strokedTexture; // ........................................................ @@ -377,8 +376,8 @@ public class PShapeOpenGL extends PShape { strokedTexture(true); } } else { - if (c3d.texture != null) { - addTexture(c3d.texture); + if (c3d.image != null) { + addTexture(c3d.image); if (c3d.stroke) { strokedTexture(true); } @@ -493,6 +492,77 @@ public class PShapeOpenGL extends PShape { } } + /////////////////////////////////////////////////////////// + + // + // Shape creation (temporary hack) + + + static protected PShapeOpenGL createShape3D(PApplet parent, PShape src) { + PShapeOpenGL dest = null; + if (src.getFamily() == GROUP) { + dest = PGraphics3D.createShapeImpl(parent, GROUP); + copyGroup3D(parent, src, dest); + } else if (src.getFamily() == PRIMITIVE) { + dest = PGraphics3D.createShapeImpl(parent, src.getKind(), + src.getParams()); + PShape.copyPrimitive(src, dest); + } else if (src.getFamily() == GEOMETRY) { + dest = PGraphics3D.createShapeImpl(parent, src.getKind()); + PShape.copyGeometry(src, dest); + } else if (src.getFamily() == PATH) { + dest = PGraphics3D.createShapeImpl(parent, PATH); + PShape.copyPath(src, dest); + } + dest.setName(src.getName()); + return dest; + } + + + static public PShapeOpenGL createShape2D(PApplet parent, PShape src) { + PShapeOpenGL dest = null; + if (src.getFamily() == GROUP) { + dest = PGraphics2D.createShapeImpl(parent, GROUP); + copyGroup2D(parent, src, dest); + } else if (src.getFamily() == PRIMITIVE) { + dest = PGraphics2D.createShapeImpl(parent, src.getKind(), + src.getParams()); + PShape.copyPrimitive(src, dest); + } else if (src.getFamily() == GEOMETRY) { + dest = PGraphics2D.createShapeImpl(parent, src.getKind()); + PShape.copyGeometry(src, dest); + } else if (src.getFamily() == PATH) { + dest = PGraphics2D.createShapeImpl(parent, PATH); + PShape.copyPath(src, dest); + } + dest.setName(src.getName()); + return dest; + } + + + static public void copyGroup3D(PApplet parent, PShape src, PShape dest) { + copyMatrix(src, dest); + copyStyles(src, dest); + copyImage(src, dest); + + for (int i = 0; i < src.getChildCount(); i++) { + PShape c = createShape3D(parent, src.getChild(i)); + dest.addChild(c); + } + } + + + static public void copyGroup2D(PApplet parent, PShape src, PShape dest) { + copyMatrix(src, dest); + copyStyles(src, dest); + copyImage(src, dest); + + for (int i = 0; i < src.getChildCount(); i++) { + PShape c = createShape2D(parent, src.getChild(i)); + dest.addChild(c); + } + } + /////////////////////////////////////////////////////////// @@ -674,13 +744,13 @@ public class PShapeOpenGL extends PShape { child.texture(tex); } } else { - PImage tex0 = texture; - texture = tex; + PImage tex0 = image; + image = tex; if (tex0 != tex && parent != null) { ((PShapeOpenGL)parent).removeTexture(tex); } if (parent != null) { - ((PShapeOpenGL)parent).addTexture(texture); + ((PShapeOpenGL)parent).addTexture(image); if (is2D() && stroke) { ((PShapeOpenGL)parent).strokedTexture(true); } @@ -697,8 +767,8 @@ public class PShapeOpenGL extends PShape { child.noTexture(); } } else { - PImage tex0 = texture; - texture = null; + PImage tex0 = image; + image = null; if (tex0 != null && parent != null) { ((PShapeOpenGL)parent).removeTexture(tex0); if (is2D()) { @@ -785,7 +855,7 @@ public class PShapeOpenGL extends PShape { if (family == GROUP) { return textures != null && textures.contains(tex); } else { - return texture == tex; + return image == tex; } } @@ -794,7 +864,7 @@ public class PShapeOpenGL extends PShape { if (family == GROUP) { return strokedTexture; } else { - return texture != null && stroke; + return image != null && stroke; } } @@ -857,6 +927,10 @@ public class PShapeOpenGL extends PShape { @Override public void vertex(float x, float y, float z) { +// if (!is3D) { +// PGraphics.showDepthWarningXYZ("vertex"); +// return; +// } vertexImpl(x, y, z, 0, 0); } @@ -872,8 +946,12 @@ public class PShapeOpenGL extends PShape { PGraphics.showWarning("Cannot add vertices to GROUP shape"); return; } +// if (!is3D) { +// PGraphics.showDepthWarningXYZ("vertex"); +// return; +// } - boolean textured = texture != null; + boolean textured = image != null; int fcolor = 0x00; if (fill || textured) { if (!textured) { @@ -887,9 +965,9 @@ public class PShapeOpenGL extends PShape { } } - if (texture != null && textureMode == IMAGE) { - u = PApplet.min(1, u / texture.width); - v = PApplet.min(1, v / texture.height); + if (image != null && textureMode == IMAGE) { + u = PApplet.min(1, u / image.width); + v = PApplet.min(1, v / image.height); } int scolor = 0x00; @@ -1202,7 +1280,7 @@ public class PShapeOpenGL extends PShape { if (fillColor == newFillColor) return; fillColor = newFillColor; - if (texture == null) { + if (image == null) { Arrays.fill(inGeo.colors, 0, inGeo.vertexCount, PGL.javaToNativeARGB(fillColor)); if (shapeEnded && tessellated && hasPolys) { @@ -1344,7 +1422,7 @@ public class PShapeOpenGL extends PShape { stroke = true; } updateStrokeColor(calcColor); - if (is2D() && texture != null && parent != null) { + if (is2D() && image != null && parent != null) { ((PShapeOpenGL)parent).strokedTexture(true); } } @@ -1496,7 +1574,7 @@ public class PShapeOpenGL extends PShape { if (tintColor == newTintColor) return; tintColor = newTintColor; - if (texture != null) { + if (image != null) { Arrays.fill(inGeo.colors, 0, inGeo.vertexCount, PGL.javaToNativeARGB(tintColor)); if (shapeEnded && tessellated && hasPolys) { @@ -1796,6 +1874,10 @@ public class PShapeOpenGL extends PShape { @Override public void translate(float tx, float ty, float tz) { +// if (!is3D) { +// PGraphics.showVariationWarning("translate"); +// return; +// } transform(TRANSLATE, tx, ty, tz); } @@ -1806,8 +1888,38 @@ public class PShapeOpenGL extends PShape { } + @Override + public void rotateX(float angle) { +// if (!is3D) { +// PGraphics.showDepthWarning("rotateX"); +// return; +// } + rotate(angle, 1, 0, 0); + } + + + @Override + public void rotateY(float angle) { +// if (!is3D) { +// PGraphics.showDepthWarning("rotateY"); +// return; +// } + rotate(angle, 0, 1, 0); + } + + + @Override + public void rotateZ(float angle) { + transform(ROTATE, angle); + } + + @Override public void rotate(float angle, float v0, float v1, float v2) { +// if (!is3D) { +// PGraphics.showVariationWarning("rotate"); +// return; +// } transform(ROTATE, angle, v0, v1, v2); } @@ -1826,6 +1938,10 @@ public class PShapeOpenGL extends PShape { @Override public void scale(float x, float y, float z) { +// if (!is3D) { +// PGraphics.showDepthWarningXYZ("scale"); +// return; +// } transform(SCALE, x, y, z); } @@ -1850,6 +1966,10 @@ public class PShapeOpenGL extends PShape { float n10, float n11, float n12, float n13, float n20, float n21, float n22, float n23, float n30, float n31, float n32, float n33) { +// if (!is3D) { +// PGraphics.showVariationWarning("applyMatrix"); +// return; +// } transform(MATRIX, n00, n01, n02, n03, n10, n11, n12, n13, n20, n21, n22, n23, @@ -2000,6 +2120,10 @@ public class PShapeOpenGL extends PShape { public void bezierVertex(float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4) { +// if (!is3D) { +// PGraphics.showDepthWarningXYZ("bezierVertex"); +// return; +// } bezierVertexImpl(x2, y2, z2, x3, y3, z3, x4, y4, z4); @@ -2030,6 +2154,10 @@ public class PShapeOpenGL extends PShape { @Override public void quadraticVertex(float cx, float cy, float cz, float x3, float y3, float z3) { +// if (!is3D) { +// PGraphics.showDepthWarningXYZ("quadraticVertex"); +// return; +// } quadraticVertexImpl(cx, cy, cz, x3, y3, z3); } @@ -2075,6 +2203,10 @@ public class PShapeOpenGL extends PShape { @Override public void curveVertex(float x, float y, float z) { +// if (!is3D) { +// PGraphics.showDepthWarningXYZ("curveVertex"); +// return; +// } curveVertexImpl(x, y, z); } @@ -2517,7 +2649,7 @@ public class PShapeOpenGL extends PShape { tessellator.setInGeometry(inGeo); tessellator.setTessGeometry(tessGeo); - tessellator.setFill(fill || texture != null); + tessellator.setFill(fill || image != null); tessellator.setStroke(stroke); tessellator.setStrokeColor(strokeColor); tessellator.setStrokeWeight(strokeWeight); @@ -2591,8 +2723,8 @@ public class PShapeOpenGL extends PShape { tessellatePath(); } - if (texture != null && parent != null) { - ((PShapeOpenGL)parent).addTexture(texture); + if (image != null && parent != null) { + ((PShapeOpenGL)parent).addTexture(image); } firstPolyIndexCache = tessellator.firstPolyIndexCache; @@ -3159,7 +3291,7 @@ public class PShapeOpenGL extends PShape { protected boolean startStrokedTex(int n) { - return texture != null && (n == firstLineIndexCache || + return image != null && (n == firstLineIndexCache || n == firstPointIndexCache); } @@ -4101,7 +4233,7 @@ public class PShapeOpenGL extends PShape { } } else { - render(gl, texture); + render(gl, image); } post(gl);