5

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

4

1 回答 1

7

您可以使用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 渲染、纹理、硬件加速、相机和照明确实适用于许多模型,并且如果您有适当的技能和时间,则可用于某些应用程序。

于 2013-10-19T09:05:30.143 回答