/** Initializes a new OBJ Object with the given filename. */ public PShapeOBJ(PApplet parent, String filename) { this(parent, parent.createReader(filename), getBasePath(parent, filename)); }
protected static void parseOBJ( PApplet parent, String path, BufferedReader reader, ArrayList<OBJFace> faces, ArrayList<OBJMaterial> materials, ArrayList<PVector> coords, ArrayList<PVector> normals, ArrayList<PVector> texcoords) { Map<String, Integer> mtlTable = new HashMap<String, Integer>(); 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. line = line.trim(); if (line.equals("") || line.indexOf('#') == 0) { // Empty line of comment, ignore line continue; } // 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) { String fn = parts[1]; if (fn.indexOf(File.separator) == -1 && !path.equals("")) { // Relative file name, adding the base path. fn = path + File.separator + fn; } BufferedReader mreader = parent.createReader(fn); if (mreader != null) { parseMTL(parent, path, mreader, materials, mtlTable); mreader.close(); } } } 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(); } }