summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorDavid Göransson <david.goransson90@gmail.com>2024-02-13 16:27:31 +0100
committerDavid Göransson <david.goransson90@gmail.com>2024-02-15 13:58:34 +0100
commitf84b22e8bced263b71e0c3abad399730c7e58ac3 (patch)
treef1d887f337fe78c7df2cbd7cd9f5396768639196 /android
parentc069c0f996ab92201a246e61c300a91c67b66331 (diff)
downloadmullvadvpn-f84b22e8bced263b71e0c3abad399730c7e58ac3.tar.xz
mullvadvpn-f84b22e8bced263b71e0c3abad399730c7e58ac3.zip
Add globe shape
Diffstat (limited to 'android')
-rw-r--r--android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/shapes/Globe.kt185
1 files changed, 185 insertions, 0 deletions
diff --git a/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/shapes/Globe.kt b/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/shapes/Globe.kt
new file mode 100644
index 0000000000..379ac407cc
--- /dev/null
+++ b/android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/shapes/Globe.kt
@@ -0,0 +1,185 @@
+package net.mullvad.mullvadvpn.lib.map.internal.shapes
+
+import android.content.res.Resources
+import android.opengl.GLES20
+import android.opengl.Matrix
+import java.nio.ByteBuffer
+import net.mullvad.mullvadvpn.lib.map.R
+import net.mullvad.mullvadvpn.lib.map.data.GlobeColors
+import net.mullvad.mullvadvpn.lib.map.internal.IndexBufferWithLength
+import net.mullvad.mullvadvpn.lib.map.internal.VERTEX_COMPONENT_SIZE
+import net.mullvad.mullvadvpn.lib.map.internal.initArrayBuffer
+import net.mullvad.mullvadvpn.lib.map.internal.initIndexBuffer
+import net.mullvad.mullvadvpn.lib.map.internal.initShaderProgram
+
+internal class Globe(resources: Resources) {
+
+ private val shaderProgram: Int
+
+ private val attribLocations: AttribLocations
+ private val uniformLocation: UniformLocation
+
+ private val landIndices: IndexBufferWithLength
+ private val landContour: IndexBufferWithLength
+ private val landVertexBuffer: Int
+
+ private val oceanIndices: IndexBufferWithLength
+ private val oceanVertexBuffer: Int
+
+ init {
+ val landPosStream = resources.openRawResource(R.raw.land_positions)
+ val landVertByteArray = landPosStream.use { it.readBytes() }
+ val landVertByteBuffer = ByteBuffer.wrap(landVertByteArray)
+ landVertexBuffer = initArrayBuffer(landVertByteBuffer)
+
+ val landTriangleIndicesStream = resources.openRawResource(R.raw.land_triangle_indices)
+ val landTriangleIndicesByteArray = landTriangleIndicesStream.use { it.readBytes() }
+ val landTriangleIndicesBuffer = ByteBuffer.wrap(landTriangleIndicesByteArray)
+ landIndices = initIndexBuffer(landTriangleIndicesBuffer)
+
+ val landContourIndicesStream = resources.openRawResource(R.raw.land_contour_indices)
+ val landContourIndicesByteArray = landContourIndicesStream.use { it.readBytes() }
+ val landContourIndicesBuffer = ByteBuffer.wrap(landContourIndicesByteArray)
+ landContour = initIndexBuffer(landContourIndicesBuffer)
+
+ val oceanPosStream = resources.openRawResource(R.raw.ocean_positions)
+ val oceanVertByteArray = oceanPosStream.use { it.readBytes() }
+ val oceanVertByteBuffer = ByteBuffer.wrap(oceanVertByteArray)
+ oceanVertexBuffer = initArrayBuffer(oceanVertByteBuffer)
+
+ val oceanTriangleIndicesStream = resources.openRawResource(R.raw.ocean_indices)
+ val oceanTriangleIndicesByteArray = oceanTriangleIndicesStream.use { it.readBytes() }
+ val oceanTriangleIndicesBuffer = ByteBuffer.wrap(oceanTriangleIndicesByteArray)
+ oceanIndices = initIndexBuffer(oceanTriangleIndicesBuffer)
+
+ // create empty OpenGL ES Program
+ shaderProgram = initShaderProgram(vertexShaderCode, fragmentShaderCode)
+
+ attribLocations =
+ AttribLocations(GLES20.glGetAttribLocation(shaderProgram, "aVertexPosition"))
+ uniformLocation =
+ UniformLocation(
+ color = GLES20.glGetUniformLocation(shaderProgram, "uColor"),
+ projectionMatrix = GLES20.glGetUniformLocation(shaderProgram, "uProjectionMatrix"),
+ modelViewMatrix = GLES20.glGetUniformLocation(shaderProgram, "uModelViewMatrix")
+ )
+ }
+
+ fun draw(
+ projectionMatrix: FloatArray,
+ viewMatrix: FloatArray,
+ colors: GlobeColors,
+ contourWidth: Float = 3f
+ ) {
+ val globeViewMatrix = viewMatrix.copyOf()
+
+ // Add program to OpenGL ES environment
+ GLES20.glUseProgram(shaderProgram)
+
+ // Set thickness of contour lines
+ GLES20.glLineWidth(contourWidth)
+ drawBufferElements(
+ projectionMatrix,
+ globeViewMatrix,
+ landVertexBuffer,
+ landContour,
+ colors.contourColorArray,
+ GLES20.GL_LINES
+ )
+
+ // Scale the globe to avoid z-fighting
+ Matrix.scaleM(
+ globeViewMatrix,
+ 0,
+ LAND_OCEAN_SCALE_FACTOR,
+ LAND_OCEAN_SCALE_FACTOR,
+ LAND_OCEAN_SCALE_FACTOR
+ )
+
+ // Draw land
+ drawBufferElements(
+ projectionMatrix,
+ globeViewMatrix,
+ landVertexBuffer,
+ landIndices,
+ colors.landColorArray,
+ GLES20.GL_TRIANGLES,
+ )
+
+ // Draw ocean
+ drawBufferElements(
+ projectionMatrix,
+ globeViewMatrix,
+ oceanVertexBuffer,
+ oceanIndices,
+ colors.oceanColorArray,
+ GLES20.GL_TRIANGLES
+ )
+ }
+
+ private fun drawBufferElements(
+ projectionMatrix: FloatArray,
+ modelViewMatrix: FloatArray,
+ positionBuffer: Int,
+ indexBuffer: IndexBufferWithLength,
+ color: FloatArray,
+ mode: Int,
+ ) {
+ GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, positionBuffer)
+ GLES20.glVertexAttribPointer(
+ attribLocations.vertexPosition,
+ VERTEX_COMPONENT_SIZE,
+ GLES20.GL_FLOAT,
+ false,
+ 0,
+ 0,
+ )
+ GLES20.glEnableVertexAttribArray(attribLocations.vertexPosition)
+
+ GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.indexBuffer)
+ GLES20.glUniform4fv(uniformLocation.color, 1, color, 0)
+ GLES20.glUniformMatrix4fv(uniformLocation.projectionMatrix, 1, false, projectionMatrix, 0)
+ GLES20.glUniformMatrix4fv(uniformLocation.modelViewMatrix, 1, false, modelViewMatrix, 0)
+ GLES20.glDrawElements(mode, indexBuffer.length, GLES20.GL_UNSIGNED_INT, 0)
+ GLES20.glDisableVertexAttribArray(attribLocations.vertexPosition)
+ }
+
+ private data class AttribLocations(val vertexPosition: Int)
+
+ private data class UniformLocation(
+ val color: Int,
+ val projectionMatrix: Int,
+ val modelViewMatrix: Int
+ )
+
+ companion object {
+ private const val LAND_OCEAN_SCALE_FACTOR = 0.9999f
+
+ // Vertex, and fragment shader code is taken from Mullvad Desktop 3dmap.ts
+ private val vertexShaderCode =
+ """
+ attribute vec3 aVertexPosition;
+
+ uniform vec4 uColor;
+ uniform mat4 uModelViewMatrix;
+ uniform mat4 uProjectionMatrix;
+
+ varying lowp vec4 vColor;
+
+ void main(void) {
+ gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0);
+ vColor = uColor;
+ }
+ """
+ .trimIndent()
+ private val fragmentShaderCode =
+ """
+ varying lowp vec4 vColor;
+
+ void main(void) {
+ gl_FragColor = vColor;
+ }
+ """
+ .trimIndent()
+ }
+}