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 //索引值数据 ); } }
效果入下: