使用鼠标在 JavaFX 中移动 3D 相机

3D Camera movement in JavaFX using mouse

我已经成功地使用鼠标拖动移动了相机。然而,问题是一旦我移动了相机并释放了鼠标按下,相机 returns 回到原点。

我希望相机保持在更改后的位置,这样当我再次使用鼠标移动相机时,它会从该位置移动到任意位置,而不是从原点移动。

package application;
    
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Camera;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Sphere;


public class Main extends Application {
    
    private static final int WIDTH = 900;
    private static final int HEIGHT = 600;  

    //Tracks drag starting point for x and y
    private double anchorX, anchorY;
    
    @Override
    public void start(Stage primaryStage) {
        Sphere sphere = new Sphere(50);
        
        Group group = new Group();
        group.getChildren().add(sphere);
     
        Camera camera = new PerspectiveCamera();
        Scene scene = new Scene(group, WIDTH, HEIGHT);
        scene.setFill(Color.SILVER);
        scene.setCamera(camera);
     
        sphere.setTranslateX(WIDTH / 2);
        sphere.setTranslateY(HEIGHT / 2);
        
        initMouseControl(scene, camera, primaryStage, sphere);
     
        primaryStage.setTitle("Solar System Simulator");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    private void initMouseControl(Scene scene, Camera camera, Stage stage, Sphere sphere) {

           scene.setOnMousePressed(event -> {
                //Save start points
                anchorX = event.getSceneX();
                anchorY = event.getSceneY();
           });
         
           scene.setOnMouseDragged(event -> {
                camera.setTranslateY(anchorY - event.getSceneY());
                camera.setTranslateX(anchorX - event.getSceneX());
           });
           
           stage.addEventHandler(ScrollEvent.SCROLL, event -> {
               sphere.setTranslateZ(sphere.getTranslateZ() + event.getDeltaY());
           });
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

我尝试使用谷歌搜索来寻找解决方案,但在使用 javafx 进行相机移动时找不到太多信息

我不知道Google能在多大程度上帮助您解决逻辑问题。我没有进一步分析您的代码,但至少每次按下鼠标按钮时,您的相机位置都会按设计重置为零。您的更改不会累积。

首先,您的场景没有启用深度缓冲。这些构造函数在场景实例 Scene(Parent root,double width,double height,boolean depthBuffer)Scene(Parent root,double width,double height,boolean depthBuffer,SceneAntialiasing antiAliasing) 中启用 3d 功能,两者都将 depthBufer 布尔值设置为 true。第二,如果你想翻译一个节点;翻译它得到它的当前坐标,然后添加新的坐标。这将避免重置坐标。我把拖动的结果除以10,因为它带来的值太高了

    public class Main extends Application {

    private static final int WIDTH = 900;
    private static final int HEIGHT = 600;

    //Tracks drag starting point for x and y
    private double anchorX, anchorY;

    @Override
    public void start(Stage primaryStage) {
        Sphere sphere = new Sphere(50);

        Group group = new Group();
        group.getChildren().add(sphere);

        Camera camera = new PerspectiveCamera();
        // for 3d  Scene constructor must have zbuffer= true and SceneAntialiasing
        Scene scene = new Scene(group, WIDTH, HEIGHT, true, SceneAntialiasing.BALANCED);
        scene.setFill(Color.SILVER);
        scene.setCamera(camera);

        sphere.setTranslateX(WIDTH / 2);
        sphere.setTranslateY(HEIGHT / 2);

        initMouseControl(scene, camera, primaryStage, sphere);

        primaryStage.setTitle("Solar System Simulator");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void initMouseControl(Scene scene, Camera camera, Stage stage, Sphere sphere) {

        scene.setOnMousePressed(event -> {
            //Save start points
            anchorX = event.getSceneX();
            anchorY = event.getSceneY();
        });
        // translating camera from its current coords pluss event 
        scene.setOnMouseDragged(event -> {
            camera.setTranslateY(camera.getTranslateY() + ((anchorY - event.getSceneY()) / 10));
            camera.setTranslateX(camera.getTranslateX() + ((anchorX - event.getSceneX()) / 10));
        });

        stage.addEventHandler(ScrollEvent.SCROLL, event -> {
            sphere.setTranslateZ(sphere.getTranslateZ() + event.getDeltaY());
        });
    }

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