Cómo y comprensión del evento de arrastre y zoom con GLSurfaceView

Tenía todo trabajando con esta aplicación de prueba he hecho que muestra un objeto 3D utilizando el estándar de vértice, color y punto de amortiguación.

Puedo..

  • Gire el objeto con eventos táctiles
  • Render object con openGL ES 1.0 usando GL10
  • Todo funciona muy bien

Ahora quiero ser capaz de acercar y alejar usando dos dedos para un movimiento de "pellizco". He encontrado algunos buenos tutoriales y código de ejemplo, pero es sobre todo para ImageViews. Todavía soy semi-nuevo para Android y no entiendo completamente cómo hacer que este trabajo de función de zoom para GLSurfaceView.

A continuación se muestra el código que tengo hasta ahora para la clase de actividad. El primer manipulador táctil es para el evento de zoom que encontré a través de un tutorial diseñado para ImageView (usé esto porque pensé que sería una conversión fácil). El segundo controlador es para el evento de rotación, que funciona muy bien.

Gracias de antemano y espero que este post ayudará a otros con el mismo problema. Estaré parado para cualquier edición o adiciones necesarias.

// Activity for rendering 3D object openGL ES 1.0 public class GL_ExampleActivity extends Activity { private GLSurfaceView surface; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); surface = new GL_ExampleSurfaceView(this); setContentView(surface); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); surface.onPause(); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); surface.onResume(); } } class GL_ExampleSurfaceView extends GLSurfaceView { private static final String TAG = "Touch"; Matrix matrix_new = new Matrix(); Matrix last_matrix = new Matrix(); static final int NONE = 0; static final int DRAG = 1; static final int ZOOM = 2; int mode = NONE; PointF start = new PointF(); PointF mid = new PointF(); float oldDist = 1f; private final float SCALE_FACTOR = 180.0f / 320; private GLRenderer renderer; private float previous_x; private float previous_y; public GL_ExampleSurfaceView(Context context) { super(context); renderer = new GLRenderer(); setRenderer(renderer); setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); } @Override public boolean onTouchEvent(MotionEvent e) { // handler for drag and zoom events switch (e.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: last_matrix.set(matrix_new); start.set(e.getX(), e.getY()); Log.d(TAG, "mode=DRAG"); mode = DRAG; //requestRender(); break; case MotionEvent.ACTION_POINTER_DOWN: oldDist = finger_distance(e); Log.d(TAG, "oldDist=" + oldDist); if (oldDist > 10f) { last_matrix.set(matrix_new); finger_distance_midpoint(mid, e); mode = ZOOM; Log.d(TAG, "mode=ZOOM"); } //requestRender(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: mode = NONE; Log.d(TAG, "mode=NONE"); //requestRender(); break; case MotionEvent.ACTION_MOVE: if (mode == DRAG) { matrix_new.set(last_matrix); matrix_new.postTranslate(e.getX() - start.x, e.getY() - start.y); } else if (mode == ZOOM) { float newDist = finger_distance(e); Log.d(TAG, "newDist=" + newDist); if (newDist > 10f) { matrix_new.set(last_matrix); float scale = newDist / oldDist; matrix_new.postScale(scale, scale, mid.x, mid.y); } } //requestRender(); break; } //view.setImageMatrix(matrix_new); // handler for rotation event, y and x axis float x = e.getX(); float y = e.getY(); switch (e.getAction()) { case MotionEvent.ACTION_MOVE: float dx = x - previous_x; float dy = y - previous_y; if (y > getHeight() / 2) { dx = dx * -1 ; } if (x < getWidth() / 2) { dy = dy * -1 ; } renderer.angle_x += dx * SCALE_FACTOR; renderer.angle_y += dy * SCALE_FACTOR; requestRender(); } previous_x = x; previous_y = y; return true; } private float finger_distance(MotionEvent e) { float x = e.getX(0) - e.getX(1); float y = e.getY(0) - e.getY(1); return FloatMath.sqrt(x * x + y * y); } private void finger_distance_midpoint(PointF point, MotionEvent e) { float x = e.getX(0) + e.getX(1); float y = e.getY(0) + e.getY(1); point.set(x / 2, y / 2); } } 

Gracias de nuevo…

Hay dos maneras obvias de abordar esto. Si sólo desea aumentar el tamaño de un objeto individual, puede utilizar glScalef al dibujar el objeto. El uso de scalef es fácil y relativamente sencillo, pero no es exactamente lo que estás pidiendo.

Otra solución es aplicar un factor de escala a su matriz de proyección que producirá el efecto deseado. Para lograr esto, solo multiplique las distancias izquierda, derecha, superior y inferior de su matriz de proyección por una escala similar a la anterior.

Gl.glFrustumf (ancho / 2 * zoom, ancho / 2 * zoom, altura / 2 * zoom, altura / 2 * zoom, 1, -1);
(Tenga en cuenta, si está utilizando una matriz ortogonal que estará utilizando glOrthof en su lugar)

Si está interesado, puede encontrar más información sobre la matriz de proyección aquí

  • Android - Detectar doble acceso y tripletap en vista
  • Captura de eventos táctiles en un elemento de lista de Android e impide el desplazamiento
  • WebKit / WebView toque / onclick resaltado por defecto (Android Ice Cream Sandwich)
  • Android ¿Cómo registrar OnTouchEvent para toda la vista de contenido principal de Activity?
  • TouchDelegate aplicado a ListView sólo responde al evento de clic
  • Android requestFocusFromTouch muestra menú con el primer elemento resaltado
  • Implementación de un control deslizante en Android
  • Android captura todos los eventos de movimiento y los envía a los niños
  • Android 4 Chrome éxito problema de prueba en eventos de toque después de transformar CSS
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.