diff --git a/android/core/src/processing/core/PShape.java b/android/core/src/processing/core/PShape.java index 6e47a5958..04d86003f 100644 --- a/android/core/src/processing/core/PShape.java +++ b/android/core/src/processing/core/PShape.java @@ -143,11 +143,11 @@ public class PShape implements PConstants { protected boolean tint; protected int tintColor; - protected int ambientColor; - protected int specularColor; + protected int ambientColor; + protected int specularColor; protected int emissiveColor; - protected float shininess; - + protected float shininess; + /** Temporary toggle for whether styles should be honored. */ protected boolean style = true; @@ -165,7 +165,7 @@ public class PShape implements PConstants { protected PShape parent; protected int childCount; protected PShape[] children; - + /** Array of VERTEX, BEZIER_VERTEX, and CURVE_VERTEX calls. */ protected int vertexCodeCount; @@ -173,14 +173,14 @@ public class PShape implements PConstants { /** True if this is a closed path. */ protected boolean close; - + // ........................................................ // internal color for setting/calculating protected float calcR, calcG, calcB, calcA; protected int calcRi, calcGi, calcBi, calcAi; protected int calcColor; - protected boolean calcAlpha; + protected boolean calcAlpha; /** The current colorMode */ public int colorMode; // = RGB; @@ -202,7 +202,10 @@ 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? @@ -252,12 +255,12 @@ public class PShape implements PConstants { this.family = family; } - + public void setKind(int kind) { this.kind = kind; } - - + + public void setName(String name) { this.name = name; } @@ -393,14 +396,14 @@ public class PShape implements PConstants { return depth; } - + // TODO unapproved protected PVector getTop() { return getTop(null); - } - - + } + + protected PVector getTop(PVector top) { if (top == null) { top = new PVector(); @@ -408,88 +411,83 @@ public class PShape implements PConstants { return top; } - + protected PVector getBottom() { return getBottom(null); - } - - + } + + protected PVector getBottom(PVector bottom) { if (bottom == null) { bottom = new PVector(); - } + } return bottom; - } - + } + /** * Return true if this shape is 2D. Defaults to true. - */ + */ public boolean is2D() { - return true; + return !is3D; } - - + + /** * Return true if this shape is 3D. Defaults to false. */ public boolean is3D() { - return false; - } - - - /** - * Return true if this shape requires rendering through OpenGL. Defaults to false. - */ - // TODO unapproved - public boolean isGL() { - return false; + return is3D; } - /////////////////////////////////////////////////////////// - + public void is3D(boolean val) { + is3D = val; + } + + /////////////////////////////////////////////////////////// + // - - // Drawing methods - + + // Drawing methods + public void texture(PImage tex) { } - + public void noTexture() { - } - + } + // TODO unapproved protected void solid(boolean solid) { } - + public void beginContour() { } - + public void endContour() { } - - public void vertex(float x, float y) { + + public void vertex(float x, float y) { } - public void vertex(float x, float y, float u, float v) { + public void vertex(float x, float y, float u, float v) { } - + public void vertex(float x, float y, float z) { } public void vertex(float x, float y, float z, float u, float v) { - } - + } + public void normal(float nx, float ny, float nz) { } public void end() { - } + } + + public void end(int mode) { + } - public void end(int mode) { - } - ////////////////////////////////////////////////////////////// // STROKE CAP/JOIN/WEIGHT @@ -583,97 +581,97 @@ public class PShape implements PConstants { ////////////////////////////////////////////////////////////// // Ambient set/update - - public void ambient(int rgb) { + + public void ambient(int rgb) { } - - public void ambient(float gray) { + + public void ambient(float gray) { } - + public void ambient(float x, float y, float z) { } - + ////////////////////////////////////////////////////////////// // Specular set/update - - public void specular(int rgb) { + + public void specular(int rgb) { } - - public void specular(float gray) { + + public void specular(float gray) { } - + public void specular(float x, float y, float z) { - } - - + } + + ////////////////////////////////////////////////////////////// - // Emissive set/update + // Emissive set/update - public void emissive(int rgb) { + public void emissive(int rgb) { } - - public void emissive(float gray) { + + public void emissive(float gray) { } - + public void emissive(float x, float y, float z) { - } - + } + ////////////////////////////////////////////////////////////// - // Shininess set/update - - public void shininess(float shine) { - } - - /////////////////////////////////////////////////////////// - + // Shininess set/update + + public void shininess(float shine) { + } + + /////////////////////////////////////////////////////////// + // - - // Bezier curves - - + + // Bezier curves + + public void bezierDetail(int detail) { - } - + } + public void bezierVertex(float x2, float y2, float x3, float y3, float x4, float y4) { } - + public void bezierVertex(float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4) { } - + public void quadraticVertex(float cx, float cy, float x3, float y3) { - } - + } + public void quadraticVertex(float cx, float cy, float cz, float x3, float y3, float z3) { } - - /////////////////////////////////////////////////////////// - + + /////////////////////////////////////////////////////////// + // - + // Catmull-Rom curves public void curveDetail(int detail) { } - + public void curveTightness(float tightness) { - } - + } + public void curveVertex(float x, float y) { - } + } public void curveVertex(float x, float y, float z) { } - - + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @@ -769,19 +767,19 @@ public class PShape implements PConstants { g.popStyle(); } } - - + + //////////////////////////////////////////////////////////////////////// // // Shape copy - - + + // TODO unapproved static protected PShape createShape(PApplet parent, PShape src) { PShape dest = null; if (src.family == GROUP) { dest = parent.createShape(GROUP); - PShape.copyGroup(parent, src, dest); + PShape.copyGroup(parent, src, dest); } else if (src.family == PRIMITIVE) { dest = parent.createShape(src.kind, src.params); PShape.copyPrimitive(src, dest); @@ -796,7 +794,7 @@ public class PShape implements PConstants { return dest; } - + // TODO unapproved static protected void copyGroup(PApplet parent, PShape src, PShape dest) { copyMatrix(src, dest); @@ -807,32 +805,32 @@ public class PShape implements PConstants { dest.addChild(c); } } - - + + // TODO unapproved static protected void copyPrimitive(PShape src, PShape dest) { - copyMatrix(src, dest); + copyMatrix(src, dest); copyStyles(src, dest); copyImage(src, dest); } - - + + // TODO unapproved static protected void copyGeometry(PShape src, PShape dest) { - copyMatrix(src, dest); + copyMatrix(src, dest); copyStyles(src, dest); copyImage(src, dest); - + if (src.style) { for (int i = 0; i < src.vertexCount; i++) { float[] vert = src.vertices[i]; - + // Do we need to copy these as well? // s.ambient(vert[AR] * 255, vert[AG] * 255, vert[AB] * 255); // s.specular(vert[SPR] * 255, vert[SPG] * 255, vert[SPB] * 255); // 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]); @@ -850,28 +848,28 @@ public class PShape implements PConstants { } } } - - dest.end(); + + dest.end(); } - - + + // TODO unapproved static protected void copyPath(PShape src, PShape dest) { - copyMatrix(src, dest); + copyMatrix(src, dest); copyStyles(src, dest); copyImage(src, dest); dest.close = src.close; - dest.setPath(src.vertexCount, src.vertices, src.vertexCodeCount, src.vertexCodes); + dest.setPath(src.vertexCount, src.vertices, src.vertexCodeCount, src.vertexCodes); } - - + + // TODO unapproved static protected void copyMatrix(PShape src, PShape dest) { if (src.matrix != null) { - dest.applyMatrix(src.matrix); - } + dest.applyMatrix(src.matrix); + } } - + // TODO unapproved static protected void copyStyles(PShape src, PShape dest) { @@ -891,19 +889,19 @@ public class PShape implements PConstants { } else { dest.fill = false; } - } - - + } + + // TODO unapproved static protected void copyImage(PShape src, PShape dest) { if (src.image != null) { dest.texture(src.image); - } + } } - + //////////////////////////////////////////////////////////////////////// - + /** * Called by the following (the shape() command adds the g) @@ -1352,8 +1350,8 @@ public class PShape implements PConstants { public PShape getTessellation() { return null; } - - + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @@ -1386,54 +1384,54 @@ public class PShape implements PConstants { return params[index]; } - + protected void setParams(float[] source) { if (params == null) { - params = new float[source.length]; - } + params = new float[source.length]; + } if (source.length != params.length) { PGraphics.showWarning("Wrong number of parameters"); return; } PApplet.arrayCopy(source, params); - } - + } + public void setPath(int vcount, float[][] verts) { setPath(vcount, verts, 0, null); } - - + + protected void setPath(int vcount, float[][] verts, int ccount, int[] codes) { if (verts == null || verts.length < vcount) return; if (0 < ccount && (codes == null || codes.length < ccount)) return; - + int ndim = verts[0].length; vertexCount = vcount; vertices = new float[vertexCount][ndim]; for (int i = 0; i < vertexCount; i++) { PApplet.arrayCopy(verts[i], vertices[i]); - } - + } + vertexCodeCount = ccount; if (0 < vertexCodeCount) { vertexCodes = new int[vertexCodeCount]; PApplet.arrayCopy(codes, vertexCodes, vertexCodeCount); - } + } } - - + + public int getVertexCount() { return vertexCount; } - + public PVector getVertex(int index) { return getVertex(index, null); - } - - + } + + public PVector getVertex(int index, PVector vec) { if (vec == null) { vec = new PVector(); @@ -1444,7 +1442,7 @@ public class PShape implements PConstants { return vec; } - + public float getVertexX(int index) { return vertices[index][X]; } @@ -1459,20 +1457,20 @@ public class PShape implements PConstants { return vertices[index][Z]; } - + public void setVertex(int index, float x, float y) { vertices[index][X] = x; vertices[index][Y] = y; } - - + + public void setVertex(int index, float x, float y, float z) { vertices[index][X] = x; vertices[index][Y] = y; vertices[index][Z] = z; } - - + + public void setVertex(int index, PVector vec) { vertices[index][X] = vec.x; vertices[index][Y] = vec.y; @@ -1483,8 +1481,8 @@ public class PShape implements PConstants { public PVector getNormal(int index) { return getNormal(index, null); } - - + + public PVector getNormal(int index, PVector vec) { if (vec == null) { vec = new PVector(); @@ -1492,48 +1490,48 @@ public class PShape implements PConstants { vec.x = vertices[index][PGraphics.NX]; vec.y = vertices[index][PGraphics.NY]; vec.z = vertices[index][PGraphics.NZ]; - return vec; + return vec; } - - + + public float getNormalX(int index) { return vertices[index][PGraphics.NX]; } - + public float getNormalY(int index) { return vertices[index][PGraphics.NY]; } - - + + public float getNormalZ(int index) { return vertices[index][PGraphics.NZ]; - } - + } + public void setNormal(int index, float nx, float ny, float nz) { vertices[index][PGraphics.NX] = nx; vertices[index][PGraphics.NY] = ny; vertices[index][PGraphics.NZ] = nz; } - - + + public float getTextureU(int index) { return vertices[index][PGraphics.U]; } - - + + public float getTextureV(int index) { return vertices[index][PGraphics.V]; - } - - + } + + public void setTextureUV(int index, float u, float v) { vertices[index][PGraphics.U] = u; vertices[index][PGraphics.V] = v; } - - + + public int getFill(int index) { int a = (int) (vertices[index][PGraphics.A] * 255); int r = (int) (vertices[index][PGraphics.R] * 255); @@ -1542,15 +1540,15 @@ public class PShape implements PConstants { return (a << 24) | (r << 16) | (g << 8) | b; } - + public void setFill(int index, int fill) { vertices[index][PGraphics.A] = ((fill >> 24) & 0xFF) / 255.0f; vertices[index][PGraphics.R] = ((fill >> 16) & 0xFF) / 255.0f; vertices[index][PGraphics.G] = ((fill >> 8) & 0xFF) / 255.0f; vertices[index][PGraphics.B] = ((fill >> 0) & 0xFF) / 255.0f; - } + } + - public int getStroke(int index) { int a = (int) (vertices[index][PGraphics.SA] * 255); int r = (int) (vertices[index][PGraphics.SR] * 255); @@ -1559,25 +1557,25 @@ public class PShape implements PConstants { return (a << 24) | (r << 16) | (g << 8) | b; } - + public void setStroke(int index, int stroke) { vertices[index][PGraphics.SA] = ((stroke >> 24) & 0xFF) / 255.0f; vertices[index][PGraphics.SR] = ((stroke >> 16) & 0xFF) / 255.0f; vertices[index][PGraphics.SG] = ((stroke >> 8) & 0xFF) / 255.0f; vertices[index][PGraphics.SB] = ((stroke >> 0) & 0xFF) / 255.0f; - } - - + } + + protected float getStrokeWeight(int index) { return vertices[index][PGraphics.SW]; } - + protected void setStrokeWeight(int index, float weight) { vertices[index][PGraphics.SW] = weight; - } - - + } + + protected int getAmbient(int index) { int r = (int) (vertices[index][PGraphics.AR] * 255); int g = (int) (vertices[index][PGraphics.AG] * 255); @@ -1585,13 +1583,13 @@ public class PShape implements PConstants { return 0xff000000 | (r << 16) | (g << 8) | b; } - + protected void setAmbient(int index, int ambient) { vertices[index][PGraphics.AR] = ((ambient >> 16) & 0xFF) / 255.0f; vertices[index][PGraphics.AG] = ((ambient >> 8) & 0xFF) / 255.0f; vertices[index][PGraphics.AB] = ((ambient >> 0) & 0xFF) / 255.0f; - } - + } + protected int getSpecular(int index) { int r = (int) (vertices[index][PGraphics.SPR] * 255); int g = (int) (vertices[index][PGraphics.SPG] * 255); @@ -1599,14 +1597,14 @@ public class PShape implements PConstants { return 0xff000000 | (r << 16) | (g << 8) | b; } - + protected void setSpecular(int index, int specular) { vertices[index][PGraphics.SPR] = ((specular >> 16) & 0xFF) / 255.0f; vertices[index][PGraphics.SPG] = ((specular >> 8) & 0xFF) / 255.0f; vertices[index][PGraphics.SPB] = ((specular >> 0) & 0xFF) / 255.0f; - } - - + } + + protected int getEmissive(int index) { int r = (int) (vertices[index][PGraphics.ER] * 255); int g = (int) (vertices[index][PGraphics.EG] * 255); @@ -1614,24 +1612,24 @@ public class PShape implements PConstants { return 0xff000000 | (r << 16) | (g << 8) | b; } - + protected void setEmissive(int index, int emissive) { vertices[index][PGraphics.ER] = ((emissive >> 16) & 0xFF) / 255.0f; vertices[index][PGraphics.EG] = ((emissive >> 8) & 0xFF) / 255.0f; vertices[index][PGraphics.EB] = ((emissive >> 0) & 0xFF) / 255.0f; - } - - + } + + protected float getShininess(int index) { return vertices[index][PGraphics.SHINE]; } - + protected void setShininess(int index, float shine) { vertices[index][PGraphics.SHINE] = shine; } - - + + public int[] getVertexCodes() { if (vertexCodes == null) { return null; @@ -1641,8 +1639,8 @@ public class PShape implements PConstants { } return vertexCodes; } - - + + public int getVertexCodeCount() { return vertexCodeCount; } @@ -2015,7 +2013,7 @@ public class PShape implements PConstants { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - + public void colorMode(int mode) { colorMode(mode, colorModeX, colorModeY, colorModeZ, colorModeA); } @@ -2059,8 +2057,8 @@ public class PShape implements PConstants { (colorModeA == 255) && (colorModeX == 255) && (colorModeY == 255) && (colorModeZ == 255); } - - + + protected void colorCalc(int rgb) { if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { colorCalc((float) rgb); @@ -2185,6 +2183,6 @@ public class PShape implements PConstants { calcB = calcBi / 255.0f; calcAlpha = (calcAi != 255); } - - + + } \ No newline at end of file diff --git a/android/core/src/processing/core/PShapeOBJ.java b/android/core/src/processing/core/PShapeOBJ.java new file mode 100644 index 000000000..b9be8db68 --- /dev/null +++ b/android/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/android/core/src/processing/opengl/PGraphics2D.java b/android/core/src/processing/opengl/PGraphics2D.java index 737fae02d..27aa13172 100644 --- a/android/core/src/processing/opengl/PGraphics2D.java +++ b/android/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/android/core/src/processing/opengl/PGraphics3D.java b/android/core/src/processing/opengl/PGraphics3D.java index ba24f1f10..a521164e1 100644 --- a/android/core/src/processing/opengl/PGraphics3D.java +++ b/android/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/android/core/src/processing/opengl/PShape2D.java b/android/core/src/processing/opengl/PShape2D.java deleted file mode 100644 index 2b3e75055..000000000 --- a/android/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/android/core/src/processing/opengl/PShape3D.java b/android/core/src/processing/opengl/PShape3D.java deleted file mode 100644 index df169eaa1..000000000 --- a/android/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/android/core/src/processing/opengl/PShapeOpenGL.java b/android/core/src/processing/opengl/PShapeOpenGL.java index 8048a4854..2f6053e8c 100644 --- a/android/core/src/processing/opengl/PShapeOpenGL.java +++ b/android/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; } } @@ -873,7 +943,7 @@ public class PShapeOpenGL extends PShape { return; } - boolean textured = texture != null; + boolean textured = image != null; int fcolor = 0x00; if (fill || textured) { if (!textured) { @@ -887,9 +957,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 +1272,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 +1414,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 +1566,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) { @@ -1806,6 +1876,24 @@ public class PShapeOpenGL extends PShape { } + @Override + public void rotateX(float angle) { + rotate(angle, 1, 0, 0); + } + + + @Override + public void rotateY(float angle) { + 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) { transform(ROTATE, angle, v0, v1, v2); @@ -2517,7 +2605,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 +2679,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 +3247,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 +4189,7 @@ public class PShapeOpenGL extends PShape { } } else { - render(gl, texture); + render(gl, image); } post(gl); diff --git a/core/src/processing/opengl/PShapeOpenGL.java b/core/src/processing/opengl/PShapeOpenGL.java index 01f198ea1..2f6053e8c 100644 --- a/core/src/processing/opengl/PShapeOpenGL.java +++ b/core/src/processing/opengl/PShapeOpenGL.java @@ -927,10 +927,6 @@ 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); } @@ -946,10 +942,6 @@ public class PShapeOpenGL extends PShape { PGraphics.showWarning("Cannot add vertices to GROUP shape"); return; } -// if (!is3D) { -// PGraphics.showDepthWarningXYZ("vertex"); -// return; -// } boolean textured = image != null; int fcolor = 0x00; @@ -1874,10 +1866,6 @@ 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); } @@ -1890,20 +1878,12 @@ 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); } @@ -1916,10 +1896,6 @@ public class PShapeOpenGL extends PShape { @Override public void rotate(float angle, float v0, float v1, float v2) { -// if (!is3D) { -// PGraphics.showVariationWarning("rotate"); -// return; -// } transform(ROTATE, angle, v0, v1, v2); } @@ -1938,10 +1914,6 @@ 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); } @@ -1966,10 +1938,6 @@ 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, @@ -2120,10 +2088,6 @@ 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); @@ -2154,10 +2118,6 @@ 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); } @@ -2203,10 +2163,6 @@ 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); }