I have a 3D box at the origin. I have a camera as well that is moved to the box so that I get to move the camera around the box instead of rotating the box. However, moving the camera using the mouse is working properly (I think), but the zooming function is not working as intended. For example, if I moved the camera on y-axis, then tried to zoom in, the box will move on the y-axis instead of z-axis (pictures attached below).
Initial Box
Box after mouse dragging up and down
Box after zoom-in
As you may see the box gets far down as I zoom-in, and it will goes up as I zoom-out. Now, I think I need to fix the camera point when I zoom-in/-out. Any ideas how to do so? Or anything else that might fix the issue.
public Main3D() {
root = new HBox();
root.setAlignment(Pos.CENTER);
xRotate = new Rotate(0, Rotate.X_AXIS);
yRotate = new Rotate(0, Rotate.Y_AXIS);
currAngleX = new SimpleDoubleProperty(0);
currAngleY = new SimpleDoubleProperty(0);
currAngleZ = new SimpleDoubleProperty(0);
truckMaterial = new PhongMaterial();
}
private void initiate3dSphereScene() {
// Create the container/truck
truck = new Box(Truck.WIDTH, Truck.HEIGHT, Truck.DEPTH);
truckMaterial.setDiffuseColor(Color.SILVER.deriveColor(.3, .3, .4, .3));
truck.setMaterial(truckMaterial);
group = new Group();
group.getChildren().add(truck);
mainScene = new SubScene(group, SCREEN_WIDTH * .75, SCREEN_HEIGHT, true, SceneAntialiasing.BALANCED);
mainScene.setFill(Color.SILVER);
// Set up the camera
camera = new PerspectiveCamera(true);
camera.getTransforms().addAll(xRotate, yRotate, new Translate(0, 0, -40));
camera.setNearClip(1);
camera.setFarClip(100000);
mainScene.setCamera(camera);
initiateMouseControl();
}
private void initiateMouseControl() {
xRotate.angleProperty().bind(currAngleX);
yRotate.angleProperty().bind(currAngleY);
mainScene.setOnMousePressed(mouseEvent -> {
currX = mouseEvent.getSceneX();
currY = mouseEvent.getSceneY();
newX = currAngleX.get();
newY = currAngleY.get();
});
mainScene.setOnMouseDragged(mouseEvent -> {
currAngleX.set(newX + (currY - mouseEvent.getSceneY()));
currAngleY.set(newY - (currX - mouseEvent.getSceneX()));
});
mainScene.addEventHandler(ScrollEvent.SCROLL, event -> {
double zoom = event.getDeltaY();
camera.translateZProperty().set(camera.getTranslateZ() + zoom / 10);
camera.translateYProperty().set(currAngleY.get());
});
mainScene.setOnKeyPressed(KeyEvent -> {
if (KeyEvent.getCode() == KeyCode.C) {
camera.translateXProperty().set(0);
camera.translateXProperty().set(0);
camera.translateZProperty().set(-40);
}
});
}
Changing the FieldOfView
property will do the trick after initializing a PerspectiveCamera
instead of a Camera
object. This will give the impression of zooming in/out.
mainScene.addEventHandler(ScrollEvent.SCROLL, event -> {
double zoomFactor = 1.05;
double deltaY = event.getDeltaY();
if (deltaY < 0) {
zoomFactor = 2.0 - zoomFactor;
}
camera.setFieldOfView(camera.getFieldOfView() / zoomFactor);
});