最简单的通过鼠标旋转相机不起作用

2024-03-31

好吧,这让我发疯。文档非常薄弱,Oracle 的示例应用程序非常奇怪,有一个巨大而复杂的帮助程序类,甚至这里的有关它的问题也没有答案!

我基本上遵循并简化了本教程 https://www.genuinecoder.com/javafx-3d-tutorial-object-transform-rotation-with-mouse/,但我不是旋转对象,而是尝试旋转相机,因此当您拖动鼠标时,它应该绕相机旋转。

然而,尽管我已通过控制台日志和调试确认正在调用事件处理程序,并且所有内容似乎都有正确的值,但我的旋转从未发生!我缺少什么?

此外,我根本无法移动相机,甚至(注释掉)translateX之类的东西也不起作用,所以我很困惑,但无法让轴看起来像除了左上角之外的任何地方!

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Camera;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;

public class RotateCameraExample extends Group {

    private double anchorX, anchorY;
    private double anchorAngleX = 0;
    private double anchorAngleY = 0;
    private DoubleProperty angleX = new SimpleDoubleProperty(0);
    private DoubleProperty angleY = new SimpleDoubleProperty(0);

    Camera camera;
    Group axes;

    public RotateCameraExample() {
        axes = buildAxes();
        getChildren().add(axes);

        camera = new PerspectiveCamera(true);
        camera.setFarClip(6000);
        camera.setNearClip(0.01);
        //camera.translateYProperty().set(300); // this doesn't do anything!  why?

        getChildren().add(camera);
        initMouseControl();
    }

    private void initMouseControl() {
        Rotate xRotate = new Rotate(0, Rotate.X_AXIS);
        Rotate yRotate = new Rotate(0, Rotate.Y_AXIS);
        camera.getTransforms().addAll(xRotate, yRotate);

        xRotate.angleProperty().bind(angleX);
        yRotate.angleProperty().bind(angleY);

        setOnMousePressed(event -> {
            anchorX = event.getSceneX();
            anchorY = event.getSceneY();
            anchorAngleX = angleX.get();
            anchorAngleY = angleY.get();
        });

        setOnMouseDragged(event -> {
            angleX.set(anchorAngleX - (anchorY - event.getSceneY()));
            angleY.set(anchorAngleY + anchorX - event.getSceneX());
        });
    }

    private Group buildAxes() {
        final Box xAxis = new Box(1200, 10, 10);
        final Box yAxis = new Box(10, 1200, 10);
        final Box zAxis = new Box(10, 10, 1200);

        xAxis.setMaterial(new PhongMaterial(Color.RED));
        yAxis.setMaterial(new PhongMaterial(Color.GREEN));
        zAxis.setMaterial(new PhongMaterial(Color.BLUE));

        Group axisGroup = new Group();
        axisGroup.getChildren().addAll(xAxis, yAxis, zAxis);
        return axisGroup;
    }
}

这里可以看到该轴在左上角可见,我希望它在围绕其移动相机时保持在 (0, 0, 0) 处。

这里是Application启动代码,这显然不是问题:

public class TestApp extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        RotateCameraExample g = new RotateCameraExample();
        Scene scene = new Scene(g, 800, 800, Color.BLACK);
        stage.setScene(scene);
        stage.show();
    }
    public static void main(String[] args) {
        launch();
    }
}

代替adding把相机交给孩子们Group,

getChildren().add(camera);

您应该设置场景的相机。

scene.setCamera(g.camera);

您将立即在屏幕中心看到轴。同样,鼠标处理程序应该应用于场景。然后,您可以在场景的处理程序中更新组的变换。

例如,下面的变化会改变相机的旋转以响应鼠标滚动事件。注意垂直鼠标滚动如何影响围绕X轴,而水平鼠标滚动会影响绕轴的旋转Y轴。同样的手势也体现了整个团队的风格。各种各样的键盘命令使人们能够围绕拍摄对象旋转相机Z轴,沿着Z轴,并重置场景。

您可以围绕圆上的点进行平移和旋转,如图所示here https://stackoverflow.com/a/2510048/230513;相比之下,这个相关的example https://stackoverflow.com/a/35240284/230513动画对象绕轴旋转。

import javafx.application.Application;
import javafx.scene.Camera;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;

/**
 * @see https://stackoverflow.com/a/69260181/230513
 */
public class RotateCameraExample extends Application {

    private static class RotateCamera extends Group {

        private final Camera camera;
        private final Rotate xRotate = new Rotate(0, Rotate.X_AXIS);
        private final Rotate yRotate = new Rotate(0, Rotate.Y_AXIS);
        private final Rotate zRotate = new Rotate(0, Rotate.Z_AXIS);

        public RotateCamera() {
            buildAxes();
            camera = new PerspectiveCamera(true);
            camera.setFarClip(6000);
            camera.setNearClip(0.01);
            camera.setTranslateZ(-2000);
            camera.getTransforms().addAll(xRotate, yRotate, zRotate);
        }

        private void buildAxes() {
            final Box xAxis = new Box(1200, 10, 10);
            final Box yAxis = new Box(10, 1200, 10);
            final Box zAxis = new Box(10, 10, 1200);

            xAxis.setMaterial(new PhongMaterial(Color.RED));
            yAxis.setMaterial(new PhongMaterial(Color.GREEN));
            zAxis.setMaterial(new PhongMaterial(Color.BLUE));

            Group axisGroup = new Group();
            axisGroup.getChildren().addAll(xAxis, yAxis, zAxis);
            this.getChildren().add(axisGroup);
        }
    }

    @Override
    public void start(Stage stage) {
        RotateCamera g = new RotateCamera();
        Scene scene = new Scene(g, 800, 800, Color.BLACK);
        scene.setCamera(g.camera);
        stage.setScene(scene);
        stage.show();
        scene.setOnScroll((final ScrollEvent e) -> {
            g.xRotate.setAngle(g.xRotate.getAngle() + e.getDeltaY() / 10);
            g.yRotate.setAngle(g.yRotate.getAngle() - e.getDeltaX() / 10);
            g.setTranslateX(g.getTranslateX() + e.getDeltaX());
            g.setTranslateY(g.getTranslateY() + e.getDeltaY());
        });
        scene.setOnKeyPressed((KeyEvent e) -> {
            KeyCode code = e.getCode();
            switch (code) {
                case LEFT:
                    g.zRotate.setAngle(g.zRotate.getAngle() + 10);
                    break;
                case RIGHT:
                    g.zRotate.setAngle(g.zRotate.getAngle() - 10);
                    break;
                case UP:
                    g.setTranslateZ(g.getTranslateZ() - 100);
                    break;
                case DOWN:
                    g.setTranslateZ(g.getTranslateZ() + 100);
                    break;
                case HOME:
                    g.xRotate.setAngle(0);
                    g.yRotate.setAngle(0);
                    g.zRotate.setAngle(0);
                    g.setTranslateX(0);
                    g.setTranslateY(0);
                    g.setTranslateZ(0);
                    break;
                default:
                    break;
            }
        });
    }

    public static void main(String[] args) {
        launch();
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

最简单的通过鼠标旋转相机不起作用 的相关文章

随机推荐

  • 尝试在 FabricJS 中使用句柄创建对话气泡

    我正在尝试使用 FabricJS 创建一个语音气泡 以集成到 WordPress 插件中 希望 免费发布 以帮助人们注释图像 我在这里找到了原始的气泡 语音气泡 html5 canvas js https stackoverflow com
  • Jetty 和其他容器如何在遵守 Servlet 规范的同时利用 NIO?

    我是 NIO 的新手 我正在尝试弄清楚 Jetty 如何利用 NIO 我对使用 Blocking IO 的传统 servlet 容器如何服务请求的理解如下 请求到达 分配一个线程来处理请求和 servlet 方法 doGet等 被调用 Se
  • ServiceStack:手动调用服务时恢复管道?

    作为后续这个问题 https stackoverflow com questions 64560997 servicestack messaging api can it make a broadcast 我想了解如何改进我对服务的手动调用
  • Wildfly 8.0.0.Final JTA 事务问题

    由于我们在事务中使用了大量 ApplicationScoped bean 但我们不想使用 EJB ApplicationScoped bean 不适用于无状态 bean 因此我们创建自己的事务拦截器 例如 Resource UserTran
  • 使用 C# 重新启动应用程序

    如何使用 C 重新启动我的 WPF 应用程序 我认为 WPF 中没有像 WinForms 中那样的直接方法 但是 您可以使用以下方法Windowns Form像这样的命名空间 您可能需要添加对System Windows Form集会 Sy
  • 在 Mathematica 中查找先前定义的消息

    Mathematica 默认定义了许多有用的消息来表示常见错误 例如使用错误数量的参数调用函数或未找到文件 一般来说 我更喜欢尽可能使用现有的 已定义的消息 因为这样可以更轻松地通过诸如Check Quiet and On Off 然而 我
  • 将应用程序更新到新代码库后,AsyncStorage 是否仍然保留?

    我有一个react native项目中我计划重新编写所有的代码库 新的源代码 我打算使用相同的包 ID 所以我的客户 他们希望用户能够收到有关新应用程序版本的通知 而他们更新后 登录状态将保持 这样用户就不必再次登录 所以我想知道在这种情况
  • Rails 子域路由重定向

    我们无法更改服务器配置文件 因此我们需要在 Rails 级别进行重定向 我对外部站点的路径重定向没有问题 例如 match meow gt redirect http meow com 问题出在子域上 我需要重定向 例如 http my e
  • SPOJ:洗牌

    最近开始解答网上评委的问题 我被困在SPOJ 中的这个问题 http www spoj pl problems CODESPTC 下面是洗 N 张牌的算法 这些牌被分成 K 个相等的牌堆 其中 K 是 N 的因数 底部的 N K 张牌按相同
  • Rails 中的部分 SSL

    我正在寻找在 Rails 中做一个部分 SSL 站点 我基本上想保护 SSL 背后的用户操作 但仅此而已 有人知道有一个插件或 gem 可以让这个变得简单而高效吗 这通常是通过SSL 要求 http github com rails ssl
  • 未收到从 MFMailComposer 发送的附件

    我正在尝试在 iPad 上发送一封带有 csv 附件的电子邮件 我根据下面显示的许多示例使用 MFMailComposer 发送电子邮件时 我可以在 MFMailComposer 窗口中看到正确的文件附件 但是当我收到电子邮件时 没有附加任
  • 创建C# Winform开发生产环境

    我想知道为我的 C winforms 项目正确创建开发和生产环境的最佳方法是什么 不幸的是没有开发环境 相反 每次我希望创建生产或开发版本时 我都必须指定发布路径 此外 由于每个产品或开发版本都使用不同的连接字符串 因此我也必须进入代码并更
  • 错误NG6002:出现在AppModule的NgModule.imports中,但本身有错误

    我在本地和建筑项目中有 Angular 12 它运行良好 没有任何错误 我的本地设置 Angular CLI 12 0 5 Node 12 16 3 Package Manager npm 6 14 4 OS win32 x64 Angul
  • 我可以从存储过程返回 varchar(max) 吗?

    带有 SQL Server 2005 后端的 VB net Web 系统 我有一个返回 varchar 的存储过程 但我们最终得到的值不适合 varchar 8000 我已将返回参数更改为 varchar max 但如何告诉 OleDbPa
  • SQL Server 找出表何时被重命名?

    是否可以查出表何时被重命名 作为首要问题 如果可能的话 是哪个用户干的 你可以试试这个 SELECT Name modify date FROM sys all objects WHERE Name Table name
  • 传递不带等号的查询字符串参数(值为空)是否有效?

    变化1 file jsp parameter1 parameter2 abc 变化2 file jsp parameter1 parameter2 abc 我知道变体 1 被认为是有效的 但是变体 2 被认为是有效的吗 具体来说 参数没有值
  • 使用 zope.schema 定义循环引用

    我正在尝试执行以下操作 定义两个类 其实例相互引用 例如以下示例中的用户和组 一个用户可以属于多个组 一个组可以包含多个用户 实际数据存储在数据库中 这是使用外键的多对多关系的简单问题 完全没问题 然后 数据通过 ORM 加载并存储在 py
  • Google Cloud Builder - Gradle

    继以下帖子后https cloudplatform googleblog com 2017 03 Google Cloud Container Builder a fast and flexible way to package your
  • 是否可以在 Vercel 中部署 NodeJs 应用程序?

    我正在尝试在 Vercel https vercel com https vercel com 之前的 Now 来自 CLI 但是 当我部署应用程序时 我打开站点 结果只是路径目录中的文件 而不是正在运行的应用程序 这是我的server j
  • 最简单的通过鼠标旋转相机不起作用

    好吧 这让我发疯 文档非常薄弱 Oracle 的示例应用程序非常奇怪 有一个巨大而复杂的帮助程序类 甚至这里的有关它的问题也没有答案 我基本上遵循并简化了本教程 https www genuinecoder com javafx 3d tu