int GUIViewTraffic::doPaintGL(int mode, const Boundary& bound) { // init view settings glRenderMode(mode); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glDisable(GL_TEXTURE_2D); glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); // draw decals (if not in grabbing mode) if (!myUseToolTips) { drawDecals(); if (myVisualizationSettings->showGrid) { paintGLGrid(); } } glLineWidth(1); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); float minB[2]; float maxB[2]; minB[0] = bound.xmin(); minB[1] = bound.ymin(); maxB[0] = bound.xmax(); maxB[1] = bound.ymax(); myVisualizationSettings->scale = m2p(SUMO_const_laneWidth); glEnable(GL_POLYGON_OFFSET_FILL); glEnable(GL_POLYGON_OFFSET_LINE); int hits2 = myGrid->Search(minB, maxB, *myVisualizationSettings); // if (myAdditionallyDrawn.size() > 0) { glTranslated(0, 0, -.01); GUINet::getGUIInstance()->lock(); for (std::map<GUIGlObject*, int>::iterator i = myAdditionallyDrawn.begin(); i != myAdditionallyDrawn.end(); ++i) { (i->first)->drawGLAdditional(this, *myVisualizationSettings); } GUINet::getGUIInstance()->unlock(); glTranslated(0, 0, .01); } glPopMatrix(); /* // draw legends glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslated(1.-.2, 1.-.5, 0.); glScaled(.2, .5, 1.); GUIColoringSchemesMap<GUILane> &sm = GUIViewTraffic::getLaneSchemesMap(); //!!! sm.getColorer(myVisualizationSettings->laneEdgeMode)->drawLegend(); */ return hits2; }
/** * Update the lightmap and draw the terrain and decals. * This function first draws the terrain in black, and then uses additive blending to put the terrain layers * on it one by one. Finally the decals are drawn. */ void drawTerrain(const glm::mat4 &mvp) { const glm::vec4 paramsXLight(1.0f / world_coord(mapWidth) *((float)mapWidth / lightmapWidth), 0, 0, 0); const glm::vec4 paramsYLight(0, 0, -1.0f / world_coord(mapHeight) *((float)mapHeight / lightmapHeight), 0); /////////////////////////////////// // set up the lightmap texture glActiveTexture(GL_TEXTURE1); // bind the texture lightmap_tex_num->bind(); // we limit the framerate of the lightmap, because updating a texture is an expensive operation if (realTime - lightmapLastUpdate >= LIGHTMAP_REFRESH) { lightmapLastUpdate = realTime; updateLightMap(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); lightmap_tex_num->upload(0, 0, 0, lightmapWidth, lightmapHeight, gfx_api::pixel_format::rgb, lightmapPixmap); } /////////////////////////////////// // terrain culling cullTerrain(); glActiveTexture(GL_TEXTURE0); // shift the lightmap half a tile as lights are supposed to be placed at the center of a tile const glm::mat4 lightMatrix = glm::translate(glm::vec3(1.f / lightmapWidth / 2, 1.f / lightmapHeight / 2, 0.f)); ////////////////////////////////////// // canvas to draw on drawDepthOnly(mvp, paramsXLight, paramsYLight); /////////////////////////////////// // terrain drawTerrainLayers(mvp, paramsXLight, paramsYLight, lightMatrix); ////////////////////////////////// // decals drawDecals(mvp, paramsXLight, paramsYLight, lightMatrix); //////////////////////////////// // disable the lightmap texture glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE0); // leave everything in a sane state so it won't mess up somewhere else //glBindBuffer(GL_ARRAY_BUFFER, 0); // HACK Must unbind GL_ARRAY_BUFFER (don't know if it has to be unbound everywhere), otherwise text rendering may mysteriously crash. }
std::string GUISUMOAbstractView::makeSnapshot(const std::string& destFile) { std::string errorMessage; FXString ext = FXPath::extension(destFile.c_str()); const bool useGL2PS = ext == "ps" || ext == "eps" || ext == "pdf" || ext == "svg" || ext == "tex" || ext == "pgf"; #ifdef HAVE_FFMPEG const bool useVideo = destFile == "" || ext == "h264" || ext == "hevc"; #endif for (int i = 0; i < 10 && !makeCurrent(); ++i) { FXSingleEventThread::sleep(100); } // draw glClearColor( myVisualizationSettings->backgroundColor.red() / 255., myVisualizationSettings->backgroundColor.green() / 255., myVisualizationSettings->backgroundColor.blue() / 255., myVisualizationSettings->backgroundColor.alpha() / 255.); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); if (myVisualizationSettings->dither) { glEnable(GL_DITHER); } else { glDisable(GL_DITHER); } if (myVisualizationSettings->antialiase) { glEnable(GL_BLEND); glEnable(GL_POLYGON_SMOOTH); glEnable(GL_LINE_SMOOTH); } else { glDisable(GL_BLEND); glDisable(GL_POLYGON_SMOOTH); glDisable(GL_LINE_SMOOTH); } applyGLTransform(); if (useGL2PS) { GLint format = GL2PS_PS; if (ext == "ps") { format = GL2PS_PS; } else if (ext == "eps") { format = GL2PS_EPS; } else if (ext == "pdf") { format = GL2PS_PDF; } else if (ext == "tex") { format = GL2PS_TEX; } else if (ext == "svg") { format = GL2PS_SVG; } else if (ext == "pgf") { format = GL2PS_PGF; } else { return "Could not save '" + destFile + "'.\n Unrecognized format '" + std::string(ext.text()) + "'."; } FILE* fp = fopen(destFile.c_str(), "wb"); if (fp == 0) { return "Could not save '" + destFile + "'.\n Could not open file for writing"; } GLint buffsize = 0, state = GL2PS_OVERFLOW; GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); while (state == GL2PS_OVERFLOW) { buffsize += 1024 * 1024; gl2psBeginPage(destFile.c_str(), "sumo-gui; http://sumo.dlr.de", viewport, format, GL2PS_SIMPLE_SORT, GL2PS_DRAW_BACKGROUND | GL2PS_USE_CURRENT_VIEWPORT, GL_RGBA, 0, NULL, 0, 0, 0, buffsize, fp, "out.eps"); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glDisable(GL_TEXTURE_2D); glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); // compute lane width // draw decals (if not in grabbing mode) if (!myUseToolTips) { drawDecals(); if (myVisualizationSettings->showGrid) { paintGLGrid(); } } glLineWidth(1); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); Boundary viewPort = myChanger->getViewport(); float minB[2]; float maxB[2]; minB[0] = viewPort.xmin(); minB[1] = viewPort.ymin(); maxB[0] = viewPort.xmax(); maxB[1] = viewPort.ymax(); myVisualizationSettings->scale = m2p(SUMO_const_laneWidth); glEnable(GL_POLYGON_OFFSET_FILL); glEnable(GL_POLYGON_OFFSET_LINE); myGrid->Search(minB, maxB, *myVisualizationSettings); if (myVisualizationSettings->showSizeLegend) { displayLegend(); } state = gl2psEndPage(); glFinish(); } fclose(fp); } else { doPaintGL(GL_RENDER, myChanger->getViewport()); if (myVisualizationSettings->showSizeLegend) { displayLegend(); } swapBuffers(); glFinish(); FXColor* buf; FXMALLOC(&buf, FXColor, getWidth()*getHeight()); // read from the back buffer glReadBuffer(GL_BACK); // Read the pixels glReadPixels(0, 0, getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)buf); makeNonCurrent(); update(); // mirror size_t mwidth = getWidth(); size_t mheight = getHeight(); FXColor* paa = buf; FXColor* pbb = buf + mwidth * (mheight - 1); do { FXColor* pa = paa; paa += mwidth; FXColor* pb = pbb; pbb -= mwidth; do { FXColor t = *pa; *pa++ = *pb; *pb++ = t; } while (pa < paa); } while (paa < pbb); try { #ifdef HAVE_FFMPEG if (useVideo) { try { saveFrame(destFile, buf); errorMessage = "video"; } catch (std::runtime_error& err) { errorMessage = err.what(); } } else #endif if (!MFXImageHelper::saveImage(destFile, getWidth(), getHeight(), buf)) { errorMessage = "Could not save '" + destFile + "'."; } } catch (InvalidArgument& e) { errorMessage = "Could not save '" + destFile + "'.\n" + e.what(); } FXFREE(&buf); } return errorMessage; }
int GUIViewTraffic::doPaintGL(int mode, SUMOReal scale) { // init view settings glRenderMode(mode); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glDisable(GL_TEXTURE_2D); glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); GLdouble sxmin = myCX - myX1; GLdouble sxmax = myCX + myX1; GLdouble symin = myCY - myY1; GLdouble symax = myCY + myY1; // compute lane width ?? ACE ?? SUMOReal lw = m2p(3.0) * scale; // draw decals (if not in grabbing mode) if (!myUseToolTips) { drawDecals(); if (myVisualizationSettings->showGrid) { paintGLGrid(); } } glLineWidth(1); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); float minB[2]; float maxB[2]; minB[0] = sxmin; minB[1] = symin; maxB[0] = sxmax; maxB[1] = symax; myVisualizationSettings->needsGlID = myUseToolTips; myVisualizationSettings->scale = lw; glEnable(GL_POLYGON_OFFSET_FILL); glEnable(GL_POLYGON_OFFSET_LINE); int hits2 = myGrid->Search(minB, maxB, *myVisualizationSettings); // glTranslated(0, 0, -.01); for (std::vector<VehicleOps>::iterator i=myVehicleOps.begin(); i!=myVehicleOps.end(); ++i) { const VehicleOps &vo = *i; switch (vo.type) { case VO_SHOW_ROUTE: { if (vo.routeNo>=0) { drawRoute(vo, vo.routeNo, 0.25); } else { if (vo.vehicle->hasCORNIntValue(MSCORN::CORN_VEH_NUMBERROUTE)) { int noReroutePlus1 = vo.vehicle->getCORNIntValue(MSCORN::CORN_VEH_NUMBERROUTE) + 1; for (int i=noReroutePlus1-1; i>=0; i--) { SUMOReal darken = SUMOReal(0.4) / SUMOReal(noReroutePlus1) * SUMOReal(i); drawRoute(vo, i, darken); } } else { drawRoute(vo, 0, 0.25); } } } break; case VO_SHOW_BEST_LANES: { drawBestLanes(vo); break; } break; default: break; } } glTranslated(0, 0, .01); glPopMatrix(); /* // draw legends glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslated(1.-.2, 1.-.5, 0.); glScaled(.2, .5, 1.); GUIColoringSchemesMap<GUILaneWrapper> &sm = GUIViewTraffic::getLaneSchemesMap(); //!!! sm.getColorer(myVisualizationSettings->laneEdgeMode)->drawLegend(); */ return hits2; }