/******************************************************************************* * Copyright (c) 2012, 2013 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.g3d.vtk.awt; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.vecmath.Point2d; import javax.vecmath.Point2i; import javax.vecmath.Point3d; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.widgets.Display; import org.simantics.g3d.tools.AdaptationUtils; import vtk.vtkCamera; import vtk.vtkProp; import vtk.vtkRenderWindow; import vtk.vtkRenderer; public class vtkCameraAndSelectorAction extends vtkAwtAction 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; public vtkCameraAndSelectorAction(InteractiveVtkPanel panel) { super(panel); this.ren = panel.GetRenderer(); this.rw = panel.GetRenderWindow(); this.cam = ren.GetActiveCamera(); } 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 resetCameraClippingRange() { Lock(); ren.ResetCameraClippingRange(); UnLock(); } public void resetCamera() { Lock(); ren.ResetCamera(); UnLock(); } public void mousePressed(MouseEvent e) { if (ren.VisibleActorCount() == 0) return; 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(); } } public void mouseReleased(MouseEvent e) { rw.SetDesiredUpdateRate(passiveRate); } public void mouseDragged(MouseEvent e) { if (ren.VisibleActorCount() == 0) return; 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.Render(); } private List selectActors = new ArrayList(); private List hoverActor = new ArrayList(); @Override public void mouseClicked(MouseEvent e) { if (!panel.isFocusOwner()) return; if (e.getButton() != MouseEvent.BUTTON1) return; lastX = e.getX(); lastY = e.getY(); 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(); } // 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 void mouseMoved(MouseEvent e) { lastX = e.getX(); lastY = e.getY(); if (!panel.isFocusOwner()) return; 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); } if (!prevHover.containsAll(hoverActor) || !hoverActor.containsAll(prevHover)) { fireHoverChanged(); } } /** * Returns mouse position in AWT screen coordinates. * @return */ public Point2i getMousePositionAWT() { return new Point2i(lastX, lastY); } /** * Returns mouse position in VTK screen coordinates. * @return */ public Point2d getMousePosition() { return new Point2d(lastX, rw.GetSize()[1]-lastY); } 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(); } 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); } } }); } 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 vtkCamera getCamera() { return cam; } public Point3d getPosition() { double pos[] = cam.GetPosition(); return new Point3d(pos); } public Point3d getFocus() { double pos[] = cam.GetFocalPoint(); return new Point3d(pos); } public void setFocus(Point3d focus) { setFocus(focus.x,focus.y,focus.z); } public void setFocus(double x, double y, double z) { Lock(); cam.SetFocalPoint(x, y, z); if (doNotRotate) cam.SetRoll(0); cam.OrthogonalizeViewUp(); ren.ResetCameraClippingRange(); panel.UpdateLight(); UnLock(); } public void setPosition(Point3d position) { setPosition(position.x,position.y,position.z); } public void setPosition(double x, double y, double z) { Lock(); cam.SetPosition(x, y, z); if (doNotRotate) cam.SetRoll(0); cam.OrthogonalizeViewUp(); ren.ResetCameraClippingRange(); panel.UpdateLight(); UnLock(); } }