From bb22ecd7e31e233b794da7b3408936f002de6338 Mon Sep 17 00:00:00 2001
From: Hannes Janetzek <hannes.janetzek@gmail.com>
Date: Wed, 30 Jan 2013 09:08:23 +0100
Subject: [PATCH] extract Layer drawing utilities from RenderOverlay into
 BasicOverlay

---
 src/org/oscim/overlay/ItemizedOverlay.java    |  4 +-
 src/org/oscim/overlay/PathOverlay.java        |  4 +-
 src/org/oscim/renderer/GLRenderer.java        | 23 ++---
 .../oscim/renderer/overlays/BasicOverlay.java | 82 +++++++++++++++++
 .../renderer/overlays/BuildingOverlay.java    |  6 ++
 .../renderer/overlays/CustomOverlay.java      | 16 ++++
 .../renderer/overlays/ExtrusionOverlay.java   |  6 ++
 .../oscim/renderer/overlays/GridOverlay.java  |  5 +-
 .../oscim/renderer/overlays/ModelOverlay.java |  6 ++
 .../renderer/overlays/RenderOverlay.java      | 89 +++++--------------
 .../renderer/overlays/TestLineOverlay.java    |  4 +
 .../oscim/renderer/overlays/TestOverlay.java  |  5 +-
 .../oscim/renderer/overlays/TextOverlay.java  |  2 +-
 .../renderer/overlays/TextOverlayExp.java     |  2 +-
 14 files changed, 160 insertions(+), 94 deletions(-)
 create mode 100644 src/org/oscim/renderer/overlays/BasicOverlay.java

diff --git a/src/org/oscim/overlay/ItemizedOverlay.java b/src/org/oscim/overlay/ItemizedOverlay.java
index 5b91b976..a0885638 100644
--- a/src/org/oscim/overlay/ItemizedOverlay.java
+++ b/src/org/oscim/overlay/ItemizedOverlay.java
@@ -6,7 +6,7 @@ import org.oscim.core.MapPosition;
 import org.oscim.core.MercatorProjection;
 import org.oscim.overlay.OverlayItem.HotspotPlace;
 import org.oscim.renderer.layer.SymbolLayer;
-import org.oscim.renderer.overlays.RenderOverlay;
+import org.oscim.renderer.overlays.BasicOverlay;
 import org.oscim.view.MapView;
 
 import android.graphics.Rect;
@@ -54,7 +54,7 @@ public abstract class ItemizedOverlay<Item extends OverlayItem> extends Overlay
 	// pre-projected points to zoomlovel 20
 	private static final byte MAX_ZOOM = 20;
 
-	class ItemOverlay extends RenderOverlay {
+	class ItemOverlay extends BasicOverlay {
 
 		private SymbolLayer mSymbolLayer;
 		private float[] mMvp = new float[16];
diff --git a/src/org/oscim/overlay/PathOverlay.java b/src/org/oscim/overlay/PathOverlay.java
index 79a838f7..32bec3f9 100644
--- a/src/org/oscim/overlay/PathOverlay.java
+++ b/src/org/oscim/overlay/PathOverlay.java
@@ -23,7 +23,7 @@ import org.oscim.core.MapPosition;
 import org.oscim.core.MercatorProjection;
 import org.oscim.renderer.layer.Layer;
 import org.oscim.renderer.layer.LineLayer;
-import org.oscim.renderer.overlays.RenderOverlay;
+import org.oscim.renderer.overlays.BasicOverlay;
 import org.oscim.theme.renderinstruction.Line;
 import org.oscim.view.MapView;
 
@@ -42,7 +42,7 @@ public class PathOverlay extends Overlay {
 	/** Paint settings. */
 	protected Paint mPaint = new Paint();
 
-	class RenderPath extends RenderOverlay {
+	class RenderPath extends BasicOverlay {
 
 		private static final byte MAX_ZOOM = 20;
 		private static final int MIN_DIST = 4;
diff --git a/src/org/oscim/renderer/GLRenderer.java b/src/org/oscim/renderer/GLRenderer.java
index e40a4885..687ab715 100644
--- a/src/org/oscim/renderer/GLRenderer.java
+++ b/src/org/oscim/renderer/GLRenderer.java
@@ -34,6 +34,7 @@ import javax.microedition.khronos.opengles.GL10;
 import org.oscim.core.MapPosition;
 import org.oscim.core.Tile;
 import org.oscim.renderer.layer.Layers;
+import org.oscim.renderer.overlays.BasicOverlay;
 import org.oscim.renderer.overlays.RenderOverlay;
 import org.oscim.theme.RenderTheme;
 import org.oscim.utils.FastMath;
@@ -279,13 +280,11 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 		tile.state = STATE_READY;
 	}
 
-	private static boolean uploadOverlayData(RenderOverlay renderOverlay) {
+	public static boolean uploadOverlayData(BasicOverlay renderOverlay) {
 		int newSize = renderOverlay.layers.getSize();
 		if (newSize > 0) {
 			if (uploadLayers(renderOverlay.layers, renderOverlay.vbo, newSize, true))
 				renderOverlay.isReady = true;
-
-			renderOverlay.newData = false;
 		}
 		return renderOverlay.isReady;
 	}
@@ -454,7 +453,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 		BaseMap.draw(tiles, tileCnt, pos);
 
 		// start drawing while overlays uploading textures, etc
-		GLES20.glFlush();
+		//GLES20.glFlush();
 
 		/* draw overlays */
 
@@ -464,22 +463,12 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 		for (int i = 0, n = overlays.size(); i < n; i++) {
 			RenderOverlay renderOverlay = overlays.get(i);
 
-			// helper to compile layers into single vbo
 			if (renderOverlay.newData) {
-				if (renderOverlay.vbo == null) {
-					renderOverlay.vbo = BufferObject.get(0);
-
-					if (renderOverlay.vbo == null)
-						continue;
-				}
-				if (uploadOverlayData(renderOverlay))
-					renderOverlay.isReady = true;
+				renderOverlay.compile();
+				renderOverlay.newData = false;
 			}
-
-			if (renderOverlay.isReady) {
-				// setMatrix(mMVPMatrix, overlay);
+			if (renderOverlay.isReady)
 				renderOverlay.render(mMapPosition, mMVPMatrix, mProjMatrix);
-			}
 		}
 
 		if (MapView.debugFrameTime) {
diff --git a/src/org/oscim/renderer/overlays/BasicOverlay.java b/src/org/oscim/renderer/overlays/BasicOverlay.java
new file mode 100644
index 00000000..92a6cde4
--- /dev/null
+++ b/src/org/oscim/renderer/overlays/BasicOverlay.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2013 OpenScienceMap
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.oscim.renderer.overlays;
+
+import org.oscim.core.MapPosition;
+import org.oscim.renderer.BufferObject;
+import org.oscim.renderer.GLRenderer;
+import org.oscim.renderer.GLState;
+import org.oscim.renderer.LineRenderer;
+import org.oscim.renderer.PolygonRenderer;
+import org.oscim.renderer.TextureRenderer;
+import org.oscim.renderer.layer.Layer;
+import org.oscim.renderer.layer.Layers;
+import org.oscim.utils.FastMath;
+import org.oscim.view.MapView;
+
+import android.opengl.GLES20;
+import android.opengl.Matrix;
+
+// Base class to use the Layers drawing 'API'
+public abstract class BasicOverlay extends RenderOverlay {
+
+	public final Layers layers;
+
+	public BufferObject vbo;
+
+	protected float[] mvp = new float[16];
+
+	public BasicOverlay(MapView mapView) {
+		super(mapView);
+		layers = new Layers();
+	}
+
+	@Override
+	public synchronized void render(MapPosition pos, float[] mv, float[] proj) {
+		setMatrix(pos, mv);
+		float div = FastMath.pow(mMapPosition.zoomLevel - pos.zoomLevel);
+
+		Matrix.multiplyMM(mvp, 0, proj, 0, mv, 0);
+
+		GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id);
+		GLState.test(false, false);
+
+		for (Layer l = layers.layers; l != null;) {
+			if (l.type == Layer.POLYGON) {
+				GLES20.glDisable(GLES20.GL_BLEND);
+				l = PolygonRenderer.draw(pos, l, mvp, true, false);
+			} else {
+				GLES20.glEnable(GLES20.GL_BLEND);
+				l = LineRenderer.draw(pos, l, mvp, div, 0, layers.lineOffset);
+			}
+		}
+
+		for (Layer l = layers.textureLayers; l != null;) {
+			l = TextureRenderer.draw(l, (mMapPosition.scale / pos.scale) * div, proj, mv);
+		}
+	}
+
+	@Override
+	public void compile() {
+		if (vbo == null) {
+			vbo = BufferObject.get(0);
+
+			if (vbo == null)
+				return;
+		}
+		if (GLRenderer.uploadOverlayData(this))
+			isReady = true;
+	}
+}
diff --git a/src/org/oscim/renderer/overlays/BuildingOverlay.java b/src/org/oscim/renderer/overlays/BuildingOverlay.java
index c2496db4..cb017cb7 100644
--- a/src/org/oscim/renderer/overlays/BuildingOverlay.java
+++ b/src/org/oscim/renderer/overlays/BuildingOverlay.java
@@ -477,6 +477,12 @@ public class BuildingOverlay extends RenderOverlay {
 			+ "  gl_FragColor = color;"
 			+ "}";
 
+	@Override
+	public void compile() {
+		// TODO Auto-generated method stub
+
+	}
+
 	//	private short[] mVertices = {
 	//	// 0 - north
 	//	-200, -200, 0,
diff --git a/src/org/oscim/renderer/overlays/CustomOverlay.java b/src/org/oscim/renderer/overlays/CustomOverlay.java
index 0aede49c..8108776a 100644
--- a/src/org/oscim/renderer/overlays/CustomOverlay.java
+++ b/src/org/oscim/renderer/overlays/CustomOverlay.java
@@ -14,6 +14,7 @@
  */
 package org.oscim.renderer.overlays;
 
+import org.oscim.core.MapPosition;
 import org.oscim.view.MapView;
 
 public class CustomOverlay extends RenderOverlay {
@@ -22,4 +23,19 @@ public class CustomOverlay extends RenderOverlay {
 		super(mapView);
 	}
 
+	@Override
+	public void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged) {
+		// tell GLRender to call 'compile'
+		newData = true;
+	}
+
+	@Override
+	public void compile() {
+		// tell GLRender to call 'render'
+		isReady = true;
+	}
+
+	@Override
+	public void render(MapPosition pos, float[] mv, float[] proj) {
+	}
 }
diff --git a/src/org/oscim/renderer/overlays/ExtrusionOverlay.java b/src/org/oscim/renderer/overlays/ExtrusionOverlay.java
index 0b857911..2549bfbe 100644
--- a/src/org/oscim/renderer/overlays/ExtrusionOverlay.java
+++ b/src/org/oscim/renderer/overlays/ExtrusionOverlay.java
@@ -460,4 +460,10 @@ public class ExtrusionOverlay extends RenderOverlay {
 	public void setAlpha(float a) {
 		mAlpha = a;
 	}
+
+	@Override
+	public void compile() {
+		// TODO Auto-generated method stub
+
+	}
 }
diff --git a/src/org/oscim/renderer/overlays/GridOverlay.java b/src/org/oscim/renderer/overlays/GridOverlay.java
index 1f8d79dd..20e69daf 100644
--- a/src/org/oscim/renderer/overlays/GridOverlay.java
+++ b/src/org/oscim/renderer/overlays/GridOverlay.java
@@ -28,7 +28,7 @@ import android.graphics.Color;
 import android.graphics.Paint.Cap;
 import android.util.Log;
 
-public class GridOverlay extends RenderOverlay {
+public class GridOverlay extends BasicOverlay {
 
 	private float[] mPoints;
 	private short[] mIndex;
@@ -110,7 +110,8 @@ public class GridOverlay extends RenderOverlay {
 	}
 
 	@Override
-	public synchronized void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged) {
+	public synchronized void update(MapPosition curPos, boolean positionChanged,
+			boolean tilesChanged) {
 
 		updateMapPosition();
 
diff --git a/src/org/oscim/renderer/overlays/ModelOverlay.java b/src/org/oscim/renderer/overlays/ModelOverlay.java
index ce1e2f19..25202e08 100644
--- a/src/org/oscim/renderer/overlays/ModelOverlay.java
+++ b/src/org/oscim/renderer/overlays/ModelOverlay.java
@@ -246,4 +246,10 @@ public class ModelOverlay extends RenderOverlay {
 		Matrix.multiplyMM(matrix, 0, curPos.viewMatrix, 0, matrix, 0);
 	}
 
+	@Override
+	public void compile() {
+		// TODO Auto-generated method stub
+
+	}
+
 }
diff --git a/src/org/oscim/renderer/overlays/RenderOverlay.java b/src/org/oscim/renderer/overlays/RenderOverlay.java
index a167d130..47c65aa7 100644
--- a/src/org/oscim/renderer/overlays/RenderOverlay.java
+++ b/src/org/oscim/renderer/overlays/RenderOverlay.java
@@ -16,19 +16,11 @@ package org.oscim.renderer.overlays;
 
 import org.oscim.core.MapPosition;
 import org.oscim.core.Tile;
-import org.oscim.renderer.BufferObject;
 import org.oscim.renderer.GLRenderer;
-import org.oscim.renderer.GLState;
-import org.oscim.renderer.LineRenderer;
-import org.oscim.renderer.PolygonRenderer;
-import org.oscim.renderer.TextureRenderer;
-import org.oscim.renderer.layer.Layer;
-import org.oscim.renderer.layer.Layers;
 import org.oscim.utils.FastMath;
 import org.oscim.utils.GlUtils;
 import org.oscim.view.MapView;
 
-import android.opengl.GLES20;
 import android.opengl.Matrix;
 
 public abstract class RenderOverlay {
@@ -37,61 +29,38 @@ public abstract class RenderOverlay {
 	// keep the Position for which the Overlay is rendered
 	protected MapPosition mMapPosition;
 
-	// current Layers to draw
-	public final Layers layers;
-
 	// flag to set when data is ready for (re)compilation.
 	public boolean newData;
 
 	// flag set by GLRenderer when data is compiled
 	public boolean isReady;
 
-	public BufferObject vbo;
-
-	protected float[] mvp = new float[16];
-
 	public RenderOverlay(MapView mapView) {
 		mMapView = mapView;
 		mMapPosition = new MapPosition();
-		layers = new Layers();
-	}
-
-	/**
-	 * Utility: update mMapPosition
-	 * @return true if position has changed
-	 */
-	protected boolean updateMapPosition() {
-		return mMapView.getMapViewPosition().getMapPosition(mMapPosition, null);
 	}
 
 	// /////////////// called from GLRender Thread ////////////////////////
-	// use synchronized (this){} when updating 'layers' from another thread
-
 	/**
+	 * called 1. by GLRenderer. Set 'newData' true when 'compile()' should be
+	 * called
+	 * before next 'render()'
 	 * @param curPos TODO
 	 * @param positionChanged
 	 *            true when MapPosition has changed
 	 * @param tilesChanged
 	 *            true when current tiles changed
 	 */
-	public synchronized void update(MapPosition curPos, boolean positionChanged,
-			boolean tilesChanged) {
-		// // keep position constant (or update layer relative to new position)
-		// mMapView.getMapViewPosition().getMapPosition(mMapPosition, null);
-		//
-		// if (first) {
-		// // fix at initial position
-		// // mapView.getMapViewPosition().getMapPosition(mMapPosition, null);
-		// first = false;
-		//
-		// // pass layers to be uploaded and drawn to GL Thread
-		// // afterwards never modify 'layers' outside of this function!
-		// newData = true;
-		// }
-	}
+	public abstract void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged);
 
 	/**
-	 * Default overlay render function
+	 * called 2. compile everything for drawing
+	 * Set 'isReady' true when things are ready for 'render()'
+	 */
+	public abstract void compile();
+
+	/**
+	 * called 3. draw overlay
 	 * @param pos
 	 *            current MapPosition
 	 * @param mv
@@ -99,32 +68,11 @@ public abstract class RenderOverlay {
 	 * @param proj
 	 *            current projection matrix
 	 */
-	public synchronized void render(MapPosition pos, float[] mv, float[] proj) {
-		setMatrix(pos, mv);
-		float div = FastMath.pow(mMapPosition.zoomLevel - pos.zoomLevel);
-
-		Matrix.multiplyMM(mvp, 0, proj, 0, mv, 0);
-
-		GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id);
-		GLState.test(false, false);
-
-		for (Layer l = layers.layers; l != null;) {
-			if (l.type == Layer.POLYGON) {
-				GLES20.glDisable(GLES20.GL_BLEND);
-				l = PolygonRenderer.draw(pos, l, mvp, true, false);
-			} else {
-				GLES20.glEnable(GLES20.GL_BLEND);
-				l = LineRenderer.draw(pos, l, mvp, div, 0, layers.lineOffset);
-			}
-		}
-
-		for (Layer l = layers.textureLayers; l != null;) {
-			l = TextureRenderer.draw(l, (mMapPosition.scale / pos.scale) * div, proj, mv);
-		}
-	}
+	public abstract void render(MapPosition pos, float[] mv, float[] proj);
 
 	/**
-	 * Utility: set matrix to scale relative to zoomlevel
+	 * Utility: set matrix relative to the difference of current MapPosition
+	 * and the last updated Overlay MapPosition
 	 * @param curPos ...
 	 * @param matrix ...
 	 */
@@ -138,7 +86,6 @@ public abstract class RenderOverlay {
 		float y = (float) (oPos.y - curPos.y * div);
 
 		// flip around date-line
-		// FIXME not sure if this is correct!
 		float max = (Tile.TILE_SIZE << oPos.zoomLevel);
 		if (x < -max / 2)
 			x = max + x;
@@ -156,4 +103,12 @@ public abstract class RenderOverlay {
 
 		Matrix.multiplyMM(matrix, 0, curPos.viewMatrix, 0, matrix, 0);
 	}
+
+	/**
+	 * Utility: update mMapPosition
+	 * @return true if position has changed
+	 */
+	protected boolean updateMapPosition() {
+		return mMapView.getMapViewPosition().getMapPosition(mMapPosition, null);
+	}
 }
diff --git a/src/org/oscim/renderer/overlays/TestLineOverlay.java b/src/org/oscim/renderer/overlays/TestLineOverlay.java
index 1888cc14..6a0a7f9e 100644
--- a/src/org/oscim/renderer/overlays/TestLineOverlay.java
+++ b/src/org/oscim/renderer/overlays/TestLineOverlay.java
@@ -388,4 +388,8 @@ public class TestLineOverlay extends RenderOverlay {
 		Matrix.multiplyMM(matrix, 0, curPos.viewMatrix, 0, matrix, 0);
 	}
 
+	@Override
+	public void compile() {
+	}
+
 }
diff --git a/src/org/oscim/renderer/overlays/TestOverlay.java b/src/org/oscim/renderer/overlays/TestOverlay.java
index c5a2ac6b..75199392 100644
--- a/src/org/oscim/renderer/overlays/TestOverlay.java
+++ b/src/org/oscim/renderer/overlays/TestOverlay.java
@@ -23,7 +23,7 @@ import org.oscim.renderer.layer.TextItem;
 import org.oscim.theme.renderinstruction.BitmapUtils;
 import org.oscim.view.MapView;
 
-public class TestOverlay extends RenderOverlay {
+public class TestOverlay extends BasicOverlay {
 
 	TextItem labels;
 
@@ -96,7 +96,8 @@ public class TestOverlay extends RenderOverlay {
 	}
 
 	@Override
-	public synchronized void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged) {
+	public synchronized void update(MapPosition curPos, boolean positionChanged,
+			boolean tilesChanged) {
 		// keep position constant (or update layer relative to new position)
 		//mMapView.getMapViewPosition().getMapPosition(mMapPosition, null);
 
diff --git a/src/org/oscim/renderer/overlays/TextOverlay.java b/src/org/oscim/renderer/overlays/TextOverlay.java
index ec5fb398..9005cabb 100644
--- a/src/org/oscim/renderer/overlays/TextOverlay.java
+++ b/src/org/oscim/renderer/overlays/TextOverlay.java
@@ -42,7 +42,7 @@ import android.util.Log;
 /**
  * @author Hannes Janetzek
  */
-public class TextOverlay extends RenderOverlay {
+public class TextOverlay extends BasicOverlay {
 	private final static String TAG = TextOverlay.class.getName();
 
 	private TileSet mTiles;
diff --git a/src/org/oscim/renderer/overlays/TextOverlayExp.java b/src/org/oscim/renderer/overlays/TextOverlayExp.java
index 9d198174..040bd9fd 100644
--- a/src/org/oscim/renderer/overlays/TextOverlayExp.java
+++ b/src/org/oscim/renderer/overlays/TextOverlayExp.java
@@ -40,7 +40,7 @@ import android.opengl.Matrix;
 import android.os.SystemClock;
 import android.util.Log;
 
-public class TextOverlayExp extends RenderOverlay {
+public class TextOverlayExp extends BasicOverlay {
 	private final static String TAG = TextOverlayExp.class.getName();
 
 	private TileSet mTiles;