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
205armarx::RobotViewer::~RobotViewer()
206{
207 sceneRootNode->unref();
208}
209
210SoSeparator*
211armarx::RobotViewer::getRootNode()
212{
213 return this->contentRootNode;
214}
215
216void
217armarx::RobotViewer::cameraViewAll()
218{
219 camera->viewAll(this->contentRootNode, SbViewportRegion());
220}
221
222//Override the default navigation behaviour of the SoQtExaminerViewer
223SbBool
224armarx::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(QWidget *widget)