]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/action/TranslateAction.java
3D framework (Simca 2012)
[simantics/3d.git] / org.simantics.g3d.vtk / src / org / simantics / g3d / vtk / action / TranslateAction.java
diff --git a/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/action/TranslateAction.java b/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/action/TranslateAction.java
new file mode 100644 (file)
index 0000000..785e549
--- /dev/null
@@ -0,0 +1,475 @@
+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
+import java.math.BigDecimal;\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.MathTools;\r
+import org.simantics.g3d.math.Ray;\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.TranslateAxisGizmo;\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
+public class TranslateAction 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 XY = 3;\r
+    public static final int XZ = 4;\r
+    public static final int YZ = 5;\r
+    public static final int P = 6;\r
+\r
+       private VTKNodeMap nodeMap;\r
+       //private TranslateGizmo  gizmo = new TranslateGizmo();\r
+       private TranslateAxisGizmo gizmo = new TranslateAxisGizmo();\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
+       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
+       \r
+       public IG3DNode getNode() {\r
+               return node;\r
+       }\r
+       \r
+       public TranslateAction(InteractiveVtkPanel panel, VTKNodeMap nodeMap) {\r
+               super(panel);\r
+               setImageDescriptor(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_out.png"));\r
+               setText("Translate");\r
+               this.nodeMap = nodeMap;\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
+               \r
+               update();\r
+               //panel.repaint();\r
+       }\r
+       \r
+       @Override\r
+       public void keyReleased(KeyEvent e) {\r
+               \r
+       }\r
+       \r
+       @Override\r
+       public void keyTyped(KeyEvent e) {\r
+               \r
+       }\r
+       \r
+       @Override\r
+       public void mouseClicked(MouseEvent e) {\r
+               if (e.getClickCount() > 1) {\r
+                       if (isOverNode(e)) {\r
+                               return;\r
+                       } else {\r
+                               panel.useDefaultAction();\r
+                       }\r
+                       //if(!gizmo.isPartOf(actor))\r
+                       //      panel.useDefaultAction();\r
+                       \r
+               }\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
+       @Override\r
+       public void mouseEntered(MouseEvent e) {\r
+               \r
+       }\r
+       \r
+       @Override\r
+       public void mouseExited(MouseEvent e) {\r
+               \r
+       }\r
+       \r
+       int index = P;\r
+       boolean valid = false;\r
+       private boolean worldCoord = true;\r
+       private AxisAngle4d aa = null;\r
+       private Quat4d q = null;\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
+               if (node == null)\r
+                       return;\r
+               if (worldCoord) {\r
+                       gizmo.setRotation(new AxisAngle4d());\r
+                       aa = null;\r
+                       q = null;\r
+               } else {\r
+                       aa = new AxisAngle4d();\r
+                       aa.set(((IG3DNode)node.getParent()).getWorldOrientation());\r
+                       gizmo.setRotation(aa);\r
+                       q = new Quat4d();\r
+                       MathTools.getQuat(aa, q);\r
+               }\r
+               \r
+               Vector3d nodePos = node.getWorldPosition();\r
+               //System.out.println(nodePos);\r
+               gizmo.setPosition(nodePos);\r
+\r
+               \r
+               Point3d camPos = new Point3d(panel.GetRenderer().GetActiveCamera().GetPosition());\r
+               Vector3d p = new Vector3d(nodePos);\r
+               p.sub(camPos);\r
+               \r
+               if (q != null) {\r
+                       Quat4d qi = new Quat4d(q);\r
+                       qi.inverse();\r
+                       MathTools.rotate(q, 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
+               panel.repaint();\r
+       }\r
+       \r
+       Vector3d prevTranslate = null;\r
+       \r
+       @Override\r
+       public void mousePressed(MouseEvent e) {\r
+               if (e.getButton() == MouseEvent.BUTTON1) {\r
+\r
+                       if (isOverNode(e)) {\r
+                               prevTranslate = getTranslate(e.getX(), e.getY());\r
+                               valid = true;\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
+               //index = gizmo.getTranslateAxis(actor);\r
+               //if (index == -1) {\r
+               //  valid = false;\r
+               //      panel.getDefaultAction().mousePressed(e);\r
+               //      return;\r
+               //}\r
+               //valid = true; \r
+               //prevTranslate = getTranslate(e.getX(), e.getY());\r
+               //System.out.println("start translate " + prevTranslate);\r
+       }\r
+       \r
+       \r
+       \r
+       @Override\r
+       public void mouseReleased(MouseEvent e) {\r
+               if (e.getButton() == MouseEvent.BUTTON1) {\r
+                       valid = false;\r
+                       prevTranslate = 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
+                       \r
+                       Vector3d translate = getTranslate(e.getX(), e.getY(), prevTranslate);\r
+                       //System.out.println("translate " + translate);\r
+                       if (translate == null)\r
+                               return;\r
+                       boolean step = ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0);\r
+                       if (worldCoord) {\r
+                               Vector3d pos = new Vector3d(node.getWorldPosition());\r
+                               pos.add(translate);\r
+                               pos = constaints(pos, step);\r
+                               setWorldPos(pos);\r
+                       } else {\r
+                               Vector3d pos = new Vector3d(node.getPosition());\r
+                               pos.add(translate);\r
+                               pos = constaints(pos, step);\r
+                               setPos(pos);\r
+                       }\r
+                       //mapping.rangeModified(node);\r
+                       \r
+                       //nodeMap.modified(node);\r
+                       update();\r
+               } else {\r
+                       panel.getDefaultAction().mouseDragged(e);\r
+                       update();\r
+               }\r
+       }\r
+       \r
+       protected void setPos(Vector3d pos) {\r
+               node.setPosition(pos);\r
+       }\r
+       \r
+       protected void setWorldPos(Vector3d pos) {\r
+               node.setWorldPosition(pos);\r
+       }\r
+       \r
+        private double istep = 10.0;\r
+        private int decimals = 2;\r
+       \r
+       private Vector3d constaints(Vector3d p, boolean step) {\r
+               if(!step)\r
+                       return p;\r
+               switch (index) {\r
+               case X:\r
+                        p.x = Math.round(istep * p.x) / istep;\r
+             BigDecimal bx = new BigDecimal(p.x);\r
+             bx.setScale(decimals, BigDecimal.ROUND_HALF_UP);\r
+             p.x = bx.doubleValue();\r
+                       break;\r
+               case Y:\r
+                        p.y = Math.round(istep * p.y) / istep;\r
+             BigDecimal by = new BigDecimal(p.y);\r
+             by.setScale(decimals, BigDecimal.ROUND_HALF_UP);\r
+             p.y = by.doubleValue();\r
+                       break;\r
+                       \r
+               case Z:\r
+                        p.z = Math.round(istep * p.z) / istep;\r
+             BigDecimal bz = new BigDecimal(p.z);\r
+             bz.setScale(decimals, BigDecimal.ROUND_HALF_UP);\r
+             p.z = bz.doubleValue();\r
+                       break;\r
+               }\r
+               return p;\r
+       }\r
+       \r
+       @Override\r
+       public void mouseMoved(MouseEvent e) {\r
+               panel.getDefaultAction().mouseMoved(e);\r
+       }\r
+       \r
+       Vector3d getTranslate(double x, double y) {\r
+               return getTranslate(x, y, new Vector3d());\r
+       }\r
+       \r
+       Vector3d getTranslate(double x, double y, Vector3d offset) {\r
+               Vector3d translate = new Vector3d();\r
+               \r
+               Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(),x, y);\r
+               \r
+               Vector3d p = node.getWorldPosition();\r
+               Vector3d dir = null;\r
+               \r
+               switch (index) {\r
+               case P:\r
+                       Vector3d normal = new Vector3d(panel.GetRenderer().GetActiveCamera().GetDirectionOfProjection());\r
+                       if (!worldCoord) {\r
+                               MathTools.rotate(q, normal, normal);\r
+                       }\r
+                       normal.normalize();\r
+                       double s[] = new double[1];\r
+            Vector3d r = new Vector3d();\r
+            if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {\r
+                r.sub(p);\r
+                translate.x = r.x;\r
+                translate.y = r.y;\r
+                translate.z = r.z;\r
+            }\r
+            break;\r
+\r
+                case X :\r
+                   dir = new Vector3d(1.0,0.0,0.0);\r
+                   if(!worldCoord)\r
+                       MathTools.rotate(q, dir, dir);\r
+                   Vector3d i1 = new Vector3d();\r
+                   Vector3d i2 = new Vector3d();\r
+                   s = new double[2];\r
+                   MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);\r
+                   translate.x = s[0];\r
+                   \r
+                   break;\r
+               case Y :\r
+                   dir = new Vector3d(0.0,1.0,0.0);\r
+                   if(!worldCoord)\r
+                       MathTools.rotate(q, dir, dir);\r
+                   i1 = new Vector3d();\r
+                   i2 = new Vector3d();\r
+                   s = new double[2];\r
+                   MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);\r
+                   translate.y = s[0];\r
+                   break;\r
+               case Z :\r
+                   dir = new Vector3d(0.0,0.0,1.0);\r
+                   if(!worldCoord)\r
+                       MathTools.rotate(q, dir, dir);\r
+                   i1 = new Vector3d();\r
+                   i2 = new Vector3d();\r
+                   s = new double[2];\r
+                   MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);\r
+                   translate.z = s[0];\r
+                   break;\r
+               case XY :\r
+                   normal = new Vector3d(0.0,0.0,1.0);\r
+                   if(!worldCoord)\r
+                       MathTools.rotate(q, normal, normal);\r
+                   r = new Vector3d();\r
+                   if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {\r
+                       r.sub(p);\r
+                       translate.x = r.x;\r
+                       translate.y = r.y;\r
+                   }\r
+                   break;\r
+               case XZ :\r
+                   normal = new Vector3d(0.0,1.0,0.0);\r
+                   if(!worldCoord)\r
+                       MathTools.rotate(q, normal, normal);\r
+                   r = new Vector3d();\r
+                   if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {\r
+                       r.sub(p);\r
+                       translate.x = r.x;\r
+                       translate.z = r.z;\r
+                   }\r
+                   break;\r
+               case YZ :\r
+                   normal = new Vector3d(1.0,0.0,0.0);\r
+                   if(!worldCoord)\r
+                       MathTools.rotate(q, normal, normal);\r
+                   r = new Vector3d();\r
+                   if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {\r
+                       r.sub(p);\r
+                       translate.y = r.y;\r
+                       translate.z = r.z;\r
+                   }\r
+                   break;\r
+               default :\r
+                   \r
+                   return null;\r
+               }\r
+               translate.sub(offset);\r
+               return translate;\r
+       }\r
+       \r
+}\r