1

I'm writing a javafx image generator for .STL files. I'm using StlMeshImporter to import the STL file. However, when I import files in my javafx scene and try to take a snapshot, I get different result for each file because they are not center in the scene.

I would like to be able to scale it or center it, in the scene dynamically to take a snapshot. Is there a way to get the width and height of the object so I could set a scale factor, and offset automatically?

Here is my class:

public class STLImageGenerator extends Application {

private static final String MESH_FILENAME
        = "./9sk02_flex_r02.stl";

private static final int VIEWPORT_SIZE = 800;

private static final double MODEL_SCALE_FACTOR = 3;
private static final double MODEL_X_OFFSET = 0;
private static final double MODEL_Y_OFFSET = 0;
private static final double MODEL_Z_OFFSET =0 ;
//  private static final int VIEWPORT_SIZE = 4096;

private static final Color lightColor = Color.rgb(204, 204, 204);
private static final Color jewelColor = Color.rgb(0, 100, 204);

final static int CANVAS_WIDTH = 512;
final static int CANVAS_HEIGHT = 512;

private Group root;
private PointLight pointLight;
Canvas canvas = null;
PerspectiveCamera perspectiveCamera = null;

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();
    System.out.println("MESHVIEWS: " + meshViews.length);
    for (int i = 0; i < meshViews.length; i++) {
        System.out.println("meshViews[i].getLayoutX():"+meshViews[i].getLayoutX());

        meshViews[i].setScaleX(MODEL_SCALE_FACTOR);
        meshViews[i].setScaleY(MODEL_SCALE_FACTOR);
        meshViews[i].setScaleZ(MODEL_SCALE_FACTOR);
        meshViews[i].setTranslateX((VIEWPORT_SIZE / 2) + MODEL_X_OFFSET-MODEL_SCALE_FACTOR);
        meshViews[i].setTranslateY((VIEWPORT_SIZE / 2) + MODEL_Y_OFFSET-MODEL_SCALE_FACTOR);
        meshViews[i].setTranslateZ((VIEWPORT_SIZE / 2) + MODEL_Z_OFFSET);



        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);
    //root.setAutoSizeChildren(true);


    return root;
}

private PerspectiveCamera addCamera(Scene scene) {
    perspectiveCamera = new PerspectiveCamera();
    System.out.println("Near Clip: " + perspectiveCamera.getNearClip());
    System.out.println("Far Clip:  " + perspectiveCamera.getFarClip());
    System.out.println("FOV:       " + perspectiveCamera.getFieldOfView());
    perspectiveCamera.setFieldOfView(5);

    scene.setCamera(perspectiveCamera);
    return perspectiveCamera;
}

@Override
public void start(Stage primaryStage) {
    //canvas = new Canvas(VIEWPORT_SIZE, VIEWPORT_SIZE);
    Group group = buildScene();


    Scene scene = new Scene(group, VIEWPORT_SIZE, VIEWPORT_SIZE, true, SceneAntialiasing.BALANCED);
    scene.setFill(Color.rgb(255, 255, 255));
    group.setAutoSizeChildren(true);

    addCamera(scene);
    //root.getChildren().add(canvas);
    primaryStage.setMaxHeight(CANVAS_HEIGHT);
    primaryStage.setMaxWidth(CANVAS_WIDTH);

    String fname = MESH_FILENAME.substring(0, MESH_FILENAME.length() - 3) + "png";
    File file = new File(fname);



    primaryStage.setTitle("Jewel Viewer");
    primaryStage.setScene(scene);

    primaryStage.show();

    try {
        SnapshotParameters s = new SnapshotParameters();
       // s.setCamera(perspectiveCamera);
        // s.setViewport(Rectangle2D.EMPTY);
        WritableImage wim = new WritableImage(1024, 1024);
        scene.snapshot(wim);
        // WritableImage writableImage = root.snapshot(new SnapshotParameters(), null);
        RenderedImage renderedImage = SwingFXUtils.fromFXImage(wim, null);
        ImageIO.write(renderedImage, "png", file);
    } catch (Exception e) {
        e.printStackTrace();
    }
}


public static void main(String[] args) {
    System.setProperty("prism.dirtyopts", "false");
    Platform.setImplicitExit(false);
    launch(args);

}
  • you could try centering your meshview by putting it in a stackpane or something, see this question https://stackoverflow.com/questions/23576044/how-to-center-a-node-within-a-pane-javafx – MMAdams Oct 17 '17 at 17:58
  • It works to center the par but I need the size of the object to set the right scale ratio otherwise it might show an object of 10x10px in a 512x512x square – Alex Hamelin Oct 17 '17 at 20:18

0 Answers0