1

I have the following piece of code that displays a sphere inside a box.

package com.example.animation3d;

import javafx.application.Application;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Sphere;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class Camera3D extends Application {


    public static final int WIDTH = 1280;
    public static final int HEIGHT = 720;
    public static final int ROTATE_SENS = 20;
    public static final int ZOOM_SENS = 20;

    public Rotate yRotate;
    public double cursorX;

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

        Box box = new Box(5, 10, 5);
        PhongMaterial material = new PhongMaterial();
        material.setDiffuseColor(Color.web("rgba(34, 139, 34, 0.5)"));
        box.setMaterial(material);

        Sphere sphere = new Sphere(0.5);
        sphere.setMaterial(new PhongMaterial(Color.RED));

        Group group = new Group();
        group.getChildren().addAll(box, sphere);

        Translate pivot = new Translate();
        yRotate = new Rotate(0, Rotate.Y_AXIS);

        // Create and position camera
        PerspectiveCamera camera = new PerspectiveCamera(true);
        camera.getTransforms().addAll (
                pivot,
                yRotate,
                new Rotate(-20, Rotate.X_AXIS),
                new Translate(0, 0, -50)
        );


        Scene scene = new Scene(group, WIDTH, HEIGHT);
        scene.setFill(Color.ALICEBLUE);
        scene.setCamera(camera);

        stage.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
            switch (event.getCode()) {
                case W:
                    camera.translateZProperty().set(camera.getTranslateZ() + 10);
                    break;
                case S:
                    camera.translateZProperty().set(camera.getTranslateZ() - 10);
                    break;
                case A:
                    yRotate.angleProperty().set(yRotate.getAngle() + 10);
                    break;
                case D:
                    yRotate.angleProperty().set(yRotate.getAngle() - 10);
                    break;
                case UP:
                    sphere.setTranslateY(sphere.getTranslateY() - 1);
                    break;
                case DOWN:
                    sphere.setTranslateY(sphere.getTranslateY() + 1);
                    break;
                case LEFT:
                    sphere.setTranslateX(sphere.getTranslateX() - 1);
                    break;
                case RIGHT:
                    sphere.setTranslateX(sphere.getTranslateX() + 1);
                    break;
            }
        });

        stage.setTitle("Camera");
        stage.setScene(scene);
        stage.show();
    }
}

However, when I run the program,

  1. Translucent effect gradually lost as I move the sphere. I have added a material to the box to make it look translucent. However, when I move the sphere with arrow keys, the box seems to become opaque again, which I do not want.

  2. Whitish background surrounding the sphere as I move it. When the sphere is moved with arrow keys, a whitish colouring surrounds the sphere and trails behind it, which I do not want.

How do these problems arise, and how can they be fixed? Thanks in advance!

Skyzx
  • 13
  • 2

1 Answers1

2

I was able to reproduce your finding, although it appeared to be a trail of altered transparency following the sphere as it moved; the trail was comprised of rectangles, each approximating the sphere's boundary.

With reference to this answer, I changed the order in which the objects were added to the group:

group.getChildren().addAll(sphere, box);

Empirically, like you, I noticed that the trails disappeared if I rotated the box slightly between each move of the sphere:

yRotate.angleProperty().set(yRotate.getAngle() + 0.1);
yRotate.angleProperty().set(yRotate.getAngle() - 0.1);

A variation of your example to work around the problem is shown below. I'm guessing that it forces a depth recalculation, as suggested here, but I'd welcome any addition insight.

image

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Sphere;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class Camera3D extends Application {

    public static final int WIDTH = 500;
    public static final int HEIGHT = 500;

    public Rotate yRotate;

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

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

        var box = new Box(5, 10, 5);
        var material = new PhongMaterial(Color.web("#20902080"));
        box.setMaterial(material);

        var sphere = new Sphere(3);
        sphere.setMaterial(new PhongMaterial(Color.RED));

        Group group = new Group();
        group.getChildren().addAll(sphere, box);

        Translate pivot = new Translate();
        yRotate = new Rotate(0, Rotate.Y_AXIS);

        // Create and position camera
        PerspectiveCamera camera = new PerspectiveCamera(true);
        camera.getTransforms().addAll(
            pivot,
            yRotate,
            new Rotate(-20, Rotate.X_AXIS),
            new Translate(0, 0, -30)
        );

        Scene scene = new Scene(group, WIDTH, HEIGHT);
        scene.setFill(Color.ALICEBLUE);
        scene.setCamera(camera);

        stage.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
            switch (event.getCode()) {
                case W ->
                    camera.translateZProperty().set(camera.getTranslateZ() + 10);
                case S ->
                    camera.translateZProperty().set(camera.getTranslateZ() - 10);
                case A ->
                    yRotate.angleProperty().set(yRotate.getAngle() + 10);
                case D ->
                    yRotate.angleProperty().set(yRotate.getAngle() - 10);
                case UP -> {
                    sphere.setTranslateY(sphere.getTranslateY() - 1);
                    adjust();
                }
                case DOWN -> {
                    sphere.setTranslateY(sphere.getTranslateY() + 1);
                    adjust();
                }
                case LEFT -> {
                    sphere.setTranslateX(sphere.getTranslateX() - 1);
                    adjust();
                }
                case RIGHT -> {
                    sphere.setTranslateX(sphere.getTranslateX() + 1);
                    adjust();
                }
            }
        });
        stage.setTitle("Camera");
        stage.setScene(scene);
        stage.show();
    }

    private void adjust() {
        yRotate.angleProperty().set(yRotate.getAngle() + 0.1);
        yRotate.angleProperty().set(yRotate.getAngle() - 0.1);
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045