X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.g3d.vtk%2Fsrc%2Forg%2Fsimantics%2Fg3d%2Fvtk%2Fswt%2FvtkCameraAndSelectorAction.java;h=a5ea614978ee803a6df23c252205ad583f0a1622;hb=370a955304d3aeacfdd59aa42d875c6142499dfd;hp=5b3e3a1fffe1ec2673039316ebb57dae685235a1;hpb=84132a1d750c45f9161afbd58b78572964e50d26;p=simantics%2F3d.git diff --git a/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/swt/vtkCameraAndSelectorAction.java b/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/swt/vtkCameraAndSelectorAction.java index 5b3e3a1f..a5ea6149 100644 --- a/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/swt/vtkCameraAndSelectorAction.java +++ b/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/swt/vtkCameraAndSelectorAction.java @@ -13,10 +13,13 @@ package org.simantics.g3d.vtk.swt; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; 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; @@ -27,22 +30,24 @@ import org.simantics.g3d.tools.AdaptationUtils; import vtk.vtkCamera; import vtk.vtkProp; +import vtk.vtkProp3D; import vtk.vtkRenderWindow; import vtk.vtkRenderer; public class vtkCameraAndSelectorAction extends vtkSwtAction implements ISelectionProvider { - + protected vtkRenderer ren; protected int lastX; protected int lastY; protected vtkRenderWindow rw; protected vtkCamera cam; protected int InteractionMode = 1; - + protected double activeRate = 5.0; protected double passiveRate = 0.01; - protected boolean doNotRotate = true; - + protected boolean doNotRotate = true; + private double[] upDirection = new double[] { 0, 1, 0 }; + public vtkCameraAndSelectorAction(InteractiveVtkComposite panel) { super(panel); this.ren = panel.getRenderer(); @@ -50,350 +55,426 @@ public class vtkCameraAndSelectorAction extends vtkSwtAction implements ISelecti this.cam = ren.GetActiveCamera(); } + public void setUpDirection(double[] upDirection) { + this.upDirection = upDirection; + } + public void Lock() { panel.lock(); } - + public void UnLock() { panel.unlock(); } - - public void InteractionModeRotate() - { - this.InteractionMode = 1; - } - - public void InteractionModeTranslate() - { - this.InteractionMode = 2; - } - - public void InteractionModeZoom() - { - this.InteractionMode = 3; - } - + + public void InteractionModeRotate() { + this.InteractionMode = 1; + } + + public void InteractionModeTranslate() { + this.InteractionMode = 2; + } + + public void InteractionModeZoom() { + this.InteractionMode = 3; + } + public void resetCameraClippingRange() { - Lock(); - ren.ResetCameraClippingRange(); - UnLock(); - } - - public void resetCamera() { - Lock(); - ren.ResetCamera(); - UnLock(); - } - - public boolean mousePressed(MouseEvent e) - { - - if (ren.VisibleActorCount() == 0) return false; - rw.SetDesiredUpdateRate(activeRate); - lastX = e.getX(); - lastY = e.getY(); - if ((e.getModifiers()==InputEvent.BUTTON2_MASK) || - (e.getModifiers()==(InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK))) - { - InteractionModeTranslate(); - } - else if (e.getModifiers()==InputEvent.BUTTON3_MASK) - { - InteractionModeZoom(); - } - else - { - InteractionModeRotate(); - } - return true; - } - - public boolean mouseReleased(MouseEvent e) - { - rw.SetDesiredUpdateRate(passiveRate); - return true; - } - - - - public boolean mouseDragged(MouseEvent e) - { - if (ren.VisibleActorCount() == 0) return false; - int x = e.getX(); - int y = e.getY(); - // rotate - if (this.InteractionMode == 1) - { - cam.Azimuth(lastX - x); - cam.Elevation(y - lastY); - if (doNotRotate) - cam.SetRoll(0); - cam.OrthogonalizeViewUp(); - resetCameraClippingRange(); - //panel.UpdateLight(); - } - // translate - if (this.InteractionMode == 2) - { - double FPoint[]; - double PPoint[]; - double APoint[] = new double[3]; - double RPoint[]; - double focalDepth; - - // get the current focal point and position - FPoint = cam.GetFocalPoint(); - PPoint = cam.GetPosition(); - - // calculate the focal depth since we'll be using it a lot - ren.SetWorldPoint(FPoint[0],FPoint[1],FPoint[2],1.0); - ren.WorldToDisplay(); - focalDepth = ren.GetDisplayPoint()[2]; - - APoint[0] = rw.GetSize()[0]/2.0 + (x - lastX); - APoint[1] = rw.GetSize()[1]/2.0 - (y - lastY); - APoint[2] = focalDepth; - ren.SetDisplayPoint(APoint); - ren.DisplayToWorld(); - RPoint = ren.GetWorldPoint(); - if (RPoint[3] != 0.0) - { - RPoint[0] = RPoint[0]/RPoint[3]; - RPoint[1] = RPoint[1]/RPoint[3]; - RPoint[2] = RPoint[2]/RPoint[3]; - } - - /* - * Compute a translation vector, moving everything 1/2 - * the distance to the cursor. (Arbitrary scale factor) - */ - cam.SetFocalPoint( - (FPoint[0]-RPoint[0])/2.0 + FPoint[0], - (FPoint[1]-RPoint[1])/2.0 + FPoint[1], - (FPoint[2]-RPoint[2])/2.0 + FPoint[2]); - cam.SetPosition( - (FPoint[0]-RPoint[0])/2.0 + PPoint[0], - (FPoint[1]-RPoint[1])/2.0 + PPoint[1], - (FPoint[2]-RPoint[2])/2.0 + PPoint[2]); - resetCameraClippingRange(); - } - // zoom - if (this.InteractionMode == 3) - { - double zoomFactor; - //double clippingRange[]; - - zoomFactor = Math.pow(1.02,(y - lastY)); - if (cam.GetParallelProjection() == 1) - { - cam.SetParallelScale(cam.GetParallelScale()/zoomFactor); - } - else - { - cam.Dolly(zoomFactor); - resetCameraClippingRange(); - } - } - lastX = x; - lastY = y; - panel.refresh(); - return true; - } - - - private List selectActors = new ArrayList(); - private List hoverActor = new ArrayList(); - - @Override - public boolean mouseClicked(MouseEvent e) { - if (!panel.getComponent().isFocusControl()) - return false; - if (e.getButton() != MouseEvent.BUTTON1) - return false; - vtkProp spick[] = panel.pick(e.getX(), e.getY()); - if (spick != null && spick.length > 0) { - for (vtkProp selectActor : spick) { - if (!e.isControlDown()) { - selectActors.clear(); - selectActors.add(selectActor); - } else { - if (selectActors.contains(selectActor)) - selectActors.remove(selectActor); - else - selectActors.add(selectActor); - } - } - fireSelectionChanged(); - } else if (!e.isControlDown()) { - selectActors.clear(); - fireSelectionChanged(); - } - return true; -// if (e.getClickCount() > 1) -// updatePickRay(e.getX(), e.getY()); - + Lock(); + ren.ResetCameraClippingRange(); + UnLock(); + } + + public void resetCamera() { + Lock(); + ren.ResetCamera(); + UnLock(); + } + + public boolean mousePressed(MouseEvent e) { + + if (ren.VisibleActorCount() == 0) + return false; + rw.SetDesiredUpdateRate(activeRate); + lastX = e.getX(); + lastY = e.getY(); + if ((e.getModifiers() == InputEvent.BUTTON2_MASK) + || (e.getModifiers() == (InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK))) { + InteractionModeTranslate(); + } else if (e.getModifiers() == InputEvent.BUTTON3_MASK) { + InteractionModeZoom(); + } else { + InteractionModeRotate(); } - -// private void updatePickRay(double x , double y) { -// Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(), x, y); -// -// -// System.out.println(ray.pos + " " + ray.dir); -// vtkPoints linePoints = new vtkPoints(); -// linePoints.InsertPoint(0,ray.pos.x, ray.pos.y, ray.pos.z); -// linePoints.InsertPoint(1, ray.pos.x + ray.dir.x, ray.pos.y + ray.dir.y, ray.pos.z + ray.dir.z); -// vtkLine aLine = new vtkLine(); -// aLine.GetPointIds().SetId(0, 0); -// aLine.GetPointIds().SetId(1, 1); -// vtkUnstructuredGrid aLineGrid = new vtkUnstructuredGrid(); -// aLineGrid.Allocate(1, 1); -// aLineGrid.InsertNextCell(aLine.GetCellType(), aLine.GetPointIds()); -// aLineGrid.SetPoints(linePoints); -// vtkDataSetMapper aLineMapper = new vtkDataSetMapper(); -// aLineMapper.SetInput(aLineGrid); -// vtkActor aLineActor = new vtkActor(); -// aLineActor.SetMapper(aLineMapper); -// aLineActor.GetProperty().SetDiffuseColor(.2, 1, 1); -// -// if (rayActor != null) { -// panel.GetRenderer().RemoveActor(rayActor); -// rayActor.Delete(); -// } -// rayActor = aLineActor; -// panel.GetRenderer().AddActor(rayActor); -// -// linePoints.Delete(); -// aLine.Delete(); -// aLineGrid.Delete(); -// aLineMapper.Delete(); -// panel.repaint(); -// } -// -// private vtkActor rayActor; - - @Override - public boolean mouseMoved(MouseEvent e) { - lastX = e.getX(); - lastY = e.getY(); - - if (!panel.getComponent().isFocusControl()) - return false; - List prevHover = new ArrayList(); - prevHover.addAll(hoverActor); - hoverActor.clear(); - vtkProp pick[] = panel.pick(e.getX(),e.getY()); - if (pick != null) { - for (vtkProp p : pick) - hoverActor.add(p); + return true; + } + + public boolean mouseReleased(MouseEvent e) { + rw.SetDesiredUpdateRate(passiveRate); + return true; + } + + public boolean mouseDragged(MouseEvent e) { + if (ren.VisibleActorCount() == 0) + return false; + int x = e.getX(); + int y = e.getY(); + // rotate + if (this.InteractionMode == 1) { + cam.Elevation(clampElevationDelta(y - lastY)); + if (doNotRotate) + cam.SetViewUp(upDirection); + cam.Azimuth(lastX - x); + cam.OrthogonalizeViewUp(); + resetCameraClippingRange(); + // panel.UpdateLight(); + } + // translate + if (this.InteractionMode == 2) { + double FPoint[]; + double PPoint[]; + double APoint[]; + double RPoint[]; + + // get the current focal point and position + FPoint = cam.GetFocalPoint(); + PPoint = cam.GetPosition(); + + // calculate the focal depth since we'll be using it a lot + ren.SetWorldPoint(FPoint[0], FPoint[1], FPoint[2], 1.0); + ren.WorldToDisplay(); + APoint = ren.GetDisplayPoint(); + +// int[] size = rw.GetSize(); + APoint[0] -= x - lastX; + APoint[1] += y - lastY; + ren.SetDisplayPoint(APoint); + ren.DisplayToWorld(); + RPoint = ren.GetWorldPoint(); + + if (RPoint[3] != 0.0) { + RPoint[0] = RPoint[0] / RPoint[3]; + RPoint[1] = RPoint[1] / RPoint[3]; + RPoint[2] = RPoint[2] / RPoint[3]; } - - if (!prevHover.containsAll(hoverActor) || !hoverActor.containsAll(prevHover)) { - fireHoverChanged(); + + /* + * Compute a translation vector, moving everything 1/2 the distance to the + * cursor. (Arbitrary scale factor) + */ + cam.SetFocalPoint(RPoint); + cam.SetPosition((RPoint[0] - FPoint[0]) + PPoint[0], (RPoint[1] - FPoint[1]) + PPoint[1], + (RPoint[2] - FPoint[2]) + PPoint[2]); + resetCameraClippingRange(); + } + // zoom + if (this.InteractionMode == 3) { + double zoomFactor; + zoomFactor = Math.pow(1.02, (y - lastY)); + cam.Dolly(zoomFactor); + + if (cam.GetParallelProjection() == 1) { + updateParallelScale(); } - return true; + resetCameraClippingRange(); } + lastX = x; + lastY = y; + panel.refresh(); + 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; - public List getSelectActor() { - return selectActors; + 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; + // double clippingRange[]; + zoomFactor = Math.pow(1.02, (e.getWheelRotation())); + 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 selectActors = new ArrayList(); + protected List hoverActor = new ArrayList(); + + @Override + public boolean mouseClicked(MouseEvent e) { + if (!panel.getComponent().isFocusControl()) + return false; + if (e.getButton() != MouseEvent.BUTTON1) + return false; + vtkProp spick[] = panel.pick(e.getX(), e.getY()); + if (spick != null && spick.length > 0) { + for (vtkProp selectActor : spick) { + if (!e.isControlDown()) { + selectActors.clear(); + selectActors.add(selectActor); + } else { + if (selectActors.contains(selectActor)) + selectActors.remove(selectActor); + else + selectActors.add(selectActor); + } + } + fireSelectionChanged(); + } else if (!e.isControlDown()) { + selectActors.clear(); + fireSelectionChanged(); } - - public List getHoverActor() { - return hoverActor; + return true; + // if (e.getClickCount() > 1) + // updatePickRay(e.getX(), e.getY()); + + } + + // private void updatePickRay(double x , double y) { + // Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(), x, y); + // + // + // System.out.println(ray.pos + " " + ray.dir); + // vtkPoints linePoints = new vtkPoints(); + // linePoints.InsertPoint(0,ray.pos.x, ray.pos.y, ray.pos.z); + // linePoints.InsertPoint(1, ray.pos.x + ray.dir.x, ray.pos.y + ray.dir.y, + // ray.pos.z + ray.dir.z); + // vtkLine aLine = new vtkLine(); + // aLine.GetPointIds().SetId(0, 0); + // aLine.GetPointIds().SetId(1, 1); + // vtkUnstructuredGrid aLineGrid = new vtkUnstructuredGrid(); + // aLineGrid.Allocate(1, 1); + // aLineGrid.InsertNextCell(aLine.GetCellType(), aLine.GetPointIds()); + // aLineGrid.SetPoints(linePoints); + // vtkDataSetMapper aLineMapper = new vtkDataSetMapper(); + // aLineMapper.SetInput(aLineGrid); + // vtkActor aLineActor = new vtkActor(); + // aLineActor.SetMapper(aLineMapper); + // aLineActor.GetProperty().SetDiffuseColor(.2, 1, 1); + // + // if (rayActor != null) { + // panel.GetRenderer().RemoveActor(rayActor); + // rayActor.Delete(); + // } + // rayActor = aLineActor; + // panel.GetRenderer().AddActor(rayActor); + // + // linePoints.Delete(); + // aLine.Delete(); + // aLineGrid.Delete(); + // aLineMapper.Delete(); + // panel.repaint(); + // } + // + // private vtkActor rayActor; + + @Override + public boolean mouseMoved(MouseEvent e) { + lastX = e.getX(); + lastY = e.getY(); + + if (!panel.getComponent().isFocusControl()) + return false; + List prevHover = new ArrayList(); + prevHover.addAll(hoverActor); + hoverActor.clear(); + vtkProp pick[] = panel.pick(e.getX(), e.getY()); + if (pick != null) { + for (vtkProp p : pick) + hoverActor.add(p); } - - private List selectionListeners = new ArrayList(); - - @Override - public void addSelectionChangedListener(ISelectionChangedListener listener) { - selectionListeners.add(listener); + + if (!prevHover.containsAll(hoverActor) || !hoverActor.containsAll(prevHover)) { + fireHoverChanged(); } - - @Override - public ISelection getSelection() { - return new StructuredSelection(selectActors); + return true; + } + + public List getSelectActor() { + return selectActors; + } + + public List getHoverActor() { + return hoverActor; + } + + private List selectionListeners = new ArrayList(); + + @Override + public void addSelectionChangedListener(ISelectionChangedListener listener) { + selectionListeners.add(listener); + } + + @Override + public ISelection getSelection() { + return new StructuredSelection(selectActors); + } + + @Override + public void removeSelectionChangedListener(ISelectionChangedListener listener) { + selectionListeners.remove(listener); + } + + @Override + public void setSelection(ISelection selection) { + setSelection(selection, false); + + } + + public void setSelection(ISelection selection, boolean fire) { + Collection selectedProps = AdaptationUtils.adaptToCollection(selection, vtkProp.class); + + selectActors.clear(); + selectActors.addAll(selectedProps); + if (fire) + fireSelectionChanged(); + } + + protected void fireSelectionChanged() { + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + + SelectionChangedEvent evt = new SelectionChangedEvent(vtkCameraAndSelectorAction.this, + new StructuredSelection(selectActors)); + for (ISelectionChangedListener l : selectionListeners) { + l.selectionChanged(evt); + } + + } + }); + } + + private List hoverListeners = new ArrayList(); + + public void addHoverChangedListener(ISelectionChangedListener listener) { + hoverListeners.add(listener); + } + + public ISelection getHoverSelection() { + return new StructuredSelection(hoverActor); + } + + public void removeHoverChangedListener(ISelectionChangedListener listener) { + hoverListeners.remove(listener); + } + + private void fireHoverChanged() { + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + StructuredSelection sel = null; + if (hoverActor == null) + sel = new StructuredSelection(); + else + sel = new StructuredSelection(hoverActor); + SelectionChangedEvent evt = new SelectionChangedEvent(vtkCameraAndSelectorAction.this, sel); + for (ISelectionChangedListener l : hoverListeners) { + l.selectionChanged(evt); + } + + } + }); + } + + public void focus(double x, double y, double z) { + Lock(); + cam.SetFocalPoint(x, y, z); + 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(); + UnLock(); + } + + public void fitToView(Collection props) { + if (props.isEmpty()) + return; - @Override - public void removeSelectionChangedListener( - ISelectionChangedListener listener) { - selectionListeners.remove(listener); + 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]); } - @Override - public void setSelection(ISelection selection) { - setSelection(selection, false); + 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(); - public void setSelection(ISelection selection, boolean fire) { - Collection selectedProps = AdaptationUtils.adaptToCollection(selection, vtkProp.class); - - selectActors.clear(); - selectActors.addAll(selectedProps); - if (fire) - fireSelectionChanged(); - } + double width = getBoxWidth(bounds, sideDir); + double height = getBoxWidth(bounds, upDir); + double depth = getBoxWidth(bounds, viewDir); - private void fireSelectionChanged() { - Display.getDefault().asyncExec(new Runnable() { - @Override - public void run() { - - SelectionChangedEvent evt = new SelectionChangedEvent(vtkCameraAndSelectorAction.this, new StructuredSelection(selectActors)); - for (ISelectionChangedListener l :selectionListeners) { - l.selectionChanged(evt); - } - - } - }); - } + int[] size = rw.GetActualSize(); + double distance1 = height / 2 / Math.tan(Math.toRadians(cam.GetViewAngle()) / 2); + double distance2 = distance1 * (width / size[0] / (height / size[1])); - private List hoverListeners = new ArrayList(); - - - public void addHoverChangedListener(ISelectionChangedListener listener) { - hoverListeners.add(listener); - } + double distance = Math.max(distance1, distance2) + depth / 2; + viewDir.scale(-distance); + viewDir.add(center); - public ISelection getHoverSelection() { - return new StructuredSelection(hoverActor); - } + cam.SetPosition(viewDir.x, viewDir.y, viewDir.z); + focus(center.x, center.y, center.z); - public void removeHoverChangedListener( - ISelectionChangedListener listener) { - hoverListeners.remove(listener); + if (cam.GetParallelProjection() == 1) { + cam.SetParallelScale(Math.max(height, width * size[1] / size[0]) / 2); } + } - private void fireHoverChanged() { - Display.getDefault().asyncExec(new Runnable() { - @Override - public void run() { - StructuredSelection sel = null; - if (hoverActor == null) - sel = new StructuredSelection(); - else - sel = new StructuredSelection(hoverActor); - SelectionChangedEvent evt = new SelectionChangedEvent(vtkCameraAndSelectorAction.this, sel); - for (ISelectionChangedListener l :hoverListeners) { - l.selectionChanged(evt); - } - - } - }); - } - - public void focus(double x, double y, double z) { - Lock(); - cam.SetFocalPoint(x, y, z); - if (doNotRotate) - cam.SetRoll(0); - cam.OrthogonalizeViewUp(); - resetCameraClippingRange(); - //panel.UpdateLight(); - UnLock(); - } - + 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); + } + }