RobotViewer.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #include "RobotViewer.h"
25 
26 #include <Inventor/nodes/SoSeparator.h>
27 #include <Inventor/nodes/SoPickStyle.h>
28 #include <Inventor/nodes/SoMaterial.h>
29 #include <Inventor/nodes/SoDrawStyle.h>
30 #include <Inventor/nodes/SoVertexProperty.h>
31 #include <Inventor/nodes/SoLineSet.h>
32 
33 #include <Inventor/events/SoMouseButtonEvent.h>
34 #include <Inventor/events/SoLocation2Event.h>
35 
36 armarx::RobotViewer::RobotViewer(QWidget* widget) : SoQtExaminerViewer(widget), sceneRootNode(new SoSeparator), contentRootNode(new SoSeparator), camera(new SoPerspectiveCamera)
37 {
38  this->setBackgroundColor(SbColor(150 / 255.0f, 150 / 255.0f, 150 / 255.0f));
39  this->setAccumulationBuffer(this->getAccumulationBuffer());
40  this->setHeadlight(true);
41  this->setViewing(false);
42  this->setDecoration(false);
43 #ifdef WIN32
44 #ifndef _DEBUG
45  this->setAntialiasing(true, 4);
46 #endif
47 #endif
48  this->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_BLEND);
49  this->setFeedbackVisibility(true);
50 
51  //Create scene root node
52  sceneRootNode->ref();
53  this->setSceneGraph(sceneRootNode);
54 
55  //Add camera to scene
56  sceneRootNode->addChild(camera);
57  this->setCamera(camera);
58 
59  //Give camera standard position
60  camera->position.setValue(SbVec3f(10, -10, 5));
61  camera->pointAt(SbVec3f(0, 0, 0), SbVec3f(0, 0, 1));
62 
63  //Add gridfloor root and make it unpickable
64  SoSeparator* gridFloorRoot = new SoSeparator();
65  SoPickStyle* unpickable = new SoPickStyle();
66  unpickable->style = SoPickStyle::UNPICKABLE;
67  SoPickStyle* pickable = new SoPickStyle();
68  pickable->style = SoPickStyle::SHAPE;
69 
70  sceneRootNode->addChild(unpickable);
71  sceneRootNode->addChild(gridFloorRoot);
72  sceneRootNode->addChild(pickable);
73 
74  /*/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
75  Here we draw our grid floor. To change the way the grid floor is drawn change the following constants.
76  GRIDSIZE: How many lines to display for each direction of each axis.
77  E. g.: 2 would lead to 2 lines in negative and positive direction respectively, plus indicator for axis.
78  5 lines in sum.
79  GRIDUNIT: Factor for coin units, e.g. 2 means between 2 lines there is space for 2 coin units.
80  GRIDSUBSIZE: How many subunits to display between the larger lines. So 5 would lead to 3 lines between 2 large lines for 5
81  subunits.
82  GRIDPATTERN: Pattern for sublines. Bitpattern, where 1 is line and 0 is no line.
83  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
84  const int GRIDSIZE = 3;
85  const int GRIDUNIT = 15;
86  const int GRIDSUBSIZE = 10;
87  const unsigned short GRIDPATTERN = 0xCCCC;
88 
89  //Red material for X axis
90  SoMaterial* red = new SoMaterial;
91  red->diffuseColor = SbColor(1, 0, 0);
92  //Green material for Y axis
93  SoMaterial* green = new SoMaterial;
94  green->diffuseColor = SbColor(0, 1, 0);
95  //Blue material for Z axis
96  SoMaterial* blue = new SoMaterial;
97  blue->diffuseColor = SbColor(0, 0, 1);
98 
99  //Small lines
100  SoDrawStyle* thinStyle = new SoDrawStyle;
101  thinStyle->lineWidth = 1;
102  thinStyle->linePattern = GRIDPATTERN;
103  //Larger lines
104  SoDrawStyle* largeStyle = new SoDrawStyle;
105  largeStyle->lineWidth = 2;
106 
107  //Our set of vertices for the grid lines
108  SoVertexProperty* vertices = new SoVertexProperty;
109  SoVertexProperty* subVertices = new SoVertexProperty;
110  SoVertexProperty* xVertices = new SoVertexProperty;
111  SoVertexProperty* yVertices = new SoVertexProperty;
112  SoVertexProperty* zVertices = new SoVertexProperty;
113 
114  //Definition of which vertex belongs to which line and should be connected
115  SoLineSet* lines = new SoLineSet;
116  SoLineSet* subLines = new SoLineSet;
117  SoLineSet* xLines = new SoLineSet;
118  SoLineSet* yLines = new SoLineSet;
119  SoLineSet* zLines = new SoLineSet;
120 
121  //Add 2 vertices for X axis
122  xVertices->vertex.set1Value(0, GRIDSIZE * GRIDUNIT, 0, 0);
123  xVertices->vertex.set1Value(1, -(GRIDSIZE * GRIDUNIT), 0, 0);
124  //Connect them to a line by adding '2' to numVertices at the correct position
125  xLines->numVertices.set1Value(0, 2);
126 
127  //Y axis
128  yVertices->vertex.set1Value(0, 0, GRIDSIZE * GRIDUNIT, 0);
129  yVertices->vertex.set1Value(1, 0, -(GRIDSIZE * GRIDUNIT), 0);
130  yLines->numVertices.set1Value(0, 2);
131 
132  //Z axis
133  zVertices->vertex.set1Value(0, 0, 0, GRIDSIZE * GRIDUNIT);
134  zVertices->vertex.set1Value(1, 0, 0, -(GRIDSIZE * GRIDUNIT));
135  zLines->numVertices.set1Value(0, 2);
136 
137  //Counters to keep track of vertex index
138  int verticescounter = 0;
139  int subverticescounter = 0;
140 
141  //Draw all lines parallel to the X and Y axis and all sublines, excepted axis itself
142  for (int i = -(GRIDSIZE * GRIDUNIT); i < GRIDUNIT * (GRIDSIZE + 1); i += GRIDUNIT)
143  {
144  if (i != 0)
145  {
146  vertices->vertex.set1Value(verticescounter++, GRIDSIZE * GRIDUNIT, i, 0);
147  vertices->vertex.set1Value(verticescounter++, -(GRIDSIZE * GRIDUNIT), i, 0);
148  lines->numVertices.set1Value((verticescounter - 1) / 2, 2);
149 
150  vertices->vertex.set1Value(verticescounter++, i, GRIDSIZE * GRIDUNIT, 0);
151  vertices->vertex.set1Value(verticescounter++, i, -(GRIDSIZE * GRIDUNIT), 0);
152  lines->numVertices.set1Value((verticescounter - 1) / 2, 2);
153  }
154 
155  //If this is not the last line to draw, draw sublines
156  if (i < GRIDUNIT * GRIDSIZE)
157  {
158  float delta = (float)GRIDUNIT / (float)GRIDSUBSIZE;
159 
160  for (int n = 1; n < GRIDSUBSIZE; n++)
161  {
162  subVertices->vertex.set1Value(subverticescounter++, GRIDSIZE * GRIDUNIT, (float)i + (float)n * delta, 0);
163  subVertices->vertex.set1Value(subverticescounter++, -(GRIDSIZE * GRIDUNIT), (float)i + (float)n * delta, 0);
164  subLines->numVertices.set1Value((subverticescounter - 1) / 2, 2);
165 
166  subVertices->vertex.set1Value(subverticescounter++, (float)i + (float)n * delta, GRIDSIZE * GRIDUNIT, 0);
167  subVertices->vertex.set1Value(subverticescounter++, (float)i + (float)n * delta, -(GRIDSIZE * GRIDUNIT), 0);
168  subLines->numVertices.set1Value((subverticescounter - 1) / 2, 2);
169  }
170  }
171  }
172 
173 
174  lines->vertexProperty.setValue(vertices);
175  subLines->vertexProperty.setValue(subVertices);
176  xLines->vertexProperty.setValue(xVertices);
177  yLines->vertexProperty.setValue(yVertices);
178  zLines->vertexProperty.setValue(zVertices);
179 
180  gridFloorRoot->addChild(thinStyle);
181  gridFloorRoot->addChild(subLines);
182  gridFloorRoot->addChild(largeStyle);
183  gridFloorRoot->addChild(lines);
184  gridFloorRoot->addChild(red);
185  gridFloorRoot->addChild(xLines);
186  gridFloorRoot->addChild(green);
187  gridFloorRoot->addChild(yLines);
188  gridFloorRoot->addChild(blue);
189  gridFloorRoot->addChild(zLines);
190 
191  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
192  //Gridfloor done
193 
194  //Create content root node
195  sceneRootNode->addChild(contentRootNode);
196 }
197 
198 armarx::RobotViewer::~RobotViewer()
199 {
200  sceneRootNode->unref();
201 }
202 
203 SoSeparator* armarx::RobotViewer::getRootNode()
204 {
205  return this->contentRootNode;
206 }
207 
208 void armarx::RobotViewer::cameraViewAll()
209 {
210  camera->viewAll(this->contentRootNode, SbViewportRegion());
211 }
212 
213 //Override the default navigation behaviour of the SoQtExaminerViewer
214 SbBool armarx::RobotViewer::processSoEvent(const SoEvent* const event)
215 {
216  const SoType type(event->getTypeId());
217 
218  //Remapping mouse press events
219  if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId()))
220  {
221  SoMouseButtonEvent* const ev = (SoMouseButtonEvent*) event;
222  const int button = ev->getButton();
223  const SbBool press = ev->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;
224 
225  //LEFT MOUSE BUTTON
226  if (button == SoMouseButtonEvent::BUTTON1)
227  {
228  SoQtExaminerViewer::processSoEvent(ev);
229  }
230 
231  //MIDDLE MOUSE BUTTON
232  if (button == SoMouseButtonEvent::BUTTON3)
233  {
234  /*Middle mouse button now is used for all changes in camera perspective.
235  To also display the cool little rotation cursor, viewing mode is set to on
236  while button is down*/
237 
238  //Enable or disable viewing mode while BUTTON3 pressed
239  if (press)
240  {
241  if (!this->isViewing())
242  {
243  this->setViewing(true);
244  }
245  }
246  else
247  {
248  if (this->isViewing())
249  {
250  this->setViewing(false);
251  }
252  }
253 
254  //Remap BUTTON3 to BUTTON1
255  ev->setButton(SoMouseButtonEvent::BUTTON1);
256 
257  //Make sure this REALLY only can happen when viewing mode is on.
258  //Zooming can also turn it on and it leads to weird effects when doing both
259  //(deselections in scene etc.) because SoQtExaminerViewer passes BUTTON1
260  //events up to scenegraph when not in viewing mode.
261  if (this->isViewing())
262  {
263  return SoQtExaminerViewer::processSoEvent(ev);
264  }
265  }
266 
267  //MOUSE WHEEL UP AND DOWN
268  if (button == SoMouseButtonEvent::BUTTON4 || button == SoMouseButtonEvent::BUTTON5)
269  {
270  /*Zooming is allowed, so just use it. We have to temporarily turn viewing mode
271  on to make SoQtExaminerViewer allow zooming.*/
272 
273  //Swap BUTTON4 and BUTTON5 because zooming out while scrolling up is just retarded
274  ev->setButton(button == SoMouseButtonEvent::BUTTON4 ?
275  SoMouseButtonEvent::BUTTON5 : SoMouseButtonEvent::BUTTON4);
276 
277  //Zooming is allowed, so just pass it and temporarily set viewing mode on, if it is not already
278  //(otherwise coin gives us warning messages...)
279  if (!this->isViewing())
280  {
281  if (!this->isViewing())
282  {
283  this->setViewing(true);
284  }
285 
286  SoQtExaminerViewer::processSoEvent(ev);
287 
288  if (this->isViewing())
289  {
290  this->setViewing(false);
291  }
292  }
293  else
294  {
295  SoQtExaminerViewer::processSoEvent(ev);
296  }
297 
298  return TRUE;
299  }
300  }
301 
302  // Keyboard handling
303  if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId()))
304  {
305  const SoKeyboardEvent* const ev = (const SoKeyboardEvent*) event;
306 
307  /*The escape key and super key (windows key) is used to switch between
308  viewing modes. We need to disable this behaviour completely.*/
309 
310  //65513 seems to be the super key, which is not available in the enum of keys in coin....
311  if (ev->getKey() == SoKeyboardEvent::ESCAPE || ev->getKey() == 65513)
312  {
313  return TRUE;
314  }
315  else if (ev->getKey() == SoKeyboardEvent::S && ev->getState() == SoButtonEvent::DOWN)
316  {
317  if (!this->isSeekMode())
318  {
319  if (!this->isViewing())
320  {
321  this->setViewing(true);
322  }
323 
324  SoQtExaminerViewer::processSoEvent(ev);
325  this->setSeekTime(0.5);
326  this->seekToPoint(ev->getPosition());
327 
328  if (this->isViewing())
329  {
330  this->setViewing(false);
331  }
332  }
333  }
334  else
335  {
336  SoQtExaminerViewer::processSoEvent(ev);
337  }
338 
339  SoQtExaminerViewer::processSoEvent(ev);
340  }
341 
342  //Let all move events trough
343  if (type.isDerivedFrom(SoLocation2Event::getClassTypeId()))
344  {
345  return SoQtExaminerViewer::processSoEvent(event);
346  }
347 
348  //YOU SHALL NOT PASS!
349  return TRUE;
350 
351  return SoQtExaminerViewer::processSoEvent(event);
352 }
RobotViewer.h
armarx::RobotViewer::RobotViewer
RobotViewer(QWidget *widget)
Definition: RobotViewer.cpp:36