Android中的3D相册

xiaoxiao2021-03-01  40

Android中的3D相册 2011年11月28日    最近学习,工作走很忙,空闲之余,我还学习了一下Android编程和Android上的一些好玩的东西。   这几天,我做了一个Android的3D相册,简单但是听好玩的,算是学习吧。也借鉴了一些别人的东西。这个相册的开发过程中,我用到了OpenGL ES中的图形绘制技术,包括纹理映射技术、物体旋转技术glRotatef()、物体平移技术glTranslatef(),并且用到了屏幕触控技术。   下图是3D相册的效果图,通过滑动手机屏幕可以改变照片呈现的角度。            通过单击操作来查看相册中的某张图片,按返回键会返回相册显示。   3D相册的具体代码已上传到日志,感兴趣的可以查看,有什么不足和待改进的地方请大神们指教。   界面实现类MySufaceView中的代码如下:   package com.bn.ex11f;   import java.io.IOException;   import java.io.InputStream;   import java.util.ArrayList;   import java.util.Collections;   import android.opengl.GLSurfaceView;   import android.opengl.GLUtils;   import android.view.KeyEvent;   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;   import static com.bn.ex11f.Constant.*;   class MySurfaceView extends GLSurfaceView   {   public float screenWidth;//屏幕宽带   public float screenHeight;//屏幕高度   public float ratio;//屏幕宽高比   private final float TOUCH_SCALE_FACTOR = 180.0f/320;//角度缩放比例   private SceneRenderer mRenderer;//场景渲染器   float mPreviousX;//上次按下位置x坐标   float mPreviousY;//上次按下位置y坐标   long previousTime;//上次按下的时间   boolean isCheck=false;//是否点击查看图片   boolean isMove=false;   int[] textureIds=new int[PHOTO_COUNT];//n张照片纹理id数组   float yAngle=0;//总场景旋转角度   int currIndex=0;//当前选中的索引   float yAngleV=0;//总场景角度变化速度   public MySurfaceView(Context context) {   super(context);   mRenderer = new SceneRenderer(); //创建场景渲染器   setRenderer(mRenderer); //设置渲染器   setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染   //启动一个线程根据当前的角速度旋转场景   threadWork=true;   new Thread()   {   public void run()   {   while(threadWork)   {   if(Float.isNaN(yAngle)||Float.isNaN(yAngleV))   {   throw new RuntimeException("yangle "+yAngle+"yAngleV="+yAngleV);   }   //根据角速度计算新的场景旋转角度   yAngle+=yAngleV;   if(Float.isNaN(yAngle))   {   throw new RuntimeException("yangle"+yAngle);   }   //将角度规格化到0~360之间   yAngle=(yAngle+360)60;   if(Float.isNaN(yAngle)||Float.isNaN(yAngleV))   {   throw new RuntimeException("yangle "+yAngle+"yAngleV="+yAngleV);   }   //若当前手指已经抬起则角速度衰减   if(!isMove)   {   yAngleV=yAngleV*0.7f;   }   //若 角速度小于阈值则归0   if(Math.abs(yAngleV)5||Math.abs(dy)>5)   {//触控位移大于阈值则进入移动状态   isMove=true;   }   if(isMove)   {//若在移动状态则计算角度变化速度   if(timeSpan!=0)   {   yAngleV=dx * TOUCH_SCALE_FACTOR/timeSpan;   }   }   break;   case MotionEvent.ACTION_UP:   //若在非移动状态且角度速度为0则看选中的是哪幅照片来显示   if(!isMove&&yAngleV==0)   {   //折算出触控点在NEAR面上的位置   float nearX=(x-screenWidth/2)*ratio/(screenWidth/2);   float nearY=(screenHeight/2-y)/(screenHeight/2);   //先判断点下去的是左边还是右边   if(x>screenWidth/2)   {//右边   ArrayList al=new ArrayList();   for(int i=0;i270&&tempAngle al=new ArrayList();   for(int i=0;i180&&tempAngle纹理矩形   @Override   public void onDrawFrame(GL10 gl)   {   //清除颜色缓存于深度缓存   gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);   //设置当前矩阵为模式矩阵   gl.glMatrixMode(GL10.GL_MODELVIEW);   //设置当前矩阵为单位矩阵   gl.glLoadIdentity();   if(isCheck)   {   //显示某一幅照片,detail状态   gl.glPushMatrix();   gl.glTranslatef(0, 0f, -52f);   gl.glTranslatef(-Board.length-Board.width*0.5f, 0, 0);   tp.drawSelf(gl,textureIds[currIndex]);   gl.glPopMatrix();   }   else   {   //显示照片组,可触控旋转选择   gl.glPushMatrix();   gl.glTranslatef(0, 0f, CENTER_Z);   yAngle=yAngle60;   gl.glRotatef(yAngle, 0, 1, 0);   for(int i=0;i纹理数组,显示每幅照片   gl.glPushMatrix();   gl.glRotatef(i*PHOTO_ANGLE_SPAN, 0, 1, 0);   tp.drawSelf(gl,textureIds);   gl.glPopMatrix();   }   gl.glPopMatrix();   }   }   @Override   public void onSurfaceChanged(GL10 gl, int width, int height) {   //设置视窗大小及位置   gl.glViewport(0, 0, width, height);   //设置当前矩阵为投影矩阵   gl.glMatrixMode(GL10.GL_PROJECTION);   //设置当前矩阵为单位矩阵   gl.glLoadIdentity();   //调用此方法计算产生透视投影矩阵   gl.glFrustumf(-ratio, ratio, -1, 1, NEAR, 100);   //设置为关闭背面剪裁   gl.glDisable(GL10.GL_CULL_FACE);   }   @Override   public void onSurfaceCreated(GL10 gl, EGLConfig config)   {   //关闭抗抖动   gl.glDisable(GL10.GL_DITHER);   //设置特定Hint项目的模式,这里为设置为使用快速模式   gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);   //设置屏幕背景色黑色RGBA   gl.glClearColor(0,0,0,0);   //启用深度测试   gl.glEnable(GL10.GL_DEPTH_TEST);   //加载n幅纹理图   textureIds[0]=initTexture(gl,R.drawable.fj1);//图片1   textureIds[1]=initTexture(gl,R.drawable.fj2);//图片2   textureIds[2]=initTexture(gl,R.drawable.fj3);//图片3   textureIds[3]=initTexture(gl,R.drawable.fj4);//图片4   textureIds[4]=initTexture(gl,R.drawable.fj5);//图片5   textureIds[5]=initTexture(gl,R.drawable.fj6);//图片6   textureIds[6]=initTexture(gl,R.drawable.fj7);//图片7   textureIds[7]=initTexture(gl,R.drawable.fj8);//图片8   textureIds[8]=initTexture(gl,R.drawable.fj9);//图片9   textureIds[9]=initTexture(gl,R.drawable.fj10);//图片10   textureIds[10]=initTexture(gl,R.drawable.fj11);//图片11   textureIds[11]=initTexture(gl,R.drawable.fj12);//图片12   textureIds[12]=initTexture(gl,R.drawable.fj13);//图片13   textureIds[13]=initTexture(gl,R.drawable.fj14);//图片14   }   }   //初始化纹理   public int initTexture(GL10 gl,int drawableId)//textureId   {   //生成纹理ID   int[] textures = new int[1];   gl.glGenTextures(1, textures, 0);   int currTextureId=textures[0];   gl.glBindTexture(GL10.GL_TEXTURE_2D, currTextureId);   gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);   gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);   gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,GL10.GL_CLAMP_TO_EDGE);   gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,GL10.GL_CLAMP_TO_EDGE);   InputStream is = this.getResources().openRawResource(drawableId);   Bitmap bitmapTmp;   try   {   bitmapTmp = BitmapFactory.decodeStream(is);   }   finally   {   try   {   is.close();   }   catch(IOException e)   {   e.printStackTrace();   }   }   GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmapTmp, 0);   bitmapTmp.recycle();   return currTextureId;   }   }   其中,public MySurfaceView (Context context) { }是界面类的构造部分,设置渲染器对象,根据当前的角度旋转场景的线程。 相关资源:android 3d相册源码
转载请注明原文地址: https://www.6miu.com/read-3200131.html

最新回复(0)