In this section, you will learn how to use the classes provided by the library osgVP-manipulator. You will learn how to add a manipulator to a node of the scene-graph and how to transform it, as well how to manage all the manipulators present in the scene. We provide the same manipulators implemented in OSG, as well as a new type of manipulator that allows the transformation of individual vertex of a given geometry. The Manipulator node -------------------- To add a **Manipulator** to an existing node is a very simple task. First of all, you have to create an instance of the class Manipulator. There are two possibilities to create a Manipulator. :: public Manipulator(); public Manipulator(String draggerType); The only difference between these two constructors is what type of manipulator will be created. The argument *draggerType* specifies this type. If no argument is passed, the default manipulator will be created. Types of dragger ================ Here is a list with all the draggers available in this version of the library: **Scale1DDragger**: Scales the object over an axis. **Scale2DDragger**: Scales the object over two given axis. **ScaleAxisDragger**: Scale the object over the three axis. **TabBoxDragger**: Scales the object through the eight corners of a box containing the object. Also permits to translate the object picking on one of the six planes which form this box. This is the default manipulator. **TabPlaneDragger**: Scales and translates the object through a plane. **TabPlaneTrackballDragger**: Scales and translates the object through a plane. Also, rotates the object through a sphere. **TrackballDragger**: Rotates the object through a sphere that contains it. **Translate1DDragger**: Translates the object over an axis. **Translate2DDragger**: Translates the object over two given axis. **TranslateAxisDragger**: Translates the object over the three axis. **TranslatePlaneDragger**: Translates the object over a plane. Adding a Node ============= Once a Manipulator has been created, the method :: public boolean addChild(Node child); inserts the given node inside the manipulator. This method can be used as many times as wanted, therefore a Manipulator can transform several objects at the same time. Other available methods ======================= :: public void setDragger(String draggerType); Changes the dragger type. :: public Node getChild(int i); Returns the node at the position *i*. :: public int getNumChildren(); Returns the number of nodes being manipulated at the moment. :: public boolean removeChild(Node child); Removes the child :: public boolean removeChildren(); Removes all the chidren inside the Manipulator. :: public Group getSelection(); Returns the subgraph with all the objects transformed. :: public boolean removeChild(int i); Removes the child number *i* of the Manipulator :: public void setChild(int i, Node node); Puts the node as the chid number i of the Manipulator. :: public String getDragger(); Returns the dragger type. Setting the Manipulator Handler ------------------------------- Once one or more nodes have been added to a manipulator, you can instantiate the class ManipulatorHandler in order to interact with them. :: ManipulatorHandler(); Once the new class has been created, it must be added as an EventHandler to the OSGViewer. :: getCanvas3D().getOSGViewer().addEventHandler(_hand); Now, the object can be transformed depending on the dragger type selected. If your application wants to enable or disable this handler, use the method: :: public void setActive(boolean active); Example: Manipulate an object =============================== Let's see an example that shows the use of the Manipulator node. (Note that this is not exactly the same code present in the library examples. It has been simplified to give a better understanding of the functionality. For example, the try/catch clauses have been removed) :: private ManipulatorHandler _hand; private Manipulator _manip; private Node _cow; _cow = osgDB.readNodeFileFromResources("/cow.ive"); _manip = new Manipulator(Manipulator.DraggerType.TRANSLATE_PLANE_DRAGGER); _manip.addChild(_cow); _hand = new ManipulatorHandler(); getCanvas3D().getOSGViewer().addEventHandler(_hand); In this example, the 3D model stored in the file *cow.ive* is loaded as a node. The next step is to create an instance of Manipulator. In this case, we have chosen the *TRANSLATE_PLANE_DRAGGER*, which draws a plane around the object and allows to translate the objects clicking on it. Later, we add the loaded node as a child of the Manipulator. Instantiating a ManipulatorHandler and adding it to the OSGViewer ends the process. .. figure:: images/manipulator.png :align: center :scale: 32 Node being Manipulated. Managing the Scene with EditionManager -------------------------------------- EditionManager is a class created to help the developers to build a more advanced edition systems. It allows the creation and management of many Manipulators at the same time, and even permits the interaction between them. Its use is very similar to the Manipulator class. The following example shows its use: :: _manager = new EditionManager(scene); getCanvas3D().addKeyListener(new ViewerStateListener(getCanvas3D() .getOSGViewer())); getCanvas3D().addKeyListener(this); _hand = new ManipulatorHandler(); getCanvas3D().getOSGViewer().addEventHandler(_hand); getCanvas3D().addMouseListener(this); Methods implemented by EM ========================= :: public Node getScene() Gets the part of the scene not manipulated. :: public Group getTransformedScene() Gets the whole transformed scene without the draggers. :: public void setScene(Node node) Changes the whole scene in the EditionManager. :: public int getNumChildren() Returns the number of children. :: public Manipulator addNode(int i) Creates a manipulator for the node at the position *i* in the scene branch of the EM. :: public Node removeNode(Node object) Extracts the node from the manipulator and returns it to the scene branch. :: public void removeAllNodes() Extract all transformed nodes and put them in the scene branch. :: public void deleteSelectedNodes() Deletes all the Manipulators and the nodes inside them. :: public void changeDragger(String draggerType) Changes the type of all the active draggers. :: public String getDraggerType() Returns the type of the dragger. :: public void group() Gets all manipulators in the scene and creates one with all of them. :: public void ungroup() Separates different nodes present in a manipulator and makes one manipulator for each of them. Implementing the picking functionality ====================================== To interact with the EditionManager class, your Java application must implement at least one *MouseListener*. The following code shows one simple example. :: public void mouseClicked(MouseEvent arg0) { if (arg0.getButton() == MouseEvent.BUTTON1) { Intersections polytopeHits = getCanvas3D().getOSGViewer() .rayPick(_manager, arg0.getX(), arg0.getY(), Manipulator.NEG_MANIPULATOR_NODEMASK); if (polytopeHits.containsIntersections()) { Intersection hit = polytopeHits. getFirstIntersection(); Node nodeHit = (Node) (hit.getNodePath().get(2)); int k; k = nodeHit.getParent(0).getChildIndex(nodeHit); AddSelectionCommand addCommand = new AddSelectionCommand(k, _manager); addCommand.execute(); _commands.add(addCommand); } else { RemoveAllSelectionCommand removeAllCommand = new RemoveAllSelectionCommand(_manager); removeAllCommand.execute(); _commands.add(removeAllCommand); } } } In this example, when the left button of the mouse is clicked, it computes the intersections with the objects present in the scene and stores the first object that intersects. Later, the subgraph containing the object is included in a new Manipulator. This process is shown in the figure 5.1: .. figure:: images/editionmanager.png :align: center :scale: 50 Adding a node to the EditionManager. If the mouse is clicked and no intersections are computed, the listener makes all the manipulators dissapear. One important part is how to extract the node to add to the EditionManager. In this example, we are assuming that the EM is the root node of the scene, therefore the nodepath level selected is 2 (as can be seen in the figure 5.1 ). If the EM is in a sublevel of the graph, the nodepath level selected must be changed. For example, if the EM is a child of the root of the scene, the nodepath level selected must be 3. The GeometryManipulator node ----------------------------- The Manipulator node transforms the objets through a MatrixTransform in the scene-graph. In this way, the transformations are applied to the whole subgraph below it. To achieve a more advanced functionality that allows to edit each vertex of the object individually, we have created the GeometryManipulator node. The use of this node is very similar to the Manipulator. First of all, you have to instantiate the class GeometryManipulator with the following method: :: public GeometryManipulator(Geometry geo, Vector indexArray); The first argument is the Geometry to be manipulated, the second is a vector that contains the selected vertex indices of that geometry. The ManipulatorHandler class must be instantiated and added to the OSGViewer to transform the vertices too. In the next figure you can see a geometry with some of its vertices being manipulated. .. figure:: images/geometrymanipulator.png :align: center :scale: 30 GeometryManipulator example.