Skip to content

Instantly share code, notes, and snippets.

@Roland09
Last active August 29, 2015 14:15
Show Gist options
  • Save Roland09/72325b03bfc80b138882 to your computer and use it in GitHub Desktop.
Save Roland09/72325b03bfc80b138882 to your computer and use it in GitHub Desktop.
Image wall like it was demonstrated at the JavaFX 2.0 presentation. Navigable via left, right and middle mouse button. You can replace the image nodes with WebView nodes and stream videos for every node.
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
// math from: http://paulbourke.net/geometry/transformationprojection/
// 3d code from http://docs.oracle.com/javafx/8/3d_graphics/jfxpub-3d_graphics.htm
public class NavigableVideoWall extends Application {
Group root = new Group();
final Xform axisGroup = new Xform();
final Xform world = new Xform();
final PerspectiveCamera camera = new PerspectiveCamera(true);
final Xform cameraXform = new Xform();
final Xform cameraXform2 = new Xform();
final Xform cameraXform3 = new Xform();
private static final double CAMERA_INITIAL_DISTANCE = -450;
private static final double CAMERA_INITIAL_X_ANGLE = -6.0;
private static final double CAMERA_INITIAL_Y_ANGLE = 320.0;
private static final double CAMERA_NEAR_CLIP = 0.1;
private static final double CAMERA_FAR_CLIP = 10000.0;
double mousePosX;
double mousePosY;
double mouseOldX;
double mouseOldY;
double mouseDeltaX;
double mouseDeltaY;
private static final double CONTROL_MULTIPLIER = 0.1;
private static final double SHIFT_MULTIPLIER = 10.0;
private static final double MOUSE_SPEED = 1.0;
private static final double ROTATION_SPEED = 0.4;
private static final double TRACK_SPEED = 0.3;
public NavigableVideoWall(){
}
public static void main(String[] args) {
launch(args);
}
// Image image = new Image( getClass().getResource("tiger.jpg").toExternalForm());
Image image = new Image("http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/320px-Siberischer_tiger_de_edit02.jpg");
private ImageView createImageView() {
ImageView c = new ImageView( image);
c.setFitWidth(220);
c.setFitWidth(120);
c.setPreserveRatio(true);
return c;
}
@Override
public void start(Stage primaryStage) {
root.getChildren().add(world);
// root.setDepthTest(DepthTest.ENABLE);
buildCamera();
ImageView c;
double r = 1300;
double yOffset = 80;
// full ring
for( double angle1=-Math.PI; angle1 <= Math.PI; angle1+=0.1)
// only a wall
// for( double angle1=Math.toRadians(angleOffsetDeg); angle1 <= Math.toRadians(90-angleOffsetDeg); angle1+=0.1)
{
double angle2 = Math.PI;
for( int i=-3; i <= 3; i++)
{
double x = r * Math.sin(angle1) * Math.cos(angle2);
double y = r * Math.sin(angle1) * Math.sin(angle2);
double z = r * Math.cos(angle1);
c = createImageView();
c.setTranslateX(x);
c.setTranslateY(yOffset * i);
c.setTranslateZ(z);
Rotate rx = new Rotate();
rx.setAxis(Rotate.Y_AXIS);
rx.setAngle(Math.toDegrees( -angle1));
c.getTransforms().addAll(rx);
world.getChildren().add( c);
}
}
Scene scene = new Scene(root, 1600, 900, Color.BLACK);
handleKeyboard(scene, world);
handleMouse(scene, world);
primaryStage.setScene( scene);
primaryStage.show();
scene.setCamera(camera);
}
private void buildCamera() {
root.getChildren().add(cameraXform);
cameraXform.getChildren().add(cameraXform2);
cameraXform2.getChildren().add(cameraXform3);
cameraXform3.getChildren().add(camera);
cameraXform3.setRotateZ(0.0);
camera.setNearClip(CAMERA_NEAR_CLIP);
camera.setFarClip(CAMERA_FAR_CLIP);
camera.setTranslateZ(CAMERA_INITIAL_DISTANCE);
cameraXform.ry.setAngle(CAMERA_INITIAL_Y_ANGLE);
cameraXform.rx.setAngle(CAMERA_INITIAL_X_ANGLE);
}
private void handleMouse(Scene scene, final Node root) {
scene.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent me) {
mousePosX = me.getSceneX();
mousePosY = me.getSceneY();
mouseOldX = me.getSceneX();
mouseOldY = me.getSceneY();
}
});
scene.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent me) {
mouseOldX = mousePosX;
mouseOldY = mousePosY;
mousePosX = me.getSceneX();
mousePosY = me.getSceneY();
mouseDeltaX = (mousePosX - mouseOldX);
mouseDeltaY = (mousePosY - mouseOldY);
double modifier = 1.0;
if (me.isControlDown()) {
modifier = CONTROL_MULTIPLIER;
}
if (me.isShiftDown()) {
modifier = SHIFT_MULTIPLIER;
}
if (me.isPrimaryButtonDown()) {
cameraXform.ry.setAngle(cameraXform.ry.getAngle() - mouseDeltaX*MOUSE_SPEED*modifier*ROTATION_SPEED);
cameraXform.rx.setAngle(cameraXform.rx.getAngle() + mouseDeltaY*MOUSE_SPEED*modifier*ROTATION_SPEED);
}
else if (me.isSecondaryButtonDown()) {
double z = camera.getTranslateZ();
double newZ = z + mouseDeltaX*MOUSE_SPEED*modifier;
camera.setTranslateZ(newZ);
}
else if (me.isMiddleButtonDown()) {
cameraXform2.t.setX(cameraXform2.t.getX() + mouseDeltaX*MOUSE_SPEED*modifier*TRACK_SPEED);
cameraXform2.t.setY(cameraXform2.t.getY() + mouseDeltaY*MOUSE_SPEED*modifier*TRACK_SPEED);
}
}
});
}
private void handleKeyboard(Scene scene, final Node root) {
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
switch (event.getCode()) {
case Z:
cameraXform2.t.setX(0.0);
cameraXform2.t.setY(0.0);
camera.setTranslateZ(CAMERA_INITIAL_DISTANCE);
cameraXform.ry.setAngle(CAMERA_INITIAL_Y_ANGLE);
cameraXform.rx.setAngle(CAMERA_INITIAL_X_ANGLE);
break;
case X:
axisGroup.setVisible(!axisGroup.isVisible());
break;
case V:
break;
}
}
});
}
}
import javafx.scene.Group;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate;
// source:
// http://docs.oracle.com/javafx/8/3d_graphics/Xform.java.html
// http://docs.oracle.com/javafx/8/3d_graphics/jfxpub-3d_graphics.htm
public class Xform extends Group {
public enum RotateOrder {
XYZ, XZY, YXZ, YZX, ZXY, ZYX
}
public Translate t = new Translate();
public Translate p = new Translate();
public Translate ip = new Translate();
public Rotate rx = new Rotate();
{ rx.setAxis(Rotate.X_AXIS); }
public Rotate ry = new Rotate();
{ ry.setAxis(Rotate.Y_AXIS); }
public Rotate rz = new Rotate();
{ rz.setAxis(Rotate.Z_AXIS); }
public Scale s = new Scale();
public Xform() {
super();
getTransforms().addAll(t, rz, ry, rx, s);
}
public Xform(RotateOrder rotateOrder) {
super();
// choose the order of rotations based on the rotateOrder
switch (rotateOrder) {
case XYZ:
getTransforms().addAll(t, p, rz, ry, rx, s, ip);
break;
case YXZ:
getTransforms().addAll(t, p, rz, rx, ry, s, ip);
break;
case YZX:
getTransforms().addAll(t, p, rx, rz, ry, s, ip); // For Camera
break;
case ZXY:
getTransforms().addAll(t, p, ry, rx, rz, s, ip);
break;
case ZYX:
getTransforms().addAll(t, p, rx, ry, rz, s, ip);
break;
}
}
public void setTranslate(double x, double y, double z) {
t.setX(x);
t.setY(y);
t.setZ(z);
}
public void setTranslate(double x, double y) {
t.setX(x);
t.setY(y);
}
// Cannot override these methods as they are final:
// public void setTranslateX(double x) { t.setX(x); }
// public void setTranslateY(double y) { t.setY(y); }
// public void setTranslateZ(double z) { t.setZ(z); }
// Use these methods instead:
public void setTx(double x) { t.setX(x); }
public void setTy(double y) { t.setY(y); }
public void setTz(double z) { t.setZ(z); }
public void setRotate(double x, double y, double z) {
rx.setAngle(x);
ry.setAngle(y);
rz.setAngle(z);
}
public void setRotateX(double x) { rx.setAngle(x); }
public void setRotateY(double y) { ry.setAngle(y); }
public void setRotateZ(double z) { rz.setAngle(z); }
public void setRy(double y) { ry.setAngle(y); }
public void setRz(double z) { rz.setAngle(z); }
public void setScale(double scaleFactor) {
s.setX(scaleFactor);
s.setY(scaleFactor);
s.setZ(scaleFactor);
}
// Cannot override these methods as they are final:
// public void setScaleX(double x) { s.setX(x); }
// public void setScaleY(double y) { s.setY(y); }
// public void setScaleZ(double z) { s.setZ(z); }
// Use these methods instead:
public void setSx(double x) { s.setX(x); }
public void setSy(double y) { s.setY(y); }
public void setSz(double z) { s.setZ(z); }
public void setPivot(double x, double y, double z) {
p.setX(x);
p.setY(y);
p.setZ(z);
ip.setX(-x);
ip.setY(-y);
ip.setZ(-z);
}
public void reset() {
t.setX(0.0);
t.setY(0.0);
t.setZ(0.0);
rx.setAngle(0.0);
ry.setAngle(0.0);
rz.setAngle(0.0);
s.setX(1.0);
s.setY(1.0);
s.setZ(1.0);
p.setX(0.0);
p.setY(0.0);
p.setZ(0.0);
ip.setX(0.0);
ip.setY(0.0);
ip.setZ(0.0);
}
public void resetTSP() {
t.setX(0.0);
t.setY(0.0);
t.setZ(0.0);
s.setX(1.0);
s.setY(1.0);
s.setZ(1.0);
p.setX(0.0);
p.setY(0.0);
p.setZ(0.0);
ip.setX(0.0);
ip.setY(0.0);
ip.setZ(0.0);
}
public void debug() {
System.out.println("t = (" +
t.getX() + ", " +
t.getY() + ", " +
t.getZ() + ") " +
"r = (" +
rx.getAngle() + ", " +
ry.getAngle() + ", " +
rz.getAngle() + ") " +
"s = (" +
s.getX() + ", " +
s.getY() + ", " +
s.getZ() + ") " +
"p = (" +
p.getX() + ", " +
p.getY() + ", " +
p.getZ() + ") " +
"ip = (" +
ip.getX() + ", " +
ip.getY() + ", " +
ip.getZ() + ")");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment