View Javadoc

1   package nl.tudelft.goal.ut2004.visualizer.timeline.map;
2   
3   import java.awt.Color;
4   import java.nio.ByteBuffer;
5   import java.util.Collection;
6   import java.util.LinkedList;
7   import java.util.List;
8   import java.util.prefs.PreferenceChangeEvent;
9   import java.util.prefs.PreferenceChangeListener;
10  
11  import javax.media.opengl.GL;
12  import javax.media.opengl.GL2;
13  import javax.media.opengl.glu.GLU;
14  
15  import nl.tudelft.goal.ut2004.visualizer.map.BlendTriangle;
16  import nl.tudelft.goal.ut2004.visualizer.map.BlendVertex;
17  import nl.tudelft.goal.ut2004.visualizer.options.MapFlag;
18  import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
19  import cz.cuni.amis.pogamut.unreal.communication.worldview.map.Box;
20  import cz.cuni.amis.pogamut.unreal.communication.worldview.map.IUnrealMap;
21  import cz.cuni.amis.pogamut.unreal.communication.worldview.map.IUnrealMapInfo;
22  import cz.cuni.amis.pogamut.unreal.communication.worldview.map.IUnrealWaylink;
23  import cz.cuni.amis.pogamut.unreal.communication.worldview.map.IUnrealWaypoint;
24  import static javax.media.opengl.GL.*; // GL constants
25  import static javax.media.opengl.GL2.*; // GL2 constants
26  
27  /**
28   * Renderer of map. Because of uncomplete server implementation I have no way of
29   * knowing state of the server, so I hope this will work.
30   * 
31   * I *assume* that server is up and running and I can get worldmap from it.
32   * 
33   * @author Honza
34   */
35  public class MapRenderer implements ISubGLRenderer<IUnrealMap>, PreferenceChangeListener {
36  
37  	private GLU glu = new GLU();
38  	public final int GRID_SCALE = 1000;
39  	public final double NAVPOINT_RADIUS = 30;
40  
41  	/**
42  	 * OpenGL display lists
43  	 */
44  	private int gridList = -1;
45  	private int pathDisplayList = -1;
46  	private int waypointDisplayList = -1;
47  	private int backgroundList = -1;
48  
49  	/**
50  	 * Flag that we should update display lists according to new data from
51  	 * preferences.
52  	 */
53  	private boolean updateLists = true;
54  
55  	private IUnrealMap map;
56  	/**
57  	 * List of all triangles used for rendering paths between
58  	 */
59  	private List<PathTriangle> pathTris;
60  	/**
61  	 * List of triangles used waypoints
62  	 */
63  	private List<BlendTriangle> waypointsTris;
64  	private int glName;
65  
66  	/**
67  	 * GameBots provides us with flags about pathways between navpoints. This
68  	 * class is human readable names for flags.
69  	 * 
70  	 * The reason why is this class and not enum is that it is a bitmap mask so
71  	 * they can easily combine. For now.
72  	 */
73  	public MapRenderer(IUnrealMap map, /* MapViewpoint observer, */int glName) {
74  		this.map = map;
75  		this.glName = glName;
76  		// TODO(MP): Add preference change lisetner to preference provider here.
77  
78  	}
79  
80  	@Override
81  	public IUnrealMap getObject() {
82  		return map;
83  	}
84  
85  	/**
86  	 * Precreate display lists for map, because map can be quite large and it
87  	 * would be troublesome to do it every rendering.
88  	 * 
89  	 * @param gl
90  	 */
91  	@Override
92  	public void prepare(GL gl) {
93  		gridList = createGridList(gl);
94  		backgroundList = createMapBackground(gl);
95  
96  		// Create data for map
97  		// waypointsTris = createWaypointsList();
98  		// Not rendering way points so we can select them.
99  		waypointsTris = new LinkedList<BlendTriangle>();
100 
101 		pathTris = createPathsList();
102 
103 	}
104 
105 	/**
106 	 * Create a diplay list for map background image, i.e. image that is show
107 	 * above grid to give a better idea about world. It is mostly screenshot
108 	 * from UnrealEd.
109 	 * 
110 	 * @param gl
111 	 * @return id of display list
112 	 */
113 	public int createMapBackground(GL gla) {
114 		GL2 gl = gla.getGL2();
115 		IUnrealMapInfo info = map.getInfo();
116 
117 		if (info == null) {
118 			return -1;
119 		}
120 
121 		Location[] pos2D = info.getImagePoints();// new Location[3];
122 		Location[] posMap = info.getWorldPoints();// new Location[3];
123 
124 		for (int i = 0; i < posMap.length; i++) {
125 			posMap[i] = posMap[i].setZ(0);
126 		}
127 
128 		// Chci pozice rohu obrazku ve 3d
129 		Location vec1stTo2nd = Location.sub(pos2D[1], pos2D[0]);
130 		Location vec1stTo3rd = Location.sub(pos2D[2], pos2D[0]);
131 
132 		// get position in 3d for every corner
133 		Coeficients[] coef = new Coeficients[4];
134 		// tlc ~ top left corner
135 		coef[0] = solveEquation(new Location(0, 0, 0), pos2D[0], vec1stTo2nd, vec1stTo3rd);
136 		// trc
137 		coef[1] = solveEquation(new Location(info.getWidth(), 0, 0), pos2D[0], vec1stTo2nd, vec1stTo3rd);
138 		// brc
139 		coef[2] = solveEquation(new Location(info.getWidth(), info.getHeight(), 0), pos2D[0], vec1stTo2nd, vec1stTo3rd);
140 		// blc
141 		coef[3] = solveEquation(new Location(0, info.getHeight(), 0), pos2D[0], vec1stTo2nd, vec1stTo3rd);
142 
143 		Location map1stTo2nd = Location.sub(posMap[1], posMap[0]);
144 		Location map1stTo3rd = Location.sub(posMap[2], posMap[0]);
145 
146 		Location[] mapLoc = new Location[4];
147 
148 		for (int i = 0; i < 4; i++) {
149 			mapLoc[i] = Location.add(posMap[0],
150 					Location.add(map1stTo2nd.scale(coef[i].a), map1stTo3rd.scale(coef[i].b)));
151 		}
152 
153 		int texture = genTexture(gl);
154 
155 		gl.glBindTexture(GL.GL_TEXTURE_2D, texture);
156 
157 		glu.gluBuild2DMipmaps(GL.GL_TEXTURE_2D, GL.GL_RGB8, info.getWidth(), info.getHeight(), GL.GL_RGB,
158 				GL.GL_UNSIGNED_BYTE, ByteBuffer.wrap(info.getImgRGBData()));
159 
160 		gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
161 		gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
162 
163 		int list = gl.glGenLists(1);
164 
165 		// start new list
166 		gl.glNewList(list, GL_COMPILE);
167 
168 		gl.glEnable(GL_TEXTURE_2D);
169 
170 		gl.glBindTexture(GL_TEXTURE_2D, texture);
171 
172 		gl.glBegin(GL_QUADS);
173 
174 		gl.glColor3d(1, 1, 1);
175 
176 		int i = 0;
177 		double z = getFloorZ() + 5;
178 		gl.glTexCoord2d(0, 1);
179 		gl.glVertex3d(mapLoc[i].x, mapLoc[i].y, z);
180 
181 		i = 1;
182 		gl.glTexCoord2d(1, 1);
183 		gl.glVertex3d(mapLoc[i].x, mapLoc[i].y, z);
184 
185 		i = 2;
186 		gl.glTexCoord2d(1, 0);
187 		gl.glVertex3d(mapLoc[i].x, mapLoc[i].y, z);
188 
189 		i = 3;
190 		gl.glTexCoord2d(0, 0);
191 		gl.glVertex3d(mapLoc[i].x, mapLoc[i].y, z);
192 
193 		gl.glEnd();
194 
195 		gl.glDisable(GL.GL_TEXTURE_2D);
196 
197 		gl.glEndList();
198 
199 		return list;
200 	}
201 
202 	/**
203 	 * Generate one texture
204 	 * 
205 	 * @param gl
206 	 * @return id of texture
207 	 */
208 	private int genTexture(GL gl) {
209 		int[] textures = new int[1];
210 		gl.glGenTextures(1, textures, 0);
211 		return textures[0];
212 	}
213 
214 	private double getFloorZ() {
215 		Box box = map.getBox();
216 		return box.minZ - box.getMinDelta() * 0.20;
217 	}
218 
219 	private double getGridZ() {
220 		Box box = map.getBox();
221 		return box.minZ - box.getMinDelta() * 0.35;
222 	}
223 
224 	private static class Coeficients {
225 
226 		public Coeficients(double a, double b) {
227 			this.a = a;
228 			this.b = b;
229 		}
230 
231 		double a, b;
232 	}
233 
234 	/**
235 	 * get vector components so R = P+a*U +b*V
236 	 * 
237 	 * @return
238 	 */
239 	private Coeficients solveEquation(Location r, Location p, Location u, Location v) {
240 		/*
241 		 * r.x = p.x + a*u.x + b*v.x r.y = p.y + a*u.y + b*v.y
242 		 */
243 		if (u.x != 0) {
244 			double multi = u.y / u.x;
245 			/*
246 			 * 0 = (p.x - r.x) * multi + a*u.x * multi + b*v.x * multi 0 = (p.y
247 			 * - r.y) + a*u.y + b*v.y
248 			 * 
249 			 * 0 = (p.y - r.y) - (p.x - r.x) * multi + b*v.y - b*v.x * multi
250 			 */
251 			double b = (-((p.y - r.y) - (p.x - r.x) * multi)) / (v.y - v.x * multi);
252 
253 			// 0 = (p.x - a.x) + a*u.x + b*v.x
254 			double a = -((p.x - r.x) + b * v.x) / u.x;
255 
256 			return new Coeficients(a, b);
257 		} else {
258 			/*
259 			 * r.x = p.x + b*v.x r.y = p.y + a*u.y + b*v.y
260 			 */
261 			double b = (r.x - p.x) / v.x;
262 			double a = (r.y - p.y - b * v.y) / u.y;
263 			return new Coeficients(a, b);
264 		}
265 
266 	}
267 
268 	/**
269 	 * Return list of triangles that (if rendered) displays all waypoints in the
270 	 * map. Waypoints are represented as circle with radius
271 	 * {@link NAVPOINT_RADIUS} at every waypoint.
272 	 * 
273 	 * @return List of triangles
274 	 */
275 	private LinkedList<BlendTriangle> createWaypointsList() {
276 		LinkedList<BlendTriangle> triangles = new LinkedList<BlendTriangle>();
277 		Collection<IUnrealWaypoint> navs = map.vertexSet();
278 
279 		GlColor color = getWayPointColor();
280 		for (IUnrealWaypoint nav : navs) {
281 			Location loc = nav.getLocation();
282 
283 			Location[] points = createCirclePoints(loc, NAVPOINT_RADIUS);
284 
285 			for (int pointIndex = 0; pointIndex < points.length; pointIndex++) {
286 				BlendTriangle triangle = new BlendTriangle();
287 
288 				triangle.setVertex(0, loc, color);
289 				triangle.setVertex(1, points[pointIndex], color);
290 				triangle.setVertex(2, points[(pointIndex + 1) % points.length], color);
291 
292 				triangles.add(triangle);
293 			}
294 		}
295 
296 		return triangles;
297 	}
298 
299 	private GlColor getWayPointColor() {
300 		// TODO: Use preference here.
301 		return new GlColor(Color.BLUE);
302 	}
303 
304 	/**
305 	 * Return list of points that form a circle with center loc and radius
306 	 * radius.
307 	 * 
308 	 * @param loc
309 	 *            Center of circle
310 	 * @param radius
311 	 *            Radius of circle
312 	 * @return List of points that form the circle
313 	 */
314 	private Location[] createCirclePoints(Location loc, double radius) {
315 		Location[] points = new Location[12];
316 
317 		double stepAngle = 2 * Math.PI / points.length;
318 
319 		for (int pointIndex = 0; pointIndex < points.length; pointIndex++) {
320 			double angle = stepAngle * pointIndex;
321 			double xPos = loc.x + radius * Math.cos(angle);
322 			double yPos = loc.y + radius * Math.sin(angle);
323 			points[pointIndex] = new Location(xPos, yPos, loc.z);
324 		}
325 
326 		return points;
327 	}
328 
329 	/**
330 	 * Create OpenGl list for grid lines of the map.
331 	 * 
332 	 * @return id of a list
333 	 */
334 	private int createGridList(GL gla) {
335 		GL2 gl = gla.getGL2();
336 		Box mapBox = map.getBox();
337 		int numMainLines = getNumGridLines(mapBox);
338 
339 		double lineLength = 2 * GRID_SCALE * numMainLines;
340 		// TODO: Is 10 good arbiotrary number?
341 		double floorZ = getGridZ();
342 		int list = gl.glGenLists(1);
343 
344 		gl.glNewList(list, GL_COMPILE);
345 		{
346 			gl.glBegin(GL_LINES);
347 			{
348 				// central X lines, red
349 				double minY = mapBox.getCenterY() - lineLength / 2;
350 				double maxY = mapBox.getCenterY() + lineLength / 2;
351 
352 				gl.glColor3d(0.45, 0.29, 0.32);
353 				gl.glVertex3d(mapBox.getCenterX(), minY, floorZ);
354 				gl.glVertex3d(mapBox.getCenterX(), maxY, floorZ);
355 
356 				// central Y line, green
357 				double minX = mapBox.getCenterX() - lineLength / 2;
358 				double maxX = mapBox.getCenterX() + lineLength / 2;
359 
360 				gl.glColor3d(0.3, 0.57, 0.31);
361 				gl.glVertex3d(minX, mapBox.getCenterY(), floorZ);
362 				gl.glVertex3d(maxX, mapBox.getCenterY(), floorZ);
363 
364 				// other lines for better idea about size of level
365 				// main lines
366 				for (int line = 1; line <= numMainLines; line++) {
367 					for (int coef = -1; coef <= 1; coef += 2) {
368 						// main lines (darker grey)
369 						gl.glColor3d(0.34, 0.34, 0.34);
370 						// draw along Y axis
371 						gl.glVertex3d(mapBox.getCenterX() + coef * line * GRID_SCALE, minY, floorZ);
372 						gl.glVertex3d(mapBox.getCenterX() + coef * line * GRID_SCALE, maxY, floorZ);
373 						// draw along X axis
374 						gl.glVertex3d(minX, mapBox.getCenterY() + coef * line * GRID_SCALE, floorZ);
375 						gl.glVertex3d(maxX, mapBox.getCenterY() + coef * line * GRID_SCALE, floorZ);
376 
377 						// minor lines (lighter grey)
378 						gl.glColor3d(0.41, 0.41, 0.41);
379 						for (int minority = 1; minority < 10; minority++) {
380 							// draw along Y axis
381 							gl.glVertex3d(mapBox.getCenterX() + coef
382 									* ((line - 1) * GRID_SCALE + minority * GRID_SCALE / 10), minY, floorZ);
383 							gl.glVertex3d(mapBox.getCenterX() + coef
384 									* ((line - 1) * GRID_SCALE + minority * GRID_SCALE / 10), maxY, floorZ);
385 							// draw along X axis
386 							gl.glVertex3d(minX, mapBox.getCenterY() + coef
387 									* ((line - 1) * GRID_SCALE + minority * GRID_SCALE / 10), floorZ);
388 							gl.glVertex3d(maxX, mapBox.getCenterY() + coef
389 									* ((line - 1) * GRID_SCALE + minority * GRID_SCALE / 10), floorZ);
390 						}
391 					}
392 				}
393 			}
394 			gl.glEnd();
395 		}
396 		gl.glEndList();
397 
398 		return list;
399 	}
400 
401 	/**
402 	 * How many squares (each square is GRID_SCALE big) will grid have from
403 	 * center to border in every direction.
404 	 * 
405 	 * @return Number of squares of the box
406 	 */
407 	private int getNumGridLines(Box mapBox) {
408 		double max = mapBox.getDeltaX() > mapBox.getDeltaY() ? mapBox.getDeltaX() : mapBox.getDeltaY();
409 
410 		max /= 2;
411 		return (int) Math.ceil(max / GRID_SCALE);
412 	}
413 
414 	/**
415 	 * Return list of locations that will represent quads
416 	 * 
417 	 * @param path
418 	 *            array of location[i*4], i is some number, currently 3, but it
419 	 *            depends on structure of connection
420 	 */
421 	private Location[] createQuadPath(IUnrealWaylink path) {
422 		Location[] quads = new Location[3 * 4];
423 
424 		IUnrealWaypoint from = path.getStart();
425 		IUnrealWaypoint to = path.getEnd();
426 
427 		Location fromLoc = from.getLocation();
428 		Location toLoc = to.getLocation();
429 
430 		// get normalized direction from fromNav to toNav in x,y plane.
431 		Location dir = Location.sub(toLoc, fromLoc);
432 		dir = dir.setZ(0);
433 		dir = dir.getNormalized();
434 
435 		Location trans = new Location(dir.y, -dir.x, 0);
436 
437 		// now do the quad to cover circle part of fromNav
438 		quads[0] = Location.add(fromLoc, trans.scale(NAVPOINT_RADIUS));
439 		quads[1] = Location.add(quads[0], dir.scale(NAVPOINT_RADIUS));
440 		quads[2] = Location.add(quads[1], trans.scale(-2 * NAVPOINT_RADIUS));
441 		quads[3] = Location.add(quads[2], dir.scale(-NAVPOINT_RADIUS));
442 
443 		// quad that is covering to toNav
444 		quads[4] = Location.add(toLoc, trans.scale(-NAVPOINT_RADIUS));
445 		quads[5] = Location.add(quads[4], dir.scale(-NAVPOINT_RADIUS));
446 		quads[6] = Location.add(quads[5], trans.scale(2 * NAVPOINT_RADIUS));
447 		quads[7] = Location.add(quads[6], dir.scale(NAVPOINT_RADIUS));
448 
449 		quads[8] = quads[2];
450 		quads[9] = quads[1];
451 		quads[10] = quads[6];
452 		quads[11] = quads[5];
453 
454 		return quads;
455 	}
456 
457 	private static class PathTriangle extends BlendTriangle {
458 
459 		private int flags;
460 
461 		public PathTriangle(int flags) {
462 			this.flags = flags;
463 		}
464 
465 		public int getFlags() {
466 			return flags;
467 		}
468 	}
469 
470 	private LinkedList<PathTriangle> createPathsList() {
471 		LinkedList<PathTriangle> triangles = new LinkedList<PathTriangle>();
472 		Collection<IUnrealWaylink> paths = map.edgeSet();
473 
474 		double deltaZ = this.map.getBox().getDeltaZ();
475 		double displaceZ = this.map.getBox().minZ;
476 
477 		for (IUnrealWaylink path : paths) {
478 			Location[] quads = createQuadPath(path);
479 
480 			GlColor lowColor = new GlColor(0.8, 0.8, 0.8);
481 			GlColor highColor = new GlColor(0.8, 0, 0);
482 
483 			// put quads to the list of blend triangles
484 			int quadNum = quads.length / 4;
485 			for (int quad = 0; quad < quadNum; quad++) {
486 				PathTriangle triOne = new PathTriangle(path.getFlags());
487 
488 				for (int i = 0; i < 3; i++) {
489 					Location vertexLoc = quads[quad * 4 + i];
490 					GlColor color = lowColor.getMixedWith(highColor, (vertexLoc.z - displaceZ) / deltaZ);
491 					triOne.setVertex(i, vertexLoc, color);
492 				}
493 
494 				PathTriangle triTwo = new PathTriangle(path.getFlags());
495 				for (int i = 0; i < 3; i++) {
496 					int quadIndex = quad * 4 + ((i + 2) % 4);
497 					Location vertexLoc = quads[quadIndex];
498 					GlColor color = lowColor.getMixedWith(highColor, (vertexLoc.z - displaceZ) / deltaZ);
499 					triTwo.setVertex(i, vertexLoc, color);
500 				}
501 
502 				triangles.add(triOne);
503 				triangles.add(triTwo);
504 			}
505 		}
506 		return triangles;
507 	}
508 
509 	@Override
510 	public synchronized void render(GL gla) {
511 		GL2 gl = gla.getGL2();
512 		
513 		/*
514 		 * After a while it seems that using lighting and blending produces
515 		 * worse results than this, at least in lucidity.
516 		 * 
517 		 * float[] lightAmbient = new float[]{0.5f, 0.5f, 0.5f, 1.0f}; float[]
518 		 * lightDiffuse = new float[]{1.0f, 1.0f, 1.0f, 1.0f}; float[]
519 		 * lightPosition = new float[]{ 0, 0, 1210,//0, 0, 0, //
520 		 * (float)levelBox.getFlag().getCenterX(), //
521 		 * (float)levelBox.getFlag().getCenterY(), //
522 		 * (float)levelBox.getFlag().getCenterZ() +
523 		 * (float)levelBox.getFlag().getDeltaZ(), 1.0f};
524 		 * gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT,
525 		 * FloatBuffer.wrap(lightAmbient)); gl.glLightfv(GL.GL_LIGHT0,
526 		 * GL.GL_DIFFUSE, FloatBuffer.wrap(lightDiffuse));
527 		 * gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION,
528 		 * FloatBuffer.wrap(lightPosition)); gl.glEnable(GL.GL_LIGHT0);
529 		 * 
530 		 * gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPOT_DIRECTION, new float[]{0, 0,
531 		 * 1}, 0);
532 		 */
533 
534 		if (updateLists || !gl.glIsList(waypointDisplayList) || !gl.glIsList(pathDisplayList)) {
535 			updateMapDisplayLists(gl);
536 			updateLists = false;
537 		}
538 
539 		gl.glLoadName(glName);
540 
541 		// Rendering like this is too CPU intensive, so using display lists
542 		// renderPaths(gl, pathTris);
543 		// renderWaypoints(gl, waypointsTris);
544 
545 		// render grid and background
546 		gl.glShadeModel(GL_FLAT);
547 		gl.glCallList(gridList);
548 		gl.glCallList(backgroundList);
549 		gl.glCallList(pathDisplayList);
550 		gl.glCallList(waypointDisplayList);
551 
552 		gl.glLoadName(-1);
553 	}
554 
555 	/**
556 	 * Render triangles stored in pathTriangles with info from settings
557 	 * 
558 	 * @param gl
559 	 */
560 	private synchronized void renderPaths(GL gla, List<PathTriangle> triangles) {
561 		GL2 gl = gla.getGL2();
562 		// Get colors from preferences
563 		GlColor lowColor = getLowColor();
564 		GlColor highColor = getHighColor();
565 
566 		boolean includeFlagBehavior = getIncludePathsFlag();
567 
568 		double deltaZ = this.map.getBox().getDeltaZ();
569 		double displaceZ = this.map.getBox().minZ;
570 
571 		gl.glEnable(GL_COLOR_MATERIAL);
572 		gl.glShadeModel(GL_SMOOTH);
573 
574 		gl.glBegin(GL_TRIANGLES);
575 		for (PathTriangle triangle : triangles) {
576 			boolean render = false;
577 			if (includeFlagBehavior) {
578 				render = includeCanRenderPathFlag(triangle.getFlags());
579 			} else {
580 				render = excludeCanRenderFlag(triangle.getFlags());
581 			}
582 
583 			if (render) {
584 				for (BlendVertex v : triangle.getVerts()) {
585 					Location vertexLoc = v.getLocation();
586 					GlColor color = lowColor.getMixedWith(highColor, (vertexLoc.z - displaceZ) / deltaZ);
587 
588 					gl.glColor4d(color.r, color.g, color.b, color.a);
589 					gl.glVertex3d(vertexLoc.x, vertexLoc.y, vertexLoc.z);
590 				}
591 			}
592 		}
593 		gl.glEnd();
594 	}
595 
596 	private boolean getIncludePathsFlag() {
597 		// TODO(MP): User a preference provider
598 		return true;
599 	}
600 
601 	private GlColor getHighColor() {
602 		// TODO(MP): User a preference provider
603 		return new GlColor(Color.WHITE);
604 	}
605 
606 	private GlColor getLowColor() {
607 		// TODO(MP): User a preference provider
608 		return new GlColor(Color.LIGHT_GRAY);
609 	}
610 
611 	/**
612 	 * If testedFlags has flag that according to preferences should be drawn,
613 	 * draw it
614 	 * 
615 	 * @param flag
616 	 * @return true if at least one of flags in testedFlag is set and
617 	 *         preferences says that we should render it
618 	 */
619 	private synchronized boolean includeCanRenderPathFlag(int testedFlag) {
620 		for (MapFlag flag : MapFlag.values()) {
621 			// if tested flag has enabled the flag
622 			if ((flag.getFlag() & testedFlag) != 0) {
623 				// if it does, does user says we should render such paths
624 				boolean shouldRender = getShouldRender();
625 				if (shouldRender) {
626 					return true;
627 				}
628 			}
629 		}
630 		return false;
631 	}
632 
633 	private boolean getShouldRender() {
634 		// TODO(MP:) Use a preference provider here.
635 		return true;
636 	}
637 
638 	/**
639 	 * If testedFlags has flag that according to preferences shouldn't be drawn,
640 	 * don't render.
641 	 * 
642 	 * @param testedFlag
643 	 * @return
644 	 */
645 	private synchronized boolean excludeCanRenderFlag(int testedFlag) {
646 		for (MapFlag flag : MapFlag.values()) {
647 			// if tested flag has enabled the flag
648 			if ((flag.getFlag() & testedFlag) != 0) {
649 				// if it does, does user says we should render such paths
650 				boolean shouldRender = getShouldRender();
651 				if (!shouldRender) {
652 					return false;
653 				}
654 			}
655 		}
656 		return true;
657 	}
658 
659 	/**
660 	 * Render all waypoints (the circles in the map), data generated in
661 	 * createWaypointsList
662 	 * 
663 	 * @param gl
664 	 * @param triangles
665 	 */
666 	private synchronized void renderWaypoints(GL gla, List<BlendTriangle> triangles) {
667 		GL2 gl = gla.getGL2();
668 		GlColor color = getWayPointColor();
669 
670 		gl.glEnable(GL_COLOR_MATERIAL);
671 		gl.glShadeModel(GL_SMOOTH);
672 
673 		gl.glBegin(GL_TRIANGLES);
674 		for (BlendTriangle triangle : triangles) {
675 			for (BlendVertex v : triangle.getVerts()) {
676 				// take color according to width
677 				gl.glColor4d(color.r, color.g, color.b, color.a);
678 				gl.glVertex3d(v.getLocation().x, v.getLocation().y, v.getLocation().z + 0.1);
679 			}
680 		}
681 		gl.glEnd();
682 	}
683 
684 	@Override
685 	public synchronized void preferenceChange(PreferenceChangeEvent evt) {
686 		updateLists = true;
687 	}
688 
689 	/**
690 	 * Update display lists for waypoints and path quads according to
691 	 * preferences
692 	 */
693 	private synchronized void updateMapDisplayLists(GL gla) {
694 		GL2 gl = gla.getGL2();
695 		
696 		// delete old
697 		gl.glDeleteLists(pathDisplayList, 1);
698 		gl.glDeleteLists(waypointDisplayList, 1);
699 
700 		// create new
701 		pathDisplayList = gl.glGenLists(1);
702 		gl.glNewList(pathDisplayList, GL_COMPILE);
703 		renderPaths(gl, pathTris);
704 		gl.glEndList();
705 
706 		waypointDisplayList = gl.glGenLists(1);
707 		gl.glNewList(waypointDisplayList, GL_COMPILE);
708 		renderWaypoints(gl, waypointsTris);
709 		gl.glEndList();
710 	}
711 
712 	@Override
713 	public List<BlendTriangle> getBlendedTris() {
714 		List<BlendTriangle> list = new LinkedList<BlendTriangle>();
715 		return list;
716 	}
717 
718 	/**
719 	 * Clean up the component (listeners, contexts ect.)
720 	 */
721 	public void destroy() {
722 		// TODO(MP): Remove preference provider
723 	}
724 }