2016-01-02 1 views
1

Existe-t-il un moyen de convertir JavaFX Node, Group ou Shape3D en Mesh?Convertir le noeud JavaFX, le groupe ou Shape3D en maillage

J'ai besoin de cela pour exporter ma scène à '.obj' et le seul exportateur que j'ai trouvé (dans la bibliothèque FXyz) nécessite Mesh.

+0

Chaque nœud 3D dans la scène pourrait se transformer en objets équivalents avec un maillage connu, et ceux-ci pourraient être exporté. Est-ce ce que vous recherchez? Quel genre d'objets avez-vous? –

+0

@ JoséPereda, je pense. Cela semble au moins être un pas dans la bonne direction. J'utilise les objets 'Sphere' et' Cylinder'. – kcpr

+0

Pouvez-vous poster un échantillon de ce que vous avez? –

Répondre

2

Le principal problème lors de l'utilisation intégrée Shape3D nœuds comme Sphere, Cylinder ou Box est ceux qui ne pas exposer leur TriangleMesh.

Si vous avez besoin ce maillage, il y a plusieurs options:

  1. Créer votre propre implémentation de cette forme, où vous fournissez le maillage
  2. Utilisez des formes équivalentes bibliothèque FXyz à la place, vous aurez déjà maille dans chacun d'entre eux
  3. S'en tenir aux noeuds Shape3D intégrés si cela est obligatoire, mais avant de les exporter, transformez-les en formes équivalentes à partir de la bibliothèque FXyz, afin que vous puissiez accéder à leurs maillages.

En ce qui concerne l'exportation du modèle, le ObjWriter actuel fxyz exporte une seule maille à la fois, de sorte que vous pouvez:

  1. Export toutes les formes de leur propre fichier .obj
  2. Modifier ObjWriter afin d'exporter une liste de maillages vers un seul fichier (vous pouvez créer une requête pull vers FXyz si vous le faites)
  3. utilisez MeshHelper pour créer un seul maillage (un seul matériau peut être appliqué), et exportez-le en un seul fichier .obj.

Je supposerai le troisième cas dans les deux situations, en créant un nouvel objet TexturedMesh, basé sur toutes les formes 3D trouvées sur la scène. Cela aura un seul maillage qui peut être exporté dans un fichier obj. Notez que vous avez besoin de FXyzLib.jar.

class EquivalentMesh extends TexturedMesh { 

    private MeshHelper mh = null; 

    public EquivalentMesh(Parent root) { 
     ArrayList<Node> nodes = new ArrayList<>(); 
     addShapes3D(root, nodes); 

     transformAndMerge(nodes); 
    } 

    // Transform Built-in Shape3Ds to a single TexturedMesh 
    private void transformAndMerge(ArrayList<Node> nodes) { 

     nodes.stream().forEach(shape -> { 
      TriangleMesh tm = null; 
      if (shape instanceof Sphere) { 
       Sphere sphere = (Sphere)shape; 
       SegmentedSphereMesh sm = new SegmentedSphereMesh(sphere.getRadius()); 
       sm.setCenter(new Point3D((float)sphere.getTranslateX(), (float)sphere.getTranslateY(), (float)sphere.getTranslateZ())); 
       tm = (TriangleMesh)sm.getMesh(); 
      } else if (shape instanceof Cylinder) { 
       Cylinder cylinder = (Cylinder)shape; 
       FrustumMesh fm = new FrustumMesh(cylinder.getRadius(), cylinder.getRadius(), cylinder.getHeight()); 
       Affine affine = new Affine(); 
       cylinder.getTransforms().forEach(affine::append); 
       javafx.geometry.Point3D ini = affine.transform(new javafx.geometry.Point3D(0, cylinder.getHeight()/2, 0)); 
       javafx.geometry.Point3D end = affine.transform(new javafx.geometry.Point3D(0, - cylinder.getHeight()/2, 0)); 
       fm.setAxisOrigin(new Point3D((float)ini.getX(), (float)ini.getY(), (float)ini.getZ())); 
       fm.setAxisEnd(new Point3D((float)end.getX(), (float)end.getY(), (float)end.getZ())); 
       fm.setSectionType(TriangleMeshHelper.SectionType.CIRCLE); 
       tm = (TriangleMesh)fm.getMesh(); 
      } else if (shape instanceof Box) { 
       Box box = (Box)shape; 
       CuboidMesh cm = new CuboidMesh(box.getWidth(), box.getHeight(), box.getDepth()); 
       cm.setCenter(new Point3D((float)box.getTranslateX(), (float)box.getTranslateY(), (float)box.getTranslateZ())); 
       // TODO: apply rotations 
       tm = (TriangleMesh)cm.getMesh(); 
      } else if (shape instanceof MeshView) { 
       tm = (TriangleMesh)((MeshView)shape).getMesh(); 
       // TODO: apply transformations 
      } 

      if (mh == null) { 
       mh = new MeshHelper(tm); 
      } else { 
       mh.addMesh(new MeshHelper(tm)); 
      } 
     }); 

     // create single mesh 
     updateMesh(mh); 
    } 

    private void addShapes3D(Parent parent, ArrayList<Node> nodes) { 
     for (Node node : parent.getChildrenUnmodifiable()) { 
      if (node instanceof Shape3D) { 
       nodes.add(node); 
      } 
      if (node instanceof Parent) { 
       addShapes3D((Parent)node, nodes); 
      } 
     } 
    } 

    @Override 
    protected void updateMesh() { 
     // no-op 
    } 

    // export to obj and mtl 
    public void export(String nameFile) { 
     OBJWriter writer=new OBJWriter((TriangleMesh) getMesh(), nameFile); 
     writer.setMaterialColor(Color.RED); 
     writer.exportMesh(); 
    } 

} 

Pour le tester, nous allons créer une scène simple:

@Override 
public void start(Stage primaryStage) { 
    Sphere sphere = new Sphere(100); 
    sphere.setMaterial(new PhongMaterial(Color.BLUE)); 
    Box box = new Box(50,50,50); 
    box.setMaterial(new PhongMaterial(Color.RED)); 
    box.setTranslateX(300); 
    Cylinder cylinder = new Cylinder(2, 300); 
    cylinder.setMaterial(new PhongMaterial(Color.GREEN)); 
    // Transformations applied: 
    cylinder.getTransforms().addAll(new Translate(150, 0, 0), new Rotate(90, Rotate.Z_AXIS)); 

    Group group = new Group(cylinder, sphere, box); 
    StackPane root = new StackPane(group); 

    Scene scene = new Scene(root, 600, 400); 

    primaryStage.setScene(scene); 
    primaryStage.show(); 

    // export as single mesh 
    EquivalentMesh equivalentMesh = new EquivalentMesh(root); 
    equivalentMesh.export("group"); 
} 

Initial scene

Notez que par la création d'une nouvelle instance de EquivalentMesh, nous avons maintenant un maillage unique et nous pouvons l'exporter, en générant des fichiers group.obj et group.mtl.

Enfin, en utilisant 3DViewer pour importer le fichier obj, c'est ce que vous obtenez:

3DViewer obj file