JavaFX中鼠标绕Z轴旋转

3

我希望能够使用鼠标在JavaFX中旋转3D对象。我已经能够通过鼠标的x、y位置计算x轴和y轴旋转的角度,并且能够围绕x轴和y轴旋转。但是我也想围绕z轴旋转对象。

如何从鼠标的x、y位置计算出z轴旋转的旋转角度?

以下是用于围绕x轴和y轴旋转对象的示例代码。

private void handleMouseEvents() {
    setOnMousePressed((MouseEvent me) -> {
        setActivated(true);
        mousePosX = me.getSceneX();
        mousePosY = me.getSceneY();
        mouseOldX = me.getSceneX();
        mouseOldY = me.getSceneY();
    });

    setOnMouseDragged((MouseEvent me) -> {
        mousePosX = me.getSceneX();
        mouseOldY = me.getSceneY();
        double dx = (mousePosX - mouseOldX) ;
        double dy = (mouseOldY - mouseOldY);
        mouseOldX = mousePosX;
        mouseOldY = mouseOldY;
        if (me.isPrimaryButtonDown()) {
            rotateY.setAngle(rotateY.getAngle() - dx);
            rotateX.setAngle(rotateX.getAngle() + dy);
        } 
    });
}
2个回答

5
我使用Zydar的公式创建了一个可直接运行的示例。 testBox 是被旋转的3D对象。
如果这不是您想要的行为,请详细说明您的问题。 重要部分:
private void handleMouseEvents() {
    scene.setOnMousePressed((MouseEvent me) -> {
        mousePosX = me.getSceneX();
        mousePosY = me.getSceneY();
    });

    scene.setOnMouseDragged((MouseEvent me) -> {
        double dx = (mousePosX - me.getSceneX()) ;
        double dy = (mousePosY - me.getSceneY());
        if (me.isPrimaryButtonDown()) {
            rotateX.setAngle(rotateX.getAngle() - 
                    (dy / testBox.getHeight() * 360) * (Math.PI / 180));
            rotateY.setAngle(rotateY.getAngle() - 
                    (dx / testBox.getWidth() * -360) * (Math.PI / 180));
        }
        mousePosX = me.getSceneX();
        mousePosY = me.getSceneY();
    });
}

整个SSCCE:

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class SampleApp extends Application {
    private Box testBox;
    private Scene scene;
    private Rotate rotateX = new Rotate(0, Rotate.X_AXIS);
    private Rotate rotateY = new Rotate(0, Rotate.Y_AXIS);
    private Rotate rotateZ = new Rotate(0, Rotate.Z_AXIS);
    private final double TURN_FACTOR = 0.5; 

    public Parent createContent() throws Exception {
        // Box
        testBox = new Box(5, 5, 5);
        testBox.getTransforms().addAll(rotateZ, rotateY, rotateX);

        // Create and position camera
        PerspectiveCamera camera = new PerspectiveCamera(true);
        camera.getTransforms().addAll(
        new Rotate(-20, Rotate.Y_AXIS),
        new Rotate(-20, Rotate.X_AXIS),
        new Translate(0, 0, -50));

        // Build the Scene Graph
        Group root = new Group();
        root.getChildren().add(camera);
        root.getChildren().add(testBox);

        // Use a SubScene
        SubScene subScene = new SubScene(root, 300, 300, true, 
             SceneAntialiasing.BALANCED);
        subScene.setFill(Color.TRANSPARENT);
        subScene.setCamera(camera);

        return new Group(subScene);
    }

    private double mousePosX, mousePosY = 0;
    private void handleMouseEvents() {
        scene.setOnMousePressed((MouseEvent me) -> {
            mousePosX = me.getSceneX();
            mousePosY = me.getSceneY();
        });

        scene.setOnMouseDragged((MouseEvent me) -> {
            double dx = (mousePosX - me.getSceneX()) ;
            double dy = (mousePosY - me.getSceneY());
            if (me.isPrimaryButtonDown()) {
                rotateX.setAngle(rotateX.getAngle() - 
                    (dy / testBox.getHeight() * 360) * (Math.PI / 180));
                rotateY.setAngle(rotateY.getAngle() - 
                    (dx / testBox.getWidth() * -360) * (Math.PI / 180));
            }
            mousePosX = me.getSceneX();
            mousePosY = me.getSceneY();
        });
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setResizable(false);
        scene = new Scene(createContent());
        handleMouseEvents();
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

我使用了上述源代码,在进行鼠标旋转时,方框的位置被重置为初始位置。但是我想要从对象的最后位置进行旋转。 - user3616468
我刚刚更新了代码,以便在计算中包括块的先前角度。现在还可以拖动整个场景。 - Luke

1

在拖动事件中,您可以尝试类似于以下的操作:

double dx = (mousePosX - me.getSceneX());
double dy = (mousePosY - me.getSceneY());

rotateX((dy / 'Your 3D-object'.getHeight() * -360) * (Math.PI / 180));
rotateY((dx / 'Your 3D-object'.getWidth() * -360) * (Math.PI / 180));

mousePosX = me.getSceneX();
mousePosY = me.getSceneY();

也许你的计算是正确的,但我猜想你设置了错误的“Y”值,特别是“dy”总是为0,因为你计算的是“mouseOldY - mouseOldY”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接