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)%360;
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=yAngle%360;
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) { }是界面类的构造部分,设置渲染器对象,根据当前的角度旋转场景的线程。
发表评论
-
关于动态贴图问题不能动态通过texture改变只能重新new 新material
2012-01-20 01:48 1618关于动态贴图问题不能动态通过texture改变只能重新new ... -
Flex学习收藏资料
2012-01-20 01:48 614Flex学习收藏资料 2010年09月16日 1、《Fl ... -
papervision3d学习笔记:图片墙(1)
2012-01-20 01:48 737papervision3d学习笔记:图片墙(1) 2010年 ... -
[AS3] Alternavta3d7.5教程(一)
2012-01-20 01:48 778[AS3] Alternavta3d7.5教程(一 ... -
广州工作2个月!差人的公司可以call我
2012-01-20 01:48 722广州工作2个月!差人的公司可以call我 2011年06月3 ... -
民国小学生的一篇作文
2012-01-19 09:35 684民国小学生的一篇作文 ... -
小学生作文能力的培养
2012-01-19 09:35 495小学生作文能力的培养 ... -
教小学生写作文1
2012-01-19 09:35 966教小学生写作文1 2011年09月09日 一、小学作文教 ... -
小学生期末评语
2012-01-19 09:35 522小学生期末评语 2010年0 ... -
小学生操行评语
2012-01-19 09:35 650小学生操行评语 2011年0 ... -
神机也有软肋 小米手机
2012-01-17 02:10 669神机也有软肋 小米手机 2011年09月11日 小米手机 ... -
3D显卡
2012-01-17 02:10 5413D显卡 2011年08月30日 3D 显卡技术术语目前 ... -
揭开Wayland的面纱(一):X Window的前生今世
2012-01-17 02:10 752揭开Wayland的面纱(一):X W ... -
VLC各模块名称及功能介绍
2012-01-17 02:10 887VLC各模块名称及功能介绍 2010年10月28日 [3 ... -
在flex页面中安装AIR程序
2012-01-15 21:42 820在flex页面中安装AIR程序 2010年07月17日 ... -
SWF与SWF交互
2012-01-15 21:42 581SWF与SWF交互 2010年07月23日 在AS2里S ... -
利用反射调用另一个swf里的代码库
2012-01-15 21:42 578利用反射调用另一个swf里的代码库 2011年02月19日 ... -
AIR笔记 使用HTML
2012-01-15 21:42 670AIR笔记 使用HTML 2011年05月17日 a ... -
Flex Module 终极减肥篇之去掉最后哪一点赘肉
2012-01-15 21:42 596Flex Module 终极减肥篇之 ...
相关推荐
在3D相册中,开发者可能编写了自定义的着色器来实现独特的光照、纹理映射和3D变换效果。 5. **Android资源管理**:项目中会涉及到Android的资源管理,包括图片资源的加载、解码和优化,以适应不同设备的性能需求。...
3D相册的核心在于利用OpenGL ES(OpenGL for Embedded Systems),这是Android系统中的一个图形库,用于处理2D和3D图形。通过OpenGL ES,开发者可以创建复杂的3D场景,包括旋转、缩放和平移等效果,将图片以立体的...
在构建3D相册时,我们需要用到OpenGL ES来绘制和操纵3D物体,如图片卡片。理解顶点坐标、纹理映射以及着色器语言(GLSL)是必要的。 2. **Matrix和MatrixStack**:Android的`android.graphics.Matrix`类提供了2D和...
《Android应用源码3D相册》是一款基于Android平台的3D效果相册应用程序,它展示了如何在Android环境中实现复杂的视觉特效,同时提供了一个学习和借鉴的实例。本项目源码主要采用Java语言编写,是Android开发者提升...
android 3d grally的代码,实现3D相册功能
"Android 3D相册图片滑动+倾斜+放大+倒影处理源码"是一个专门针对这一需求的解决方案,它提供了丰富的3D效果,使得用户在浏览相册时能感受到更加生动、立体的视觉体验。 首先,我们要理解3D相册的核心概念。在...
在Android平台上,开发一款引人入胜的3D相册应用可以极大地提升用户体验。"android 3d相册"源码提供了一个实现此类功能的实例,对于开发者来说,这是一个宝贵的资源,可以用来学习如何在Android上创建具有立体视觉...
超炫的android 3d相册
在这个案例中,开发者创建了一个继承自Android内置Gallery类的自定义View,以便添加3D旋转效果。 2. **矩阵运算**(Matrix):3D画廊的核心在于对图片进行3D旋转,这需要利用Android的Matrix类来完成。Matrix提供了...
为了实现3D相册,你需要: 1. **数据结构与模型加载**:创建一个3D模型来表示相册,这可能涉及到将2D图片映射到3D表面上。使用例如Assimp库来导入3D模型或自己解析3D格式(如OBJ、3DS)。 2. **纹理映射**:将用户...
本项目名为"android 3D相册完美实现",它展示了如何将普通的相册功能提升到一个新的维度,包括立体滑动和透明阴影等特效。 首先,3D相册的核心在于实现图片的三维旋转和平移。这通常涉及到Android的`ImageView`或...
android 供学习 3D 相册开发
这篇文档将深入解析《Android 3D相册图片滑动+倾斜+放大+倒影处理源码》这一项目,这是一个适合计算机专业学生进行毕业设计学习的Android应用源码示例。我们将探讨其中的关键技术点,包括3D效果实现、图片滑动交互、...
通过OpenGL ES,开发者可以创建复杂的3D模型,实现旋转、缩放、平移等交互操作,使相册中的图片能够在3D空间中自由移动和展示。 其次,"verticalCarousel"这一文件名暗示了应用可能采用了一种垂直滚动的轮播样式。...
【Android应用源码3D相册 .zip】这个压缩包文件提供了一个实现3D效果的Android相册应用的源代码,对于想要学习Android图形渲染、动画处理以及自定义控件开发的开发者来说,是一个非常有价值的参考资料。源码中的关键...
这个"Android 3D相册图片滑动+倾斜+放大+倒影处理源码"提供了实现此类高级视觉效果的方法。下面将详细探讨这个源码中的关键知识点。 1. **3D相册效果**:此源码实现了3D翻转效果,让用户在浏览相册时仿佛在操作真实...
在Android开发中,创建一个具有视觉吸引力的3D相册是一项挑战,但通过巧妙地结合各种技术,可以实现像标题中描述的那样——3D相册图片滑动、倾斜、放大以及倒影处理。这个源码项目正是为了解决这个问题,提供了一种...
在本文中,我们将详细探讨该3D相册的实现原理,关键技术和设计模式,以及如何利用这些知识进行自己的项目开发。 1. **3D渲染技术** - OpenGL ES:Android系统中用于3D图形编程的主要API,是OpenGL的一个子集,专为...