Reputation: 1
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
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
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
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