The answer is yes, you can create a photosphere in JavaFX.
As for the how, there's an easy solution based on a sphere from the 3D API, but we can implement an improved solution, with a custom mesh.
Let's start by using a regular sphere. We just need a 360o image, like this one.
As we want to see from the inside of the sphere, we have to flip the image horizontally, and add it to the sphere material's diffusion map.
Then we just need to set up a camera in the very center of the sphere, add some lights and start spinning.
@Override
public void start(Stage primaryStage) {
PerspectiveCamera camera = new PerspectiveCamera(true);
camera.setNearClip(0.1);
camera.setFarClip(10000.0);
camera.setFieldOfView(90);
Sphere sphere = new Sphere(1000);
sphere.setCullFace(CullFace.NONE);
PhongMaterial material = new PhongMaterial();
/*
"SonyCenter 360panorama" by Fran?ois Reincke - Own work. Made using autostitch (www.autostitch.net)..
Licensed under CC BY-SA 3.0 via Wikimedia Commons - http://commons.wikimedia.org/wiki/File:SonyCenter_360panorama.jpg#mediaviewer/File:SonyCenter_360panorama.jpg
*/
material.setDiffuseMap(new Image(getClass().getResource("SonyCenter_360panorama_reversed.jpg").toExternalForm()));
sphere.setMaterial(material);
Group root3D = new Group(camera,sphere,new AmbientLight(Color.WHITE));
Scene scene = new Scene(root3D, 800, 600, true, SceneAntialiasing.BALANCED);
scene.setCamera(camera);
primaryStage.setTitle("PhotoSphere in JavaFX3D");
primaryStage.setScene(scene);
primaryStage.show();
final Timeline rotateTimeline = new Timeline();
rotateTimeline.setCycleCount(Timeline.INDEFINITE);
camera.setRotationAxis(Rotate.Y_AXIS);
final KeyValue kv1 = new KeyValue(camera.rotateProperty(), 360);
final KeyFrame kf1 = new KeyFrame(Duration.millis(30000), kv1);
rotateTimeline.getKeyFrames().addAll(kf1);
rotateTimeline.play();
}
Now you will want to add some controls to the camera (so you can navigate). You will discover that this solution has a weak spot at the top and bottom of the sphere, due to the fact that all the top or bottom side of the image is located in one point:
You can find a solution to this problem at the F(X)yz library here. A custom mesh called SegmentedSphereMesh
allows you to crop the extremes of the sphere, so the image can keep its aspect ratio without being stretched.
If you clone and build the repo, add FXyz.jar to your project, and just replace Sphere
in the previous snippet with this:
SegmentedSphereMesh sphere = new SegmentedSphereMesh(100,0,26,1000);
sphere.setCullFace(CullFace.NONE);
sphere.setTextureModeImage(getClass().getResource("SonyCenter_360panorama_reversed.jpg").toExternalForm());
In the same library you can find SkyBox
, based on a cube and one square image on each of its faces. Also check the advanced camera options.
Finally, note that this and more 3D advanced shapes are now demonstrated in the F(X)yz-Sampler application.