package wyf.swq;
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
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);
}
@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();
}
}
package wyf.swq;
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;//角度缩放比例,即屏幕宽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接口,渲染器
Triangle tr=new Triangle();
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, 0, 0, 0);//设置屏幕背景色为黑色
gl.glEnable(GL10.GL_DEPTH_TEST);//启用深度检测
}}}
package wyf.swq;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import javax.microedition.khronos.opengles.GL10;
public class Triangle {
private IntBuffer myVertexBuffer;//顶点坐标数据缓冲
private IntBuffer myColorBuffer;//顶点着色数据缓冲
private ByteBuffer myIndexBuffer;//顶点构建的索引数据缓冲
int vCount=0;//顶点数量
int iCount=0;//索引数量
float yAngle=0;//绕y轴旋转的角度
float zAngle=0;//绕z轴旋转的角度
public Triangle(){
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,
1*UNIT_SIZE,5*UNIT_SIZE,0,
-1*UNIT_SIZE,-5*UNIT_SIZE,0,
1*UNIT_SIZE,-5*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=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)//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 //索引值数据
);
}}