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