SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GUIPolygon.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // The GUI-version of a polygon
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
13 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <string>
34 #include "GUIPolygon.h"
40 #include <utils/gui/div/GLHelper.h>
42 
43 #ifdef CHECK_MEMORY_LEAKS
44 #include <foreign/nvwa/debug_new.h>
45 #endif // CHECK_MEMORY_LEAKS
46 
47 
48 // ===========================================================================
49 // method definitions
50 // ===========================================================================
51 GUIPolygon::GUIPolygon(const std::string& id, const std::string& type,
52  const RGBColor& color, const PositionVector& shape, bool fill,
53  SUMOReal layer, SUMOReal angle, const std::string& imgFile):
54  Polygon(id, type, color, shape, fill, layer, angle, imgFile),
56  myDisplayList(0),
57  myLineWidth(-1)
58 
59 {}
60 
61 
63 
64 
65 
68  GUISUMOAbstractView& parent) {
69  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
70  buildPopupHeader(ret, app, false);
71  FXString t(myType.c_str());
72  new FXMenuCommand(ret, "(" + t + ")", 0, 0, 0);
73  new FXMenuSeparator(ret);
77  buildPositionCopyEntry(ret, false);
78  return ret;
79 }
80 
81 
85  return 0;
86 }
87 
88 
91  Boundary b;
93  b.grow(10);
94  return b;
95 }
96 
97 
98 void APIENTRY beginCallback(GLenum which) {
99  glBegin(which);
100 }
101 
102 void APIENTRY errorCallback(GLenum errorCode) {
103  const GLubyte* estring;
104 
105  estring = gluErrorString(errorCode);
106  fprintf(stderr, "Tessellation Error: %s\n", estring);
107  exit(0);
108 }
109 
110 void APIENTRY endCallback(void) {
111  glEnd();
112 }
113 
114 void APIENTRY vertexCallback(GLvoid* vertex) {
115  glVertex3dv((GLdouble*) vertex);
116 }
117 
118 void APIENTRY combineCallback(GLdouble coords[3],
119  GLdouble* vertex_data[4],
120  GLfloat weight[4], GLdouble** dataOut) {
121  UNUSED_PARAMETER(weight);
122  UNUSED_PARAMETER(*vertex_data);
123  GLdouble* vertex;
124 
125  vertex = (GLdouble*) malloc(7 * sizeof(GLdouble));
126 
127  vertex[0] = coords[0];
128  vertex[1] = coords[1];
129  vertex[2] = coords[2];
130  *dataOut = vertex;
131 }
132 
133 
134 GLfloat INV_POLY_TEX_DIM = 1.0 / 256.0;
135 GLfloat xPlane[] = {INV_POLY_TEX_DIM, 0.0, 0.0, 0.0};
136 GLfloat yPlane[] = {0.0, INV_POLY_TEX_DIM, 0.0, 0.0};
137 
138 void
140  Boundary boundary = myShape.getBoxBoundary();
141  if (s.scale * MAX2(boundary.getWidth(), boundary.getHeight()) < s.minPolySize) {
142  return;
143  }
144  if (getFill()) {
145  if (myShape.size() < 3) {
146  return;
147  }
148  } else {
149  if (myShape.size() < 2) {
150  return;
151  }
152  }
154  //if (myDisplayList == 0 || (!getFill() && myLineWidth != s.polyExaggeration)) {
155  // storeTesselation(s.polyExaggeration);
156  //}
157  glPushName(getGlID());
158  glPushMatrix();
159  glTranslated(0, 0, getLayer());
160  // XXX shape should be rotated around its center when initializing the polygon. do we even need this?
161  //glRotated(getAngle(), 0, 0, 1);
163 
164  int textureID = -1;
165  if (getFill()) {
166  const std::string& file = getImgFile();
167  if (file != "") {
168  textureID = GUITexturesHelper::getTextureID(file);
169  }
170  }
171  // init generation of texture coordinates
172  if (textureID >= 0) {
173  glEnable(GL_TEXTURE_2D);
174  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
175  glDisable(GL_CULL_FACE);
176  glDisable(GL_DEPTH_TEST); // without DEPTH_TEST vehicles may be drawn below roads
177  glDisable(GL_LIGHTING);
178  glDisable(GL_COLOR_MATERIAL);
179  glDisable(GL_ALPHA_TEST);
180  glEnable(GL_BLEND);
181  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
182  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
183  glBindTexture(GL_TEXTURE_2D, textureID);
184  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
185  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
186  // http://www.gamedev.net/topic/133564-glutesselation-and-texture-mapping/
187  glEnable(GL_TEXTURE_GEN_S);
188  glEnable(GL_TEXTURE_GEN_T);
189  glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
190  glTexGenfv(GL_S, GL_OBJECT_PLANE, xPlane);
191  glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
192  glTexGenfv(GL_T, GL_OBJECT_PLANE, yPlane);
193  }
194  // recall tesselation
195  //glCallList(myDisplayList);
197  // de-init generation of texture coordinates
198  if (textureID >= 0) {
199  glEnable(GL_DEPTH_TEST);
200  glBindTexture(GL_TEXTURE_2D, 0);
201  glDisable(GL_TEXTURE_2D);
202  glDisable(GL_TEXTURE_GEN_S);
203  glDisable(GL_TEXTURE_GEN_T);
204  }
205  glPopMatrix();
207  glPopName();
208 }
209 
210 
211 void
214  Polygon::setShape(shape);
215  //storeTesselation(myLineWidth);
216 }
217 
218 
219 void
221  if (getFill()) {
222  // draw the tesselated shape
223  double* points = new double[myShape.size() * 3];
224  GLUtesselator* tobj = gluNewTess();
225  gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid(APIENTRY*)()) &glVertex3dv);
226  gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid(APIENTRY*)()) &beginCallback);
227  gluTessCallback(tobj, GLU_TESS_END, (GLvoid(APIENTRY*)()) &endCallback);
228  //gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (APIENTRY*) ()) &errorCallback);
229  gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid(APIENTRY*)()) &combineCallback);
230  gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
231  gluTessBeginPolygon(tobj, NULL);
232  gluTessBeginContour(tobj);
233  for (size_t i = 0; i != myShape.size(); ++i) {
234  points[3 * i] = myShape[(int) i].x();
235  points[3 * i + 1] = myShape[(int) i].y();
236  points[3 * i + 2] = 0;
237  gluTessVertex(tobj, points + 3 * i, points + 3 * i);
238  }
239  gluTessEndContour(tobj);
240 
241  gluTessEndPolygon(tobj);
242  gluDeleteTess(tobj);
243  delete[] points;
244 
245  } else {
246  myLineWidth = lineWidth;
249  }
250  //std::cout << "OpenGL says: '" << gluErrorString(glGetError()) << "'\n";
251 }
252 
253 
254 void
256  if (myDisplayList > 0) {
257  glDeleteLists(myDisplayList, 1);
258  }
259  myDisplayList = glGenLists(1);
260  if (myDisplayList == 0) {
261  throw ProcessError("GUIPolygon::storeTesselation() could not create display list");
262  }
263  glNewList(myDisplayList, GL_COMPILE);
264  performTesselation(lineWidth);
265  glEndList();
266 }
267 
268 
269 /****************************************************************************/
270