3D Launcher 有两种方法实现,一种是假3D,用动画实现,另一种真3D使用OpenGL。
一,使用动画
参考http://www.ibm.com/developerworks/cn/opensource/os-cn-android-anmt2/index.html 实现。
目前效果不是很好,还在修改。主要是旋转轴的问题,假3D其实是把2维图像进行变换,变换后的图像看起来像3D的样子
,所以假3D旋转时,那个旋转轴要平移,效果才好看些。
看了几款手机的Launcher 3D效果,估计都是通过这种方法实现的。
二,使用OpenGL实现真3D Launcher
Android源代码使用的是5个cellLayout,为了建模方便,计算简单,使用四方体,忽略了绕X轴的旋转。
主要方法如下:
1.建立四方体。
2.celllayout抓图,生成纹理,之前见网上说纹理长宽需要是2的N次方,才能显示。经过实验,发现不一定需要
2的N次方,生成的纹理在模拟器和G6,还有一块板子上跑,都正常显示。
3. 旋转后,松开鼠标,判断四个面,哪个面是当前workspace。


1
public
int
computeFace()
2 {
3 // Log.d("GLRender","yrot:" +String.valueOf(yrot) );
4 float angle = baseRadian * yrot;
5
6 float []front = rotateAngle(angle, frontNormal);
7 float []right = rotateAngle(angle, rightNormal);
8 float []back = rotateAngle(angle, backNormal);
9 float []left = rotateAngle(angle, leftNormal);
10
11 float frontDot = dot(front, sightNormal);
12 float rightDot = dot(right, sightNormal);
13 float backDot = dot(back, sightNormal);
14 float leftDot = dot(left, sightNormal);
15
16 /* Log.d("GLRender","frontDot:" +String.valueOf(frontDot) );
17 Log.d("GLRender","rightDot:" +String.valueOf(rightDot) );
18 Log.d("GLRender","backDot:" +String.valueOf(backDot) );
19 Log.d("GLRender","leftDot:" +String.valueOf(leftDot) ); */
20
21 if ((frontDot < rightDot) && (frontDot < backDot) && (frontDot < leftDot))
22 {
23 return 2 ; // front
24 }
25 else if ((rightDot < frontDot) && (rightDot < backDot) && (rightDot < leftDot))
26 {
27 return 3 ; // right
28 }
29 else if ((backDot < frontDot) && (backDot < rightDot) && (backDot < leftDot))
30 {
31 return 0 ; // back
32 }
33 else
34 {
35 return 1 ; // left
36 }
37
2 {
3 // Log.d("GLRender","yrot:" +String.valueOf(yrot) );
4 float angle = baseRadian * yrot;
5
6 float []front = rotateAngle(angle, frontNormal);
7 float []right = rotateAngle(angle, rightNormal);
8 float []back = rotateAngle(angle, backNormal);
9 float []left = rotateAngle(angle, leftNormal);
10
11 float frontDot = dot(front, sightNormal);
12 float rightDot = dot(right, sightNormal);
13 float backDot = dot(back, sightNormal);
14 float leftDot = dot(left, sightNormal);
15
16 /* Log.d("GLRender","frontDot:" +String.valueOf(frontDot) );
17 Log.d("GLRender","rightDot:" +String.valueOf(rightDot) );
18 Log.d("GLRender","backDot:" +String.valueOf(backDot) );
19 Log.d("GLRender","leftDot:" +String.valueOf(leftDot) ); */
20
21 if ((frontDot < rightDot) && (frontDot < backDot) && (frontDot < leftDot))
22 {
23 return 2 ; // front
24 }
25 else if ((rightDot < frontDot) && (rightDot < backDot) && (rightDot < leftDot))
26 {
27 return 3 ; // right
28 }
29 else if ((backDot < frontDot) && (backDot < rightDot) && (backDot < leftDot))
30 {
31 return 0 ; // back
32 }
33 else
34 {
35 return 1 ; // left
36 }
37
5.自动旋转到3中判断的当前面,通过下面函数得到需要旋转的角度。


1
public
float
getDeltaAngle(
float
yRot)
2 {
3 if (yRot > 0 )
4 {
5 if (yRot < 90 )
6 {
7 if (yRot >= 45 )
8 return 90 - yRot;
9 else
10 return - yRot;
11 }
12 else if (yRot >= 90 && yRot < 180 )
13 {
14 if (yRot >= 135 )
15 return 180 - yRot;
16 else
17 return - (yRot - 90 );
18 }
19 else if (yRot >= 180 && yRot < 270 )
20 {
21 if (yRot >= 225 )
22 return 270 - yRot;
23 else
24 return - (yRot - 180 );
25 }
26 else
27 {
28 if (yRot >= 315 )
29 return 360 - yRot;
30 else
31 return - (yRot - 270 );
32 }
33 }
34 else if (yRot < 0 )
35 {
36 if (yRot > - 90 )
37 {
38 if (yRot >= - 45 )
39 return - yRot;
40 else
41 return - ( 90 + yRot);
42 }
43 else if (yRot <= - 90 && yRot > - 180 )
44 {
45 if (yRot >= - 135 )
46 return - (yRot + 90 );
47 else
48 return - ( 180 + yRot);
49 }
50 else if (yRot <= - 180 && yRot > - 270 )
51 {
52 if (yRot >= - 225 )
53 return - ( 180 + yRot);
54 else
55 return - ( 270 + yRot);
56 }
57 else
58 {
59 if (yRot >= - 315 )
60 return - ( 270 + yRot);
61 else
62 return - ( 360 + yRot);
63 }
64 }
65
66 return 0 ;
67 }
68
2 {
3 if (yRot > 0 )
4 {
5 if (yRot < 90 )
6 {
7 if (yRot >= 45 )
8 return 90 - yRot;
9 else
10 return - yRot;
11 }
12 else if (yRot >= 90 && yRot < 180 )
13 {
14 if (yRot >= 135 )
15 return 180 - yRot;
16 else
17 return - (yRot - 90 );
18 }
19 else if (yRot >= 180 && yRot < 270 )
20 {
21 if (yRot >= 225 )
22 return 270 - yRot;
23 else
24 return - (yRot - 180 );
25 }
26 else
27 {
28 if (yRot >= 315 )
29 return 360 - yRot;
30 else
31 return - (yRot - 270 );
32 }
33 }
34 else if (yRot < 0 )
35 {
36 if (yRot > - 90 )
37 {
38 if (yRot >= - 45 )
39 return - yRot;
40 else
41 return - ( 90 + yRot);
42 }
43 else if (yRot <= - 90 && yRot > - 180 )
44 {
45 if (yRot >= - 135 )
46 return - (yRot + 90 );
47 else
48 return - ( 180 + yRot);
49 }
50 else if (yRot <= - 180 && yRot > - 270 )
51 {
52 if (yRot >= - 225 )
53 return - ( 180 + yRot);
54 else
55 return - ( 270 + yRot);
56 }
57 else
58 {
59 if (yRot >= - 315 )
60 return - ( 270 + yRot);
61 else
62 return - ( 360 + yRot);
63 }
64 }
65
66 return 0 ;
67 }
68
4.添加地面和倒影,美化下。
补张透明的实验品: