Skip to content

Commit

Permalink
Support for non-rect shapes in textures (#8)
Browse files Browse the repository at this point in the history
* Add VideoActivity

* Add ExoPlayer with two shapes

* Ensure all drawables have the correct vertexArray limit

* Support irregular shapes for textures

* Release v0.3.0
  • Loading branch information
natario1 authored Sep 9, 2019
1 parent 764de44 commit b9283ff
Show file tree
Hide file tree
Showing 18 changed files with 337 additions and 47 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
### v0.3.0

- Support for non-rect shapes in textures ([#8][8])

https://github.com/natario1/Egloo/compare/v0.2.4...v0.3.0

### v0.2.4

- Added GlRoundRect ([#7][7])
Expand All @@ -24,3 +30,4 @@ https://github.com/natario1/Egloo/compare/v0.2.1...v0.2.2
[3]: https://github.com/natario1/Egloo/pull/3
[5]: https://github.com/natario1/Egloo/pull/5
[7]: https://github.com/natario1/Egloo/pull/7
[8]: https://github.com/natario1/Egloo/pull/8
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ with respect to a typical object-oriented context. Egloo tries to take some of t
by creating a **thin**, flexible layer of abstraction around EGL and GLES calls.

```groovy
implementation 'com.otaliastudios.opengl:egloo:0.2.4'
implementation 'com.otaliastudios.opengl:egloo:0.3.0'
```

&#10240; <!-- Hack to add whitespace -->
Expand Down
9 changes: 8 additions & 1 deletion demo/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,17 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

// required by ExoPlayer
compileOptions {
targetCompatibility JavaVersion.VERSION_1_8
}
}

dependencies {
implementation project(':library')
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.0.2'
implementation 'androidx.core:core-ktx:1.1.0'
implementation 'com.google.android.exoplayer:exoplayer-core:2.10.4'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.10.4'
}
6 changes: 4 additions & 2 deletions demo/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.otaliastudios.opengl.demo">

<uses-permission android:name="android.permission.INTERNET"/>

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
Expand All @@ -11,13 +13,13 @@
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".MainActivity">
<activity android:name=".ShapesActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".VideoActivity"/>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package com.otaliastudios.opengl.demo

import android.animation.ValueAnimator
import android.content.Intent
import android.graphics.Color
import android.graphics.PixelFormat
import android.graphics.RectF
import android.opengl.GLES20
import android.opengl.GLSurfaceView
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.SurfaceHolder
import android.view.SurfaceView
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
Expand All @@ -19,7 +22,7 @@ import com.otaliastudios.opengl.scene.GlScene
import com.otaliastudios.opengl.surface.EglWindowSurface
import kotlin.math.roundToInt

class MainActivity : AppCompatActivity() {
class ShapesActivity : AppCompatActivity() {

private lateinit var surfaceView: SurfaceView
private var eglCore: EglCore? = null
Expand All @@ -43,17 +46,14 @@ class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setContentView(R.layout.activity_shapes)

// Using a handler just because the holder callback runs inside a try-catch.
// We prefer to crash if there's something wrong.
val handler = Handler()
surfaceView = findViewById(R.id.surface_view)
surfaceView.setZOrderOnTop(true)
surfaceView.holder.setFormat(PixelFormat.RGBA_8888)
surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder?) {
handler.post { onSurfaceCreated() }
onSurfaceCreated()
}

override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
Expand All @@ -62,12 +62,13 @@ class MainActivity : AppCompatActivity() {
}

override fun surfaceDestroyed(holder: SurfaceHolder?) {
handler.post { onSurfaceDestroyed() }
onSurfaceDestroyed()
}
})
}

private fun onSurfaceCreated() {
Log.e("SHAPES", "CREATED.")
eglCore = EglCore()
eglSurface = EglWindowSurface(eglCore!!, surfaceView.holder.surface!!)
eglSurface!!.makeCurrent()
Expand All @@ -76,6 +77,7 @@ class MainActivity : AppCompatActivity() {
}

private fun onSurfaceDestroyed() {
Log.e("SHAPES", "DESTROYING.")
drawAnimator.cancel()
flatProgram?.release()
eglSurface?.release()
Expand All @@ -86,6 +88,7 @@ class MainActivity : AppCompatActivity() {
}

private fun draw() {
Log.w("SHAPES", "drawing.")
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)

// Animate the background rect
Expand Down Expand Up @@ -126,4 +129,16 @@ class MainActivity : AppCompatActivity() {
private fun floatValue(start: Float, end: Float): Float {
return start + drawAnimator.animatedFraction * (end - start)
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.activity_shapes, menu)
return true
}

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
startActivity(Intent(this, VideoActivity::class.java))
onSurfaceDestroyed()
finish()
return true
}
}
186 changes: 186 additions & 0 deletions demo/src/main/java/com/otaliastudios/opengl/demo/VideoActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package com.otaliastudios.opengl.demo

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color
import android.graphics.PixelFormat
import android.graphics.RectF
import android.graphics.SurfaceTexture
import android.net.Uri
import android.opengl.GLES20
import android.opengl.GLSurfaceView
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.view.*
import android.widget.Toast
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import com.google.android.exoplayer2.ExoPlayerFactory
import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.android.exoplayer2.source.ExtractorMediaSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.util.Util
import com.google.android.exoplayer2.video.VideoListener
import com.otaliastudios.opengl.core.EglConfigChooser
import com.otaliastudios.opengl.core.EglContextFactory
import com.otaliastudios.opengl.core.EglCore
import com.otaliastudios.opengl.draw.*
import com.otaliastudios.opengl.program.GlFlatProgram
import com.otaliastudios.opengl.program.GlTextureProgram
import com.otaliastudios.opengl.scene.GlScene
import com.otaliastudios.opengl.surface.EglWindowSurface
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10
import kotlin.math.roundToInt

class VideoActivity : AppCompatActivity(), GLSurfaceView.Renderer {

private lateinit var glSurfaceView: GLSurfaceView
private var glTextureProgram: GlTextureProgram? = null
private var surfaceTexture: SurfaceTexture? = null
private var surface: Surface? = null

private val scene = GlScene()
private val glRect = GlRect()
private val glRoundRect = GlRoundRect().apply { setCornersPx(200) }
private var glDrawable: GlDrawable = glRect
private lateinit var player: SimpleExoPlayer

private var videoWidth = -1
private var videoHeight = -1
private var surfaceWidth = -1
private var surfaceHeight = -1

@SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_video)

// Set up the player
player = ExoPlayerFactory.newSimpleInstance(this)
val dataSourceFactory = DefaultDataSourceFactory(this,
Util.getUserAgent(this, "Egloo"))
val videoSource = ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"))
player.prepare(videoSource)
player.playWhenReady = true

// Set up the gl surface view
glSurfaceView = findViewById(R.id.gl_surface_view)
glSurfaceView.setZOrderOnTop(true)
glSurfaceView.holder.setFormat(PixelFormat.RGBA_8888)
glSurfaceView.setEGLContextFactory(EglContextFactory.GLES2)
glSurfaceView.setEGLConfigChooser(EglConfigChooser.GLES2)
glSurfaceView.setRenderer(this)
glSurfaceView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
glSurfaceView.holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder?) {}
override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {}
override fun surfaceDestroyed(holder: SurfaceHolder?) {
onSurfaceDestroyed()
}
})

// Address the aspect ratio
player.addVideoListener(object: VideoListener {
override fun onVideoSizeChanged(width: Int, height: Int,
unappliedRotationDegrees: Int,
pixelWidthHeightRatio: Float) {
videoWidth = width
videoHeight = height
onVideoOrSurfaceSizeChanged()
}
})

// On touch, change the current drawable.
glSurfaceView.setOnTouchListener { v, event ->
glDrawable = if (glDrawable == glRect) glRoundRect else glRect
false
}
Toast.makeText(this, "Touch the screen to change shape.", Toast.LENGTH_LONG).show()
}

override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
// Configure GL
glTextureProgram = GlTextureProgram()

// Configure the player
surfaceTexture = SurfaceTexture(glTextureProgram!!.textureId)
surfaceTexture!!.setOnFrameAvailableListener {
glSurfaceView.requestRender()
}
surface = Surface(surfaceTexture!!)
player.setVideoSurface(surface)
}

override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
GLES20.glViewport(0, 0, width, height)
scene.setViewportSize(width, height)
surfaceWidth = width
surfaceHeight = height
onVideoOrSurfaceSizeChanged()
}

override fun onDrawFrame(gl: GL10) {
val texture = surfaceTexture ?: return
val program = glTextureProgram ?: return
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
texture.updateTexImage()
texture.getTransformMatrix(program.textureTransform)
scene.draw(program, glDrawable)
}

private fun onSurfaceDestroyed() {
player.setVideoSurface(null)
glTextureProgram?.release()
glTextureProgram = null
surfaceTexture?.release()
surfaceTexture = null
surface?.release()
surface = null
}

private fun onVideoOrSurfaceSizeChanged() {
if (videoWidth == -1 || videoHeight == -1) return
if (surfaceWidth == -1 || surfaceHeight == -1) return
val videoRatio = videoWidth.toFloat() / videoHeight
val surfaceRatio = surfaceWidth.toFloat() / surfaceHeight
val rect: RectF
if (videoRatio > surfaceRatio) {
// Video is wider. We should collapse height.
val surfaceRealHeight = surfaceWidth / videoRatio
val surfaceRealHeightEgloo = surfaceRealHeight / surfaceHeight * 2
rect = RectF(-1F, surfaceRealHeightEgloo / 2F,
1F, -surfaceRealHeightEgloo / 2F)
} else if (videoRatio < surfaceRatio) {
// Video is taller. We should collapse width
val surfaceRealWidth = surfaceHeight * videoRatio
val surfaceRealWidthEgloo = surfaceRealWidth / surfaceWidth * 2
rect = RectF(-surfaceRealWidthEgloo / 2F, 1F,
surfaceRealWidthEgloo / 2F, -1F)
} else {
rect = RectF(-1F, 1F, 1F, -1F)
}
glRect.setVertexArray(rect)
glRoundRect.setRect(rect)
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.activity_video, menu)
return true
}

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
startActivity(Intent(this, ShapesActivity::class.java))
onSurfaceDestroyed()
finish()
return true
}

override fun onDestroy() {
super.onDestroy()
player.release()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#444444"
tools:context=".MainActivity">
tools:context=".ShapesActivity">

<SurfaceView
android:id="@+id/surface_view"
Expand Down
15 changes: 15 additions & 0 deletions demo/src/main/res/layout/activity_video.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#444444"
tools:context=".VideoActivity">

<android.opengl.GLSurfaceView
android:id="@+id/gl_surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</FrameLayout>
7 changes: 7 additions & 0 deletions demo/src/main/res/menu/activity_shapes.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/video"
android:title="Texture" />
</menu>
7 changes: 7 additions & 0 deletions demo/src/main/res/menu/activity_video.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/shapes"
android:title="Shapes" />
</menu>
Loading

0 comments on commit b9283ff

Please sign in to comment.