Use GlsurfaceView to perform operation methods and understanding of events

I used standard vertex, color and point buffers to display a 3D object.

I can..

>Use Touch event to rotate the object
>Use GL10 to render the object using openGL ES 1.0
>Everything is great

Now I want to be able to zoom in and out with two fingers for a “pinch in” action. I I found some good tutorials and sample codes, but it is mainly used for ImageViews. I am still a semi newbie to Android, and I don’t fully understand how to make this zoom function work for GLSurfaceView.

The following is my current Code written for the Activity class. The first touch handler is the zoom event I found through the tutorial designed for ImageView (I use it because I think it will be a simple transition). The second handler is for rotation Event, it works normally.

Thank you in advance, I hope this article can help others to solve the same problem.
If any edits or additions are needed, I will be on standby at any time.

// 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< br /> {
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_ExampleSurf aceView(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 (m ode == 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();
< br /> 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 {
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);
}
< br /> private void finger_distance_midpoint(PointF point, MotionEvent e)
{
float x = e.getX(0) + e.getX(1);< br /> float y = e.getY(0) + e.getY(1);
point.set(x / 2, y / 2);
}

}

Thanks again…

There are two obvious ways to solve this Question. If you only want to increase the size of a single object, you can use glScalef when drawing the object. Using scalef is easy and relatively simple, but it does not fully meet your requirements.

Another One solution is to apply a scaling factor to the projection matrix to produce the desired effect. To achieve this, just multiply the left, right, top, and bottom distances of the projection matrix by such a ratio before drawing.

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

If you are interested, you can find more information about the projection matrix here

I use standard vertices, colors And the point buffer shows a 3D object.

I can..

>Use touch events to rotate the object
>Use GL10 to render the object using openGL ES 1.0< br>>Everything is great

Now I want to be able to zoom in and out with two fingers for a “pinch in” action. I found some good tutorials and sample codes, but it is mainly used for ImageViews . I am still a semi-newbie to Android, and I don’t fully understand how to make this zoom function applicable to GLSurfaceView.

Below is the code I currently write for the Activity class. The first touch handler I passed as The zoom event found in the tutorial designed by ImageView (I use it because I think it will be a simple conversion). The second handler is for the rotation event and it works fine.

Thank you in advance , I hope this article can help others solve the same problem.
If any edits or additions are needed, I will be on standby at any time.

// Activity for rendering 3D object openGL ES 1.0
public class GL_Exampl eActivity 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.ACTI ON_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 {
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…

There are two obvious ways to solve this problem. If you Just want to increase the size of a single object, you can use glScalef when drawing objects. Using scalef is easy and relatively simple, but it does not fully meet your requirements.

Another solution is Apply a scaling factor to the projection matrix to produce the desired effect. To achieve this, just multiply the left, right, top, and bottom distances of the projection matrix by such a ratio 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 are interested, you can find more information about the projection matrix here

Leave a Comment

Your email address will not be published.