How to create 3d shape from STL in JavaFX 8?

2019-01-28 08:11发布

问题:

I have class STLFile which returns two arrays: one with coordinates of normals and another one with vertices coords. So now I want to create 3d shape with these coordinates in my JavaFX app. The problem is that how can I do this without textures. Using the official guide I've made TriangleMesh with coordinates and add it to MeshView. But unfortunately nothing appeared in the scene. So can anybody explain me how to do this, because the description in official guide couldn't be called sufficient?

回答1:

You can load STL files using the Interactive Mesh JavaFX STL Model Importer.

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 source model information

-- 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