Android3D游戏开发之彩色六边形

今天要为大家讲的是,怎样使用OpenGL绘制迷人的彩色六边形及实现该过程中使用的一些控件(ToggleButton).

下面我们先来看个效果图:

当我们单击该按钮时,触发了按钮事件,在该事件中,我们设置了投影矩阵,这样图像看起来就会变小写,效果如下:

当我们点击图像,移动时,会得到如下效果:

上面效果怎么实现的呢?下面,来分享下,这个开发过程;

1、创建一个Android项目,命名为GLTast01;

2、修该main.xml布局文件,文件具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:id="@+id/main_liner"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
<ToggleButton 
	android:textOff="正交投影"
	android:textOn="透视投影" 
	android:checked="false" 
	android:id="@+id/ToggleButton01" 
	android:layout_width="fill_parent" 
	android:layout_height="wrap_content">
</ToggleButton>
</LinearLayout>

在这里有必要跟大家讲下,ToggleButton组件,该组件有两个属性,分别为:textOff和textOn。这两个分别是什么用的呢?textOn是设置当你选中该组件时显示的文本。而textOff则是当该组件没有被选中时显示的文本。这里不要弄混了。还有就是checked属性。该属性是设置是否处于选中状态。

3、创建Hexagon.java文件,该文件主要封装了,六边形的一些变量,比如顶点个数,颜色值等。都在这里面设置,具体代码如下:

public class Hexagon {
	private IntBuffer   mVertexBuffer;//顶点坐标数据缓冲
    private IntBuffer   mColorBuffer;//顶点着色数据缓冲
    private ByteBuffer  mIndexBuffer;//顶点构建索引数据缓冲
    int vCount=0;//图形顶点数量
    int iCount=0;//索引顶点数量
    public Hexagon(int zOffset){
    	//顶点坐标数据的初始化
        vCount=7;
        final int UNIT_SIZE=10000;
        int vertices[]=new int[]{
        	0*UNIT_SIZE,0*UNIT_SIZE,zOffset*UNIT_SIZE,
        	2*UNIT_SIZE,3*UNIT_SIZE,zOffset*UNIT_SIZE,
        	4*UNIT_SIZE,0*UNIT_SIZE,zOffset*UNIT_SIZE,
        	2*UNIT_SIZE,-3*UNIT_SIZE,zOffset*UNIT_SIZE,
        	-2*UNIT_SIZE,-3*UNIT_SIZE,zOffset*UNIT_SIZE,
        	-4*UNIT_SIZE,0*UNIT_SIZE,zOffset*UNIT_SIZE,
        	-2*UNIT_SIZE,3*UNIT_SIZE,zOffset*UNIT_SIZE
        };
      //创建顶点坐标数据缓冲
        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
        vbb.order(ByteOrder.nativeOrder());//设置字节顺序
        mVertexBuffer = vbb.asIntBuffer();//转换为int型缓冲
        mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
        mVertexBuffer.position(0);//设置缓冲区起始位置
        //顶点着色数据的初始化
        final int one = 65535;
        int colors[]=new int[]//顶点颜色值数组,每个顶点4个色彩值RGBA
        {
        		0,0,one,0,
        		0,one,0,0,
        		0,one,one,0,
        		one,0,0,0,
        		one,0,one,0,
        		one,one,0,0,
        		one,one,one,0
        };
        //创建顶点着色数据缓冲
        ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
        cbb.order(ByteOrder.nativeOrder());//设置字节顺序
        mColorBuffer = cbb.asIntBuffer();//转换为int型缓冲
        mColorBuffer.put(colors);//向缓冲区中放入顶点着色数据
        mColorBuffer.position(0);//设置缓冲区起始位置
        //三角形构造索引数据初始化
        iCount=18;
        byte indices[]=new byte[]{
        	0,2,1,
        	0,3,2,
        	0,4,3,
        	0,5,4,
        	0,6,5,
        	0,1,6
        };
        //创建三角形构造索引数据缓冲
        mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
        mIndexBuffer.put(indices);//向缓冲区中放入三角形构造索引数据
        mIndexBuffer.position(0);//设置缓冲区起始位置
    }
    public void drawSelf(GL10 gl){        
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);//启用顶点坐标数组
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);//启用顶点颜色数组
        gl.glVertexPointer(//为画笔指定顶点坐标数据     
        		3,				//每个顶点的坐标数量为3  xyz 
        		GL10.GL_FIXED,	//顶点坐标值的类型为 GL_FIXED
        		0, 				//连续顶点坐标数据之间的间隔
        		mVertexBuffer	//顶点坐标数据
        );
        gl.glColorPointer(//为画笔指定顶点着色数据     
        		4, 				//设置颜色的组成成分,必须为4—RGBA
        		GL10.GL_FIXED, 	//顶点颜色值的类型为 GL_FIXED
        		0, 				//连续顶点着色数据之间的间隔
        		mColorBuffer	//顶点着色数据
        );
        gl.glDrawElements(//索引法绘制图形
        		GL10.GL_TRIANGLES, 		//以三角形方式填充
        		iCount, 			 	//一共icount/3个三角形,iCount个顶点
        		GL10.GL_UNSIGNED_BYTE, 	//索引值的尺寸
        		mIndexBuffer			//索引值数据
        );
    }
}
4、创建我们得MySurfaceView视图,该类继承了GLSurfaceView,在该类中包含了一个内部类SceneRenderer,用于绘制屏幕,下面来看下该类的代码如下:
public class MySurfaceView extends GLSurfaceView{
	private final float TOUCH_SCALE_FACTOR = 180.0f/320;	//角度缩放比例
           private SceneRenderer mRenderer;			//场景渲染器
	public boolean isPerspective=false;			//投影标志位
	private float mPreviousY;				//上次的触控位置Y坐标
           public float xAngle=0;				//整体绕x轴旋转的角度  
	public MySurfaceView(Context context) {
        super(context);
        mRenderer = new SceneRenderer();			//创建场景渲染器
        setRenderer(mRenderer);				//设置渲染器		
        setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//主动渲染   
    }
	//触摸事件回调方法
    @Override 
    public boolean onTouchEvent(MotionEvent e) {
        float y = e.getY();
        switch (e.getAction()) {				//获取动作
        case MotionEvent.ACTION_MOVE:				//判断是否是滑动
            float dy = y - mPreviousY;				//计算触控笔Y位移
            xAngle+= dy * TOUCH_SCALE_FACTOR;			//设置沿x轴旋转角度
            requestRender();					//重绘画面
        }
        mPreviousY = y;					//作为上一次触点的Y坐标
        return true;
    }
    private class SceneRenderer implements GLSurfaceView.Renderer { 
		Hexagon[] ha=new Hexagon[]{			//六边形数组
			new Hexagon(0),
			new Hexagon(-2),
			new Hexagon(-4),
			new Hexagon(-6),
			new Hexagon(-8),
			new Hexagon(-10),
			new Hexagon(-12),
	    };
    	public SceneRenderer(){}//渲染器构造类
    	@Override
        public void onDrawFrame(GL10 gl) {  
            gl.glMatrixMode(GL10.GL_PROJECTION);//设置当前矩阵为投影矩阵
            gl.glLoadIdentity(); //设置当前矩阵为单位矩阵        
            float ratio = (float) 320/480;//计算透视投影的比例
            if(isPerspective){
                gl.glFrustumf(-ratio, ratio, -1, 1, 1f, 10);//调用此方法计算产生透视投影矩阵
            }
            else{
            	gl.glOrthof(-ratio, ratio, -1, 1, 1, 10);//调用此方法计算产生正交投影矩阵
            }
			gl.glEnable(GL10.GL_CULL_FACE);//设置为打开背面剪裁	
	        gl.glShadeModel(GL10.GL_SMOOTH);    		//设置着色模型为平滑着色       	
        	gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);//清除缓存
            gl.glMatrixMode(GL10.GL_MODELVIEW);			//设置当前矩阵为模式矩阵
            gl.glLoadIdentity();    			 	//设置当前矩阵为单位矩阵
            
            gl.glTranslatef(0, 0f, -1.4f); 			//沿z轴向远处推
            gl.glRotatef(xAngle, 1, 0, 0);			//绕x轴旋转制定角度
            
            for(Hexagon th:ha){
            	th.drawSelf(gl);				//循环绘制六边形数组中的每个六边形
            }
        }
    	@Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
        	gl.glViewport(0, 0, width, height); //设置视窗大小及位置              
        }
    	@Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {    
        	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);			//启用深度测试
        }
    }
}

5、下面就剩下,控制文件MyActivity.java文件了。该文件主要是把MySurfaceView视图添加到main.xml中,并处理一些单击事件,代码如下:

public class MyActivity extends Activity {
	private MySurfaceView mSurfaceView;	//声明MySurfaceView对象
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mSurfaceView = new MySurfaceView(this);	//创建
        mSurfaceView.requestFocus();//获取焦点	//MySurfaceView对象
        mSurfaceView.setFocusableInTouchMode(true);//设置为可触控  
        LinearLayout ll=(LinearLayout)findViewById(R.id.main_liner); //获得布局引用
        ll.addView(mSurfaceView);//在布局中添加MySurfaceView对象
        //控制是否打开背面剪裁的ToggleButton
        ToggleButton tb=(ToggleButton)this.findViewById(R.id.ToggleButton01);//获得按钮引用
        tb.setOnCheckedChangeListener(new MyListener());        //为按钮设置监听器
    }
    class MyListener implements OnCheckedChangeListener{
		@Override
		public void onCheckedChanged(CompoundButton buttonView,
				boolean isChecked) {
			// TODO Auto-generated method stub
				mSurfaceView.isPerspective=!mSurfaceView.isPerspective;//在正交投影与透视投影之间切换
				mSurfaceView.requestRender();//重新绘制
		}
    }
}

6、到此整个项目就已开发完毕。单击项目运行,就会得到以上效果;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值