1

我非常坚持我的应用程序,我没有看到任何有人在做我正在做的事情的例子。 https://www.dropbox.com/sh/lqzoegg5v8drzog/nLxDuIVAh0

我有一个 3D 世界,我将 TriagleMesh 对象从 STL 文件加载到 3D 世界中。3D 世界是使用 Oracle 使用 xforms 的许多示例创建的。我可以在 3D 世界中转动相机,一切都很好。

当 3D 世界向右有 X+ 并且我用鼠标向右移动我的对象时,对象实际上是向右移动的。当我转动世界以使 X+ 向左移动时,当我将鼠标向右移动时,对象向左移动

应用程序当前在 MouseEvent 拖动事件处理程序上使用 getScreenX 和 getScreenY。我已经尝试过 getSceneX 和 getSceneY 并且它的行为方式相同。当我使用 getX 和 getY 时,对象会到处乱跳,从 getX 和 getY 返回的坐标会不断变化。这很可能是因为对象正在移动,并且 getX 和 getY 坐标返回鼠标在移动之前相对于对象的位置。假设我确实使用了 getX 和 getY 并且我旋转了对象,然后它的坐标系发生了变化。如果它在右边有 X+,它将在左边。因此,如果我然后尝试将对象向右移动,它会向左移动

我想我需要使用 getScreenX/Y 然后根据相机的旋转以某种方式转换鼠标坐标。我将如何在 JavaFX 中做到这一点?

编辑 1 排序

我在这个 jira https://javafx-jira.kenai.com/browse/RT-35178中获得了以下代码

final Rectangle mousePlane = new Rectangle(800, 800, Color.TRANSPARENT);
mousePlane.setMouseTransparent(true);
mousePlane.setDepthTest(DepthTest.DISABLE); // this makes the plane to be picked even if there are objects closer to the camera
// + translation and rotation so it's parallel to your plane

When an object is dragged, it does this:

cube.setOnDragDetected(new EventHandler<MouseEvent>() {
    @Override public void handle(MouseEvent event) {
        cube.setMouseTransparent(true); // cube will not be picked
        mousePlane.setMouseTransparent(false); // mousePlane will be pickable
        cube.startFullDrag(); // see javadoc, this redirects drag events from the origin (cube) to the picked target (which will be mousePlane)
    }
});

+ some cleanup:

cube.setOnMouseReleased(new EventHandler<MouseEvent>() {
    @Override public void handle(MouseEvent event) {
        cube.setMouseTransparent(false);
        mousePlane.setMouseTransparent(true);
    }
});

and now the movement itself:

        mousePlane.setOnMouseDragOver(new EventHandler<MouseDragEvent>() {
            @Override public void handle(MouseDragEvent event) {
                Point3D coords = event.getPickResult().getIntersectedPoint();
                double x = coords.getX();
                double y = coords.getY();
                double z = coords.getZ();

                coords = mousePlane.localToParent(new Point3D(x, y, z)); //mouseplane has the same parent as the real plane and objects like cube

                // You might need to adjust this depending on your hierarchy and transformations
                cube.setTranslateX(coords.getX());
                cube.setTranslateY(coords.getY());
                cube.setTranslateZ(coords.getZ());
            }
        });

我所做的是将拖动检测到的代码放在我的 Gizmo 对象中。Gizmo 会将 MouseTransparent 设置为 true 并 startFullDrag。然后它调用 GizmoViewer 以便 GizmoViewer 可以设置 mousePlane MouseTransparent。这允许鼠标平面而不是 Gizmo 检测到拖动。我还在 GizmoViewer 中设置了一个标志 dragJustStarted = true; 然后当我开始拖动并且在 mousePlane 上触发 OnMouseDragOver 时,它将设置 mouseOldX、mousePosX、mouseOldY、mousePosY 的值,如果它检测到这是第一次执行拖动,它将退出。当拖动再次执行时,我拥有所有正确的鼠标值,我可以微笑着拖动

鼠标平面的设置

private void setupMousePlane() {

    mousePlane.setLayoutX(-800 / 2);
    mousePlane.setLayoutY(-800 / 2);
    mousePlane.setOpacity(0.7);
    mousePlane.setMouseTransparent(true);
    mousePlane.setDepthTest(DepthTest.DISABLE); // this makes the plane to be picked even if there are objects closer to the camera

    mousePlane.setOnMouseDragOver(new EventHandler<MouseDragEvent>() {
        @Override
        public void handle(MouseDragEvent me) {
            if (me.isPrimaryButtonDown() && me.isShiftDown()) {
                //do nothing, we are rotating on the gizmo
            } else if (me.isPrimaryButtonDown()) {
                Point3D coords = me.getPickResult().getIntersectedPoint();
                mouseOldX = mousePosX;
                mouseOldY = mousePosY;
                mousePosX = coords.getX();
                mousePosY = coords.getY();

                double z = coords.getZ();

                coords = mousePlane.localToParent(new Point3D(mousePosX, mousePosY, z)); //mouseplane has the same parent as the real plane and objects like cube
                mousePosX = coords.getX();
                mousePosY = coords.getY();
                mouseDeltaX = (mousePosX - mouseOldX);
                mouseDeltaY = (mousePosY - mouseOldY);

                if (dragJustStarted) {
                    dragJustStarted = false;
                } else {

                    double modifier = 10;
                    double modifierFactor = 0.15;
                    double yFlip = 1.0;
                    double flip = -1.0;

                    for (Gizmo gizmo : gizmoSelectionHelper.getSelection()) {
                        gizmo.getGizmoXform2().t.setX(gizmo.getGizmoXform2().t.getX() - flip * mouseDeltaX * modifierFactor * modifier * 0.3);  // -
                        gizmo.getGizmoXform2().t.setY(gizmo.getGizmoXform2().t.getY() + yFlip * mouseDeltaY * modifierFactor * modifier * 0.3);  // -
                        configureGizmoPivot(gizmo);
                    }
                }
            }
        }
    });

    world.getChildren().addAll(mousePlane);
}

检测到 Gizmo/屏幕对象拖动

private final EventHandler mouseDragDetectedHandler = new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent me) {
        if (me.isPrimaryButtonDown()) {
            Gizmo gizmo = (Gizmo) me.getSource();
            gizmo.setMouseTransparent(true);
            gizmo.startFullDrag();
            gizmo.getGizmoViewer().startDraggingGizmo(me);
        }
    }
};

释放 Gizmo 鼠标(对这个问题很重要的方法刚刚开始)

private final EventHandler mouseReleasedHandler = new EventHandler<MouseEvent>() {

    @Override
    public void handle(MouseEvent me) {
        Gizmo gizmo = (Gizmo) me.getSource();
        if (MouseButton.PRIMARY == me.getButton()) {
            gizmo.setMouseTransparent(false);
            gizmo.getGizmoViewer().stopDraggingGizmo();

小工具查看器

public void startDraggingGizmo(MouseEvent me) {
    // mousePlane will be pickable
    mousePlane.setMouseTransparent(false);

    dragJustStarted = true;
}

public void stopDraggingGizmo() {
    mousePlane.setMouseTransparent(true);
}
4

0 回答 0