Реакция на события прикосновений

Создание объектов движущихся по заданной программе, такой как вращение треугольника полезно для получения некоторого внимания, но что, если вы хотите иметь возможность взаимодействия пользователей с OpenGL ES графикой? Для обеспечения сенсорной интерактивности вашего OpenGL ES приложения необходимо в вашей реализации GLSurfaceView переопределить onTouchEvent() для обработки сенсорных событий.

Этот урок покажет вам, как прослушивать события прикосновений, чтобы пользователи могли повернуть объект OpenGL ES.

Настройка обработчика сенсорных событий

Чтобы ваше OpenGL ES приложение реагировало на сенсорные события, необходимо реализовать onTouchEvent() метод в GLSurfaceView классе. Пример реализация показывает, как прослушивать MotionEvent.ACTION_MOVE события и перенести их на угол вращения фигуры.

@Override
public boolean onTouchEvent(MotionEvent e) {
    // MotionEvent reports input details from the touch screen
    // and other input controls. In this case, you are only
    // interested in events where the touch position changed.

    float x = e.getX();
    float y = e.getY();

    switch (e.getAction()) {
        case MotionEvent.ACTION_MOVE:

            float dx = x - mPreviousX;
            float dy = y - mPreviousY;

            // reverse direction of rotation above the mid-line
            if (y > getHeight() / 2) {
              dx = dx * -1 ;
            }

            // reverse direction of rotation to left of the mid-line
            if (x < getWidth() / 2) {
              dy = dy * -1 ;
            }

            mRenderer.setAngle(
                    mRenderer.getAngle() +
                    ((dx + dy) * TOUCH_SCALE_FACTOR);  // = 180.0f / 320
            requestRender();
    }

    mPreviousX = x;
    mPreviousY = y;
    return true;
}

Обратите внимание, что после расчета угла поворота, этот метод вызывает requestRender() , чтобы проинформировать визуализатор, что пришло время перерисовать кадр. Этот подход является наиболее эффективным для данного примера, потому что не имеет смысла менять кадр, если нет изменения вращения. Тем не менее, это так же не окажет никакого влияния на эффективность, если вы потребуете от визуализатора перерисовать только при изменении данных с помощью setRenderMode() метода, поэтому убедитесь, что следующая линия раскомментирована в визуализаторе:

public MyGLSurfaceView(Context context) {
    ...
    // Render the view only when there is a change in the drawing data
    setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}

Сделать видимым угол поворота

В примере кода выше требуется, чтобы вы сделали видимым угол поворота из визуализатора, добавив открытый член класса. Поскольку код визуализатора работает в отдельном потоке отдельно от основного потока пользовательского интерфейса вашего приложения, вы должны объявить эту открытую переменную как volatile. Вот код, который это делает:

public class MyGLRenderer implements GLSurfaceView.Renderer {
    ...
    public volatile float mAngle;

Применение вращения

Чтобы применить вращение порожденное сенсорным вводом, закомментируйте код, который генерирует угол и добавьте mAngle, который содержит угол генерируемый сенсорным вводом:

public void onDrawFrame(GL10 gl) {
    ...
    float[] scratch = new float[16];

    // Create a rotation for the triangle
    // long time = SystemClock.uptimeMillis() % 4000L;
    // float angle = 0.090f * ((int) time);
    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);

    // Combine the rotation matrix with the projection and camera view
    // Note that the mMVPMatrix factor *must be first* in order
    // for the matrix multiplication product to be correct.
    Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);

    // Draw triangle
    mTriangle.draw(scratch);
}

После завершения действия описанных выше, запустите программу и проведите пальцем по экрану, чтобы повернуть треугольник:

Рисунок 1. Треугольник поворачиваться с помощью сенсорного ввода (круг показывает место прикосновения).