]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/swt/vtkCameraAndSelectorAction.java
Added vtkCameraAndSelectorAction.setViewDir(Vector3d)
[simantics/3d.git] / org.simantics.g3d.vtk / src / org / simantics / g3d / vtk / swt / vtkCameraAndSelectorAction.java
index 7a6f0d894173ad29e8eebb48be2c18da39ad20e6..e177834ed0ae624ba7a78abc2b100f03b62467a7 100644 (file)
@@ -18,6 +18,8 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import javax.vecmath.Vector3d;
+
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.ISelectionChangedListener;
 import org.eclipse.jface.viewers.ISelectionProvider;
@@ -28,6 +30,7 @@ import org.simantics.g3d.tools.AdaptationUtils;
 
 import vtk.vtkCamera;
 import vtk.vtkProp;
+import vtk.vtkProp3D;
 import vtk.vtkRenderWindow;
 import vtk.vtkRenderer;
 
@@ -167,16 +170,13 @@ public class vtkCameraAndSelectorAction extends vtkSwtAction implements ISelecti
                // zoom
                if (this.InteractionMode == 3) {
                        double zoomFactor;
-                       // double clippingRange[];
-
                        zoomFactor = Math.pow(1.02, (y - lastY));
+                       cam.Dolly(zoomFactor);
+                       
                        if (cam.GetParallelProjection() == 1) {
-                               cam.SetParallelScale(cam.GetParallelScale() / zoomFactor);
-                               resetCameraClippingRange();
-                       } else {
-                               cam.Dolly(zoomFactor);
-                               resetCameraClippingRange();
+                               updateParallelScale();
                        }
+                       resetCameraClippingRange();
                }
                lastX = x;
                lastY = y;
@@ -208,16 +208,21 @@ public class vtkCameraAndSelectorAction extends vtkSwtAction implements ISelecti
                double zoomFactor;
                // double clippingRange[];
                zoomFactor = Math.pow(1.02, (e.getWheelRotation()));
-               if (cam.GetParallelProjection() == 1) {
-                       cam.SetParallelScale(cam.GetParallelScale() / zoomFactor);
-               } else {
-                       cam.Dolly(zoomFactor);
-                       resetCameraClippingRange();
-               }
+               cam.Dolly(zoomFactor);
+               updateParallelScale();
+               resetCameraClippingRange();
                panel.refresh();
                return true;
        }
 
+       private void updateParallelScale() {
+               // Make height of parallel projection match the distance
+               double distance = cam.GetDistance();
+               double angle = cam.GetViewAngle();
+               double scale = Math.tan(Math.toRadians(angle / 2)) * distance;
+               cam.SetParallelScale(scale);
+       }
+
        protected List<vtkProp> selectActors = new ArrayList<vtkProp>();
        protected List<vtkProp> hoverActor = new ArrayList<vtkProp>();
 
@@ -415,5 +420,74 @@ public class vtkCameraAndSelectorAction extends vtkSwtAction implements ISelecti
                // panel.UpdateLight();
                UnLock();
        }
+       
+       public void fitToView(Collection<vtkProp3D> props) {
+               if (props.isEmpty())
+                       return;
+               
+               double[] bounds = new double[] { Double.MAX_VALUE, -Double.MAX_VALUE,  Double.MAX_VALUE, -Double.MAX_VALUE,  Double.MAX_VALUE, -Double.MAX_VALUE }, b = new double[6];
+               for (vtkProp3D prop : props) {
+                       prop.GetBounds(b);
+                       for (int i = 0; i < 6; i+=2)
+                               bounds[i] = Math.min(bounds[i], b[i]);
+                       for (int i = 1; i < 6; i+=2)
+                               bounds[i] = Math.max(bounds[i], b[i]);
+               }
+               
+               fitToView(bounds);
+       }
+
+       public void fitToView(double[] bounds) {
+               Vector3d center = new Vector3d((bounds[0] + bounds[1])/2, (bounds[2] + bounds[3])/2, (bounds[4] + bounds[5])/2);
+               Vector3d viewDir = new Vector3d(cam.GetDirectionOfProjection());
+               Vector3d upDir = new Vector3d(cam.GetViewUp());
+               viewDir.normalize();
+               upDir.normalize();
+               Vector3d sideDir = new Vector3d();
+               sideDir.cross(viewDir, upDir);
+               sideDir.normalize();
+               
+               double width = getBoxWidth(bounds, sideDir);
+               double height = getBoxWidth(bounds, upDir);
+               double depth = getBoxWidth(bounds, viewDir);
+               
+               int[] size = rw.GetActualSize();
+               
+               double distance1 = height / 2 / Math.tan(Math.toRadians(cam.GetViewAngle()) / 2);
+               double distance2 = distance1 * (width / size[0] / (height / size[1]));
+               
+               double distance = Math.max(distance1, distance2) + depth / 2;
+               
+               viewDir.scale(-distance);
+               viewDir.add(center);
+               
+               cam.SetPosition(viewDir.x, viewDir.y, viewDir.z);
+               focus(center.x, center.y, center.z);
+               
+               if (cam.GetParallelProjection() == 1) {
+                       cam.SetParallelScale(Math.max(height, width * size[1] / size[0]) / 2);
+               }
+       }
+
+       private static double getBoxWidth(double[] bounds, Vector3d dir) {
+               double dx = bounds[1] - bounds[0];
+               double dy = bounds[3] - bounds[2];
+               double dz = bounds[5] - bounds[4];
+               
+               return Math.abs(dx * dir.x) + Math.abs(dy * dir.y) + Math.abs(dz * dir.z);
+       }
+
+       public void setViewDir(Vector3d direction) {
+               Vector3d focal = new Vector3d(cam.GetFocalPoint());
+               Vector3d pos = new Vector3d(cam.GetPosition());
+               Vector3d dir = new Vector3d(pos);
+               dir.sub(focal);
+               double distance = dir.length();
+               dir.scaleAdd(distance, direction, focal);
+               cam.SetPosition(dir.x, dir.y, dir.z);
+               focus(focal.x, focal.y, focal.z);
+               //panel.UpdateLight();
+               panel.refresh();
+       }
 
 }