人人范文网 范文大全

Android 3D相册实验报告

发布时间:2020-03-03 08:40:02 来源:范文大全 收藏本文 下载本文 手机版

中原工学院计算机学院 软件平台开发技术

大作业

专 业: 软件工程 班 级: 软件121 作品名称: 3D相册 姓 名: 辛俊闪 学 号: 201200834101 指导教师: 刘凤华

2015年 6 月 15 日

一、设计目的

奔着让二维的手机照片能够显示出3D的立体效果,让我们的相册更加炫的目的,我初步的想法是开发一个基于android平台的手机相册小应用。

二、作品简介

该应用是基于android开发,将相册置于立体空间中呈现,并且可以通过用手指横向滑动手机屏幕的方式来选择所有浏览的图片,在滑动过程中相册的旋转同时带有惯性因素,使场景效果更自然、更人性化,手指点击一张照片可以进入单独显示对应照片界面,在该界面操作左滑右滑可以切换照片下一张上一张。在浏览完成后,可以按返回键跳转回相册显示。

三、设计思路

3.1 用到的主要技术

本项目开发过程中,用到了OpenGL ES中的图形绘制技术,包括纹理映射技术、物体旋转技术glRotatef()、物体的平移技术glTranslatef(),并且应用到了屏幕触控技术。

3.2 相关技术难点学习

(1)android开发中关于GLSurfaceView简介

SDK 中的 android.opengl.GLSurfaceView 类提供如下功能: 在 OpenGL ES 和 View 系统之间建立联系;

使得 OpenGL ES 可以工作在 Activity 生命周期中; 可选择合适的 frame buffer 像素格式;

创建并管理一个单独的渲染线程,可以实现平滑的动画; 提供 debugging 工具和 API。

GLSurfaceView.Render 接口有三个方法:

onSurfaceCreated():该方法在渲染开始前调用,OpenGL ES 的绘制上下文被重建时也会被调用。当 activity 暂停时绘制上下文会丢失,当 activity 继续时,绘制上下文会被重建。另外,创建长期存在的 OpenGL 资源(如 texture)往往也在这里进行。

onSurfaceChanged():当 surface 的尺寸发生改变时该方法被调用。往往在这里设置 viewport。若你的 camera 是固定的,也可以在这里设置 camera。

onDrawFrame():每帧都通过该方法进行绘制。绘制时通常先调用 glClear 函数来清空 framebuffer,然后在调用 OpenGL ES 的起它的接口进行绘制。

(2)初始化GLSurfaceView

初始化过程其实仅需要你使用setRenderer(Renderer)设置一个渲染(render)。当然,你也可以修改GLSurfaceView一些默认配置。

* setDebugFlags(int) * setEGLConfigChooser(boolean) * setEGLConfigChooser(EGLConfigChooser) * setEGLConfigChooser(int, int, int, int, int, int) * setGLWrapper(GLWrapper)

(3)定制android.view.Surface

GLSurfaceView默认会创建像素格式为PixelFormat.RGB_565的surface。如果需要透明效果,调用 getHolder().setFormat(PixelFormat.TRANSLUCENT)。透明(TRANSLUCENT)的surface的像 素格式都是32位,每个色彩单元都是8位深度,像素格式是设备相关的,这意味着它可能是ARGB、RGBA或其它。

(4)选择EGL配置

Android设备往往支持多种EGL配置,可以使用不同数目的通道(channel),也可以指定每个通道具有不同数目的位(bits)深度。因此, 在渲染器工作之前就应该指定EGL的配置。GLSurfaceView默认EGL配置的像素格式为RGB_656,16位的深度缓存(depth buffer),默认不开启遮罩缓存(stencil buffer)。如果你要选择不同的EGL配置,请使用setEGLConfigChooser方法中的一种。

(5)调试行为

你可以调用调试方法setDebugFlags(int)或setGLWrapper(GLSurfaceView.GLWrapper)来自定义 GLSurfaceView一些行为。在setRenderer方法之前或之后都可以调用调试方法,不过最好是在之前调用,这样它们能立即生效。

(6)设置渲染器

总之,你必须调用setRenderer(GLSurfaceView.Renderer)来注册一个GLSurfaceView.Renderer渲染器。渲染器负责真正的GL渲染工作。

(7)渲染模式

渲染器设定之后,你可以使用setRenderMode(int)指定渲染模式是按需(on demand)还是连续(continuous)。默认是连续渲染。

(8)Activity生命周期

Activity窗口暂停(pause)或恢复(resume)时,GLSurfaceView都会收到通知,此时它的onPause方法和 onResume方法应该被调用。这样做是为了让GLSurfaceView暂停或恢复它的渲染线程,以便它及时释放或重建OpenGL的资源。

(9)事件处理

为了处理事件,一般都是继承GLSurfaceView类并重载它的事件方法。但是由于GLSurfaceView是多线程操作,所以需要一些特殊的处 理。由于渲染器在独立的渲染线程里,你应该使用Java的跨线程机制跟渲染器通讯。queueEvent(Runnable)方法就是一种相对简单的操 作

四、主要实现

4.1Activity类的开发过程

(1)重写onCreate()方法

//设置全屏显示

requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //横屏显示设置

this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); //设置屏幕分辨率

DisplayMetrics dm=new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); mGLSurfaceView=new MySurfaceView(this); mGLSurfaceView.screenHeight=dm.heightPixels; mGLSurfaceView.screenWidth=dm.widthPixels; //获取屏幕焦点并使其可触控显示

mGLSurfaceView.ratio=mGLSurfaceView.screenWidth/mGLSurfaceView.screenHeight; mGLSurfaceView.requestFocus(); mGLSurfaceView.setFocusableInTouchMode(true); (2)重写onResume()方法

//Activity恢复(resume)时,GLSurfaceView都会收到通知,此时它的onResume方法应该被调用。这样做是为了让GLSurfaceView恢复它的渲染线程,以便它及时重建OpenGL的资源。

Constant.threadWork=false; mGLSurfaceView.onPause();

(3)重写onPause()方法

//Activity窗口暂停(pause)时,GLSurfaceView都会收到通知,此时它的onPause方法应该被调用。这样做是为了让GLSurfaceView暂停它的渲染线程,以便它及时释放OpenGL的资源。

Constant.threadWork=true;

mGLSurfaceView.onResume(); 4.2界面实现类的开发过程

(1)界面类的构造器部分

public MySurfaceView(Context context) { super(context); mRenderer = new SceneRenderer(); //创建场景渲染器

setRenderer(mRenderer);

//设置渲染器

setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染连续渲染

//启动一个线程根据当前的角速度旋转场景

threadWork=true; new Thread() { public void run() {

while(threadWork)

{

.....

} } }.start(); } (2)按键单击事件

public boolean onKeyDown(int keyCode, KeyEvent e) { if(keyCode==4)

} {//若按下的是返回键

if(isCheck)

{//若在detail场景中则回主场景

isCheck=false; } else

{//若在主场景中则退出程序

System.exit(0); } } return true; (3)屏幕触控事件回调方法

public boolean onTouchEvent(MotionEvent e) {

if(isCheck) {//若在detail中

float bx = e.getX();//获取触控点X坐标

dbx = bxmPreviousX;//计算X向触控位移

float dy = y - mPreviousY;//计算Y向触控位移

long currTime=System.currentTimeMillis();//获取当前时间戳 单位为毫秒

long timeSpan=(currTime-previousTime)/10;//计算两次触控事件之间的时间差

switch (e.getAction()) { case MotionEvent.ACTION_DOWN: isMove=false; break; case MotionEvent.ACTION_MOVE:

if(Math.abs(dx)>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;i

{

//计算此幅照片的角度

float tempAngle=(i*PHOTO_ANGLE_SPAN+yAngle)%360;

//若角度在270到360范围内则在右边的前面

if(tempAngle>270&&tempAngle

{

al.add(new

CandidataDis(tempAngle-270,tempAngle,i));

}

} //根据与270度的夹角排序,夹角小的排在前面 Collections.sort(al);

//遍历候选列表谁在X范围内谁单独显示

currIndex=-1;

for(CandidataDis cd:al)

{

if(cd.isInXRange(nearX,nearY))

{

currIndex=cd.index;

break;

}

}

}

else

{

ArrayList al=new ArrayList();

for(int i=0;i

{

//计算此幅照片的角度

float tempAngle=(i*PHOTO_ANGLE_SPAN+yAngle)%360; //若角度在180到270范围内则在左边的前面 if(tempAngle>180&&tempAngle

al.add(new CandidataDis(270-tempAngle,tempAngle,i));

}

}

//根据与270度的夹角排序,夹角小的排在前面 Collections.sort(al); //遍历候选列表谁在X范围内谁单独显示

currIndex=-1; for(CandidataDis cd:al) { if(cd.isInXRange(nearX,nearY)) {

currIndex=cd.index;

break; } } }

//若有选中照片,则设置进入detail显示状态

if(currIndex!=-1)

{

isCheck=true;

}

} isMove=false; break; } mPreviousX = x;//记录触控笔位置

mPreviousY = y;//记录触控笔位置

previousTime=currTime;//记录此次时间

return true; } (4)渲染器内部类开发

private cla SceneRenderer implements GLSurfaceView.Renderer { Board tp=new Board(); //用于显示照片的纹理矩形

@Override

public void onDrawFrame(GL10 gl) { ..... } } (5)初始化纹理

public int initTexture(GL10 gl,int drawableId)//textureId

{

.... }

五、作品展示

(1)应用主界面

通过滑动手机屏幕的方式改变照片的呈现角度。

(2)detail界面

通过单击主界面的照片进入detail界面,左右滑动查看上一张下一张。

六、心得体会

一直都很喜欢3D做成的软件,但是对于android的3D开发却从来没有接触过,本来是想着做一个3D游戏的,但是在学习的过程中发现对于一个初学者来说想在短时间内做好一个3D游戏开发是非常困难,于是就选择了一个相对简单的3D相册练练手。

在做这个小应用的过程中也遇到了很多问题,比如说GLSurfaceView的应用问题,渲染器的使用问题,缓冲区的分配回收问题等等,曾经也为了这些新知识头痛了很久,查找了很多网上的资料也专门从图书馆借了几本关于3D开发的书,最后总算是把问题都解决了,虽然不能说完全理解,但是能够灵活运用。

相册作文

相册介绍

同学聚会相册序言

同学聚会相册序言

同学聚会相册序言

毕业相册寄语

大学毕业相册寄语

宝贝百天相册

旅游相册书

大学毕业相册留言

Android 3D相册实验报告
《Android 3D相册实验报告.doc》
将本文的Word文档下载到电脑,方便编辑。
推荐度:
点击下载文档
点击下载本文文档