]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/swt/InteractiveVtkComposite.java
Camera rotation with stable rotation speed
[simantics/3d.git] / org.simantics.g3d.vtk / src / org / simantics / g3d / vtk / swt / InteractiveVtkComposite.java
1 package org.simantics.g3d.vtk.swt;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import org.eclipse.swt.widgets.Composite;
7 import org.simantics.g3d.scenegraph.RenderListener;
8 import org.simantics.g3d.vtk.action.vtkAction;
9 import org.simantics.g3d.vtk.common.VtkView;
10 import org.simantics.utils.threads.IThreadWorkQueue;
11 import org.simantics.utils.threads.SWTThread;
12 import org.simantics.utils.threads.ThreadUtils;
13
14 import vtk.vtkAbstractPicker;
15 import vtk.vtkActor2D;
16 import vtk.vtkActor2DCollection;
17 import vtk.vtkAreaPicker;
18 import vtk.vtkAssemblyNode;
19 import vtk.vtkAssemblyPath;
20 import vtk.vtkCellPicker;
21 import vtk.vtkObjectBase;
22 import vtk.vtkPointPicker;
23 import vtk.vtkProp;
24 import vtk.vtkProp3DCollection;
25 import vtk.vtkPropCollection;
26 import vtk.vtkPropPicker;
27 import vtk.vtkRenderWindow;
28 import vtk.vtkRenderer;
29 import vtk.vtkScenePicker;
30 import vtk.rendering.swt.vtkSwtComponent;
31
32 public class InteractiveVtkComposite extends vtkSwtComponent implements VtkView{
33         
34         Composite parentComposite;
35         public InteractiveVtkComposite(Composite parentComposite) {
36                 super(parentComposite);
37                 this.parentComposite = parentComposite;
38                 
39                 // TODO Auto-generated constructor stub
40         }
41         
42         private boolean updating = false;
43         private Object mutex = new Object();
44         
45         @Override
46         public void refresh() {
47 //              if (Thread.currentThread() == getThreadQueue().getThread())
48 //                      update();
49 //              else {
50                         synchronized (mutex) {
51                                 if (!updating) {
52                                         updating = true;
53                                         ThreadUtils.asyncExec(getThreadQueue(), new Runnable() {
54                                                 
55                                                 @Override
56                                                 public void run() {
57                                                         if (parentComposite.isDisposed())
58                                                                 return;
59                                                         synchronized (mutex) {
60                                                                 updating = false;
61                                                         }
62                                                         update();
63                                                 }
64                                         });
65                                         
66                                 }
67                         }
68 //              }
69         }
70         
71         boolean update = false;
72         @Override
73         public void update() {
74                 if (update)
75                         return;
76                 update = true;
77                 super.update();
78                 update = false;
79         }
80         
81         @Override
82         public IThreadWorkQueue getThreadQueue() {
83                 return SWTThread.getThreadAccess();
84         }
85         
86
87         boolean render = false;
88         @Override
89         public void Render() {
90                 if (render)
91                         return;
92 //              System.out.println(getClass().getSimpleName() +" render");
93                 render = true;
94                 firePreRender();
95                 super.Render();
96                 firePostRender();
97                 render = false;
98         }
99
100         public void addListener(RenderListener l) {
101                 listeners.add(l);
102         }
103         
104         public void removeListener(RenderListener l) {
105                 listeners.remove(l);
106         }
107         
108         private List<RenderListener> listeners = new ArrayList<RenderListener>();
109         
110         List<RenderListener> list = new ArrayList<RenderListener>();
111         
112         private void firePreRender() {
113                 if (listeners.size() > 0) {
114                         list.addAll(listeners);
115                         for (RenderListener l : list)
116                                 l.preRender();
117                         list.clear();
118                 }
119         }
120         
121         private void firePostRender() {
122                 if (listeners.size() > 0) {
123                         list.addAll(listeners);
124                         for (RenderListener l : list)
125                                 l.postRender();
126                         list.clear();
127                 }
128         }
129
130         
131         private List<vtkObjectBase> deletable = new ArrayList<vtkObjectBase>();
132         
133         public void addDeletable(vtkObjectBase o) {
134                 deletable.add(o);
135         }
136         
137         public void removeDeletable (vtkObjectBase o) {
138                 deletable.remove(o);
139         }
140         
141         @Override
142         public void Delete() {
143                 for (vtkObjectBase o : deletable) {
144                         if (o.GetVTKId() != 0) {
145                                 o.Delete();
146                         }
147                 }
148                 deletable.clear();
149                 
150                 super.Delete();
151         }
152         
153         private vtkSwtAction defaultAction;
154         private vtkSwtAction currentAction;
155         
156         public void setActiveAction(vtkAction action) {
157                 if (action.equals(currentAction))
158                         return;
159                 if (currentAction != null)
160                         currentAction.deattach();
161                 currentAction = (vtkSwtAction)action;
162                 if (action != null)
163                         action.attach();
164         }
165         
166         public void setDefaultAction(vtkAction defaultAction) {
167                 this.defaultAction = (vtkSwtAction)defaultAction;
168         }
169         
170         public void useDefaultAction() {
171                 setActiveAction(defaultAction);
172         }
173         
174         public vtkAction getDefaultAction() {
175                 return defaultAction;
176         }
177         
178         public void lock() {
179                 getVTKLock().lock();
180                 if (getComponent().getContext() != null && !getComponent().getContext().isCurrent()) {
181                         @SuppressWarnings("unused")
182                         int ret = getComponent().getContext().makeCurrent();
183 //                      System.out.println("Make current2 " + ret);
184                 }
185         }
186         
187         public void unlock() {
188                 getVTKLock().unlock();
189         }
190         
191         private vtkScenePicker scenePicker;
192         
193         int pickType = 4;
194         
195         public int getPickType() {
196                 return pickType;
197         }
198         
199         public void setPickType(int pickType) {
200                 this.pickType = pickType;
201         }
202         
203         public vtkProp[] pick(int x, int y) {
204                 
205                 
206                 vtkRenderWindow rw = getRenderWindow();
207                 vtkRenderer ren = getRenderer();
208                 
209                 int ax = x;
210                 int ay = rw.GetSize()[1] - y;
211
212                 if (pickType == 0) {
213                         throw new IllegalStateException("SWT Binding does not work with hw picking");
214 //                      lock();
215 //                      ren.BreakOnError();
216 //                      ren.DrawOff();
217 //                      vtkPropPicker picker = new vtkPropPicker();
218 //                      picker.DebugOn();
219 //                      //picker.PickProp(x, rw.GetSize()[1] - y, ren);
220 //                      picker.Pick(x, rw.GetSize()[1] - y,0, ren);
221 //                      ren.DrawOn();
222 //                      unlock();
223 //      
224 //                      vtkAssemblyPath apath = picker.GetPath();
225 //                      return processPick(picker, apath);
226 //                      
227                 } else if (pickType == 1) {
228                         throw new IllegalStateException("SWT Binding does not work with hw picking");
229 //                      if (scenePicker == null) {
230 //                              scenePicker = new vtkScenePicker();
231 //                              scenePicker.SetRenderer(ren);
232 //                              scenePicker.EnableVertexPickingOn();
233 //                              
234 //                      }
235 //                      lock();
236 //
237 //                      vtkAssemblyPath apath = ren.PickProp(ax, ay);
238 //                      
239 //                      unlock();
240 //                      
241 //                      if (apath != null) {
242 //                              apath.InitTraversal();
243 //                              vtkAssemblyNode node = apath.GetLastNode();
244 //                              vtkProp test = (vtkProp) node.GetViewProp();
245 //                              apath.Delete();
246 //                              node.Delete();
247 //                              return new vtkProp[]{test};
248 //      
249 //                      }
250                         
251                 } else if (pickType == 2) {
252                         vtkPointPicker picker = new vtkPointPicker();
253                         //picker.SetTolerance(2.0/(double)rw.GetSize()[0]);
254                         picker.SetTolerance(0.00001);
255                         lock();
256                         picker.Pick(new double[]{ax, ay,0}, ren);
257                         unlock();
258                         
259                         vtkAssemblyPath apath = picker.GetPath();
260                         return processPick(picker, apath);
261                 } else if (pickType == 3) {
262                         vtkAreaPicker picker = new vtkAreaPicker();
263                         lock();
264                         picker.Pick(new double[]{ax, ay,0}, ren);
265                         unlock();
266                         vtkAssemblyPath apath = picker.GetPath();
267                         return processPick(picker, apath);
268                 } else if (pickType == 4) {
269                         vtkCellPicker picker = new vtkCellPicker();
270                         picker.SetTolerance(0.00001);
271                         lock();
272                         picker.Pick(new double[]{ax, ay,0}, ren);
273                         unlock();       
274                         vtkAssemblyPath apath = picker.GetPath();
275                         return processPick(picker, apath);
276                 } else if (pickType == 5) {
277                         vtkActor2DCollection coll = ren.GetActors2D(); 
278                         coll.InitTraversal();
279                         vtkActor2D a;
280                         
281                         List<vtkActor2D> picked = new ArrayList<vtkActor2D>();
282                         while ((a = coll.GetNextItem()) != null) {
283                                 double pos[] = a.GetPosition();
284                                 // TODO : width and height do not seem to affect the perceived size of Actor2D.
285                                 //        actual size should be fetched from mapper. 
286                                 double w = a.GetWidth();
287                                 double h = a.GetHeight();
288                                 int minx = (int)(pos[0]-w*0.5);
289                                 int miny = (int)(pos[1]-h*0.5);
290                                 int maxx = (int)(pos[0]+w*0.5);
291                                 int maxy = (int)(pos[1]+h*0.5);
292                                 if (minx <= ax && maxx >= ax &&
293                                         miny <= ay && maxy >= ay) {
294                                         picked.add(a);
295                                 }
296                         }
297                         return picked.toArray(new vtkProp[picked.size()]);
298                 }
299
300                 return null;
301         }
302         
303         public vtkProp[] pick2(int x, int y) {
304                 vtkRenderWindow rw = getRenderWindow();
305                 vtkRenderer ren = getRenderer();
306                 
307 //              vtkPicker picker = new vtkPicker();
308 //              vtkAbstractPicker picker = new vtkAbstractPicker();
309 //              picker.Pick(x, rw.GetSize()[1] - y, ren);
310 //              // see page 60 of VTK user's guide
311 //
312                 if (pickType == 0) {
313         
314                         vtkPropPicker picker = new vtkPropPicker();
315                         lock();
316                         picker.PickProp(x, rw.GetSize()[1] - y, ren);
317         
318                         unlock();
319                         vtkPropCollection coll = picker.GetPickList();
320                         return processPick(picker, coll);
321                         
322                 } else if (pickType == 1) {
323                         if (scenePicker == null) {
324                                 scenePicker = new vtkScenePicker();
325                                 scenePicker.SetRenderer(ren);
326                                 scenePicker.EnableVertexPickingOn();
327                                 scenePicker.DebugOn();
328                                 
329                         }
330                         lock();
331
332                         
333                         vtkAssemblyPath apath = ren.PickProp(x, rw.GetSize()[1] - y);
334                         
335                         unlock();
336                         
337                         if (apath != null) {
338                                 apath.InitTraversal();
339
340                                 
341                                 vtkAssemblyNode node = apath.GetLastNode();
342                                 vtkProp test = (vtkProp) node.GetViewProp();
343                                 apath.Delete();
344                                 node.Delete();
345                                 return new vtkProp[]{test};
346         
347                         }
348                         
349                 } else if (pickType == 2) {
350                         vtkPointPicker picker = new vtkPointPicker();
351                         picker.SetTolerance(2.0/(double)rw.GetSize()[0]);
352                         lock();
353                         picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren);
354                         unlock();
355                         vtkProp3DCollection coll = picker.GetProp3Ds();
356                         return processPick(picker, coll);
357                 } else if (pickType == 3) {
358                         vtkAreaPicker picker = new vtkAreaPicker();
359                         lock();
360                         picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren);
361                         //picker.AreaPick(x-1, rw.GetSize()[1] - y-1,x+1,rw.GetSize()[1] - y+1, ren);
362                         unlock();
363                         vtkProp3DCollection coll = picker.GetProp3Ds();
364                         return processPick(picker, coll);
365                 } else if (pickType == 4) {
366                         vtkCellPicker picker = new vtkCellPicker();
367                         picker.SetTolerance(2.0/(double)rw.GetSize()[0]);
368                         lock();
369                         picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren);
370                         unlock();       
371                         vtkProp3DCollection coll = picker.GetProp3Ds();
372                         return processPick(picker, coll);
373                 }
374
375                 return null;
376         }
377         
378         private vtkProp[] processPick(vtkAbstractPicker picker, vtkAssemblyPath apath) {
379 //              double[] pickPos = picker.GetPickPosition();
380                 picker.Delete();
381                 if (apath != null) {
382                         apath.InitTraversal();
383                         vtkProp result[] = new vtkProp[apath.GetNumberOfItems()];
384                         for (int i = apath.GetNumberOfItems()-1; i >= 0; i--) {
385                                 vtkAssemblyNode node = apath.GetNextNode();
386                                 vtkProp test = (vtkProp) node.GetViewProp();
387 //                              System.out.println("Picked: " + test.GetClassName() + " " + test.GetVTKId());
388                                 result[i] = test;
389                                 node.Delete();
390                         }
391                         apath.Delete();
392                         return result;
393
394                 }
395                 return null;
396         }
397         
398         private vtkProp[] processPick(vtkAbstractPicker picker, vtkPropCollection coll) {
399 //              double[] pickPos = picker.GetPickPosition();
400                 picker.Delete();
401                 if (coll != null) {
402                         coll.InitTraversal();
403                         vtkProp result[] = new vtkProp[coll.GetNumberOfItems()];
404                         for (int i = coll.GetNumberOfItems()-1; i >= 0; i--) {
405                                 vtkProp test = coll.GetNextProp();
406                                 
407 //                              System.out.println("Picked: " + test.GetClassName() + " " + test.GetVTKId());
408                                 result[i] = test;
409                                 
410                         }
411                         coll.Delete();
412                         return result;
413
414                 }
415                 return null;
416         }
417         
418         
419         
420 }