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。
View Code
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中判断的当前面,通过下面函数得到需要旋转的角度。
View Code
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.添加地面和倒影,美化下。
补张透明的实验品: