32 package eu.mihosoft.vrl.v3d.ext.openjfx.importers.obj;
36 import eu.mihosoft.vrl.v3d.ext.openjfx.importers.SmoothingGroups;
37 import eu.mihosoft.vrl.v3d.ext.openjfx.shape3d.PolygonMesh;
38 import eu.mihosoft.vrl.v3d.ext.openjfx.shape3d.PolygonMeshView;
39 import javafx.scene.paint.Color;
40 import javafx.scene.paint.Material;
41 import javafx.scene.paint.PhongMaterial;
47 import java.util.logging.Level;
48 import java.util.logging.Logger;
100 private static boolean debug =
false;
113 static void log(String
string) {
115 System.out.println(
string);
129 private Map<String, PolygonMesh>
meshes =
new HashMap<>();
132 private Map<String, Material>
materials =
new HashMap<>();
148 this.objFilename = filename;
149 log(
"Reading filename = " + filename);;
150 read(
new URL(filename).openStream());
169 return meshes.values().iterator().next();
178 return materials.values().iterator().next();
209 polygonMeshView.setId(key);
213 return polygonMeshView;
241 private List<int[]>
faces =
new ArrayList<>();
253 private Material
material =
new PhongMaterial(Color.WHITE);
270 private void read(InputStream inputStream)
throws IOException {
271 BufferedReader br =
new BufferedReader(
new InputStreamReader(inputStream));
273 int currentSmoothGroup = 0;
274 String key =
"default";
275 while ((line = br.readLine()) !=
null) {
277 if (line.startsWith(
"g ") || line.equals(
"g")) {
279 key = line.length() > 2 ? line.substring(2) :
"default";
281 }
else if (line.startsWith(
"v ")) {
282 String[] split = line.substring(2).trim().split(
" +");
283 float x = Float.parseFloat(split[0]) *
scale;
284 float y = Float.parseFloat(split[1]) *
scale;
285 float z = Float.parseFloat(split[2]) *
scale;
297 }
else if (line.startsWith(
"vt ")) {
298 String[] split = line.substring(3).trim().split(
" +");
299 float u = split[0].trim().equalsIgnoreCase(
"nan") ? Float.NaN : Float.parseFloat(split[0]);
300 float v = split[1].trim().equalsIgnoreCase(
"nan") ? Float.NaN : Float.parseFloat(split[1]);
306 }
else if (line.startsWith(
"f ")) {
307 String[] split = line.substring(2).trim().split(
" +");
308 int[] faceIndexes =
new int[split.length*2];
309 int[] faceNormalIndexes =
new int[split.length];
310 for (
int i = 0; i < split.length; i++) {
311 String[] split2 = split[i].split(
"/");
312 faceIndexes[i*2] =
vertexIndex(Integer.parseInt(split2[0]));
313 faceIndexes[(i*2)+1] = (split2.length > 1 && split2[1].length()>0) ?
uvIndex(Integer.parseInt(split2[1])) : -1;
314 faceNormalIndexes[i] = (split2.length > 2 && split2[2].length()>0) ?
normalIndex(Integer.parseInt(split2[2])) : -1;
316 faces.add(faceIndexes);
319 }
else if (line.startsWith(
"s ")) {
320 if (line.substring(2).equals(
"off")) {
321 currentSmoothGroup = 0;
323 currentSmoothGroup = Integer.parseInt(line.substring(2));
325 }
else if (line.startsWith(
"mtllib ")) {
327 String[] split = line.substring(
"mtllib ".length()).trim().split(
" +");
328 for (String filename : split) {
332 }
else if (line.startsWith(
"usemtl ")) {
335 String materialName = line.substring(
"usemtl ".length());
337 Material m = mm.get(materialName);
343 }
else if (line.isEmpty() || line.startsWith(
"#")) {
345 }
else if (line.startsWith(
"vn ")) {
346 String[] split = line.substring(2).trim().split(
" +");
347 float x = Float.parseFloat(split[0]);
348 float y = Float.parseFloat(split[1]);
349 float z = Float.parseFloat(split[2]);
354 log(
"line skipped: " + line);
356 }
catch (Exception ex) {
357 Logger.getLogger(
MtlReader.class.getName()).log(Level.SEVERE,
"Failed to parse line:" + line, ex);
362 log(
"Totally loaded " + (
vertexes.
size() / 3.) +
" vertexes, "
364 + (
faces.size() / 6.) +
" faces, "
379 Map<Integer, Integer> vertexMap =
new HashMap<>(
vertexes.
size() / 2);
380 Map<Integer, Integer> uvMap =
new HashMap<>(
uvs.
size() / 2);
381 Map<Integer, Integer> normalMap =
new HashMap<>(
normals.
size() / 2);
385 boolean useNormals =
true;
391 int[] faceIndexes =
faces.get(i);
393 for (
int j=0;j<faceIndexes.length;j+=2){
394 int vi = faceIndexes[j];
395 Integer nvi = vertexMap.get(vi);
397 nvi = newVertexes.
size() / 3;
398 vertexMap.put(vi, nvi);
403 faceIndexes[j] = nvi;
405 int uvi = faceIndexes[j+1];
406 Integer nuvi = uvMap.get(uvi);
408 nuvi = newUVs.
size() / 2;
409 uvMap.put(uvi, nuvi);
418 faceIndexes[j+1] = nuvi;
421 int ni = faceNormalIndexes[j/2];
422 Integer nni = normalMap.get(ni);
424 nni = newNormals.
size() / 3;
425 normalMap.put(ni, nni);
437 faceNormalIndexes[j/2] = nni;
458 System.out.println(
"mesh.points = " + mesh.
getPoints());
459 System.out.println(
"mesh.texCoords = " + mesh.
getTexCoords());
460 System.out.println(
"mesh.faces: ");
461 for (
int[] face: mesh.
faces) {
462 System.out.println(
" face:: "+Arrays.toString(face));
467 String keyBase = key;
468 while (
meshes.get(key) !=
null) {
469 key = keyBase +
" (" + keyIndex++ +
")";
474 log(
"Added mesh '" + key +
"' of " + (mesh.
getPoints().size()/3) +
" vertexes, "
476 + mesh.
faces.length +
" faces, "
477 + 0 +
" smoothing groups.");
478 log(
"material diffuse color = " + ((PhongMaterial)
material).getDiffuseColor());
479 log(
"material diffuse map = " + ((PhongMaterial)
material).getDiffuseMap());
List< Integer > subList(int fromIndex, int toIndex)
Map< String, Material > getMaterials()
static void setFlatXZ(boolean flatXZ)
Map< String, PolygonMesh > meshes
static void setDebug(boolean debug)
PolyObjImporter(String filename)
PolygonMesh getMesh(String key)
PolygonMeshView buildPolygonMeshView(String key)
void read(InputStream inputStream)
static void setScale(float scale)
Map< String, Material > materials
IntegerArrayList smoothingGroups
int vertexIndex(int vertexIndex)
Set< String > getMeshes()
Material getMaterial(String key)
int normalIndex(int normalIndex)
PolyObjImporter(InputStream inputStream)
List< Map< String, Material > > materialLibrary
void setMaterial(Material material)
void setMesh(PolygonMesh mesh)
ObservableFloatArray getTexCoords()
ObservableIntegerArray getFaceSmoothingGroups()
ObservableFloatArray getPoints()