OpenGL ES 正交投影与透视投影效果对比的代码实现

MyActivity.java

package lxy.litsoft;

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 {

	private ToggleButton tb01;
	private MySurfaceView mSurfaceView;
	private LinearLayout ll;
	
    /** 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();						//获取焦点
        mSurfaceView.setFocusableInTouchMode(true);			//设置为可触控
        ll = (LinearLayout)findViewById(R.id.main_line);
        ll.addView(mSurfaceView);
        tb01 = (ToggleButton)findViewById(R.id.ToggleButton01);
        tb01.setOnCheckedChangeListener(new MyListener());
    }
    
    private class MyListener implements OnCheckedChangeListener{

		@Override
		public void onCheckedChanged(CompoundButton buttonView,
				boolean isChecked) {
			// TODO Auto-generated method stub
			mSurfaceView.isPerspection = !mSurfaceView.isPerspection;
															//正交投影与透视投影之间切换
			mSurfaceView.requestRender();					//重新绘制
		}
    	
    }
    
	
	@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();				//恢复
	}
}


main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:id="@+id/main_line"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

	<ToggleButton
		android:textOn="透视投影"
		android:textOff="正交投影"
		android:checked="false"
		android:id="@+id/ToggleButton01"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"></ToggleButton>
		
</LinearLayout>


MySurfaceView.java

package lxy.litsoft;

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 myRender;							//场景渲染器
	public boolean isPerspection = false;			//投影方式标志位
	private float mPreviousY;								//上一次的触控位置Y坐标
	public float xAngle = 0;								//整体绕x轴旋转的角度
	
	public MySurfaceView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		myRender = new SceneRenderer();
		this.setRenderer(myRender);							//设置渲染器
		this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//主动渲染
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {		//触摸事件回调方法
		// TODO Auto-generated method stub
		float y = event.getY();								//获得当前触控点Y坐标
		switch(event.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) {
			// TODO Auto-generated method stub
			gl.glEnable(GL10.GL_CULL_FACE);			//设置打开背景剪裁
//			gl.glMatrixMode(GL10.GL_MODELVIEW);		//设置当前矩阵为模式矩阵
			gl.glMatrixMode(GL10.GL_PROJECTION);	//设置当前矩阵为投影矩阵
			gl.glLoadIdentity();					//设置当前矩阵为单位矩阵
			float ratio = (float)320/480;			//透视投影的比例
			if(isPerspection){
				gl.glFrustumf(-ratio, ratio, -1, 1, 1f, 10);	//计算产生透视投影矩阵
			}
			else{
				gl.glOrthof(-ratio, ratio, -1, 1, 1, 10);		//计算产生正交投影矩阵
			}
			gl.glShadeModel(GL10.GL_SMOOTH);		//设置平滑着色
			gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);//清除缓存
			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) {
			// TODO Auto-generated method stub
			gl.glViewport(0, 0, width, height);		//设置视窗大小和位置
		}

		@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);		//启用深度测试
		}
	}
}


Hexagon.java

package lxy.litsoft;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import javax.microedition.khronos.opengles.GL10;

public class Hexagon {
	private IntBuffer myVertexBuffer;		//顶点坐标数据缓冲
	private IntBuffer myColorsBuffer;		//顶点着色数据缓冲
	private ByteBuffer myIndexBuffer;		//顶点构建索引数据缓冲
	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());	//设置字节顺序
		myVertexBuffer = vbb.asIntBuffer();	//转换成int型缓冲
		myVertexBuffer.put(vertices);		//向缓冲中放入数据
		myVertexBuffer.position(0);			//缓冲起始位置
		
		final int one = 65535;				//支持65535色色彩通道
		int []colors = new int[]{			//创建顶点颜色数据数组
			0, 0, one, 0,					//每个顶点色个色彩值RGBA
			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());
		myColorsBuffer = cbb.asIntBuffer();
		myColorsBuffer.put(colors);
		myColorsBuffer.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,
		};
		//创建三角形构造索引数据缓冲
		myIndexBuffer = ByteBuffer.allocateDirect(indices.length);
		myIndexBuffer.put(indices);
		myIndexBuffer.position(0);
	}
	
	public void drawSelf(GL10 gl){		//绘制函数
		gl.glEnableClientState(GL10.GL_COLOR_ARRAY);	//启用顶点坐标数组
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);	//启用顶点颜色数组
		gl.glVertexPointer(		//为画笔指定顶点坐标数据
				3, 				//每个顶点有3个坐标值
				GL10.GL_FIXED, 	//顶点坐标值的类型
				0, 				//连续顶点坐标数据之间的间隔
				myVertexBuffer	//顶点坐标数据
				);
		gl.glColorPointer(		//为画笔指定顶点着色数据
				4, 				//每个颜色有4个颜色值RGBA
				GL10.GL_FIXED, 	//顶点坐标值的类型
				0, 				//连续顶点坐标数据之间的间隔
				myColorsBuffer	//顶点颜色数据
				);
		gl.glDrawElements(				//索引法绘制图像
				GL10.GL_TRIANGLES, 		//绘制模式
				iCount, 				//索引数量
				GL10.GL_UNSIGNED_BYTE, 	//索引值的类型
				myIndexBuffer			//索引值数据
				);
	}
}


效果入下:

OpenGL ES 正交投影与透视投影效果对比的代码实现_第1张图片


OpenGL ES 正交投影与透视投影效果对比的代码实现_第2张图片


你可能感兴趣的:(android,layout,Class,float,Constructor,colors)