1

I'm trying to get a few shapes to "play nicely" with each other. I have 2 boxes next to each other and a cylinder "on top" of one of the boxes. I put them in a SubScene with a camera that can zoom in and out with a scrolling operation and pan by dragging. Here is my MCVE:

import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Cylinder;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class MyApp extends Application {

    DoubleProperty transX = new SimpleDoubleProperty();
    DoubleProperty transY = new SimpleDoubleProperty();
    DoubleProperty transZ = new SimpleDoubleProperty();

    double startX, startY, curX, curY;

    @Override
    public void start(Stage stage) throws Exception {

        Box box1 = new Box(30, 30, 5);
        box1.setMaterial(new PhongMaterial(Color.RED));
        Box box2 = new Box(30, 30, 5);
        box2.setMaterial(new PhongMaterial(Color.GREEN));
        box2.setTranslateX(32);
        Cylinder cyn = new Cylinder(5, 15);

        Group root = new Group(box1, box2, cyn);
        root.getTransforms().addAll(new Translate(0, 0, 200),
                                    new Rotate(-60, Rotate.X_AXIS),
                                    new Rotate(-45, Rotate.Z_AXIS));

        SubScene subs = new SubScene(root, 0, 0, true, SceneAntialiasing.BALANCED);

        PerspectiveCamera camera = new PerspectiveCamera(true);
        camera.setFarClip(1000);
        camera.setNearClip(0);
        camera.translateZProperty().bind(transZ);
        camera.translateXProperty().bind(transX);
        camera.translateYProperty().bind(transY);
        subs.setCamera(camera);

        Pane pane = new Pane(subs);
        pane.setStyle("-fx-border-color: red;" + 
                      "-fx-border-width: 3;");
        subs.widthProperty().bind(pane.widthProperty());
        subs.heightProperty().bind(pane.heightProperty());

        pane.setOnScroll(e -> transZ.set(transZ.get() + e.getDeltaY() * 0.2));
        pane.setOnMousePressed(e -> {
            startX = curX = e.getX();
            startY = curY = e.getY();
        });
        pane.setOnMouseDragged(e -> {
            startX = curX;
            startY = curY;
            curX = e.getX();
            curY = e.getY();
            double deltaX = curX - startX;
            double deltaY = curY - startY;
            double deltaZ = deltaY * Math.sqrt(3);
            transX.set(transX.get() - deltaX);
            transY.set(transY.get() - deltaY);
            transZ.set(transZ.get() + deltaZ);
        });

        Scene scene = new Scene(pane, 500, 500);
        stage.setScene(scene);
        stage.sizeToScene();
        stage.show();
    }

    public static void main(String[] args) throws Exception {

        launch(args);
    }
}

I have 2 problems here:

  1. the Z order is specified by the order in which I put them in the group. I want the Z order to "Take care of itself". If I have shapes in space with specific coordinates and sizes and a camera at a specific position and angle I should be seeing a unique view without needing to specify the order. Here is a picture:

    enter image description here

    it looks like the green box is closer to the camera than the red box but my code doesn't imply this.

  2. the cylinder moves relative to the box when the camera pans. In the image I mark in blue lines the location of the cylinder on the red box:

    enter image description here

    and now i pan the camera and get

    enter image description here

    I want the relative location of the shapes to not change as I pan the camera.

  3. Edit: i removed this from the question and ask it in another one:
    the shapes are shown on top of the border:

    enter image description here

    i thought that because the shapes are in the pane then pane's border will be higher in the Z order. I want the border to appear on top.

Mark
  • 2,167
  • 4
  • 32
  • 64

2 Answers2

1

I guess it is actually a bug in JavaFX but at least it is easy to fix. Just don't set the near clipping pane of the camera to 0. Changing this line of your code to

camera.setNearClip(10);

will solve your first two problems.

mipa
  • 10,369
  • 2
  • 16
  • 35
  • Which of the 3 problems are you referring to? – Mark Oct 29 '16 at 09:34
  • Number 1 and also number 2, as far as I understand your problem. Number 3 is a different issue. – mipa Oct 29 '16 at 09:43
  • Side note: if you think it's a bug in JavaFX, please file an issue here: http://bugs.java.com/ – Puce Oct 29 '16 at 13:19
  • @Puce I personally am not sure any of the problems I mentioned are bugs. Do you think they should be submitted? – Mark Oct 29 '16 at 13:38
  • @mipa mentioned it's likely a bug. I'm not familiar with that part of the API. – Puce Oct 29 '16 at 14:08
  • Well, whether this is a bug in a strictly technical sense is probably arguable. But Oracle already mentions potential problems in the documentation. The JavaDoc for nearClipProperty says: "A value less than or equal to zero is treated as a very small positive number." So 0.0 is clearly an illegal value but setting it explicitly did neither result in an exception or error message nor was it corrected sufficiently. The default value of this property 0.1 would have worked by the way. So judge yourself whether you do consider this behaviour a bug or not. – mipa Oct 29 '16 at 15:36
  • mipa: yes i see now. you are right that the nearClip is causing this and it does seem like a bug. I set the near clip to `0.0001` and it caused visual artifacts all over. – Mark Oct 29 '16 at 16:09
  • I know. i'm waiting to see if someone else has a take on it and if oracle acknowledges the bug. – Mark Oct 30 '16 at 05:19
  • Apparently not a bug: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8169053. Don't know how it's not a bug because the docs say something else. – Mark Nov 17 '16 at 20:28
0

Try to enable the Group Depth test with the following line:

 setDepthTest(DepthTest.ENABLE);
Nathan Tuggy
  • 2,237
  • 27
  • 30
  • 38