int y = e.getY();
// rotate
if (this.InteractionMode == 1) {
- cam.Azimuth(lastX - x);
- cam.Elevation(y - lastY);
+ cam.Elevation(clampElevationDelta(y - lastY));
if (doNotRotate)
cam.SetViewUp(upDirection);
+ cam.Azimuth(lastX - x);
cam.OrthogonalizeViewUp();
resetCameraClippingRange();
// panel.UpdateLight();
return true;
}
+ private static double dot(double[] a, double[] b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+ }
+
+ /** Calculate change in elevation, clamped to vertical directions. */
+ private double clampElevationDelta(double elevationDelta) {
+ if (!doNotRotate)
+ return elevationDelta;
+
+ double[] direction = cam.GetDirectionOfProjection();
+ double d = Math.min(1.0, Math.max(-1.0, dot(direction, upDirection)));
+ double elevation = Math.toDegrees(Math.acos(d)) + elevationDelta;
+ if (elevation < 0)
+ elevationDelta -= elevation - 1e-5;
+ else if (elevation > 180)
+ elevationDelta -= elevation - 180 + 1e-5;
+ return elevationDelta;
+ }
+
@Override
public boolean mouseWheelMoved(MouseWheelEvent e) {
double zoomFactor;
public void focus(double x, double y, double z) {
Lock();
cam.SetFocalPoint(x, y, z);
- if (doNotRotate)
- cam.SetViewUp(upDirection);
+ if (doNotRotate) {
+ double[] proj = cam.GetDirectionOfProjection();
+ if (Math.abs(proj[1] * upDirection[2] - proj[2] * upDirection[1]) < 1e-6 &&
+ Math.abs(proj[2] * upDirection[0] - proj[0] * upDirection[2]) < 1e-6 &&
+ Math.abs(proj[0] * upDirection[1] - proj[1] * upDirection[0]) < 1e-6)
+ cam.SetViewUp(upDirection[1], upDirection[2], upDirection[0]);
+ else
+ cam.SetViewUp(upDirection);
+ }
cam.OrthogonalizeViewUp();
resetCameraClippingRange();
// panel.UpdateLight();