Skip to content

Commit 2de677e

Browse files
committed
Add globe shape
1 parent 191c529 commit 2de677e

File tree

1 file changed

+185
-0
lines changed
  • android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/shapes

1 file changed

+185
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
package net.mullvad.mullvadvpn.lib.map.internal.shapes
2+
3+
import android.content.res.Resources
4+
import android.opengl.GLES20
5+
import android.opengl.Matrix
6+
import java.nio.ByteBuffer
7+
import net.mullvad.mullvadvpn.lib.map.R
8+
import net.mullvad.mullvadvpn.lib.map.data.GlobeColors
9+
import net.mullvad.mullvadvpn.lib.map.internal.IndexBufferWithLength
10+
import net.mullvad.mullvadvpn.lib.map.internal.VERTEX_COMPONENT_SIZE
11+
import net.mullvad.mullvadvpn.lib.map.internal.initArrayBuffer
12+
import net.mullvad.mullvadvpn.lib.map.internal.initIndexBuffer
13+
import net.mullvad.mullvadvpn.lib.map.internal.initShaderProgram
14+
15+
internal class Globe(resources: Resources) {
16+
17+
private val shaderProgram: Int
18+
19+
private val attribLocations: AttribLocations
20+
private val uniformLocation: UniformLocation
21+
22+
private data class AttribLocations(val vertexPosition: Int)
23+
24+
private data class UniformLocation(
25+
val color: Int,
26+
val projectionMatrix: Int,
27+
val modelViewMatrix: Int
28+
)
29+
30+
private val landIndices: IndexBufferWithLength
31+
private val landContour: IndexBufferWithLength
32+
private val landVertexBuffer: Int
33+
34+
private val oceanIndices: IndexBufferWithLength
35+
private val oceanVertexBuffer: Int
36+
37+
init {
38+
val landPosStream = resources.openRawResource(R.raw.land_positions)
39+
val landVertByteArray = landPosStream.use { it.readBytes() }
40+
val landVertByteBuffer = ByteBuffer.wrap(landVertByteArray)
41+
landVertexBuffer = initArrayBuffer(landVertByteBuffer)
42+
43+
val landTriangleIndicesStream = resources.openRawResource(R.raw.land_triangle_indices)
44+
val landTriangleIndicesByteArray = landTriangleIndicesStream.use { it.readBytes() }
45+
val landTriangleIndicesBuffer = ByteBuffer.wrap(landTriangleIndicesByteArray)
46+
landIndices = initIndexBuffer(landTriangleIndicesBuffer)
47+
48+
val landContourIndicesStream = resources.openRawResource(R.raw.land_contour_indices)
49+
val landContourIndicesByteArray = landContourIndicesStream.use { it.readBytes() }
50+
val landContourIndicesBuffer = ByteBuffer.wrap(landContourIndicesByteArray)
51+
landContour = initIndexBuffer(landContourIndicesBuffer)
52+
53+
val oceanPosStream = resources.openRawResource(R.raw.ocean_positions)
54+
val oceanVertByteArray = oceanPosStream.use { it.readBytes() }
55+
val oceanVertByteBuffer = ByteBuffer.wrap(oceanVertByteArray)
56+
oceanVertexBuffer = initArrayBuffer(oceanVertByteBuffer)
57+
58+
val oceanTriangleIndicesStream = resources.openRawResource(R.raw.ocean_indices)
59+
val oceanTriangleIndicesByteArray = oceanTriangleIndicesStream.use { it.readBytes() }
60+
val oceanTriangleIndicesBuffer = ByteBuffer.wrap(oceanTriangleIndicesByteArray)
61+
oceanIndices = initIndexBuffer(oceanTriangleIndicesBuffer)
62+
63+
// create empty OpenGL ES Program
64+
shaderProgram = initShaderProgram(vertexShaderCode, fragmentShaderCode)
65+
66+
attribLocations =
67+
AttribLocations(GLES20.glGetAttribLocation(shaderProgram, "aVertexPosition"))
68+
uniformLocation =
69+
UniformLocation(
70+
color = GLES20.glGetUniformLocation(shaderProgram, "uColor"),
71+
projectionMatrix = GLES20.glGetUniformLocation(shaderProgram, "uProjectionMatrix"),
72+
modelViewMatrix = GLES20.glGetUniformLocation(shaderProgram, "uModelViewMatrix")
73+
)
74+
}
75+
76+
fun draw(
77+
projectionMatrix: FloatArray,
78+
viewMatrix: FloatArray,
79+
colors: GlobeColors,
80+
contourWidth: Float = 3f
81+
) {
82+
val globeViewMatrix = viewMatrix.copyOf()
83+
84+
// Add program to OpenGL ES environment
85+
GLES20.glUseProgram(shaderProgram)
86+
87+
// Set thickness of contour lines
88+
GLES20.glLineWidth(contourWidth)
89+
drawBufferElements(
90+
projectionMatrix,
91+
globeViewMatrix,
92+
landVertexBuffer,
93+
landContour,
94+
colors.contourColorArray,
95+
GLES20.GL_LINES
96+
)
97+
98+
// Scale the globe to avoid z-fighting
99+
Matrix.scaleM(
100+
globeViewMatrix,
101+
0,
102+
LAND_OCEAN_SCALE_FACTOR,
103+
LAND_OCEAN_SCALE_FACTOR,
104+
LAND_OCEAN_SCALE_FACTOR
105+
)
106+
107+
// Draw land
108+
drawBufferElements(
109+
projectionMatrix,
110+
globeViewMatrix,
111+
landVertexBuffer,
112+
landIndices,
113+
colors.landColorArray,
114+
GLES20.GL_TRIANGLES,
115+
)
116+
117+
// Draw ocean
118+
drawBufferElements(
119+
projectionMatrix,
120+
globeViewMatrix,
121+
oceanVertexBuffer,
122+
oceanIndices,
123+
colors.oceanColorArray,
124+
GLES20.GL_TRIANGLES
125+
)
126+
}
127+
128+
private fun drawBufferElements(
129+
projectionMatrix: FloatArray,
130+
modelViewMatrix: FloatArray,
131+
positionBuffer: Int,
132+
indexBuffer: IndexBufferWithLength,
133+
color: FloatArray,
134+
mode: Int,
135+
) {
136+
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, positionBuffer)
137+
GLES20.glVertexAttribPointer(
138+
attribLocations.vertexPosition,
139+
VERTEX_COMPONENT_SIZE,
140+
GLES20.GL_FLOAT,
141+
false,
142+
0,
143+
0,
144+
)
145+
GLES20.glEnableVertexAttribArray(attribLocations.vertexPosition)
146+
147+
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.indexBuffer)
148+
GLES20.glUniform4fv(uniformLocation.color, 1, color, 0)
149+
GLES20.glUniformMatrix4fv(uniformLocation.projectionMatrix, 1, false, projectionMatrix, 0)
150+
GLES20.glUniformMatrix4fv(uniformLocation.modelViewMatrix, 1, false, modelViewMatrix, 0)
151+
GLES20.glDrawElements(mode, indexBuffer.length, GLES20.GL_UNSIGNED_INT, 0)
152+
GLES20.glDisableVertexAttribArray(attribLocations.vertexPosition)
153+
}
154+
155+
companion object {
156+
private const val LAND_OCEAN_SCALE_FACTOR = 0.9999f
157+
158+
// Vertex, and fragment shader code is taken from Mullvad Desktop 3dmap.ts
159+
private val vertexShaderCode =
160+
"""
161+
attribute vec3 aVertexPosition;
162+
163+
uniform vec4 uColor;
164+
uniform mat4 uModelViewMatrix;
165+
uniform mat4 uProjectionMatrix;
166+
167+
varying lowp vec4 vColor;
168+
169+
void main(void) {
170+
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0);
171+
vColor = uColor;
172+
}
173+
"""
174+
.trimIndent()
175+
private val fragmentShaderCode =
176+
"""
177+
varying lowp vec4 vColor;
178+
179+
void main(void) {
180+
gl_FragColor = vColor;
181+
}
182+
"""
183+
.trimIndent()
184+
}
185+
}

0 commit comments

Comments
 (0)