-
Bug
-
Resolution: Not an Issue
-
P4
-
None
-
8
-
JDK 8.0-b94, Linux, Mac, Windows
Rotation of each cylinder is centric. Rotation of the cube (2x2x2) is centric, also. If both rotations are active the entire model 'jumps' around the center point.
package jiraissue;
import javafx.animation.Interpolator;
import javafx.animation.RotateTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.BoundingBox;
import javafx.scene.AmbientLight;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Cylinder;
import javafx.scene.transform.Affine;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Duration;
public class HierarchicalRotateTransitions extends Application {
public static void main(String[] args) {
launch(args);
}
private Affine viewingRotate = new Affine();
private Translate viewingTranslate = new Translate();
private RotateTransition cylCubeRotTransition = null;
private RotateTransition[] cylRotTransAll = null;
@Override public void start(Stage stage) {
// SubScene & Root
final Group subSceneRoot = new Group();
final SubScene subScene = new SubScene(subSceneRoot, 800, 800, true, false);
subScene.setFill(Color.YELLOWGREEN);
// Viewing : Camera & Light
// SubScene's camera
final PerspectiveCamera perspectiveCamera = new PerspectiveCamera(true);
perspectiveCamera.setFarClip(25);
perspectiveCamera.setNearClip(0.1);
perspectiveCamera.setFieldOfView(44);
subScene.setCamera(perspectiveCamera);
// SubScene's lights
final PointLight pointLight = new PointLight(Color.WHITE);
pointLight.setTranslateZ(-20000);
final AmbientLight ambLight = new AmbientLight(Color.color(0.3, 0.3, 0.3));
// Viewing group: camera and headlight
final Group viewingGroup = new Group(perspectiveCamera, pointLight);
viewingGroup.getTransforms().setAll(viewingRotate, viewingTranslate);
// View from top (+Y)
viewingRotate.setToTransform(new Rotate(-90, Rotate.X_AXIS));
viewingTranslate.setZ(-8);
//
// Group hierarchy of the cube
//
// Centers the entire cube at (0,0,0)
final Group cylCubeCenterGroup = new Group();
// Cube rotation target
final Group cylCubeRotGroup = new Group(cylCubeCenterGroup);
cylCubeRotTransition = new RotateTransition();
cylCubeRotTransition.setNode(cylCubeRotGroup);
cylCubeRotTransition.setAxis(Rotate.Y_AXIS);
cylCubeRotTransition.setCycleCount(Timeline.INDEFINITE);
cylCubeRotTransition.setAutoReverse(false);
cylCubeRotTransition.setInterpolator(Interpolator.LINEAR);
cylCubeRotTransition.setByAngle(360);
cylCubeRotTransition.setDuration(Duration.millis(10000));
// Add all to SubScene
subSceneRoot.getChildren().addAll(cylCubeRotGroup, viewingGroup, ambLight);
final int xDist = 2;
final int yDist = 2;
final int zDist = 2;
long delay = 4;
final long delayIncr = 4;
Group cylCenterGroup = null; // center Tux at (0,y,0)
Group cylRotationGroup = null; // target for rotate transition
Group cylPositionGroup = null; // position Tux within the cube
// Cube's size
final int dim = 2;
final int numTux = dim*dim*dim;
final double maxTux = 10*10*10;
int n = 0;
float xTrans = 0;
float yTrans = 0;
float zTrans = 0;
cylRotTransAll = new RotateTransition[numTux];
final ObservableList<Node> children = cylCubeCenterGroup.getChildren();
for (int i=0; i < dim; i++) { // z axis
for (int j=0; j < dim; j++) { // y axis
for (int k=0; k < dim; k++) { // x axis
Cylinder cylinder = new Cylinder(0.25, 1.5);
// group hierarchy from bottom to top
// 1.
cylCenterGroup = new Group(cylinder);
cylCenterGroup.setRotationAxis(Rotate.X_AXIS);
cylCenterGroup.setRotate(90);
// 2.
cylRotationGroup = new Group(cylCenterGroup);
RotateTransition rotateTransition = new RotateTransition();
rotateTransition.setNode(cylRotationGroup);
rotateTransition.setAxis(Rotate.Y_AXIS);
rotateTransition.setDelay(Duration.millis(delay));
rotateTransition.setDuration(Duration.millis(5000 - 2*n*(maxTux/numTux)));
rotateTransition.setCycleCount(Timeline.INDEFINITE);
rotateTransition.setAutoReverse(false);
rotateTransition.setInterpolator(Interpolator.LINEAR);
rotateTransition.setByAngle(360);
cylRotTransAll[n] = rotateTransition;
// 3.
cylPositionGroup = new Group(cylRotationGroup);
cylPositionGroup.setTranslateX(xTrans);
cylPositionGroup.setTranslateY(yTrans);
cylPositionGroup.setTranslateZ(zTrans);
children.add(cylPositionGroup);
xTrans += xDist;
delay = delayIncr * n;
n++;
} // x axis
xTrans = 0;
yTrans += yDist;
} // y axis
yTrans = 0;
zTrans += zDist;
} // z axis cylCubeCenterTranslate
final BoundingBox cylCubeBinL = (BoundingBox)cylCubeCenterGroup.getBoundsInLocal();
System.out.println("cylCubeBinL " + cylCubeBinL);
cylCubeCenterGroup.setTranslateX(-(cylCubeBinL.getMinX()+cylCubeBinL.getMaxX())/2.0);
cylCubeCenterGroup.setTranslateY(-(cylCubeBinL.getMinY()+cylCubeBinL.getMaxY())/2.0);
cylCubeCenterGroup.setTranslateZ(-(cylCubeBinL.getMinZ()+cylCubeBinL.getMaxZ())/2.0);
final BoundingBox cylCubeBinP = (BoundingBox)cylCubeCenterGroup.getBoundsInParent();
System.out.println("cylCubeBinP " + cylCubeBinP);
// Scene
final CheckBox cylRotCheck = new CheckBox("Cylinders play/pause");
cylRotCheck.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean old_val, Boolean new_val) {
playPauseCylRotation(new_val);
}
});
final Button cylRotStopButton = new Button("stop");
cylRotStopButton.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(final ActionEvent e) {
cylRotCheck.setSelected(false);
for (RotateTransition rot : cylRotTransAll) {
rot.stop();
rot.getNode().setRotate(0);
}
}
});
final CheckBox cubeRotCheck = new CheckBox("Cube play/pause");
cubeRotCheck.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean old_val, Boolean new_val) {
playPauseCubeRotation(new_val);
}
});
final Button cubeRotStopButton = new Button("stop");
cubeRotStopButton.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(final ActionEvent e) {
cubeRotCheck.setSelected(false);
cylCubeRotTransition.stop();
cylCubeRotTransition.getNode().setRotate(0);
}
});
final HBox hBox = new HBox();
hBox.setSpacing(20);
hBox.getChildren().addAll(cylRotCheck, cylRotStopButton, cubeRotCheck, cubeRotStopButton);
final BorderPane borderPane = new BorderPane();
borderPane.setMinHeight(0);
borderPane.setMinWidth(0);
borderPane.setCenter(subScene);
borderPane.setBottom(hBox);
final Scene scene = new Scene(borderPane, 850, 850, true);
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override public void handle(WindowEvent event) {
System.exit(0);
}
});
stage.setScene(scene);
stage.setTitle("HierarchicalRotateTransitions");
stage.show();
}
private void playPauseCylRotation(boolean play) {
if (play) {
for (RotateTransition rot : cylRotTransAll) {
rot.play();
}
}
else {
for (RotateTransition rot : cylRotTransAll) {
rot.pause();
}
}
}
private void playPauseCubeRotation(boolean play) {
if (play) {
cylCubeRotTransition.play();
}
else {
cylCubeRotTransition.pause();
}
}
}
package jiraissue;
import javafx.animation.Interpolator;
import javafx.animation.RotateTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.BoundingBox;
import javafx.scene.AmbientLight;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Cylinder;
import javafx.scene.transform.Affine;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Duration;
public class HierarchicalRotateTransitions extends Application {
public static void main(String[] args) {
launch(args);
}
private Affine viewingRotate = new Affine();
private Translate viewingTranslate = new Translate();
private RotateTransition cylCubeRotTransition = null;
private RotateTransition[] cylRotTransAll = null;
@Override public void start(Stage stage) {
// SubScene & Root
final Group subSceneRoot = new Group();
final SubScene subScene = new SubScene(subSceneRoot, 800, 800, true, false);
subScene.setFill(Color.YELLOWGREEN);
// Viewing : Camera & Light
// SubScene's camera
final PerspectiveCamera perspectiveCamera = new PerspectiveCamera(true);
perspectiveCamera.setFarClip(25);
perspectiveCamera.setNearClip(0.1);
perspectiveCamera.setFieldOfView(44);
subScene.setCamera(perspectiveCamera);
// SubScene's lights
final PointLight pointLight = new PointLight(Color.WHITE);
pointLight.setTranslateZ(-20000);
final AmbientLight ambLight = new AmbientLight(Color.color(0.3, 0.3, 0.3));
// Viewing group: camera and headlight
final Group viewingGroup = new Group(perspectiveCamera, pointLight);
viewingGroup.getTransforms().setAll(viewingRotate, viewingTranslate);
// View from top (+Y)
viewingRotate.setToTransform(new Rotate(-90, Rotate.X_AXIS));
viewingTranslate.setZ(-8);
//
// Group hierarchy of the cube
//
// Centers the entire cube at (0,0,0)
final Group cylCubeCenterGroup = new Group();
// Cube rotation target
final Group cylCubeRotGroup = new Group(cylCubeCenterGroup);
cylCubeRotTransition = new RotateTransition();
cylCubeRotTransition.setNode(cylCubeRotGroup);
cylCubeRotTransition.setAxis(Rotate.Y_AXIS);
cylCubeRotTransition.setCycleCount(Timeline.INDEFINITE);
cylCubeRotTransition.setAutoReverse(false);
cylCubeRotTransition.setInterpolator(Interpolator.LINEAR);
cylCubeRotTransition.setByAngle(360);
cylCubeRotTransition.setDuration(Duration.millis(10000));
// Add all to SubScene
subSceneRoot.getChildren().addAll(cylCubeRotGroup, viewingGroup, ambLight);
final int xDist = 2;
final int yDist = 2;
final int zDist = 2;
long delay = 4;
final long delayIncr = 4;
Group cylCenterGroup = null; // center Tux at (0,y,0)
Group cylRotationGroup = null; // target for rotate transition
Group cylPositionGroup = null; // position Tux within the cube
// Cube's size
final int dim = 2;
final int numTux = dim*dim*dim;
final double maxTux = 10*10*10;
int n = 0;
float xTrans = 0;
float yTrans = 0;
float zTrans = 0;
cylRotTransAll = new RotateTransition[numTux];
final ObservableList<Node> children = cylCubeCenterGroup.getChildren();
for (int i=0; i < dim; i++) { // z axis
for (int j=0; j < dim; j++) { // y axis
for (int k=0; k < dim; k++) { // x axis
Cylinder cylinder = new Cylinder(0.25, 1.5);
// group hierarchy from bottom to top
// 1.
cylCenterGroup = new Group(cylinder);
cylCenterGroup.setRotationAxis(Rotate.X_AXIS);
cylCenterGroup.setRotate(90);
// 2.
cylRotationGroup = new Group(cylCenterGroup);
RotateTransition rotateTransition = new RotateTransition();
rotateTransition.setNode(cylRotationGroup);
rotateTransition.setAxis(Rotate.Y_AXIS);
rotateTransition.setDelay(Duration.millis(delay));
rotateTransition.setDuration(Duration.millis(5000 - 2*n*(maxTux/numTux)));
rotateTransition.setCycleCount(Timeline.INDEFINITE);
rotateTransition.setAutoReverse(false);
rotateTransition.setInterpolator(Interpolator.LINEAR);
rotateTransition.setByAngle(360);
cylRotTransAll[n] = rotateTransition;
// 3.
cylPositionGroup = new Group(cylRotationGroup);
cylPositionGroup.setTranslateX(xTrans);
cylPositionGroup.setTranslateY(yTrans);
cylPositionGroup.setTranslateZ(zTrans);
children.add(cylPositionGroup);
xTrans += xDist;
delay = delayIncr * n;
n++;
} // x axis
xTrans = 0;
yTrans += yDist;
} // y axis
yTrans = 0;
zTrans += zDist;
} // z axis cylCubeCenterTranslate
final BoundingBox cylCubeBinL = (BoundingBox)cylCubeCenterGroup.getBoundsInLocal();
System.out.println("cylCubeBinL " + cylCubeBinL);
cylCubeCenterGroup.setTranslateX(-(cylCubeBinL.getMinX()+cylCubeBinL.getMaxX())/2.0);
cylCubeCenterGroup.setTranslateY(-(cylCubeBinL.getMinY()+cylCubeBinL.getMaxY())/2.0);
cylCubeCenterGroup.setTranslateZ(-(cylCubeBinL.getMinZ()+cylCubeBinL.getMaxZ())/2.0);
final BoundingBox cylCubeBinP = (BoundingBox)cylCubeCenterGroup.getBoundsInParent();
System.out.println("cylCubeBinP " + cylCubeBinP);
// Scene
final CheckBox cylRotCheck = new CheckBox("Cylinders play/pause");
cylRotCheck.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean old_val, Boolean new_val) {
playPauseCylRotation(new_val);
}
});
final Button cylRotStopButton = new Button("stop");
cylRotStopButton.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(final ActionEvent e) {
cylRotCheck.setSelected(false);
for (RotateTransition rot : cylRotTransAll) {
rot.stop();
rot.getNode().setRotate(0);
}
}
});
final CheckBox cubeRotCheck = new CheckBox("Cube play/pause");
cubeRotCheck.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean old_val, Boolean new_val) {
playPauseCubeRotation(new_val);
}
});
final Button cubeRotStopButton = new Button("stop");
cubeRotStopButton.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(final ActionEvent e) {
cubeRotCheck.setSelected(false);
cylCubeRotTransition.stop();
cylCubeRotTransition.getNode().setRotate(0);
}
});
final HBox hBox = new HBox();
hBox.setSpacing(20);
hBox.getChildren().addAll(cylRotCheck, cylRotStopButton, cubeRotCheck, cubeRotStopButton);
final BorderPane borderPane = new BorderPane();
borderPane.setMinHeight(0);
borderPane.setMinWidth(0);
borderPane.setCenter(subScene);
borderPane.setBottom(hBox);
final Scene scene = new Scene(borderPane, 850, 850, true);
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override public void handle(WindowEvent event) {
System.exit(0);
}
});
stage.setScene(scene);
stage.setTitle("HierarchicalRotateTransitions");
stage.show();
}
private void playPauseCylRotation(boolean play) {
if (play) {
for (RotateTransition rot : cylRotTransAll) {
rot.play();
}
}
else {
for (RotateTransition rot : cylRotTransAll) {
rot.pause();
}
}
}
private void playPauseCubeRotation(boolean play) {
if (play) {
cylCubeRotTransition.play();
}
else {
cylCubeRotTransition.pause();
}
}
}