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; } }
同样运行,在屏幕上滑动,既可以看到立方体随之变换.
结果不再截图.