Skip to content

Commit b5d2152

Browse files
committed
ported latest PShapeOBJ from java mode
1 parent cb8c058 commit b5d2152

File tree

1 file changed

+94
-88
lines changed

1 file changed

+94
-88
lines changed

core/src/processing/core/PShapeOBJ.java

Lines changed: 94 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
package processing.core;
2424

2525
import java.io.BufferedReader;
26+
import java.io.File;
2627
import java.util.ArrayList;
27-
import java.util.HashMap;
28-
import java.util.Map;
28+
import java.util.Hashtable;
2929

3030
/**
3131
* This class is not part of the Processing API and should not be used
@@ -45,18 +45,21 @@ public class PShapeOBJ extends PShape {
4545
* Initializes a new OBJ Object with the given filename.
4646
*/
4747
public PShapeOBJ(PApplet parent, String filename) {
48-
this(parent, parent.createReader(filename));
48+
this(parent, parent.createReader(filename), getBasePath(parent, filename));
4949
}
5050

51-
5251
public PShapeOBJ(PApplet parent, BufferedReader reader) {
52+
this(parent, reader, "");
53+
}
54+
55+
public PShapeOBJ(PApplet parent, BufferedReader reader, String basePath) {
5356
ArrayList<OBJFace> faces = new ArrayList<OBJFace>();
5457
ArrayList<OBJMaterial> materials = new ArrayList<OBJMaterial>();
5558
ArrayList<PVector> coords = new ArrayList<PVector>();
5659
ArrayList<PVector> normals = new ArrayList<PVector>();
5760
ArrayList<PVector> texcoords = new ArrayList<PVector>();
58-
parseOBJ(parent, reader,
59-
faces, materials, coords, normals, texcoords);
61+
parseOBJ(parent, basePath, reader,
62+
faces, materials, coords, normals, texcoords);
6063

6164
// The OBJ geometry is stored with each face in a separate child shape.
6265
parent = null;
@@ -95,10 +98,10 @@ protected PShapeOBJ(OBJFace face, OBJMaterial mtl,
9598
vertexCount = face.vertIdx.size();
9699
vertices = new float[vertexCount][12];
97100
for (int j = 0; j < face.vertIdx.size(); j++){
98-
int vertIdx, normIdx, texIdx;
99-
PVector vert, norms, tex;
101+
int vertIdx, normIdx;
102+
PVector vert, norms;
100103

101-
vert = norms = tex = null;
104+
vert = norms = null;
102105

103106
vertIdx = face.vertIdx.get(j).intValue() - 1;
104107
vert = coords.get(vertIdx);
@@ -110,13 +113,6 @@ protected PShapeOBJ(OBJFace face, OBJMaterial mtl,
110113
}
111114
}
112115

113-
if (j < face.texIdx.size()) {
114-
texIdx = face.texIdx.get(j).intValue() - 1;
115-
if (-1 < texIdx) {
116-
tex = texcoords.get(texIdx);
117-
}
118-
}
119-
120116
vertices[j][X] = vert.x;
121117
vertices[j][Y] = vert.y;
122118
vertices[j][Z] = vert.z;
@@ -132,13 +128,23 @@ protected PShapeOBJ(OBJFace face, OBJMaterial mtl,
132128
vertices[j][PGraphics.NZ] = norms.z;
133129
}
134130

135-
if (tex != null) {
136-
vertices[j][PGraphics.U] = tex.x;
137-
vertices[j][PGraphics.V] = tex.y;
138-
}
139-
140131
if (mtl != null && mtl.kdMap != null) {
132+
// This face is textured.
133+
int texIdx;
134+
PVector tex = null;
135+
136+
if (j < face.texIdx.size()) {
137+
texIdx = face.texIdx.get(j).intValue() - 1;
138+
if (-1 < texIdx) {
139+
tex = texcoords.get(texIdx);
140+
}
141+
}
142+
141143
image = mtl.kdMap;
144+
if (tex != null) {
145+
vertices[j][PGraphics.U] = tex.x;
146+
vertices[j][PGraphics.V] = tex.y;
147+
}
142148
}
143149
}
144150
}
@@ -168,14 +174,14 @@ protected void addChildren(ArrayList<OBJFace> faces,
168174
}
169175

170176

171-
static protected void parseOBJ(PApplet parent,
177+
static protected void parseOBJ(PApplet parent, String path,
172178
BufferedReader reader,
173179
ArrayList<OBJFace> faces,
174180
ArrayList<OBJMaterial> materials,
175181
ArrayList<PVector> coords,
176182
ArrayList<PVector> normals,
177183
ArrayList<PVector> texcoords) {
178-
Map<String, Integer> mtlTable = new HashMap<String, Integer>();
184+
Hashtable<String, Integer> mtlTable = new Hashtable<String, Integer>();
179185
int mtlIdxCur = -1;
180186
boolean readv, readvn, readvt;
181187
try {
@@ -184,7 +190,7 @@ static protected void parseOBJ(PApplet parent,
184190
String line;
185191
String gname = "object";
186192
while ((line = reader.readLine()) != null) {
187-
// Parse the line.
193+
// Parse the line.
188194
line = line.trim();
189195
if (line.equals("") || line.indexOf('#') == 0) {
190196
// Empty line of comment, ignore line
@@ -216,35 +222,37 @@ static protected void parseOBJ(PApplet parent,
216222
if (parts[0].equals("v")) {
217223
// vertex
218224
PVector tempv = new PVector(Float.valueOf(parts[1]).floatValue(),
219-
Float.valueOf(parts[2]).floatValue(),
220-
Float.valueOf(parts[3]).floatValue());
225+
Float.valueOf(parts[2]).floatValue(),
226+
Float.valueOf(parts[3]).floatValue());
221227
coords.add(tempv);
222228
readv = true;
223229
} else if (parts[0].equals("vn")) {
224230
// normal
225231
PVector tempn = new PVector(Float.valueOf(parts[1]).floatValue(),
226-
Float.valueOf(parts[2]).floatValue(),
227-
Float.valueOf(parts[3]).floatValue());
232+
Float.valueOf(parts[2]).floatValue(),
233+
Float.valueOf(parts[3]).floatValue());
228234
normals.add(tempn);
229235
readvn = true;
230236
} else if (parts[0].equals("vt")) {
231237
// uv, inverting v to take into account Processing's inverted Y axis
232238
// with respect to OpenGL.
233239
PVector tempv = new PVector(Float.valueOf(parts[1]).floatValue(),
234-
1 - Float.valueOf(parts[2]).
235-
floatValue());
240+
1 - Float.valueOf(parts[2]).
241+
floatValue());
236242
texcoords.add(tempv);
237243
readvt = true;
238244
} else if (parts[0].equals("o")) {
239245
// Object name is ignored, for now.
240246
} else if (parts[0].equals("mtllib")) {
241-
242247
if (parts[1] != null) {
243248
String fn = parts[1];
249+
if (fn.indexOf(File.separator) == -1 && !path.equals("")) {
250+
// Relative file name, adding the base path.
251+
fn = path + File.separator + fn;
252+
}
244253
BufferedReader mreader = parent.createReader(fn);
245254
if (mreader != null) {
246-
parseMTL(parent, fn, mreader, materials, mtlTable);
247-
mreader.close();
255+
parseMTL(parent, path, mreader, materials, mtlTable);
248256
}
249257
}
250258
} else if (parts[0].equals("g")) {
@@ -332,10 +340,10 @@ static protected void parseOBJ(PApplet parent,
332340
}
333341

334342

335-
static protected void parseMTL(PApplet parent, String mtlfn,
343+
static protected void parseMTL(PApplet parent, String path,
336344
BufferedReader reader,
337345
ArrayList<OBJMaterial> materials,
338-
Map<String, Integer> materialsHash) {
346+
Hashtable<String, Integer> materialsHash) {
339347
try {
340348
String line;
341349
OBJMaterial currentMtl = null;
@@ -348,46 +356,39 @@ static protected void parseMTL(PApplet parent, String mtlfn,
348356
if (parts[0].equals("newmtl")) {
349357
// Starting new material.
350358
String mtlname = parts[1];
351-
currentMtl = addMaterial(mtlname, materials, materialsHash);
352-
} else {
353-
if (currentMtl == null) {
354-
currentMtl = addMaterial("material" + materials.size(),
355-
materials, materialsHash);
356-
}
357-
if (parts[0].equals("map_Kd") && parts.length > 1) {
358-
// Loading texture map.
359-
String texname = parts[1];
360-
currentMtl.kdMap = parent.loadImage(texname);
361-
if (currentMtl.kdMap == null) {
362-
System.err.println("The texture map \"" + texname + "\" " +
363-
"in the materials definition file \"" + mtlfn + "\" " +
364-
"is missing or inaccessible, make sure " +
365-
"the URL is valid or that the file has been " +
366-
"added to your sketch and is readable.");
367-
}
368-
} else if (parts[0].equals("Ka") && parts.length > 3) {
369-
// The ambient color of the material
370-
currentMtl.ka.x = Float.valueOf(parts[1]).floatValue();
371-
currentMtl.ka.y = Float.valueOf(parts[2]).floatValue();
372-
currentMtl.ka.z = Float.valueOf(parts[3]).floatValue();
373-
} else if (parts[0].equals("Kd") && parts.length > 3) {
374-
// The diffuse color of the material
375-
currentMtl.kd.x = Float.valueOf(parts[1]).floatValue();
376-
currentMtl.kd.y = Float.valueOf(parts[2]).floatValue();
377-
currentMtl.kd.z = Float.valueOf(parts[3]).floatValue();
378-
} else if (parts[0].equals("Ks") && parts.length > 3) {
379-
// The specular color weighted by the specular coefficient
380-
currentMtl.ks.x = Float.valueOf(parts[1]).floatValue();
381-
currentMtl.ks.y = Float.valueOf(parts[2]).floatValue();
382-
currentMtl.ks.z = Float.valueOf(parts[3]).floatValue();
383-
} else if ((parts[0].equals("d") ||
384-
parts[0].equals("Tr")) && parts.length > 1) {
385-
// Reading the alpha transparency.
386-
currentMtl.d = Float.valueOf(parts[1]).floatValue();
387-
} else if (parts[0].equals("Ns") && parts.length > 1) {
388-
// The specular component of the Phong shading model
389-
currentMtl.ns = Float.valueOf(parts[1]).floatValue();
359+
currentMtl = new OBJMaterial(mtlname);
360+
materialsHash.put(mtlname, new Integer(materials.size()));
361+
materials.add(currentMtl);
362+
} else if (parts[0].equals("map_Kd") && parts.length > 1) {
363+
// Loading texture map.
364+
String texname = parts[1];
365+
if (texname.indexOf(File.separator) == -1 && !path.equals("")) {
366+
// Relative file name, adding the base path.
367+
texname = path + File.separator + texname;
390368
}
369+
currentMtl.kdMap = parent.loadImage(texname);
370+
} else if (parts[0].equals("Ka") && parts.length > 3) {
371+
// The ambient color of the material
372+
currentMtl.ka.x = Float.valueOf(parts[1]).floatValue();
373+
currentMtl.ka.y = Float.valueOf(parts[2]).floatValue();
374+
currentMtl.ka.z = Float.valueOf(parts[3]).floatValue();
375+
} else if (parts[0].equals("Kd") && parts.length > 3) {
376+
// The diffuse color of the material
377+
currentMtl.kd.x = Float.valueOf(parts[1]).floatValue();
378+
currentMtl.kd.y = Float.valueOf(parts[2]).floatValue();
379+
currentMtl.kd.z = Float.valueOf(parts[3]).floatValue();
380+
} else if (parts[0].equals("Ks") && parts.length > 3) {
381+
// The specular color weighted by the specular coefficient
382+
currentMtl.ks.x = Float.valueOf(parts[1]).floatValue();
383+
currentMtl.ks.y = Float.valueOf(parts[2]).floatValue();
384+
currentMtl.ks.z = Float.valueOf(parts[3]).floatValue();
385+
} else if ((parts[0].equals("d") ||
386+
parts[0].equals("Tr")) && parts.length > 1) {
387+
// Reading the alpha transparency.
388+
currentMtl.d = Float.valueOf(parts[1]).floatValue();
389+
} else if (parts[0].equals("Ns") && parts.length > 1) {
390+
// The specular component of the Phong shading model
391+
currentMtl.ns = Float.valueOf(parts[1]).floatValue();
391392
}
392393
}
393394
}
@@ -396,27 +397,19 @@ static protected void parseMTL(PApplet parent, String mtlfn,
396397
}
397398
}
398399

399-
protected static OBJMaterial addMaterial(String mtlname,
400-
ArrayList<OBJMaterial> materials,
401-
Map<String, Integer> materialsHash) {
402-
OBJMaterial currentMtl = new OBJMaterial(mtlname);
403-
materialsHash.put(mtlname, Integer.valueOf(materials.size()));
404-
materials.add(currentMtl);
405-
return currentMtl;
406-
}
407400

408401
protected static int rgbaValue(PVector color) {
409402
return 0xFF000000 | ((int)(color.x * 255) << 16) |
410-
((int)(color.y * 255) << 8) |
411-
(int)(color.z * 255);
403+
((int)(color.y * 255) << 8) |
404+
(int)(color.z * 255);
412405
}
413406

414407

415408
protected static int rgbaValue(PVector color, float alpha) {
416409
return ((int)(alpha * 255) << 24) |
417-
((int)(color.x * 255) << 16) |
418-
((int)(color.y * 255) << 8) |
419-
(int)(color.z * 255);
410+
((int)(color.x * 255) << 16) |
411+
((int)(color.y * 255) << 8) |
412+
(int)(color.z * 255);
420413
}
421414

422415

@@ -438,6 +431,18 @@ static protected class OBJFace {
438431
}
439432

440433

434+
static protected String getBasePath(PApplet parent, String filename) {
435+
// Obtaining the path
436+
File file = new File(parent.dataPath(filename));
437+
if (!file.exists()) {
438+
file = parent.sketchFile(filename);
439+
}
440+
String absolutePath = file.getAbsolutePath();
441+
return absolutePath.substring(0,
442+
absolutePath.lastIndexOf(File.separator));
443+
}
444+
445+
441446
// Stores a material defined in an MTL file.
442447
static protected class OBJMaterial {
443448
String name;
@@ -462,4 +467,5 @@ static protected class OBJMaterial {
462467
kdMap = null;
463468
}
464469
}
465-
}
470+
}
471+

0 commit comments

Comments
 (0)