/* * Copyright (c) 2008, 2011 Oracle and/or its affiliates. * All rights reserved. Use is subject to license terms. * * This file is available and licensed under the following license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * - Neither the name of Oracle Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package cube3dfxcanvas; import javafx.animation.Animation; import javafx.animation.KeyFrame; import javafx.animation.KeyValue; import javafx.animation.Timeline; import javafx.application.ConditionalFeature; import javafx.application.Platform; import javafx.embed.swt.FXCanvas; import javafx.scene.DepthTest; import javafx.scene.Group; import javafx.scene.PerspectiveCamera; import javafx.scene.Scene; import javafx.scene.paint.Color; import javafx.scene.shape.RectangleBuilder; import javafx.scene.transform.Rotate; import javafx.util.Duration; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; /* Cube3DFXCanvas is derived from 'ensemble.samples.graphics3d.CubeSample'. * * Redistribution and use are permitted according to the above copyrigth and license notice. * * Date: 2011/12/21 * Author: August Lammersdorf, InteractiveMesh */ // ISSUE : FXCanvas doesn't support 3D z-depth sorting. // Rectangles and cubes are rendered in child-index-order. public final class Cube3DFXCanvas { /** * @param args the command line arguments */ public static void main(String[] args) { new Cube3DFXCanvas().initAndShowGUI(); } private void initAndShowGUI() { System.out.println("EFFECT = " + Platform.isSupported(ConditionalFeature.EFFECT) + "\nINPUT_METHOD = " + Platform.isSupported(ConditionalFeature.INPUT_METHOD) + "\nSCENE3D = " + Platform.isSupported(ConditionalFeature.SCENE3D) + "\nSHAPE_CLIP = " + Platform.isSupported(ConditionalFeature.SHAPE_CLIP) ); Display display = new Display(); Shell shell = new Shell(display); shell.setLayout(new FillLayout()); shell.setText("Cube 3D in FXCanvas"); final int panelWidth = 1000; final int panelHeight = 800; final FXCanvas fxCanvas = new FXCanvas(shell, SWT.NONE); // JavaFX and SWT share the same basic threading model !? // Platform.runLater(new Runnable() { // public void run() { double cubeSize = panelHeight/2.5; double cubeOffset = cubeSize*0.7; Cube c1 = new Cube(cubeSize, Color.RED, 1); c1.rx.setAngle(45); c1.ry.setAngle(45); Cube c2 = new Cube(cubeSize, Color.GREEN, 1); c2.setTranslateX(cubeOffset); c2.rx.setAngle(45); c2.ry.setAngle(45); Cube c3 = new Cube(cubeSize, Color.ORANGE, 1); c3.setTranslateX(-cubeOffset); c3.rx.setAngle(45); c3.ry.setAngle(45); Timeline animation = new Timeline(); animation.getKeyFrames().addAll( new KeyFrame(Duration.ZERO, new KeyValue(c1.ry.angleProperty(), 0d), new KeyValue(c2.rx.angleProperty(), 0d), new KeyValue(c3.rz.angleProperty(), 0d) ), new KeyFrame(Duration.millis(10000), new KeyValue(c1.ry.angleProperty(), 360d), new KeyValue(c2.rx.angleProperty(), 360d), new KeyValue(c3.rz.angleProperty(), 360d) )); animation.setCycleCount(Animation.INDEFINITE); // create root group Group cubes = new Group(c1,c2,c3); cubes.setDepthTest(DepthTest.ENABLE); // translate and rotate group so that origin is center and +Y is up cubes.setTranslateX(panelWidth/2); cubes.setTranslateY(panelHeight/2); cubes.getTransforms().add(new Rotate(180, Rotate.X_AXIS)); // create scene Scene scene = new Scene(cubes, panelWidth, panelHeight, true); scene.setCamera(new PerspectiveCamera()); fxCanvas.setScene(scene); // start spining animation animation.play(); // } // }); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); System.exit(0); } private static class Cube extends Group { final Rotate rx = new Rotate(0,Rotate.X_AXIS); final Rotate ry = new Rotate(0,Rotate.Y_AXIS); final Rotate rz = new Rotate(0,Rotate.Z_AXIS); public Cube(double size, Color color, double shade) { getTransforms().addAll(rz, ry, rx); getChildren().addAll( RectangleBuilder.create() // back face .width(size).height(size) .fill(color.deriveColor(0.0, 1.0, (1 - 0.5*shade), 1.0)) .translateX(-0.5*size) .translateY(-0.5*size) .translateZ(0.5*size) .build(), RectangleBuilder.create() // bottom face .width(size).height(size) .fill(color.deriveColor(0.0, 1.0, (1 - 0.4*shade), 1.0)) .translateX(-0.5*size) .translateY(0) .rotationAxis(Rotate.X_AXIS) .rotate(90) .build(), RectangleBuilder.create() // right face .width(size).height(size) .fill(color.deriveColor(0.0, 1.0, (1 - 0.3*shade), 1.0)) .translateX(-1*size) .translateY(-0.5*size) .rotationAxis(Rotate.Y_AXIS) .rotate(90) .build(), RectangleBuilder.create() // left face .width(size).height(size) .fill(color.deriveColor(0.0, 1.0, (1 - 0.2*shade), 1.0)) .translateX(0) .translateY(-0.5*size) .rotationAxis(Rotate.Y_AXIS) .rotate(90) .build(), RectangleBuilder.create() // top face .width(size).height(size) .fill(color.deriveColor(0.0, 1.0, (1 - 0.1*shade), 1.0)) .translateX(-0.5*size) .translateY(-1*size) .rotationAxis(Rotate.X_AXIS) .rotate(90) .build(), RectangleBuilder.create() // top face .width(size).height(size) .fill(color) .translateX(-0.5*size) .translateY(-0.5*size) .translateZ(-0.5*size) .build() ); } } }