import java.io.IOException; import java.io.InputStream; import android.opengl.GLSurfaceView; import android.opengl.GLES20; import android.opengl.GLUtils; import android.view.MotionEvent; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; class MySurfaceView extends GLSurfaceView { private final float TOUCH_SCALE_FACTOR = 180.0f/480;//角度缩放比例 private float cameraX=0;//摄像机的位置 private float cameraY=0; private float cameraZ=8; private float targetX=0;//看点 private float targetY=-2; private float targetZ=-15; private float sightDis=30;//摄像机和目标的距离 private float angdegElevation=45;//仰角 private float angdegAzimuth=90;//方位角 private float mPreviousY;//上次的触控位置Y坐标 private float mPreviousX;//上次的触控位置X坐标 private SceneRenderer mRenderer;//场景渲染器 int textureId; //系统分配的纹理id boolean lightFlag=true; //光照旋转的标志位 public MySurfaceView(Context context) { super(context); this.setEGLContextClientVersion(2); //设置使用OPENGL ES2.0 mRenderer = new SceneRenderer(); //创建场景渲染器 setRenderer(mRenderer); //设置渲染器 setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染 } //触摸事件回调方法 @Override public boolean onTouchEvent(MotionEvent e) { float y = e.getY(); float x = e.getX(); switch (e.getAction()) { case MotionEvent.ACTION_MOVE: float dy = y - mPreviousY;//计算触控笔Y位移 float dx = x - mPreviousX;//计算触控笔X位移 angdegAzimuth += dx * TOUCH_SCALE_FACTOR;//设置沿y轴旋转角度 angdegElevation+= dy * TOUCH_SCALE_FACTOR;//设置沿x轴旋转角度 //方位角 if(angdegAzimuth>=360){ angdegAzimuth=0; }else if(angdegAzimuth<=0){ angdegAzimuth=360; } //仰角 if(angdegElevation>=85){ angdegElevation=85; }else if(angdegElevation<=0){ angdegElevation=0; } } mPreviousY = y;//记录触控笔位置 mPreviousX = x;//记录触控笔位置 return true; } private class SceneRenderer implements GLSurfaceView.Renderer { Building building; public void onDrawFrame(GL10 gl) { //清除深度缓冲与颜色缓冲 GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); double angradElevation=Math.toRadians(angdegElevation);//仰角(弧度) double angradAzimuth=Math.toRadians(angdegAzimuth);//方位角 cameraX=(float) (targetX+sightDis*Math.cos(angradElevation)*Math.cos(angradAzimuth)); cameraY=(float) (targetY+sightDis*Math.sin(angradElevation)); cameraZ=(float) (targetZ+sightDis*Math.cos(angradElevation)*Math.sin(angradAzimuth)); MatrixState.setCamera(//设置camera位置 cameraX, //人眼位置的X cameraY, //人眼位置的Y cameraZ, //人眼位置的Z targetX, //人眼球看的点X targetY, //人眼球看的点Y targetZ, //人眼球看的点Z 0, //头的朝向 1, 0 ); //保护现场 MatrixState.pushMatrix(); MatrixState.translate(0, 0, -15); building.drawSelf(textureId); MatrixState.popMatrix(); } public void onSurfaceChanged(GL10 gl, int width, int height) { //设置视窗大小及位置 GLES20.glViewport(0, 0, width, height); //计算GLSurfaceView的宽高比 float ratio= (float) width / height; //调用此方法计算产生透视投影矩阵 MatrixState.setProjectFrustum(-ratio, ratio, -1, 1, 4f, 100); // //调用此方法产生摄像机9参数位置矩阵 // MatrixState.setCamera(0,0,8.0f,0f,0f,0f,0f,1.0f,0.0f); //初始化光源 MatrixState.setLightLocation(10 , 0 , -10); //启动一个线程定时修改灯光的位置 new Thread() { public void run() { float redAngle = 0; while(lightFlag) { //根据角度计算灯光的位置 redAngle=(redAngle+5)%360; float rx=(float) (15*Math.sin(Math.toRadians(redAngle))); float rz=(float) (15*Math.cos(Math.toRadians(redAngle))); MatrixState.setLightLocation(rx, 0, rz); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } public void onSurfaceCreated(GL10 gl, EGLConfig config) { //设置屏幕背景色RGBA GLES20.glClearColor(0.0f,0.0f,0.0f, 1.0f); //启用深度测试 GLES20.glEnable(GLES20.GL_DEPTH_TEST); //设置为打开背面剪裁 GLES20.glEnable(GLES20.GL_CULL_FACE); //初始化变换矩阵 MatrixState.setInitStack(); //加载纹理 textureId=initTexture(R.drawable.white); //创建对象 building=new Building(MySurfaceView.this,0.8f,8,8); } } public int initTexture(int drawableId)//textureId { //生成纹理ID int[] textures = new int[1]; GLES20.glGenTextures ( 1, //产生的纹理id的数量 textures, //纹理id的数组 0 //偏移量 ); int textureId=textures[0]; GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE); //通过输入流加载图片===============begin=================== InputStream is = this.getResources().openRawResource(drawableId); Bitmap bitmapTmp; try { bitmapTmp = BitmapFactory.decodeStream(is); } finally { try { is.close(); } catch(IOException e) { e.printStackTrace(); } } //通过输入流加载图片===============end===================== //实际加载纹理 GLUtils.texImage2D ( GLES20.GL_TEXTURE_2D, //纹理类型,在OpenGL ES中必须为GL10.GL_TEXTURE_2D 0, //纹理的层次,0表示基本图像层,可以理解为直接贴图 bitmapTmp, //纹理图像 0 //纹理边框尺寸 ); bitmapTmp.recycle(); //纹理加载成功后释放图片 return textureId; } }