us.ihmc.scs2.sessionVisualizer.jfx.Skybox Maven / Gradle / Ivy
package us.ihmc.scs2.sessionVisualizer.jfx;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.geometry.Point3D;
import javafx.geometry.Rectangle2D;
import javafx.scene.Camera;
import javafx.scene.Group;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.transform.Affine;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Transform;
import javafx.scene.transform.Translate;
import us.ihmc.log.LogTools;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class Skybox extends Group
{
public enum SkyboxTheme
{
CLOUDY_CROWN_MIDDAY, SCS1, OFF, CUSTOM
}
private final Translate translate = new Translate();
private final DoubleProperty size = new SimpleDoubleProperty(this, "size", 100000.0);
private final Affine backAffine = new Affine();
private final Affine frontAffine = new Affine();
private final Affine topAffine = new Affine();
private final Affine bottomAffine = new Affine();
private final Affine leftAffine = new Affine();
private final Affine rightAffine = new Affine();
private final ImageView topView = new ImageView();
private final ImageView bottomView = new ImageView();
private final ImageView leftView = new ImageView();
private final ImageView rightView = new ImageView();
private final ImageView backView = new ImageView();
private final ImageView frontView = new ImageView();
private final ImageView[] views = new ImageView[] {topView, leftView, backView, rightView, frontView, bottomView};
private Camera camera;
private ChangeListener cameraMotionListener = (observable, oldValue, newValue) ->
{
translate.setX(newValue.getTx());
translate.setY(newValue.getTy());
translate.setZ(newValue.getTz());
};
;
public Skybox()
{
for (ImageView view : views)
{
view.setSmooth(true);
view.setPreserveRatio(true);
view.fitWidthProperty().bind(size);
view.fitHeightProperty().bind(size);
}
updateTransforms(size.get());
backView.getTransforms().addAll(backAffine);
frontView.getTransforms().addAll(frontAffine);
topView.getTransforms().addAll(topAffine);
bottomView.getTransforms().addAll(bottomAffine);
leftView.getTransforms().addAll(leftAffine);
rightView.getTransforms().addAll(rightAffine);
getTransforms().add(translate);
getChildren().addAll(views);
setMouseTransparent(true);
}
private void updateTransforms(double size)
{
backAffine.setToIdentity();
backAffine.appendTranslation(-0.5 * size, -0.5 * size, 0.5 * size);
backAffine.appendRotation(+90.0, Point3D.ZERO, Rotate.Z_AXIS);
backAffine.appendRotation(-90.0, Point3D.ZERO, Rotate.X_AXIS);
frontAffine.setToIdentity();
frontAffine.appendTranslation(0.5 * size, 0.5 * size, 0.5 * size);
frontAffine.appendRotation(-90.0, Point3D.ZERO, Rotate.Z_AXIS);
frontAffine.appendRotation(-90.0, Point3D.ZERO, Rotate.X_AXIS);
topAffine.setToIdentity();
topAffine.appendTranslation(-0.5 * size, 0.5 * size, 0.5 * size);
topAffine.appendRotation(-90.0, Point3D.ZERO, Rotate.Z_AXIS);
bottomAffine.setToIdentity();
bottomAffine.appendTranslation(0.5 * size, 0.5 * size, -0.5 * size);
bottomAffine.appendRotation(180.0, Point3D.ZERO, Rotate.X_AXIS);
bottomAffine.appendRotation(+90.0, Point3D.ZERO, Rotate.Z_AXIS);
leftAffine.setToIdentity();
leftAffine.appendTranslation(-0.5 * size, 0.5 * size, 0.5 * size);
leftAffine.appendRotation(-90.0, Point3D.ZERO, Rotate.X_AXIS);
rightAffine.setToIdentity();
rightAffine.appendTranslation(0.5 * size, -0.5 * size, 0.5 * size);
rightAffine.appendRotation(180.0, Point3D.ZERO, Rotate.Z_AXIS);
rightAffine.appendRotation(-90.0, Point3D.ZERO, Rotate.X_AXIS);
}
public void setupSkybox(Image skybox)
{
if (skybox.getWidth() / 4 != skybox.getHeight() / 3)
throw new IllegalArgumentException("Unexpected size ratio");
int sideSize = (int) (skybox.getWidth() - skybox.getHeight());
int topX = sideSize;
int bottomX = sideSize;
int leftX = 0;
int frontX = 3 * sideSize;
int rightX = 2 * sideSize;
int backX = 1 * sideSize;
int topY = 0;
int bottomY = 2 * sideSize;
int leftY = sideSize;
int rightY = sideSize;
int frontY = sideSize;
int backY = sideSize;
backView.setImage(skybox);
frontView.setImage(skybox);
topView.setImage(skybox);
bottomView.setImage(skybox);
leftView.setImage(skybox);
rightView.setImage(skybox);
// FIXME Need to play with the viewports to get rid of the poor connection between side panels.
topView.setViewport(new Rectangle2D(topX, topY, sideSize, sideSize));
bottomView.setViewport(new Rectangle2D(bottomX, bottomY, sideSize, sideSize));
leftView.setViewport(new Rectangle2D(leftX, leftY, sideSize, sideSize));
backView.setViewport(new Rectangle2D(frontX, frontY, sideSize, sideSize));
rightView.setViewport(new Rectangle2D(rightX, rightY, sideSize, sideSize));
frontView.setViewport(new Rectangle2D(backX, backY, sideSize, sideSize));
}
public void setupSkybox(Image topImage, Image bottomImage, Image leftImage, Image rightImage, Image frontImage, Image backImage)
{
backView.setImage(backImage);
frontView.setImage(frontImage);
topView.setImage(topImage);
bottomView.setImage(bottomImage);
leftView.setImage(leftImage);
rightView.setImage(rightImage);
}
public boolean loadSkyboxFlexible(File file)
{
if (!file.exists())
{
LogTools.warn("File: " + file.getAbsolutePath() + " does not exist.");
return false;
}
if (file.isDirectory())
{
File[] imageFiles = new File[6];
for (String extension : new String[] {".png", ".jpg", ".bmp"})
{
if (findSkyboxImageFiles(file, extension, imageFiles, false))
return loadSkyboxFromImageFiles(imageFiles);
}
LogTools.warn("Could not find skybox images in (%s).".formatted(file.getAbsolutePath()));
return false;
}
else
{
return loadSkyboxFromSingleImageFile(file);
}
}
public boolean loadSkyboxFromSingleImageFile(File file)
{
if (!file.exists())
{
LogTools.warn("File: " + file.getAbsolutePath() + " does not exist.");
return false;
}
if (file.isDirectory())
{
LogTools.warn("Given file: " + file.getAbsolutePath() + " is a directory.");
return false;
}
Image image = loadImage(file);
if (image == null)
return false;
setupSkybox(image);
return true;
}
public boolean loadSkyboxFromDirectory(File directory, String fileExtension)
{
if (!directory.exists())
{
LogTools.warn("Directory: " + directory.getAbsolutePath() + " does not exist.");
return false;
}
if (!directory.isDirectory())
{
LogTools.warn("Given file: " + directory.getAbsolutePath() + " is not a directory.");
return false;
}
File[] imageFiles = new File[6];
if (!findSkyboxImageFiles(directory, fileExtension, imageFiles, true))
return false;
return loadSkyboxFromImageFiles(imageFiles);
}
public boolean loadSkyboxFromImageFiles(File[] imageFiles)
{
File topFile = imageFiles[0];
File bottomFile = imageFiles[1];
File leftFile = imageFiles[2];
File rightFile = imageFiles[3];
File frontFile = imageFiles[4];
File backFile = imageFiles[5];
return loadSkyboxFromImageFiles(topFile, bottomFile, leftFile, rightFile, frontFile, backFile);
}
public boolean loadSkyboxFromImageFiles(File topFile, File bottomFile, File leftFile, File rightFile, File frontFile, File backFile)
{
Image topImage = loadImage(topFile);
Image bottomImage = loadImage(bottomFile);
Image leftImage = loadImage(leftFile);
Image rightImage = loadImage(rightFile);
Image frontImage = loadImage(frontFile);
Image backImage = loadImage(backFile);
if (topImage == null || bottomImage == null || leftImage == null || rightImage == null || frontImage == null || backImage == null)
return false;
setupSkybox(topImage, bottomImage, leftImage, rightImage, frontImage, backImage);
return true;
}
public boolean findSkyboxImageFiles(File directory, String fileExtension, File[] imageFiles, boolean printWarnings)
{
String topName = "Up." + fileExtension;
String bottomName = "Down." + fileExtension;
String leftName = "Left." + fileExtension;
String rightName = "Right." + fileExtension;
String frontName = "Front." + fileExtension;
String backName = "Back." + fileExtension;
String[] filenames = {topName, bottomName, leftName, rightName, frontName, backName};
for (int i = 0; i < filenames.length; i++)
{
String filename = filenames[i];
File[] result = directory.listFiles(name -> name.getName().equalsIgnoreCase(filename));
if (result.length == 0)
{
if (printWarnings)
LogTools.warn("Could not find the file for (%s) image of the skybox.".formatted(filename));
return false;
}
imageFiles[i] = result[0];
}
return true;
}
public boolean loadSkyboxFromResource(String directoryPath, String fileExtension)
{
Image topImage = loadImage(SessionVisualizerIOTools.getSkyboxResource(directoryPath + "/Up." + fileExtension));
Image bottomImage = loadImage(SessionVisualizerIOTools.getSkyboxResource(directoryPath + "/Down." + fileExtension));
Image leftImage = loadImage(SessionVisualizerIOTools.getSkyboxResource(directoryPath + "/Left." + fileExtension));
Image rightImage = loadImage(SessionVisualizerIOTools.getSkyboxResource(directoryPath + "/Right." + fileExtension));
Image frontImage = loadImage(SessionVisualizerIOTools.getSkyboxResource(directoryPath + "/Front." + fileExtension));
Image backImage = loadImage(SessionVisualizerIOTools.getSkyboxResource(directoryPath + "/Back." + fileExtension));
if (topImage == null || bottomImage == null || leftImage == null || rightImage == null || frontImage == null || backImage == null)
return false;
setupSkybox(topImage, bottomImage, leftImage, rightImage, frontImage, backImage);
return true;
}
private static Image loadImage(File file)
{
if (file == null)
return null;
try
{
return loadImage(new FileInputStream(file));
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
return null;
}
private static Image loadImage(InputStream is)
{
if (is == null)
return null;
Image image = new Image(is);
try
{
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
return image;
}
public void setupCloudyCrown()
{
Image topImage = SessionVisualizerIOTools.SKYBOX_TOP_IMAGE;
Image bottomImage = SessionVisualizerIOTools.SKYBOX_BOTTOM_IMAGE;
Image leftImage = SessionVisualizerIOTools.SKYBOX_LEFT_IMAGE;
Image rightImage = SessionVisualizerIOTools.SKYBOX_RIGHT_IMAGE;
Image frontImage = SessionVisualizerIOTools.SKYBOX_FRONT_IMAGE;
Image backImage = SessionVisualizerIOTools.SKYBOX_BACK_IMAGE;
setupSkybox(topImage, bottomImage, leftImage, rightImage, frontImage, backImage);
}
public void setupSCS1Skybox()
{
Image topImage = SessionVisualizerIOTools.SCS1_SKYBOX_TOP_IMAGE;
Image bottomImage = SessionVisualizerIOTools.SCS1_SKYBOX_BOTTOM_IMAGE;
Image leftImage = SessionVisualizerIOTools.SCS1_SKYBOX_LEFT_IMAGE;
Image rightImage = SessionVisualizerIOTools.SCS1_SKYBOX_RIGHT_IMAGE;
Image frontImage = SessionVisualizerIOTools.SCS1_SKYBOX_FRONT_IMAGE;
Image backImage = SessionVisualizerIOTools.SCS1_SKYBOX_BACK_IMAGE;
setupSkybox(topImage, bottomImage, leftImage, rightImage, frontImage, backImage);
}
public void setupCamera(Camera camera)
{
if (this.camera != null)
this.camera.localToSceneTransformProperty().removeListener(cameraMotionListener);
this.camera = camera;
if (camera != null)
camera.localToSceneTransformProperty().addListener(cameraMotionListener);
}
public void setSize(double size)
{
this.size.set(size);
}
public double getSize()
{
return size.get();
}
public DoubleProperty sizeProperty()
{
return size;
}
public void dispose()
{
setupCamera(null);
for (ImageView view : views)
{
view.setImage(null);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy