Ruch obiektów zgodnie z gotowym programem, takim jak obracający się trójkąt, jest przydatny
ale co w sytuacji, gdy użytkownik chce korzystać z grafiki OpenGL ES?
Kluczem do tego, aby aplikacja OpenGL ES była interaktywna, jest rozszerzenie wdrożenia
GLSurfaceView
, aby zastąpić parametr
onTouchEvent()
, aby nasłuchiwać zdarzeń dotknięcia.
Z tej lekcji dowiesz się, jak nasłuchiwać zdarzeń dotknięcia, aby umożliwić użytkownikom obracanie obiektu OpenGL ES.
Skonfiguruj detektor dotyku
Aby aplikacja OpenGL ES reagowała na zdarzenia dotknięcia, musisz zaimplementować klucz
Metoda onTouchEvent()
w:
GLSurfaceView
zajęcia. Przykładowa implementacja poniżej pokazuje, jak nasłuchiwać
MotionEvent.ACTION_MOVE
zdarzeń i przetłumacz je na język
kąt obrotu kształtu.
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; }
Zwróć uwagę, że po obliczeniu kąta obrotu metoda ta wywołuje
requestRender()
, aby poinformować
że nadszedł czas na wyrenderowanie klatki. W tym przykładzie to właśnie ta metoda sprawdza się najlepiej.
ponieważ ramki nie trzeba ponownie rysować, chyba że obrót nastąpi zmiana. Jednak
nie ma żadnego wpływu na wydajność, chyba że zażądasz również, aby mechanizm renderowania
dane zmieniają się za pomocą funkcji setRenderMode()
, więc upewnij się, że ten wiersz nie jest skomentowany w mechanizmie renderowania:
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); }
Pokaż kąt obrotu
Przykładowy kod powyżej wymaga udostępnienia kąta obrotu za pomocą mechanizmu renderowania
dodanie członka publicznego. Ponieważ kod mechanizmu renderowania działa w osobnym wątku niż główny użytkownik
wątku interfejsu Twojej aplikacji, musisz zadeklarować tę zmienną publiczną jako volatile
.
Oto kod do zadeklarowania zmiennej i udostępnienia pary metody pobierającej i ustawiającej:
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; } }
Zastosuj rotację
Aby zastosować obrót wygenerowany przez sterowanie dotykowe, zmień w komentarz kod, który generuje kąt, a następnie dodaj zmienną, która zawiera kąt wygenerowany za pomocą dotyku:
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); }
Po wykonaniu powyższych czynności uruchom program i przeciągnij palcem po ekranie aby obrócić trójkąt: