I have an object, like a box in this example. I want this box to move in a sine to the left on the sphere when the Z-axis is rotated. But after the box has made a curve, i.e. the rotation of the Z-axis is back to 0. The sphere no longer rotates downwards as it did at the start, but upwards to the right.
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Sphere;
import javafx.scene.transform.*;
import javafx.stage.Stage;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
import java.util.ArrayList;
public class TestFX extends Application {
public static final float WIDTH = 1400;
public static final float HEIGHT = 1000;
private final ArrayList<String> input = new ArrayList<>();
private final Sphere sphere = new Sphere(500);
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Flugzeug flieger = new Flugzeug(30, 30, 50);
flieger.setMaterial(new PhongMaterial(Color.GREEN));
flieger.setTranslateZ(330);
flieger.getTransforms().add(new Rotate(20, Rotate.X_AXIS));
sphere.translateZProperty().set(710);
sphere.translateYProperty().set(420);
PhongMaterial phongMaterial = new PhongMaterial();
phongMaterial.setDiffuseMap(new Image(getClass().getResourceAsStream("Earth_diffuse_8k.png")));
sphere.setMaterial(phongMaterial);
PerspectiveCamera camera = new PerspectiveCamera(true);
camera.setFarClip(40000);
Group root = new Group(flieger, sphere);
Scene scene = new Scene(root, WIDTH, HEIGHT, true);
scene.setCamera(camera);
primaryStage.setTitle("FliegenFX");
primaryStage.setScene(scene);
primaryStage.show();
new AnimationTimer() {
@Override
public void handle(long now) {
initGameLogic(flieger);
dreheErde(flieger, sphere);
}
}.start();
scene.setOnKeyPressed(event -> {
String code = event.getCode().toString();
if (!input.contains(code))
input.add(code);
});
scene.setOnKeyReleased(event -> {
String code = event.getCode().toString();
input.remove(code);
});
}
// TODO Erddrehung nach Drehung beibehalten
private void dreheErde(Flugzeug flieger, Sphere erde) {
double rotationFactor = 0.005;
double drehung = flieger.getDrehung() * rotationFactor;
double amplitude = 2;
double frequency = 0.001;
float angle = (float) (Math.sin(drehung * frequency) * amplitude);
Quaternionf quat = new Quaternionf();
Matrix4f matrix4f = new Matrix4f();
Affine affine = new Affine();
quat.rotateY(angle);
quat.rotateZ(angle);
quat.rotateX(-0.001f);
quat.normalize();
quat.get(matrix4f);
float[] matrixArray = new float[16];
matrix4f.get(matrixArray);
double[] matrix = new double[16];
for (int i = 0 ; i < matrixArray.length; i )
{
matrix[i] = matrixArray[i];
}
affine.append(matrix, MatrixType.MT_3D_4x4, 0);
erde.getTransforms().add(affine);
}
private void initGameLogic(Flugzeug flieger) {
if (input.contains("LEFT")) {
flieger.rotateByZ(-0.5);
}
if (input.contains("RIGHT")) {
flieger.rotateByZ(0.5);
}
}
private class Flugzeug extends Box{
private double drehung = 0;
private Rotate r;
private Transform t = new Rotate();
public Flugzeug(double width, double height, double depth){
super(width, height, depth);
}
public void rotateByZ(double ang){
drehung = ang;
r = new Rotate(ang, Rotate.Z_AXIS);
t = t.createConcatenation(r);
getTransforms().clear();
getTransforms().addAll(t);
}
public double getDrehung() {
return drehung;
}
}
}
I have tried many different ways with trigonometry but they have not been successful. This was for example to move the X-axis of the sphere also according to the sine or to subtract the movements of the Y and Z axis of the sphere as cosine.
I think it has to be transformed in a Rotation Matrix, but i‘ve never had matrix calculation.
CodePudding user response:
Rotating a Group
inside another Group
in 3d scene
In this approach Box
instance doesn't seem to move 'cause it's moving with the camera . Camera and box are moving together because is it's Group
parent who is rotating with keyboard event . The Sphere
node is in another group and is not affected . Sphere itself is rotating in Y axis
App.java
public class App extends Application {
@Override
public void start(Stage stage) {
Shape3D sphere = new Sphere(10);
PhongMaterial mat = new PhongMaterial();
mat.setDiffuseMap(new Image("https://www.h-schmidt.net/map/map.jpg"));
sphere.setMaterial(mat);
RotateTransition sphereRotation = new RotateTransition(Duration.seconds(40), sphere);
sphereRotation.setAxis(Rotate.Y_AXIS);
sphereRotation.setToAngle(360);
sphereRotation.setInterpolator(Interpolator.LINEAR);
sphereRotation.setCycleCount(Animation.INDEFINITE);
sphereRotation.play();
Shape3D box = new Box(2, 2, 2);
box.setMaterial(new PhongMaterial(Color.ORANGE));
box.setTranslateZ(-11);
PerspectiveCamera camera = new PerspectiveCamera(true);
camera.setTranslateZ(-30);
var planeGroup = new Group(box, camera);
Group sphereGroup = new Group(sphere);
Group group3d = new Group(planeGroup, sphereGroup);
Scene scene = new Scene(group3d, 640, 480, true, SceneAntialiasing.BALANCED);
scene.setOnKeyPressed((t) -> {
if (t.getCode() == KeyCode.UP) {
Rotate r = new Rotate(-2);
r.setAxis(Rotate.X_AXIS);
planeGroup.getTransforms().add(r);
}
if (t.getCode() == KeyCode.LEFT) {
Rotate r = new Rotate(2);
r.setAxis(Rotate.Y_AXIS);
planeGroup.getTransforms().add(r);
}
if (t.getCode() == KeyCode.RIGHT) {
Rotate r = new Rotate(-2);
r.setAxis(Rotate.Y_AXIS);
planeGroup.getTransforms().add(r);
}
if (t.getCode() == KeyCode.DOWN) {
Rotate r = new Rotate(2);
r.setAxis(Rotate.X_AXIS);
planeGroup.getTransforms().add(r);
}
});
scene.setCamera(camera);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}