]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/action/RotateAction.java
d47456fdbca390145b381b3ab07209e2989cb688
[simantics/3d.git] / org.simantics.g3d.vtk / src / org / simantics / g3d / vtk / action / RotateAction.java
1 /*******************************************************************************\r
2  * Copyright (c) 2012, 2013 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.g3d.vtk.action;\r
13 \r
14 import java.awt.Cursor;\r
15 import java.awt.event.KeyEvent;\r
16 import java.awt.event.MouseEvent;\r
17 \r
18 import javax.vecmath.AxisAngle4d;\r
19 import javax.vecmath.Point3d;\r
20 import javax.vecmath.Quat4d;\r
21 import javax.vecmath.Vector3d;\r
22 \r
23 import org.simantics.g3d.math.EulerTools;\r
24 import org.simantics.g3d.math.MathTools;\r
25 import org.simantics.g3d.math.Ray;\r
26 import org.simantics.g3d.math.EulerTools.Order;\r
27 import org.simantics.g3d.preferences.PreferenceConstants;\r
28 import org.simantics.g3d.scenegraph.IG3DNode;\r
29 import org.simantics.g3d.scenegraph.structural.IStructuralNode;\r
30 import org.simantics.g3d.vtk.Activator;\r
31 import org.simantics.g3d.vtk.common.InteractiveVtkPanel;\r
32 import org.simantics.g3d.vtk.common.VTKNodeMap;\r
33 import org.simantics.g3d.vtk.gizmo.RotateAxisGizmo;\r
34 import org.simantics.g3d.vtk.utils.vtkUtil;\r
35 import org.simantics.utils.threads.AWTThread;\r
36 import org.simantics.utils.threads.ThreadUtils;\r
37 \r
38 import vtk.vtkProp;\r
39 /**\r
40  * FIXME: complete rewrite.\r
41  * \r
42  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
43  *\r
44  */\r
45 public class RotateAction extends vtkAction{\r
46         \r
47         public static final int X = 0;\r
48     public static final int Y = 1;\r
49     public static final int Z = 2;\r
50     public static final int P = 3;\r
51 \r
52         private VTKNodeMap nodeMap;\r
53         //private TranslateGizmo  gizmo = new TranslateGizmo();\r
54         private RotateAxisGizmo gizmo = new RotateAxisGizmo();\r
55         private IG3DNode node;\r
56         \r
57         \r
58         \r
59         private Cursor activeCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);\r
60         private Cursor dragCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);\r
61         \r
62         \r
63         int stepMethod = 1;\r
64         Order order = Order.YXZ;\r
65         \r
66     private int steps; \r
67     private double angles[];\r
68         \r
69         int index = P;\r
70         boolean valid = false;\r
71         private boolean worldCoord = true;\r
72         //private AxisAngle4d aa = null;\r
73         private Quat4d parentWorldOrientation = null;\r
74         \r
75         //AxisAngle4d rotation = new AxisAngle4d();\r
76         Quat4d worldOrientation = new Quat4d();\r
77         \r
78         public void setNode(IG3DNode node) {\r
79                 this.node = node;\r
80                 if ((node instanceof IStructuralNode) && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot()) {\r
81                         setEnabled(false);\r
82                 } else {\r
83                         setEnabled(true);\r
84                 }\r
85                 \r
86                 String set = org.simantics.g3d.Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.ORIENTATION_PRESENTATION);\r
87                 if (set.equals("aa")) {\r
88                         stepMethod = 0;\r
89                 } else if (set.equals("euler")){\r
90                         stepMethod = 1;\r
91                         String eulerOrder = org.simantics.g3d.Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.EULER_ANGLE_ORDER);\r
92                         try {\r
93                                 order = Order.valueOf(eulerOrder);\r
94                         } catch (Exception e) {\r
95                                 order = Order.YXZ;\r
96                         }\r
97                 } else {\r
98                         stepMethod = 2;\r
99                 }\r
100         }\r
101         \r
102         public IG3DNode getNode() {\r
103                 return node;\r
104         }\r
105         \r
106         public RotateAction(InteractiveVtkPanel panel, VTKNodeMap nodeMap) {\r
107                 super(panel);\r
108                 setImageDescriptor(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_rotate_clockwise.png"));\r
109                 setText("Rotate");\r
110                 this.nodeMap = nodeMap;\r
111                 \r
112                 \r
113                 steps = 36;\r
114         angles = new double[steps+1];\r
115         for (int i = 0; i < angles.length; i++) {\r
116             angles[i] = - Math.PI + (Math.PI * i * 2.0 / steps);\r
117         }\r
118         }\r
119         \r
120         public void attach() {\r
121                 if (node == null)\r
122                         return;\r
123                 \r
124                 super.attach();\r
125                 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
126                         public void run() {\r
127                                 attachUI();\r
128                                 update();\r
129                         }\r
130                 });\r
131                 \r
132                 \r
133                 \r
134         }\r
135         \r
136         public void deattach() {\r
137                 \r
138                 node = null;\r
139                 nodeMap.commit();\r
140                 deattachUI();\r
141                 super.deattach();\r
142                 panel.repaint();\r
143         }\r
144         \r
145         private void attachUI() {\r
146                 panel.setCursor(activeCursor);\r
147                 gizmo.attach(panel.GetRenderer());\r
148         }\r
149         \r
150         private void deattachUI() {\r
151                 panel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));\r
152                 gizmo.deattach();\r
153         }\r
154         \r
155         @Override\r
156         public void keyPressed(KeyEvent e) {\r
157                 if (e.getKeyCode() == KeyEvent.VK_ESCAPE)\r
158                         panel.useDefaultAction();\r
159                 if (valid)\r
160                         return;\r
161                 if (e.getKeyCode() == KeyEvent.VK_X) {\r
162                         if (index != X)\r
163                                 index = X;\r
164                         else\r
165                                 index = P;\r
166                 }\r
167                 if (e.getKeyCode() == KeyEvent.VK_Y) {\r
168                         if (index != Y)\r
169                                 index = Y;\r
170                         else\r
171                                 index = P;\r
172                 }\r
173                 if (e.getKeyCode() == KeyEvent.VK_Z) {\r
174                         if (index != Z)\r
175                                 index = Z;\r
176                         else\r
177                                 index = P;\r
178                 }\r
179                 if (e.getKeyCode() == KeyEvent.VK_G) {\r
180                         worldCoord = !worldCoord;\r
181                 }\r
182                 gizmo.setType(index);\r
183                 panel.repaint();\r
184         }\r
185         \r
186         @Override\r
187         public void keyReleased(KeyEvent e) {\r
188                 \r
189         }\r
190         \r
191         \r
192         \r
193         @Override\r
194         public void mouseClicked(MouseEvent e) {\r
195                 if (e.getClickCount() > 1) {\r
196                         if (isOverNode(e)) {\r
197                                 return;\r
198                         }\r
199                         panel.useDefaultAction();\r
200                         //if(!gizmo.isPartOf(actor))\r
201                         //      panel.useDefaultAction();\r
202                         \r
203                 }\r
204         }\r
205         \r
206         @Override\r
207         public void mouseEntered(MouseEvent e) {\r
208                 \r
209         }\r
210         \r
211         @Override\r
212         public void mouseExited(MouseEvent e) {\r
213                 \r
214         }\r
215         \r
216         \r
217 \r
218         \r
219         \r
220         public void setWorldCoord(boolean b) {\r
221                 if (worldCoord == b)\r
222                         return;\r
223                 worldCoord = b;\r
224                 update();\r
225                                         \r
226         }\r
227         \r
228         \r
229         private void update() {\r
230                 Vector3d nodePos = node.getWorldPosition();\r
231                 System.out.println(nodePos);\r
232                 gizmo.setPosition(nodePos);\r
233                 if (worldCoord) {\r
234                         gizmo.setRotation(new AxisAngle4d());\r
235                         parentWorldOrientation = null;\r
236                 } else {\r
237                         AxisAngle4d aa = new AxisAngle4d();\r
238                         parentWorldOrientation = ((IG3DNode)node.getParent()).getWorldOrientation();\r
239                         aa.set(parentWorldOrientation);\r
240                         gizmo.setRotation(aa);\r
241                 }\r
242 \r
243                 Point3d camPos = new Point3d(panel.GetRenderer().GetActiveCamera().GetPosition());\r
244                 Vector3d p = new Vector3d(nodePos);\r
245                 p.sub(camPos);\r
246                 \r
247                 if (parentWorldOrientation != null) {\r
248                         Quat4d qi = new Quat4d(parentWorldOrientation);\r
249                         qi.inverse();\r
250                         MathTools.rotate(parentWorldOrientation, p, p);\r
251                 }\r
252                 if (panel.GetRenderer().GetActiveCamera().GetParallelProjection() == 0) {\r
253                         double distance = p.length();\r
254                         p.negate();\r
255             double fov = panel.GetRenderer().GetActiveCamera().GetViewAngle();\r
256             float s = (float) (Math.sin(fov) * distance * 0.1); \r
257 \r
258             Vector3d scale = new Vector3d(1., 1., 1.);\r
259             \r
260 //            if (p.x > 0.f)\r
261 //                scale.x = -1.;\r
262 //            if (p.y > 0.f)\r
263 //                scale.y = -1.;\r
264 //            if (p.z > 0.f)\r
265 //                scale.z = -1.;\r
266             scale.scale(s);\r
267             gizmo.setScale(scale);\r
268                         \r
269                 } else {\r
270                         Vector3d scale = new Vector3d(1.f, 1.f, 1.f);\r
271             double s = panel.GetRenderer().GetActiveCamera().GetParallelScale() / 5.;\r
272 //            if (p.x > 0.f)\r
273 //                scale.x = -1.;\r
274 //            if (p.y > 0.f)\r
275 //                scale.y = -1.;\r
276 //            if (p.z > 0.f)\r
277 //                scale.z = -1.;\r
278             scale.scale(s);\r
279             gizmo.setScale(scale);\r
280                 }\r
281                 \r
282                 panel.Render();\r
283         }\r
284         \r
285         private boolean isOverNode(MouseEvent e) {\r
286                 vtkProp picked[] = panel.pick(e.getX(), e.getY());\r
287                 if (picked !=null) {\r
288                         for (int i = 0; i < picked.length; i++) {\r
289                                 if (node.equals(nodeMap.getNode(picked[i])))\r
290                                         return true;\r
291                         }\r
292                 }\r
293                 return false;\r
294         }\r
295         \r
296 \r
297         \r
298         @Override\r
299         public void mousePressed(MouseEvent e) {\r
300                 if (e.getButton() == MouseEvent.BUTTON1) {\r
301         \r
302         \r
303                         if (isOverNode(e)) {\r
304                                 valid = true;\r
305                                 if ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0) {\r
306                                         useStep = true;\r
307                     } else {\r
308                         useStep = false;\r
309                     }\r
310                                 worldOrientation = node.getWorldOrientation();\r
311                                 doChanges(true, e.getX(), e.getY());\r
312                                 \r
313                                 panel.setCursor(dragCursor);\r
314                         } else {\r
315                                 valid = false;\r
316                                 panel.getDefaultAction().mousePressed(e);\r
317                                 panel.setCursor(activeCursor);\r
318                         }\r
319                 } else {\r
320                         panel.getDefaultAction().mousePressed(e);\r
321                 }\r
322         }\r
323         \r
324         \r
325         \r
326         @Override\r
327         public void mouseReleased(MouseEvent e) {\r
328                 if (e.getButton() == MouseEvent.BUTTON1) {\r
329                         valid = false;\r
330                         worldOrientation = null;\r
331                         panel.setCursor(activeCursor);\r
332                 } else {\r
333                         panel.getDefaultAction().mouseReleased(e);\r
334                 }\r
335         }\r
336         \r
337         @Override\r
338         public void mouseDragged(MouseEvent e) {\r
339                 if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) > 0 && valid) { \r
340                         if ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0) {\r
341                                 useStep = true;\r
342             } else {\r
343                 useStep = false;\r
344             }\r
345                         doChanges(false, e.getX(), e.getY());\r
346                         \r
347                         //nodeMap.modified(node);\r
348                         update();\r
349                 } else {\r
350                         panel.getDefaultAction().mouseDragged(e);\r
351                         update();\r
352                 }\r
353         }\r
354         \r
355          Vector3d axis = null;\r
356         \r
357         @Override\r
358         public void keyTyped(KeyEvent e) {\r
359                  if (e.getKeyCode() == KeyEvent.VK_LEFT) {\r
360                 inputType = InputType.KEY;\r
361                 axis = new Vector3d(0.0,1.0,0.0);\r
362              } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {\r
363                         inputType = InputType.KEY;\r
364                         axis = new Vector3d(0.0,-1.0,0.0);\r
365              } else if (e.getKeyCode() ==KeyEvent.VK_UP) {\r
366                         inputType = InputType.KEY;\r
367                         axis = new Vector3d(1.0,0.0,0.0);\r
368              } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {\r
369                         inputType = InputType.KEY;\r
370                         axis = new Vector3d(-1.0,0.0,0.0);\r
371              } \r
372         }\r
373         \r
374     public void doChanges(boolean pressed, int x, int y) {\r
375         Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(),x, y);\r
376         Vector3d p = node.getWorldPosition();\r
377         \r
378         if (pressed) {\r
379             Vector3d axis = getRotationAxis();\r
380             if (axis != null) {\r
381                 if (!worldCoord) {\r
382                         MathTools.rotate(parentWorldOrientation, axis, axis);\r
383                 }\r
384 \r
385                \r
386                 double s[] = new double[2];\r
387                 Vector3d i2 = new Vector3d();\r
388                \r
389                 boolean intersect = MathTools.intersectStraightPlane(ray.pos, ray.dir, p, axis, i2, s);\r
390                 double dot = Math.abs(ray.dir.dot(axis));\r
391                 if (intersect &&  dot > 0.4)\r
392                         inputType = InputType.INTERSECT;\r
393                 else\r
394                         inputType = InputType.NONINTERSECT;\r
395                         \r
396                 \r
397                 if (inputType == InputType.INTERSECT) {\r
398                     // picking ray and plane defined by gizmo's center point and\r
399                     // rotation axis can intersect\r
400                     // vector from center point to intersection point\r
401                     i2.sub(p);\r
402                     // creating vectors i and j that are lying on the plane and\r
403                     // are perpendicular\r
404                     // vectors are used to calculate polar coordinate for\r
405                     // intersection point\r
406                     j.set(i2);\r
407                     i.cross(j, axis);\r
408                     System.out.println("I,J " + i + " " + j);\r
409                     double angleI = i2.angle(i);\r
410                     double angleJ = i2.angle(j);\r
411                     prevAngle = Math.atan2(Math.cos(angleJ), Math.cos(angleI));\r
412                 } else {\r
413                     // picking ray and plane defined by gizmo's center point and\r
414                     // rotation axis are parallel,\r
415                     // so we'll use cross product of rotation axis and picking\r
416                     // ray to detect amount of rotation\r
417                     i.cross(ray.dir, axis);\r
418                     MathTools.intersectStraightStraight(ray.pos, ray.dir, p, i, new Vector3d(), new Vector3d(), s);\r
419                     prevS = s[1];\r
420                 }\r
421             }\r
422            \r
423             \r
424         }\r
425 \r
426         if (inputType != InputType.KEY)\r
427                 axis = getRotationAxis();\r
428         if (axis == null) {\r
429             return;   \r
430         }\r
431         Vector3d taxis = null;\r
432         if (!worldCoord) {\r
433                 taxis = new Vector3d(axis);\r
434                 MathTools.rotate(parentWorldOrientation, axis, axis);\r
435         }\r
436         System.out.println(inputType);\r
437         if (inputType == InputType.INTERSECT) {\r
438 \r
439             double s[] = new double[2];\r
440             Vector3d i2 = new Vector3d();\r
441             MathTools.intersectStraightPlane(ray.pos, ray.dir, p, axis, i2, s);\r
442             i2.sub(p);\r
443             double angleI = i2.angle(i);\r
444             double angleJ = i2.angle(j);\r
445             double angle = Math.atan2(Math.cos(angleJ), Math.cos(angleI));\r
446             System.out.println("Angle " + angle + " i " + angleI + " j " + angleJ + " prev " + prevAngle);\r
447             if(!worldCoord)\r
448                 axis = taxis;\r
449             if (useStep) {\r
450 \r
451                 //setOrientation(MathTools.getQuat(rotation));\r
452                 AxisAngle4d rot = new AxisAngle4d(axis,angle-prevAngle);\r
453                 Quat4d qrot = new Quat4d();\r
454                 MathTools.getQuat(rot, qrot);\r
455                 //prevAngle = angle;\r
456                 qrot.mulInverse(worldOrientation);\r
457                 \r
458           \r
459                 if (stepMethod == 0) {\r
460                         rot.set(qrot);\r
461                         rot.angle = roundAngle(rot.angle);\r
462                         //qrot.set(rot);\r
463                         MathTools.getQuat(rot,qrot);\r
464                         setOrientation(qrot);\r
465                 } else if (stepMethod == 1){\r
466                           \r
467                         //Vector3d euler = MathTools.getEuler(qrot);\r
468                         Vector3d euler = EulerTools.getEulerFromQuat(order, qrot);\r
469                         euler.x = roundAngle(euler.x);\r
470                         euler.y = roundAngle(euler.y);\r
471                         euler.z = roundAngle(euler.z);\r
472                         //Quat4d q = MathTools.getQuat(euler);\r
473                         Quat4d q = EulerTools.getQuatFromEuler(order, euler);\r
474                         setOrientation(q);\r
475                         System.out.println(" (" + MathTools.radToDeg(euler.x) + " " + MathTools.radToDeg(euler.y) + " " + MathTools.radToDeg(euler.z) +  ") " + qrot + " "+ q);\r
476                 } else {\r
477                         setOrientation(qrot);\r
478                 }\r
479                 \r
480             } else {\r
481                 if (worldCoord) {\r
482                         //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,angle-prevAngle));\r
483                         AxisAngle4d aa = MathTools.getAxisAngle(node.getWorldOrientation());\r
484                         AxisAngle4d rot = new AxisAngle4d(axis,angle-prevAngle);\r
485                         MathTools.multiplyOrientation(aa, rot);\r
486                         setWorldOrientation(MathTools.getQuat(rot));\r
487                 } else {\r
488                         AxisAngle4d aa = MathTools.getAxisAngle(node.getOrientation());\r
489                         AxisAngle4d rot = new AxisAngle4d(axis,angle-prevAngle);\r
490                         MathTools.multiplyOrientation(aa, rot);\r
491                         setOrientation(MathTools.getQuat(rot));\r
492                         //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getLocalOrientation(), new AxisAngle4d(axis,angle-prevAngle));\r
493                 }\r
494                 prevAngle = angle;\r
495             }\r
496             \r
497         } else if (inputType == InputType.NONINTERSECT){\r
498 \r
499             double s[] = new double[2];\r
500             MathTools.intersectStraightStraight(ray.pos, ray.dir, p, i, new Vector3d(), new Vector3d(), s);\r
501             if(!worldCoord)\r
502                 axis = taxis;\r
503             if (useStep) {\r
504                 //setOrientation(MathTools.getQuat(rotation));\r
505                 AxisAngle4d rot = new AxisAngle4d(axis,s[1] - prevS);\r
506                 \r
507                 Quat4d qrot = new Quat4d();\r
508                 //qrot.set(rot);\r
509                 MathTools.getQuat(rot, qrot);\r
510                 //prevAngle = angle;\r
511                 qrot.mulInverse(worldOrientation);\r
512                 \r
513           \r
514                 if (stepMethod == 0) {\r
515                         rot.set(qrot);\r
516                         rot.angle = roundAngle(rot.angle);\r
517                         //qrot.set(rot);\r
518                         MathTools.getQuat(rot,qrot);\r
519                         setOrientation(qrot);\r
520                 } else if (stepMethod == 1){\r
521                           \r
522                         //Vector3d euler = MathTools.getEuler(qrot);\r
523                         Vector3d euler = EulerTools.getEulerFromQuat(order, qrot);\r
524                         euler.x = roundAngle(euler.x);\r
525                         euler.y = roundAngle(euler.y);\r
526                         euler.z = roundAngle(euler.z);\r
527                         //Quat4d q = MathTools.getQuat(euler);\r
528                         Quat4d q = EulerTools.getQuatFromEuler(order, euler);\r
529                         setOrientation(q);\r
530                         System.out.println(" (" + MathTools.radToDeg(euler.x) + " " + MathTools.radToDeg(euler.y) + " " + MathTools.radToDeg(euler.z) +  ") " + qrot + " "+ q);\r
531                 } else {\r
532                         setOrientation(qrot);\r
533                 }\r
534                 prevS = s[1];\r
535                 \r
536 //                    G3DTools.setOrientation(mo.getG3DNode(graph).getLocalOrientation(), rotations.get(mo));\r
537 //                    G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,s[1] - prevS));\r
538 //                    AxisAngle4d aa = G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation());\r
539 //                    rotations.put(mo, aa);\r
540 //                    Vector3d euler = MathTools.getEuler(aa);\r
541 //                    euler.x = roundAngle(euler.x);\r
542 //                    euler.y = roundAngle(euler.y);\r
543 //                    euler.z = roundAngle(euler.z);\r
544 //                    aa = MathTools.getFromEuler2(euler);\r
545 //                    prevS = s[1];\r
546 //                    G3DTools.setOrientation(mo.getG3DNode(graph).getLocalOrientation(), aa);\r
547 //                    Vector3d e = MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()));\r
548 //                    e.scale(180.0/Math.PI);\r
549 //                    text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + e + " ";\r
550                 \r
551                 \r
552             } else {\r
553                         if (worldCoord) {\r
554                                 AxisAngle4d aa =  MathTools.getAxisAngle(node.getWorldOrientation());\r
555                         AxisAngle4d rot = new AxisAngle4d(axis,s[1] - prevS);\r
556                         MathTools.multiplyOrientation(aa, rot);\r
557                         setWorldOrientation(MathTools.getQuat(rot));\r
558                                 //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,s[1] - prevS));\r
559                         } else {\r
560                                 AxisAngle4d aa =  MathTools.getAxisAngle(node.getOrientation());\r
561                         AxisAngle4d rot = new AxisAngle4d(axis,s[1] - prevS);\r
562                         MathTools.multiplyOrientation(aa, rot);\r
563                         setOrientation(MathTools.getQuat(rot));\r
564                                 //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getLocalOrientation(), new AxisAngle4d(axis,s[1] - prevS));\r
565                         }\r
566                         //text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation())) + " ";\r
567                 prevS = s[1];\r
568                 \r
569             }\r
570            \r
571         } else {\r
572                 if (worldCoord) {\r
573                         AxisAngle4d aa = MathTools.getAxisAngle(node.getWorldOrientation());\r
574                 AxisAngle4d rot = new AxisAngle4d(axis,Math.PI * 0.5);\r
575                 MathTools.multiplyOrientation(aa, rot);\r
576                 setWorldOrientation(MathTools.getQuat(rot));\r
577                         //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,Math.PI * 0.5));\r
578                 } else {\r
579                         AxisAngle4d aa = MathTools.getAxisAngle(node.getOrientation());\r
580                 AxisAngle4d rot = new AxisAngle4d(axis,Math.PI * 0.5);\r
581                 MathTools.multiplyOrientation(aa, rot);\r
582                 setOrientation(MathTools.getQuat(rot));\r
583                         //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getLocalOrientation(), new AxisAngle4d(axis,Math.PI * 0.5));\r
584                 }\r
585              //   text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation())) + " ";\r
586             \r
587         }\r
588         //setInfoText(text);\r
589  \r
590     }\r
591     \r
592     protected void setOrientation(Quat4d q) {\r
593         node.setOrientation(q);\r
594     }\r
595     \r
596     protected void setWorldOrientation(Quat4d q) {\r
597         node.setWorldOrientation(q);\r
598     }\r
599         \r
600         @Override\r
601         public void mouseMoved(MouseEvent e) {\r
602                 panel.getDefaultAction().mouseMoved(e);\r
603         }\r
604         \r
605         private Vector3d getRotationAxis() {\r
606                 switch (index) {\r
607                 case X:\r
608                         return new Vector3d(1.0, 0.0, 0.0);\r
609                 case Y:\r
610                         return new Vector3d(0.0, 1.0, 0.0);\r
611                 case Z:\r
612                         return new Vector3d(0.0, 0.0, 1.0);\r
613                 case P:\r
614                         Vector3d axis = new Vector3d(panel.GetRenderer().GetActiveCamera()\r
615                                         .GetDirectionOfProjection());\r
616                         axis.normalize();\r
617                         return axis;\r
618                 default:\r
619                         return null;\r
620                 }\r
621         }\r
622         \r
623          private double prevS = 0.0;\r
624             \r
625     private Vector3d i = new Vector3d();\r
626     private Vector3d j = new Vector3d();\r
627     private double prevAngle = 0;\r
628 \r
629     enum InputType{INTERSECT,NONINTERSECT,KEY,NONE};\r
630     InputType inputType;\r
631     private boolean useStep = false;\r
632     \r
633     \r
634     \r
635     private double roundAngle(double angle) {\r
636         while (angle < - Math.PI)\r
637             angle += Math.PI*2.0;\r
638         while (angle > Math.PI)\r
639             angle -= Math.PI*2.0;\r
640         \r
641         \r
642         int index = 0;\r
643         while (angle > angles[index])\r
644             index++;\r
645         if (index == 0) {\r
646             angle = angles[0];\r
647         } else {\r
648             double d = angle - angles[index - 1];\r
649             double d2 = angles[index] - angle;\r
650             if (d < d2)\r
651                 angle = angles[index - 1];\r
652             else\r
653                 angle = angles[index];\r
654         }\r
655         return angle;\r
656     }\r
657         \r
658 }\r