]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/swt/vtkCameraAndSelectorAction.java
Fix camera focus method to handle special case of vertical direction.
[simantics/3d.git] / org.simantics.g3d.vtk / src / org / simantics / g3d / vtk / swt / vtkCameraAndSelectorAction.java
index ebdfb245219a43990271074a2d8f253ffdf774cf..7a6f0d894173ad29e8eebb48be2c18da39ad20e6 100644 (file)
@@ -118,10 +118,10 @@ public class vtkCameraAndSelectorAction extends vtkSwtAction implements ISelecti
                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();
@@ -184,6 +184,25 @@ public class vtkCameraAndSelectorAction extends vtkSwtAction implements ISelecti
                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;
@@ -382,8 +401,15 @@ public class vtkCameraAndSelectorAction extends vtkSwtAction implements ISelecti
        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();