Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/osgview/GUIOSGView.cpp
169665 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file GUIOSGView.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Michael Behrisch
17
/// @author Mirko Barthauer
18
/// @date 19.01.2012
19
///
20
// An OSG-based 3D view on the simulation
21
/****************************************************************************/
22
#include <config.h>
23
24
#ifdef HAVE_OSG
25
26
#include <cmath>
27
#include <fxkeys.h>
28
#include <iostream>
29
#include <limits>
30
#include <utility>
31
#include <foreign/rtree/SUMORTree.h>
32
#include <gui/GUIApplicationWindow.h>
33
#include <gui/GUISUMOViewParent.h>
34
#include <gui/GUIViewTraffic.h>
35
#include <guisim/GUIEdge.h>
36
#include <guisim/GUIJunctionWrapper.h>
37
#include <guisim/GUILane.h>
38
#include <guisim/GUINet.h>
39
#include <guisim/GUIPerson.h>
40
#include <guisim/GUIVehicle.h>
41
#include <microsim/MSEdge.h>
42
#include <microsim/MSEdgeControl.h>
43
#include <microsim/MSLane.h>
44
#include <microsim/MSNet.h>
45
#include <microsim/MSVehicleControl.h>
46
#include <microsim/traffic_lights/MSSimpleTrafficLightLogic.h>
47
#include <microsim/traffic_lights/MSTLLogicControl.h>
48
#include <microsim/transportables/MSTransportableControl.h>
49
#include <utils/common/FileHelpers.h>
50
#include <utils/common/MsgHandler.h>
51
#include <utils/common/RGBColor.h>
52
#include <utils/common/StringUtils.h>
53
#include <utils/foxtools/MFXCheckableButton.h>
54
#include <utils/foxtools/MFXImageHelper.h>
55
#include <utils/geom/GeoConvHelper.h>
56
#include <utils/geom/PositionVector.h>
57
#include <utils/gui/div/GLHelper.h>
58
#include <utils/gui/div/GUIDesigns.h>
59
#include <utils/gui/div/GUIGlobalSelection.h>
60
#include <utils/gui/globjects/GLIncludes.h>
61
#include <utils/gui/globjects/GUIGlObjectStorage.h>
62
#include <utils/gui/images/GUIIconSubSys.h>
63
#include <utils/gui/images/GUITexturesHelper.h>
64
#include <utils/gui/settings/GUICompleteSchemeStorage.h>
65
#include <utils/gui/windows/GUIAppEnum.h>
66
#include <utils/gui/windows/GUIDialog_EditViewport.h>
67
#include <utils/gui/windows/GUIDialog_ViewSettings.h>
68
#include <utils/gui/windows/GUIPerspectiveChanger.h>
69
#include <utils/gui/windows/GUISUMOAbstractView.h>
70
71
#include "GUIOSGBuilder.h"
72
#include "GUIOSGPerspectiveChanger.h"
73
#include "GUIOSGView.h"
74
75
//#define DEBUG_GLERRORS
76
77
FXDEFMAP(GUIOSGView) GUIOSGView_Map[] = {
78
//________Message_Type_________ ___ID___ ________Message_Handler________
79
FXMAPFUNC(SEL_CHORE, MID_CHORE, GUIOSGView::onIdle),
80
};
81
FXIMPLEMENT(GUIOSGView, GUISUMOAbstractView, GUIOSGView_Map, ARRAYNUMBER(GUIOSGView_Map))
82
83
84
std::ostream&
85
operator<<(std::ostream& os, const osg::Vec3d& v) {
86
return os << v.x() << "," << v.y() << "," << v.z();
87
}
88
89
// ===========================================================================
90
// GUIOSGView::Command_TLSChange member method definitions
91
// ===========================================================================
92
93
GUIOSGView::Command_TLSChange::Command_TLSChange(const MSLink* const link, osg::Switch* switchNode)
94
: myLink(link), mySwitch(switchNode), myLastState(LINKSTATE_TL_OFF_NOSIGNAL) {
95
execute();
96
}
97
98
99
GUIOSGView::Command_TLSChange::~Command_TLSChange() {}
100
101
102
void
103
GUIOSGView::Command_TLSChange::execute() {
104
switch (myLink->getState()) {
105
case LINKSTATE_TL_GREEN_MAJOR:
106
case LINKSTATE_TL_GREEN_MINOR:
107
mySwitch->setSingleChildOn(0);
108
break;
109
case LINKSTATE_TL_YELLOW_MAJOR:
110
case LINKSTATE_TL_YELLOW_MINOR:
111
mySwitch->setSingleChildOn(1);
112
break;
113
case LINKSTATE_TL_RED:
114
case LINKSTATE_STOP:
115
mySwitch->setSingleChildOn(2);
116
break;
117
case LINKSTATE_TL_REDYELLOW:
118
mySwitch->setSingleChildOn(3);
119
break;
120
case LINKSTATE_TL_OFF_BLINKING:
121
case LINKSTATE_TL_OFF_NOSIGNAL:
122
mySwitch->setSingleChildOn(3);
123
break;
124
default:
125
mySwitch->setAllChildrenOff();
126
}
127
myLastState = myLink->getState();
128
}
129
130
// ===========================================================================
131
// GUIOSGView member method definitions
132
// ===========================================================================
133
134
GUIOSGView::GUIOSGView(
135
FXComposite* p,
136
GUIMainWindow& app,
137
GUISUMOViewParent* parent,
138
GUINet& net, FXGLVisual* glVis,
139
FXGLCanvas* share) :
140
GUISUMOAbstractView(p, app, parent, net.getVisualisationSpeedUp(), glVis, share),
141
myTracked(0), myLastUpdate(-1),
142
myOSGNormalizedCursorX(0.), myOSGNormalizedCursorY(0.) {
143
if (myChanger != nullptr) {
144
delete (myChanger);
145
}
146
int w = getWidth();
147
int h = getHeight();
148
myAdapter = new FXOSGAdapter(this, new FXCursor(parent->getApp(), CURSOR_CROSS));
149
myViewer = new osgViewer::Viewer();
150
myCameraManipulator = new GUIOSGManipulator(this);
151
myChanger = new GUIOSGPerspectiveChanger(*this, *myGrid);
152
const char* sumoPath = getenv("SUMO_HOME");
153
if (sumoPath != 0) {
154
std::string newPath = std::string(sumoPath) + "/data/3D";
155
if (FileHelpers::isReadable(newPath)) {
156
osgDB::FilePathList path = osgDB::Registry::instance()->getDataFilePathList();
157
path.push_back(newPath);
158
osgDB::Registry::instance()->setDataFilePathList(path);
159
}
160
}
161
162
myGreenLight = osgDB::readNodeFile("tlg.obj");
163
myYellowLight = osgDB::readNodeFile("tly.obj");
164
myRedLight = osgDB::readNodeFile("tlr.obj");
165
myRedYellowLight = osgDB::readNodeFile("tlu.obj");
166
myPoleBase = osgDB::readNodeFile("poleBase.obj");
167
if (myGreenLight == 0 || myYellowLight == 0 || myRedLight == 0 || myRedYellowLight == 0 || myPoleBase == 0) {
168
WRITE_ERROR(TL("Could not load traffic light files."));
169
}
170
// calculate camera frustum to scale the ground plane all across
171
double left, right, bottom, top, zNear, zFar;
172
myViewer->getCamera()->getProjectionMatrixAsFrustum(left, right, bottom, top, zNear, zFar);
173
myRoot = GUIOSGBuilder::buildOSGScene(myGreenLight, myYellowLight, myRedLight, myRedYellowLight, myPoleBase);
174
myPlane = new osg::MatrixTransform();
175
myPlane->setCullCallback(new ExcludeFromNearFarComputationCallback());
176
myPlane->addChild(GUIOSGBuilder::buildPlane((float)(zFar - zNear)));
177
myPlane->addUpdateCallback(new PlaneMoverCallback(myViewer->getCamera()));
178
myRoot->addChild(myPlane);
179
// add the stats handler
180
osgViewer::StatsHandler* statsHandler = new osgViewer::StatsHandler();
181
statsHandler->setKeyEventTogglesOnScreenStats(osgGA::GUIEventAdapter::KEY_I);
182
myViewer->addEventHandler(statsHandler);
183
myViewer->setSceneData(myRoot);
184
myViewer->setCameraManipulator(myCameraManipulator);
185
186
myViewer->setKeyEventSetsDone(0);
187
myViewer->getCamera()->setGraphicsContext(myAdapter);
188
myViewer->getCamera()->setViewport(0, 0, w, h);
189
myViewer->getCamera()->setNearFarRatio(0.005); // does not work together with setUpDepthPartitionForCamera
190
myViewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
191
myViewer->addEventHandler(new PickHandler(this));
192
osg::Vec3d lookFrom, lookAt, up;
193
myCameraManipulator->getHomePosition(lookFrom, lookAt, up);
194
lookFrom = lookAt + osg::Z_AXIS;
195
up = osg::Y_AXIS;
196
myCameraManipulator->setHomePosition(lookFrom, lookAt, up);
197
myViewer->home();
198
recenterView();
199
myViewer->home();
200
getApp()->addChore(this, MID_CHORE);
201
myTextNode = new osg::Geode();
202
myText = new osgText::Text;
203
myText->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
204
myText->setShaderTechnique(osgText::NO_TEXT_SHADER);
205
osgText::Font* font = osgText::readFontFile("arial.ttf");
206
if (font != nullptr) {
207
myText->setFont(font);
208
}
209
myText->setCharacterSize(16.f);
210
myTextNode->addDrawable(myText);
211
myText->setAlignment(osgText::TextBase::AlignmentType::LEFT_TOP);
212
myText->setDrawMode(osgText::TextBase::DrawModeMask::FILLEDBOUNDINGBOX | osgText::TextBase::DrawModeMask::TEXT);
213
myText->setBoundingBoxColor(osg::Vec4(0.0f, 0.0f, 0.2f, 0.5f));
214
myText->setBoundingBoxMargin(2.0f);
215
216
myHUD = new osg::Camera;
217
myHUD->setProjectionMatrixAsOrtho2D(0, 800, 0, 800); // default size will be overwritten
218
myHUD->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
219
myHUD->setViewMatrix(osg::Matrix::identity());
220
myHUD->setClearMask(GL_DEPTH_BUFFER_BIT);
221
myHUD->setRenderOrder(osg::Camera::POST_RENDER);
222
myHUD->setAllowEventFocus(false);
223
myHUD->setGraphicsContext(myAdapter);
224
myHUD->addChild(myTextNode);
225
myHUD->setViewport(0, 0, w, h);
226
myViewer->addSlave(myHUD, false);
227
myCameraManipulator->updateHUDText();
228
229
// adjust the main light
230
adoptViewSettings();
231
osgUtil::Optimizer optimizer;
232
optimizer.optimize(myRoot);
233
}
234
235
236
GUIOSGView::~GUIOSGView() {
237
getApp()->removeChore(this, MID_CHORE);
238
myViewer->setDone(true);
239
myViewer = 0;
240
myRoot = 0;
241
myAdapter = 0;
242
myCameraManipulator = 0;
243
myHUD = 0;
244
myText = 0;
245
myTextNode = 0;
246
myGreenLight = 0;
247
myYellowLight = 0;
248
myRedLight = 0;
249
myRedYellowLight = 0;
250
myPoleBase = 0;
251
}
252
253
254
void
255
GUIOSGView::adoptViewSettings() {
256
// lighting
257
osg::Light* globalLight = myViewer->getLight();
258
globalLight->setAmbient(toOSGColorVector(myVisualizationSettings->ambient3DLight));
259
globalLight->setDiffuse(toOSGColorVector(myVisualizationSettings->diffuse3DLight));
260
myViewer->getCamera()->setClearColor(toOSGColorVector(myVisualizationSettings->skyColor));
261
262
// ground color
263
osg::Geode* planeGeode = dynamic_cast<osg::Geode*>(myPlane->getChild(0));
264
osg::Geometry* planeGeom = dynamic_cast<osg::Geometry*>(planeGeode->getChild(0));
265
osg::Vec4ubArray* colors = dynamic_cast<osg::Vec4ubArray*>(planeGeom->getColorArray());
266
(*colors)[0].set(myVisualizationSettings->backgroundColor.red(),
267
myVisualizationSettings->backgroundColor.green(),
268
myVisualizationSettings->backgroundColor.blue(),
269
myVisualizationSettings->backgroundColor.alpha());
270
planeGeom->setColorArray(colors);
271
272
// show/hide OSG nodes
273
unsigned int cullMask = 0xFFFFFFFF;
274
if (!myVisualizationSettings->show3DTLSDomes) {
275
cullMask &= ~(unsigned int)NODESET_TLSDOMES;
276
}
277
if (!myVisualizationSettings->show3DTLSLinkMarkers) {
278
cullMask &= ~(unsigned int)NODESET_TLSLINKMARKERS;
279
}
280
if (!myVisualizationSettings->generate3DTLSModels) {
281
cullMask &= ~(unsigned int)NODESET_TLSMODELS;
282
}
283
myViewer->getCamera()->setCullMask(cullMask);
284
unsigned int hudCullMask = (myVisualizationSettings->show3DHeadUpDisplay) ? 0xFFFFFFFF : 0;
285
myHUD->setCullMask(hudCullMask);
286
}
287
288
289
Position
290
GUIOSGView::getPositionInformation() const {
291
Position pos;
292
getPositionAtCursor(myOSGNormalizedCursorX, myOSGNormalizedCursorY, pos);
293
return pos;
294
}
295
296
297
bool
298
GUIOSGView::is3DView() const {
299
return true;
300
}
301
302
303
void
304
GUIOSGView::buildViewToolBars(GUIGlChildWindow* v) {
305
// build coloring tools
306
{
307
const std::vector<std::string>& names = gSchemeStorage.getNames();
308
for (std::vector<std::string>::const_iterator i = names.begin(); i != names.end(); ++i) {
309
v->getColoringSchemesCombo()->appendIconItem(i->c_str());
310
if ((*i) == myVisualizationSettings->name) {
311
v->getColoringSchemesCombo()->setCurrentItem(v->getColoringSchemesCombo()->getNumItems() - 1);
312
}
313
}
314
}
315
// for junctions
316
GUIDesigns::buildFXButton(v->getLocatorPopup(),
317
"Locate Junction", "Locate a junction within the network.", "",
318
GUIIconSubSys::getIcon(GUIIcon::LOCATEJUNCTION), v, MID_HOTKEY_SHIFT_J_LOCATEJUNCTION,
319
GUIDesignButtonPopup);
320
// for edges
321
GUIDesigns::buildFXButton(v->getLocatorPopup(),
322
"Locate Street", "Locate a street within the network.", "",
323
GUIIconSubSys::getIcon(GUIIcon::LOCATEEDGE), v, MID_HOTKEY_SHIFT_E_LOCATEEDGE,
324
GUIDesignButtonPopup);
325
// for vehicles
326
GUIDesigns::buildFXButton(v->getLocatorPopup(),
327
"Locate Vehicle", "Locate a vehicle within the network.", "",
328
GUIIconSubSys::getIcon(GUIIcon::LOCATEVEHICLE), v, MID_HOTKEY_SHIFT_V_LOCATEVEHICLE,
329
GUIDesignButtonPopup);
330
// for persons
331
GUIDesigns::buildFXButton(v->getLocatorPopup(),
332
"Locate Person", "Locate a person within the network.", "",
333
GUIIconSubSys::getIcon(GUIIcon::LOCATEPERSON), v, MID_HOTKEY_SHIFT_P_LOCATEPERSON,
334
GUIDesignButtonPopup);
335
// for containers
336
GUIDesigns::buildFXButton(v->getLocatorPopup(),
337
"Locate Container", "Locate a container within the network.", "",
338
GUIIconSubSys::getIcon(GUIIcon::LOCATECONTAINER), v, MID_HOTKEY_SHIFT_C_LOCATECONTAINER,
339
GUIDesignButtonPopup);
340
// for tls
341
GUIDesigns::buildFXButton(v->getLocatorPopup(),
342
"Locate TLS", "Locate a tls within the network.", "",
343
GUIIconSubSys::getIcon(GUIIcon::LOCATETLS), v, MID_HOTKEY_SHIFT_T_LOCATETLS,
344
GUIDesignButtonPopup);
345
// for additional stuff
346
GUIDesigns::buildFXButton(v->getLocatorPopup(),
347
"Locate Additional", "Locate an additional structure within the network.", "",
348
GUIIconSubSys::getIcon(GUIIcon::LOCATEADD), v, MID_HOTKEY_SHIFT_A_LOCATEADDITIONAL,
349
GUIDesignButtonPopup);
350
// for pois
351
GUIDesigns::buildFXButton(v->getLocatorPopup(),
352
"Locate POI", "Locate a POI within the network.", "",
353
GUIIconSubSys::getIcon(GUIIcon::LOCATEPOI), v, MID_HOTKEY_SHIFT_O_LOCATEPOI,
354
GUIDesignButtonPopup);
355
// for polygons
356
GUIDesigns::buildFXButton(v->getLocatorPopup(),
357
"Locate Polygon", "Locate a Polygon within the network.", "",
358
GUIIconSubSys::getIcon(GUIIcon::LOCATEPOLY), v, MID_HOTKEY_SHIFT_L_LOCATEPOLY,
359
GUIDesignButtonPopup);
360
}
361
362
363
void
364
GUIOSGView::resize(int w, int h) {
365
GUISUMOAbstractView::resize(w, h);
366
updateHUDPosition(w, h);
367
}
368
369
370
void
371
GUIOSGView::position(int x, int y, int w, int h) {
372
GUISUMOAbstractView::position(x, y, w, h);
373
updateHUDPosition(w, h);
374
}
375
376
377
void
378
GUIOSGView::updateHUDPosition(int w, int h) {
379
// keep the HUD text in the left top corner
380
myHUD->setProjectionMatrixAsOrtho2D(0, w, 0, h);
381
myText->setPosition(osg::Vec3d(0., static_cast<double>(height), 0.));
382
}
383
384
385
void
386
GUIOSGView::updateHUDText(const std::string text) {
387
myText->setText(text, osgText::String::ENCODING_UTF8);
388
}
389
390
391
void
392
GUIOSGView::recenterView() {
393
stopTrack();
394
Position center = myGrid->getCenter();
395
double radius = std::max(myGrid->xmax() - myGrid->xmin(), myGrid->ymax() - myGrid->ymin());
396
myChanger->centerTo(center, radius);
397
}
398
399
400
bool
401
GUIOSGView::setColorScheme(const std::string& name) {
402
if (!gSchemeStorage.contains(name)) {
403
return false;
404
}
405
if (myGUIDialogViewSettings != 0) {
406
if (myGUIDialogViewSettings->getCurrentScheme() != name) {
407
myGUIDialogViewSettings->setCurrentScheme(name);
408
}
409
}
410
myVisualizationSettings = &gSchemeStorage.get(name.c_str());
411
myVisualizationSettings->gaming = myApp->isGaming();
412
adoptViewSettings();
413
update();
414
return true;
415
}
416
417
418
long
419
GUIOSGView::onPaint(FXObject*, FXSelector, void*) {
420
if (!isEnabled()) {
421
return 1;
422
}
423
myDecalsLockMutex.lock();
424
for (GUISUMOAbstractView::Decal& d : myDecals) {
425
if (!d.initialised && d.filename.length() > 0) {
426
if (d.filename.length() == 6 && d.filename.substr(0, 5) == "light") {
427
GUIOSGBuilder::buildLight(d, *myRoot);
428
} else if (d.filename.length() > 3 && d.filename.substr(0, 3) == "tl:") {
429
const int linkStringIdx = (int)d.filename.find(':', 3);
430
GUINet* net = (GUINet*) MSNet::getInstance();
431
try {
432
const std::string tlLogic = d.filename.substr(3, linkStringIdx - 3);
433
MSTLLogicControl::TLSLogicVariants& vars = net->getTLSControl().get(tlLogic);
434
const int linkIdx = StringUtils::toInt(d.filename.substr(linkStringIdx + 1));
435
if (linkIdx < 0 || linkIdx >= static_cast<int>(vars.getActive()->getLinks().size())) {
436
throw NumberFormatException("");
437
}
438
const MSLink* const link = vars.getActive()->getLinksAt(linkIdx)[0];
439
osg::Group* tlNode = GUIOSGBuilder::getTrafficLight(d, vars, link, myGreenLight, myYellowLight, myRedLight, myRedYellowLight, myPoleBase, true, 0.5);
440
tlNode->setName("tlLogic:" + tlLogic);
441
myRoot->addChild(tlNode);
442
} catch (NumberFormatException&) {
443
WRITE_ERRORF(TL("Invalid link index in '%'."), d.filename);
444
} catch (InvalidArgument&) {
445
WRITE_ERRORF(TL("Unknown traffic light in '%'."), d.filename);
446
}
447
} else {
448
GUIOSGBuilder::buildDecal(d, *myRoot);
449
}
450
d.initialised = true;
451
}
452
}
453
myDecalsLockMutex.unlock();
454
455
// reset active flag
456
for (auto& item : myVehicles) {
457
item.second.active = false;
458
}
459
460
GUINet* net = static_cast<GUINet*>(MSNet::getInstance());
461
// build edges
462
for (const MSEdge* e : net->getEdgeControl().getEdges()) {
463
for (const MSLane* l : e->getLanes()) {
464
const MSLane::VehCont& vehicles = l->getVehiclesSecure();
465
for (MSVehicle* msVeh : vehicles) {
466
GUIVehicle* veh = static_cast<GUIVehicle*>(msVeh);
467
if (!(veh->isOnRoad() || veh->isParking() || veh->wasRemoteControlled())) {
468
continue;
469
}
470
auto itVeh = myVehicles.find(veh);
471
if (itVeh == myVehicles.end()) {
472
myVehicles[veh] = GUIOSGBuilder::buildMovable(veh->getVehicleType());
473
myRoot->addChild(myVehicles[veh].pos);
474
myVehicles[veh].pos->setName("vehicle:" + veh->getID());
475
veh->setNode(myVehicles[veh].pos);
476
} else {
477
itVeh->second.active = true;
478
}
479
osg::PositionAttitudeTransform* n = myVehicles[veh].pos;
480
n->setPosition(osg::Vec3d(veh->getPosition().x(), veh->getPosition().y(), veh->getPosition().z()));
481
const double dir = veh->getAngle() + M_PI / 2.;
482
const double slope = -veh->getSlope();
483
n->setAttitude(osg::Quat(osg::DegreesToRadians(slope), osg::Vec3(1, 0, 0),
484
0, osg::Vec3(0, 1, 0),
485
dir, osg::Vec3(0, 0, 1)));
486
/*
487
osg::ref_ptr<osg::AnimationPath> path = new osg::AnimationPath;
488
// path->setLoopMode( osg::AnimationPath::NO_LOOPING );
489
osg::AnimationPath::ControlPoint pointA(n->getPosition(), n->getAttitude());
490
osg::AnimationPath::ControlPoint pointB(osg::Vec3(veh->getPosition().x(), veh->getPosition().y(), veh->getPosition().z()),
491
osg::Quat(dir, osg::Vec3(0, 0, 1)) *
492
osg::Quat(osg::DegreesToRadians(slope), osg::Vec3(0, 1, 0)));
493
path->insert(0.0f, pointA);
494
path->insert(0.5f, pointB);
495
n->setUpdateCallback(new osg::AnimationPathCallback(path));
496
*/
497
498
if (myVisualizationSettings->ignoreColorSchemeFor3DVehicles) {
499
myVehicles[veh].activateMaterial(false);
500
} else {
501
myVehicles[veh].activateMaterial(true);
502
RGBColor col;
503
if (!GUIBaseVehicle::setFunctionalColor(myVisualizationSettings->vehicleColorer.getActive(), veh, col)) {
504
col = myVisualizationSettings->vehicleColorer.getScheme().getColor(veh->getColorValue(*myVisualizationSettings, myVisualizationSettings->vehicleColorer.getActive()));
505
}
506
myVehicles[veh].mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4d(col.red() / 255., col.green() / 255., col.blue() / 255., col.alpha() / 255.));
507
}
508
myVehicles[veh].lights->setValue(0, veh->signalSet(MSVehicle::VEH_SIGNAL_BLINKER_RIGHT | MSVehicle::VEH_SIGNAL_BLINKER_EMERGENCY));
509
myVehicles[veh].lights->setValue(1, veh->signalSet(MSVehicle::VEH_SIGNAL_BLINKER_LEFT | MSVehicle::VEH_SIGNAL_BLINKER_EMERGENCY));
510
myVehicles[veh].lights->setValue(2, veh->signalSet(MSVehicle::VEH_SIGNAL_BRAKELIGHT));
511
}
512
l->releaseVehicles();
513
}
514
}
515
// remove inactive
516
for (auto veh = myVehicles.begin(); veh != myVehicles.end();) {
517
if (!veh->second.active) {
518
removeVeh((veh++)->first);
519
} else {
520
++veh;
521
}
522
}
523
524
const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
525
if (now != myLastUpdate || (myGUIDialogViewSettings != 0 && myGUIDialogViewSettings->shown())) {
526
GUINet::getGUIInstance()->updateColor(*myVisualizationSettings);
527
}
528
if (now != myLastUpdate && myTracked != 0) {
529
osg::Vec3d lookFrom, lookAt, up;
530
lookAt[0] = myTracked->getPosition().x();
531
lookAt[1] = myTracked->getPosition().y();
532
lookAt[2] = myTracked->getPosition().z();
533
const double angle = myTracked->getAngle();
534
lookFrom[0] = lookAt[0] + 50. * cos(angle);
535
lookFrom[1] = lookAt[1] + 50. * sin(angle);
536
lookFrom[2] = lookAt[2] + 10.;
537
osg::Matrix m;
538
m.makeLookAt(lookFrom, lookAt, osg::Z_AXIS);
539
myViewer->getCameraManipulator()->setByInverseMatrix(m);
540
}
541
542
// reset active flag
543
for (auto& item : myPersons) {
544
item.second.active = false;
545
}
546
547
for (const MSEdge* e : net->getEdgeControl().getEdges()) {
548
const GUIEdge* ge = static_cast<const GUIEdge*>(e);
549
const std::set<MSTransportable*, ComparatorNumericalIdLess>& persons = ge->getPersonsSecure();
550
for (auto person : persons) {
551
if (person->hasArrived() || !person->hasDeparted()) {
552
//std::cout << SIMTIME << " person " << person->getID() << " is loaded but arrived\n";
553
continue;
554
}
555
auto itPers = myPersons.find(person);
556
if (itPers == myPersons.end()) {
557
myPersons[person] = GUIOSGBuilder::buildMovable(person->getVehicleType());
558
myRoot->addChild(myPersons[person].pos);
559
} else {
560
itPers->second.active = true;
561
}
562
osg::PositionAttitudeTransform* n = myPersons[person].pos;
563
const Position pos = person->getPosition();
564
n->setPosition(osg::Vec3d(pos.x(), pos.y(), pos.z()));
565
const double dir = person->getAngle() + M_PI / 2.;
566
n->setAttitude(osg::Quat(dir, osg::Vec3d(0, 0, 1)));
567
568
RGBColor col;
569
GUIPerson* actualPerson = dynamic_cast<GUIPerson*>(person);
570
if (!GUIPerson::setFunctionalColor(myVisualizationSettings->personColorer.getActive(), actualPerson, col)) {
571
col = myVisualizationSettings->personColorer.getScheme().getColor(actualPerson->getColorValue(*myVisualizationSettings, myVisualizationSettings->vehicleColorer.getActive()));
572
}
573
myPersons[person].mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4d(col.red() / 255., col.green() / 255., col.blue() / 255., col.alpha() / 255.));
574
}
575
ge->releasePersons();
576
}
577
578
// remove inactive
579
for (auto person = myPersons.begin(); person != myPersons.end();) {
580
if (!person->second.active) {
581
removeTransportable((person++)->first);
582
} else {
583
++person;
584
}
585
}
586
587
if (myAdapter->makeCurrent()) {
588
myViewer->frame();
589
makeNonCurrent();
590
}
591
myLastUpdate = now;
592
return 1;
593
}
594
595
596
void
597
GUIOSGView::removeVeh(MSVehicle* veh) {
598
if (myTracked == veh) {
599
stopTrack();
600
}
601
std::map<MSVehicle*, OSGMovable>::iterator i = myVehicles.find(veh);
602
if (i != myVehicles.end()) {
603
myRoot->removeChild(i->second.pos);
604
myVehicles.erase(i);
605
}
606
}
607
608
609
void
610
GUIOSGView::removeTransportable(MSTransportable* t) {
611
std::map<MSTransportable*, OSGMovable>::iterator i = myPersons.find(t);
612
if (i != myPersons.end()) {
613
myRoot->removeChild(i->second.pos);
614
myPersons.erase(i);
615
}
616
}
617
618
619
void GUIOSGView::updateViewportValues() {
620
osg::Vec3d lookFrom, lookAt, up;
621
myViewer->getCameraManipulator()->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
622
myGUIDialogEditViewport->setValues(Position(lookFrom[0], lookFrom[1], lookFrom[2]),
623
Position(lookAt[0], lookAt[1], lookAt[2]), calculateRotation(lookFrom, lookAt, up));
624
}
625
626
627
void
628
GUIOSGView::showViewportEditor() {
629
getViewportEditor(); // make sure it exists;
630
osg::Vec3d lookFrom, lookAt, up;
631
myViewer->getCameraManipulator()->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
632
Position from(lookFrom[0], lookFrom[1], lookFrom[2]), at(lookAt[0], lookAt[1], lookAt[2]);
633
myGUIDialogEditViewport->setOldValues(from, at, calculateRotation(lookFrom, lookAt, up));
634
myGUIDialogEditViewport->setZoomValue(100);
635
myGUIDialogEditViewport->show();
636
}
637
638
639
void
640
GUIOSGView::setViewportFromToRot(const Position& lookFrom, const Position& lookAt, double rotation) {
641
osg::Vec3d lookFromOSG, lookAtOSG, up;
642
lookFromOSG[0] = lookFrom.x();
643
lookFromOSG[1] = lookFrom.y();
644
lookFromOSG[2] = lookFrom.z();
645
lookAtOSG[0] = lookAt.x();
646
lookAtOSG[1] = lookAt.y();
647
lookAtOSG[2] = lookAt.z();
648
649
osg::Vec3d viewAxis, viewUp, orthogonal, normal;
650
viewAxis = lookFromOSG - lookAtOSG;
651
viewAxis.normalize();
652
viewUp = (viewAxis[0] + viewAxis[1] == 0.) ? osg::Vec3d(0., 1., 0.) : osg::Vec3d(0., 0., 1.); // check for parallel vectors
653
orthogonal = viewUp ^ viewAxis;
654
orthogonal.normalize();
655
normal = viewAxis ^ orthogonal;
656
657
rotation = std::fmod(rotation, 360.);
658
if (rotation < 0) {
659
rotation += 360.;
660
}
661
myChanger->setRotation(rotation);
662
double angle = DEG2RAD(rotation);
663
up = normal * cos(angle) - orthogonal * sin(angle);
664
up.normalize();
665
666
double zoom = (myGUIDialogEditViewport != nullptr) ? myGUIDialogEditViewport->getZoomValue() : 100.;
667
lookFromOSG = lookFromOSG + viewAxis * (100. - zoom);
668
lookAtOSG = lookFromOSG - viewAxis;
669
myViewer->getCameraManipulator()->setHomePosition(lookFromOSG, lookAtOSG, up);
670
myViewer->home();
671
}
672
673
674
void
675
GUIOSGView::copyViewportTo(GUISUMOAbstractView* view) {
676
osg::Vec3d lookFrom, lookAt, up;
677
myViewer->getCameraManipulator()->getHomePosition(lookFrom, lookAt, up);
678
view->setViewportFromToRot(Position(lookFrom[0], lookFrom[1], lookFrom[2]),
679
Position(lookAt[0], lookAt[1], lookAt[2]), 0);
680
}
681
682
683
void
684
GUIOSGView::startTrack(int id) {
685
if (myTracked == 0 || (int)myTracked->getGlID() != id) {
686
myTracked = 0;
687
MSVehicleControl::constVehIt it = MSNet::getInstance()->getVehicleControl().loadedVehBegin();
688
for (; it != MSNet::getInstance()->getVehicleControl().loadedVehEnd(); it++) {
689
GUIVehicle* veh = (GUIVehicle*)(*it).second;
690
if ((int)veh->getGlID() == id) {
691
if (!veh->isOnRoad() || myVehicles.find(veh) == myVehicles.end()) {
692
return;
693
}
694
myTracked = veh;
695
break;
696
}
697
}
698
if (myTracked != 0) {
699
osg::Vec3d lookFrom, lookAt, up;
700
lookAt[0] = myTracked->getPosition().x();
701
lookAt[1] = myTracked->getPosition().y();
702
lookAt[2] = myTracked->getPosition().z();
703
lookFrom[0] = lookAt[0] + 50.;
704
lookFrom[1] = lookAt[1] + 50.;
705
lookFrom[2] = lookAt[2] + 10.;
706
osg::Matrix m;
707
m.makeLookAt(lookFrom, lookAt, osg::Z_AXIS);
708
myViewer->getCameraManipulator()->setByInverseMatrix(m);
709
}
710
}
711
}
712
713
714
void
715
GUIOSGView::stopTrack() {
716
myTracked = 0;
717
}
718
719
720
GUIGlID
721
GUIOSGView::getTrackedID() const {
722
return myTracked == 0 ? GUIGlObject::INVALID_ID : myTracked->getGlID();
723
}
724
725
726
void
727
GUIOSGView::onGamingClick(Position pos) {
728
MSTLLogicControl& tlsControl = MSNet::getInstance()->getTLSControl();
729
const MSTrafficLightLogic* minTll = nullptr;
730
double minDist = std::numeric_limits<double>::infinity();
731
for (const MSTrafficLightLogic* const tll : tlsControl.getAllLogics()) {
732
if (tlsControl.isActive(tll)) {
733
// get the links
734
const MSTrafficLightLogic::LaneVector& lanes = tll->getLanesAt(0);
735
if (lanes.size() > 0) {
736
const Position& endPos = lanes[0]->getShape().back();
737
if (endPos.distanceTo(pos) < minDist) {
738
minDist = endPos.distanceTo(pos);
739
minTll = tll;
740
}
741
}
742
}
743
}
744
if (minTll != 0) {
745
const MSTLLogicControl::TLSLogicVariants& vars = tlsControl.get(minTll->getID());
746
const std::vector<MSTrafficLightLogic*> logics = vars.getAllLogics();
747
if (logics.size() > 1) {
748
MSSimpleTrafficLightLogic* l = (MSSimpleTrafficLightLogic*) logics[0];
749
for (int i = 0; i < (int)logics.size() - 1; i++) {
750
if (minTll->getProgramID() == logics[i]->getProgramID()) {
751
l = (MSSimpleTrafficLightLogic*) logics[i + 1];
752
tlsControl.switchTo(minTll->getID(), l->getProgramID());
753
}
754
}
755
if (l == logics[0]) {
756
tlsControl.switchTo(minTll->getID(), l->getProgramID());
757
}
758
l->changeStepAndDuration(tlsControl, MSNet::getInstance()->getCurrentTimeStep(), 0, l->getPhase(0).duration);
759
update();
760
}
761
}
762
}
763
764
765
SUMOTime
766
GUIOSGView::getCurrentTimeStep() const {
767
return MSNet::getInstance()->getCurrentTimeStep();
768
}
769
770
771
long GUIOSGView::onConfigure(FXObject* sender, FXSelector sel, void* ptr) {
772
// update the window dimensions, in case the window has been resized.
773
const int w = getWidth();
774
const int h = getHeight();
775
if (w > 0 && h > 0) {
776
myAdapter->getEventQueue()->windowResize(0, 0, w, h);
777
myAdapter->resized(0, 0, w, h);
778
updateHUDPosition(w, h);
779
}
780
return FXGLCanvas::onConfigure(sender, sel, ptr);
781
}
782
783
784
long GUIOSGView::onKeyPress(FXObject* sender, FXSelector sel, void* ptr) {
785
int key = ((FXEvent*)ptr)->code;
786
myAdapter->getEventQueue()->keyPress(key);
787
// leave key handling for some cases to OSG
788
if (key == FX::KEY_f || key == FX::KEY_Left || key == FX::KEY_Right || key == FX::KEY_Up || key == FX::KEY_Down) {
789
return 1;
790
}
791
return FXGLCanvas::onKeyPress(sender, sel, ptr);
792
}
793
794
795
long GUIOSGView::onKeyRelease(FXObject* sender, FXSelector sel, void* ptr) {
796
int key = ((FXEvent*)ptr)->code;
797
myAdapter->getEventQueue()->keyRelease(key);
798
// leave key handling for some cases to OSG
799
if (key == FX::KEY_f || key == FX::KEY_Left || key == FX::KEY_Right || key == FX::KEY_Up || key == FX::KEY_Down) {
800
return 1;
801
}
802
return FXGLCanvas::onKeyRelease(sender, sel, ptr);
803
}
804
805
806
long GUIOSGView::onLeftBtnPress(FXObject* sender, FXSelector sel, void* ptr) {
807
handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
808
809
FXEvent* event = (FXEvent*)ptr;
810
myAdapter->getEventQueue()->mouseButtonPress((float)event->click_x, (float)event->click_y, 1);
811
if (myApp->isGaming()) {
812
onGamingClick(getPositionInformation());
813
}
814
815
return FXGLCanvas::onLeftBtnPress(sender, sel, ptr);
816
}
817
818
819
long GUIOSGView::onLeftBtnRelease(FXObject* sender, FXSelector sel, void* ptr) {
820
FXEvent* event = (FXEvent*)ptr;
821
myAdapter->getEventQueue()->mouseButtonRelease((float)event->click_x, (float)event->click_y, 1);
822
myChanger->onLeftBtnRelease(ptr);
823
return FXGLCanvas::onLeftBtnRelease(sender, sel, ptr);
824
}
825
826
827
long GUIOSGView::onMiddleBtnPress(FXObject* sender, FXSelector sel, void* ptr) {
828
handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
829
830
FXEvent* event = (FXEvent*)ptr;
831
myAdapter->getEventQueue()->mouseButtonPress((float)event->click_x, (float)event->click_y, 2);
832
833
return FXGLCanvas::onMiddleBtnPress(sender, sel, ptr);
834
}
835
836
837
long GUIOSGView::onMiddleBtnRelease(FXObject* sender, FXSelector sel, void* ptr) {
838
FXEvent* event = (FXEvent*)ptr;
839
myAdapter->getEventQueue()->mouseButtonRelease((float)event->click_x, (float)event->click_y, 2);
840
myChanger->onMiddleBtnRelease(ptr);
841
return FXGLCanvas::onMiddleBtnRelease(sender, sel, ptr);
842
}
843
844
845
long GUIOSGView::onRightBtnPress(FXObject* sender, FXSelector sel, void* ptr) {
846
handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
847
848
FXEvent* event = (FXEvent*)ptr;
849
myAdapter->getEventQueue()->mouseButtonPress((float)event->click_x, (float)event->click_y, 3);
850
851
return FXGLCanvas::onRightBtnPress(sender, sel, ptr);
852
}
853
854
855
long GUIOSGView::onRightBtnRelease(FXObject* sender, FXSelector sel, void* ptr) {
856
FXEvent* event = (FXEvent*)ptr;
857
myAdapter->getEventQueue()->mouseButtonRelease((float)event->click_x, (float)event->click_y, 3);
858
myChanger->onRightBtnRelease(ptr);
859
return FXGLCanvas::onRightBtnRelease(sender, sel, ptr);
860
}
861
862
863
long
864
GUIOSGView::onMouseMove(FXObject* sender, FXSelector sel, void* ptr) {
865
// if popup exist but isn't shown, destroy it first
866
if (myPopup && !myPopup->shown()) {
867
destroyPopup();
868
}
869
870
FXEvent* event = (FXEvent*)ptr;
871
osgGA::GUIEventAdapter* ea = myAdapter->getEventQueue()->mouseMotion((float)event->win_x, (float)event->win_y);
872
setWindowCursorPosition(ea->getXnormalized(), ea->getYnormalized());
873
if (myGUIDialogEditViewport != nullptr && myGUIDialogEditViewport->shown()) {
874
updateViewportValues();
875
}
876
updatePositionInformation();
877
return FXGLCanvas::onMotion(sender, sel, ptr);
878
}
879
880
881
long
882
GUIOSGView::onIdle(FXObject* /* sender */, FXSelector /* sel */, void*) {
883
forceRefresh();
884
update();
885
getApp()->addChore(this, MID_CHORE);
886
return 1;
887
}
888
889
890
long
891
GUIOSGView::onCmdCloseLane(FXObject*, FXSelector, void*) {
892
GUILane* lane = getLaneUnderCursor();
893
if (lane != nullptr) {
894
lane->closeTraffic();
895
GUIGlObjectStorage::gIDStorage.unblockObject(lane->getGlID());
896
GUINet::getGUIInstance()->updateColor(*myVisualizationSettings);
897
update();
898
}
899
return 1;
900
}
901
902
903
long
904
GUIOSGView::onCmdCloseEdge(FXObject*, FXSelector, void*) {
905
GUILane* lane = getLaneUnderCursor();
906
if (lane != nullptr) {
907
dynamic_cast<GUIEdge*>(&lane->getEdge())->closeTraffic(lane);
908
GUIGlObjectStorage::gIDStorage.unblockObject(lane->getGlID());
909
GUINet::getGUIInstance()->updateColor(*myVisualizationSettings);
910
update();
911
}
912
return 1;
913
}
914
915
916
long
917
GUIOSGView::onCmdAddRerouter(FXObject*, FXSelector, void*) {
918
GUILane* lane = getLaneUnderCursor();
919
if (lane != nullptr) {
920
dynamic_cast<GUIEdge*>(&lane->getEdge())->addRerouter();
921
GUIGlObjectStorage::gIDStorage.unblockObject(lane->getGlID());
922
update();
923
}
924
return 1;
925
}
926
927
928
long
929
GUIOSGView::onCmdShowReachability(FXObject* menu, FXSelector selector, void*) {
930
GUILane* lane = getLaneUnderCursor();
931
if (lane != nullptr) {
932
// reset
933
GUIViewTraffic::showLaneReachability(lane, menu, selector);
934
// switch to 'color by selection' unless coloring 'by reachability'
935
if (myVisualizationSettings->laneColorer.getActive() != 36) {
936
myVisualizationSettings->laneColorer.setActive(1);
937
GUINet::getGUIInstance()->updateColor(*myVisualizationSettings);
938
}
939
update();
940
}
941
return 1;
942
}
943
944
945
long
946
GUIOSGView::onVisualizationChange(FXObject*, FXSelector, void*) {
947
adoptViewSettings();
948
return 1;
949
}
950
951
952
void
953
GUIOSGView::setWindowCursorPosition(float x, float y) {
954
myOSGNormalizedCursorX = x;
955
myOSGNormalizedCursorY = y;
956
}
957
958
959
double
960
GUIOSGView::calculateRotation(const osg::Vec3d& lookFrom, const osg::Vec3d& lookAt, const osg::Vec3d& up) {
961
osg::Vec3d viewAxis, viewUp, orthogonal, normal;
962
viewAxis = lookFrom - lookAt;
963
viewAxis.normalize();
964
viewUp = (abs(viewAxis[0]) + abs(viewAxis[1]) == 0.) ? osg::Y_AXIS : osg::Z_AXIS; // check for parallel vectors
965
orthogonal = viewUp ^ viewAxis;
966
orthogonal.normalize();
967
normal = viewAxis ^ orthogonal;
968
double angle = atan2((normal ^ up).length() / (normal.length() * up.length()), (normal * up) / (normal.length() * up.length()));
969
if (angle < 0) {
970
angle += M_PI;
971
}
972
return RAD2DEG(angle);
973
}
974
975
976
void
977
GUIOSGView::updatePositionInformation() const {
978
Position pos;
979
if (getPositionAtCursor(myOSGNormalizedCursorX, myOSGNormalizedCursorY, pos)) {
980
myApp->getCartesianLabel()->setText(("x:" + toString(pos.x()) + ", y:" + toString(pos.y())).c_str());
981
// set geo position
982
GeoConvHelper::getFinal().cartesian2geo(pos);
983
if (GeoConvHelper::getFinal().usingGeoProjection()) {
984
myApp->getGeoLabel()->setText(("lat:" + toString(pos.y(), gPrecisionGeo) + ", lon:" + toString(pos.x(), gPrecisionGeo)).c_str());
985
} else {
986
myApp->getGeoLabel()->setText(TL("(No projection defined)"));
987
}
988
} else {
989
// set placeholder
990
myApp->getCartesianLabel()->setText(TL("N/A"));
991
myApp->getGeoLabel()->setText(TL("N/A"));
992
}
993
}
994
995
996
bool
997
GUIOSGView::getPositionAtCursor(float xNorm, float yNorm, Position& pos) const {
998
// only reasonable if view axis points to the ground (not parallel to the ground or in the sky)
999
osg::Vec3d lookFrom, lookAt, up, viewAxis;
1000
myViewer->getCameraManipulator()->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
1001
if ((lookAt - lookFrom).z() >= 0.) {
1002
// looking to the sky makes position at ground pointless
1003
return false;
1004
}
1005
// solve linear equation of ray crossing the ground plane
1006
osg::Matrixd iVP = osg::Matrixd::inverse(myViewer->getCamera()->getViewMatrix() * myViewer->getCamera()->getProjectionMatrix());
1007
osg::Vec3 nearPoint = osg::Vec3(xNorm, yNorm, 0.0f) * iVP;
1008
osg::Vec3 farPoint = osg::Vec3(xNorm, yNorm, 1.0f) * iVP;
1009
osg::Vec3 ray = farPoint - nearPoint;
1010
osg::Vec3 groundPos = nearPoint - ray * nearPoint.z() / ray.z();
1011
pos.setx(groundPos.x());
1012
pos.sety(groundPos.y());
1013
pos.setz(0.);
1014
return true;
1015
}
1016
1017
1018
std::vector<GUIGlObject*>
1019
GUIOSGView::getGUIGlObjectsUnderCursor() {
1020
std::vector<GUIGlObject*> result;
1021
osgUtil::LineSegmentIntersector::Intersections intersections;
1022
if (myViewer->computeIntersections(myViewer->getCamera(), osgUtil::Intersector::CoordinateFrame::PROJECTION, myOSGNormalizedCursorX, myOSGNormalizedCursorY, intersections)) {
1023
for (auto intersection : intersections) {
1024
if (!intersection.nodePath.empty()) {
1025
// the object is identified by the ID stored in OSG
1026
for (osg::Node* currentNode : intersection.nodePath) {
1027
if (currentNode->getName().length() > 0 && currentNode->getName().find(":") != std::string::npos) {
1028
const std::string objID = currentNode->getName();
1029
GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(objID);
1030
// check that GUIGlObject exist
1031
if (o == nullptr) {
1032
continue;
1033
}
1034
// check that GUIGlObject isn't the network
1035
if (o->getGlID() == 0) {
1036
continue;
1037
}
1038
result.push_back(o);
1039
// unblock object
1040
GUIGlObjectStorage::gIDStorage.unblockObject(o->getGlID());
1041
}
1042
}
1043
}
1044
}
1045
}
1046
return result;
1047
}
1048
1049
1050
GUILane*
1051
GUIOSGView::getLaneUnderCursor() {
1052
std::vector<GUIGlObject*> objects = getGUIGlObjectsUnderCursor();
1053
if (objects.size() > 0) {
1054
return dynamic_cast<GUILane*>(objects[0]);
1055
}
1056
return nullptr;
1057
}
1058
1059
1060
void
1061
GUIOSGView::zoom2Pos(Position& camera, Position& lookAt, double zoom) {
1062
osg::Vec3d lookFromOSG, lookAtOSG, viewAxis, up;
1063
myViewer->getCameraManipulator()->getInverseMatrix().getLookAt(lookFromOSG, lookAtOSG, up);
1064
lookFromOSG[0] = camera.x();
1065
lookFromOSG[1] = camera.y();
1066
lookFromOSG[2] = camera.z();
1067
lookAtOSG[0] = lookAt.x();
1068
lookAtOSG[1] = lookAt.y();
1069
lookAtOSG[2] = lookAt.z();
1070
viewAxis = lookAtOSG - lookFromOSG;
1071
viewAxis.normalize();
1072
1073
// compute new camera and lookAt pos
1074
osg::Vec3d cameraUpdate = lookFromOSG + viewAxis * (zoom - 100.);
1075
osg::Vec3d lookAtUpdate = cameraUpdate + viewAxis;
1076
1077
myViewer->getCameraManipulator()->setHomePosition(cameraUpdate, lookAtUpdate, up);
1078
myViewer->home();
1079
}
1080
1081
1082
osg::Vec4d
1083
GUIOSGView::toOSGColorVector(RGBColor c, bool useAlpha) {
1084
return osg::Vec4d(c.red() / 255., c.green() / 255., c.blue() / 255., (useAlpha) ? c.alpha() / 255. : 1.);
1085
}
1086
1087
1088
GUIOSGView::FXOSGAdapter::FXOSGAdapter(GUISUMOAbstractView* parent, FXCursor* cursor)
1089
: myParent(parent), myOldCursor(cursor) {
1090
_traits = new GraphicsContext::Traits();
1091
_traits->x = 0;
1092
_traits->y = 0;
1093
_traits->width = parent->getWidth();
1094
_traits->height = parent->getHeight();
1095
_traits->windowDecoration = false;
1096
_traits->doubleBuffer = true;
1097
_traits->sharedContext = 0;
1098
if (valid()) {
1099
setState(new osg::State());
1100
getState()->setGraphicsContext(this);
1101
#ifdef DEBUG_GLERRORS
1102
getState()->setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE);
1103
std::cout << "OSG getCheckForGLErrors " << getState()->getCheckForGLErrors() << std::endl;
1104
#endif
1105
if (_traits.valid() && _traits->sharedContext != 0) {
1106
getState()->setContextID(_traits->sharedContext->getState()->getContextID());
1107
incrementContextIDUsageCount(getState()->getContextID());
1108
} else {
1109
getState()->setContextID(createNewContextID());
1110
}
1111
}
1112
}
1113
1114
1115
GUIOSGView::FXOSGAdapter::~FXOSGAdapter() {
1116
delete myOldCursor;
1117
}
1118
1119
1120
void
1121
GUIOSGView::FXOSGAdapter::grabFocus() {
1122
// focus this window
1123
myParent->setFocus();
1124
}
1125
1126
1127
void
1128
GUIOSGView::FXOSGAdapter::useCursor(bool cursorOn) {
1129
if (cursorOn) {
1130
myParent->setDefaultCursor(myOldCursor);
1131
} else {
1132
myParent->setDefaultCursor(NULL);
1133
}
1134
}
1135
1136
1137
bool
1138
GUIOSGView::FXOSGAdapter::makeCurrentImplementation() {
1139
myParent->makeCurrent();
1140
return true;
1141
}
1142
1143
1144
bool
1145
GUIOSGView::FXOSGAdapter::releaseContext() {
1146
myParent->makeNonCurrent();
1147
return true;
1148
}
1149
1150
1151
void
1152
GUIOSGView::FXOSGAdapter::swapBuffersImplementation() {
1153
myParent->swapBuffers();
1154
}
1155
1156
1157
bool
1158
GUIOSGView::PickHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& /* aa */) {
1159
if (ea.getEventType() == osgGA::GUIEventAdapter::DRAG) {
1160
myDrag = true;
1161
} else if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE && ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) {
1162
if (!myDrag) {
1163
if (myParent->makeCurrent()) {
1164
std::vector<GUIGlObject*> objects = myParent->getGUIGlObjectsUnderCursor();
1165
if (objects.size() > 0) {
1166
myParent->openObjectDialog(objects);
1167
}
1168
myParent->makeNonCurrent();
1169
}
1170
}
1171
myDrag = false;
1172
}
1173
return false;
1174
}
1175
1176
1177
#endif
1178
1179
/****************************************************************************/
1180
1181