Issue
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,
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.
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!
Solution
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.
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);
}
}
Answered By - trashgod
Answer Checked By - Pedro (JavaFixing Volunteer)