diff options
| author | David Göransson <david.goransson90@gmail.com> | 2024-02-13 16:27:31 +0100 |
|---|---|---|
| committer | David Göransson <david.goransson90@gmail.com> | 2024-02-15 13:58:34 +0100 |
| commit | f84b22e8bced263b71e0c3abad399730c7e58ac3 (patch) | |
| tree | f1d887f337fe78c7df2cbd7cd9f5396768639196 /android/lib/map | |
| parent | c069c0f996ab92201a246e61c300a91c67b66331 (diff) | |
| download | mullvadvpn-f84b22e8bced263b71e0c3abad399730c7e58ac3.tar.xz mullvadvpn-f84b22e8bced263b71e0c3abad399730c7e58ac3.zip | |
Add globe shape
Diffstat (limited to 'android/lib/map')
| -rw-r--r-- | android/lib/map/src/main/kotlin/net/mullvad/mullvadvpn/lib/map/internal/shapes/Globe.kt | 185 |
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() + } +} |
