最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

Gallery 3D 源码分析汇总

IT圈 admin 35浏览 0评论

2024年2月21日发(作者:成晓凡)

Gallery 3D 分析

文章分类:移动开发

Gallery 3D 分析

是个抽象类。

有5个变量,分别是mX;mY(位置坐标);mWidth;mHeight(宽与高);mHidden (是否隐藏);

一个抽象方法,非抽象子类都有实现。

Java代码

1. public abstract void generate(RenderView view, lists);

其他的可以在子类中重写

Java代码

1. // Returns true if something is animating.

2. public boolean update(RenderView view, float frameInterval) {

3. return false;

4. }

5.

6. public void renderOpaque(RenderView view, GL11 gl) {

7. }

8.

9. public void renderBlended(RenderView view, GL11 gl) {

10. }

11.

12. public boolean onTouchEvent(MotionEvent event) {

13. return false;

14. }

15.

16. // Allows subclasses to further constrain the hit test defined by layer

17. // bounds.

18. public boolean containsPoint(float x, float y) {

19. return true;

20. }

21.

22. protected void onSurfaceCreated(RenderView view, GL11 gl) {

23. }

24.

25. protected void onSizeChanged() {

26. }

27.

28. protected void onHiddenChanged() {

29. }

有好几个类都继承了Layer抽象类:

BackgroundLayer

CanvasLayer

GridLayer

HudLayer

LoadingLayer

RootLayer

其中用到的RenderView类

Java代码

1. final class RenderView extends GLSurfaceView implements er, SensorEventListener

里面有个静态 final 类 Lists

里面定义了updateList,opaqueList,blendedList,hitTestList,systemList等以Layer为对象内容的ArrayList;以及一个清空所有ArrayList的方法Clear().

Gallery 3D 代码分析之概览

文章分类:移动开发

Gallery 3D UI 非常炫,如下图所示:

需要明确的几个问题

伪 2D 还是 3D:

gallery3d 基于 android SDK OpenGL ES 接口开发,使用了 Java API,没有使用 NDK。

图片如何显示:

在 OpenGL ES 中,要显示图片,需要定义一个四边形,然后把图片当作 texture 贴到四边形上。

布局及特效如何实现:

这是 gallery3d 的精华所在,需认真分析。

大数据量图片/cache 如何实现和管理:

gallery3d 有缓冲区的设计,非常不错,需要认真分析。

动画引擎:

简单的讲,动画引擎对外可表现为一个接口:

Java代码

1. float animate(float initVal, float *currentVal, long timeElapsed, long duration)

即,给定初始值(initVal),动画引擎根据逝去的时间(timeElapsed)和动画总时间(duration)计算下一帧对应的值 (currentVal),这个值可能是位置坐标,也可能是一个矩阵 matrix,或者是其它的属性。显示一帧就调用该函数更新actor的属性,各个帧连起来显示就成了动画。

3D坐标与2D坐标的转换:

这个需要仔细分析。

使用缓冲区对象 (GL_OES_vertex_buffer_object)

OpenGL ES 中的顶点数组使得几何图元的显示方便了很多,但是如果每次都要向 OPENGL 发送一大块数据,而这数据其实并没有修改过,那么这传输就是冗余的。所以这里添加了缓冲区对象,将顶点数组存储在服务器端的缓冲区对象中。

gallery3d 使用了缓冲区对象来保存顶点数据。

参考:

Nexus One Gallery on Android

构件图

gallery3d 的基本构件组成及其关系如下所示:

Gallery 3D 代码分析之 GLSurfaceView

文章分类:移动开发

简介

SDK 中的 aceView 类提供如下功能:

在 OpenGL ES 和 View 系统之间建立联系;

使得 OpenGL ES 可以工作在 Activity 生命周期中;

可选择合适的 frame buffer 像素格式;

创建并管理一个单独的渲染线程,可以实现平滑的动画;

提供 debugging 工具和 API。

一个简单的 GLSurfaceView 应用

Java代码

1. package cs;

2.

3. import fig;

4. import 10;

5.

6. import ty;

7. import aceView;

8. import ;

9.

10. public class ClearActivity extends Activity {

11. @Override

12. protected void onCreate(Bundle savedInstanceState) {

13. te(savedInstanceState);

14. mGLView = new GLSurfaceView(this);

15. derer(new ClearRenderer());

16. setContentView(mGLView);

17. }

18.

19. @Override

20. protected void onPause() {

21. e();

22. e();

23. }

24.

25. @Override

26. protected void onResume() {

27. me();

28. me();

29. }

30.

31. private GLSurfaceView mGLView;

32. }

33.

34. class ClearRenderer implements er {

35. public void onSurfaceCreated(GL10 gl, EGLConfig config) {

36. // Do nothing special.

37. }

38.

39. public void onSurfaceChanged(GL10 gl, int w, int h) {

40. port(0, 0, w, h);

41. }

42.

43. public void onDrawFrame(GL10 gl) {

44. r(_COLOR_BUFFER_BIT | _DEPTH_BUFFER_BIT);

45. }

46. }

这个程序功能很简单,每帧绘制时将屏幕设置成黑色。但它是一个完整的工作在 Activity 生命周期中的

OpenGL 程序。当 activity 暂停时,它暂停渲染;当 activity 继续时,它继续渲染。可以将这个程序用作非交互式的 demo 程序。可以在 Frame() 接口中增加 OpenGL 调用做很多的绘制。

接口有三个方法:

* onSurfaceCreated():该方法在渲染开始前调用,OpenGL ES 的绘制上下文被重建时也会被调用。当

activity 暂停时绘制上下文会丢失,当 activity 继续时,绘制上下文会被重建。另外,创建长期存在的

OpenGL 资源(如 texture)往往也在这里进行。

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

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

输入如何处理

若是开发一个交互型的应用(如游戏),通常需要子类化 GLSurfaceView,由此可以获取输入事件。下面有个例子:

Java代码

1. package est;

2.

3. import fig;

4. import 10;

5.

6. import ty;

7. import t;

8. import aceView;

9. import ;

10. import Event;

11.

12. public class ClearActivity extends Activity {

13. @Override

14. protected void onCreate(Bundle savedInstanceState) {

15. te(savedInstanceState);

16. mGLView = new ClearGLSurfaceView(this);

17. setContentView(mGLView);

18. }

19.

20. @Override

21. protected void onPause() {

22. e();

23. e();

24. }

25.

26. @Override

27. protected void onResume() {

28. me();

29. me();

30. }

31.

32. private GLSurfaceView mGLView;

33. }

34.

35. class ClearGLSurfaceView extends GLSurfaceView {

36. public ClearGLSurfaceView(Context context) {

37. super(context);

38. mRenderer = new ClearRenderer();

39. setRenderer(mRenderer);

40. }

41.

42. public boolean onTouchEvent(final MotionEvent event) {

43. queueEvent(new Runnable(){

44. public void run() {

45. or(() / getWidth(),

46. () / getHeight(), 1.0f);

47. }});

48. return true;

49. }

50.

51. ClearRenderer mRenderer;

52. }

53.

54. class ClearRenderer implements er {

55. public void onSurfaceCreated(GL10 gl, EGLConfig config) {

56. // Do nothing special.

57. }

58.

59. public void onSurfaceChanged(GL10 gl, int w, int h) {

60. port(0, 0, w, h);

61. }

62.

63. public void onDrawFrame(GL10 gl) {

64. rColor(mRed, mGreen, mBlue, 1.0f);

65. r(_COLOR_BUFFER_BIT | _DEPTH_BUFFER_BIT);

66. }

67.

68. public void setColor(float r, float g, float b) {

69. mRed = r;

70. mGreen = g;

71. mBlue = b;

72. }

73.

74. private float mRed;

75. private float mGreen;

76. private float mBlue;

77. }

其他的 GLSurfaceView 例子

在 Android SDK 的 API Demo例子程序中还有很多例子:

GLSurfaceView

Kube

Translucent GLSurfaceView:透明背景

Textured Triangle:纹理贴图

Sprite Text:在 texture 上写文本并显示在 3D 场景中

Touch Rotate:旋转 3D 对象

选择一个 Surface

GLSurfaceView 提供了接口可选择 surface 的类型。默认情况下, GLSurfaceView 会使用一个 16 位

RGB frame buffer,带 16 位深度。你也可以根据自己的需要进行选择,比如在 Translucent

GLSurfaceView 例子里,需要一个 Alpha 通道来实现透明。GLSurfaceView 提供了

setEGLSurfaceChooser()方法来选择 surface。

选择一个 RGB (565)的16位 framebuffer,接口如下:

Java代码

1. setEGLConfigChooser(boolean needDepth)

若要定制 red, green, blue, alpha 和 depth,则用如下接口:

Java代码

1. setEGLConfigChooser(int redSize, int greenSize,int blueSize, int alphaSize,int depthSize, int stencilSize)

使用自己实现的 EGLConfigChooser,用如下的接口:

Java代码

1. setEGLConfigChooser(EGLConfigChooser configChooser)

持续型渲染模式&通知型渲染模式

大多数 3D 应用,如游戏、模拟等都是持续型渲染的动画,还有些 3D 应用是反应式的(reactive),它们往往先被动等待,当用户有了动作再做出反应。对于这种应用,持续渲染屏幕是浪费时间。若开发反应式的应用,可以调用下面的方法

Java代码

1. derMode(RENDERMODE_WHEN_DIRTY);

停止持续渲染。当调用

Java代码

1. tRender()

时,程序再渲染屏幕。

调试

ugFlags() 方法可以激活 log 或者错误检测,它们可以帮助调试 OpenGL ES 调用。具体使用时,在 GLSurfaceView 的构造函数中,调用 setRender() 之前调用

ugFlags()就可以了。下面是个例子:

Java代码

1. public ClearGLSurfaceView(Context context) {

2. super(context);

3. // Turn on error-checking and logging

4. setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);

5. mRenderer = new ClearRenderer();

6. setRenderer(mRenderer);

7. }

Gallery3d 代码分析之渲染流程

文章分类:移动开发

RenderView

gallery3d 的渲染从 RenderView 开始。RenderView 从 GLSurfaceView 继承而来,采用了通知型绘制模式,即通过调用 requestRender 通知 RenderView 重绘屏幕。

RenderView 将所有需要绘制的对象都保存一个 Lists中,Lists 包含了5个ArrayList,其定义如下所示:

Java代码

1. public final ArrayList updateList = new ArrayList();

2. public final ArrayList opaqueList = new ArrayList();

3. public final ArrayList blendedList = new ArrayList();

4. public final ArrayList hitTestList = new ArrayList();

5. public final ArrayList systemList = new ArrayList();

RenderView 的 onDrawFrame 接口完成每一帧的绘制操作,绘制时遍历 lists 里每个 list 的每一个成员并调用其 renderXXX 函数。主要代码如下所示:

Java代码

1. ...

2. final Lists lists = sLists;

3.

4. final ArrayList updateList = List;

5. boolean isDirty = false;

6. for (int i = 0, size = (); i != size; ++i) {

7. boolean retVal = (i).update(this, mFrameInterval);

8. isDirty |= retVal;

9. }

10. if (isDirty) {

11. requestRender();

12. }

13.

14. // Clear the depth buffer.

15. r(_DEPTH_BUFFER_BIT);

16. le(_SCISSOR_TEST);

17. sor(0, 0, getWidth(), getHeight());

18.

19. // Run the opaque pass.

20. ble(_BLEND);

21. final ArrayList opaqueList = List;

22. for (int i = () - 1; i >= 0; --i) {

23. final Layer layer = (i);

24. if (!n) {

25. Opaque(this, gl);

26. }

27. }

28.

29. // Run the blended pass.

30. le(_BLEND);

31. final ArrayList blendedList = dList;

32. for (int i = 0, size = (); i != size; ++i) {

33. final Layer layer = (i);

34. if (!n) {

35. Blended(this, gl);

36. }

37. }

38. ble(_BLEND);

lists 的各个 list 里包含的各个 layer 如下所示:

Java代码

1. lists

2. |------------------|-----------------|-----------------|---------------|

3. updateList opaqueList blendedList systemList hitTestList

4. | | | | |

5. GridLayer GridLayer GridLayer GridLayer GridLayer

6. BackgroudLayer BackgroudLayer BackgroudLayer

7. HudLayer HudLayer HudLayer HudLayer

8. TimeBar TimeBar TimeBar

9. PathBar PathBar PathBar

10. XXXButton XXXButton XXXButton

11. XXXMenu XXXMenu XXXMenu

Layer 类提供了 update(...), renderOpaque (...), renderBlended (...) 接口,从上面 RenderView 的

onDrawFrame 绘制代码可以看到,这些接口被调用。

Java代码

1. public abstract class Layer {

2. ... ...

3.

4. public abstract void generate(RenderView view, lists);

5.

6. public boolean update(RenderView view, float frameInterval) {

7. return false;

8. }

9.

10. public void renderOpaque(RenderView view, GL11 gl) {

11. }

12.

13. public void renderBlended(RenderView view, GL11 gl) {

14. }

15. ... ...

16.

17. }

GridLayer

GridLayer 中有个 GridDrawManager,专门负责绘制。

下面是 GridDrawManager 的构造函数,从其参数里可以看出些门道。

Java代码

1. mDrawManager = new GridDrawManager(context, mCamera, mDrawables, sDisplayList, sDisplayItems, sDisplaySlots);

Gallery3D笔记布局及特效

文章分类:移动开发

布局及特效 gallery3d 的精华

一、布局

gallery3d的界面生成和普通的应用程序不一样。普通程序一般一个界面就是一个activity,布局用xml或代码都可以实现,界面切换是activity的切换方式;而gallery3d没有用android的UI系统,而是用opengl画出来的,即界面是在同一个 activity的,如主界面,缩略图界面,单张图片查看界面,标记界面等都属于同一个activity。那么这界面布局不同的界面是如何组合到一起的呢?分析代码,可以把它看成一个状态机:

1、标记模式 public static final int MODE_SELECT = 1;(HudLayer)

包含了主界面标记模式,缩略界面矩阵游览时标记模式、缩略图界面分类游览时标记模式3个界面

2、普通模式 public static final int MODE_NORMAL = 0;(HudLayer)

包含了

Java代码

1. public static final int STATE_MEDIA_SETS = 0;主界面

2. public static final int STATE_GRID_VIEW = 1;缩略图矩阵浏览

3. public static final int STATE_FULL_SCREEN = 2;查看界面

4. public static final int STATE_TIMELINE = 3;缩略图界面分类浏览

有了以上状态分类后,在渲染的时候就能根据些界面的组成来定哪些控件譔隐藏,哪些要显示了。

下面是基本控件:

Java代码

1. yer

2. oundLayer

3. er

4. utton

5. r

6. r

7. enu

8. rLayer

在渲染时,每一帧所有界面上的元素都画了,由于根据上面的状态只把特定窗口的特定元素显示出来,其它窗口中的隐藏,所以不会乱。

Layer是上面控件的基类,上面控件的类也就有了下面两个方法来隐藏不譔显示的界面元素。

Java代码

1. public boolean isHidden() {

2. return mHidden;

3. }

4.

5. public void setHidden(boolean hidden) {

6. if (mHidden != hidden) {

7. mHidden = hidden;

8. onHiddenChanged();

9. }

10. }

下面是根据上面分类来画不同元素所用的标识:

Java代码

1. public static final int PASS_THUMBNAIL_CONTENT = 0;

2. public static final int PASS_FOCUS_CONTENT = 1;

3. public static final int PASS_FRAME = 2;

4. public static final int PASS_PLACEHOLDER = 3;

5. public static final int PASS_FRAME_PLACEHOLDER = 4;

6. public static final int PASS_TEXT_LABEL = 5;

7. public static final int PASS_SELECTION_LABEL = 6;

8. public static final int PASS_VIDEO_LABEL = 7;

9. public static final int PASS_LOCATION_LABEL = 8;

10. public static final int PASS_MEDIASET_SOURCE_LABEL = 9;

Java代码

1. drawDisplayItem(view, gl, displayItem, texture, PASS_THUMBNAIL_CONTENT, placeholder,tedPlaceholderFade); 画缩略图的,注掉此句,前两屏只显示框,第三屏OK

2. drawDisplayItem(view, gl, displayItem, texture, PASS_FOCUS_CONTENT, null, 0.0f);画单张图片的,注掉,第三屏黑屏

3. drawDisplayItem(view, gl, itemDrawn, textureToUse, PASS_FRAME, previousTexture, ratio);画边框的,注掉,前两屏明显没有边框,巨齿明显

4. drawDisplayItem(view, gl, displayItem, textureString, PASS_TEXT_LABEL, null, 0);画文本标签的

5. drawDisplayItem(view, gl, displayItem, textureToUse, PASS_SELECTION_LABEL, null, 0);画选中标记的

6. drawDisplayItem(view, gl, displayItem, videoTexture, PASS_VIDEO_LABEL, null, 0);画视频标记的

7. drawDisplayItem(view, gl, displayItem, locationTexture, PASS_LOCATION_LABEL, null, 0);画位置标记的

8. drawDisplayItem(view, gl, displayItem, locationTexture, PASS_MEDIASET_SOURCE_LABEL,transparentTexture, 0.85f);画源来源图标的(相机或一般文件夹)

二、特效

举如何显示一张图片为例,在图片完全显示出来经过这样一个过程,附近的图片渐小渐出,当前图片渐大渐入,当前图片逐渐变大直到全屏。实现这个特效,要进行很多帧的渲染。就是说并不是只调一次onDrawFrame函数就可以了,要调用多次。可以把这个特效的实现想成一个状态变化的过程,在每一个状态,纹理的显示大小和位置都不同,这也符合动画的基本原理。放大、缩小我们只要改变顶点数据就可以做到,gallery3d也是这样做的,下面是主要代码:

我们知道调用onDrawFrame来渲染,最后调到下面的drawFocusItems函数,

Java代码

1. GridQuad quad = creenGrid[vboIndex];

2. float u = malizedWidth();

3. float v = malizedHeight();

4. float imageWidth = th();

5. float imageHeight = ght();

6. boolean portrait = ((theta / 90) % 2 == 1);

7. if (portrait) {

8. viewAspect = 1.0f / viewAspect;

9. }

10. Quad(viewAspect, u, v, imageWidth, imageHeight);//改变用来贴图片的长方形的大小

11. rays(gl);//绑定新数据,为渲染做准备。

而位置的改变有两种方式,一种是直接以顶点数据中改变,另一种是计算出在3维3个方向的偏移量,再调用gltranslate来做,从代码可以看出采用的是第二种方式来做的,比第一种方式更方便一些。代码:

Java代码

1. slatef(-translateXf, -translateYf, -translateZf);

而这里的3个偏移量的计算是和camera相关的,相关文件为,,过程很复杂,理清楚后再细化吧。

cache管理

下面是cache文件

Java代码

1. /sdcard/Android/data//cache/local-album-cache

2. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-album-cache

3. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-meta-cache

4. ----rwxr-x system sdcard_rw 299877 2010-05-28 07:36 local-album-cachechunk_0

5. d---rwxr-x system sdcard_rw 2010-05-21 09:56 geocoder-cache

6. ----rwxr-x system sdcard_rw 284 2010-05-28 07:36 local-album-cacheindex

7. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-image-thumbs

8. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-video-thumbs

9. d---rwxr-x system sdcard_rw 2010-05-21 09:56 picasa-thumbs

10. ----rwxr-x system sdcard_rw 80 2010-05-28 07:36 local-meta-cachechunk_0

11. ----rwxr-x system sdcard_rw 164 2010-05-28 07:36 local-meta-cacheindex

12. d---rwxr-x system sdcard_rw 2010-05-21 09:56 hires-image-cache

13. ----rwxr-x system sdcard_rw 627629 2010-05-28 07:37 local-image-thumbschunk_0

14. ----rwxr-x system sdcard_rw 3914 2010-05-21 09:56 local-image-thumbsindex

15. ----rwxr-x system sdcard_rw 53343 2010-05-28 07:34 hires-image-cache-49829483_

16. ----rwxr-x system sdcard_rw 237692 2010-05-28 07:33 hires-image-cache3684568484369117627_

17. ----rwxr-x system sdcard_rw 133182 2010-05-28 07:34 hires-image-cache626432_

18. ----rwxr-x system sdcard_rw 83223 2010-05-28 07:34 hires-image-cache4275479623210216146_

19. ----rwxr-x system sdcard_rw 292837 2010-05-28 07:34 hires-image-cache-6463937_

20. ----rwxr-x system sdcard_rw 191377 2010-05-28 07:35 hires-image-cache26313646_

21. ----rwxr-x system sdcard_rw 366905 2010-05-28 07:35 hires-image-cache-3280884_

22. ----rwxr-x system sdcard_rw 323671 2010-05-28 07:35 hires-image-cache57524722_

创建cache的关键代码

Java代码

1. LocalDataSource

2. public static final DiskCache sThumbnailCache = new DiskCache("local-image-thumbs");----------------------local-image-thumbs local-image-thumbschunk_0 local-image-thumbsindex

3. public static final DiskCache sThumbnailCacheVideo = new DiskCache("local-video-thumbs");--------------------local-video-thumbs

4. public static final DiskCache sAlbumCache = new DiskCache("local-album-cache");----------------------local-album-cache local-album-cacheindex

5. public static final DiskCache sMetaAlbumCache = new DiskCache("local-meta-cache");------------------local-meta-cache local-meta-cacheindex

6. getChunkFile --------------local-meta-cachechunk_0 local-album-cachechunk_0

7.

8. ReverseGeocoder:: private static final DiskCache sGeoCache = new DiskCache("geocoder-cache"); -------------------------geocoder-cache

9. PicasaDataSource:: public static final DiskCache sThumbnailCache = new DiskCache("picasa-thumbs");-----------------------------picasa-thumbs

10. UriTexture::writeToCache --------------------------hires-image-cache-xxx_

布局补充:

在画一个界面是,是分类化的,比如第一个界面是显示所有有图片的文件夹,在代码里叫专辑.有这些元素要创建:

文本标签 显示专辑名和专辑内图片或视频数

路径条显示路径名

按纽拍照按纽,放大/缩小

菜单栏全选,取消全选,分享,删除,更多等

图片边框

用于显示图片的矩形

在渲染时一次把一类元素画完,再画另一类.如主界面顺序为:

路径条->按纽->文本标签->图片边框->图片.

具体代码见drawBlendedComponents函数

中写缓存: (ALBUM_CACHE_LOCALE_INDEX, sDummyData,

0);

第一个是 key ,这里是正常数据,当然还有别的 key , key 分别是 -1,-2,-3,-4,-5 。

中,执行上面的写的过程,这里先得明白他的 cache 怎么装的:

它是由很多称之为“片”的文件组成的,形成一个 List 形式: private final

LongSparseArray mChunkFiles = new LongSparseArray();

即 mChuckFiles 就是整个 cache ,里面包括很多 chunk( 即片 ) ,每一个 chunk 大小为 1MB.

当要写入某一个 chunk 里面的时候,先要找到他在 mChuckFiles 里面的索引值即 chunkIndex, 由

(chunkIndex); 来获取这个文件, chunkIndex 怎么来的呢?

private LongSparseArray mIndexMap;

Record record = (key); 这里的 key 就是上面用 put 方法传过来的

ALBUM_CACHE_LOCALE_INDEX 的值(就是 -5 )

int chunkIndex = ;

这么一步步来的。

当然了,第一次都是空的,也就是 get 不到东西 (chunkIndex); 和 Record record =

(key); 都 get 不到,那么第一次就先把东西放进去, (key, new Record

(chunkIndex, , , Disk, timestamp)); (记录 key 值)以及 final

String chunkFilePath = mCacheDirectoryPath + CHUNK_FILE_PREFIX + chunk; chunkFile = new

RandomAccessFile(chunkFilePath, "rw");(chunk, chunkFile); (三句代码来新建一个

chunkfile 并放到 cache 列表里面)

注意: Record 是内部类,只是一个数据集合类而已,相当于文件描述信息。每个 cache (即 chunk )对应一个。

private final LongSparseArray mChunkFiles = new

LongSparseArray(); 中mChunkFiles 最大装 13 个,每个 chunk 是 1M, 所以全部 Cache 是 13M.

Gallery3D中画图时调用glTranslate函数参数赋值过程

文章分类:移动开发

GridDrawManager::drawDisplayItem(RenderView view, GL11 gl, DisplayItem displayItem, Texture

texture, int pass,Texture previousTexture, float mixRatio) 函数有下面几句:

Java代码

1. Vector3f animatedPosition = tedPosition;

2. float translateXf = animatedPosition.x * Scale;

3. float translateYf = animatedPosition.y * Scale;

4. float translateZf = -animatedPosition.z;

调用过程:

->computeVisibleItems(),displayItems[baseIndex + j] = displayItem;Vector3f position = ();

tPositionForSlotIndex(i, camera, layout, deltaAnchorPosition, position);//give

position value itionAndStackIndex(displayItem, position, j, true);//raletive position to

item

->GridLayer, mDrawManager = new GridDrawManager(context, mCamera, mDrawables, sDisplayList,

sDisplayItems, sDisplaySlots);

->GridDrawManager(), mDisplayItems = displayItems;

->drawFocusItems ,DisplayItem[] displayItems = mDisplayItems;

->animatedPosition = tedPosition;

->drawDisplayItem, amAnimatedPosition

->DisplayItem::commit() (mTargetPosition);

-> DisplayItem::set(Vector3f position, int stackIndex, boolean performTransition) mTargetPosition.z =

Java代码

1. public void getPositionForSlotIndex(int slotIndex, int itemWidth, int itemHeight, Vector3f outPosition) {

2. outPosition.x = (slotIndex / mNumRows) * (itemWidth + mSpacingX);

3. outPosition.y = (slotIndex % mNumRows) * (itemHeight + mSpacingY);

4. int maxY = (mNumRows - 1) * (itemHeight + mSpacingY);

5. outPosition.y -= (maxY >> 1);

6. outPosition.z = 0;

7. Log.d("outPosition","slotIndex="+slotIndex+",mNumRows="+mNumRows+",outPosition=("+outPosition.x+","+outPosition.y+","+outPosition.z+")");

8. }

在gallery3d中矩阵是从上到下、从左到右排列的,在主界面时最多有3行,mNumRows=3,在缩略图界面最多4行mNumRows=4,在查看界面只有一行mNumRows=1

上面函数是计算所绘制项位置的,slotIndex / mNumRows得到的是当前处于多少列,slotIndex %

mNumRows得到的是处于多少行。 int maxY = (mNumRows - 1) * (itemHeight + mSpacingY);

outPosition.y -= (maxY >> 1);是为了在y方向对称,想成屏幕中间是分界线,以上的项y为负,线以下的y为正。

deltaAnchorPosition的赋值过程:

Java代码

1. int currentlyVisibleSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);->anchorItem = ef;-> newSlotIndex = i;->if (currentAnchorSlotIndex != D && newAnchorSlotIndex != D) {

2. itionForSlotIndex(newAnchorSlotIndex, itemWidth, itemHeight, deltaAnchorPosition);

3. itionForSlotIndex(currentAnchorSlotIndex, itemWidth, itemHeight, currentSlotPosition);

4. ct(sDeltaAnchorPosition);

5. ct(currentSlotPosition);

6. deltaAnchorPosition.y = 0;

7. deltaAnchorPosition.z = 0;

8. }

MediaFeed::run()

onFeedChanged(, onLayout(newSlotIndex, currentlyVisibleSlotIndex, null);

onLayout, (deltaAnchorPosition);

computeVisibleRange(),(sDeltaAnchorPositionUncommited);

(sDeltaAnchorPosition);

deltaAnchorPosition

Gallery3D各个界面可见范围计算方法

文章分类:移动开发

computeVisibleRange算法分析:

第1步,计算出left,right,bottom,top

第2步,计算出numSlots,并除于2赋值给index

第3步,由index得position,判断position是否在第1步计算出的范围内,是的话,就把第2步计算得出的中间的index赋值给 firstVisibleSlotIndex,lastVisibleSlotIndex,否则,根据滑动窗口算法改变index直到求组所需index

第4步,在while循环中,用第3步得到的firstVisibleSlotIndex求出position,进行和第2步相反的判断,即 position若不在可视范围内,则将相应的index给firstVisibleSlotIndex,否则减 firstVisibleSlotIndex,直到找到最小的可视范围内的index作为firstVisibleSlotIndex。

第5步,在while循环中,用第3步得到的lastVisibleSlotIndex求出position,进行和第2步相反的判断,即 position若不在可视范围内,则将相应的index给lastVisibleSlotIndex,否则增 lastVisibleSlotIndex,直到找到可视范围内的最大的index作为lastVisibleSlotIndex。

第6步,进行firstVisibleSlotIndex,lastVisibleSlotIndex的越界判断。 outBufferedVisibleRange对应的是可见的。outBufferedVisibleRange对应的是0~文件夹的最大数。

computeVisibleItems算法分析:

第1步由slot计算出position,set,当前set不为空且slot在有效范围,创建bestItems,计算sortedIntersection

第2步计算这个slotindex中的图片数目,取这个文件中的前12张图片加到bestItems.

第3步 取bestItems里的图片对应的displayList中的displayItem,并赋值给displayItems数组,同时保存 position,及j,j是bestItems数组中一项,范围是0~12。

第四步 对于每一个文件夹,要在displayItems里有对应的12项,当文件夹内图片不足12时,余下的用null填充。

当绘制缩略图界面时,有些不同

在第1步中,slotindex不再表示文件夹,这时表示具体某一张图片了,所以由slot得到的set里始终只有

1项,且会调 eSortedIntersection(visibleItems, items, MAX_ITEMS_PER_SLOT,

bestItems, sTempHash);给bestItems赋值,这样第2步就在bestItems加项动作不执行。

镜像倒影特效Gallery

文章分类:移动开发

效果展示

本文档将介绍在android上如何实现一个倒影效果的Gallery。

为了达到上图所示的效果,

首先,是需要有一个自定义的gallery,实现了对Gallery的继承,通过重写getChildStaticTransformation方法来控制,每个子view有不同的缩放比例,形成阶梯状的展示。这个gallery是在坤庭的代码基础上实现的,我这里就不再重复介绍。

接下来,gallery中的每个view,都是一个自定义的MirrorView,由它来实现了画原图及画倒影。新的算法解决了性能问题,下面就重点说一下这部分内容:

镜像特效最近还蛮流行的,尤其在HTC 的Sense 介面上,常常都可以见到。大家可以看到,加了个镜像特效后,那感觉就很立体,感觉上好像是这些图片摆立在一个玻璃桌面上。

在Android 上要帮图片加上镜像特效,会不会很麻烦?一点也不麻烦,只要几行代码,就可以搞定。

因此,在开始看答案之前,我会建议你要先有Photoshop 的使用经验。想想,如果用Photoshop 要帮图片加上镜像特效,要如何做?我想一般不外乎是先复制个图片,并将其垂直翻转,接着再对这翻转的图片,加个由灰到黑的渐层mask 即可。

好了,让我们来看一下答案。底下就是帮图片加上镜像特效的程式范例。

Java代码

1. public class MirrorView extends View {

2.

3. Paint m_paint;

4.

5. int m_nShadowH;

6.

7. Drawable m_dw;

8.

9. Bitmap m_bitmap;

10.

11. Matrix mMatrix;

12.

13. int shadowHeight;

14.

15. public MirrorView(Context context, Bitmap bitmap) {

16.

17. super (context);

18.

19. m_bitmap = bitmap;

20.

21. _Init();

22.

23. }

24.

25. private void _Init() {

26.

27. //m_dw = new BitmapDrawable(Resource(getResources(), ));

28.

29. m_dw = new BitmapDrawable(m_bitmap);

30.

31. m_nds(0,0,m_rinsicWidth(),m_rinsicHeight());

32.

33. m_nShadowH = m_rinsicHeight()/1;

34.

35. m_paint = new Paint(_ALIAS_FLAG );

36.

37. LinearGradient lg = new LinearGradient(0, 0, 0, m_nShadowH, 0xB0FFFFFF, 0×00000000, );

38.

39. m_der(lg);

40.

41. m_rmode(new PorterDuffXfermode(LY ));

42.

43. mMatrix = new Matrix();

44.

45. }

46.

47. @Override

48.

49. public void onDraw(Canvas canvas) {

50.

51. super .onDraw(canvas);

52.

53. int nX = 0;

54.

55. int nY = 0;

56.

57. _DrawNormalImg(canvas, nX, nY);

58.

59. _DrawMirror(canvas, nX, nY);

60.

61. }

62.

63. private void _DrawNormalImg(Canvas canvas, int nX, int nY) {

64.

65. (_SAVE_FLAG );

66.

67. ate(nX, nY);

68.

69. m_(canvas);

70.

71. e();

72.

73. }

74.

75. private void _DrawMirror(Canvas canvas, int nX, int nY) {

76.

77. int nW = m_rinsicWidth();

78.

79. int nH = m_rinsicHeight();

80.

81. shadowHeight=nH/2;

82.

83. float [] src={0, nH, nW, nH, nW,nH – m_nShadowH, 0, nH – m_nShadowH};

84.

85. float [] dst={ 0, nH, nW, nH,nW, shadowHeight, 0, shadowHeight };

86.

87. ();

88.

89. yToPoly(src, 0, dst, 0, >> 1);

90.

91. (mMatrix);

92.

93. //draw mirror image

94.

95. (_SAVE_FLAG );

96.

97. (1.0f, -1.0f);

98.

99. ate(nX, -(nY + nH * 2));

100.

101. ct(0, nH, nW, nH – m_nShadowH);

102.

103. m_(canvas);

104.

105. e();

106.

107. //draw mask

108.

109. ();

110.

111. ate(nX, nY + nH);

112.

113. ct(0, 0, nW, m_nShadowH, m_paint);

114.

115. e();

116.

117. e();

118.

119. }

120.

121. }

_DrawMirror() 方法是关键。用Photoshop 要如何做出镜像特效?第一步是先画出垂直翻转的图片。

Android 绘图座标体系预设的原点在左上角,X 轴往右是越来越大的正值,而Y 轴往下,则是越来越大的正值。要画出垂直翻转的图片,其实也就是要垂直翻转整个绘图座标体系。在 Android 中,要如何做?答案就是 (1.0f, -1.0f)。很简单吧,没想到给scale() 函式一个负值,就可以翻转相对应的轴。

在Photoshop 中,做镜像特效的第二步是要对这翻转的图片,加个由灰到黑的渐层mask。

在Android 中,要画渐层色,那就一定得用LinearGradient 这个类别。至于要对背景图加上个mask,就请参考一下Paint 的setXfermode() 函式。 _Init() 这个函式,就是负责生成一个由灰到黑渐层mask 的m_paint 物件。

这个控件我测试过,200张图片加入adapter,在大数据量情况下性能也没有问题。

菱形3D实例

文章分类:移动开发

下面是具体的实现方法:

首先需要建两个array,第一array是用来告诉opengl这个图形有哪些顶点:

画一个三维的坐标轴,然后把你要画的点都算出来,然后放在这个array里。

Java代码

1. float l=1.5f;

2. float[] vertex={

3.

4. 0.0f,l,0.0f,

5.

6. l,0.0f,0.0f,

7.

8. 0.0f,0.0f,l,

9.

10. -l,0.0f,0.0f,

11.

12. 0.0f,0.0f,-l,

13.

14. 0.0f,-l,0.0f

15.

16. };

第二个array是告诉opengl 你要怎样组织这些点:

这里我要画三角形,所以每三个点是一组。

Java代码

1. byte[] edge=

2. {

3. 0,1,2,

4. 1,2,5,

5.

6. 0,2,3,

7. 5,2,3,

8.

9. 0,3,4,

10. 5,3,4,

11.

12. 0,4,1,

13. 5,4,1

14.

15. };

这里的数字,是第一个array的index。

下面你要建立两个Buffer它们是用来存放这两个array的。

Java代码

1. ByteBuffer bb = teDirect(*4);

2. (Order());

3. fbv=tBuffer();

4. (vertex);

5. on(0);

6.

7. ffe=teDirect();

8. (edge);

9. on(0);

这样一个三维的菱形就画好了。

下面你要写一个方法能让它自己把自己画出来!

Java代码

1. public void draw(GL10 gl)

2. {

3. tFace(_CW);

4. exPointer(3, _FLOAT, 0, fbv);

5. Elements(_TRIANGLES, 24, _UNSIGNED_BYTE, ffe);

6.

7. }

先说第一个glFrontFace,物体都有一个正面一个反面,这里告诉opengl显示这个物体按顺时针方向(CW=>

clockwise)

exPointer(3, _FLOAT, 0, fbv);这个方法是把本程序所用的点都传递个opengl。opengl需要知道什么哪?首先是这个点是几维的(opengl 支持2,3,4 维),这里是3所以是三维的,第二个参数告诉opengl,这个点是用什么样类型的变量来储存的,这里是float类型。第三个是步长(stride),这个我还没弄明白,不过我看的例子都为0. 最后把你建立好的三维坐标点都传给opengl

Elements。这个方法是告诉opengl如果要画这个图形,应该怎么画。第一个参数,告诉opengl 用画三角形(这样opengl就以三个点为一组),然后告诉opengl你要用到多少个点(注意这个点是在第二个array里的点数)。第三个是告诉opengl这些点(其实是三维坐标点的reference)的类型。这里是unsigned

byte。最后把你排列点的array 放进去!

第二个大的步骤是创建一个让这个三维坐标运行的环境(Renderer)。

这是一个interface类

首先,在onDrawFrame里,我们告诉本程序这个三维图形的行为:

在做任何事情之前,我们要清空所有以前内存里的东西,这个内存包括:Color 和Depth

r(_COLOR_BUFFER_BIT|_DEPTH_BUFFER_BIT);

然后告诉opengl你要用那个MatrixMode 这个就比较难解释了。

如果写程序只要记住 GL_MODELVIEW 是管理图形的缩放,移动,和转动就行了.(如果那个朋友想理解的更深一点,可以联系我,我可以把我的笔记发过去或者参考

/~powerk/GeneralGraphicsNotes/projection/projection_ )。

slatef(0, 0, -3.0f);

这个方法告诉opengl把图形沿z轴迁移3个unit。这三个值分别是x,y,z轴。

tef(angle,0, 1, 0);

这个方法告诉我们以y为轴。转angle个度数。注意这里的1和0是告诉沿着那个轴转,别的值应该没有意义。

leClientState(_VERTEX_ARRAY);

还记得上边说的opengl分client side和service side吗。这个是告诉opengl如果client side调用draw什么的时候,这个vertex array是可用的。opengl有很多这样的可选项,所以需要告诉opengl,因为我们已经设置了vertex array(我们的第一个array),所以告诉opengl 它是可用的(如果不告诉,opengl会忽略)!

(gl);

这个方法是把图形画出来。

angle++;

为了达到动态的效果,我们让每一个frame 的angle,比上一个多一度。

当显示空间大小发生变化的时候,我们应该告诉opengl一下信息:

Java代码

1. public void onSurfaceChanged(GL10 gl, int width, int height)

2. {

3. port(0, 0, width, height);

4. ixMode(_PROJECTION);

5. Identity();

6. float ratio = (float)width/height;

7. tumf(-ratio, ratio, -1, 1, 1, 10);

8.

9. }

首先是opengl可用的空间:

port(0, 0, width, height);

想象一下用这四个点画出来的四边形,就是opengl所能用的空间。

ixMode(_PROJECTION);

这个matrix是如何把三维坐标转换为二维坐标并把它放在显示器上。

Identity

是告诉opengl初始化这个matrix。

tumf

要把三维的东西用二维显示出来,需要知道几个东西,第一是这个显示平面有多大,你可以看多近和多远。这里的头四个参数,建立了一个四边形,告诉opengl把图形显示在这个范围了。后两个参数告诉opengl这里显示平面里可以显示三维空间里最近和最远的位置。

当这个三维图形建立的是时候,我们可以告诉opengl一些基本参数。这里把能省略的都省略了(其实什么都没有也可以运行!)

Java代码

1. public void onSurfaceCreated(GL10 gl, EGLConfig arg1)

2. {

3. le(_DEPTH_TEST);

4. rColor(0,0, 0, 0);

5. }

le(_DEPTH_TEST); 告诉opengl要检查depth,为什么哪。在三维空间里一个物体A在另一个物体B后面,那么这个A被B挡住里,所以你是看不见的。我们要告诉opengl,我们不想看见被挡住的东西。这个GL_DEPTH_TEST 就是这个功能。

rColor(0,0, 0, 0);

设置这个背景颜色为黑色,应为我们没有给我们的三维图形设置颜色(为了简单),它的初始化颜色是白色。

以下是源代码:

Java代码

1. package ;

2.

3. import ffer;

4. import der;

5. import uffer;

6.

7. import 10;

8.

9. public class TriangleShape

10. {

11.

12. private final float l=1.5f;

13.

14. private FloatBuffer fbv;

15.

16. private ByteBuffer ffe;

17.

18. public TriangleShape()

19.

20. {

21.

22. float[] vertex={

23.

24. 0.0f,l,0.0f,

25.

26. l,0.0f,0.0f,

27.

28. 0.0f,0.0f,l,

29.

30. -l,0.0f,0.0f,

31.

32. 0.0f,0.0f,-l,

33.

34. 0.0f,-l,0.0f

35.

36. };

37.

38.

39. byte[] edge=

40.

41. {

42.

43. 0,1,2,

44.

45. 1,2,5,

46.

47.

48.

49. 0,2,3,

50.

51. 5,2,3,

52.

53.

54.

55. 0,3,4,

56.

57. 5,3,4,

58.

59.

60.

61. 0,4,1,

62.

63. 5,4,1

64.

65. };

66.

67. ByteBuffer bb = teDirect(*4);

68.

69. (Order());

70.

71. fbv=tBuffer();

72.

73. (vertex);

74.

75. on(0);

76.

77.

78.

79.

80. ffe=teDirect();

81.

82. (edge);

83.

84. on(0);

85.

86. }

87.

88. public void draw(GL10 gl)

89.

90. {

91.

92. tFace(_CW);

93.

94. exPointer(3, _FLOAT, 0, fbv);

95.

96. Elements(_TRIANGLES, 24, _UNSIGNED_BYTE, ffe);

97.

98. }

99. }

100.

101.

102. package ;

103.

104. import fig;

105. import 10;

106.

107. import er;

108.

109. public class MySimpleRendered implements Renderer

110. {

111.

112. private int angle=50;

113.

114. private TriangleShape trian;

115.

116. public MySimpleRendered()

117.

118. {

119.

120. trian = new TriangleShape();

121.

122. }

123.

124. @Override

125.

126. public void onDrawFrame(GL10 gl)

127.

128. {

129.

130. // TODO Auto-generated method stub

131.

132. r(_COLOR_BUFFER_BIT|_DEPTH_BUFFER_BIT);

133.

134. ixMode(_MODELVIEW);

135.

136. Identity();

137.

138. slatef(0, 0, -3.0f);

139.

140. tef(angle,0, 1, 0);

141.

142. tef(angle, 1, 0, 0);

143.

144. leClientState(_VERTEX_ARRAY);

145.

146. (gl);

147.

148. angle++;

149.

150. }

151.

152.

153. @Override

154.

155. public void onSurfaceChanged(GL10 gl, int width, int height)

156.

157. {

158.

159. // TODO Auto-generated method stub

160.

161. port(0, 0, width, height);

162.

163. ixMode(_PROJECTION);

164.

165. Identity();

166.

167. float ratio = (float)width/height;

168.

169. tumf(-ratio, ratio, -1, 1, 1, 10);

170.

171.

172.

173. }

174.

175.

176. @Override

177.

178. public void onSurfaceCreated(GL10 gl, EGLConfig arg1)

179.

180. {

181.

182. le(_DEPTH_TEST);

183.

184. rColor(0,0, 0, 0);

185.

186. }

187.

188. }

189. package ;

190.

191. import ty;

192. import ;

193. import aceView;

194. public class Triangle extends Activity {

195. /** Called when the activity is first created. */

196.

197. private GLSurfaceView my_view;

198. @Override

199. public void onCreate(Bundle savedInstanceState) {

200. te(savedInstanceState);

201. setContentView();

202. my_view = new GLSurfaceView(this);

203. my_derer(new MySimpleRendered());

204. tentView(my_view);

205. }

206. public void onResume()

207. {

208.

209. me();

210.

211. my_me();

212. }

213. public void onPause()

214. {

215.

216. e();

217.

218. my_e();

219. }

220. }

3D桌面效果动画类

文章分类:移动开发

Java代码

1. public class CubeAnimation extends Animation implements

2. ionListener {

3. public static final int FACE_LEFT = 0;

4. public static final int FACE_RIGHT = 1;

5. private int mInd;

6. private float mFromDegrees;

7. private float mToDegrees;

8. private float mCenterX;

9. private float mCenterY;

10. private int mHorizonType = 1;

11. private float mHorizonValue = 0.5F;

12. private Camera mCamera;

13. private View mView;

14.

15. public CubeAnimation(int ind) {

16. = ind;

17. egrees = 0.0F;

18. rees = 90.0F;

19. }

20.

21. public CubeAnimation(Context context, AttributeSet attrs) {

22. super(context, attrs);

23. TypedArray a = StyledAttributes(attrs,

24. imation);

25.

26. egrees = 0.0F;

27. rees = 90.0F;

28.

29. Description d = alue(lue(0));

30. onType = ;

31. onValue = ;

32.

33. = (1, 0);

34.

35. boolean t = lean(2, true);

36. if (!(t)) {

37. = (1 - );

38. rees = 0.0F;

39. egrees = 90.0F;

40. }

41. e();

42. }

43.

44. public void onAnimationStart(Animation anim) {

45. ibility(E);

46. }

47.

48. public void onAnimationEnd(Animation anim) {

49. ibility(( == 0) ? 0 : 8);

50. = (1 - );

51. }

52.

53. public void onAnimationRepeat(Animation anim) {

54. }

55.

56. public static void startCubeAnimation(Context context, int id, View view1,

57. View view2) {

58. XmlPullParser parser;

59. try {

60. parser = ources().getAnimation(id);

61. AttributeSet attrs = ibuteSet(parser);

62.

63. int type = ntType();

64. int depth = th();

65. while (true) {

66. while (true) {

67. if ((((type = ()) == 3) && (th() <= depth))

68. || (type == 1))

69. break label172;

70. if (type == 2)

71. break;

72. }

73.

74. String name = e();

75.

76. if (("cube")) {

77. CubeAnimation anim1 = new CubeAnimation(context, attrs);

78. = 1;

79. = view1;

80. mationListener(anim1);

81. CubeAnimation anim2 = new CubeAnimation(context, attrs);

82. = 0;

83. = view2;

84. mationListener(anim2);

85. nimation(anim1);

86. label172: nimation(anim2);

87. }

88. }

89. } catch (ndException ex) {

90. Log.e("CubeAnimation", "NotFoundException");

91. } catch (XmlPullParserException ex) {

92. Log.e("CubeAnimation", "XmlPullParserException");

93. } catch (IOException ex) {

94. Log.e("CubeAnimation", "IOException");

95. }

96. }

97.

98. public void initialize(int width, int height, int parentWidth,

99. int parentHeight) {

100. lize(width, height, parentWidth, parentHeight);

101. rX = resolveSize(1, 0.5F, width, parentWidth);

102. rY = resolveSize(1, 0.5F, height, parentHeight);

103. if (onType == 0) {

104. onValue /= height;

105. }

106.

107. a = new Camera();

108. }

109.

110. protected void applyTransformation(float interpolatedTime, Transformation t) {

111. float fromDegrees = egrees;

112. float degrees = fromDegrees + (rees - fromDegrees)

113. * interpolatedTime;

114.

115. float centerX = rX;

116. float centerY = rY;

117. Camera camera = a;

118.

119. Matrix matrix = rix();

120.

121. ();

122.

123. float b = 0.0F;

124. float e = -onValue;

125.

126. if ( == 0) {

127. degrees += 90.0F;

128. }

129.

130. Y(degrees);

131.

132. rix(matrix);

133. e();

134.

135. if ( == 0) {

136. le(-1.0F, 1.0F, centerX, 0.0F);

137. }

138.

139. float tranX = 320.0F * interpolatedTime;

140.

141. float tranY = -centerY * e + b;

142. nslate(0.0F, centerY * e);

143. anslate(tranX, tranY);

144. }

145.

146. protected static class Description {

147. public int type;

148. public float value;

149.

150. static Description parseValue(TypedValue value) {

151. Description d = new Description();

152. if (value == null) {

153. = 0;

154. = 0.0F;

155. } else {

156. if ( == 6) {

157. = ((( & 0xF) == 1) ? 2 : 1);

158.

159. = xToFloat();

160. return d;

161. }

162. if ( == 4) {

163. = 0;

164. = at();

165. return d;

166. }

167. if (( >= 16) && ( <= 31)) {

168. = 0;

169. = ;

170. return d;

171. }

172. }

173.

174. = 0;

175. = 0.0F;

176.

177. return d;

178. }

179. }

180. }

gallery3d源码学习总结(一)——绘制流程drawFocusItems

显示单张图片相关的输入变量

1. int selectedSlotIndex = mSelectedSlot;

2. GridDrawables drawables = mDrawables;

3. GridCamera camera = mCamera;

4. DisplayItem[] displayItems = mDisplayItems;

5. int firstBufferedVisibleSlot = ;

6. int lastBufferedVisibleSlot = ;

7. boolean isCameraZAnimating = mating();

复制代码

删除当前选中槽位前后2步之外的大缩略图

1. for (int i = firstBufferedVisibleSlot; i <= lastBufferedVisibleSlot; ++i)

{

2. if (selectedSlotIndex != D && (i >=

selectedSlotIndex - 2 && i <= selectedSlotIndex + 2)) {

3. continue;

4. }

5. DisplayItem displayItem = displayItems[(i -

firstBufferedVisibleSlot) * _ITEMS_PER_SLOT];

6. if (displayItem != null) {

7. creennailImage();

8. }

9. }

复制代码

得到当前图片的DispalyItem元素

1. int centerIndexInDrawnArray = (selectedSlotIndex -

firstBufferedVisibleSlot) * _ITEMS_PER_SLOT;

2. if (centerIndexInDrawnArray < 0 || centerIndexInDrawnArray >=

) {

3. return;

4. }

5. DisplayItem centerDisplayItem =

displayItems[centerIndexInDrawnArray];

6. if (centerDisplayItem == null ||

== D) {

7. return;

8. }

复制代码

判断大缩略图是否加载完成

1. boolean focusItemTextureLoaded = false;

2. Texture centerTexture =

eennailImage(text());

3. if (centerTexture != null && ed()) {

4. focusItemTextureLoaded = true;

5. }

复制代码

是否跳过当前图片前一张图片

1. float camX = tX * ;

2. float centerTranslateX = tedPosition.x;

3. final boolean skipPrevious = centerTranslateX < camX;

复制代码

开启opengl混合模式并设置混合函数

1. le(_BLEND);

2. dFunc(_ONE, _ONE);

复制代码

循环遍历前中后三幅图片分别进行“核心绘制处理”

1. for (int i = -1; i <= 1; ++i) {

2. if (slideshowMode && timeElapsedSinceView > 1.0f && i != 0)

3. continue;

4. 。。。

5. }

复制代码

核心绘制处理——输入变量准备

1. if (slideshowMode && timeElapsedSinceView > 1.0f && i != 0)

2. continue;

3. float viewAspect = tRatio;

4. int selectedSlotToUse = selectedSlotIndex + i;

5. if (selectedSlotToUse >= 0 && selectedSlotToUse <=

lastBufferedVisibleSlot) {

6. int indexInDrawnArray = (selectedSlotToUse -

firstBufferedVisibleSlot) * _ITEMS_PER_SLOT;

7. if (indexInDrawnArray < 0 || indexInDrawnArray >=

) {

8. return;

9. }

10. DisplayItem displayItem =

displayItems[indexInDrawnArray];

11. MediaItem item = ef;

12. final Texture thumbnailTexture =

mbnailImage(text(), sThumbnailConfig);

13. Texture texture =

eennailImage(text());

复制代码

在幻灯模式下且超过1秒的切换时间无须显示前后两张图片;

得到视角和当前displayItem、对应媒体对象、小缩略图材质、大缩略图材质。

加载高质量的材质资源

1. if (isCameraZAnimating && (texture == null || !ed())) {

2. texture = thumbnailTexture;

3. ue(0f);

4. eValue(1f, 0.75f,

meTime());

5. }

6. Texture hiRes = (zoomValue != 1.0f && i == 0 &&

iaType() != _TYPE_VIDEO) ? displayItem

7. .getHiResImage(text())

8. : null;

9. if (_DENSITY > 1.0f) {

10. hiRes = texture;

11. }

12. if (i != 0) {

13. iResImage();

14. }

15. if (hiRes != null) {

16. if (!ed()) {

17. (hiRes);

18. (hiRes, true);

19. } else {

20. texture = hiRes;

21. }

22. }

复制代码

如果Camera正在拉远或拉近,且大缩略图材质为空或未加载完成,则选择小缩略图作为材质,将当前图片的“大缩略图混合比例”变量进行初始化(目标值为1秒,渐变时间为0.75秒,渐变开始时间为当前帧时间)。

如果处于放大状态,则加载原图hiRes,加载成功后赋值给材质变量texture;并清除前后图片的原图。

加载材质

1. final Texture fsTexture = texture;

2. if (texture == null || !ed()) {

3. if ((centerTranslateX - camX) < 0.1f) {

4. if (focusItemTextureLoaded && i != 0) {

5. (texture);

6. }

7. if (i == 0) {

8. (texture);

9. (texture, true);

10. }

11. }

12. texture = thumbnailTexture;

13. if (i == 0) {

14. ue(0f);

15. eValue(1f, 0.75f,

meTime());

16. }

17. }

复制代码

保留当前的最佳材质,

如果此材质加载未完成,则继续按优先级加载,并把小缩略图(基本上都已经加载成功了)设置为当前材质;

最佳材质未加载完成之前,替换渐变不会开始。

无须绘制

1. if (ating() || slideshowMode) {

2. if (!slideshowMode && skipPrevious && i == -1) {

3. continue;

4. }

5. if (!skipPrevious && i == 1) {

6. continue;

7. }

8. }

9. int theta = (int) geTheta();

复制代码

如果相机缩放过程中,非幻灯片模式下且镜头中不需要展示前一张的情况下,无须处理前一张;

如果相机缩放或幻灯片绘制过程中,需要展示前一张的情况下,无须处理后一张。

处理前后渐变绘制

1. // If it is in slideshow mode, we draw the previous item in

2. // the next item's position.

3. if (slideshowMode && timeElapsedSinceView < 1.0f &&

timeElapsedSinceView != 0) {

4. if (i == -1) {

5. int nextSlotToUse = selectedSlotToUse + 1;

6. if (nextSlotToUse >= 0 && nextSlotToUse <=

lastBufferedVisibleSlot) {

7. int nextIndexInDrawnArray = (nextSlotToUse

- firstBufferedVisibleSlot)

8. * _ITEMS_PER_SLOT;

9. if (nextIndexInDrawnArray >= 0 &&

nextIndexInDrawnArray < ) {

10. float currentImageTheta =

tedImageTheta;

11. displayItem =

displayItems[nextIndexInDrawnArray];

12. backupImageTheta =

tedImageTheta;

13. tedImageTheta =

currentImageTheta;

14. ha(1.0f -

timeElapsedSinceView);

15. }

16. }

17. } else if (i == 0) {

18. tedImageTheta =

backupImageTheta;

19. ha(timeElapsedSinceView);

20. }

21. }

复制代码

如果处于幻灯片模式中渐变过程中,处理上一幅相片时找到它的下一个DispalyItem,处理本张相片则直接使用当前DispalyItem,为的是同样找到当前DisplayItem,并绑定上一张相片和本张相片,两张相片透明度互补达到渐变的效果。

绘制小大缩略图渐变过程-小缩略图

1. int vboIndex = i + 1;

2. float alpha = ha();

3. float selectedMixRatio =

ue(meTime());

4. if (selectedMixRatio != 1f) {

5. texture = thumbnailTexture;

6. ha(alpha * (1.0f -

selectedMixRatio));

7. }

8. GridQuad quad =

creenGrid[vboIndex];

9. float u = malizedWidth();

10. float v = malizedHeight();

11. float imageWidth = th();

12. float imageHeight = ght();

13. boolean portrait = ((theta / 90) % 2 == 1);

14. if (portrait) {

15. viewAspect = 1.0f / viewAspect;

16. }

17. Quad(viewAspect, u, v, imageWidth,

imageHeight);

18. rays(gl);

19.

20. drawDisplayItem(view, gl, displayItem, texture,

PASS_FOCUS_CONTENT, null, 0.0f);

21. Arrays(gl);

复制代码

绘制小缩略图,请注意:selectedMixRatio表示大缩略图的绘制透明度,小缩略图的自然就是1.0f - selectedMixRatio。

绘制小大缩略图渐变过程-大缩略图

1. if (selectedMixRatio != 0.0f && selectedMixRatio != 1.0f) {

2. texture = fsTexture;

3. if (texture != null) {

4. float drawAlpha = selectedMixRatio;

5. ha(alpha * drawAlpha);

6. u = malizedWidth();

7. v = malizedHeight();

8. imageWidth = th();

9. imageHeight = ght();

10. Quad(viewAspect, u, v,

imageWidth, imageHeight);

11. rays(gl);

12. drawDisplayItem(view, gl, displayItem,

fsTexture, PASS_FOCUS_CONTENT, null, 1.0f);

13. Arrays(gl);

14. }

15. }

复制代码

更新当前图片长宽数据

1. if (i == 0 || slideshowMode) {

2. mCurrentFocusItemWidth = th();

3. mCurrentFocusItemHeight = ght();

4. if (portrait) {

5. // Swap these values.

6. float itemWidth = mCurrentFocusItemWidth;

7. mCurrentFocusItemWidth =

mCurrentFocusItemHeight;

8. mCurrentFocusItemHeight = itemWidth;

9. }

10. }

复制代码

绘制视频元素

1. ha(alpha);

2. if (iaType() ==

_TYPE_VIDEO) {

3. // The play graphic overlay.

4. rays(gl);

5. drawDisplayItem(view, gl, displayItem,

reVideo, PASS_VIDEO_LABEL, null, 0);

6. Arrays(gl);

7. }

复制代码

【此部分讲解已结束】,如您对其他部分感兴趣请回帖说明

gallery3d源码学习总结(二)——绘制流程drawThumbnails

应大家要求,续写了第二部分,如有错误敬请赐教。

此函数控制相册表格页、相片表格页、时间分类表格页的展示,非常重要。以下以相册表格页为例进行讲解,其他的就举一反三吧。

准备输入参数

1. final GridDrawables drawables = mDrawables;

2. final DisplayList displayList = mDisplayList;

3. final DisplayItem[] displayItems = mDisplayItems;

4.

5. final int firstBufferedVisibleSlot = ;

6. final int lastBufferedVisibleSlot = ;

7. final int firstVisibleSlot = ;

8. final int lastVisibleSlot = ;

9.

10. final int selectedSlotIndex = mSelectedSlot;

11. final int currentFocusSlot = mCurrentFocusSlot;

12. final int currentScaleSlot = mCurrentScaleSlot;

13.

14. final DisplayItem[] itemsDrawn = mItemsDrawn;

15. itemsDrawn[0] = null; // No items drawn yet.

16. int drawnCounter = 0;

17.

18. final GridQuad grid = ;

19. rays(gl);

20.

21. int numTexturesQueued = 0;

22. Context context = text();

复制代码

通过之前的computeVisibleItems(),已得到显示元素列表,显示元素缓冲数组,缓存可见槽位的范围,可见槽位的范围;得到当前选中的槽位索引selectedSlotIndex、当前焦点槽位索引currentFocusSlot和缩放槽位索引currentScaleSlot。

已画元素的缓存数组,绑定表格类材质。selectedSlotIndex、currentFocusSlot、currentScaleSlot在不进行任何操作时都是-1.

遍历缓存可见槽位范围中的每一个槽位

1. for (int itrSlotIndex = firstBufferedVisibleSlot; itrSlotIndex <=

lastBufferedVisibleSlot; ++itrSlotIndex) {

2. int index = itrSlotIndex;

3. ...

4. }

复制代码

即遍历每个相册,index是相册序号。

为每个相册分别计算“需要绘制“的最开头那张照片的序号

1. boolean priority = !(index < firstVisibleSlot || index >

lastVisibleSlot);

2. int startSlotIndex = 0;

3. final int maxDisplayedItemsPerSlot = (index ==

mCurrentScaleSlot) ? _DISPLAYED_ITEMS_PER_FOCUSED_SLOT

4. : _DISPLAYED_ITEMS_PER_SLOT;

5. if (index != mCurrentScaleSlot) {

6. for (int j = maxDisplayedItemsPerSlot - 1; j >= 0; --j) {

7. DisplayItem displayItem = displayItems[(index -

firstBufferedVisibleSlot) * _ITEMS_PER_SLOT + j];

8. if (displayItem == null) {

9. continue;

10. } else {

11. Texture texture =

mbnailImage(context, sThumbnailConfig);

12. if (texture != null && ed() == false)

{

13. startSlotIndex = j;

14. break;

15. }

16. }

17. }

18. }

复制代码

priority表示当前槽位在[firstVisibleSlot,lastVisibleSlot]范围中,则为高优先级,可见槽位上的自然是最高优先级喽;

maxDisplayedItemsPerSlot表示每个槽位中最多的显示项目,即每个相册封面的最大缩略图数,此处为4;

startSlotIndex是当前帧每个相册中“需要绘制“的最开头那张照片的序号(取值在0-3之间),注意“需要绘制“的最开头那张照片往往不是相册中的第一张照片,帧动画开始时它通常是第四张照片(第四张被依次压在321张照片下面嘛,因此绘制加载材质都要按照第四张向首张的次序),随着动画和材质逐步加载,它慢慢变为第三张、第二张、第一张。

从第四张向第一张加载材质

1. // Prime the textures in the reverse order.

2. for (int j = 0; j < maxDisplayedItemsPerSlot; ++j) {

3. int stackIndex = (index == mCurrentScaleSlot) ?

maxDisplayedItemsPerSlot - j - 1 : j;

4. DisplayItem displayItem = displayItems[(index -

firstBufferedVisibleSlot) * _ITEMS_PER_SLOT

5. + stackIndex];

6. if (displayItem == null) {

7. continue;

8. } else {

9. ntSlotIndex = index;

10. if (selectedSlotIndex != D && (index <=

selectedSlotIndex - 2 || index >= selectedSlotIndex + 2)) {

11. creennailImage();

12. }

13.

14. Texture texture =

mbnailImage(context, sThumbnailConfig);

15. if (index == mCurrentScaleSlot && texture != null

&& !ed()) {

16. (texture, true);

17. (texture);

18. } else if (texture != null && !ed() /*&&

numTexturesQueued <= 6*/) {

19. /*boolean isCached = ed();*/

2024年2月21日发(作者:成晓凡)

Gallery 3D 分析

文章分类:移动开发

Gallery 3D 分析

是个抽象类。

有5个变量,分别是mX;mY(位置坐标);mWidth;mHeight(宽与高);mHidden (是否隐藏);

一个抽象方法,非抽象子类都有实现。

Java代码

1. public abstract void generate(RenderView view, lists);

其他的可以在子类中重写

Java代码

1. // Returns true if something is animating.

2. public boolean update(RenderView view, float frameInterval) {

3. return false;

4. }

5.

6. public void renderOpaque(RenderView view, GL11 gl) {

7. }

8.

9. public void renderBlended(RenderView view, GL11 gl) {

10. }

11.

12. public boolean onTouchEvent(MotionEvent event) {

13. return false;

14. }

15.

16. // Allows subclasses to further constrain the hit test defined by layer

17. // bounds.

18. public boolean containsPoint(float x, float y) {

19. return true;

20. }

21.

22. protected void onSurfaceCreated(RenderView view, GL11 gl) {

23. }

24.

25. protected void onSizeChanged() {

26. }

27.

28. protected void onHiddenChanged() {

29. }

有好几个类都继承了Layer抽象类:

BackgroundLayer

CanvasLayer

GridLayer

HudLayer

LoadingLayer

RootLayer

其中用到的RenderView类

Java代码

1. final class RenderView extends GLSurfaceView implements er, SensorEventListener

里面有个静态 final 类 Lists

里面定义了updateList,opaqueList,blendedList,hitTestList,systemList等以Layer为对象内容的ArrayList;以及一个清空所有ArrayList的方法Clear().

Gallery 3D 代码分析之概览

文章分类:移动开发

Gallery 3D UI 非常炫,如下图所示:

需要明确的几个问题

伪 2D 还是 3D:

gallery3d 基于 android SDK OpenGL ES 接口开发,使用了 Java API,没有使用 NDK。

图片如何显示:

在 OpenGL ES 中,要显示图片,需要定义一个四边形,然后把图片当作 texture 贴到四边形上。

布局及特效如何实现:

这是 gallery3d 的精华所在,需认真分析。

大数据量图片/cache 如何实现和管理:

gallery3d 有缓冲区的设计,非常不错,需要认真分析。

动画引擎:

简单的讲,动画引擎对外可表现为一个接口:

Java代码

1. float animate(float initVal, float *currentVal, long timeElapsed, long duration)

即,给定初始值(initVal),动画引擎根据逝去的时间(timeElapsed)和动画总时间(duration)计算下一帧对应的值 (currentVal),这个值可能是位置坐标,也可能是一个矩阵 matrix,或者是其它的属性。显示一帧就调用该函数更新actor的属性,各个帧连起来显示就成了动画。

3D坐标与2D坐标的转换:

这个需要仔细分析。

使用缓冲区对象 (GL_OES_vertex_buffer_object)

OpenGL ES 中的顶点数组使得几何图元的显示方便了很多,但是如果每次都要向 OPENGL 发送一大块数据,而这数据其实并没有修改过,那么这传输就是冗余的。所以这里添加了缓冲区对象,将顶点数组存储在服务器端的缓冲区对象中。

gallery3d 使用了缓冲区对象来保存顶点数据。

参考:

Nexus One Gallery on Android

构件图

gallery3d 的基本构件组成及其关系如下所示:

Gallery 3D 代码分析之 GLSurfaceView

文章分类:移动开发

简介

SDK 中的 aceView 类提供如下功能:

在 OpenGL ES 和 View 系统之间建立联系;

使得 OpenGL ES 可以工作在 Activity 生命周期中;

可选择合适的 frame buffer 像素格式;

创建并管理一个单独的渲染线程,可以实现平滑的动画;

提供 debugging 工具和 API。

一个简单的 GLSurfaceView 应用

Java代码

1. package cs;

2.

3. import fig;

4. import 10;

5.

6. import ty;

7. import aceView;

8. import ;

9.

10. public class ClearActivity extends Activity {

11. @Override

12. protected void onCreate(Bundle savedInstanceState) {

13. te(savedInstanceState);

14. mGLView = new GLSurfaceView(this);

15. derer(new ClearRenderer());

16. setContentView(mGLView);

17. }

18.

19. @Override

20. protected void onPause() {

21. e();

22. e();

23. }

24.

25. @Override

26. protected void onResume() {

27. me();

28. me();

29. }

30.

31. private GLSurfaceView mGLView;

32. }

33.

34. class ClearRenderer implements er {

35. public void onSurfaceCreated(GL10 gl, EGLConfig config) {

36. // Do nothing special.

37. }

38.

39. public void onSurfaceChanged(GL10 gl, int w, int h) {

40. port(0, 0, w, h);

41. }

42.

43. public void onDrawFrame(GL10 gl) {

44. r(_COLOR_BUFFER_BIT | _DEPTH_BUFFER_BIT);

45. }

46. }

这个程序功能很简单,每帧绘制时将屏幕设置成黑色。但它是一个完整的工作在 Activity 生命周期中的

OpenGL 程序。当 activity 暂停时,它暂停渲染;当 activity 继续时,它继续渲染。可以将这个程序用作非交互式的 demo 程序。可以在 Frame() 接口中增加 OpenGL 调用做很多的绘制。

接口有三个方法:

* onSurfaceCreated():该方法在渲染开始前调用,OpenGL ES 的绘制上下文被重建时也会被调用。当

activity 暂停时绘制上下文会丢失,当 activity 继续时,绘制上下文会被重建。另外,创建长期存在的

OpenGL 资源(如 texture)往往也在这里进行。

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

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

输入如何处理

若是开发一个交互型的应用(如游戏),通常需要子类化 GLSurfaceView,由此可以获取输入事件。下面有个例子:

Java代码

1. package est;

2.

3. import fig;

4. import 10;

5.

6. import ty;

7. import t;

8. import aceView;

9. import ;

10. import Event;

11.

12. public class ClearActivity extends Activity {

13. @Override

14. protected void onCreate(Bundle savedInstanceState) {

15. te(savedInstanceState);

16. mGLView = new ClearGLSurfaceView(this);

17. setContentView(mGLView);

18. }

19.

20. @Override

21. protected void onPause() {

22. e();

23. e();

24. }

25.

26. @Override

27. protected void onResume() {

28. me();

29. me();

30. }

31.

32. private GLSurfaceView mGLView;

33. }

34.

35. class ClearGLSurfaceView extends GLSurfaceView {

36. public ClearGLSurfaceView(Context context) {

37. super(context);

38. mRenderer = new ClearRenderer();

39. setRenderer(mRenderer);

40. }

41.

42. public boolean onTouchEvent(final MotionEvent event) {

43. queueEvent(new Runnable(){

44. public void run() {

45. or(() / getWidth(),

46. () / getHeight(), 1.0f);

47. }});

48. return true;

49. }

50.

51. ClearRenderer mRenderer;

52. }

53.

54. class ClearRenderer implements er {

55. public void onSurfaceCreated(GL10 gl, EGLConfig config) {

56. // Do nothing special.

57. }

58.

59. public void onSurfaceChanged(GL10 gl, int w, int h) {

60. port(0, 0, w, h);

61. }

62.

63. public void onDrawFrame(GL10 gl) {

64. rColor(mRed, mGreen, mBlue, 1.0f);

65. r(_COLOR_BUFFER_BIT | _DEPTH_BUFFER_BIT);

66. }

67.

68. public void setColor(float r, float g, float b) {

69. mRed = r;

70. mGreen = g;

71. mBlue = b;

72. }

73.

74. private float mRed;

75. private float mGreen;

76. private float mBlue;

77. }

其他的 GLSurfaceView 例子

在 Android SDK 的 API Demo例子程序中还有很多例子:

GLSurfaceView

Kube

Translucent GLSurfaceView:透明背景

Textured Triangle:纹理贴图

Sprite Text:在 texture 上写文本并显示在 3D 场景中

Touch Rotate:旋转 3D 对象

选择一个 Surface

GLSurfaceView 提供了接口可选择 surface 的类型。默认情况下, GLSurfaceView 会使用一个 16 位

RGB frame buffer,带 16 位深度。你也可以根据自己的需要进行选择,比如在 Translucent

GLSurfaceView 例子里,需要一个 Alpha 通道来实现透明。GLSurfaceView 提供了

setEGLSurfaceChooser()方法来选择 surface。

选择一个 RGB (565)的16位 framebuffer,接口如下:

Java代码

1. setEGLConfigChooser(boolean needDepth)

若要定制 red, green, blue, alpha 和 depth,则用如下接口:

Java代码

1. setEGLConfigChooser(int redSize, int greenSize,int blueSize, int alphaSize,int depthSize, int stencilSize)

使用自己实现的 EGLConfigChooser,用如下的接口:

Java代码

1. setEGLConfigChooser(EGLConfigChooser configChooser)

持续型渲染模式&通知型渲染模式

大多数 3D 应用,如游戏、模拟等都是持续型渲染的动画,还有些 3D 应用是反应式的(reactive),它们往往先被动等待,当用户有了动作再做出反应。对于这种应用,持续渲染屏幕是浪费时间。若开发反应式的应用,可以调用下面的方法

Java代码

1. derMode(RENDERMODE_WHEN_DIRTY);

停止持续渲染。当调用

Java代码

1. tRender()

时,程序再渲染屏幕。

调试

ugFlags() 方法可以激活 log 或者错误检测,它们可以帮助调试 OpenGL ES 调用。具体使用时,在 GLSurfaceView 的构造函数中,调用 setRender() 之前调用

ugFlags()就可以了。下面是个例子:

Java代码

1. public ClearGLSurfaceView(Context context) {

2. super(context);

3. // Turn on error-checking and logging

4. setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);

5. mRenderer = new ClearRenderer();

6. setRenderer(mRenderer);

7. }

Gallery3d 代码分析之渲染流程

文章分类:移动开发

RenderView

gallery3d 的渲染从 RenderView 开始。RenderView 从 GLSurfaceView 继承而来,采用了通知型绘制模式,即通过调用 requestRender 通知 RenderView 重绘屏幕。

RenderView 将所有需要绘制的对象都保存一个 Lists中,Lists 包含了5个ArrayList,其定义如下所示:

Java代码

1. public final ArrayList updateList = new ArrayList();

2. public final ArrayList opaqueList = new ArrayList();

3. public final ArrayList blendedList = new ArrayList();

4. public final ArrayList hitTestList = new ArrayList();

5. public final ArrayList systemList = new ArrayList();

RenderView 的 onDrawFrame 接口完成每一帧的绘制操作,绘制时遍历 lists 里每个 list 的每一个成员并调用其 renderXXX 函数。主要代码如下所示:

Java代码

1. ...

2. final Lists lists = sLists;

3.

4. final ArrayList updateList = List;

5. boolean isDirty = false;

6. for (int i = 0, size = (); i != size; ++i) {

7. boolean retVal = (i).update(this, mFrameInterval);

8. isDirty |= retVal;

9. }

10. if (isDirty) {

11. requestRender();

12. }

13.

14. // Clear the depth buffer.

15. r(_DEPTH_BUFFER_BIT);

16. le(_SCISSOR_TEST);

17. sor(0, 0, getWidth(), getHeight());

18.

19. // Run the opaque pass.

20. ble(_BLEND);

21. final ArrayList opaqueList = List;

22. for (int i = () - 1; i >= 0; --i) {

23. final Layer layer = (i);

24. if (!n) {

25. Opaque(this, gl);

26. }

27. }

28.

29. // Run the blended pass.

30. le(_BLEND);

31. final ArrayList blendedList = dList;

32. for (int i = 0, size = (); i != size; ++i) {

33. final Layer layer = (i);

34. if (!n) {

35. Blended(this, gl);

36. }

37. }

38. ble(_BLEND);

lists 的各个 list 里包含的各个 layer 如下所示:

Java代码

1. lists

2. |------------------|-----------------|-----------------|---------------|

3. updateList opaqueList blendedList systemList hitTestList

4. | | | | |

5. GridLayer GridLayer GridLayer GridLayer GridLayer

6. BackgroudLayer BackgroudLayer BackgroudLayer

7. HudLayer HudLayer HudLayer HudLayer

8. TimeBar TimeBar TimeBar

9. PathBar PathBar PathBar

10. XXXButton XXXButton XXXButton

11. XXXMenu XXXMenu XXXMenu

Layer 类提供了 update(...), renderOpaque (...), renderBlended (...) 接口,从上面 RenderView 的

onDrawFrame 绘制代码可以看到,这些接口被调用。

Java代码

1. public abstract class Layer {

2. ... ...

3.

4. public abstract void generate(RenderView view, lists);

5.

6. public boolean update(RenderView view, float frameInterval) {

7. return false;

8. }

9.

10. public void renderOpaque(RenderView view, GL11 gl) {

11. }

12.

13. public void renderBlended(RenderView view, GL11 gl) {

14. }

15. ... ...

16.

17. }

GridLayer

GridLayer 中有个 GridDrawManager,专门负责绘制。

下面是 GridDrawManager 的构造函数,从其参数里可以看出些门道。

Java代码

1. mDrawManager = new GridDrawManager(context, mCamera, mDrawables, sDisplayList, sDisplayItems, sDisplaySlots);

Gallery3D笔记布局及特效

文章分类:移动开发

布局及特效 gallery3d 的精华

一、布局

gallery3d的界面生成和普通的应用程序不一样。普通程序一般一个界面就是一个activity,布局用xml或代码都可以实现,界面切换是activity的切换方式;而gallery3d没有用android的UI系统,而是用opengl画出来的,即界面是在同一个 activity的,如主界面,缩略图界面,单张图片查看界面,标记界面等都属于同一个activity。那么这界面布局不同的界面是如何组合到一起的呢?分析代码,可以把它看成一个状态机:

1、标记模式 public static final int MODE_SELECT = 1;(HudLayer)

包含了主界面标记模式,缩略界面矩阵游览时标记模式、缩略图界面分类游览时标记模式3个界面

2、普通模式 public static final int MODE_NORMAL = 0;(HudLayer)

包含了

Java代码

1. public static final int STATE_MEDIA_SETS = 0;主界面

2. public static final int STATE_GRID_VIEW = 1;缩略图矩阵浏览

3. public static final int STATE_FULL_SCREEN = 2;查看界面

4. public static final int STATE_TIMELINE = 3;缩略图界面分类浏览

有了以上状态分类后,在渲染的时候就能根据些界面的组成来定哪些控件譔隐藏,哪些要显示了。

下面是基本控件:

Java代码

1. yer

2. oundLayer

3. er

4. utton

5. r

6. r

7. enu

8. rLayer

在渲染时,每一帧所有界面上的元素都画了,由于根据上面的状态只把特定窗口的特定元素显示出来,其它窗口中的隐藏,所以不会乱。

Layer是上面控件的基类,上面控件的类也就有了下面两个方法来隐藏不譔显示的界面元素。

Java代码

1. public boolean isHidden() {

2. return mHidden;

3. }

4.

5. public void setHidden(boolean hidden) {

6. if (mHidden != hidden) {

7. mHidden = hidden;

8. onHiddenChanged();

9. }

10. }

下面是根据上面分类来画不同元素所用的标识:

Java代码

1. public static final int PASS_THUMBNAIL_CONTENT = 0;

2. public static final int PASS_FOCUS_CONTENT = 1;

3. public static final int PASS_FRAME = 2;

4. public static final int PASS_PLACEHOLDER = 3;

5. public static final int PASS_FRAME_PLACEHOLDER = 4;

6. public static final int PASS_TEXT_LABEL = 5;

7. public static final int PASS_SELECTION_LABEL = 6;

8. public static final int PASS_VIDEO_LABEL = 7;

9. public static final int PASS_LOCATION_LABEL = 8;

10. public static final int PASS_MEDIASET_SOURCE_LABEL = 9;

Java代码

1. drawDisplayItem(view, gl, displayItem, texture, PASS_THUMBNAIL_CONTENT, placeholder,tedPlaceholderFade); 画缩略图的,注掉此句,前两屏只显示框,第三屏OK

2. drawDisplayItem(view, gl, displayItem, texture, PASS_FOCUS_CONTENT, null, 0.0f);画单张图片的,注掉,第三屏黑屏

3. drawDisplayItem(view, gl, itemDrawn, textureToUse, PASS_FRAME, previousTexture, ratio);画边框的,注掉,前两屏明显没有边框,巨齿明显

4. drawDisplayItem(view, gl, displayItem, textureString, PASS_TEXT_LABEL, null, 0);画文本标签的

5. drawDisplayItem(view, gl, displayItem, textureToUse, PASS_SELECTION_LABEL, null, 0);画选中标记的

6. drawDisplayItem(view, gl, displayItem, videoTexture, PASS_VIDEO_LABEL, null, 0);画视频标记的

7. drawDisplayItem(view, gl, displayItem, locationTexture, PASS_LOCATION_LABEL, null, 0);画位置标记的

8. drawDisplayItem(view, gl, displayItem, locationTexture, PASS_MEDIASET_SOURCE_LABEL,transparentTexture, 0.85f);画源来源图标的(相机或一般文件夹)

二、特效

举如何显示一张图片为例,在图片完全显示出来经过这样一个过程,附近的图片渐小渐出,当前图片渐大渐入,当前图片逐渐变大直到全屏。实现这个特效,要进行很多帧的渲染。就是说并不是只调一次onDrawFrame函数就可以了,要调用多次。可以把这个特效的实现想成一个状态变化的过程,在每一个状态,纹理的显示大小和位置都不同,这也符合动画的基本原理。放大、缩小我们只要改变顶点数据就可以做到,gallery3d也是这样做的,下面是主要代码:

我们知道调用onDrawFrame来渲染,最后调到下面的drawFocusItems函数,

Java代码

1. GridQuad quad = creenGrid[vboIndex];

2. float u = malizedWidth();

3. float v = malizedHeight();

4. float imageWidth = th();

5. float imageHeight = ght();

6. boolean portrait = ((theta / 90) % 2 == 1);

7. if (portrait) {

8. viewAspect = 1.0f / viewAspect;

9. }

10. Quad(viewAspect, u, v, imageWidth, imageHeight);//改变用来贴图片的长方形的大小

11. rays(gl);//绑定新数据,为渲染做准备。

而位置的改变有两种方式,一种是直接以顶点数据中改变,另一种是计算出在3维3个方向的偏移量,再调用gltranslate来做,从代码可以看出采用的是第二种方式来做的,比第一种方式更方便一些。代码:

Java代码

1. slatef(-translateXf, -translateYf, -translateZf);

而这里的3个偏移量的计算是和camera相关的,相关文件为,,过程很复杂,理清楚后再细化吧。

cache管理

下面是cache文件

Java代码

1. /sdcard/Android/data//cache/local-album-cache

2. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-album-cache

3. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-meta-cache

4. ----rwxr-x system sdcard_rw 299877 2010-05-28 07:36 local-album-cachechunk_0

5. d---rwxr-x system sdcard_rw 2010-05-21 09:56 geocoder-cache

6. ----rwxr-x system sdcard_rw 284 2010-05-28 07:36 local-album-cacheindex

7. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-image-thumbs

8. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-video-thumbs

9. d---rwxr-x system sdcard_rw 2010-05-21 09:56 picasa-thumbs

10. ----rwxr-x system sdcard_rw 80 2010-05-28 07:36 local-meta-cachechunk_0

11. ----rwxr-x system sdcard_rw 164 2010-05-28 07:36 local-meta-cacheindex

12. d---rwxr-x system sdcard_rw 2010-05-21 09:56 hires-image-cache

13. ----rwxr-x system sdcard_rw 627629 2010-05-28 07:37 local-image-thumbschunk_0

14. ----rwxr-x system sdcard_rw 3914 2010-05-21 09:56 local-image-thumbsindex

15. ----rwxr-x system sdcard_rw 53343 2010-05-28 07:34 hires-image-cache-49829483_

16. ----rwxr-x system sdcard_rw 237692 2010-05-28 07:33 hires-image-cache3684568484369117627_

17. ----rwxr-x system sdcard_rw 133182 2010-05-28 07:34 hires-image-cache626432_

18. ----rwxr-x system sdcard_rw 83223 2010-05-28 07:34 hires-image-cache4275479623210216146_

19. ----rwxr-x system sdcard_rw 292837 2010-05-28 07:34 hires-image-cache-6463937_

20. ----rwxr-x system sdcard_rw 191377 2010-05-28 07:35 hires-image-cache26313646_

21. ----rwxr-x system sdcard_rw 366905 2010-05-28 07:35 hires-image-cache-3280884_

22. ----rwxr-x system sdcard_rw 323671 2010-05-28 07:35 hires-image-cache57524722_

创建cache的关键代码

Java代码

1. LocalDataSource

2. public static final DiskCache sThumbnailCache = new DiskCache("local-image-thumbs");----------------------local-image-thumbs local-image-thumbschunk_0 local-image-thumbsindex

3. public static final DiskCache sThumbnailCacheVideo = new DiskCache("local-video-thumbs");--------------------local-video-thumbs

4. public static final DiskCache sAlbumCache = new DiskCache("local-album-cache");----------------------local-album-cache local-album-cacheindex

5. public static final DiskCache sMetaAlbumCache = new DiskCache("local-meta-cache");------------------local-meta-cache local-meta-cacheindex

6. getChunkFile --------------local-meta-cachechunk_0 local-album-cachechunk_0

7.

8. ReverseGeocoder:: private static final DiskCache sGeoCache = new DiskCache("geocoder-cache"); -------------------------geocoder-cache

9. PicasaDataSource:: public static final DiskCache sThumbnailCache = new DiskCache("picasa-thumbs");-----------------------------picasa-thumbs

10. UriTexture::writeToCache --------------------------hires-image-cache-xxx_

布局补充:

在画一个界面是,是分类化的,比如第一个界面是显示所有有图片的文件夹,在代码里叫专辑.有这些元素要创建:

文本标签 显示专辑名和专辑内图片或视频数

路径条显示路径名

按纽拍照按纽,放大/缩小

菜单栏全选,取消全选,分享,删除,更多等

图片边框

用于显示图片的矩形

在渲染时一次把一类元素画完,再画另一类.如主界面顺序为:

路径条->按纽->文本标签->图片边框->图片.

具体代码见drawBlendedComponents函数

中写缓存: (ALBUM_CACHE_LOCALE_INDEX, sDummyData,

0);

第一个是 key ,这里是正常数据,当然还有别的 key , key 分别是 -1,-2,-3,-4,-5 。

中,执行上面的写的过程,这里先得明白他的 cache 怎么装的:

它是由很多称之为“片”的文件组成的,形成一个 List 形式: private final

LongSparseArray mChunkFiles = new LongSparseArray();

即 mChuckFiles 就是整个 cache ,里面包括很多 chunk( 即片 ) ,每一个 chunk 大小为 1MB.

当要写入某一个 chunk 里面的时候,先要找到他在 mChuckFiles 里面的索引值即 chunkIndex, 由

(chunkIndex); 来获取这个文件, chunkIndex 怎么来的呢?

private LongSparseArray mIndexMap;

Record record = (key); 这里的 key 就是上面用 put 方法传过来的

ALBUM_CACHE_LOCALE_INDEX 的值(就是 -5 )

int chunkIndex = ;

这么一步步来的。

当然了,第一次都是空的,也就是 get 不到东西 (chunkIndex); 和 Record record =

(key); 都 get 不到,那么第一次就先把东西放进去, (key, new Record

(chunkIndex, , , Disk, timestamp)); (记录 key 值)以及 final

String chunkFilePath = mCacheDirectoryPath + CHUNK_FILE_PREFIX + chunk; chunkFile = new

RandomAccessFile(chunkFilePath, "rw");(chunk, chunkFile); (三句代码来新建一个

chunkfile 并放到 cache 列表里面)

注意: Record 是内部类,只是一个数据集合类而已,相当于文件描述信息。每个 cache (即 chunk )对应一个。

private final LongSparseArray mChunkFiles = new

LongSparseArray(); 中mChunkFiles 最大装 13 个,每个 chunk 是 1M, 所以全部 Cache 是 13M.

Gallery3D中画图时调用glTranslate函数参数赋值过程

文章分类:移动开发

GridDrawManager::drawDisplayItem(RenderView view, GL11 gl, DisplayItem displayItem, Texture

texture, int pass,Texture previousTexture, float mixRatio) 函数有下面几句:

Java代码

1. Vector3f animatedPosition = tedPosition;

2. float translateXf = animatedPosition.x * Scale;

3. float translateYf = animatedPosition.y * Scale;

4. float translateZf = -animatedPosition.z;

调用过程:

->computeVisibleItems(),displayItems[baseIndex + j] = displayItem;Vector3f position = ();

tPositionForSlotIndex(i, camera, layout, deltaAnchorPosition, position);//give

position value itionAndStackIndex(displayItem, position, j, true);//raletive position to

item

->GridLayer, mDrawManager = new GridDrawManager(context, mCamera, mDrawables, sDisplayList,

sDisplayItems, sDisplaySlots);

->GridDrawManager(), mDisplayItems = displayItems;

->drawFocusItems ,DisplayItem[] displayItems = mDisplayItems;

->animatedPosition = tedPosition;

->drawDisplayItem, amAnimatedPosition

->DisplayItem::commit() (mTargetPosition);

-> DisplayItem::set(Vector3f position, int stackIndex, boolean performTransition) mTargetPosition.z =

Java代码

1. public void getPositionForSlotIndex(int slotIndex, int itemWidth, int itemHeight, Vector3f outPosition) {

2. outPosition.x = (slotIndex / mNumRows) * (itemWidth + mSpacingX);

3. outPosition.y = (slotIndex % mNumRows) * (itemHeight + mSpacingY);

4. int maxY = (mNumRows - 1) * (itemHeight + mSpacingY);

5. outPosition.y -= (maxY >> 1);

6. outPosition.z = 0;

7. Log.d("outPosition","slotIndex="+slotIndex+",mNumRows="+mNumRows+",outPosition=("+outPosition.x+","+outPosition.y+","+outPosition.z+")");

8. }

在gallery3d中矩阵是从上到下、从左到右排列的,在主界面时最多有3行,mNumRows=3,在缩略图界面最多4行mNumRows=4,在查看界面只有一行mNumRows=1

上面函数是计算所绘制项位置的,slotIndex / mNumRows得到的是当前处于多少列,slotIndex %

mNumRows得到的是处于多少行。 int maxY = (mNumRows - 1) * (itemHeight + mSpacingY);

outPosition.y -= (maxY >> 1);是为了在y方向对称,想成屏幕中间是分界线,以上的项y为负,线以下的y为正。

deltaAnchorPosition的赋值过程:

Java代码

1. int currentlyVisibleSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);->anchorItem = ef;-> newSlotIndex = i;->if (currentAnchorSlotIndex != D && newAnchorSlotIndex != D) {

2. itionForSlotIndex(newAnchorSlotIndex, itemWidth, itemHeight, deltaAnchorPosition);

3. itionForSlotIndex(currentAnchorSlotIndex, itemWidth, itemHeight, currentSlotPosition);

4. ct(sDeltaAnchorPosition);

5. ct(currentSlotPosition);

6. deltaAnchorPosition.y = 0;

7. deltaAnchorPosition.z = 0;

8. }

MediaFeed::run()

onFeedChanged(, onLayout(newSlotIndex, currentlyVisibleSlotIndex, null);

onLayout, (deltaAnchorPosition);

computeVisibleRange(),(sDeltaAnchorPositionUncommited);

(sDeltaAnchorPosition);

deltaAnchorPosition

Gallery3D各个界面可见范围计算方法

文章分类:移动开发

computeVisibleRange算法分析:

第1步,计算出left,right,bottom,top

第2步,计算出numSlots,并除于2赋值给index

第3步,由index得position,判断position是否在第1步计算出的范围内,是的话,就把第2步计算得出的中间的index赋值给 firstVisibleSlotIndex,lastVisibleSlotIndex,否则,根据滑动窗口算法改变index直到求组所需index

第4步,在while循环中,用第3步得到的firstVisibleSlotIndex求出position,进行和第2步相反的判断,即 position若不在可视范围内,则将相应的index给firstVisibleSlotIndex,否则减 firstVisibleSlotIndex,直到找到最小的可视范围内的index作为firstVisibleSlotIndex。

第5步,在while循环中,用第3步得到的lastVisibleSlotIndex求出position,进行和第2步相反的判断,即 position若不在可视范围内,则将相应的index给lastVisibleSlotIndex,否则增 lastVisibleSlotIndex,直到找到可视范围内的最大的index作为lastVisibleSlotIndex。

第6步,进行firstVisibleSlotIndex,lastVisibleSlotIndex的越界判断。 outBufferedVisibleRange对应的是可见的。outBufferedVisibleRange对应的是0~文件夹的最大数。

computeVisibleItems算法分析:

第1步由slot计算出position,set,当前set不为空且slot在有效范围,创建bestItems,计算sortedIntersection

第2步计算这个slotindex中的图片数目,取这个文件中的前12张图片加到bestItems.

第3步 取bestItems里的图片对应的displayList中的displayItem,并赋值给displayItems数组,同时保存 position,及j,j是bestItems数组中一项,范围是0~12。

第四步 对于每一个文件夹,要在displayItems里有对应的12项,当文件夹内图片不足12时,余下的用null填充。

当绘制缩略图界面时,有些不同

在第1步中,slotindex不再表示文件夹,这时表示具体某一张图片了,所以由slot得到的set里始终只有

1项,且会调 eSortedIntersection(visibleItems, items, MAX_ITEMS_PER_SLOT,

bestItems, sTempHash);给bestItems赋值,这样第2步就在bestItems加项动作不执行。

镜像倒影特效Gallery

文章分类:移动开发

效果展示

本文档将介绍在android上如何实现一个倒影效果的Gallery。

为了达到上图所示的效果,

首先,是需要有一个自定义的gallery,实现了对Gallery的继承,通过重写getChildStaticTransformation方法来控制,每个子view有不同的缩放比例,形成阶梯状的展示。这个gallery是在坤庭的代码基础上实现的,我这里就不再重复介绍。

接下来,gallery中的每个view,都是一个自定义的MirrorView,由它来实现了画原图及画倒影。新的算法解决了性能问题,下面就重点说一下这部分内容:

镜像特效最近还蛮流行的,尤其在HTC 的Sense 介面上,常常都可以见到。大家可以看到,加了个镜像特效后,那感觉就很立体,感觉上好像是这些图片摆立在一个玻璃桌面上。

在Android 上要帮图片加上镜像特效,会不会很麻烦?一点也不麻烦,只要几行代码,就可以搞定。

因此,在开始看答案之前,我会建议你要先有Photoshop 的使用经验。想想,如果用Photoshop 要帮图片加上镜像特效,要如何做?我想一般不外乎是先复制个图片,并将其垂直翻转,接着再对这翻转的图片,加个由灰到黑的渐层mask 即可。

好了,让我们来看一下答案。底下就是帮图片加上镜像特效的程式范例。

Java代码

1. public class MirrorView extends View {

2.

3. Paint m_paint;

4.

5. int m_nShadowH;

6.

7. Drawable m_dw;

8.

9. Bitmap m_bitmap;

10.

11. Matrix mMatrix;

12.

13. int shadowHeight;

14.

15. public MirrorView(Context context, Bitmap bitmap) {

16.

17. super (context);

18.

19. m_bitmap = bitmap;

20.

21. _Init();

22.

23. }

24.

25. private void _Init() {

26.

27. //m_dw = new BitmapDrawable(Resource(getResources(), ));

28.

29. m_dw = new BitmapDrawable(m_bitmap);

30.

31. m_nds(0,0,m_rinsicWidth(),m_rinsicHeight());

32.

33. m_nShadowH = m_rinsicHeight()/1;

34.

35. m_paint = new Paint(_ALIAS_FLAG );

36.

37. LinearGradient lg = new LinearGradient(0, 0, 0, m_nShadowH, 0xB0FFFFFF, 0×00000000, );

38.

39. m_der(lg);

40.

41. m_rmode(new PorterDuffXfermode(LY ));

42.

43. mMatrix = new Matrix();

44.

45. }

46.

47. @Override

48.

49. public void onDraw(Canvas canvas) {

50.

51. super .onDraw(canvas);

52.

53. int nX = 0;

54.

55. int nY = 0;

56.

57. _DrawNormalImg(canvas, nX, nY);

58.

59. _DrawMirror(canvas, nX, nY);

60.

61. }

62.

63. private void _DrawNormalImg(Canvas canvas, int nX, int nY) {

64.

65. (_SAVE_FLAG );

66.

67. ate(nX, nY);

68.

69. m_(canvas);

70.

71. e();

72.

73. }

74.

75. private void _DrawMirror(Canvas canvas, int nX, int nY) {

76.

77. int nW = m_rinsicWidth();

78.

79. int nH = m_rinsicHeight();

80.

81. shadowHeight=nH/2;

82.

83. float [] src={0, nH, nW, nH, nW,nH – m_nShadowH, 0, nH – m_nShadowH};

84.

85. float [] dst={ 0, nH, nW, nH,nW, shadowHeight, 0, shadowHeight };

86.

87. ();

88.

89. yToPoly(src, 0, dst, 0, >> 1);

90.

91. (mMatrix);

92.

93. //draw mirror image

94.

95. (_SAVE_FLAG );

96.

97. (1.0f, -1.0f);

98.

99. ate(nX, -(nY + nH * 2));

100.

101. ct(0, nH, nW, nH – m_nShadowH);

102.

103. m_(canvas);

104.

105. e();

106.

107. //draw mask

108.

109. ();

110.

111. ate(nX, nY + nH);

112.

113. ct(0, 0, nW, m_nShadowH, m_paint);

114.

115. e();

116.

117. e();

118.

119. }

120.

121. }

_DrawMirror() 方法是关键。用Photoshop 要如何做出镜像特效?第一步是先画出垂直翻转的图片。

Android 绘图座标体系预设的原点在左上角,X 轴往右是越来越大的正值,而Y 轴往下,则是越来越大的正值。要画出垂直翻转的图片,其实也就是要垂直翻转整个绘图座标体系。在 Android 中,要如何做?答案就是 (1.0f, -1.0f)。很简单吧,没想到给scale() 函式一个负值,就可以翻转相对应的轴。

在Photoshop 中,做镜像特效的第二步是要对这翻转的图片,加个由灰到黑的渐层mask。

在Android 中,要画渐层色,那就一定得用LinearGradient 这个类别。至于要对背景图加上个mask,就请参考一下Paint 的setXfermode() 函式。 _Init() 这个函式,就是负责生成一个由灰到黑渐层mask 的m_paint 物件。

这个控件我测试过,200张图片加入adapter,在大数据量情况下性能也没有问题。

菱形3D实例

文章分类:移动开发

下面是具体的实现方法:

首先需要建两个array,第一array是用来告诉opengl这个图形有哪些顶点:

画一个三维的坐标轴,然后把你要画的点都算出来,然后放在这个array里。

Java代码

1. float l=1.5f;

2. float[] vertex={

3.

4. 0.0f,l,0.0f,

5.

6. l,0.0f,0.0f,

7.

8. 0.0f,0.0f,l,

9.

10. -l,0.0f,0.0f,

11.

12. 0.0f,0.0f,-l,

13.

14. 0.0f,-l,0.0f

15.

16. };

第二个array是告诉opengl 你要怎样组织这些点:

这里我要画三角形,所以每三个点是一组。

Java代码

1. byte[] edge=

2. {

3. 0,1,2,

4. 1,2,5,

5.

6. 0,2,3,

7. 5,2,3,

8.

9. 0,3,4,

10. 5,3,4,

11.

12. 0,4,1,

13. 5,4,1

14.

15. };

这里的数字,是第一个array的index。

下面你要建立两个Buffer它们是用来存放这两个array的。

Java代码

1. ByteBuffer bb = teDirect(*4);

2. (Order());

3. fbv=tBuffer();

4. (vertex);

5. on(0);

6.

7. ffe=teDirect();

8. (edge);

9. on(0);

这样一个三维的菱形就画好了。

下面你要写一个方法能让它自己把自己画出来!

Java代码

1. public void draw(GL10 gl)

2. {

3. tFace(_CW);

4. exPointer(3, _FLOAT, 0, fbv);

5. Elements(_TRIANGLES, 24, _UNSIGNED_BYTE, ffe);

6.

7. }

先说第一个glFrontFace,物体都有一个正面一个反面,这里告诉opengl显示这个物体按顺时针方向(CW=>

clockwise)

exPointer(3, _FLOAT, 0, fbv);这个方法是把本程序所用的点都传递个opengl。opengl需要知道什么哪?首先是这个点是几维的(opengl 支持2,3,4 维),这里是3所以是三维的,第二个参数告诉opengl,这个点是用什么样类型的变量来储存的,这里是float类型。第三个是步长(stride),这个我还没弄明白,不过我看的例子都为0. 最后把你建立好的三维坐标点都传给opengl

Elements。这个方法是告诉opengl如果要画这个图形,应该怎么画。第一个参数,告诉opengl 用画三角形(这样opengl就以三个点为一组),然后告诉opengl你要用到多少个点(注意这个点是在第二个array里的点数)。第三个是告诉opengl这些点(其实是三维坐标点的reference)的类型。这里是unsigned

byte。最后把你排列点的array 放进去!

第二个大的步骤是创建一个让这个三维坐标运行的环境(Renderer)。

这是一个interface类

首先,在onDrawFrame里,我们告诉本程序这个三维图形的行为:

在做任何事情之前,我们要清空所有以前内存里的东西,这个内存包括:Color 和Depth

r(_COLOR_BUFFER_BIT|_DEPTH_BUFFER_BIT);

然后告诉opengl你要用那个MatrixMode 这个就比较难解释了。

如果写程序只要记住 GL_MODELVIEW 是管理图形的缩放,移动,和转动就行了.(如果那个朋友想理解的更深一点,可以联系我,我可以把我的笔记发过去或者参考

/~powerk/GeneralGraphicsNotes/projection/projection_ )。

slatef(0, 0, -3.0f);

这个方法告诉opengl把图形沿z轴迁移3个unit。这三个值分别是x,y,z轴。

tef(angle,0, 1, 0);

这个方法告诉我们以y为轴。转angle个度数。注意这里的1和0是告诉沿着那个轴转,别的值应该没有意义。

leClientState(_VERTEX_ARRAY);

还记得上边说的opengl分client side和service side吗。这个是告诉opengl如果client side调用draw什么的时候,这个vertex array是可用的。opengl有很多这样的可选项,所以需要告诉opengl,因为我们已经设置了vertex array(我们的第一个array),所以告诉opengl 它是可用的(如果不告诉,opengl会忽略)!

(gl);

这个方法是把图形画出来。

angle++;

为了达到动态的效果,我们让每一个frame 的angle,比上一个多一度。

当显示空间大小发生变化的时候,我们应该告诉opengl一下信息:

Java代码

1. public void onSurfaceChanged(GL10 gl, int width, int height)

2. {

3. port(0, 0, width, height);

4. ixMode(_PROJECTION);

5. Identity();

6. float ratio = (float)width/height;

7. tumf(-ratio, ratio, -1, 1, 1, 10);

8.

9. }

首先是opengl可用的空间:

port(0, 0, width, height);

想象一下用这四个点画出来的四边形,就是opengl所能用的空间。

ixMode(_PROJECTION);

这个matrix是如何把三维坐标转换为二维坐标并把它放在显示器上。

Identity

是告诉opengl初始化这个matrix。

tumf

要把三维的东西用二维显示出来,需要知道几个东西,第一是这个显示平面有多大,你可以看多近和多远。这里的头四个参数,建立了一个四边形,告诉opengl把图形显示在这个范围了。后两个参数告诉opengl这里显示平面里可以显示三维空间里最近和最远的位置。

当这个三维图形建立的是时候,我们可以告诉opengl一些基本参数。这里把能省略的都省略了(其实什么都没有也可以运行!)

Java代码

1. public void onSurfaceCreated(GL10 gl, EGLConfig arg1)

2. {

3. le(_DEPTH_TEST);

4. rColor(0,0, 0, 0);

5. }

le(_DEPTH_TEST); 告诉opengl要检查depth,为什么哪。在三维空间里一个物体A在另一个物体B后面,那么这个A被B挡住里,所以你是看不见的。我们要告诉opengl,我们不想看见被挡住的东西。这个GL_DEPTH_TEST 就是这个功能。

rColor(0,0, 0, 0);

设置这个背景颜色为黑色,应为我们没有给我们的三维图形设置颜色(为了简单),它的初始化颜色是白色。

以下是源代码:

Java代码

1. package ;

2.

3. import ffer;

4. import der;

5. import uffer;

6.

7. import 10;

8.

9. public class TriangleShape

10. {

11.

12. private final float l=1.5f;

13.

14. private FloatBuffer fbv;

15.

16. private ByteBuffer ffe;

17.

18. public TriangleShape()

19.

20. {

21.

22. float[] vertex={

23.

24. 0.0f,l,0.0f,

25.

26. l,0.0f,0.0f,

27.

28. 0.0f,0.0f,l,

29.

30. -l,0.0f,0.0f,

31.

32. 0.0f,0.0f,-l,

33.

34. 0.0f,-l,0.0f

35.

36. };

37.

38.

39. byte[] edge=

40.

41. {

42.

43. 0,1,2,

44.

45. 1,2,5,

46.

47.

48.

49. 0,2,3,

50.

51. 5,2,3,

52.

53.

54.

55. 0,3,4,

56.

57. 5,3,4,

58.

59.

60.

61. 0,4,1,

62.

63. 5,4,1

64.

65. };

66.

67. ByteBuffer bb = teDirect(*4);

68.

69. (Order());

70.

71. fbv=tBuffer();

72.

73. (vertex);

74.

75. on(0);

76.

77.

78.

79.

80. ffe=teDirect();

81.

82. (edge);

83.

84. on(0);

85.

86. }

87.

88. public void draw(GL10 gl)

89.

90. {

91.

92. tFace(_CW);

93.

94. exPointer(3, _FLOAT, 0, fbv);

95.

96. Elements(_TRIANGLES, 24, _UNSIGNED_BYTE, ffe);

97.

98. }

99. }

100.

101.

102. package ;

103.

104. import fig;

105. import 10;

106.

107. import er;

108.

109. public class MySimpleRendered implements Renderer

110. {

111.

112. private int angle=50;

113.

114. private TriangleShape trian;

115.

116. public MySimpleRendered()

117.

118. {

119.

120. trian = new TriangleShape();

121.

122. }

123.

124. @Override

125.

126. public void onDrawFrame(GL10 gl)

127.

128. {

129.

130. // TODO Auto-generated method stub

131.

132. r(_COLOR_BUFFER_BIT|_DEPTH_BUFFER_BIT);

133.

134. ixMode(_MODELVIEW);

135.

136. Identity();

137.

138. slatef(0, 0, -3.0f);

139.

140. tef(angle,0, 1, 0);

141.

142. tef(angle, 1, 0, 0);

143.

144. leClientState(_VERTEX_ARRAY);

145.

146. (gl);

147.

148. angle++;

149.

150. }

151.

152.

153. @Override

154.

155. public void onSurfaceChanged(GL10 gl, int width, int height)

156.

157. {

158.

159. // TODO Auto-generated method stub

160.

161. port(0, 0, width, height);

162.

163. ixMode(_PROJECTION);

164.

165. Identity();

166.

167. float ratio = (float)width/height;

168.

169. tumf(-ratio, ratio, -1, 1, 1, 10);

170.

171.

172.

173. }

174.

175.

176. @Override

177.

178. public void onSurfaceCreated(GL10 gl, EGLConfig arg1)

179.

180. {

181.

182. le(_DEPTH_TEST);

183.

184. rColor(0,0, 0, 0);

185.

186. }

187.

188. }

189. package ;

190.

191. import ty;

192. import ;

193. import aceView;

194. public class Triangle extends Activity {

195. /** Called when the activity is first created. */

196.

197. private GLSurfaceView my_view;

198. @Override

199. public void onCreate(Bundle savedInstanceState) {

200. te(savedInstanceState);

201. setContentView();

202. my_view = new GLSurfaceView(this);

203. my_derer(new MySimpleRendered());

204. tentView(my_view);

205. }

206. public void onResume()

207. {

208.

209. me();

210.

211. my_me();

212. }

213. public void onPause()

214. {

215.

216. e();

217.

218. my_e();

219. }

220. }

3D桌面效果动画类

文章分类:移动开发

Java代码

1. public class CubeAnimation extends Animation implements

2. ionListener {

3. public static final int FACE_LEFT = 0;

4. public static final int FACE_RIGHT = 1;

5. private int mInd;

6. private float mFromDegrees;

7. private float mToDegrees;

8. private float mCenterX;

9. private float mCenterY;

10. private int mHorizonType = 1;

11. private float mHorizonValue = 0.5F;

12. private Camera mCamera;

13. private View mView;

14.

15. public CubeAnimation(int ind) {

16. = ind;

17. egrees = 0.0F;

18. rees = 90.0F;

19. }

20.

21. public CubeAnimation(Context context, AttributeSet attrs) {

22. super(context, attrs);

23. TypedArray a = StyledAttributes(attrs,

24. imation);

25.

26. egrees = 0.0F;

27. rees = 90.0F;

28.

29. Description d = alue(lue(0));

30. onType = ;

31. onValue = ;

32.

33. = (1, 0);

34.

35. boolean t = lean(2, true);

36. if (!(t)) {

37. = (1 - );

38. rees = 0.0F;

39. egrees = 90.0F;

40. }

41. e();

42. }

43.

44. public void onAnimationStart(Animation anim) {

45. ibility(E);

46. }

47.

48. public void onAnimationEnd(Animation anim) {

49. ibility(( == 0) ? 0 : 8);

50. = (1 - );

51. }

52.

53. public void onAnimationRepeat(Animation anim) {

54. }

55.

56. public static void startCubeAnimation(Context context, int id, View view1,

57. View view2) {

58. XmlPullParser parser;

59. try {

60. parser = ources().getAnimation(id);

61. AttributeSet attrs = ibuteSet(parser);

62.

63. int type = ntType();

64. int depth = th();

65. while (true) {

66. while (true) {

67. if ((((type = ()) == 3) && (th() <= depth))

68. || (type == 1))

69. break label172;

70. if (type == 2)

71. break;

72. }

73.

74. String name = e();

75.

76. if (("cube")) {

77. CubeAnimation anim1 = new CubeAnimation(context, attrs);

78. = 1;

79. = view1;

80. mationListener(anim1);

81. CubeAnimation anim2 = new CubeAnimation(context, attrs);

82. = 0;

83. = view2;

84. mationListener(anim2);

85. nimation(anim1);

86. label172: nimation(anim2);

87. }

88. }

89. } catch (ndException ex) {

90. Log.e("CubeAnimation", "NotFoundException");

91. } catch (XmlPullParserException ex) {

92. Log.e("CubeAnimation", "XmlPullParserException");

93. } catch (IOException ex) {

94. Log.e("CubeAnimation", "IOException");

95. }

96. }

97.

98. public void initialize(int width, int height, int parentWidth,

99. int parentHeight) {

100. lize(width, height, parentWidth, parentHeight);

101. rX = resolveSize(1, 0.5F, width, parentWidth);

102. rY = resolveSize(1, 0.5F, height, parentHeight);

103. if (onType == 0) {

104. onValue /= height;

105. }

106.

107. a = new Camera();

108. }

109.

110. protected void applyTransformation(float interpolatedTime, Transformation t) {

111. float fromDegrees = egrees;

112. float degrees = fromDegrees + (rees - fromDegrees)

113. * interpolatedTime;

114.

115. float centerX = rX;

116. float centerY = rY;

117. Camera camera = a;

118.

119. Matrix matrix = rix();

120.

121. ();

122.

123. float b = 0.0F;

124. float e = -onValue;

125.

126. if ( == 0) {

127. degrees += 90.0F;

128. }

129.

130. Y(degrees);

131.

132. rix(matrix);

133. e();

134.

135. if ( == 0) {

136. le(-1.0F, 1.0F, centerX, 0.0F);

137. }

138.

139. float tranX = 320.0F * interpolatedTime;

140.

141. float tranY = -centerY * e + b;

142. nslate(0.0F, centerY * e);

143. anslate(tranX, tranY);

144. }

145.

146. protected static class Description {

147. public int type;

148. public float value;

149.

150. static Description parseValue(TypedValue value) {

151. Description d = new Description();

152. if (value == null) {

153. = 0;

154. = 0.0F;

155. } else {

156. if ( == 6) {

157. = ((( & 0xF) == 1) ? 2 : 1);

158.

159. = xToFloat();

160. return d;

161. }

162. if ( == 4) {

163. = 0;

164. = at();

165. return d;

166. }

167. if (( >= 16) && ( <= 31)) {

168. = 0;

169. = ;

170. return d;

171. }

172. }

173.

174. = 0;

175. = 0.0F;

176.

177. return d;

178. }

179. }

180. }

gallery3d源码学习总结(一)——绘制流程drawFocusItems

显示单张图片相关的输入变量

1. int selectedSlotIndex = mSelectedSlot;

2. GridDrawables drawables = mDrawables;

3. GridCamera camera = mCamera;

4. DisplayItem[] displayItems = mDisplayItems;

5. int firstBufferedVisibleSlot = ;

6. int lastBufferedVisibleSlot = ;

7. boolean isCameraZAnimating = mating();

复制代码

删除当前选中槽位前后2步之外的大缩略图

1. for (int i = firstBufferedVisibleSlot; i <= lastBufferedVisibleSlot; ++i)

{

2. if (selectedSlotIndex != D && (i >=

selectedSlotIndex - 2 && i <= selectedSlotIndex + 2)) {

3. continue;

4. }

5. DisplayItem displayItem = displayItems[(i -

firstBufferedVisibleSlot) * _ITEMS_PER_SLOT];

6. if (displayItem != null) {

7. creennailImage();

8. }

9. }

复制代码

得到当前图片的DispalyItem元素

1. int centerIndexInDrawnArray = (selectedSlotIndex -

firstBufferedVisibleSlot) * _ITEMS_PER_SLOT;

2. if (centerIndexInDrawnArray < 0 || centerIndexInDrawnArray >=

) {

3. return;

4. }

5. DisplayItem centerDisplayItem =

displayItems[centerIndexInDrawnArray];

6. if (centerDisplayItem == null ||

== D) {

7. return;

8. }

复制代码

判断大缩略图是否加载完成

1. boolean focusItemTextureLoaded = false;

2. Texture centerTexture =

eennailImage(text());

3. if (centerTexture != null && ed()) {

4. focusItemTextureLoaded = true;

5. }

复制代码

是否跳过当前图片前一张图片

1. float camX = tX * ;

2. float centerTranslateX = tedPosition.x;

3. final boolean skipPrevious = centerTranslateX < camX;

复制代码

开启opengl混合模式并设置混合函数

1. le(_BLEND);

2. dFunc(_ONE, _ONE);

复制代码

循环遍历前中后三幅图片分别进行“核心绘制处理”

1. for (int i = -1; i <= 1; ++i) {

2. if (slideshowMode && timeElapsedSinceView > 1.0f && i != 0)

3. continue;

4. 。。。

5. }

复制代码

核心绘制处理——输入变量准备

1. if (slideshowMode && timeElapsedSinceView > 1.0f && i != 0)

2. continue;

3. float viewAspect = tRatio;

4. int selectedSlotToUse = selectedSlotIndex + i;

5. if (selectedSlotToUse >= 0 && selectedSlotToUse <=

lastBufferedVisibleSlot) {

6. int indexInDrawnArray = (selectedSlotToUse -

firstBufferedVisibleSlot) * _ITEMS_PER_SLOT;

7. if (indexInDrawnArray < 0 || indexInDrawnArray >=

) {

8. return;

9. }

10. DisplayItem displayItem =

displayItems[indexInDrawnArray];

11. MediaItem item = ef;

12. final Texture thumbnailTexture =

mbnailImage(text(), sThumbnailConfig);

13. Texture texture =

eennailImage(text());

复制代码

在幻灯模式下且超过1秒的切换时间无须显示前后两张图片;

得到视角和当前displayItem、对应媒体对象、小缩略图材质、大缩略图材质。

加载高质量的材质资源

1. if (isCameraZAnimating && (texture == null || !ed())) {

2. texture = thumbnailTexture;

3. ue(0f);

4. eValue(1f, 0.75f,

meTime());

5. }

6. Texture hiRes = (zoomValue != 1.0f && i == 0 &&

iaType() != _TYPE_VIDEO) ? displayItem

7. .getHiResImage(text())

8. : null;

9. if (_DENSITY > 1.0f) {

10. hiRes = texture;

11. }

12. if (i != 0) {

13. iResImage();

14. }

15. if (hiRes != null) {

16. if (!ed()) {

17. (hiRes);

18. (hiRes, true);

19. } else {

20. texture = hiRes;

21. }

22. }

复制代码

如果Camera正在拉远或拉近,且大缩略图材质为空或未加载完成,则选择小缩略图作为材质,将当前图片的“大缩略图混合比例”变量进行初始化(目标值为1秒,渐变时间为0.75秒,渐变开始时间为当前帧时间)。

如果处于放大状态,则加载原图hiRes,加载成功后赋值给材质变量texture;并清除前后图片的原图。

加载材质

1. final Texture fsTexture = texture;

2. if (texture == null || !ed()) {

3. if ((centerTranslateX - camX) < 0.1f) {

4. if (focusItemTextureLoaded && i != 0) {

5. (texture);

6. }

7. if (i == 0) {

8. (texture);

9. (texture, true);

10. }

11. }

12. texture = thumbnailTexture;

13. if (i == 0) {

14. ue(0f);

15. eValue(1f, 0.75f,

meTime());

16. }

17. }

复制代码

保留当前的最佳材质,

如果此材质加载未完成,则继续按优先级加载,并把小缩略图(基本上都已经加载成功了)设置为当前材质;

最佳材质未加载完成之前,替换渐变不会开始。

无须绘制

1. if (ating() || slideshowMode) {

2. if (!slideshowMode && skipPrevious && i == -1) {

3. continue;

4. }

5. if (!skipPrevious && i == 1) {

6. continue;

7. }

8. }

9. int theta = (int) geTheta();

复制代码

如果相机缩放过程中,非幻灯片模式下且镜头中不需要展示前一张的情况下,无须处理前一张;

如果相机缩放或幻灯片绘制过程中,需要展示前一张的情况下,无须处理后一张。

处理前后渐变绘制

1. // If it is in slideshow mode, we draw the previous item in

2. // the next item's position.

3. if (slideshowMode && timeElapsedSinceView < 1.0f &&

timeElapsedSinceView != 0) {

4. if (i == -1) {

5. int nextSlotToUse = selectedSlotToUse + 1;

6. if (nextSlotToUse >= 0 && nextSlotToUse <=

lastBufferedVisibleSlot) {

7. int nextIndexInDrawnArray = (nextSlotToUse

- firstBufferedVisibleSlot)

8. * _ITEMS_PER_SLOT;

9. if (nextIndexInDrawnArray >= 0 &&

nextIndexInDrawnArray < ) {

10. float currentImageTheta =

tedImageTheta;

11. displayItem =

displayItems[nextIndexInDrawnArray];

12. backupImageTheta =

tedImageTheta;

13. tedImageTheta =

currentImageTheta;

14. ha(1.0f -

timeElapsedSinceView);

15. }

16. }

17. } else if (i == 0) {

18. tedImageTheta =

backupImageTheta;

19. ha(timeElapsedSinceView);

20. }

21. }

复制代码

如果处于幻灯片模式中渐变过程中,处理上一幅相片时找到它的下一个DispalyItem,处理本张相片则直接使用当前DispalyItem,为的是同样找到当前DisplayItem,并绑定上一张相片和本张相片,两张相片透明度互补达到渐变的效果。

绘制小大缩略图渐变过程-小缩略图

1. int vboIndex = i + 1;

2. float alpha = ha();

3. float selectedMixRatio =

ue(meTime());

4. if (selectedMixRatio != 1f) {

5. texture = thumbnailTexture;

6. ha(alpha * (1.0f -

selectedMixRatio));

7. }

8. GridQuad quad =

creenGrid[vboIndex];

9. float u = malizedWidth();

10. float v = malizedHeight();

11. float imageWidth = th();

12. float imageHeight = ght();

13. boolean portrait = ((theta / 90) % 2 == 1);

14. if (portrait) {

15. viewAspect = 1.0f / viewAspect;

16. }

17. Quad(viewAspect, u, v, imageWidth,

imageHeight);

18. rays(gl);

19.

20. drawDisplayItem(view, gl, displayItem, texture,

PASS_FOCUS_CONTENT, null, 0.0f);

21. Arrays(gl);

复制代码

绘制小缩略图,请注意:selectedMixRatio表示大缩略图的绘制透明度,小缩略图的自然就是1.0f - selectedMixRatio。

绘制小大缩略图渐变过程-大缩略图

1. if (selectedMixRatio != 0.0f && selectedMixRatio != 1.0f) {

2. texture = fsTexture;

3. if (texture != null) {

4. float drawAlpha = selectedMixRatio;

5. ha(alpha * drawAlpha);

6. u = malizedWidth();

7. v = malizedHeight();

8. imageWidth = th();

9. imageHeight = ght();

10. Quad(viewAspect, u, v,

imageWidth, imageHeight);

11. rays(gl);

12. drawDisplayItem(view, gl, displayItem,

fsTexture, PASS_FOCUS_CONTENT, null, 1.0f);

13. Arrays(gl);

14. }

15. }

复制代码

更新当前图片长宽数据

1. if (i == 0 || slideshowMode) {

2. mCurrentFocusItemWidth = th();

3. mCurrentFocusItemHeight = ght();

4. if (portrait) {

5. // Swap these values.

6. float itemWidth = mCurrentFocusItemWidth;

7. mCurrentFocusItemWidth =

mCurrentFocusItemHeight;

8. mCurrentFocusItemHeight = itemWidth;

9. }

10. }

复制代码

绘制视频元素

1. ha(alpha);

2. if (iaType() ==

_TYPE_VIDEO) {

3. // The play graphic overlay.

4. rays(gl);

5. drawDisplayItem(view, gl, displayItem,

reVideo, PASS_VIDEO_LABEL, null, 0);

6. Arrays(gl);

7. }

复制代码

【此部分讲解已结束】,如您对其他部分感兴趣请回帖说明

gallery3d源码学习总结(二)——绘制流程drawThumbnails

应大家要求,续写了第二部分,如有错误敬请赐教。

此函数控制相册表格页、相片表格页、时间分类表格页的展示,非常重要。以下以相册表格页为例进行讲解,其他的就举一反三吧。

准备输入参数

1. final GridDrawables drawables = mDrawables;

2. final DisplayList displayList = mDisplayList;

3. final DisplayItem[] displayItems = mDisplayItems;

4.

5. final int firstBufferedVisibleSlot = ;

6. final int lastBufferedVisibleSlot = ;

7. final int firstVisibleSlot = ;

8. final int lastVisibleSlot = ;

9.

10. final int selectedSlotIndex = mSelectedSlot;

11. final int currentFocusSlot = mCurrentFocusSlot;

12. final int currentScaleSlot = mCurrentScaleSlot;

13.

14. final DisplayItem[] itemsDrawn = mItemsDrawn;

15. itemsDrawn[0] = null; // No items drawn yet.

16. int drawnCounter = 0;

17.

18. final GridQuad grid = ;

19. rays(gl);

20.

21. int numTexturesQueued = 0;

22. Context context = text();

复制代码

通过之前的computeVisibleItems(),已得到显示元素列表,显示元素缓冲数组,缓存可见槽位的范围,可见槽位的范围;得到当前选中的槽位索引selectedSlotIndex、当前焦点槽位索引currentFocusSlot和缩放槽位索引currentScaleSlot。

已画元素的缓存数组,绑定表格类材质。selectedSlotIndex、currentFocusSlot、currentScaleSlot在不进行任何操作时都是-1.

遍历缓存可见槽位范围中的每一个槽位

1. for (int itrSlotIndex = firstBufferedVisibleSlot; itrSlotIndex <=

lastBufferedVisibleSlot; ++itrSlotIndex) {

2. int index = itrSlotIndex;

3. ...

4. }

复制代码

即遍历每个相册,index是相册序号。

为每个相册分别计算“需要绘制“的最开头那张照片的序号

1. boolean priority = !(index < firstVisibleSlot || index >

lastVisibleSlot);

2. int startSlotIndex = 0;

3. final int maxDisplayedItemsPerSlot = (index ==

mCurrentScaleSlot) ? _DISPLAYED_ITEMS_PER_FOCUSED_SLOT

4. : _DISPLAYED_ITEMS_PER_SLOT;

5. if (index != mCurrentScaleSlot) {

6. for (int j = maxDisplayedItemsPerSlot - 1; j >= 0; --j) {

7. DisplayItem displayItem = displayItems[(index -

firstBufferedVisibleSlot) * _ITEMS_PER_SLOT + j];

8. if (displayItem == null) {

9. continue;

10. } else {

11. Texture texture =

mbnailImage(context, sThumbnailConfig);

12. if (texture != null && ed() == false)

{

13. startSlotIndex = j;

14. break;

15. }

16. }

17. }

18. }

复制代码

priority表示当前槽位在[firstVisibleSlot,lastVisibleSlot]范围中,则为高优先级,可见槽位上的自然是最高优先级喽;

maxDisplayedItemsPerSlot表示每个槽位中最多的显示项目,即每个相册封面的最大缩略图数,此处为4;

startSlotIndex是当前帧每个相册中“需要绘制“的最开头那张照片的序号(取值在0-3之间),注意“需要绘制“的最开头那张照片往往不是相册中的第一张照片,帧动画开始时它通常是第四张照片(第四张被依次压在321张照片下面嘛,因此绘制加载材质都要按照第四张向首张的次序),随着动画和材质逐步加载,它慢慢变为第三张、第二张、第一张。

从第四张向第一张加载材质

1. // Prime the textures in the reverse order.

2. for (int j = 0; j < maxDisplayedItemsPerSlot; ++j) {

3. int stackIndex = (index == mCurrentScaleSlot) ?

maxDisplayedItemsPerSlot - j - 1 : j;

4. DisplayItem displayItem = displayItems[(index -

firstBufferedVisibleSlot) * _ITEMS_PER_SLOT

5. + stackIndex];

6. if (displayItem == null) {

7. continue;

8. } else {

9. ntSlotIndex = index;

10. if (selectedSlotIndex != D && (index <=

selectedSlotIndex - 2 || index >= selectedSlotIndex + 2)) {

11. creennailImage();

12. }

13.

14. Texture texture =

mbnailImage(context, sThumbnailConfig);

15. if (index == mCurrentScaleSlot && texture != null

&& !ed()) {

16. (texture, true);

17. (texture);

18. } else if (texture != null && !ed() /*&&

numTexturesQueued <= 6*/) {

19. /*boolean isCached = ed();*/

发布评论

评论列表 (0)

  1. 暂无评论