gpt4 book ai didi

java - 如何3D打印JavaFX 3D场景?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:24:29 24 4
gpt4 key购买 nike

我一直在使用 JavaFX 开发这个科学应用程序。该程序基本上从算法生成数据并将它们可视化为相交的球体。 enter image description here

我想 3D 打印这个模型的一部分(彩色形状)。有没有办法导出 JavaFX 场景?即使这意味着将其导出到 .STL 或 .obj 等文件中,然后导入到 Blender 中以进行进一步优化或文件转换。

最佳答案

如果您想将 3D 模型导出为 .obj,您需要访问每个形状的 TriangleMesh,以便导出顶点和面。

目前,使用内置的 JavaFX 3D 形状,如 Sphere,这是不可能的,因为它们的网格没有暴露。

此外,没有内置的导出方法。

因此,解决方案将从头开始创建您的 3D 形状并提供导出方法,或者使用第三方解决方案。

如果您查看 F(X)yz library ,它解决了你的部分问题,因为它已经提供了:

  • 可完全访问其网格信息的多个 3D 形状
  • 导出任何给定 3D 形状的 .obj 和 .mtl。

不幸的是,它现在不允许将多个形状导出到一个 .obj 文件中,但可以轻松添加。

这是一个Group导出器的快速实现,它会将组中的所有MeshView及其漫射颜色导出到一个单独的obj文件和一个单独的mtl文件中.

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) {}
}
}
}

使用 F(X)yz 中的 SegmentedSphereMesh,您可以创建一个球体,因此这将是如何构建一个组并导出它们的示例:

@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

如果您现在使用 3DViewer 导入生成的 spheres.obj你会看到:

3DViewer

关于java - 如何3D打印JavaFX 3D场景?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38414393/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com