OpenGL ES как применять преобразования из android .graphics.Matrix - PullRequest
0 голосов
/ 24 апреля 2020

У меня есть 3x3 android .graphics.Matrix , и я хочу применить все преобразования к матрице OpenGL 4x4 только для 2D-преобразований. До сих пор мне удавалось применить вращение и масштабирование. Я использовал пример из команды android ЗДЕСЬ для рендеринга треугольника. Я использовал этот класс для генерации android .graphics.Matrix из жестов пальцев, сделанных пользователем для масштаба , перемещения и перевода преобразований.

После этого я присоединяю MatrixGestureDetector к onTouchEvent из представления. В классе MyGLSurfaceView:

class MyGLSurfaceView : GLSurfaceView {

    ...
    private val matrixGestureDetector = MatrixGestureDetector()

    override fun onTouchEvent(e: MotionEvent): Boolean {

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

Затем я использовал его для преобразования android .graphics.Matrix в матрицу OpenGL в методе onDrawFrame в MyGLRenderer класс

    ...
    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 формируется из координат в диапазоне [-1,1], посмотрите на изображение ниже:
enter image description here

Но перевод значений X и Y из android .graphics.Matrix не находится в этом диапазоне, для этого я изменил это:

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
)

Теперь перевод работает, но масштабирование и поворот не выполняются в точке поворота (центральная точка вращения между двумя пальцами). Как применить все преобразования и есть ли пример кода для двумерных преобразований для жестов пальцев, который я могу найти где угодно?

1 Ответ

0 голосов
/ 06 мая 2020

Хорошо, я выяснил, что при преобразовании из системы координат Graphi c в систему координат 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
}

Я также обновил весь класс преобразования жестов пальца, для генерации матрицы OpenGL, с примененными преобразованиями от жестов пальца вот класс OpenGLFingerGestureTransformations .

Чтобы получить матрицу OpenGL, сначала создайте свой собственный OpenGLMatrixGestureDetector объект, используя тот же способ, что и MatrixGestureDetector:

class MyGLSurfaceView : GLSurfaceView {

    ...
    private val matrixGestureDetector = OpenGLMatrixGestureDetector()

    override fun onTouchEvent(e: MotionEvent): Boolean {

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

Затем в классе MyGLRenderer просто сгенерируйте матрицу с помощью метода 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)
}

Я загрузил полный исходный код ЗДЕСЬ .
Вот окончательный результат:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...