2016-01-02 25 views
1

是否有任何可能的方法將JavaFX Node,GroupShape3D轉換爲Mesh將JavaFX節點,組或Shape3D轉換爲網格

我需要這個將我的場景導出到'.obj',我發現的唯一導出器(在FXyz庫中)需要Mesh

+0

每個3D節點有可能轉化爲等價物具有已知目,這些可能出口。這是你想要的?你有什麼樣的物體? –

+0

@JoséPereda,我認爲是。它至少看起來像朝着一個好方向邁出的一步。我使用'Sphere'和'Cylinder'對象。 – kcpr

+0

你可以發佈你的樣品嗎? –

回答

2

當使用內置Shape3D節點像SphereCylinderBox的主要問題是那些不暴露自己的TriangleMesh

如果你需要一個網格,有幾個選項:

  1. 創建自己的實現的形狀,在那裏你提供網格
  2. 使用FXyz庫相當於形狀代替的,所以你已經在在所有這些網格中都有網格
  3. 如果這是一項要求,但在導出它們之前將它們轉換爲與FXyz庫等效的形狀,以便您可以訪問它們的網格,請堅持內置Shape3D節點。

在導出模型而言,在FXyz當前ObjWriter只出口一個網狀的時間,所以您可以:

  1. 導出所有形狀自己obj文件
  2. 修改ObjWriter將網格列表導出到單個文件中(如果需要,歡迎創建一個到FXyz的拉取請求)
  3. 使用MeshHelper創建一個單一網格(只能應用一種材質),然後將其導出到一個.obj文件。

我將假定在這兩種情況下的第三種情況,創建一個新的TexturedMesh對象,基於在場景中找到的所有3D形狀。這將有一個可以導出到obj文件的網格。注意你需要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(); 
    } 

} 

爲了測試它,讓我們創建一個簡單的場景:

@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

注意,通過創建EquivalentMesh一個新實例,現在我們有一個網格,我們可以導出它,生成group.objgroup.mtl文件。

最後,使用3DViewer導入OBJ文件,這是你會得到什麼:

3DViewer obj file

場景中的