android 使用ONPENGL ES 绘制三角形 (二)(索引方法)

来源:互联网 发布:cs1.6中文版for mac 编辑:程序博客网 时间:2024/05/08 00:37

     

      索引法是指通过调用gl。glDrawElements()方法来绘制何种基本几何图形。

      直接撸代码:

      1.编写MyActiviity.java ,具体显示流程如下:

          * 先引用相关包,并声明了MySurfaceView。

          *  为布局文件的按钮添加监听器列,分别用于监听三个不同的按钮。

          *  重写onpause方法,并同时挂起或回复MySufaceView试图

        

        MyActivity.java:

package com.scout.eeeeeee;import android.app.Activity;import android.os.Bundle;import android.widget.CompoundButton;import android.widget.CompoundButton.OnCheckedChangeListener;import android.widget.LinearLayout;import android.widget.ToggleButton;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);//        ToggleButton tb01 = (ToggleButton) this.findViewById(R.id.ToggleButton01);            //获得第一个开关按钮的引用        tb01.setOnCheckedChangeListener(new FirstListener());                            //为开关按钮注册监听器        ToggleButton tb02 = (ToggleButton) this.findViewById(R.id.ToggleButton02);            //获得第二个开关按钮的引用        tb02.setOnCheckedChangeListener(new SecondListener());//        ToggleButton tb03 = (ToggleButton) this.findViewById(R.id.ToggleButton03);            //获得第三个开关按钮的引用        tb03.setOnCheckedChangeListener(new ThirdListener());//    }    class FirstListener implements OnCheckedChangeListener {                                //声明第一个按钮的监听器        @Override        public void onCheckedChanged(CompoundButton buttonView,                            //重写方法                                     boolean isChecked) {            // TODO Auto-generated method stub            mSurfaceView.setBackFlag(!mSurfaceView.isBackFlag());                        //实现功能        }    }    class SecondListener implements OnCheckedChangeListener {                            //声明第二个按钮的监听器        @Override        public void onCheckedChanged(CompoundButton buttonView,                            //重写方法                                     boolean isChecked) {            // TODO Auto-generated method stub            mSurfaceView.setSmoothFlag(!mSurfaceView.isSmoothFlag());                    //实现功能        }    }    class ThirdListener implements OnCheckedChangeListener {                                //声明第三个按钮的监听器        @Override        public void onCheckedChanged(CompoundButton buttonView,                            //重写方法                                     boolean isChecked) {            // TODO Auto-generated method stub            mSurfaceView.setSelfCulling(!mSurfaceView.isSelfCulling());                    //实现功能        }    }    @Override    protected void onPause() {        // TODO Auto-generated method stub        super.onPause();                                                                //继承父类的onPause()方法        mSurfaceView.onPause();                                                            //调用onPause()方法    }    @Override    protected void onResume() {        // TODO Auto-generated method stub        super.onResume();                                                                //继承父类的onResume()方法        mSurfaceView.onResume();                                                        //调用onResume()方法    }}


2.编写文件MySufaceView.java

    * 在创建MySurfaceView的对象的同事设置渲染器和渲染模式

   *  设置背面裁剪、平滑着色、自定义卷绕编制位的方法

   *  定义了触摸回调方法以实现屏幕触控,并在屏幕上滑动而使场景物体旋转的功能。

   *  定义渲染器内部类似以实现图像的渲染、屏幕横竖发生变化时的功能

   *  重写onDrawFrame方法,分别实现背面裁剪、平滑这色功能,并在屏幕发生横竖切换时自动调用

   *  当MySurfaceView创建时呗调用以初始化屏幕背景颜色、绘制模式、是否深度检测等

   

   

package com.scout.eeeeeee;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;    //角度缩放比例    private SceneRenderer myRenderer;                 //场景渲染器    private boolean backFlag=false;                      //是否打开背面剪裁的标志位    private boolean smoothFlag=false;                 //是否打开平面着色的标志位    private boolean selfCulling=false;                //是否采用自定义卷绕顺序的标志位    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);//设置渲染模式为主动渲染    }    public void setBackFlag(boolean flag){             //        this.backFlag=flag;    }    public boolean isBackFlag(){                     //        return backFlag;    }    public void setSmoothFlag(boolean flag){            //        this.smoothFlag=flag;    }    public boolean isSmoothFlag(){                   //        return smoothFlag;    }    public void setSelfCulling(boolean flag){           //        this.selfCulling=flag;    }    public boolean isSelfCulling(){                      //        return selfCulling;    }    //触摸事件回调方法    @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.tp.yAngle+=dx*TOUCH_SCALE_FACTOR;   //设置沿y轴旋转角度                myRenderer.tp.zAngle+=dy*TOUCH_SCALE_FACTOR;   //设置沿z轴旋转角度                requestRender();                        //渲染画面        }        myPreviousY=y;                            //        myPreviousX=x;                            //        return true;    }    private class SceneRenderer  implements GLSurfaceView.Renderer{        suoyinCH tp=new suoyinCH();        public SceneRenderer(){}        @Override        public void onDrawFrame(GL10 gl) {            // TODO Auto-generated method stub            if(backFlag){                gl.glEnable(GL10.GL_CULL_FACE);             //设置为打开背面剪裁            }            else{                gl.glDisable(GL10.GL_CULL_FACE);         //设置为关闭背面剪裁            }            if(smoothFlag){                gl.glShadeModel(GL10.GL_SMOOTH);         //设置着色模型为平滑着色            }            else{                gl.glShadeModel(GL10.GL_FLAT);          //设置着色模型为不平滑着色            }            if(selfCulling){                gl.glFrontFace(GL10.GL_CW);             //设置自定义卷绕顺序为顺时针为正面            }            else{                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);                    //            tp.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, 255, 255, 0);                           //设置屏幕背景色为黑色            gl.glEnable(GL10.GL_DEPTH_TEST);                        //启用深度检测        }}}
 3.编写文件suoyinCH.java , 定义suoyinCH类的构造器来初始化相关数据,这些数据 包括初始化三角形的顶点数据缓冲
   颜色数据缓冲、索引数据缓冲。然后定义应用程序中具体实现场景物体的绘制方法,主要包括启用相关数组、旋转场景
   物体、指定画笔的顶点坐标数据和顶点颜色数据,并用画笔实现绘图功能。
     
package com.scout.eeeeeee;  import java.nio.ByteBuffer;                         //引人相关包  import java.nio.ByteOrder;                      //引人相关包  import java.nio.IntBuffer;                      //引人相关包  import javax.microedition.khronos.opengles.GL10;      //引人相关包  public class suoyinCH {    private IntBuffer myVertexBuffer;        //顶点坐标数据缓冲    private IntBuffer myColorBuffer;         //顶点着色数据缓冲    private ByteBuffer myIndexBuffer;        //顶点索引数据缓冲    int vCount=0;                       //顶点数量    int iCount=0;                       //索引数量    float yAngle=0;                         //绕y轴旋转的角度    float zAngle=0;                         //绕z轴旋转的角度    public suoyinCH(){        vCount=6;                       //一个三角形,3个顶点        final int UNIT_SIZE=10000;          //缩放比例        int []vertices=new int[]{                -8*UNIT_SIZE,10*UNIT_SIZE,0,                -2*UNIT_SIZE,2*UNIT_SIZE,0,                -8*UNIT_SIZE,2*UNIT_SIZE,0,                8*UNIT_SIZE,2*UNIT_SIZE,0,                8*UNIT_SIZE,10*UNIT_SIZE,0,                2*UNIT_SIZE,10*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,                0,0,one,0,                0,0,one,0,                one,0,one,0,                0,0,0,0,                one,0,0,0        };        ByteBuffer cbb=ByteBuffer.allocateDirect(colors.length*4);    //分配的内存块        cbb.order(ByteOrder.nativeOrder());       //设置本地平台的字节顺序        myColorBuffer=cbb.asIntBuffer();      //转换为int型缓冲        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){        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              //顶点数量        );    }}
   
效果图:
 

原创粉丝点击