使用点线法绘制三角形1.编写布局文件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_liner"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</LinearLayout>
2.编写MyActivity.java
public class MyActivity extends Activity {
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();
}
}
3.编写MySufaceView.java,首先引入相关的类及自定义试图加载图像,然后角度缩放比例,并重写触控事件的回调方法来计算在屏幕上滑动多少距离对应物体旋转多 少度, 最后定义渲染器类,实现其内部的相关方法来渲染场景。
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接口,渲染器
threeCH tr=new threeCH();
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, 255,255, 0);//设置屏幕背景色为黑色
gl.glEnable(GL10.GL_DEPTH_TEST);//启用深度检测
}}}
4.编写threeCH.java,首先在此定义类来绘制图像,然后初始化三角形的顶点数据缓冲和颜色数据缓冲,并创建整数类型的顶点数据数组,最后
定义应用程序中各个实现场景物体的绘制方法。
public class threeCH {
private IntBuffer myVertexBuffer;//顶点坐标数据缓冲
private IntBuffer myColorBuffer;//顶点着色数据缓冲
private ByteBuffer myIndexBuffer;//顶点构建的索引数据缓冲
int vCount=0;//顶点数量
int iCount=0;//索引数量
float yAngle=0;//绕y轴旋转的角度
float zAngle=0;//绕z轴旋转的角度
public threeCH(){
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
};
//创建顶点坐标数据缓存,由于不同平台字节顺序不同,数据单元不是字节的(上面的事整型的缓存),一定要经过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=3;
byte []indices=new byte[]
{
0,1,2
};
//创建三角形构造索引数据缓冲
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//为画笔指定顶点 颜色数据
(
6,
GL10.GL_FIXED,
0,
myColorBuffer
);
gl.glDrawElements//绘制图形
(
GL10.GL_TRIANGLES,//填充模式,这里是以三角形方式填充
iCount, //顶点数量
GL10.GL_UNSIGNED_BYTE,//索引值的类型
myIndexBuffer //索引值数据
);
}}
效果图: