2

Many 3d programs uses an outline to hint the user when 3d object is selected .

is there a way to mimic that behavior in javafx ?

Giovanni Contreras
  • 2,345
  • 1
  • 13
  • 22

1 Answers1

6

Outline with a scaled 3d object with front faces culled

culledfaces javafx

In this aproach . A 3d object is instansiated with the class type of PickResult node when mouse is entered on a Group node , that object has the same sizes of the picked one and the same translations ( in this case is just x axis ) but is slightly scaled (1.1). So , the 3d object is bigger and it is in the same spot but is not overlaping the shape3d underneath beacuse any face looking toward the camera is culled with Culface.FRONT enum in Shape3d.setCullFace() . Finally , when mouse exits pickresult node the 3d object is removed from group's children allowing next iterations . This is a single class functional javafx app you can try

App.java

public class App extends Application {

    private Shape3D outLine;

    @Override
    public void start(Stage stage) {
        Shape3D sphere = new Sphere(0.45);
        PhongMaterial sMaterial = new PhongMaterial(Color.CORAL);
        sphere.setMaterial(sMaterial);
        sphere.setTranslateX(-1.1);
        Shape3D box = new Box(0.9, 0.9, 0.9);
        box.setTranslateX(1.1);
        box.setMaterial(new PhongMaterial(Color.PALEGREEN));
        Shape3D cylinder = new Cylinder(0.45, 0.8);
        cylinder.setMaterial(new PhongMaterial(Color.PALEVIOLETRED));
        PerspectiveCamera camera = new PerspectiveCamera(true);
        camera.setTranslateZ(-5.5);

        Group group3d = new Group(camera, box, sphere, cylinder);

        Scene scene = new Scene(group3d, 640, 480, true, SceneAntialiasing.BALANCED);
        group3d.setOnMouseExited((t) -> {
            group3d.getChildren().remove(outLine);
        });
        group3d.setOnMouseEntered((t) -> {

            PickResult pickResult = t.getPickResult();
            Node intersectedNode = pickResult.getIntersectedNode();

            if (intersectedNode instanceof Sphere) {

                outLine = new Sphere(((Sphere) intersectedNode).getRadius());
                outLine.setTranslateX(intersectedNode.getTranslateX());
                group3d.getChildren().add(outLine);

                outLine.setCullFace(CullFace.FRONT);
                outLine.setScaleX(1.1);
                outLine.setScaleY(1.1);
                outLine.setScaleZ(1.1);

            }
            if (intersectedNode instanceof Cylinder) {
                Cylinder c = (Cylinder) intersectedNode;
                outLine = new Cylinder(c.getRadius(), c.getHeight(), c.getDivisions());
                outLine.setTranslateX(c.getTranslateX());
                group3d.getChildren().add(outLine);

                outLine.setCullFace(CullFace.FRONT);
                outLine.setScaleX(1.1);
                outLine.setScaleY(1.1);
                outLine.setScaleZ(1.1);

            }
            if (intersectedNode instanceof Box) {
                Box b = (Box) intersectedNode;
                outLine = new Box(b.getWidth(), b.getHeight(), b.getDepth());
                outLine.setTranslateX(b.getTranslateX());
                group3d.getChildren().add(outLine);

                outLine.setCullFace(CullFace.FRONT);
                outLine.setScaleX(1.1);
                outLine.setScaleY(1.1);
                outLine.setScaleZ(1.1);

            }
        });
        scene.setCamera(camera);
        scene.setFill(Color.AQUA);
        stage.setScene(scene);
        stage.setTitle("outline javafx");
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

Note Shape3d objects scale from its very center . If this method will be implemented with custom MeshView objects , those meshes needs to scale at its center as well

Giovanni Contreras
  • 2,345
  • 1
  • 13
  • 22
  • Is adding the `camera` to the two groups essential? Sorry to impose, but I hadn't seen this usage before. Thanks for any guidance. – trashgod May 22 '22 at 18:38
  • 1
    No it isn't in this case .I ussually add a camera in a separate group for moving camera implementation . my bad . is not nescesary in this case – Giovanni Contreras May 22 '22 at 18:46