--- /dev/null
+package org.simantics.g3d.vtk.action;\r
+\r
+import java.awt.Cursor;\r
+import java.awt.event.KeyEvent;\r
+import java.awt.event.MouseEvent;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.EulerTools;\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.g3d.math.Ray;\r
+import org.simantics.g3d.math.EulerTools.Order;\r
+import org.simantics.g3d.preferences.PreferenceConstants;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.structural.IStructuralNode;\r
+import org.simantics.g3d.vtk.Activator;\r
+import org.simantics.g3d.vtk.common.InteractiveVtkPanel;\r
+import org.simantics.g3d.vtk.common.VTKNodeMap;\r
+import org.simantics.g3d.vtk.gizmo.RotateAxisGizmo;\r
+import org.simantics.g3d.vtk.utils.vtkUtil;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+import vtk.vtkProp;\r
+/**\r
+ * FIXME: complete rewrite.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class RotateAction extends vtkAction{\r
+ \r
+ public static final int X = 0;\r
+ public static final int Y = 1;\r
+ public static final int Z = 2;\r
+ public static final int P = 3;\r
+\r
+ private VTKNodeMap nodeMap;\r
+ //private TranslateGizmo gizmo = new TranslateGizmo();\r
+ private RotateAxisGizmo gizmo = new RotateAxisGizmo();\r
+ private IG3DNode node;\r
+ \r
+ \r
+ \r
+ private Cursor activeCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);\r
+ private Cursor dragCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);\r
+ \r
+ \r
+ int stepMethod = 1;\r
+ Order order = Order.YXZ;\r
+ \r
+ private int steps; \r
+ private double angles[];\r
+ \r
+ int index = P;\r
+ boolean valid = false;\r
+ private boolean worldCoord = true;\r
+ //private AxisAngle4d aa = null;\r
+ private Quat4d parentWorldOrientation = null;\r
+ \r
+ //AxisAngle4d rotation = new AxisAngle4d();\r
+ Quat4d worldOrientation = new Quat4d();\r
+ \r
+ public void setNode(IG3DNode node) {\r
+ this.node = node;\r
+ if ((node instanceof IStructuralNode) && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot()) {\r
+ setEnabled(false);\r
+ } else {\r
+ setEnabled(true);\r
+ }\r
+ \r
+ String set = org.simantics.g3d.Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.ORIENTATION_PRESENTATION);\r
+ if (set.equals("aa")) {\r
+ stepMethod = 0;\r
+ } else if (set.equals("euler")){\r
+ stepMethod = 1;\r
+ String eulerOrder = org.simantics.g3d.Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.EULER_ANGLE_ORDER);\r
+ try {\r
+ order = Order.valueOf(eulerOrder);\r
+ } catch (Exception e) {\r
+ order = Order.YXZ;\r
+ }\r
+ } else {\r
+ stepMethod = 2;\r
+ }\r
+ }\r
+ \r
+ public IG3DNode getNode() {\r
+ return node;\r
+ }\r
+ \r
+ public RotateAction(InteractiveVtkPanel panel, VTKNodeMap nodeMap) {\r
+ super(panel);\r
+ setImageDescriptor(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_rotate_clockwise.png"));\r
+ setText("Rotate");\r
+ this.nodeMap = nodeMap;\r
+ \r
+ \r
+ steps = 36;\r
+ angles = new double[steps+1];\r
+ for (int i = 0; i < angles.length; i++) {\r
+ angles[i] = - Math.PI + (Math.PI * i * 2.0 / steps);\r
+ }\r
+ }\r
+ \r
+ public void attach() {\r
+ if (node == null)\r
+ return;\r
+ \r
+ super.attach();\r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ public void run() {\r
+ attachUI();\r
+ update();\r
+ }\r
+ });\r
+ \r
+ \r
+ \r
+ }\r
+ \r
+ public void deattach() {\r
+ \r
+ node = null;\r
+ nodeMap.commit();\r
+ deattachUI();\r
+ super.deattach();\r
+ panel.repaint();\r
+ }\r
+ \r
+ private void attachUI() {\r
+ panel.setCursor(activeCursor);\r
+ gizmo.attach(panel.GetRenderer());\r
+ }\r
+ \r
+ private void deattachUI() {\r
+ panel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));\r
+ gizmo.deattach();\r
+ }\r
+ \r
+ @Override\r
+ public void keyPressed(KeyEvent e) {\r
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE)\r
+ panel.useDefaultAction();\r
+ if (valid)\r
+ return;\r
+ if (e.getKeyCode() == KeyEvent.VK_X) {\r
+ if (index != X)\r
+ index = X;\r
+ else\r
+ index = P;\r
+ }\r
+ if (e.getKeyCode() == KeyEvent.VK_Y) {\r
+ if (index != Y)\r
+ index = Y;\r
+ else\r
+ index = P;\r
+ }\r
+ if (e.getKeyCode() == KeyEvent.VK_Z) {\r
+ if (index != Z)\r
+ index = Z;\r
+ else\r
+ index = P;\r
+ }\r
+ if (e.getKeyCode() == KeyEvent.VK_G) {\r
+ worldCoord = !worldCoord;\r
+ }\r
+ gizmo.setType(index);\r
+ panel.repaint();\r
+ }\r
+ \r
+ @Override\r
+ public void keyReleased(KeyEvent e) {\r
+ \r
+ }\r
+ \r
+ \r
+ \r
+ @Override\r
+ public void mouseClicked(MouseEvent e) {\r
+ if (e.getClickCount() > 1) {\r
+ if (isOverNode(e)) {\r
+ return;\r
+ }\r
+ panel.useDefaultAction();\r
+ //if(!gizmo.isPartOf(actor))\r
+ // panel.useDefaultAction();\r
+ \r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void mouseEntered(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void mouseExited(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ \r
+\r
+ \r
+ \r
+ public void setWorldCoord(boolean b) {\r
+ if (worldCoord == b)\r
+ return;\r
+ worldCoord = b;\r
+ update();\r
+ \r
+ }\r
+ \r
+ \r
+ private void update() {\r
+ Vector3d nodePos = node.getWorldPosition();\r
+ System.out.println(nodePos);\r
+ gizmo.setPosition(nodePos);\r
+ if (worldCoord) {\r
+ gizmo.setRotation(new AxisAngle4d());\r
+ parentWorldOrientation = null;\r
+ } else {\r
+ AxisAngle4d aa = new AxisAngle4d();\r
+ parentWorldOrientation = ((IG3DNode)node.getParent()).getWorldOrientation();\r
+ aa.set(parentWorldOrientation);\r
+ gizmo.setRotation(aa);\r
+ }\r
+\r
+ Point3d camPos = new Point3d(panel.GetRenderer().GetActiveCamera().GetPosition());\r
+ Vector3d p = new Vector3d(nodePos);\r
+ p.sub(camPos);\r
+ \r
+ if (parentWorldOrientation != null) {\r
+ Quat4d qi = new Quat4d(parentWorldOrientation);\r
+ qi.inverse();\r
+ MathTools.rotate(parentWorldOrientation, p, p);\r
+ }\r
+ if (panel.GetRenderer().GetActiveCamera().GetParallelProjection() == 0) {\r
+ double distance = p.length();\r
+ p.negate();\r
+ double fov = panel.GetRenderer().GetActiveCamera().GetViewAngle();\r
+ float s = (float) (Math.sin(fov) * distance * 0.1); \r
+\r
+ Vector3d scale = new Vector3d(1., 1., 1.);\r
+ \r
+// if (p.x > 0.f)\r
+// scale.x = -1.;\r
+// if (p.y > 0.f)\r
+// scale.y = -1.;\r
+// if (p.z > 0.f)\r
+// scale.z = -1.;\r
+ scale.scale(s);\r
+ gizmo.setScale(scale);\r
+ \r
+ } else {\r
+ Vector3d scale = new Vector3d(1.f, 1.f, 1.f);\r
+ double s = panel.GetRenderer().GetActiveCamera().GetParallelScale() / 5.;\r
+// if (p.x > 0.f)\r
+// scale.x = -1.;\r
+// if (p.y > 0.f)\r
+// scale.y = -1.;\r
+// if (p.z > 0.f)\r
+// scale.z = -1.;\r
+ scale.scale(s);\r
+ gizmo.setScale(scale);\r
+ }\r
+ \r
+ panel.Render();\r
+ }\r
+ \r
+ private boolean isOverNode(MouseEvent e) {\r
+ vtkProp picked[] = panel.pick(e.getX(), e.getY());\r
+ if (picked !=null) {\r
+ for (int i = 0; i < picked.length; i++) {\r
+ if (node.equals(nodeMap.getNode(picked[i])))\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+ \r
+\r
+ \r
+ @Override\r
+ public void mousePressed(MouseEvent e) {\r
+ if (e.getButton() == MouseEvent.BUTTON1) {\r
+ \r
+ \r
+ if (isOverNode(e)) {\r
+ valid = true;\r
+ if ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0) {\r
+ useStep = true;\r
+ } else {\r
+ useStep = false;\r
+ }\r
+ worldOrientation = node.getWorldOrientation();\r
+ doChanges(true, e.getX(), e.getY());\r
+ \r
+ panel.setCursor(dragCursor);\r
+ } else {\r
+ valid = false;\r
+ panel.getDefaultAction().mousePressed(e);\r
+ panel.setCursor(activeCursor);\r
+ }\r
+ } else {\r
+ panel.getDefaultAction().mousePressed(e);\r
+ }\r
+ }\r
+ \r
+ \r
+ \r
+ @Override\r
+ public void mouseReleased(MouseEvent e) {\r
+ if (e.getButton() == MouseEvent.BUTTON1) {\r
+ valid = false;\r
+ worldOrientation = null;\r
+ panel.setCursor(activeCursor);\r
+ } else {\r
+ panel.getDefaultAction().mouseReleased(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void mouseDragged(MouseEvent e) {\r
+ if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) > 0 && valid) { \r
+ if ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0) {\r
+ useStep = true;\r
+ } else {\r
+ useStep = false;\r
+ }\r
+ doChanges(false, e.getX(), e.getY());\r
+ \r
+ //nodeMap.modified(node);\r
+ update();\r
+ } else {\r
+ panel.getDefaultAction().mouseDragged(e);\r
+ update();\r
+ }\r
+ }\r
+ \r
+ Vector3d axis = null;\r
+ \r
+ @Override\r
+ public void keyTyped(KeyEvent e) {\r
+ if (e.getKeyCode() == KeyEvent.VK_LEFT) {\r
+ inputType = InputType.KEY;\r
+ axis = new Vector3d(0.0,1.0,0.0);\r
+ } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {\r
+ inputType = InputType.KEY;\r
+ axis = new Vector3d(0.0,-1.0,0.0);\r
+ } else if (e.getKeyCode() ==KeyEvent.VK_UP) {\r
+ inputType = InputType.KEY;\r
+ axis = new Vector3d(1.0,0.0,0.0);\r
+ } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {\r
+ inputType = InputType.KEY;\r
+ axis = new Vector3d(-1.0,0.0,0.0);\r
+ } \r
+ }\r
+ \r
+ public void doChanges(boolean pressed, int x, int y) {\r
+ Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(),x, y);\r
+ Vector3d p = node.getWorldPosition();\r
+ \r
+ if (pressed) {\r
+ Vector3d axis = getRotationAxis();\r
+ if (axis != null) {\r
+ if (!worldCoord) {\r
+ MathTools.rotate(parentWorldOrientation, axis, axis);\r
+ }\r
+\r
+ \r
+ double s[] = new double[2];\r
+ Vector3d i2 = new Vector3d();\r
+ \r
+ boolean intersect = MathTools.intersectStraightPlane(ray.pos, ray.dir, p, axis, i2, s);\r
+ double dot = Math.abs(ray.dir.dot(axis));\r
+ if (intersect && dot > 0.4)\r
+ inputType = InputType.INTERSECT;\r
+ else\r
+ inputType = InputType.NONINTERSECT;\r
+ \r
+ \r
+ if (inputType == InputType.INTERSECT) {\r
+ // picking ray and plane defined by gizmo's center point and\r
+ // rotation axis can intersect\r
+ // vector from center point to intersection point\r
+ i2.sub(p);\r
+ // creating vectors i and j that are lying on the plane and\r
+ // are perpendicular\r
+ // vectors are used to calculate polar coordinate for\r
+ // intersection point\r
+ j.set(i2);\r
+ i.cross(j, axis);\r
+ System.out.println("I,J " + i + " " + j);\r
+ double angleI = i2.angle(i);\r
+ double angleJ = i2.angle(j);\r
+ prevAngle = Math.atan2(Math.cos(angleJ), Math.cos(angleI));\r
+ } else {\r
+ // picking ray and plane defined by gizmo's center point and\r
+ // rotation axis are parallel,\r
+ // so we'll use cross product of rotation axis and picking\r
+ // ray to detect amount of rotation\r
+ i.cross(ray.dir, axis);\r
+ MathTools.intersectStraightStraight(ray.pos, ray.dir, p, i, new Vector3d(), new Vector3d(), s);\r
+ prevS = s[1];\r
+ }\r
+ }\r
+ \r
+ \r
+ }\r
+\r
+ if (inputType != InputType.KEY)\r
+ axis = getRotationAxis();\r
+ if (axis == null) {\r
+ return; \r
+ }\r
+ Vector3d taxis = null;\r
+ if (!worldCoord) {\r
+ taxis = new Vector3d(axis);\r
+ MathTools.rotate(parentWorldOrientation, axis, axis);\r
+ }\r
+ System.out.println(inputType);\r
+ if (inputType == InputType.INTERSECT) {\r
+\r
+ double s[] = new double[2];\r
+ Vector3d i2 = new Vector3d();\r
+ MathTools.intersectStraightPlane(ray.pos, ray.dir, p, axis, i2, s);\r
+ i2.sub(p);\r
+ double angleI = i2.angle(i);\r
+ double angleJ = i2.angle(j);\r
+ double angle = Math.atan2(Math.cos(angleJ), Math.cos(angleI));\r
+ System.out.println("Angle " + angle + " i " + angleI + " j " + angleJ + " prev " + prevAngle);\r
+ if(!worldCoord)\r
+ axis = taxis;\r
+ if (useStep) {\r
+\r
+ //setOrientation(MathTools.getQuat(rotation));\r
+ AxisAngle4d rot = new AxisAngle4d(axis,angle-prevAngle);\r
+ Quat4d qrot = new Quat4d();\r
+ MathTools.getQuat(rot, qrot);\r
+ //prevAngle = angle;\r
+ qrot.mulInverse(worldOrientation);\r
+ \r
+ \r
+ if (stepMethod == 0) {\r
+ rot.set(qrot);\r
+ rot.angle = roundAngle(rot.angle);\r
+ //qrot.set(rot);\r
+ MathTools.getQuat(rot,qrot);\r
+ setOrientation(qrot);\r
+ } else if (stepMethod == 1){\r
+ \r
+ //Vector3d euler = MathTools.getEuler(qrot);\r
+ Vector3d euler = EulerTools.getEulerFromQuat(order, qrot);\r
+ euler.x = roundAngle(euler.x);\r
+ euler.y = roundAngle(euler.y);\r
+ euler.z = roundAngle(euler.z);\r
+ //Quat4d q = MathTools.getQuat(euler);\r
+ Quat4d q = EulerTools.getQuatFromEuler(order, euler);\r
+ setOrientation(q);\r
+ System.out.println(" (" + MathTools.radToDeg(euler.x) + " " + MathTools.radToDeg(euler.y) + " " + MathTools.radToDeg(euler.z) + ") " + qrot + " "+ q);\r
+ } else {\r
+ setOrientation(qrot);\r
+ }\r
+ \r
+ } else {\r
+ if (worldCoord) {\r
+ //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,angle-prevAngle));\r
+ AxisAngle4d aa = MathTools.getAxisAngle(node.getWorldOrientation());\r
+ AxisAngle4d rot = new AxisAngle4d(axis,angle-prevAngle);\r
+ MathTools.multiplyOrientation(aa, rot);\r
+ setWorldOrientation(MathTools.getQuat(rot));\r
+ } else {\r
+ AxisAngle4d aa = MathTools.getAxisAngle(node.getOrientation());\r
+ AxisAngle4d rot = new AxisAngle4d(axis,angle-prevAngle);\r
+ MathTools.multiplyOrientation(aa, rot);\r
+ setOrientation(MathTools.getQuat(rot));\r
+ //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getLocalOrientation(), new AxisAngle4d(axis,angle-prevAngle));\r
+ }\r
+ prevAngle = angle;\r
+ }\r
+ \r
+ } else if (inputType == InputType.NONINTERSECT){\r
+\r
+ double s[] = new double[2];\r
+ MathTools.intersectStraightStraight(ray.pos, ray.dir, p, i, new Vector3d(), new Vector3d(), s);\r
+ if(!worldCoord)\r
+ axis = taxis;\r
+ if (useStep) {\r
+ //setOrientation(MathTools.getQuat(rotation));\r
+ AxisAngle4d rot = new AxisAngle4d(axis,s[1] - prevS);\r
+ \r
+ Quat4d qrot = new Quat4d();\r
+ //qrot.set(rot);\r
+ MathTools.getQuat(rot, qrot);\r
+ //prevAngle = angle;\r
+ qrot.mulInverse(worldOrientation);\r
+ \r
+ \r
+ if (stepMethod == 0) {\r
+ rot.set(qrot);\r
+ rot.angle = roundAngle(rot.angle);\r
+ //qrot.set(rot);\r
+ MathTools.getQuat(rot,qrot);\r
+ setOrientation(qrot);\r
+ } else if (stepMethod == 1){\r
+ \r
+ //Vector3d euler = MathTools.getEuler(qrot);\r
+ Vector3d euler = EulerTools.getEulerFromQuat(order, qrot);\r
+ euler.x = roundAngle(euler.x);\r
+ euler.y = roundAngle(euler.y);\r
+ euler.z = roundAngle(euler.z);\r
+ //Quat4d q = MathTools.getQuat(euler);\r
+ Quat4d q = EulerTools.getQuatFromEuler(order, euler);\r
+ setOrientation(q);\r
+ System.out.println(" (" + MathTools.radToDeg(euler.x) + " " + MathTools.radToDeg(euler.y) + " " + MathTools.radToDeg(euler.z) + ") " + qrot + " "+ q);\r
+ } else {\r
+ setOrientation(qrot);\r
+ }\r
+ prevS = s[1];\r
+ \r
+// G3DTools.setOrientation(mo.getG3DNode(graph).getLocalOrientation(), rotations.get(mo));\r
+// G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,s[1] - prevS));\r
+// AxisAngle4d aa = G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation());\r
+// rotations.put(mo, aa);\r
+// Vector3d euler = MathTools.getEuler(aa);\r
+// euler.x = roundAngle(euler.x);\r
+// euler.y = roundAngle(euler.y);\r
+// euler.z = roundAngle(euler.z);\r
+// aa = MathTools.getFromEuler2(euler);\r
+// prevS = s[1];\r
+// G3DTools.setOrientation(mo.getG3DNode(graph).getLocalOrientation(), aa);\r
+// Vector3d e = MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()));\r
+// e.scale(180.0/Math.PI);\r
+// text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + e + " ";\r
+ \r
+ \r
+ } else {\r
+ if (worldCoord) {\r
+ AxisAngle4d aa = MathTools.getAxisAngle(node.getWorldOrientation());\r
+ AxisAngle4d rot = new AxisAngle4d(axis,s[1] - prevS);\r
+ MathTools.multiplyOrientation(aa, rot);\r
+ setWorldOrientation(MathTools.getQuat(rot));\r
+ //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,s[1] - prevS));\r
+ } else {\r
+ AxisAngle4d aa = MathTools.getAxisAngle(node.getOrientation());\r
+ AxisAngle4d rot = new AxisAngle4d(axis,s[1] - prevS);\r
+ MathTools.multiplyOrientation(aa, rot);\r
+ setOrientation(MathTools.getQuat(rot));\r
+ //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getLocalOrientation(), new AxisAngle4d(axis,s[1] - prevS));\r
+ }\r
+ //text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation())) + " ";\r
+ prevS = s[1];\r
+ \r
+ }\r
+ \r
+ } else {\r
+ if (worldCoord) {\r
+ AxisAngle4d aa = MathTools.getAxisAngle(node.getWorldOrientation());\r
+ AxisAngle4d rot = new AxisAngle4d(axis,Math.PI * 0.5);\r
+ MathTools.multiplyOrientation(aa, rot);\r
+ setWorldOrientation(MathTools.getQuat(rot));\r
+ //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,Math.PI * 0.5));\r
+ } else {\r
+ AxisAngle4d aa = MathTools.getAxisAngle(node.getOrientation());\r
+ AxisAngle4d rot = new AxisAngle4d(axis,Math.PI * 0.5);\r
+ MathTools.multiplyOrientation(aa, rot);\r
+ setOrientation(MathTools.getQuat(rot));\r
+ //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getLocalOrientation(), new AxisAngle4d(axis,Math.PI * 0.5));\r
+ }\r
+ // text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation())) + " ";\r
+ \r
+ }\r
+ //setInfoText(text);\r
+ \r
+ }\r
+ \r
+ protected void setOrientation(Quat4d q) {\r
+ node.setOrientation(q);\r
+ }\r
+ \r
+ protected void setWorldOrientation(Quat4d q) {\r
+ node.setWorldOrientation(q);\r
+ }\r
+ \r
+ @Override\r
+ public void mouseMoved(MouseEvent e) {\r
+ panel.getDefaultAction().mouseMoved(e);\r
+ }\r
+ \r
+ private Vector3d getRotationAxis() {\r
+ switch (index) {\r
+ case X:\r
+ return new Vector3d(1.0, 0.0, 0.0);\r
+ case Y:\r
+ return new Vector3d(0.0, 1.0, 0.0);\r
+ case Z:\r
+ return new Vector3d(0.0, 0.0, 1.0);\r
+ case P:\r
+ Vector3d axis = new Vector3d(panel.GetRenderer().GetActiveCamera()\r
+ .GetDirectionOfProjection());\r
+ axis.normalize();\r
+ return axis;\r
+ default:\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ private double prevS = 0.0;\r
+ \r
+ private Vector3d i = new Vector3d();\r
+ private Vector3d j = new Vector3d();\r
+ private double prevAngle = 0;\r
+\r
+ enum InputType{INTERSECT,NONINTERSECT,KEY,NONE};\r
+ InputType inputType;\r
+ private boolean useStep = false;\r
+ \r
+ \r
+ \r
+ private double roundAngle(double angle) {\r
+ while (angle < - Math.PI)\r
+ angle += Math.PI*2.0;\r
+ while (angle > Math.PI)\r
+ angle -= Math.PI*2.0;\r
+ \r
+ \r
+ int index = 0;\r
+ while (angle > angles[index])\r
+ index++;\r
+ if (index == 0) {\r
+ angle = angles[0];\r
+ } else {\r
+ double d = angle - angles[index - 1];\r
+ double d2 = angles[index] - angle;\r
+ if (d < d2)\r
+ angle = angles[index - 1];\r
+ else\r
+ angle = angles[index];\r
+ }\r
+ return angle;\r
+ }\r
+ \r
+}\r