Auf Touch-Ereignisse reagieren

Das Bewegen von Objekten gemäß einem voreingestellten Programm wie dem rotierenden Dreieck ist nützlich für Aber was ist, wenn Nutzer mit Ihrer OpenGL ES-Grafik interagieren sollen? Um Ihre OpenGL ES-App interaktiv zu gestalten, müssen Sie die Implementierung GLSurfaceView zum Überschreiben von onTouchEvent(), um auf Touch-Ereignisse zu warten.

In dieser Lektion erfahren Sie, wie Sie auf Touch-Ereignisse warten, damit Nutzer ein OpenGL ES-Objekt drehen können.

Touch-Listener einrichten

Damit Ihre OpenGL ES-Anwendung auf Touch-Events reagieren kann, müssen Sie den onTouchEvent()-Methode in Ihrem Klasse GLSurfaceView. Das Implementierungsbeispiel unten zeigt, wie auf MotionEvent.ACTION_MOVE Ereignis und übersetzen Sie sie in einen Drehwinkel für eine Form.

Kotlin

private const val TOUCH_SCALE_FACTOR: Float = 180.0f / 320f
...
private var previousX: Float = 0f
private var previousY: Float = 0f

override fun onTouchEvent(e: MotionEvent): Boolean {
    // 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.

    val x: Float = e.x
    val y: Float = e.y

    when (e.action) {
        MotionEvent.ACTION_MOVE -> {

            var dx: Float = x - previousX
            var dy: Float = y - previousY

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

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

            renderer.angle += (dx + dy) * TOUCH_SCALE_FACTOR
            requestRender()
        }
    }

    previousX = x
    previousY = y
    return true
}

Java

private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
private float previousX;
private float previousY;

@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 - previousX;
            float dy = y - previousY;

            // 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 ;
            }

            renderer.setAngle(
                    renderer.getAngle() +
                    ((dx + dy) * TOUCH_SCALE_FACTOR));
            requestRender();
    }

    previousX = x;
    previousY = y;
    return true;
}

Beachten Sie, dass diese Methode nach der Berechnung des Rotationswinkels requestRender(), um dem dass es Zeit ist, den Frame zu rendern. Dieser Ansatz ist in diesem Beispiel am effizientesten. da der Frame erst dann neu gezeichnet werden muss, wenn sich die Drehung ändert. Allerdings hat keine Auswirkungen auf die Effizienz, es sei denn, Sie fordern vom Renderer nur dann eine erneute Zeichnung an, wenn die Datenänderungen mithilfe von setRenderMode() muss diese Zeile im Renderer ohne Kommentar versehen sein:

Kotlin

class MyGlSurfaceView(context: Context) : GLSurfaceView(context) {

    init {
        // Render the view only when there is a change in the drawing data
        renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
    }
}

Java

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

Drehwinkel sichtbar machen

Der Beispielcode oben erfordert, dass Sie den Rotationswinkel durch den Renderer sichtbar machen, indem Sie Öffentliches Mitglied hinzufügen Da der Renderer-Code in einem anderen Thread als der Hauptnutzer ausgeführt wird verwenden, müssen Sie diese öffentliche Variable als volatile deklarieren. Hier ist der Code, mit dem die Variable deklariert und das Getter- und Setter-Paar offengelegt wird:

Kotlin

class MyGLRenderer4 : GLSurfaceView.Renderer {

    @Volatile
    var angle: Float = 0f
}

Java

public class MyGLRenderer implements GLSurfaceView.Renderer {
    ...

    public volatile float mAngle;

    public float getAngle() {
        return mAngle;
    }

    public void setAngle(float angle) {
        mAngle = angle;
    }
}

Rotation anwenden

Um die durch Berührung erzeugte Drehung anzuwenden, kommentiere den Code aus, der einen Winkel und Fügen Sie eine Variable hinzu, die den durch Berührungseingabe generierten Winkel enthält:

Kotlin

override fun onDrawFrame(gl: GL10) {
    ...
    val scratch = FloatArray(16)

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

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

    // Draw triangle
    triangle.draw(scratch)
}

Java

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(rotationMatrix, 0, mAngle, 0, 0, -1.0f);

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

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

Wenn Sie die oben beschriebenen Schritte abgeschlossen haben, starten Sie das Programm und ziehen Sie Ihren Finger über das Bildschirm, um das Dreieck zu drehen:

Abbildung 1: Dreieck, das bei Eingabe per Berührung gedreht wird (Kreis zeigt Berührung) Standort).