From b9ebf1e57b0509a6ba2ba0cc09e7008a24d90ada Mon Sep 17 00:00:00 2001
From: Hannes Janetzek <hannes.janetzek@gmail.com>
Date: Sun, 25 May 2014 02:26:36 +0200
Subject: [PATCH] refactor ExtrusionRenderer

+ cleanups
---
 .../org/oscim/renderer/ExtrusionRenderer.java | 201 +++++++-----------
 1 file changed, 75 insertions(+), 126 deletions(-)

diff --git a/vtm/src/org/oscim/renderer/ExtrusionRenderer.java b/vtm/src/org/oscim/renderer/ExtrusionRenderer.java
index 8cae3ea8..39a1e691 100644
--- a/vtm/src/org/oscim/renderer/ExtrusionRenderer.java
+++ b/vtm/src/org/oscim/renderer/ExtrusionRenderer.java
@@ -25,9 +25,8 @@ import org.slf4j.LoggerFactory;
 
 public abstract class ExtrusionRenderer extends LayerRenderer {
 	static final Logger log = LoggerFactory.getLogger(ExtrusionRenderer.class);
-	static final boolean debugDraw = false;
 
-	private final boolean drawAlpha;
+	private final boolean mTranslucent;
 	private final int mMode;
 	private Shader mShader;
 
@@ -37,7 +36,7 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
 
 	public ExtrusionRenderer(boolean mesh, boolean alpha) {
 		mMode = mesh ? 1 : 0;
-		drawAlpha = alpha;
+		mTranslucent = alpha;
 	}
 
 	public static class Shader extends GLShader {
@@ -67,11 +66,6 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
 	}
 
 	private void renderCombined(int vertexPointer, ExtrusionLayers els) {
-		if (els.vboIndices == null)
-			return;
-
-		els.vboIndices.bind();
-		els.vboVertices.bind();
 
 		for (ExtrusionLayer el = els.layers; el != null; el = el.next()) {
 
@@ -93,169 +87,149 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
 
 	@Override
 	public void render(GLViewport v) {
-		// TODO one could render in one pass to texture and then draw the texture
-		// with alpha... might be faster and would allow postprocessing outlines.
-
-		ExtrusionLayers[] els = mExtrusionLayerSet;
-		Shader s = mShader;
-
-		if (debugDraw) {
-			s.useProgram();
-			GLState.enableVertexArrays(s.aPos, s.aLight);
-			GL.glUniform1i(s.uMode, 0);
-			GLUtils.glUniform4fv(s.uColor, 4, DEBUG_COLOR);
-			GL.glUniform1f(s.uAlpha, 1);
-
-			GLState.test(false, false);
-			GLState.blend(true);
-			for (int i = 0; i < mExtrusionLayerCnt; i++) {
-				ExtrusionLayer el = els[i].getLayers();
-
-				setMatrix(v, els[i], 0);
-				v.mvp.setAsUniform(s.uMVP);
-
-				renderCombined(s.aPos, els[i]);
-
-				/* just a temporary reference! */
-				els[i] = null;
-			}
-			return;
-		}
 
 		GL.glDepthMask(true);
 		GL.glClear(GL20.GL_DEPTH_BUFFER_BIT);
 
 		GLState.test(true, false);
 
+		Shader s = mShader;
 		s.useProgram();
 		GLState.enableVertexArrays(s.aPos, -1);
-		GLState.blend(false);
 
-		GL.glEnable(GL20.GL_CULL_FACE);
+		/* only use face-culling when it's unlikely
+		 * that one'moves through the building' */
+		if (v.pos.zoomLevel < 18)
+			GL.glEnable(GL20.GL_CULL_FACE);
+
 		GL.glDepthFunc(GL20.GL_LESS);
-
 		GL.glUniform1f(s.uAlpha, mAlpha);
 
-		if (drawAlpha) {
+		ExtrusionLayers[] els = mExtrusionLayerSet;
+
+		if (mTranslucent) {
+			/* only draw to depth buffer */
+			GLState.blend(false);
 			GL.glColorMask(false, false, false, false);
 			GL.glUniform1i(s.uMode, -1);
-			//GLUtils.glUniform4fv(uExtColor, 4, mColor);
 
-			/* draw to depth buffer */
 			for (int i = 0; i < mExtrusionLayerCnt; i++) {
-				ExtrusionLayer el = els[i].getLayers();
-				if (el == null)
-					continue;
+				if (els[i].vboIndices == null)
+					return;
 
-				int d = 0; // FIXME MapTile.depthOffset(t) * 10;
+				els[i].vboIndices.bind();
+				els[i].vboVertices.bind();
 
-				setMatrix(v, els[i], d);
+				setMatrix(v, els[i], true);
 				v.mvp.setAsUniform(s.uMVP);
 
 				renderCombined(s.aPos, els[i]);
 			}
 
+			/* only draw to color buffer */
 			GL.glColorMask(true, true, true, true);
 			GL.glDepthMask(false);
-			GLState.blend(true);
+
+			GL.glDepthFunc(GL20.GL_EQUAL);
 		}
 
 		GLState.blend(true);
-		GLState.enableVertexArrays(s.aPos, s.aLight);
 
+		GLState.enableVertexArrays(s.aPos, s.aLight);
 		float[] currentColor = null;
 
 		for (int i = 0; i < mExtrusionLayerCnt; i++) {
-			ExtrusionLayer el = els[i].getLayers();
-
-			if (el == null)
-				continue;
-
 			if (els[i].vboIndices == null)
 				continue;
 
 			els[i].vboIndices.bind();
 			els[i].vboVertices.bind();
 
-			int d = 0;
-			if (drawAlpha) {
-				GL.glDepthFunc(GL20.GL_EQUAL);
-
-				// FIXME d = MapTile.depthOffset(t) * 10;
+			if (!mTranslucent) {
+				setMatrix(v, els[i], false);
+				v.mvp.setAsUniform(s.uMVP);
 			}
 
-			setMatrix(v, els[i], d);
-			v.mvp.setAsUniform(s.uMVP);
-
+			ExtrusionLayer el = els[i].getLayers();
 			for (; el != null; el = el.next()) {
 
 				if (el.colors != currentColor) {
 					currentColor = el.colors;
-					GLUtils.glUniform4fv(s.uColor, mMode == 0 ? 4 : 1,
+					GLUtils.glUniform4fv(s.uColor,
+					                     mMode == 0 ? 4 : 1,
 					                     el.colors);
 				}
 
-				/* indices offset */
-				int indexOffset = el.indexOffset;
-				/* vertex byte offset */
-				int vertexOffset = el.getOffset();
-
-				GL.glVertexAttribPointer(s.aPos, 3,
-				                         GL20.GL_SHORT, false, 8, vertexOffset);
+				GL.glVertexAttribPointer(s.aPos, 3, GL20.GL_SHORT,
+				                         false, 8, el.getOffset());
 
 				GL.glVertexAttribPointer(s.aLight, 2,
-				                         GL20.GL_UNSIGNED_BYTE, false, 8, vertexOffset + 6);
+				                         GL20.GL_UNSIGNED_BYTE,
+				                         false, 8, el.getOffset() + 6);
 
 				/* draw extruded outlines */
 				if (el.numIndices[0] > 0) {
+					if (mTranslucent) {
+						GL.glDepthFunc(GL20.GL_EQUAL);
+						setMatrix(v, els[i], true);
+						v.mvp.setAsUniform(s.uMVP);
+					}
+
 					/* draw roof */
 					GL.glUniform1i(s.uMode, 0);
-					GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[2],
+					GL.glDrawElements(GL20.GL_TRIANGLES,
+					                  el.numIndices[2],
 					                  GL20.GL_UNSIGNED_SHORT,
-					                  (el.numIndices[0] + el.numIndices[1]) * 2);
+					                  (el.numIndices[0]
+					                  + el.numIndices[1]) * 2);
 
 					/* draw sides 1 */
 					GL.glUniform1i(s.uMode, 1);
-					GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[0],
+					GL.glDrawElements(GL20.GL_TRIANGLES,
+					                  el.numIndices[0],
 					                  GL20.GL_UNSIGNED_SHORT, 0);
 
 					/* draw sides 2 */
 					GL.glUniform1i(s.uMode, 2);
-					GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[1],
-					                  GL20.GL_UNSIGNED_SHORT, el.numIndices[0] * 2);
+					GL.glDrawElements(GL20.GL_TRIANGLES,
+					                  el.numIndices[1],
+					                  GL20.GL_UNSIGNED_SHORT,
+					                  el.numIndices[0] * 2);
 
-					if (drawAlpha) {
+					if (mTranslucent) {
 						/* drawing gl_lines with the same coordinates does not
 						 * result in same depth values as polygons, so add
 						 * offset and draw gl_lequal: */
 						GL.glDepthFunc(GL20.GL_LEQUAL);
+						v.mvp.addDepthOffset(100);
+						v.mvp.setAsUniform(s.uMVP);
 					}
 
-					v.mvp.addDepthOffset(100);
-					v.mvp.setAsUniform(s.uMVP);
-
 					GL.glUniform1i(s.uMode, 3);
-
-					int offset = 2 * (indexOffset
+					int offset = 2 * (el.indexOffset
 					        + el.numIndices[0]
 					        + el.numIndices[1]
 					        + el.numIndices[2]);
 
-					GL.glDrawElements(GL20.GL_LINES, el.numIndices[3],
-					                  GL20.GL_UNSIGNED_SHORT, offset);
+					GL.glDrawElements(GL20.GL_LINES,
+					                  el.numIndices[3],
+					                  GL20.GL_UNSIGNED_SHORT,
+					                  offset);
+
 				}
 
 				/* draw triangle meshes */
 				if (el.numIndices[4] > 0) {
-					int offset = 2 * (indexOffset
+					int offset = 2 * (el.indexOffset
 					        + el.numIndices[0]
 					        + el.numIndices[1]
 					        + el.numIndices[2]
 					        + el.numIndices[3]);
 
-					GL.glUniform1i(s.uMode, 4);
-					GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[4],
-					                  GL20.GL_UNSIGNED_SHORT, offset);
+					GL.glDrawElements(GL20.GL_TRIANGLES,
+					                  el.numIndices[4],
+					                  GL20.GL_UNSIGNED_SHORT,
+					                  offset);
 				}
 			}
 
@@ -263,56 +237,31 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
 			els[i] = null;
 		}
 
-		GL.glDepthMask(false);
-		GL.glDisable(GL20.GL_CULL_FACE);
+		if (!mTranslucent)
+			GL.glDepthMask(false);
+
+		if (v.pos.zoomLevel < 18)
+			GL.glDisable(GL20.GL_CULL_FACE);
+
 		GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, 0);
 	}
 
-	private static void setMatrix(GLViewport v, ExtrusionLayers l, int delta) {
+	private static void setMatrix(GLViewport v, ExtrusionLayers l, boolean offset) {
+
 		int z = l.zoomLevel;
 		double curScale = Tile.SIZE * v.pos.scale;
 		float scale = (float) (v.pos.scale / (1 << z));
 
 		float x = (float) ((l.x - v.pos.x) * curScale);
 		float y = (float) ((l.y - v.pos.y) * curScale);
+
 		v.mvp.setTransScale(x, y, scale / MapRenderer.COORD_SCALE);
-
-		// scale height ???
 		v.mvp.setValue(10, scale / 10);
-
 		v.mvp.multiplyLhs(v.viewproj);
 
-		v.mvp.addDepthOffset(delta);
+		if (offset) {
+			int delta = (int) (l.x * (1 << z)) % 4 + (int) (l.y * (1 << z)) % 4 * 4;
+			v.mvp.addDepthOffset(delta);
+		}
 	}
-
-	private static float A = 0.88f;
-	private static float R = 0xe9;
-	private static float G = 0xe8;
-	private static float B = 0xe6;
-	private static float O = 20;
-	private static float S = 4;
-	private static float L = 0;
-
-	private static float[] DEBUG_COLOR = {
-	        // roof color
-	        A * ((R + L) / 255),
-	        A * ((G + L) / 255),
-	        A * ((B + L) / 255),
-	        0.8f,
-	        // sligthly differ adjacent side
-	        // faces to improve contrast
-	        A * ((R - S) / 255 + 0.01f),
-	        A * ((G - S) / 255 + 0.01f),
-	        A * ((B - S) / 255),
-	        A,
-	        A * ((R - S) / 255),
-	        A * ((G - S) / 255),
-	        A * ((B - S) / 255),
-	        A,
-	        // roof outline
-	        (R - O) / 255,
-	        (G - O) / 255,
-	        (B - O) / 255,
-	        0.9f,
-	};
 }