-
Bug
-
Resolution: Not an Issue
-
P4
-
None
-
jfx13
-
x86
-
os_x
ADDITIONAL SYSTEM INFORMATION :
macOs 10.14.6
A DESCRIPTION OF THE PROBLEM :
Dynamically generating a transparent, diffuse texture map for a PhongMaterial seems to work but, in the case of the example included here, the animated bouncing balls displayed inside the diffuse texture map leave behind curious trails that resemble motion blur. I would like to find a way to prevent this from happening.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run example program at: https://github.com/wholder/JavaFxDynamicTexture3D and notice the ghost trails left behind the animated bouncing balls.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I would not expect to see the ghosting.
ACTUAL -
The animated bouncing ball displayed in the dynamic texture leaves a shadowy trail behind it as it moves that resembles motion blur.
---------- BEGIN SOURCE ----------
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.*;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.*;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;
/*
* This program demonstrates how animated bouncing balls drawn into a dynamically-generated texture
* leave a shadowy trail behind as they move that resembles motion blur.
*/
public class JavaFxDynamicTexture3D extends Application {
private Canvas canvas;
private GraphicsContext gc;
private Group root = new Group();
private XGroup cube = new XGroup();
private double angleX, angleY;
private int ballX = 120, ballY = 70, deltaX = 7, deltaY = 10;
private static final int ballDiameter = 100;
private PhongMaterial material = new PhongMaterial();
public static void main (String[] args) {
launch(args);
}
public static class XGroup extends Group {
Rotate rx = new Rotate(0, Rotate.X_AXIS);
Rotate ry = new Rotate(0, Rotate.Y_AXIS);
XGroup () {
getTransforms().addAll(ry, rx);
}
void setRotateX (double x) {
rx.setAngle(x);
}
void setRotateY (double y) {
ry.setAngle(y);
}
}
private void updateBall () {
gc.setFill(new Color(0.4, 0.4, 0.4, .5));
gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
// If ball reaches left or right edge, reverse direction
if (ballX + deltaX < 0 || ballX + deltaX > canvas.getWidth() - ballDiameter) {
deltaX = -deltaX;
}
// If ball reaches top or bottom edge, reverse direction
if (ballY+ deltaY < 0 || ballY + deltaY > canvas.getHeight() - ballDiameter) {
deltaY = -deltaY;
}
ballX += deltaX;
ballY += deltaY;
gc.setFill(Color.BLUE);
gc.fillOval(ballX, ballY, ballDiameter, ballDiameter);
WritableImage texture = canvas.snapshot(null, null);
while (texture.getProgress() < 1) {
try {
// Note: never gets here, so the image is fully generated
Thread.sleep(1);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
material.setDiffuseMap(texture);
}
// Build Camera
private PerspectiveCamera getCamera () {
PerspectiveCamera camera = new PerspectiveCamera(true);
Group cameraXGroup = new Group();
cameraXGroup.getChildren().add(camera);
camera.setTranslateZ(-1000);
camera.setNearClip(0.1);
camera.setFarClip(10000.0);
camera.setFieldOfView(40);
return camera;
}
private SubScene get3dScene () {
// Build updatable texture
canvas = new Canvas(512, 512);
gc = canvas.getGraphicsContext2D();
material.setDiffuseColor(new Color(0.6, 0.6, 0.6, .6));
updateBall();
// Build foreground object using dynamic texture
Box box = new Box(350, 350, 350);
box.setMaterial(material);
// Note: must add inner box first for transparency to work
cube.getChildren().addAll(new Box(100, 100, 100), box);
root.getChildren().add(cube);
SubScene subScene = new SubScene(root, 512, 512, true, SceneAntialiasing.BALANCED);
subScene.setFill(new Color(0.8, 0.8, 0.8, 1.0));
subScene.setCamera(getCamera());
return subScene;
}
@Override
public void start (Stage stage) {
stage.setTitle("JavaFxDynamicTexture3D.java");
Scene scene = new Scene(new Group(get3dScene()));
stage.setScene(scene);
stage.show();
stage.setOnCloseRequest(e -> {
Platform.exit();
System.exit(0);
});
animate();
System.out.println("javafx.runtime.version: " + System.getProperty("java.version"));
}
public void animate () {
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(30), ev -> {
updateBall();
cube.setRotateX(angleX += 1);
cube.setRotateY(angleY += 1.3);
}));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
None found so far.
FREQUENCY : always
macOs 10.14.6
A DESCRIPTION OF THE PROBLEM :
Dynamically generating a transparent, diffuse texture map for a PhongMaterial seems to work but, in the case of the example included here, the animated bouncing balls displayed inside the diffuse texture map leave behind curious trails that resemble motion blur. I would like to find a way to prevent this from happening.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run example program at: https://github.com/wholder/JavaFxDynamicTexture3D and notice the ghost trails left behind the animated bouncing balls.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I would not expect to see the ghosting.
ACTUAL -
The animated bouncing ball displayed in the dynamic texture leaves a shadowy trail behind it as it moves that resembles motion blur.
---------- BEGIN SOURCE ----------
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.*;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.*;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;
/*
* This program demonstrates how animated bouncing balls drawn into a dynamically-generated texture
* leave a shadowy trail behind as they move that resembles motion blur.
*/
public class JavaFxDynamicTexture3D extends Application {
private Canvas canvas;
private GraphicsContext gc;
private Group root = new Group();
private XGroup cube = new XGroup();
private double angleX, angleY;
private int ballX = 120, ballY = 70, deltaX = 7, deltaY = 10;
private static final int ballDiameter = 100;
private PhongMaterial material = new PhongMaterial();
public static void main (String[] args) {
launch(args);
}
public static class XGroup extends Group {
Rotate rx = new Rotate(0, Rotate.X_AXIS);
Rotate ry = new Rotate(0, Rotate.Y_AXIS);
XGroup () {
getTransforms().addAll(ry, rx);
}
void setRotateX (double x) {
rx.setAngle(x);
}
void setRotateY (double y) {
ry.setAngle(y);
}
}
private void updateBall () {
gc.setFill(new Color(0.4, 0.4, 0.4, .5));
gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
// If ball reaches left or right edge, reverse direction
if (ballX + deltaX < 0 || ballX + deltaX > canvas.getWidth() - ballDiameter) {
deltaX = -deltaX;
}
// If ball reaches top or bottom edge, reverse direction
if (ballY+ deltaY < 0 || ballY + deltaY > canvas.getHeight() - ballDiameter) {
deltaY = -deltaY;
}
ballX += deltaX;
ballY += deltaY;
gc.setFill(Color.BLUE);
gc.fillOval(ballX, ballY, ballDiameter, ballDiameter);
WritableImage texture = canvas.snapshot(null, null);
while (texture.getProgress() < 1) {
try {
// Note: never gets here, so the image is fully generated
Thread.sleep(1);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
material.setDiffuseMap(texture);
}
// Build Camera
private PerspectiveCamera getCamera () {
PerspectiveCamera camera = new PerspectiveCamera(true);
Group cameraXGroup = new Group();
cameraXGroup.getChildren().add(camera);
camera.setTranslateZ(-1000);
camera.setNearClip(0.1);
camera.setFarClip(10000.0);
camera.setFieldOfView(40);
return camera;
}
private SubScene get3dScene () {
// Build updatable texture
canvas = new Canvas(512, 512);
gc = canvas.getGraphicsContext2D();
material.setDiffuseColor(new Color(0.6, 0.6, 0.6, .6));
updateBall();
// Build foreground object using dynamic texture
Box box = new Box(350, 350, 350);
box.setMaterial(material);
// Note: must add inner box first for transparency to work
cube.getChildren().addAll(new Box(100, 100, 100), box);
root.getChildren().add(cube);
SubScene subScene = new SubScene(root, 512, 512, true, SceneAntialiasing.BALANCED);
subScene.setFill(new Color(0.8, 0.8, 0.8, 1.0));
subScene.setCamera(getCamera());
return subScene;
}
@Override
public void start (Stage stage) {
stage.setTitle("JavaFxDynamicTexture3D.java");
Scene scene = new Scene(new Group(get3dScene()));
stage.setScene(scene);
stage.show();
stage.setOnCloseRequest(e -> {
Platform.exit();
System.exit(0);
});
animate();
System.out.println("javafx.runtime.version: " + System.getProperty("java.version"));
}
public void animate () {
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(30), ev -> {
updateBall();
cube.setRotateX(angleX += 1);
cube.setRotateY(angleY += 1.3);
}));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
None found so far.
FREQUENCY : always