I'm trying to display various Text objects inside a 3D scene
The problem is that when i zoom close to the text it looks very blurry.
Here's a screenshot from my app
Question: how can i improve the graphic quality of the text on the screen?
I've tried setting cache as in JavaFX 2D text with background in 3D scene because it seemed to improve graphics quality on the answer screenshots but it did not help me in my case.
Below is a compileable example stripped down form my app. It just create some random Text objects with positions and provides you a way to move around. Notice how the texts displays horribly when you zoom close.
You F10 and F11 to zoom in and out and mouse drag to move the camera.
package timelinefx;
import static javafx.application.Application.launch;
import java.util.Random;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
import javafx.scene.CacheHint;
public class TextInto3DScene extends Application {
static Stage stage;
static Scene scene;
static Group root;
static Group subSceneRoot;
static PerspectiveCamera camera;
static SubScene subScene;
static boolean cached = true;
static int width = 1000;
static int height = width;
@Override
public void start(Stage primaryStage) throws Exception {
createWindow();
}
protected static void createWindow(){
stage = new Stage();
root = new Group();
root.setCache(cached);
root.setCacheHint(CacheHint.QUALITY); //doesn't work
scene = new Scene(root, 1500, 700, true, SceneAntialiasing.BALANCED);
//Initialize the camera
camera = new PerspectiveCamera(true);
camera.setNearClip(0.1);
camera.setFarClip(5000);
camera.setTranslateZ(-200);
//creates the SubScene and add the camera to it!
subSceneRoot = new Group();
subSceneRoot.setCache(cached); //doesn't work
subScene = new SubScene(subSceneRoot, 1800, 700, true, SceneAntialiasing.BALANCED);
subScene.setCache(cached);
root.getChildren().add(subScene);
subScene.setFill(Color.WHITE);
subScene.setCamera(camera);
//Create random texts
for( int i = 0;i<=100;++i){
Text text = new Text(Math.random()* width-width/2, Math.random()*height-height/2, randomText() );
text.setFill( Color.BLACK );
text.setTranslateZ( Math.random()*750 );
text.setCache(cached); //doesn't work
text.setCacheHint(CacheHint.QUALITY);
subSceneRoot.getChildren().add(text);
}
stage.setScene(scene);
setEventHandlers();
stage.show();
}
static void setEventHandlers() {
scene.setOnMouseDragged((event) -> {
//camera.setRotate(event.getX());
double translateX = (event.getSceneX() - 0) / stage.getWidth();
translateX = translateX * width - width/2;
double translateY = (event.getSceneY() - 0) / stage.getHeight();
translateY = translateY * height - height/2;
double tz;
if(!camera.getTransforms().isEmpty()){
tz = camera.getTransforms().get(0).getTz();
} else {
tz = camera.getTranslateZ();
}
camera.getTransforms().clear();
camera.getTransforms().addAll( new Translate(translateX, translateY, tz) );
});
//KEY PRESSED
scene.setOnKeyPressed((event) -> {
switch (event.getCode().toString()) {
case "F10":
double amt = event.isControlDown() ? 100 : 30;
camera.setTranslateZ(camera.getTranslateZ() + amt);
break;
case "F11":
amt = event.isControlDown() ? -100 : -30;
camera.setTranslateZ(camera.getTranslateZ() + amt);
break;
}
});
}
static String randomText(){
String out = "";
Random r = new Random();
for(int i = 0;i<=10;++i){
char c = (char) (r.nextInt(26) + 'a');
out += c;
}
return out;
}
public static void main(String[] args) {
launch(args);
}
}