一、本文主要是展示一个demo,实现的是画一个三维的立方体,通过滑动屏幕来旋转方向,上下左右来移动。直接上代码:
MainActivity:
 package com.example.zp.a3dword; import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Point;import android.opengl.GLSurfaceView;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.KeyEvent;import android.view.MotionEvent;import android.view.View;import android.view.Window;import android.view.WindowManager; public class MainActivity extends AppCompatActivity {  private GLSurfaceView glSurfaceView; GLRenderer renderer; //屏幕的宽高 int width; int height; float speed = 0.5f;  @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); glSurfaceView= (GLSurfaceView) findViewById(R.id.gl_surfaceView);// glSurfaceView =new GLSurfaceView(this); Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.ayx); Bitmap bitmap2 = BitmapFactory.decodeResource(this.getResources(), R.drawable.ayx2); Bitmap mBitmap[] = {bitmap,bitmap2}; renderer=new GLRenderer(mBitmap); glSurfaceView.setRenderer(renderer);// setContentView(glSurfaceView); WindowManager wm = this.getWindowManager(); Point p = new Point(0,0); wm.getDefaultDisplay().getSize(p); width = p.x; height =p.y;  }  int downX; //向一个方向的起始点坐标 int previewX; // 记住前一个点的x坐标 int currentX; //当前点的ex坐标  int downY; //向一个方向的起始点坐标 int previewY; // 记住前一个点的x坐标 int currentY; //当前点的ex坐标  @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: downX = (int) event.getX(); previewX = downX; downY = (int) event.getY(); previewY= downY; break; case MotionEvent.ACTION_MOVE: currentX = (int) event.getX(); currentY = (int) event.getY();//****************************X方向旋转******************************************// //判断运动的方向是否改变,大于0不改变 if((currentX - downX)*(currentX - previewX)>0) { int dis = currentX - downX; float angle = (float) dis / (float) width * (float) Math.PI; renderer.letfrightDirectionChange(angle); previewX = currentX; } else { downX = previewX; }//****************************Y方向旋转******************************************// currentY = (int) event.getY(); //判断运动的方向是否改变,大于0不改变 if((currentY - downY)*(currentY - previewY)>0) { int dis = currentY - downY; float angle = (float) dis / (float) width * (float) Math.PI; renderer.updownDirectionChange(angle); previewY = currentY; } else { downY = previewY; }  break; case MotionEvent.ACTION_UP: break; } return true; }  public void goBack(View view) { renderer.goAhead(-speed); } public void goAhead(View view) { renderer.goAhead(speed); } public void goLeft(View view) { renderer.goleft(speed); } public void goRight(View view) { renderer.goleft(-speed); }}Render的实现:
 package com.example.zp.a3dword; import android.graphics.Bitmap;import android.opengl.GLSurfaceView;import android.opengl.GLUtils;import java.nio.FloatBuffer;import java.nio.IntBuffer; import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10; /** * Created by lenovo on 2016/9/7. */public class GLRenderer implements GLSurfaceView.Renderer{  float xrot = 0; float yrot = 0;  private float visonPointX=0f; private float visonPointY=0f; private float visonPointZ=-3f;  int size=3; int one = 0x10000*size;  int textureSize = 2; int texture[] = new int [textureSize]; private Bitmap mBitmap[];   //当正方体很小,为1个点位的时候发现在角落的时候两边出现黑条,这是因为屏幕显示的,即我们看到的视觉是一个以(0,0,0)为中心的平面,旋转函数是旋转整个三维世界,而 //视觉平面的大小位置永远不变,我自己定义为视觉坐标,视觉坐标是不变的,三维世界的坐标起初与视觉坐标是一致的,且视觉显示的是-1层即z为-1的那层只有小与-1的物体可以看到 // 当随着三维世界的旋转就会与视觉坐标产生差异,视觉坐标不变,当随着三维世界的旋转,三维世界的坐标对应的点对应与视觉坐标-1层及大于-1层的物体就不会显示 //正方体的6个面,4个点确定一个面 IntBuffer vertices = BufferUtil.intToBuffer(new int[]{ -one,-one,one, one,-one,one,  -one,one,one, one,one,one,  -one,-one,-one, -one,one,-one,  one,-one,-one,one,one,-one,  -one,one,-one, -one,one,one,  one,one,-one, one,one,one,  -one,-one,-one, one,-one,-one,  -one,-one,one,one,-one,one,  one,-one,-one, one,one,-one,  one,-one,one, one,one,one,  -one,-one,-one, -one,-one,one,  -one,one,-one,-one,one,one  });  //这里one 为几就贴几张,是指一个边贴几张,一个面就是one*one张了,one为1*5所以这里除以5,就会只贴一张 int one2 = one/size; IntBuffer texCoords2 = BufferUtil.intToBuffer(new int[]{ 0, one2, one2, one2, 0, 0, one2, 0, 0, 0, 0, one2, one2, 0, one2, one2, one2, one2, one2, 0, 0, one2, 0, 0, 0, one2, one2, one2, 0, 0, one2, 0, 0, 0, 0, one2, one2, 0, one2, one2, one2, 0, 0, 0, one2, one2, 0, one2, });  public GLRenderer(Bitmap mBitmap[]) { this.mBitmap = mBitmap; }  @Override public void onDrawFrame(GL10 gl) { // 清除屏幕和深度缓存 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // 重置当前的模型观察矩阵// gl.glEnable(GL10.GL_LIGHTING); gl.glLoadIdentity(); gl.glTranslatef(visonPointX,visonPointY,visonPointZ);  //设置3个方向的旋转 gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); gl.glRotatef(yrot, 0.0f,1.0f, 0.0f);// gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f);   gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);//启用纹理映射  gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertices); gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texCoords2); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]);  for(int i = 0 ; i < 6 ; i ++) { gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP , i*4 , 4); gl.glFinish(); } gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);  }  @Override public void onSurfaceChanged(GL10 gl, int width, int height) { float ratio = (float) width / height; //设置OpenGL场景的大小 gl.glViewport(0, 0, width, height); //设置投影矩阵 gl.glMatrixMode(GL10.GL_PROJECTION); //重置投影矩阵 gl.glLoadIdentity(); // 设置视口的大小 gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); // 选择模型观察矩阵 gl.glMatrixMode(GL10.GL_MODELVIEW); // 重置模型观察矩阵 gl.glLoadIdentity();  }  @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // 黑色背景 gl.glClearColor(0, 0, 0, 0);// gl.glEnable(GL10.GL_CULL_FACE); // 启用阴影平滑 gl.glShadeModel(GL10.GL_SMOOTH); // 启用深度测试 gl.glEnable(GL10.GL_DEPTH_TEST);  // 启用混合模式 gl.glEnable(GL10.GL_BLEND); gl.glDisable(GL10.GL_DEPTH_TEST); // 关闭深度测试 //设置光线,,1.0f为全光线,a=50% gl.glColor4f(1.0f,1.0f,1.0f,0.5f); // 基于源象素alpha通道值的半透明混合函数 gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE);  //启用纹理映射 gl.glClearDepthf(1.0f); //深度测试的类型 gl.glDepthFunc(GL10.GL_LEQUAL); //精细的透视修正 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); //允许2D贴图,纹理 gl.glEnable(GL10.GL_TEXTURE_2D); getTextures(gl);   // //设置光颜色// FloatBuffer lightAmbient = BufferUtil.floatToBuffer(new float[]{// 1f, 1f, 1f, 1f// } );// FloatBuffer lightDiffuse = BufferUtil.floatToBuffer(new float[]{// 1f,1f,1f,1f// } );// //定义光源位置// FloatBuffer lightPosition = BufferUtil.floatToBuffer(new float[]{// -2f,0f,-4f,1f// } );// //设置环境光// gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, lightAmbient);//// //设置漫射光// gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, lightDiffuse);//// //设置光源位置// gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, lightPosition);//// //开启一号光源// gl.glEnable(GL10.GL_LIGHT1);  }   private void getTextures(GL10 gl) { IntBuffer intBuffer = IntBuffer.allocate(2);//申请2个纹理存储空间 // 创建纹理 gl.glGenTextures(2 , intBuffer); //创建2个纹理,绑定intuffer texture[0] = intBuffer.get(); // 获取第一个纹理的存储指针,即纹理存储位置,位置+1 texture[1] = intBuffer.get(); //获取下一个纹理存储的位置  // 设置要使用的纹理 gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]); //生成纹理 GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0 , mBitmap[0] , 0);//利用图mBitmap[0]生成纹理,存储在texture[0] // 线形滤波 gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);  //生成第二个纹理 gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0 , mBitmap[1] , 0);//利用图mBitmap[0]生成纹理,存储在texture[1] gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);  }  //三维世界向右旋转,我们的视觉就向左旋转了 public void letfrightDirectionChange( float angle) { yrot = yrot + angle; }  public void updownDirectionChange(float angle) { xrot = xrot + angle; }  public void goAhead (float dis) { visonPointZ = visonPointZ + dis; } public void goleft (float dis) { visonPointX = visonPointX + dis; } }BufferUtil工具类前面展示过这里就省略了。