问题
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