32 package eu.mihosoft.vrl.v3d.ext.openjfx.importers.obj;
34 import eu.mihosoft.vrl.v3d.ObjFile;
35 import eu.mihosoft.vrl.v3d.ext.openjfx.importers.SmoothingGroups;
36 import java.io.BufferedReader;
37 import java.io.FileNotFoundException;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.io.InputStreamReader;
42 import java.util.ArrayList;
43 import java.util.Collection;
44 import java.util.HashMap;
45 import java.util.List;
48 import java.util.logging.Level;
49 import java.util.logging.Logger;
50 import javafx.scene.paint.Color;
51 import javafx.scene.paint.Material;
52 import javafx.scene.paint.PhongMaterial;
53 import javafx.scene.shape.CullFace;
54 import javafx.scene.shape.Mesh;
55 import javafx.scene.shape.MeshView;
56 import javafx.scene.shape.TriangleMesh;
107 private static boolean debug =
false;
120 static void log(String
string) {
122 System.out.println(
string);
136 private final Map<String, TriangleMesh>
meshes =
new HashMap<>();
139 private final Map<String, Material>
materials =
new HashMap<>();
177 read(obj.getObjStream(), obj.getMtlStream());
186 return meshes.values().iterator().next();
213 return materials.values().iterator().next();
243 MeshView meshView =
new MeshView();
245 meshView.setMaterial(
materials.get(key));
246 meshView.setMesh(
meshes.get(key));
247 meshView.setCullFace(CullFace.NONE);
288 private Material
material =
new PhongMaterial(Color.WHITE);
305 private void read(InputStream objInputStream)
throws IOException {
306 read(objInputStream,
null);
316 private void read(InputStream objInputStream, InputStream mtlInputStream)
throws IOException {
317 BufferedReader br =
new BufferedReader(
new InputStreamReader(objInputStream));
319 int currentSmoothGroup = 0;
320 String key =
"default";
321 while ((line = br.readLine()) !=
null) {
323 if (line.startsWith(
"g ") || line.equals(
"g")) {
325 key = line.length() > 2 ? line.substring(2) :
"default";
327 }
else if (line.startsWith(
"v ")) {
328 String[] split = line.substring(2).trim().split(
" +");
329 float x = Float.parseFloat(split[0]) *
scale;
330 float y = Float.parseFloat(split[1]) *
scale;
331 float z = Float.parseFloat(split[2]) *
scale;
342 }
else if (line.startsWith(
"vt ")) {
343 String[] split = line.substring(3).trim().split(
" +");
344 float u = Float.parseFloat(split[0]);
345 float v = Float.parseFloat(split[1]);
350 }
else if (line.startsWith(
"f ")) {
351 String[] split = line.substring(2).trim().split(
" +");
352 int[][] data =
new int[split.length][];
353 boolean uvProvided =
true;
354 boolean normalProvided =
true;
355 for (
int i = 0; i < split.length; i++) {
356 String[] split2 = split[i].split(
"/");
357 if (split2.length < 2) {
360 if (split2.length < 3) {
361 normalProvided =
false;
363 data[i] =
new int[split2.length];
364 for (
int j = 0; j < split2.length; j++) {
365 if (split2[j].length() == 0) {
371 normalProvided =
false;
374 data[i][j] = Integer.parseInt(split2[j]);
381 if (uvProvided && !
flatXZ) {
387 if (normalProvided) {
390 normalProvided =
false;
393 for (
int i = 1; i < data.length - 1; i++) {
400 if (uvProvided && !
flatXZ) {
404 if (normalProvided) {
423 }
else if (line.startsWith(
"s ")) {
424 if (line.substring(2).equals(
"off")) {
425 currentSmoothGroup = 0;
427 currentSmoothGroup = Integer.parseInt(line.substring(2));
429 }
else if (line.startsWith(
"mtllib ")) {
431 String[] split = line.substring(
"mtllib ".length()).trim().split(
" +");
433 if (mtlInputStream ==
null) {
434 for (String filename : split) {
441 if (split.length > 1) {
442 log(
"WARNING: more than one mtllib not supported if reading from streams! Using only one mtllib.");
447 }
else if (line.startsWith(
"usemtl ")) {
450 String materialName = line.substring(
"usemtl ".length());
452 Material m = mm.get(materialName);
458 }
else if (line.isEmpty() || line.startsWith(
"#")) {
460 }
else if (line.startsWith(
"vn ")) {
461 String[] split = line.substring(2).trim().split(
" +");
462 float x = Float.parseFloat(split[0]);
463 float y = Float.parseFloat(split[1]);
464 float z = Float.parseFloat(split[2]);
469 log(
"line skipped: " + line);
471 }
catch (Exception ex) {
472 Logger.getLogger(
MtlReader.class.getName()).log(Level.SEVERE,
"Failed to parse line:" + line, ex);
478 "Totally loaded " + (
vertexes.
size() / 3.) +
" vertexes, "
495 Map<Integer, Integer> vertexMap =
new HashMap<>(
vertexes.
size() / 2);
496 Map<Integer, Integer> uvMap =
new HashMap<>(
uvs.
size() / 2);
497 Map<Integer, Integer> normalMap =
new HashMap<>(
normals.
size() / 2);
501 boolean useNormals =
true;
505 Integer nvi = vertexMap.get(vi);
507 nvi = newVertexes.
size() / 3;
508 vertexMap.put(vi, nvi);
516 Integer nuvi = uvMap.get(uvi);
518 nuvi = newUVs.
size() / 2;
519 uvMap.put(uvi, nuvi);
532 Integer nni = normalMap.get(ni);
534 nni = newNormals.
size() / 3;
535 normalMap.put(ni, nni);
551 TriangleMesh mesh =
new TriangleMesh();
561 mesh.getFaceSmoothingGroups().setAll(smGroups);
567 String keyBase = key;
568 while (
meshes.get(key) !=
null) {
569 key = keyBase +
" (" + keyIndex++ +
")";
575 "Added mesh '" + key +
"' of " + mesh.getPoints().size() / mesh.getPointElementSize() +
" vertexes, "
576 + mesh.getTexCoords().size() / mesh.getTexCoordElementSize() +
" uvs, "
577 + mesh.getFaces().size() / mesh.getFaceElementSize() +
" faces, "
578 + mesh.getFaceSmoothingGroups().size() +
" smoothing groups.");
579 log(
"material diffuse color = " + ((PhongMaterial)
material).getDiffuseColor());
580 log(
"material diffuse map = " + ((PhongMaterial)
material).getDiffuseMap());
List< Integer > subList(int fromIndex, int toIndex)
Integer set(int index, Integer element)
Map< String, Material > getMaterials()
IntegerArrayList smoothingGroups
void read(InputStream objInputStream)
void read(InputStream objInputStream, InputStream mtlInputStream)
Collection< Material > getMaterialCollection()
Collection< TriangleMesh > getMeshCollection()
final List< Map< String, Material > > materialLibrary
TriangleMesh getMesh(String key)
Material getMaterial(String key)
final Map< String, TriangleMesh > meshes
MeshView buildMeshView(String key)
ObjImporter(InputStream inputStream)
int normalIndex(int normalIndex)
static void setDebug(boolean debug)
final Map< String, Material > materials
static void setFlatXZ(boolean flatXZ)
Set< String > getMeshes()
int vertexIndex(int vertexIndex)
IntegerArrayList faceNormals
ObjImporter(String objFileUrl)
static void setScale(float scale)