34 #pragma warning(disable: 4127) // do not warn about constant conditional expression
36 #include <osgViewer/Viewer>
37 #include <osgViewer/ViewerEventHandlers>
38 #include <osgGA/NodeTrackerManipulator>
39 #include <osgDB/ReadFile>
40 #include <osg/PositionAttitudeTransform>
42 #include <osg/ShapeDrawable>
84 FXDEFMAP(GUIOSGView) GUIOSGView_Map[] = {
86 FXMAPFUNC(SEL_CHORE,
MID_CHORE, GUIOSGView::OnIdle)
92 operator<<(std::ostream& os,
const osg::Vec3d& v) {
93 return os << v.x() <<
"," << v.y() <<
"," << v.z();
100 GUIOSGView::Command_TLSChange::Command_TLSChange(
const MSLink*
const link, osg::Switch* switchNode)
106 GUIOSGView::Command_TLSChange::~Command_TLSChange() {}
110 GUIOSGView::Command_TLSChange::execute() {
111 switch (myLink->getState()) {
114 mySwitch->setSingleChildOn(0);
118 mySwitch->setSingleChildOn(1);
121 mySwitch->setSingleChildOn(2);
124 mySwitch->setSingleChildOn(3);
127 mySwitch->setAllChildrenOff();
129 myLastState = myLink->getState();
137 GUIOSGView::GUIOSGView(
141 GUINet& net, FXGLVisual* glVis,
144 myTracked(0), myCameraManipulator(new SUMOTerrainManipulator()), myLastUpdate(-1) {
152 myAdapter =
new FXOSGAdapter(
this,
new FXCursor(parent->getApp(), CURSOR_CROSS));
154 myViewer =
new osgViewer::Viewer();
155 myViewer->getCamera()->setGraphicsContext(myAdapter);
156 myViewer->getCamera()->setViewport(0, 0, w, h);
157 myViewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
159 const char* sumoPath = getenv(
"SUMO_HOME");
161 std::string newPath = std::string(sumoPath) +
"/data/3D";
163 osgDB::FilePathList path = osgDB::Registry::instance()->getDataFilePathList();
164 path.push_back(newPath);
165 osgDB::Registry::instance()->setDataFilePathList(path);
169 myGreenLight = osgDB::readNodeFile(
"tlg.obj");
170 myYellowLight = osgDB::readNodeFile(
"tly.obj");
171 myRedLight = osgDB::readNodeFile(
"tlr.obj");
172 myRedYellowLight = osgDB::readNodeFile(
"tlu.obj");
173 if (myGreenLight == 0 || myYellowLight == 0 || myRedLight == 0 || myRedYellowLight == 0) {
174 WRITE_ERROR(
"Could not load traffic light files.");
176 myRoot = GUIOSGBuilder::buildOSGScene(myGreenLight, myYellowLight, myRedLight, myRedYellowLight);
178 myViewer->addEventHandler(
new osgViewer::StatsHandler());
179 myViewer->setSceneData(myRoot);
180 myViewer->setCameraManipulator(myCameraManipulator);
181 osg::Vec3d lookFrom, lookAt, up;
182 myCameraManipulator->getHomePosition(lookFrom, lookAt, up);
183 double z = lookFrom[2];
184 lookFrom[2] = -lookFrom.y();
186 myCameraManipulator->setHomePosition(lookFrom, lookAt, up);
192 GUIOSGView::~GUIOSGView() {
194 myViewer->setDone(
true);
206 for (std::vector<std::string>::const_iterator i = names.begin(); i != names.end(); ++i) {
208 if ((*i) == myVisualizationSettings->name) {
216 "\tLocate Junction\tLocate a junction within the network.",
218 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
221 "\tLocate Street\tLocate a street within the network.",
223 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
226 "\tLocate Vehicle\tLocate a vehicle within the network.",
228 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
231 "\tLocate Vehicle\tLocate a person within the network.",
233 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
236 "\tLocate TLS\tLocate a tls within the network.",
238 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
241 "\tLocate Additional\tLocate an additional structure within the network.",
243 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
246 "\tLocate POI\tLocate a POI within the network.",
248 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
251 "\tLocate Polygon\tLocate a Polygon within the network.",
253 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
258 GUIOSGView::recenterView() {
260 Position center = myGrid->getCenter();
261 osg::Vec3d lookFromOSG, lookAtOSG, up;
262 myViewer->getCameraManipulator()->getHomePosition(lookFromOSG, lookAtOSG, up);
263 lookFromOSG[0] = center.
x();
264 lookFromOSG[1] = center.
y();
265 lookFromOSG[2] = myChanger->zoom2ZPos(100);
266 lookAtOSG[0] = center.
x();
267 lookAtOSG[1] = center.
y();
269 myViewer->getCameraManipulator()->setHomePosition(lookFromOSG, lookAtOSG, up);
275 GUIOSGView::centerTo(
GUIGlID id,
bool ,
double ) {
281 GUIOSGView::setColorScheme(
const std::string& name) {
285 if (myVisualizationChanger != 0) {
286 if (myVisualizationChanger->getCurrentScheme() != name) {
287 myVisualizationChanger->setCurrentScheme(name);
291 myVisualizationSettings->
gaming = myApp->isGaming();
298 GUIOSGView::onPaint(FXObject*, FXSelector,
void*) {
304 if (!d.initialised) {
305 if (d.filename.length() == 6 && d.filename.substr(0, 5) ==
"light") {
306 GUIOSGBuilder::buildLight(d, *myRoot);
307 }
else if (d.filename.length() > 3 && d.filename.substr(0, 3) ==
"tl:") {
308 const int linkStringIdx = (int)d.filename.find(
':', 3);
313 if (linkIdx < 0 || linkIdx >=
static_cast<int>(vars.
getActive()->
getLinks().size())) {
317 osg::Switch* switchNode =
new osg::Switch();
318 switchNode->addChild(GUIOSGBuilder::getTrafficLight(d, d.layer < 0 ? 0 : myGreenLight, osg::Vec4d(0., 1., 0., .3)),
false);
319 switchNode->addChild(GUIOSGBuilder::getTrafficLight(d, d.layer < 0 ? 0 : myYellowLight, osg::Vec4d(1., 1., 0., .3)),
false);
320 switchNode->addChild(GUIOSGBuilder::getTrafficLight(d, d.layer < 0 ? 0 : myRedLight, osg::Vec4d(1., 0., 0., .3)),
false);
321 switchNode->addChild(GUIOSGBuilder::getTrafficLight(d, d.layer < 0 ? 0 : myRedYellowLight, osg::Vec4d(1., .5, 0., .3)),
false);
322 myRoot->addChild(switchNode);
325 WRITE_ERROR(
"Invalid link index in '" + d.filename +
"'.");
327 WRITE_ERROR(
"Unknown traffic light in '" + d.filename +
"'.");
330 GUIOSGBuilder::buildDecal(d, *myRoot);
332 d.initialised =
true;
335 myDecalsLock.unlock();
338 for (
auto& item : myVehicles) {
339 item.second.active =
false;
346 auto itVeh = myVehicles.find(veh);
347 if (itVeh == myVehicles.end()) {
348 myVehicles[veh] = GUIOSGBuilder::buildMovable(veh->
getVehicleType());
349 myRoot->addChild(myVehicles[veh].pos);
351 itVeh->second.active =
true;
353 osg::PositionAttitudeTransform* n = myVehicles[veh].pos;
356 const double slope = veh->
getSlope();
357 n->setAttitude(osg::Quat(dir, osg::Vec3d(0, 0, 1)) *
358 osg::Quat(osg::DegreesToRadians(slope), osg::Vec3d(0, 1, 0)));
370 const RGBColor& col = myVisualizationSettings->vehicleColorer.getScheme().getColor(veh->
getColorValue(*myVisualizationSettings, myVisualizationSettings->vehicleColorer.getActive()));
371 myVehicles[veh].geom->setColor(osg::Vec4d(col.
red() / 255., col.
green() / 255., col.
blue() / 255., col.
alpha() / 255.));
377 for (
auto veh = myVehicles.begin(); veh != myVehicles.end();) {
378 if (!veh->second.active) {
379 removeVeh((veh++)->first);
386 if (now != myLastUpdate || (myVisualizationChanger != 0 && myVisualizationChanger->shown())) {
389 if (now != myLastUpdate && myTracked != 0) {
390 osg::Vec3d lookFrom, lookAt, up;
391 lookAt[0] = myTracked->getPosition().x();
392 lookAt[1] = myTracked->getPosition().y();
393 lookAt[2] = myTracked->getPosition().z();
394 const double angle = myTracked->getAngle();
395 lookFrom[0] = lookAt[0] + 50. * cos(angle);
396 lookFrom[1] = lookAt[1] + 50. * sin(angle);
397 lookFrom[2] = lookAt[2] + 10.;
399 m.makeLookAt(lookFrom, lookAt, osg::Z_AXIS);
400 myCameraManipulator->setByInverseMatrix(m);
404 for (
auto& item : myPersons) {
405 item.second.active =
false;
414 auto itPers = myPersons.find(person);
415 if (itPers == myPersons.end()) {
416 myPersons[person] = GUIOSGBuilder::buildMovable(person->
getVehicleType());
417 myRoot->addChild(myPersons[person].pos);
419 itPers->second.active =
true;
421 osg::PositionAttitudeTransform* n = myPersons[person].pos;
423 n->setPosition(osg::Vec3d(pos.
x(), pos.
y(), pos.
z()));
425 n->setAttitude(osg::Quat(dir, osg::Vec3d(0, 0, 1)));
428 for (
auto person = myPersons.begin(); person != myPersons.end();) {
429 if (!person->second.active) {
430 removeTransportable((person++)->first);
437 if (myAdapter->makeCurrent()) {
448 if (myTracked == veh) {
451 std::map<MSVehicle*, OSGMovable>::iterator i = myVehicles.find(veh);
452 if (i != myVehicles.end()) {
453 myRoot->removeChild(i->second.pos);
461 std::map<MSTransportable*, OSGMovable>::iterator i = myPersons.find(t);
462 if (i != myPersons.end()) {
463 myRoot->removeChild(i->second.pos);
470 GUIOSGView::showViewportEditor() {
472 osg::Vec3d lookFromOSG, lookAtOSG, up;
473 myViewer->getCameraManipulator()->getInverseMatrix().getLookAt(lookFromOSG, lookAtOSG, up);
474 Position from(lookFromOSG[0], lookFromOSG[1], lookFromOSG[2]), at(lookAtOSG[0], lookAtOSG[1], lookAtOSG[2]);
475 myViewportChooser->setOldValues(from, at, 0);
476 myViewportChooser->show();
481 GUIOSGView::setViewportFromToRot(
const Position& lookFrom,
const Position& lookAt,
double ) {
482 osg::Vec3d lookFromOSG, lookAtOSG, up;
483 myViewer->getCameraManipulator()->getHomePosition(lookFromOSG, lookAtOSG, up);
484 lookFromOSG[0] = lookFrom.
x();
485 lookFromOSG[1] = lookFrom.
y();
486 lookFromOSG[2] = lookFrom.
z();
487 lookAtOSG[0] = lookAt.
x();
488 lookAtOSG[1] = lookAt.
y();
489 lookAtOSG[2] = lookAt.
z();
490 myViewer->getCameraManipulator()->setHomePosition(lookFromOSG, lookAtOSG, up);
498 osg::Vec3d lookFrom, lookAt, up;
499 myCameraManipulator->getHomePosition(lookFrom, lookAt, up);
501 Position(lookAt[0], lookAt[1], lookAt[2]), 0);
507 GUIOSGView::startTrack(
int id) {
508 if (myTracked == 0 || (
int)myTracked->getGlID() !=
id) {
513 if ((
int)veh->
getGlID() == id) {
514 if (!veh->
isOnRoad() || myVehicles.find(veh) == myVehicles.end()) {
521 if (myTracked != 0) {
522 osg::Vec3d lookFrom, lookAt, up;
524 lookAt[1] = myTracked->getPosition().y();
525 lookAt[2] = myTracked->getPosition().z();
526 lookFrom[0] = lookAt[0] + 50.;
527 lookFrom[1] = lookAt[1] + 50.;
528 lookFrom[2] = lookAt[2] + 10.;
530 m.makeLookAt(lookFrom, lookAt, osg::Z_AXIS);
531 myCameraManipulator->setByInverseMatrix(m);
538 GUIOSGView::stopTrack() {
544 GUIOSGView::getTrackedID()
const {
550 GUIOSGView::onGamingClick(
Position pos) {
553 double minDist = std::numeric_limits<double>::infinity();
558 if (lanes.size() > 0) {
559 const Position& endPos = lanes[0]->getShape().back();
569 const std::vector<MSTrafficLightLogic*> logics = vars.
getAllLogics();
570 if (logics.size() > 1) {
572 for (
int i = 0; i < (int)logics.size() - 1; i++) {
573 if (minTll->
getProgramID() == logics[i]->getProgramID()) {
578 if (l == logics[0]) {
589 GUIOSGView::getCurrentTimeStep()
const {
594 long GUIOSGView::onConfigure(FXObject* sender, FXSelector sel,
void* ptr) {
596 myAdapter->getEventQueue()->windowResize(0, 0, getWidth(), getHeight());
597 myAdapter->resized(0, 0, getWidth(), getHeight());
599 return FXGLCanvas::onConfigure(sender, sel, ptr);
602 long GUIOSGView::onKeyPress(FXObject* sender, FXSelector sel,
void* ptr) {
603 int key = ((FXEvent*)ptr)->code;
604 myAdapter->getEventQueue()->keyPress(key);
606 return FXGLCanvas::onKeyPress(sender, sel, ptr);
609 long GUIOSGView::onKeyRelease(FXObject* sender, FXSelector sel,
void* ptr) {
610 int key = ((FXEvent*)ptr)->code;
611 myAdapter->getEventQueue()->keyRelease(key);
613 return FXGLCanvas::onKeyRelease(sender, sel, ptr);
616 long GUIOSGView::onLeftBtnPress(FXObject* sender, FXSelector sel,
void* ptr) {
617 handle(
this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
619 FXEvent*
event = (FXEvent*)ptr;
620 myAdapter->getEventQueue()->mouseButtonPress((
float)
event->click_x, (float)event->click_y, 1);
621 if (myApp->isGaming()) {
622 onGamingClick(getPositionInformation());
625 return FXGLCanvas::onLeftBtnPress(sender, sel, ptr);
628 long GUIOSGView::onLeftBtnRelease(FXObject* sender, FXSelector sel,
void* ptr) {
629 FXEvent*
event = (FXEvent*)ptr;
630 myAdapter->getEventQueue()->mouseButtonRelease((
float)
event->click_x, (float)event->click_y, 1);
632 return FXGLCanvas::onLeftBtnRelease(sender, sel, ptr);
635 long GUIOSGView::onMiddleBtnPress(FXObject* sender, FXSelector sel,
void* ptr) {
636 handle(
this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
638 FXEvent*
event = (FXEvent*)ptr;
639 myAdapter->getEventQueue()->mouseButtonPress((
float)
event->click_x, (float)event->click_y, 2);
641 return FXGLCanvas::onMiddleBtnPress(sender, sel, ptr);
644 long GUIOSGView::onMiddleBtnRelease(FXObject* sender, FXSelector sel,
void* ptr) {
645 FXEvent*
event = (FXEvent*)ptr;
646 myAdapter->getEventQueue()->mouseButtonRelease((
float)
event->click_x, (float)event->click_y, 2);
648 return FXGLCanvas::onMiddleBtnRelease(sender, sel, ptr);
651 long GUIOSGView::onRightBtnPress(FXObject* sender, FXSelector sel,
void* ptr) {
652 handle(
this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
654 FXEvent*
event = (FXEvent*)ptr;
655 myAdapter->getEventQueue()->mouseButtonPress((
float)
event->click_x, (float)event->click_y, 3);
657 return FXGLCanvas::onRightBtnPress(sender, sel, ptr);
660 long GUIOSGView::onRightBtnRelease(FXObject* sender, FXSelector sel,
void* ptr) {
661 FXEvent*
event = (FXEvent*)ptr;
662 myAdapter->getEventQueue()->mouseButtonRelease((
float)
event->click_x, (float)event->click_y, 3);
664 return FXGLCanvas::onRightBtnRelease(sender, sel, ptr);
668 GUIOSGView::onMouseMove(FXObject* sender, FXSelector sel,
void* ptr) {
669 FXEvent*
event = (FXEvent*)ptr;
670 myAdapter->getEventQueue()->mouseMotion((
float)
event->win_x, (float)event->win_y);
672 return FXGLCanvas::onMotion(sender, sel, ptr);
676 GUIOSGView::OnIdle(FXObject* , FXSelector ,
void*) {
686 : myParent(parent), myOldCursor(cursor) {
687 _traits =
new GraphicsContext::Traits();
690 _traits->width = parent->getWidth();
691 _traits->height = parent->getHeight();
692 _traits->windowDecoration =
false;
693 _traits->doubleBuffer =
true;
694 _traits->sharedContext = 0;
696 setState(
new osg::State());
697 getState()->setGraphicsContext(
this);
698 if (_traits.valid() && _traits->sharedContext != 0) {
699 getState()->setContextID(_traits->sharedContext->getState()->getContextID());
700 incrementContextIDUsageCount(getState()->getContextID());
702 getState()->setContextID(createNewContextID());
708 GUIOSGView::FXOSGAdapter::~FXOSGAdapter() {
713 void GUIOSGView::FXOSGAdapter::grabFocus() {
715 myParent->setFocus();
718 void GUIOSGView::FXOSGAdapter::useCursor(
bool cursorOn) {
720 myParent->setDefaultCursor(myOldCursor);
722 myParent->setDefaultCursor(NULL);
726 bool GUIOSGView::FXOSGAdapter::makeCurrentImplementation() {
727 myParent->makeCurrent();
731 bool GUIOSGView::FXOSGAdapter::releaseContext() {
732 myParent->makeNonCurrent();
736 void GUIOSGView::FXOSGAdapter::swapBuffersImplementation() {
737 myParent->swapBuffers();