我非常坚持我的应用程序,我没有看到任何有人在做我正在做的事情的例子。 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);
}