1 /*******************************************************************************
2 * Copyright (c) 2012, 2013 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.g3d.vtk.swt;
14 import java.awt.event.InputEvent;
15 import java.awt.event.MouseEvent;
16 import java.awt.event.MouseWheelEvent;
17 import java.util.ArrayList;
18 import java.util.Collection;
19 import java.util.List;
21 import org.eclipse.jface.viewers.ISelection;
22 import org.eclipse.jface.viewers.ISelectionChangedListener;
23 import org.eclipse.jface.viewers.ISelectionProvider;
24 import org.eclipse.jface.viewers.SelectionChangedEvent;
25 import org.eclipse.jface.viewers.StructuredSelection;
26 import org.eclipse.swt.widgets.Display;
27 import org.simantics.g3d.tools.AdaptationUtils;
31 import vtk.vtkRenderWindow;
32 import vtk.vtkRenderer;
34 public class vtkCameraAndSelectorAction extends vtkSwtAction implements ISelectionProvider {
36 protected vtkRenderer ren;
39 protected vtkRenderWindow rw;
40 protected vtkCamera cam;
41 protected int InteractionMode = 1;
43 protected double activeRate = 5.0;
44 protected double passiveRate = 0.01;
45 protected boolean doNotRotate = true;
46 private double[] upDirection = new double[] { 0, 1, 0 };
48 public vtkCameraAndSelectorAction(InteractiveVtkComposite panel) {
50 this.ren = panel.getRenderer();
51 this.rw = panel.getRenderWindow();
52 this.cam = ren.GetActiveCamera();
55 public void setUpDirection(double[] upDirection) {
56 this.upDirection = upDirection;
63 public void UnLock() {
67 public void InteractionModeRotate() {
68 this.InteractionMode = 1;
71 public void InteractionModeTranslate() {
72 this.InteractionMode = 2;
75 public void InteractionModeZoom() {
76 this.InteractionMode = 3;
79 public void resetCameraClippingRange() {
81 ren.ResetCameraClippingRange();
85 public void resetCamera() {
91 public boolean mousePressed(MouseEvent e) {
93 if (ren.VisibleActorCount() == 0)
95 rw.SetDesiredUpdateRate(activeRate);
98 if ((e.getModifiers() == InputEvent.BUTTON2_MASK)
99 || (e.getModifiers() == (InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK))) {
100 InteractionModeTranslate();
101 } else if (e.getModifiers() == InputEvent.BUTTON3_MASK) {
102 InteractionModeZoom();
104 InteractionModeRotate();
109 public boolean mouseReleased(MouseEvent e) {
110 rw.SetDesiredUpdateRate(passiveRate);
114 public boolean mouseDragged(MouseEvent e) {
115 if (ren.VisibleActorCount() == 0)
120 if (this.InteractionMode == 1) {
121 cam.Elevation(clampElevationDelta(y - lastY));
123 cam.SetViewUp(upDirection);
124 cam.Azimuth(lastX - x);
125 cam.OrthogonalizeViewUp();
126 resetCameraClippingRange();
127 // panel.UpdateLight();
130 if (this.InteractionMode == 2) {
136 // get the current focal point and position
137 FPoint = cam.GetFocalPoint();
138 PPoint = cam.GetPosition();
140 // calculate the focal depth since we'll be using it a lot
141 ren.SetWorldPoint(FPoint[0], FPoint[1], FPoint[2], 1.0);
142 ren.WorldToDisplay();
143 APoint = ren.GetDisplayPoint();
145 // int[] size = rw.GetSize();
146 APoint[0] -= x - lastX;
147 APoint[1] += y - lastY;
148 ren.SetDisplayPoint(APoint);
149 ren.DisplayToWorld();
150 RPoint = ren.GetWorldPoint();
152 if (RPoint[3] != 0.0) {
153 RPoint[0] = RPoint[0] / RPoint[3];
154 RPoint[1] = RPoint[1] / RPoint[3];
155 RPoint[2] = RPoint[2] / RPoint[3];
159 * Compute a translation vector, moving everything 1/2 the distance to the
160 * cursor. (Arbitrary scale factor)
162 cam.SetFocalPoint(RPoint);
163 cam.SetPosition((RPoint[0] - FPoint[0]) + PPoint[0], (RPoint[1] - FPoint[1]) + PPoint[1],
164 (RPoint[2] - FPoint[2]) + PPoint[2]);
165 resetCameraClippingRange();
168 if (this.InteractionMode == 3) {
170 // double clippingRange[];
172 zoomFactor = Math.pow(1.02, (y - lastY));
173 if (cam.GetParallelProjection() == 1) {
174 cam.SetParallelScale(cam.GetParallelScale() / zoomFactor);
175 resetCameraClippingRange();
177 cam.Dolly(zoomFactor);
178 resetCameraClippingRange();
187 private static double dot(double[] a, double[] b) {
188 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
191 /** Calculate change in elevation, clamped to vertical directions. */
192 private double clampElevationDelta(double elevationDelta) {
194 return elevationDelta;
196 double[] direction = cam.GetDirectionOfProjection();
197 double d = Math.min(1.0, Math.max(-1.0, dot(direction, upDirection)));
198 double elevation = Math.toDegrees(Math.acos(d)) + elevationDelta;
200 elevationDelta -= elevation - 1e-5;
201 else if (elevation > 180)
202 elevationDelta -= elevation - 180 + 1e-5;
203 return elevationDelta;
207 public boolean mouseWheelMoved(MouseWheelEvent e) {
209 // double clippingRange[];
210 zoomFactor = Math.pow(1.02, (e.getWheelRotation()));
211 if (cam.GetParallelProjection() == 1) {
212 cam.SetParallelScale(cam.GetParallelScale() / zoomFactor);
214 cam.Dolly(zoomFactor);
215 resetCameraClippingRange();
221 protected List<vtkProp> selectActors = new ArrayList<vtkProp>();
222 protected List<vtkProp> hoverActor = new ArrayList<vtkProp>();
225 public boolean mouseClicked(MouseEvent e) {
226 if (!panel.getComponent().isFocusControl())
228 if (e.getButton() != MouseEvent.BUTTON1)
230 vtkProp spick[] = panel.pick(e.getX(), e.getY());
231 if (spick != null && spick.length > 0) {
232 for (vtkProp selectActor : spick) {
233 if (!e.isControlDown()) {
234 selectActors.clear();
235 selectActors.add(selectActor);
237 if (selectActors.contains(selectActor))
238 selectActors.remove(selectActor);
240 selectActors.add(selectActor);
243 fireSelectionChanged();
244 } else if (!e.isControlDown()) {
245 selectActors.clear();
246 fireSelectionChanged();
249 // if (e.getClickCount() > 1)
250 // updatePickRay(e.getX(), e.getY());
254 // private void updatePickRay(double x , double y) {
255 // Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(), x, y);
258 // System.out.println(ray.pos + " " + ray.dir);
259 // vtkPoints linePoints = new vtkPoints();
260 // linePoints.InsertPoint(0,ray.pos.x, ray.pos.y, ray.pos.z);
261 // linePoints.InsertPoint(1, ray.pos.x + ray.dir.x, ray.pos.y + ray.dir.y,
262 // ray.pos.z + ray.dir.z);
263 // vtkLine aLine = new vtkLine();
264 // aLine.GetPointIds().SetId(0, 0);
265 // aLine.GetPointIds().SetId(1, 1);
266 // vtkUnstructuredGrid aLineGrid = new vtkUnstructuredGrid();
267 // aLineGrid.Allocate(1, 1);
268 // aLineGrid.InsertNextCell(aLine.GetCellType(), aLine.GetPointIds());
269 // aLineGrid.SetPoints(linePoints);
270 // vtkDataSetMapper aLineMapper = new vtkDataSetMapper();
271 // aLineMapper.SetInput(aLineGrid);
272 // vtkActor aLineActor = new vtkActor();
273 // aLineActor.SetMapper(aLineMapper);
274 // aLineActor.GetProperty().SetDiffuseColor(.2, 1, 1);
276 // if (rayActor != null) {
277 // panel.GetRenderer().RemoveActor(rayActor);
278 // rayActor.Delete();
280 // rayActor = aLineActor;
281 // panel.GetRenderer().AddActor(rayActor);
283 // linePoints.Delete();
285 // aLineGrid.Delete();
286 // aLineMapper.Delete();
290 // private vtkActor rayActor;
293 public boolean mouseMoved(MouseEvent e) {
297 if (!panel.getComponent().isFocusControl())
299 List<vtkProp> prevHover = new ArrayList<vtkProp>();
300 prevHover.addAll(hoverActor);
302 vtkProp pick[] = panel.pick(e.getX(), e.getY());
304 for (vtkProp p : pick)
308 if (!prevHover.containsAll(hoverActor) || !hoverActor.containsAll(prevHover)) {
314 public List<vtkProp> getSelectActor() {
318 public List<vtkProp> getHoverActor() {
322 private List<ISelectionChangedListener> selectionListeners = new ArrayList<ISelectionChangedListener>();
325 public void addSelectionChangedListener(ISelectionChangedListener listener) {
326 selectionListeners.add(listener);
330 public ISelection getSelection() {
331 return new StructuredSelection(selectActors);
335 public void removeSelectionChangedListener(ISelectionChangedListener listener) {
336 selectionListeners.remove(listener);
340 public void setSelection(ISelection selection) {
341 setSelection(selection, false);
345 public void setSelection(ISelection selection, boolean fire) {
346 Collection<vtkProp> selectedProps = AdaptationUtils.adaptToCollection(selection, vtkProp.class);
348 selectActors.clear();
349 selectActors.addAll(selectedProps);
351 fireSelectionChanged();
354 protected void fireSelectionChanged() {
355 Display.getDefault().asyncExec(new Runnable() {
359 SelectionChangedEvent evt = new SelectionChangedEvent(vtkCameraAndSelectorAction.this,
360 new StructuredSelection(selectActors));
361 for (ISelectionChangedListener l : selectionListeners) {
362 l.selectionChanged(evt);
369 private List<ISelectionChangedListener> hoverListeners = new ArrayList<ISelectionChangedListener>();
371 public void addHoverChangedListener(ISelectionChangedListener listener) {
372 hoverListeners.add(listener);
375 public ISelection getHoverSelection() {
376 return new StructuredSelection(hoverActor);
379 public void removeHoverChangedListener(ISelectionChangedListener listener) {
380 hoverListeners.remove(listener);
383 private void fireHoverChanged() {
384 Display.getDefault().asyncExec(new Runnable() {
387 StructuredSelection sel = null;
388 if (hoverActor == null)
389 sel = new StructuredSelection();
391 sel = new StructuredSelection(hoverActor);
392 SelectionChangedEvent evt = new SelectionChangedEvent(vtkCameraAndSelectorAction.this, sel);
393 for (ISelectionChangedListener l : hoverListeners) {
394 l.selectionChanged(evt);
401 public void focus(double x, double y, double z) {
403 cam.SetFocalPoint(x, y, z);
405 double[] proj = cam.GetDirectionOfProjection();
406 if (Math.abs(proj[1] * upDirection[2] - proj[2] * upDirection[1]) < 1e-6 &&
407 Math.abs(proj[2] * upDirection[0] - proj[0] * upDirection[2]) < 1e-6 &&
408 Math.abs(proj[0] * upDirection[1] - proj[1] * upDirection[0]) < 1e-6)
409 cam.SetViewUp(upDirection[1], upDirection[2], upDirection[0]);
411 cam.SetViewUp(upDirection);
413 cam.OrthogonalizeViewUp();
414 resetCameraClippingRange();
415 // panel.UpdateLight();