我有返回两个数组的类 STLFile:一个带有法线坐标,另一个带有顶点坐标。所以现在我想在我的 JavaFX 应用程序中使用这些坐标创建 3d 形状。问题是我怎么能在没有纹理的情况下做到这一点。使用官方指南,我制作了带坐标的 TriangleMesh 并将其添加到 MeshView。但不幸的是,现场什么也没出现。那么任何人都可以解释我如何做到这一点,因为官方指南中的描述还不够?
1 回答
您可以使用Interactive Mesh JavaFX STL Model Importer加载 STL 文件。
JewelViewer.java
import com.interactivemesh.jfx.importer.stl.StlMeshImporter;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Mesh;
import javafx.scene.shape.MeshView;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import java.io.File;
public class JewelViewer extends Application {
private static final String MESH_FILENAME =
"/Users/lilyshard/Downloads/Perfect Diamond/Perfect Diamond.STL";
private static final double MODEL_SCALE_FACTOR = 400;
private static final double MODEL_X_OFFSET = 0; // standard
private static final double MODEL_Y_OFFSET = 0; // standard
private static final int VIEWPORT_SIZE = 800;
private static final Color lightColor = Color.rgb(244, 255, 250);
private static final Color jewelColor = Color.rgb(0, 190, 222);
private Group root;
private PointLight pointLight;
static MeshView[] loadMeshViews() {
File file = new File(MESH_FILENAME);
StlMeshImporter importer = new StlMeshImporter();
importer.read(file);
Mesh mesh = importer.getImport();
return new MeshView[] { new MeshView(mesh) };
}
private Group buildScene() {
MeshView[] meshViews = loadMeshViews();
for (int i = 0; i < meshViews.length; i++) {
meshViews[i].setTranslateX(VIEWPORT_SIZE / 2 + MODEL_X_OFFSET);
meshViews[i].setTranslateY(VIEWPORT_SIZE / 2 + MODEL_Y_OFFSET);
meshViews[i].setTranslateZ(VIEWPORT_SIZE / 2);
meshViews[i].setScaleX(MODEL_SCALE_FACTOR);
meshViews[i].setScaleY(MODEL_SCALE_FACTOR);
meshViews[i].setScaleZ(MODEL_SCALE_FACTOR);
PhongMaterial sample = new PhongMaterial(jewelColor);
sample.setSpecularColor(lightColor);
sample.setSpecularPower(16);
meshViews[i].setMaterial(sample);
meshViews[i].getTransforms().setAll(new Rotate(38, Rotate.Z_AXIS), new Rotate(20, Rotate.X_AXIS));
}
pointLight = new PointLight(lightColor);
pointLight.setTranslateX(VIEWPORT_SIZE*3/4);
pointLight.setTranslateY(VIEWPORT_SIZE/2);
pointLight.setTranslateZ(VIEWPORT_SIZE/2);
PointLight pointLight2 = new PointLight(lightColor);
pointLight2.setTranslateX(VIEWPORT_SIZE*1/4);
pointLight2.setTranslateY(VIEWPORT_SIZE*3/4);
pointLight2.setTranslateZ(VIEWPORT_SIZE*3/4);
PointLight pointLight3 = new PointLight(lightColor);
pointLight3.setTranslateX(VIEWPORT_SIZE*5/8);
pointLight3.setTranslateY(VIEWPORT_SIZE/2);
pointLight3.setTranslateZ(0);
Color ambientColor = Color.rgb(80, 80, 80, 0);
AmbientLight ambient = new AmbientLight(ambientColor);
root = new Group(meshViews);
root.getChildren().add(pointLight);
root.getChildren().add(pointLight2);
root.getChildren().add(pointLight3);
root.getChildren().add(ambient);
return root;
}
private PerspectiveCamera addCamera(Scene scene) {
PerspectiveCamera perspectiveCamera = new PerspectiveCamera();
System.out.println("Near Clip: " + perspectiveCamera.getNearClip());
System.out.println("Far Clip: " + perspectiveCamera.getFarClip());
System.out.println("FOV: " + perspectiveCamera.getFieldOfView());
scene.setCamera(perspectiveCamera);
return perspectiveCamera;
}
@Override
public void start(Stage primaryStage) {
Group group = buildScene();
group.setScaleX(2);
group.setScaleY(2);
group.setScaleZ(2);
group.setTranslateX(50);
group.setTranslateY(50);
Scene scene = new Scene(group, VIEWPORT_SIZE, VIEWPORT_SIZE, true);
scene.setFill(Color.rgb(10, 10, 40));
addCamera(scene);
primaryStage.setTitle("Jewel Viewer");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
System.setProperty("prism.dirtyopts", "false");
launch(args);
}
}
STL源模型信息
-- Model information --
Model Name : Perfect Diamond
Author : Scott Allen
Publisher : mtgtopdeck
You can view this model here :
http://www.3dvia.com/content/024BE6380A1C2E00
More models about this author :
http://www.3dvia.com/mtgtopdeck
-- Attached license --
A license is attached to the Perfect Diamond model and all related media.
You must agree with this licence before using the enclosed media.
License : Attribution-NonCommercial 2.5
Detailed license : http://creativecommons.org/licenses/by-nc/2.5/
The licenses used by 3dvia are based on Creative Commons Licenses.
More info: http://creativecommons.org/about/licenses/meet-the-licenses
常问问题
我尝试使用您的代码,但导入了不同的 STL [无法正常工作](显示在其他查看器中)
如果我记得,当我写这个例子时,我通过反复试验调整了一些设置,如对象比例、位置、照明相机定位等,直到我得到我喜欢的渲染。
我怀疑我使用的设置是否能正常工作(或者甚至可能对所有模型都没有)。
可能相机、对象定位、剪辑设置或照明不适合您的模型。
或者,由于功能有限,它可能只是导入失败。
您可以尝试交互式网格模型查看器,看看它是否会导入您的模型。如果不是,那么进口商不支持您的模型。
您还可以查看具有模型导入的FXyz 库并尝试它们,尽管您可能需要转换为另一种格式(例如 obj)才能使用它。
此外,当前不支持某些模型功能,例如透明度和翻转法线,因此无法渲染也可能是由于 JavaFX 3D 实现而不是模型导入器或相机/场景设置,在这种情况下您的模型将无法渲染无论您使用什么进口商,都正确。
对 JavaFX 3D 的期望
一般来说,JavaFX 3D 没有像LWJGL等其他基于 Java 的 3D 库那样广泛使用和积极开发,因此不要期望像其他潜在的 3D 解决方案那样广泛的功能基础和可显示的模型集。
尽管如此,JavaFX 3D 中的基本 Phong 渲染、纹理、硬件加速、相机和照明确实适用于许多模型,并且如果您有适当的技能和时间,则可用于某些应用程序。