Maveňツ
Maveňツ

Reputation: 1

zoom out in OpenGL in android

I m using 3D object and rendering it and showing it by extends GLSurfaceView implementing Renderer, the problem is that how to do zoom out-in with pinch-in and pinch-out.

Below is my class

package com.example.objLoader;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;
import android.os.Debug;
import android.view.KeyEvent;
import android.view.MotionEvent;
public class ManishRenderer extends GLSurfaceView implements Renderer { 
/** Triangle instance */
private OBJParser parser;
private TDModel model;

/* Rotation values */
private float xrot;                 //X Rotation
private float yrot;                 //Y Rotation

/* Rotation speed values */

private float xspeed;               //X Rotation Speed ( NEW )
private float yspeed;               //Y Rotation Speed ( NEW )

private float z = 320.0f;

private float oldX;
    private float oldY;
private final float TOUCH_SCALE = 0.8f;     //Proved to be good for normal rotation ( NEW )

private float[] lightAmbient = {1.0f, 1.0f, 1.0f, 1.0f};
private float[] lightDiffuse = {1.0f, 1.0f, 1.0f, 1.0f};
private float[] lightPosition = {0.0f, -3.0f, 2.0f, 1.0f};
private FloatBuffer lightAmbientBuffer;
private FloatBuffer lightDiffuseBuffer;
private FloatBuffer lightPositionBuffer;

public ManishRenderer(Context ctx) {
    super(ctx);



    parser=new OBJParser(ctx);
    model=parser.parseOBJ("/storage/sdcard1/man.obj");  
    Debug.stopMethodTracing();
    this.setRenderer(this);
    this.requestFocus();
    this.setFocusableInTouchMode(true);

    ByteBuffer byteBuf = ByteBuffer.allocateDirect(lightAmbient.length * 5024);
    byteBuf.order(ByteOrder.nativeOrder());
    lightAmbientBuffer = byteBuf.asFloatBuffer();
    lightAmbientBuffer.put(lightAmbient);
    lightAmbientBuffer.position(0);

    byteBuf = ByteBuffer.allocateDirect(lightDiffuse.length * 5024);
    byteBuf.order(ByteOrder.nativeOrder());
    lightDiffuseBuffer = byteBuf.asFloatBuffer();
    lightDiffuseBuffer.put(lightDiffuse);
    lightDiffuseBuffer.position(0);

    byteBuf = ByteBuffer.allocateDirect(lightPosition.length * 5024);
    byteBuf.order(ByteOrder.nativeOrder());
    lightPositionBuffer = byteBuf.asFloatBuffer();
    lightPositionBuffer.put(lightPosition);
    lightPositionBuffer.position(0);
}
/**
 * The Surface is created/init()
 */
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbientBuffer);      
    gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuseBuffer);      
    gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPositionBuffer);    
    gl.glEnable(GL10.GL_LIGHT0);        
    gl.glShadeModel(GL10.GL_SMOOTH);            
    gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);    
    gl.glClearDepthf(1.0f);                     
    gl.glEnable(GL10.GL_DEPTH_TEST);            
    gl.glDepthFunc(GL10.GL_LEQUAL);             
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); 
}

/**
 * Here we do our drawing
 */
public void onDrawFrame(GL10 gl) {
    //Clear Screen And Depth Buffer
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);    
    gl.glLoadIdentity();                    
    gl.glEnable(GL10.GL_LIGHTING);
    gl.glTranslatef(0.0f, -1.2f, -z);   //Move down 1.2 Unit And Into The Screen 6.0
    gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);   //X
    gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);   //Y
    model.draw(gl);                     //Draw the square
    gl.glLoadIdentity();        
    xrot += xspeed;
    yrot += yspeed;

}

/**
 * If the surface changes, reset the view
 */
public void onSurfaceChanged(GL10 gl, int width, int height) {
    if(height == 0) {                       //Prevent A Divide By Zero By
        height = 1;                         //Making Height Equal One
    }

    gl.glViewport(0, 0, width, height);     //Reset The Current Viewport
    gl.glMatrixMode(GL10.GL_PROJECTION);    //Select The Projection Matrix
    gl.glLoadIdentity();                    //Reset The Projection Matrix

    //Calculate The Aspect Ratio Of The Window
    GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 1100.0f);

    gl.glMatrixMode(GL10.GL_MODELVIEW);     //Select The Modelview Matrix
    gl.glLoadIdentity();                    //Reset The Modelview Matrix
}
@Override
public boolean onTouchEvent(MotionEvent event) {
    //
    float x = event.getX();
    float y = event.getY();

    //If a touch is moved on the screen
    if(event.getAction() == MotionEvent.ACTION_MOVE) {
        //Calculate the change
        float dx = x - oldX;
        float dy = y - oldY;
        //Define an upper area of 10% on the screen
        int upperArea = this.getHeight() / 10;

        //Zoom in/out if the touch move has been made in the upper
        if(y < upperArea) {
            z -= dx * TOUCH_SCALE / 2;

        //Rotate around the axis otherwise
        } else {                
            xrot += dy * TOUCH_SCALE;
            yrot += dx * TOUCH_SCALE;
        }        

    //A press on the screen
    } else if(event.getAction() == MotionEvent.ACTION_UP) {


    }

    //Remember the values
    oldX = x;
    oldY = y;

    //We handled the event
    return true;
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    //
    if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {

    } else if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {

    } else if(keyCode == KeyEvent.KEYCODE_DPAD_UP) {
        z -= 3;

    } else if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
        z += 3;

    } else if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {

    }

    //We handled the event
    return true;
}}

Tried SurfaceView Zoom IN and OUT functionality using Custom Camera

but it is not what i m searching :( i m not having UI i.e xml part where i can add zoom-in-out widgets

Upvotes: 6

Views: 5239

Answers (3)

Roman Black
Roman Black

Reputation: 3497

You need to implement OnScaleGestureDetector and create ScaleGestureDetector to listen pinch-in and pinch-out events.

For example I use it as an inner class of GLSurfaceView:

...

private float sizeCoef = 1;

...

private class ScaleDetectorListener implements ScaleGestureDetector.OnScaleGestureListener{

    float scaleFocusX = 0;
    float scaleFocusY = 0;

    public boolean onScale(ScaleGestureDetector arg0) {
        float scale = arg0.getScaleFactor() * sizeCoef;

        sizeCoef = scale;

        requestRender();

        return true;
    }

    public boolean onScaleBegin(ScaleGestureDetector arg0) {
        invalidate();

        scaleFocusX = arg0.getFocusX();
        scaleFocusY = arg0.getFocusY();

        return true;
    }

    public void onScaleEnd(ScaleGestureDetector arg0) {
        scaleFocusX = 0;
        scaleFocusY = 0;
    }
} 

Also You have to add some code to onDrawFrame() method:

public void onDrawFrame(GL10 gl) {
    //Clear Screen And Depth Buffer
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);    
    gl.glLoadIdentity();                    
    gl.glEnable(GL10.GL_LIGHTING);
    gl.glTranslatef(0.0f, -1.2f, -z);   //Move down 1.2 Unit And Into The Screen 6.0
    gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);   //X
    gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);   //Y

    gl.glScalef(sizeCoef, sizeCoef, 0);  // if You have a 3d object put sizeCoef as all parameters

    model.draw(gl);                     //Draw the square
    gl.glLoadIdentity();        
    xrot += xspeed;
    yrot += yspeed;

}

Upvotes: 4

Ben
Ben

Reputation: 1295

I would recommend looking at GLU.glLookAt() which allows you to set the eye and center point. You can then move your eye forward and back based on your zoom value.

Alternatively you can use the android.openglMatrix class. And use perspectiveMatrix and lookAtMatrix functions then multiple those together and set them as your projectionMatrix.

Upvotes: 2

Bartol Karuza
Bartol Karuza

Reputation: 138

The SDK can help you a bit, using the standard Gesture detector. More details on how to implement this ScaleGestureDetector can be found here.

The basic step is that you pass the touch events into the ScaleGestureDetector and you will receive a callback on the listener when a scale event has happened, where you change your zoom state.

Upvotes: 2

Related Questions