Practical guidance and understanding of drag and zoom events using GLSurfaceView

I had everything that works with this test application that I made, which displays a three-dimensional object using a standard vertex, color, and dot buffer.

I can..

  • rotate object with touch events
  • render an object using openGL ES 1.0 using GL10
  • everything works perfectly

Now I want to be able to zoom in and out using two fingers to move the β€œpinch”. I found some good tutorials and sample code, but mostly this is for ImageViews. I am still not familiar with Android, and I do not quite understand how to make this zoom function for GLSurfaceView.

Below is the code that I have so far used for the Activity class. The first touch handler is for the zoom event that I found in the tutorial for ImageView (I used this because I thought it would be a simple conversion). The second handler is a rotation event that works great.

Thanks in advance, and I hope this post helps others with the same issue. I will be behind any changes or additions.

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

Thanks again...

+4
source share
1 answer

There are two obvious ways to approach this. If you just want to increase the size of an individual object, you can use glScalef when drawing the object. Using scalef is easy and relatively simple, but it's not quite what you are asking for.

Another solution is to apply the scaling factor to your projection matrix, which will give the desired effect. To achieve this, simply multiply the left, right, top, and bottom distances of your projection matrix by the same scale before drawing.

gl.glFrustumf (width / 2 * zoom, width / 2 * zoom, height / 2 * zoom, height / 2 * zoom, 1, -1);
(Note that if you use an orthogonal matrix, you will use glOrthof instead)

If you're interested, you can find more information on the projection matrix here.

+2
source

Source: https://habr.com/ru/post/1414542/


All Articles