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: