3d - 如何在 JavaFX 8 中从 STL 创建 3D 形状?

标签 3d javafx-2 javafx-8

我有类 STLFile,它返回两个数组:一个包含法线坐标,另一个包含顶点坐标。所以现在我想在我的 JavaFX 应用程序中使用这些坐标创建 3d 形状。问题是如果没有纹理我该如何做到这一点。使用官方指南,我用坐标制作了 TriangleMesh 并将其添加到 MeshView 中。但遗憾的是,现场什么也没有出现。那么有人可以解释一下如何做到这一点吗,因为官方指南中的描述还不够充分?

最佳答案

您可以使用Interactive Mesh JavaFX STL Model Importer加载STL文件.

jewel

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

常见问题

I've tried to use your code but importing a different STL [did not work correctly] (that shows up in other viewers)

当我编写这个示例时,如果我记得的话,我通过反复试验调整了一些设置,例如对象比例、位置、照明相机定位等,直到得到我喜欢的渲染。

我怀疑我使用的设置是否通用,无法正常工作(或者甚至可能适用于所有型号)。

也许相机、对象定位、剪辑设置或灯光不适合您的模型。

或者可能只是由于功能有限而导致导入失败。

您可以尝试interactive mesh model viewer并查看它是否导入您的模型。如果不是,则导入商不支持您的模型。

您还可以看到FXyz lib它具有模型导入并尝试它们,尽管您可能需要转换为其他格式(例如 obj)才能使用它。

此外,某些模型功能,例如透明胶片和 flipped normals目前不支持,因此渲染失败也可能是由于 JavaFX 3D 实现而不是模型导入器或相机/场景设置造成的,在这种情况下,无论您使用什么导入器,您的模型都将无法正确渲染。

对 JavaFX 3D 的期望

一般来说,JavaFX 3D 的使用和开发并不像其他基于 Java 的 3D 库(例如 LWJGL)那样广泛。 ,因此不要期望像其他潜在的 3D 解决方案那样具有广泛的功能基础和可显示模型集。

不过,JavaFX 3D 中的基本 Phong 渲染、纹理、硬件加速、相机和照明确实适用于许多模型,并且如果您有适当的技能和时间,也可用于某些应用程序。

关于3d - 如何在 JavaFX 8 中从 STL 创建 3D 形状?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19462571/

相关文章:

c++ - 布雷森纳姆算法

JavaFX - 为整个应用程序设置默认 CSS 样式表

javafx - 自动调整滚动 Pane 的大小

java - 检测 JavaFX WebView 中的 URL 更改

java - 所有 fx 构建器都已弃用……除了 .adapter 中的一堆?

java - FXML 按钮导致空指针,硬编码按钮则不会

android - 实现室内地图

c++ - 3D 点投影到 2D XY 平面

python - 在激光 3D 扫描仪中查找结果 XYZ 点

包含 textField 的 JavaFX 2 对象从未被垃圾收集器清除