- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我一直在使用 JavaFX 开发这个科学应用程序。该程序基本上从算法生成数据并将它们可视化为相交的球体。
我想 3D 打印这个模型的一部分(彩色形状)。有没有办法导出 JavaFX 场景?即使这意味着将其导出到 .STL 或 .obj 等文件中,然后导入到 Blender 中以进行进一步优化或文件转换。
最佳答案
如果您想将 3D 模型导出为 .obj,您需要访问每个形状的 TriangleMesh
,以便导出顶点和面。
目前,使用内置的 JavaFX 3D 形状,如 Sphere
,这是不可能的,因为它们的网格没有暴露。
此外,没有内置的导出方法。
因此,解决方案将从头开始创建您的 3D 形状并提供导出方法,或者使用第三方解决方案。
如果您查看 F(X)yz library ,它解决了你的部分问题,因为它已经提供了:
不幸的是,它现在不允许将多个形状导出到一个 .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();
}
如果您现在使用 3DViewer 导入生成的 spheres.obj
你会看到:
关于java - 如何3D打印JavaFX 3D场景?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38414393/
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
我试图用这种形式简单地获取数字 28 integer+space+integer+integer+space+integer我试过这个正则表达式 \\s\\d\\d\\s 但我得到了两个数字11 和
最近一直在学习D语言。我一直对运行时感到困惑。 从我能收集到的关于它的信息中,(这不是很多)我知道它是一种有助于 D 的一些特性的运行时。像垃圾收集一样,它与您自己的程序一起运行。但是既然 D 是编译
想问一下这两个正则表达式有区别吗? \d\d\d 与 \d{3} 我已经在我的本地机器上使用 Java 和 Windows 操作系统对此进行了测试,两者都工作正常并且结果相同。但是,当在 linux
我正在学习 Go,而且我坚持使用 Go 之旅(exercise-stringer.go:https://tour.golang.org/methods/7)。 这是一些代码: type IPAddr
我在Java正则表达式中发现了一段令我困惑的代码: Pattern.compile( "J.*\\d[0-35-9]-\\d\\d-\\d\\d" ); 要编译的字符串是: String string
我在 ruby 代码上偶然发现了这个。我知道\d{4})\/(\d\d)\/(\d\d)\/(.*)/是什么意思,但是\1-\2-\3-\4 是什么意思? 最佳答案 \1-\2-\3-\4 是 b
我一直在努力解决这个问题,这让我很恼火。我了解 D 运行时库。它是什么,它做什么。我也明白你可以在没有它的情况下编译 D 应用程序。就像 XoMB 所做的那样。好吧,XoMB 定义了自己的运行时,但是
我有两个列表列表,子列表代表路径。我想找到所有路径。 List> pathList1 List> pathList2 当然是天真的解决方案: List> result = new ArrayList>
我需要使用 Regex 格式化一个字符串,该字符串包含数字、字母 a-z 和 A-Z,同时还包含破折号和空格。 从用户输入我有02-219 8 53 24 输出应该是022 198 53 24 我正在
目标是达到与this C++ example相同的效果: 避免创建临时文件。我曾尝试将 C++ 示例翻译为 D,但没有成功。我也尝试过不同的方法。 import std.datetime : benc
tl;dr:你好吗perfect forwarding在 D? 该链接有一个很好的解释,但例如,假设我有这个方法: void foo(T)(in int a, out int b, ref int c
有什么方法可以在 D 中使用abstract auto 函数吗? 如果我声明一个类如下: class MyClass { abstract auto foo(); } 我收到以下错误: mai
有没有人为内存中重叠的数组切片实现交集?算法在没有重叠时返回 []。 当 pretty-print (使用重叠缩进)内存中重叠的数组切片时,我想要这个。 最佳答案 如果您确定它们是数组,那么只需取 p
我已经开始学习 D,但我在使用 Andrei Alexandrescu 所著的 The D Programming Language 一书中提供的示例时遇到了一些麻烦。由于 int 和 ulong 类
如何创建一个不可变的类? 我的目标是创建一个实例始终不可变的类。现在我只是用不可变的方法和构造函数创建了一个“可变”类。我将其称为 mData,m 表示可变。然后我创建一个别名 alias immut
不久前我买了《The D Programming Language》。好书,很有教育意义。但是,我在尝试编译书中列出的语言功能时遇到了麻烦:扩展函数。 在这本书中,Andrei 写了任何可以像这样调用
我在 D http://www.digitalmars.com/d/2.0/lazy-evaluation.html 中找到了函数参数的惰性求值示例 我想知道如何在 D 中实现可能的无限数据结构,就像
这个问题在这里已经有了答案: 12 年前关闭。 Possible Duplicate: Could anyone explain these undefined behaviors (i = i++
当前是否可以跨模块扫描/查询/迭代具有某些属性的所有函数(或类)? 例如: source/packageA/something.d: @sillyWalk(10) void doSomething()
我是一名优秀的程序员,十分优秀!