All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.earth.worldwind.layer.atmosphere.DrawableGroundAtmosphere.kt Maven / Gradle / Ivy

Go to download

The WorldWind Kotlin SDK (WWK) includes the library, examples and tutorials for building multiplatform 3D virtual globe applications for Android, Web and Java.

There is a newer version: 1.5.23
Show newest version
package earth.worldwind.layer.atmosphere

import earth.worldwind.draw.DrawContext
import earth.worldwind.draw.Drawable
import earth.worldwind.geom.Matrix3
import earth.worldwind.geom.Matrix4
import earth.worldwind.geom.Sector
import earth.worldwind.geom.Vec3
import earth.worldwind.layer.atmosphere.AbstractAtmosphereProgram.FragMode.*
import earth.worldwind.render.Texture
import earth.worldwind.util.Pool
import earth.worldwind.util.kgl.*
import kotlin.jvm.JvmStatic

open class DrawableGroundAtmosphere : Drawable {
    val lightDirection = Vec3()
    var globeRadius = 0.0
    var atmosphereAltitude = 0.0
    var program: GroundProgram? = null
    var nightTexture: Texture? = null
    protected val mvpMatrix = Matrix4()
    protected val texCoordMatrix = Matrix3()
    protected val fullSphereSector = Sector().setFullSphere()
    private var pool: Pool? = null

    companion object {
        @JvmStatic
        fun obtain(pool: Pool): DrawableGroundAtmosphere {
            val instance = pool.acquire() ?: DrawableGroundAtmosphere()  // get an instance from the pool
            instance.pool = pool
            return instance
        }
    }

    override fun recycle() {
        program = null
        nightTexture = null
        pool?.release(this)
        pool = null
    }

    override fun draw(dc: DrawContext) {
        val program = program ?: return  // program unspecified
        if (!program.useProgram(dc)) return  // program failed to build

        // Use the render context's globe radius and atmosphere altitude.
        program.loadAtmosphereParams(globeRadius, atmosphereAltitude)

        // Use the draw context's eye point.
        program.loadEyePoint(dc.eyePoint)

        // Use this layer's light direction.
        program.loadLightDirection(lightDirection)

        // Set up to use the shared tile tex coord attributes.
        dc.gl.enableVertexAttribArray(1)

        // Attempt to bind the night side texture to multi-texture unit 0.
        dc.activeTextureUnit(GL_TEXTURE0)
        val nightTexture = nightTexture
        val textureBound = nightTexture?.bindTexture(dc) == true
        for (idx in 0 until dc.drawableTerrainCount) {
            // Get the drawable terrain associated with the draw context.
            val terrain = dc.getDrawableTerrain(idx)

            // Use the terrain's vertex point attribute and vertex tex coord attribute.
            if (!terrain.useVertexPointAttrib(dc, 0 /*vertexPoint*/) ||
                !terrain.useVertexTexCoordAttrib(dc, 1 /*vertexTexCoord*/)
            ) continue  // vertex buffer failed to bind

            // Use the vertex origin for the terrain.
            val terrainOrigin = terrain.vertexOrigin
            program.loadVertexOrigin(terrainOrigin)

            // Use the draw context's modelview projection matrix, transformed to terrain local coordinates.
            mvpMatrix.copy(dc.modelviewProjection)
            mvpMatrix.multiplyByTranslation(terrainOrigin.x, terrainOrigin.y, terrainOrigin.z)
            program.loadModelviewProjection(mvpMatrix)

            // Use a tex coord matrix that registers the night texture correctly on each terrain.
            if (textureBound && nightTexture != null) {
                texCoordMatrix.copy(nightTexture.coordTransform)
                texCoordMatrix.multiplyByTileTransform(terrain.sector, fullSphereSector)
                program.loadTexCoordMatrix(texCoordMatrix)
            }

            // Draw the terrain as triangles, multiplying the current fragment color by the program's secondary color.
            program.loadFragMode(SECONDARY)
            dc.gl.blendFunc(GL_DST_COLOR, GL_ZERO)
            terrain.drawTriangles(dc)

            // Draw the terrain as triangles, adding the current fragment color to the program's primary color.
            program.loadFragMode(if (textureBound) PRIMARY_TEX_BLEND else PRIMARY)
            dc.gl.blendFunc(GL_ONE, GL_ONE)
            terrain.drawTriangles(dc)
        }

        // Restore the default WorldWind OpenGL state.
        dc.gl.blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
        dc.gl.disableVertexAttribArray(1)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy