OpenGL ES 如何应用来自 android.graphics.Matrix 的转换
OpenGL ES how to apply transformations from android.graphics.Matrix
我有一个 3x3 android.graphics.Matrix,我想将所有变换应用到 4x4 OpenGL 矩阵,仅用于 2D 变换。到目前为止,我已经设法应用旋转和缩放我正在使用来自 android 团队 HERE to render a triangle. I used this class 的示例,用于根据用户为 所做的手指手势生成 android.graphics.Matrix scale、move 和 translate 转换。
之后,我将 MatrixGestureDetector 附加到视图的 onTouchEvent 上。在 MyGLSurfaceView class:
class MyGLSurfaceView : GLSurfaceView {
...
private val matrixGestureDetector = MatrixGestureDetector()
override fun onTouchEvent(e: MotionEvent): Boolean {
matrixGestureDetector.onTouchEvent(e)
requestRender()
return true
}
}
然后我在onDrawFrame方法中用它把android.graphics.Matrix转换成OpenGL Matrix
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)
}
要应用翻译,我必须从 添加 m[2] 和 m[5] android.graphics.Matrix 值并将 openGLMatrix 更改为:
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
)
现在的问题是 OpenGL viewbox 的大小是由 [-1,1] 范围内的坐标组成的,请看下图:
但是 android.graphics.Matrix 的翻译 X 和 Y 值不在该范围内,为此我将其更改为:
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
)
现在平移工作,但缩放和旋转没有在枢轴点(两个手指之间的旋转中心点)上完成。如何应用所有转换,是否有我可以在任何地方找到的手指手势 2D 转换的示例代码?
嗯,我发现从Graphic坐标系到OpenGL坐标系的平移计算有误。以下是在 OpenGL 坐标系中获取准确平移的代码,设置为单独的函数:
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
}
我还更新了整个手指手势变换 class,用于生成 OpenGL 矩阵,这里是 class OpenGLFingerGestureTransformations.
要获取 OpenGL 矩阵,首先创建您自己的 OpenGLMatrixGestureDetector 对象,使用与创建 MatrixGestureDetector 相同的方法:
class MyGLSurfaceView : GLSurfaceView {
...
private val matrixGestureDetector = OpenGLMatrixGestureDetector()
override fun onTouchEvent(e: MotionEvent): Boolean {
matrixGestureDetector.onTouchEvent(e)
requestRender()
return true
}
}
然后在 MyGLRenderer class 中使用 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)
}
我已经上传了完整的源代码HERE。
这是最终结果:
我有一个 3x3 android.graphics.Matrix,我想将所有变换应用到 4x4 OpenGL 矩阵,仅用于 2D 变换。到目前为止,我已经设法应用旋转和缩放我正在使用来自 android 团队 HERE to render a triangle. I used this class 的示例,用于根据用户为 所做的手指手势生成 android.graphics.Matrix scale、move 和 translate 转换。
之后,我将 MatrixGestureDetector 附加到视图的 onTouchEvent 上。在 MyGLSurfaceView class:
class MyGLSurfaceView : GLSurfaceView {
...
private val matrixGestureDetector = MatrixGestureDetector()
override fun onTouchEvent(e: MotionEvent): Boolean {
matrixGestureDetector.onTouchEvent(e)
requestRender()
return true
}
}
然后我在onDrawFrame方法中用它把android.graphics.Matrix转换成OpenGL Matrix 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)
}
要应用翻译,我必须从 添加 m[2] 和 m[5] android.graphics.Matrix 值并将 openGLMatrix 更改为:
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
)
现在的问题是 OpenGL viewbox 的大小是由 [-1,1] 范围内的坐标组成的,请看下图:
但是 android.graphics.Matrix 的翻译 X 和 Y 值不在该范围内,为此我将其更改为:
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
)
现在平移工作,但缩放和旋转没有在枢轴点(两个手指之间的旋转中心点)上完成。如何应用所有转换,是否有我可以在任何地方找到的手指手势 2D 转换的示例代码?
嗯,我发现从Graphic坐标系到OpenGL坐标系的平移计算有误。以下是在 OpenGL 坐标系中获取准确平移的代码,设置为单独的函数:
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
}
我还更新了整个手指手势变换 class,用于生成 OpenGL 矩阵,这里是 class OpenGLFingerGestureTransformations.
要获取 OpenGL 矩阵,首先创建您自己的 OpenGLMatrixGestureDetector 对象,使用与创建 MatrixGestureDetector 相同的方法:
class MyGLSurfaceView : GLSurfaceView {
...
private val matrixGestureDetector = OpenGLMatrixGestureDetector()
override fun onTouchEvent(e: MotionEvent): Boolean {
matrixGestureDetector.onTouchEvent(e)
requestRender()
return true
}
}
然后在 MyGLRenderer class 中使用 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)
}
我已经上传了完整的源代码HERE。
这是最终结果: