JavaFX:在不转动轴的情况下旋转对象

时间:2016-10-19 06:55:30

标签: javafx

为了处理项目Rybi的立方体游戏,我必须围绕特定的轴转动立方体,所以问题是如果我绕一个轴转动一个物体,例如90度的Y轴,所以如果我再次绕x轴转动,旋转将在Z轴的方向上,因为X轴取决于Z.

下面,有一段代码说明了我刚才介绍的相同情况。

有没有办法以我想要的方式做事

public class RybiCube extends Application {

    final Group root = new Group();
    final PerspectiveCamera camera = new PerspectiveCamera(true);
    final XformCamera cameraXform = new XformCamera();
    public static final double CAMERA_INITIAL_DISTANCE = -1000;
    public static final double CAMERA_NEAR_CLIP = 0.1;
    public static final double CAMERA_FAR_CLIP = 10000.0;

    public void init(Stage primaryStage) {

        Box box = new Box();
        box.setHeight(70);
        box.setWidth(200);
        box.setDepth(70);
        //box.setRotationAxis(Rotate.Y_AXIS);
        //box.setRotate(80);
        box.getTransforms().add(new Rotate(90,Rotate.Y_AXIS));
        box.getTransforms().add(new Rotate(45,Rotate.X_AXIS));


        PhongMaterial material = new PhongMaterial();
        material.setDiffuseColor(Color.ORANGE);
        material.setSpecularColor(Color.BLACK);
        box.setMaterial(material);

        root.getChildren().add(box);
        buildCamera();
        Scene scene = new Scene(root, 600, 600, true);
        primaryStage.setScene(scene);
        scene.setCamera(camera);
        ///
        primaryStage.setResizable(false);
        scene.setFill(Color.rgb(0, 0,0,0.5));
        primaryStage.setScene(scene);        
    }

    private void buildCamera() {
        root.getChildren().add(cameraXform);
        cameraXform.getChildren().add(camera);
        camera.setNearClip(CAMERA_NEAR_CLIP);
        camera.setFarClip(CAMERA_FAR_CLIP);
        camera.setTranslateZ(CAMERA_INITIAL_DISTANCE);
    }

    public void start(Stage primaryStage)
    {
        init(primaryStage);
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }

}
class XformCamera extends Group {

    final Translate tr = new Translate(0.0, 0.0, 0.0);
    final Rotate rx = new Rotate(00, Rotate.X_AXIS);
    final Rotate ry = new Rotate(10, Rotate.Y_AXIS);
    final Rotate rz = new Rotate(0, Rotate.Z_AXIS);

    public XformCamera() {
        super();
        this.getTransforms().addAll(tr, rx, ry, rz);
    }

}

2 个答案:

答案 0 :(得分:0)

您可以简单地将逆变换应用于轴(使用inverseDeltaTransform):

public static void addRotate(Node node, Point3D rotationAxis, double angle) {
    ObservableList<Transform> transforms = node.getTransforms();
    try {
        for (Transform t : transforms) {
            rotationAxis = t.inverseDeltaTransform(rotationAxis);
        }
    } catch (NonInvertibleTransformException ex) {
        throw new IllegalStateException(ex);
    }
    transforms.add(new Rotate(angle, rotationAxis));
}
box.getTransforms().add(new Rotate(90,Rotate.Y_AXIS));
addRotate(box, Rotate.X_AXIS, 45);

答案 1 :(得分:0)

以下代码基于3D方向,可能对您的应用很有用。

import javafx.scene.Group;
import javafx.scene.transform.Affine;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class XformOrientation extends Group {

    private static final int SIZE = 5;
    private Affine affine;

    private final List<Double> averageRoll = new ArrayList();
    private final List<Double> averagePitch = new ArrayList();
    private final List<Double> averageYaw = new ArrayList();

    public XformOrientation() {
        super();
        affine = new Affine();
        this.getTransforms().add(affine);
    }

    /**
     * angles in degrees
     * @param roll
     * @param pitch
     * @param yaw
     */
    public void processEvent(double roll, double pitch, double yaw) {
        double avYaw = average(averageYaw, Math.toRadians(yaw));
        double avPitch = average(averagePitch, Math.toRadians(pitch));
        double avRoll = average(averageRoll, Math.toRadians(roll));
        matrixRotateNode(avRoll, avPitch, avYaw);
    }

    private void matrixRotateNode(double roll, double pitch, double yaw) {
        double mxx = Math.cos(pitch) * Math.cos(yaw);
        double mxy = Math.cos(roll) * Math.sin(pitch) +
                Math.cos(pitch) * Math.sin(roll) * Math.sin(yaw);
        double mxz = Math.sin(pitch) * Math.sin(roll) -
                Math.cos(pitch) * Math.cos(roll) * Math.sin(yaw);
        double myx = -Math.cos(yaw) * Math.sin(pitch);
        double myy = Math.cos(pitch) * Math.cos(roll) -
                Math.sin(pitch) * Math.sin(roll) * Math.sin(yaw);
        double myz = Math.cos(pitch) * Math.sin(roll) +
                Math.cos(roll) * Math.sin(pitch) * Math.sin(yaw);
        double mzx = Math.sin(yaw);
        double mzy = -Math.cos(yaw) * Math.sin(roll);
        double mzz = Math.cos(roll) * Math.cos(yaw);

        affine.setToTransform(mxx, mxy, mxz, 0,
                myx, myy, myz, 0,
                mzx, mzy, mzz, 0);
    }

    private double average(List<Double> list, double value) {
        while (list.size() > SIZE) {
            list.remove(0);
        }
        list.add(value);

        return list.stream()
                .collect(Collectors.averagingDouble(d -> d));
    }

}

作为应用程序,您可以使用

    private final XformOrientation world = new XformOrientation();

    PhongMaterial whiteMaterial = new PhongMaterial();
    whiteMaterial.setDiffuseColor(Color.WHITE);
    whiteMaterial.setSpecularColor(Color.LIGHTBLUE);
    Box box = new Box(400, 200, 100);
    box.setMaterial(whiteMaterial);

    world.getChildren().addAll(box);

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            Platform.runLater(() -> {
                world.processEvent(getRoll(), getPitch(), getYaw());
            });
        }
    };
    getAhrsInfo().rollProperty().addListener((observable, oldValue, newValue) -> runnable.run());
    getAhrsInfo().pitchProperty().addListener((observable, oldValue, newValue) -> runnable.run());
    getAhrsInfo().yawProperty().addListener((observable, oldValue, newValue) -> runnable.run());