OpenGL的承载体是GLSurfaceView,而GLSurfaceView类在很多方面类似于View,那么它同样具有与View的一些待遇,比如也能够响应KeyEvent,MotionEvent事件等等,从前面几篇中,有很多立方体的图形可以在每次重绘的时候,设置不同的位置和旋转角度,就可以实现图形的位置的变化,这里就可以通过触摸事件产生的坐标位置,让图形跟随触摸方向移动或者变换.
整体上不是很难.
<1> : 新建Android studio工程,工程名为PumpKinBasicInput,绘制立方体借鉴了前一篇的.
主类:
package org.pumpkin.pumpkinbasicinput;
import android.app.Activity;
import android.app.ActionBar;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
public class PumpKinMainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
InputSurfaceView inputSurfaceView=new InputSurfaceView(this);
setContentView(inputSurfaceView/*R.layout.activity_pump_kin_main*/);
}
}
继承GLSurfaceView类:
package org.pumpkin.pumpkinbasicinput;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.KeyEvent;
import android.view.MotionEvent;
/**
* Created by Administrator on 2016/5/6.
*/
public class InputSurfaceView extends GLSurfaceView {
private final float TOUCH_SCALE_FACTOR = 180.0f / 320.0f;
private float previousX;
private float previousY;
private InputRenderer renderer;
public InputSurfaceView(Context context) {
super(context);
renderer=new InputRenderer(context);
this.setRenderer(renderer);
this.requestFocus();
this.setFocusableInTouchMode(true);
}
@Override
public boolean onKeyDown(int keyCode,KeyEvent event){
switch (event.getAction()){
case KeyEvent.KEYCODE_DPAD_LEFT:
renderer.speedY -= 0.1f;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
renderer.speedY += 0.1f;
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
renderer.speedX -= 0.1f;
break;
case KeyEvent.KEYCODE_DPAD_UP:
renderer.speedX += 0.1f;
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
break;
}
return true;//super.onKeyDown(keyCode,event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float currentX = event.getX();
float currentY = event.getY();
float deltaX, deltaY;
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_MOVE:
deltaX = currentX - previousX;
deltaY = currentY - previousY;
renderer.angleX += deltaY * TOUCH_SCALE_FACTOR;
renderer.angleY += deltaX * TOUCH_SCALE_FACTOR;
break;
}
previousX = currentX;
previousY = currentY;
return true;//super.onTouchEvent(event);
}
}
下面是立方体的绘制:
package org.pumpkin.pumpkinbasicinput;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.opengles.GL10;
/**
* Created by Administrator on 2016/5/5.
*/
public class MulTextureCube {
private int[] textures;
private Bitmap[] mBitmap=new Bitmap[6];
private FloatBuffer vertexBuffer;
private FloatBuffer texBuffer;
private float[] vertices={
-1.0f, -1.0f, 0.0f, // 0. left-bottom-front
1.0f, -1.0f, 0.0f, // 1. right-bottom-front
-1.0f, 1.0f, 0.0f, // 2. left-top-front
1.0f, 1.0f, 0.0f // 3. right-top-front
};
float[] texCoords={
0.0f, 1.0f, // A. left-bottom (NEW)
1.0f, 1.0f, // B. right-bottom (NEW)
0.0f, 0.0f, // C. left-top (NEW)
1.0f, 0.0f // D. right-top (NEW)
};
int[] textureIDs=new int[1];
public MulTextureCube(Context context){
mBitmap[0] = BitmapFactory.decodeResource(context.getResources(), R.drawable.gh);
mBitmap[1] = BitmapFactory.decodeResource(context.getResources(), R.drawable.ghh);
mBitmap[2] = BitmapFactory.decodeResource(context.getResources(), R.drawable.gtr);
mBitmap[3] = BitmapFactory.decodeResource(context.getResources(), R.drawable.ghr);
mBitmap[4] = BitmapFactory.decodeResource(context.getResources(), R.drawable.yel);
mBitmap[5] = BitmapFactory.decodeResource(context.getResources(), R.drawable.hj);
ByteBuffer vbb=ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer=vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer tbb=ByteBuffer.allocateDirect(texCoords.length*4);
tbb.order(ByteOrder.nativeOrder());
texBuffer=tbb.asFloatBuffer();
texBuffer.put(texCoords);
texBuffer.position(0);
}
public void loadTexture(GL10 gl){
IntBuffer textBuffer=IntBuffer.allocate(6);
gl.glGenTextures(6,textBuffer);
textures=textBuffer.array();
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[0]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,mBitmap[0],0);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[1]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,mBitmap[1],0);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[2]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,mBitmap[2],0);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[3]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,mBitmap[3],0);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[4]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,mBitmap[4],0);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[5]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,mBitmap[5],0);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);
}
public void draw(GL10 gl){
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3,GL10.GL_FLOAT,0,vertexBuffer);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glTexCoordPointer(2,GL10.GL_FLOAT,0,texBuffer);
//front
gl.glPushMatrix();
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[0]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);
gl.glPopMatrix();
//left
gl.glPushMatrix();
gl.glRotatef(270.0f,0.0f,1.0f,0.0f);
gl.glTranslatef(0.0f,0.0f,1.0f);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[1]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);
gl.glPopMatrix();
//back
gl.glPushMatrix();
gl.glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[2]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// right
gl.glPushMatrix();
gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[3]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// top
gl.glPushMatrix();
gl.glRotatef(270.0f, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[4]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// bottom
gl.glPushMatrix();
gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[5]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
}
渲染器:
package org.pumpkin.pumpkinbasicinput;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
/**
* Created by Administrator on 2016/5/6.
*/
public class InputRenderer implements GLSurfaceView.Renderer {
private Context mContext;
private MulTextureCube mulTextureCube;
float angleX = 0;
float angleY = 0;
float speedX = 0;
float speedY = 0;
float z = -6.0f;
public InputRenderer(Context context){
mContext=context;
mulTextureCube=new MulTextureCube(context);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
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);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glDisable(GL10.GL_DITHER);
mulTextureCube.loadTexture(gl);
gl.glEnable(GL10.GL_TEXTURE_2D);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if(height==0){
height=1;
}
float aspect=(float)width/height;
gl.glViewport(0,0,width,height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, 45, aspect, 0.1f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, z);
gl.glRotatef(angleX, 1.0f, 0.0f, 0.0f);
gl.glRotatef(angleY, 0.0f, 1.0f, 0.0f);
mulTextureCube.draw(gl);
angleX += speedX;
angleY += speedY;
}
}
同样运行,在屏幕上滑动,既可以看到立方体随之变换.
结果不再截图.