OpenGL ES how to apply transformations from android.graphics.Matrix

吃可爱长大的小学妹 提交于 2020-05-28 04:53:47

问题


I have a 3x3 android.graphics.Matrix, and i want to apply all transformation to a 4x4 OpenGL Matrix for 2D transformations only. So far I have manage to apply rotation and scaling I am using the example from the android team HERE to render a triangle. I used this class for generating the android.graphics.Matrix, from finger gestures made by the user for scale, move and translate transformations.

After that I attach the MatrixGestureDetector on the onTouchEvent from the View. In the MyGLSurfaceView class:

class MyGLSurfaceView : GLSurfaceView {

    ...
    private val matrixGestureDetector = MatrixGestureDetector()

    override fun onTouchEvent(e: MotionEvent): Boolean {

        matrixGestureDetector.onTouchEvent(e)
        requestRender()
        return true
    } 
}

Then I used it to convert the android.graphics.Matrix to a OpenGL Matrix in the onDrawFrame method in MyGLRenderer class

    ...
    lateinit var matrixGestureDetector: MatrixGestureDetector

    override fun onDrawFrame(unused: GL10) {
            ...
             // get graphics matrix values
             val m = FloatArray(9)
             matrixGestureDetector.matrix.getValues(m)

             // set rotation and scaling from graphics matrix to form new 4x4 OpenGL matrix
             val openGLMatrix = floatArrayOf(
                    m[0], m[3], 0f, 0f,
                    m[1], m[4], 0f, 0f,
                    0f, 0f, 1f, 0f,
                    0f, 0f, 0f, 1f
             )
             Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, openGLMatrix, 0)

             // draw shape, where scaling and rotation work
             mTriangle.draw(scratch)
    }

To apply the translation I have to add the m[2] and m[5] from the android.graphics.Matrix values and change the openGLMatrix to:

val openGLMatrix = floatArrayOf(
    m[0], m[3], 0f, 0f,
    m[1], m[4], 0f, 0f,
    0f, 0f, 1f, 0f,
    m[2], m[5], 0f, 1f
)

Now the problem is that the OpenGL viewbox size is formed by coordinates in range [-1,1], look at the image below:

But the translation X and Y values from the android.graphics.Matrix are not in that range, to do that I changed it to:

val scaleX: Float = m[android.graphics.Matrix.MSCALE_X]
val skewY: Float = m[android.graphics.Matrix.MSKEW_Y] 
val translateX = m[android.graphics.Matrix.MTRANS_X]
val translateY = m[android.graphics.Matrix.MTRANS_Y]
val ratio = width.toFloat() / height

val openGLMatrix = floatArrayOf(
    m[0], m[3], 0f, 0f,
    m[1], m[4], 0f, 0f,
    0f, 0f, 1f, 0f,
    -ratio * (translateX / width * 2), -(translateY / height * 2), 0f, 1f
)

Now translation work, but scale and rotation are not done on the pivot point(center point of rotation between the two fingers). How to apply all the transformation and is there a example code for 2D transformations for finger gestures that I can find anywhere?


回答1:


Well, I figure out that there is miscalculations in the conversion from Graphic coordinate system to a OpenGL coordinate system for the translation. Here is the code for getting the accurate translation in a OpenGL coordinate system, set as separate functions:

fun normalizeTranslateX(x: Float): Float {

    val translateX = if (x < width / 2f) {
        -1f + (x / (width / 2f))
    } else {
         (x - (width / 2f)) / (width / 2f)
    }

    return -translateX * OpenGLRenderer.NEAR * ratio
}

fun normalizeTranslateY(y: Float): Float {

    val translateY = if (y < height / 2f) {
        1f - (y / (height / 2f))
    } else {
        -(y - (height / 2f)) / (height / 2f)
    }

    return translateY * OpenGLRenderer.NEAR
}

I have also updated the whole finger gesture transformation class, for generating the OpenGL matrix, with the applied transformations from the finger gestures here is the class OpenGLFingerGestureTransformations.

To get the OpenGL matrix first create your own OpenGLMatrixGestureDetector object, using the same way as creating MatrixGestureDetector:

class MyGLSurfaceView : GLSurfaceView {

    ...
    private val matrixGestureDetector = OpenGLMatrixGestureDetector()

    override fun onTouchEvent(e: MotionEvent): Boolean {

        matrixGestureDetector.onTouchEvent(e)
        requestRender()
        return true
    } 
}

Then in the MyGLRenderer class just generate the matrix with the method transform()

...
lateinit var matrixGestureDetector: OpenGLMatrixGestureDetector
private val transformedMatrixOpenGL: FloatArray = FloatArray(16)

override fun onDrawFrame(unused: GL10) {

   ...

   // get OpenGL matrix with the applied transformations, from finger gestures
   matrixGestureDetector.transform(mMVPMatrix, transformedMatrixOpenGL)

   // draw shapes with apply transformations from finger gestures
   mTriangle.draw(transformedMatrixOpenGL)
}

I have uploaded the full source code HERE.
Here is the final result:



来源:https://stackoverflow.com/questions/61414054/opengl-es-how-to-apply-transformations-from-android-graphics-matrix

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!