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