第一个用GLSurfaceView画图形

来源:互联网 发布:手游服务端源码 编辑:程序博客网 时间:2024/05/01 17:18

package wyf.swq;
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
public class MyActivity extends Activity {
    /** Called when the activity is first created. */
 private MySurfaceView mSurfaceView;//声明MySurfaceView对象
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);    
        mSurfaceView=new MySurfaceView(this);//创建MySurfaceView对象
        mSurfaceView.requestFocus();//获取焦点
        mSurfaceView.setFocusableInTouchMode(true);//设置为可触控
        LinearLayout ll=(LinearLayout)this.findViewById(R.id.main_liner);//获得线性布局的引用
        ll.addView(mSurfaceView);
    }
 @Override
 protected void onPause() {
  // TODO Auto-generated method stub
  super.onPause();
  mSurfaceView.onPause();
 }
 @Override
 protected void onResume() {
  // TODO Auto-generated method stub
  super.onResume();
  mSurfaceView.onResume();
 } 
}

 

 

   package wyf.swq;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;
public class MySurfaceView extends GLSurfaceView {
 private final float TOUCH_SCALE_FACTOR=180.0f/320;//角度缩放比例,即屏幕宽320,从屏幕的一端滑到另一端,x轴上的差距对应相应的需要旋转的角度
 private SceneRenderer myRenderer;//场景渲染器
 private float myPreviousY;//上次屏幕上的触控位置的Y坐标
 private float myPreviousX;//上次屏幕上的触控位置的X坐标
 public MySurfaceView(Context context) {
  super(context);
  // TODO Auto-generated constructor stub
  myRenderer=new SceneRenderer();//创建场景渲染器
  this.setRenderer(myRenderer);//设置渲染器
  this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染
 }
 @Override//触摸事件回调方法
 public boolean onTouchEvent(MotionEvent event) {
  // TODO Auto-generated method stub
  float y=event.getY();//获得当前触点的Y坐标
  float x=event.getX();//获得当前触点的X坐标
  switch(event.getAction()){
  case MotionEvent.ACTION_MOVE:
   float dy=y-myPreviousY;//滑动距离在y轴方向上的垂直距离
   float dx=x-myPreviousX;//活动距离在x轴方向上的垂直距离
   myRenderer.tr.yAngle+=dx*TOUCH_SCALE_FACTOR;//设置沿y轴旋转角度
   myRenderer.tr.zAngle+=dy*TOUCH_SCALE_FACTOR;//设置沿z轴旋转角度
   requestRender();//渲染画面
  }
  myPreviousY=y;
  myPreviousX=x;
  return true;
 }
 private class SceneRenderer  implements GLSurfaceView.Renderer{//内部类,实现Renderer接口,渲染器 
  Triangle tr=new Triangle();
  public SceneRenderer(){  
  }
  @Override
  public void onDrawFrame(GL10 gl) {
   // TODO Auto-generated method stub  
   gl.glEnable(GL10.GL_CULL_FACE);//设置为打开背面剪裁 
   gl.glShadeModel(GL10.GL_SMOOTH);//设置着色模型为平滑着色
   gl.glFrontFace(GL10.GL_CCW);//设置自定义卷绕顺序为逆时针为正面
   gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);//清除颜色缓存和深度缓存
   gl.glMatrixMode(GL10.GL_MODELVIEW);//设置当前矩阵为模式矩阵
   gl.glLoadIdentity();//设置当前矩阵为单位矩阵 
   gl.glTranslatef(0, 0, -2.0f);//
   tr.drawSelf(gl);//
  }
  @Override
  public void onSurfaceChanged(GL10 gl, int width, int height) {
   // TODO Auto-generated method stub
    gl.glViewport(0, 0, width, height);
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    float ratio=(float)width/height;
    gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
  }
  @Override
  public void onSurfaceCreated(GL10 gl, EGLConfig config) {
   // TODO Auto-generated method stub
   gl.glDisable(GL10.GL_DITHER);//关闭抗抖动
   gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);//设置特定Hint项目的模式,这里为设置使用快速模式
   gl.glClearColor(0, 0, 0, 0);//设置屏幕背景色为黑色
   gl.glEnable(GL10.GL_DEPTH_TEST);//启用深度检测 
  }}}

 

 

 

package wyf.swq;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import javax.microedition.khronos.opengles.GL10;
public class Triangle {
 private IntBuffer myVertexBuffer;//顶点坐标数据缓冲
 private IntBuffer myColorBuffer;//顶点着色数据缓冲
 private ByteBuffer myIndexBuffer;//顶点构建的索引数据缓冲
 int vCount=0;//顶点数量
 int iCount=0;//索引数量
 float yAngle=0;//绕y轴旋转的角度
 float zAngle=0;//绕z轴旋转的角度
 public Triangle(){
  vCount=3;//一个三角形,3个顶点
  final int UNIT_SIZE=10000;//缩放比例
  int []vertices=new int[]
        {
    -8*UNIT_SIZE,6*UNIT_SIZE,0,
    -8*UNIT_SIZE,-6*UNIT_SIZE,0,
    8*UNIT_SIZE,-6*UNIT_SIZE,0,
    1*UNIT_SIZE,5*UNIT_SIZE,0,
    -1*UNIT_SIZE,-5*UNIT_SIZE,0,
    1*UNIT_SIZE,-5*UNIT_SIZE,0
        };
  //创建顶点坐标数据缓存,由于不同平台字节顺序不同,数据单元不是字节的(上面的事整型的缓存),一定要经过ByteBuffer转换,关键是通过ByteOrder设置nativeOrder()
  ByteBuffer vbb=ByteBuffer.allocateDirect(vertices.length*4);//一个整数四个字节,根据最新分配的内存块来创建一个有向的字节缓冲
  vbb.order(ByteOrder.nativeOrder());//设置这个字节缓冲的字节顺序为本地平台的字节顺序
  myVertexBuffer=vbb.asIntBuffer();//转换为int型缓冲
  myVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
  myVertexBuffer.position(0);//设置缓冲区的起始位置
  final int one=65535;//支持65535色色彩通道
  int []colors=new int[]//顶点颜色值数组,每个顶点4个色彩值RGBA
  {
   one,one,one,0,
   one,one,one,0,
   one,one,one,0
  };
  ByteBuffer cbb=ByteBuffer.allocateDirect(colors.length*4);
  cbb.order(ByteOrder.nativeOrder());
  myColorBuffer=cbb.asIntBuffer();
  myColorBuffer.put(colors);
  myColorBuffer.position(0);
  //为三角形构造索引数据初始化
  iCount=6;
  byte []indices=new byte[]
            {
    0,1,2,
    3,4,5
            };
  //创建三角形构造索引数据缓冲
  myIndexBuffer=ByteBuffer.allocateDirect(indices.length);
  myIndexBuffer.put(indices);
  myIndexBuffer.position(0);
 }
 public void drawSelf(GL10 gl)//GL10是实现接口GL的一公共接口,包含了一系列常量和抽象方法
 {
  gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);//启用顶点坐标数组
  gl.glEnableClientState(GL10.GL_COLOR_ARRAY);//启用顶点颜色数组
  
  gl.glRotatef(yAngle,0,1,0);//根据yAngle的角度值,绕y轴旋转yAngle
  gl.glRotatef(zAngle,0,0,1);
  
  gl.glVertexPointer//为画笔指定顶点坐标数据
  (
    3,     //每个顶点的坐标数量为3
    GL10.GL_FIXED,  //顶点坐标值的类型为GL_FIXED,整型
    0,     //连续顶点坐标数据之间的间隔
    myVertexBuffer  //顶点坐标数量
  );
  gl.glColorPointer//为画笔指定顶点 颜色数据
  (
   4,
   GL10.GL_FIXED,
   0,
   myColorBuffer
  );
  gl.glDrawElements//绘制图形
  (
   GL10.GL_TRIANGLES,  //填充模式,这里是以三角形方式填充
   iCount,     //顶点数量
   GL10.GL_UNSIGNED_BYTE, //索引值的类型
   myIndexBuffer   //索引值数据
  );
 }}

原创粉丝点击