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