使用JavaFX实现物体在球体周围的位移

5gfr0r5j  于 2023-01-29  发布在  Java
关注(0)|答案(1)|浏览(93)

我有一个对象,比如这个例子中的盒子。我希望这个盒子在Z轴旋转时在球体上以正弦向左移动。但是在盒子做了一条曲线之后,也就是Z轴的旋转回到0。球体不再像开始时那样向下旋转,而是向右向上旋转。

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;
        }
    }
}

我尝试了许多不同的方法与三角,但他们都没有成功。这是例如移动的X轴的领域也根据正弦或减去移动的Y和Z轴的领域作为余弦。
我认为它必须转换成旋转矩阵,但我从来没有矩阵计算。

k10s72fa

k10s72fa1#

在3d场景中旋转另一个Group内的Group

在这种方法中,Box示例看起来没有移动,因为它是随着摄像机移动的。摄像机和长方体一起移动,因为它的Group父节点是随着键盘事件旋转的。Sphere节点在另一个组中,不受影响。球体本身在Y轴上旋转

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();
    }

    }

相关问题