【发布时间】:2018-12-07 22:40:08
【问题描述】:
我有一个项目正在尝试为其开发控件。我需要能够通过单击鼠标并拖动和释放来连续旋转对象。释放后,我希望对象继续从其初始点旋转到我释放鼠标的位置。(前提是对象尚未到达此位置。)我以前见过以这种方式工作的应用程序,但我似乎不能在线查找任何代码以显示它是如何实现的。在将鼠标控件添加到我的项目之前,我正在使用下面的代码来测试它们。它已经包含简单的拖放机制。但是,对于如何添加连续旋转,我将不胜感激。我希望鼠标能够控制对象沿任意轴的旋转速度。正如我设置的那样,它沿任何轴旋转。但是我想要拖动而不是旋转对象,使对象以与拖动鼠标的距离成比例的速度旋转(递归旋转)。这将随着距离的增加而增加速度。如果我将相同的方向拖动两次相同的距离,速度应该会加倍,然后物体会以两倍的速度旋转。
package javafxapplication3;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.geometry.Point3D;
import javafx.scene.DepthTest;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Sphere;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Transform;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
public class trafo extends Application {
final Group root = new Group();
final XformWorld world = new XformWorld();
final PerspectiveCamera camera = new PerspectiveCamera(true);
final XformCamera cameraXform = new XformCamera();
private static final double CAMERA_INITIAL_DISTANCE = -1000;
private static final double CAMERA_NEAR_CLIP = 0.1;
private static final double CAMERA_FAR_CLIP = 10000.0;
double mousePosX, mousePosY, mouseOldX, mouseOldY, mouseDeltaX, mouseDeltaY;
double mouseFactorX, mouseFactorY;
@Override
public void start(Stage primaryStage) {
root.getChildren().add(world);
root.setDepthTest(DepthTest.ENABLE);
buildCamera();
buildBodySystem();
Scene scene = new Scene(root, 800, 600, true);
scene.setFill(Color.GREY);
handleMouse(scene);
primaryStage.setTitle("TrafoTest");
primaryStage.setScene(scene);
primaryStage.show();
scene.setCamera(camera);
mouseFactorX = 180.0 / scene.getWidth();
mouseFactorY = 180.0 / scene.getHeight();
}
private void buildCamera() {
root.getChildren().add(cameraXform);
cameraXform.getChildren().add(camera);
camera.setNearClip(CAMERA_NEAR_CLIP);
camera.setFarClip(CAMERA_FAR_CLIP);
camera.setTranslateZ(CAMERA_INITIAL_DISTANCE);
}
private void buildBodySystem() {
PhongMaterial whiteMaterial = new PhongMaterial();
whiteMaterial.setDiffuseColor(Color.WHITE);
whiteMaterial.setSpecularColor(Color.LIGHTBLUE);
Box box = new Box(400, 200, 100);
box.setMaterial(whiteMaterial);
PhongMaterial redMaterial = new PhongMaterial();
redMaterial.setDiffuseColor(Color.DARKRED);
redMaterial.setSpecularColor(Color.RED);
Sphere sphere = new Sphere(5);
sphere.setMaterial(redMaterial);
sphere.setTranslateX(200.0);
sphere.setTranslateY(-100.0);
sphere.setTranslateZ(-50.0);
world.getChildren().addAll(box);
world.getChildren().addAll(sphere);
}
private void handleMouse(Scene scene) {
scene.setOnMousePressed((MouseEvent me) -> {
mousePosX = me.getSceneX();
mousePosY = me.getSceneY();
mouseOldX = me.getSceneX();
mouseOldY = me.getSceneY();
});
scene.setOnMouseDragged((MouseEvent me) -> {
mouseOldX = mousePosX;
mouseOldY = mousePosY;
mousePosX = me.getSceneX();
mousePosY = me.getSceneY();
mouseDeltaX = (mousePosX - mouseOldX);
mouseDeltaY = (mousePosY - mouseOldY);
if (me.isPrimaryButtonDown()) {
cameraXform.ry(mouseDeltaX * 180.0 / scene.getWidth());
cameraXform.rx(-mouseDeltaY * 180.0 / scene.getHeight());
} else if (me.isSecondaryButtonDown()) {
camera.setTranslateZ(camera.getTranslateZ() + mouseDeltaY);
}
});
}
public static void main(String[] args) {
launch(args);
}
}
class XformWorld extends Group {
final Translate t = new Translate(0.0, 0.0, 0.0);
final Rotate rx = new Rotate(0, 0, 0, 0, Rotate.X_AXIS);
final Rotate ry = new Rotate(0, 0, 0, 0, Rotate.Y_AXIS);
final Rotate rz = new Rotate(0, 0, 0, 0, Rotate.Z_AXIS);
public XformWorld() {
super();
this.getTransforms().addAll(t, rx, ry, rz);
}
}
class XformCamera extends Group {
Point3D px = new Point3D(1.0, 0.0, 0.0);
Point3D py = new Point3D(0.0, 1.0, 0.0);
Rotate r;
Transform t = new Rotate();
public XformCamera() {
super();
}
public void rx(double angle) {
r = new Rotate(angle, px);
this.t = t.createConcatenation(r);
this.getTransforms().clear();
this.getTransforms().addAll(t);
}
public void ry(double angle) {
r = new Rotate(angle, py);
this.t = t.createConcatenation(r);
this.getTransforms().clear();
this.getTransforms().addAll(t);
}
}
【问题讨论】:
-
"释放后我希望对象继续从其初始点旋转到我释放鼠标的位置。" 这是什么意思?举个例子吧。
-
澄清一下,我想要类似于 google earth 的旋转:google.com/earth 只是我希望旋转以与松开鼠标时相同的速度继续。我想我的意思是我想要一个旋转速度。也许这就像启动对 my rotate_x 和 rotate_y 函数的递归调用以响应鼠标释放事件一样简单?我需要计算一个旋转速度。这应该基于我拖动的速度,但也是我放开鼠标的即时性。这样图像就没有赶上它@user1803551
-
"我需要计算一个旋转速度。这应该基于我拖动的速度,以及我放开鼠标的即时性。"那是什么计算?我们不能告诉你你想要什么。您必须具体说明您希望它如何工作。 Edit您的问题及相关细节。
-
@user1803551 编辑更有帮助吗?我相信它的速度可以像计算 mouseDelta_X 和 mouseDelta_Y 一样计算。
-
所以当你拖动鼠标时,在释放之前,什么都没有发生?只有在释放时对象才会开始旋转?
标签: animation javafx 3d rotation javafx-8