2016-07-16 26 views
6

मैं जावाएफएक्स में इस वैज्ञानिक अनुप्रयोग पर काम कर रहा हूं। कार्यक्रम मूल रूप से एक एल्गोरिदम से डेटा उत्पन्न करता है और उन्हें छेड़छाड़ करने वाले क्षेत्रों में देखता है। enter image description hereकैसे 3 डी प्रिंट जावाएफएक्स 3 डी दृश्य?

मैं इस मॉडल (रंगीन आकार) का 3 डी प्रिंट हिस्सा चाहता हूं। क्या JavaFX दृश्य निर्यात करने का कोई तरीका है? भले ही इसका मतलब है कि इसे .stl या .obj जैसी फ़ाइल में निर्यात करना और ब्लेंडर में आयात करना और परिष्करण या फ़ाइल रूपांतरण के लिए आयात करना।

उत्तर

3

यदि आप अपने 3 डी मॉडल को .obj में निर्यात करना चाहते हैं तो आपको प्रत्येक आकार के TriangleMesh तक पहुंच प्राप्त करने की आवश्यकता है, ताकि आप कोष्ठक और चेहरे निर्यात कर सकें।

वर्तमान में, Sphere जैसे अंतर्निहित जावाएफएक्स 3 डी आकारों का उपयोग करके, यह संभव नहीं है, क्योंकि उनके मेष का खुलासा नहीं किया जाता है।

इसके अलावा, कोई अंतर्निहित निर्यात विधि नहीं है।

तो समाधान आपके 3 डी आकारों को स्क्रैच से बनाएगा और निर्यात विधि प्रदान करेगा, या तृतीय पक्ष समाधान का उपयोग करेगा।

आप एफ (एक्स) YZ library पर एक नजर है, तो यह अपनी समस्याओं का हिस्सा हल करती है, क्योंकि यह पहले से ही प्रदान करता है:

  • कई 3 डी आकार उनके meshes जानकारी
  • निर्यात करने के लिए पूर्ण पहुँच के साथ किसी दिए गए 3 डी आकार के लिए .obj और .mtl को।

दुर्भाग्यवश यह अब एक एकल .obj फ़ाइल में एकाधिक आकारों को निर्यात करने की अनुमति नहीं देता है, लेकिन ऐसा कुछ है जिसे आसानी से जोड़ा जा सकता है।

यह Group निर्यातक का त्वरित कार्यान्वयन है, जो समूह में सभी MeshView और उनके प्रसार रंग को एक ओबीजे फ़ाइल और एक एकल एमटीएल फ़ाइल में निर्यात करेगा।

public class GroupOBJWriter { 

    private final String newline = System.getProperty("line.separator"); 
    private float[] points0, texCoord0; 
    private int[] faces0, sm0; 
    private BufferedWriter writer = null; 
    private final String fileName; 
    private String diffuseMap; 
    private String diffuseColor = "0.0 0.0 0.0"; // black 
    private final Group group; 

    public GroupOBJWriter(Group group, String fileName){ 
     this.group = group; 
     this.fileName = fileName; 
    } 

    public void exportMesh(){ 
     File objFile = new File(fileName + ".obj"); 
     try{ 
      writer = new BufferedWriter(new FileWriter(objFile)); 
      writer.write("mtllib " + fileName + ".mtl" + newline); 

      AtomicInteger counter = new AtomicInteger(); 
      AtomicInteger vCounter = new AtomicInteger(); 

      group.getChildren().stream() 
       .filter(MeshView.class::isInstance) 
       .map(s -> (TriangleMesh) ((MeshView) s).getMesh()) 
       .forEach(mesh -> { 
        try{ 
         writer.write("# Material" + newline); 
         int count = counter.getAndIncrement(); 
         writer.write("usemtl " + fileName + "-" + count + ""+newline); 

         points0 = new float[mesh.getPoints().size()]; 
         mesh.getPoints().toArray(points0); 
         List<Point3D> points1 = IntStream.range(0, points0.length/3) 
          .mapToObj(i -> new Point3D(points0[3*i], points0[3*i+1], points0[3*i+2])) 
          .collect(Collectors.toList()); 

         writer.write("# Vertices (" + points1.size() + ") for shape " + count + "" + newline); 
         points1.forEach(p -> { 
          try { 
           writer.write("v " + p.x + " " + p.y + " " + p.z + "" + newline); 
          } catch (IOException ex) { 
           System.out.println("Error writting vertex "+ex); 
          } 
         }); 
         writer.write(newline); 

         texCoord0 = new float[mesh.getTexCoords().size()]; 
         mesh.getTexCoords().toArray(texCoord0); 

         List<Point2D> texCoord1 = IntStream.range(0, texCoord0.length/2) 
           .mapToObj(i -> new Point2D(texCoord0[2*i], texCoord0[2*i+1])) 
           .collect(Collectors.toList()); 

         writer.write("# Textures Coordinates (" + texCoord1.size() + ") for shape " + count + "" + newline); 
         texCoord1.forEach(t->{ 
          try { 
           // objimporter u->u, v->(1-v) 
           writer.write("vt " + ((float) t.getX()) + " " + ((float) (1d - t.getY())) + "" +newline); 
          } catch (IOException ex) { 
           System.out.println("Error writting texture coordinate " + ex); 
          } 
         }); 
         writer.write(newline); 

         faces0 = new int[mesh.getFaces().size()]; 
         mesh.getFaces().toArray(faces0); 
         List<Integer[]> faces1 = IntStream.range(0, faces0.length/6) 
           .mapToObj(i -> new Integer[]{faces0[6*i], faces0[6*i+1], 
            faces0[6*i+2], faces0[6*i+3], 
            faces0[6*i+4], faces0[6*i+5]}) 
           .collect(Collectors.toList()); 

         writer.write("# Faces (" + faces1.size() + ") for shape " + count + "" + newline); 
         writer.write("# Material for shape " + count + "" + newline); 
         writer.write("usemtl " + fileName + "-" + count + "" + newline); 
         sm0 = new int[mesh.getFaces().size()]; 
         mesh.getFaceSmoothingGroups().toArray(sm0); 
         if (sm0[0] > 0) { 
          writer.write("s " + sm0[0] + "" + newline); 
         } 

         AtomicInteger c = new AtomicInteger(); 
         final int inc = vCounter.get() + 1; 
         faces1.forEach(f->{ 
          try { 
           writer.write("f " + (f[0] + inc) + "/" + (f[1] + inc) + 
               " " + (f[2] + inc) + "/" + (f[3] + inc) + 
               " " + (f[4] + inc) + "/" + (f[5] + inc) + "" + newline); 
           if (sm0[c.getAndIncrement()] != sm0[c.get()]) { 
            writer.write("s " + (sm0[c.get()] > 0 ? sm0[c.get()] : "off") + "" + newline); 
           } 
          } catch (IOException ex) { 
           System.out.println("Error writting face "+ex); 
          } 
         }); 
         vCounter.addAndGet(points1.size()); 
         writer.write(newline); 
        } catch(IOException io){ 
         System.out.println("Error creating writer obj " + io); 
        } 
       }); 
     } catch(IOException io){ 
      System.out.println("Error creating writer obj "+io); 
     } finally { 
      try { 
       if(writer!=null){ 
        writer.close(); 
       } 
      } catch (Exception e) {} 
     } 

     File mtlFile = new File(fileName+".mtl"); 

     try{ 
      writer = new BufferedWriter(new FileWriter(mtlFile)); 

      AtomicInteger counter = new AtomicInteger(); 
      group.getChildren().stream() 
       .filter(MeshView.class::isInstance) 
       .map(s -> ((PhongMaterial) ((MeshView) s).getMaterial()).getDiffuseColor()) 
       .forEach(color -> { 
        try{ 
         diffuseColor=""+((float)(color.getRed()))+" "+((float)(color.getGreen()))+" "+((float)(color.getBlue())); 

         int count = counter.getAndIncrement(); 
         writer.write("# Material " + fileName + "-" + count + "" + newline); 
         writer.write("newmtl " + fileName + "-" + count + "" + newline); 
         writer.write("illum 4" + newline); // Illumination [0-10] 
         writer.write("Kd " + diffuseColor + "" + newline); // diffuse color black 
         writer.write("Ka 0.10 0.10 0.10" + newline); // ambient color 
         writer.write("Tf 1.00 1.00 1.00" + newline); // Transmission filter 
         if (diffuseMap != null) { 
          writer.write("map_Kd " + diffuseMap + "" + newline); 
         } 
         writer.write("Ni 1.00" + newline); // optical density 
         writer.write("Ks 1.00 1.00 1.00" + newline); // specular reflectivity 
         writer.write("Ns 32.00" + newline); // specular exponent 
         writer.write(newline); 
        } catch(IOException io){ 
         System.out.println("Error creating writer obj " + io); 
        } 
       }); 
     } catch(IOException io){ 
      System.out.println("Error creating writer mtl "+io); 
     } finally { 
      try { 
       if(writer!=null){ 
        writer.close(); 
       } 
      } catch (Exception e) {} 
     } 
    } 
} 
SegmentedSphereMesh एफ (एक्स) से साथ

YZ आप एक क्षेत्र बना सकते हैं, तो यह कैसे एक समूह का निर्माण करने का एक नमूना हो सकता है और उन्हें निर्यात होगा:

@Override 
public void start(Stage primaryStage) throws Exception { 
    PerspectiveCamera camera = new PerspectiveCamera(true); 
    camera.setTranslateZ(-20); 
    Group sceneRoot = new Group(); 
    Scene scene = new Scene(sceneRoot, 800, 600, true, SceneAntialiasing.BALANCED); 
    scene.setCamera(camera); 
    Group group = new Group(); 

    for (int i = -5; i < 5; i++) { 
     for (int j = -2; j < 2; j++) { 
      for (int k = 0; k < 3; k++) { 
       SegmentedSphereMesh sphere = new SegmentedSphereMesh(50, 0, 0, 0.75, new Point3D((float) i, (float) j, (float) k)); 

       sphere.setTextureModeNone(Color.rgb(255/10 * (6 + i), 255/5 * (j + 3), 255/3 * (k + 1))); 
       group.getChildren().add(sphere); 
      } 
     } 
    } 

    group.getTransforms().addAll(new Rotate(40, Rotate.X_AXIS), new Rotate(10, Rotate.Y_AXIS)); 
    sceneRoot.getChildren().addAll(group);   

    primaryStage.setTitle("F(X)yz - Segmented Spheres Group"); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 

    GroupOBJWriter writer=new GroupOBJWriter(group,"spheres"); 
    writer.exportMesh(); 
} 

Group of spheres

हैं अब आप परिणाम spheres.obj3DViewer के साथ आयात करेंगे, आप देखेंगे:

3DViewer