您的位置:首页 > 移动开发 > Android开发

Android OpenGL ES 开发教程(19):绘制迷你太阳系

2012-11-30 14:49 330 查看



前面介绍了3D坐标系统和3D坐标变换以及在OpenGLES中坐标变换的过程,并与相机拍照片的过程做类比,以便更好的理解这OpenGL中构造3D模型的一部步骤:



本例提供绘制一个迷你太阳系系统作为前面知识的总结,这个迷你太阳系,有一个红色的太阳,一个蓝色的地图和一个白色的月亮构成:

太阳居中,逆时针自转。
地球绕太阳顺时针公转,本身不自转。
月亮绕地球顺时针公转,自身逆时针自转。

为简单起见,使用一个2D五角星做为天体而没有使用球体(绘制球体在后面有介绍),构造一个Star类:

查看源代码

打印帮助

1
public
class
Star{
2
//Ourvertices.
3
protected

float
vertices[];

4
5
//Ourvertexbuffer.
6
protected

FloatBuffervertexBuffer;
7
8
public

Star(){
9
10
float

a=(
float
)(
1
.0f/(
2
.0f-2f*Math.cos(72f*Math.PI/
180
.f)));
11
float

bx=(
float
)(a*Math.cos(
18
*Math.PI/
180
.0f));
12
float

by=(
float
)(a*Math.sin(
18
*Math.PI/180f));
13
float

cy=(
float
)(-a*Math.cos(
18
*Math.PI/180f));
14
vertices=
new

float
[]{
15
0
,a,
0
.5f,cy,-bx,by,bx,by,-
0
.5f,cy
16
};

17
18
ByteBuffervbb
19
=ByteBuffer.allocateDirect(vertices.length*
4
);
20
vbb.order(ByteOrder.nativeOrder());
21
vertexBuffer=vbb.asFloatBuffer();
22
vertexBuffer.put(vertices);
23
vertexBuffer.position(
0
);
24
25
}

26
27
/**
28
*Thisfunctiondrawsourstaronscreen.
29
*@paramgl
30
*/
31
public

void
draw(GL10gl){

32
//Counter-clockwisewinding.
33
gl.glFrontFace(GL10.GL_CCW);
34
//Enablefaceculling.
35
gl.glEnable(GL10.GL_CULL_FACE);
36
//Whatfacestoremovewiththefaceculling.
37
gl.glCullFace(GL10.GL_BACK);
38
39
//Enabledtheverticesbufferforwriting
40
//andtobeusedduring
41
//rendering.
42
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
43
//Specifiesthelocationanddataformatof
44
//anarrayofvertex
45
//coordinatestousewhenrendering.
46
gl.glVertexPointer(
2
,GL10.GL_FLOAT,
0
,
47
vertexBuffer);
48
49
gl.glDrawArrays(GL10.GL_LINE_LOOP,
0
,
5
);
50
51
//Disabletheverticesbuffer.
52
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
53
//Disablefaceculling.
54
gl.glDisable(GL10.GL_CULL_FACE);
55
}

56
57
}
Star定义了五角星的五个顶点,并使用glDrawArrays来绘制五角星,因此vertices顶点的顺序比较重要。

然后定义一个DrawSolarSystem来绘制这个迷你太阳系:

查看源代码

打印帮助

1
public
class
DrawSolarSystem
extends

OpenGLESActivity
2
implements

IOpenGLDemo{
3
4
private

Starsun=
new

Star();
5
private

Starearth=
new

Star();
6
private

Starmoon=
new

Star();
7
8
private

int
angle=
0
;
9
10
/**Calledwhentheactivityisfirstcreated.*/
11
@Override
12
public

void
onCreate(BundlesavedInstanceState){
13
super
.onCreate(savedInstanceState);
14
15
}

16
17
public

void
DrawScene(GL10gl){
18
super
.DrawScene(gl);
19
gl.glLoadIdentity();
20
GLU.gluLookAt(gl,
0
.0f,
0
.0f,
15
.0f,
21
0
.0f,
0
.0f,
0
.0f,
22
0
.0f,
1
.0f,
0
.0f);
23
//StarA
24
//Savethecurrentmatrix.
25
gl.glPushMatrix();
26
//RotateStarAcounter-clockwise.
27
gl.glRotatef(angle,
0
,
0
,
1
);
28
gl.glColor4f(
1
.0f,
0
.0f,
0
.0f,
1
.0f);
29
//DrawStarA.
30
sun.draw(gl);
31
//Restorethelastmatrix.
32
gl.glPopMatrix();
33
//StarB
34
//Savethecurrentmatrix
35
gl.glPushMatrix();
36
//RotateStarBbeforemovingit,
37
//makingitrotatearoundA.
38
gl.glRotatef(-angle,
0
,
0
,
1
);
39
//MoveStarB.
40
gl.glTranslatef(
3
,
0
,
0
);
41
//Scaleitto50%ofStarA
42
gl.glScalef(.5f,.5f,.5f);
43
gl.glColor4f(
0
.0f,
0
.0f,
1
.0f,
1
.0f);
44
//DrawStarB.
45
earth.draw(gl);
46
//StarC
47
//Savethecurrentmatrix
48
gl.glPushMatrix();
49
//MaketherotationaroundB
50
gl.glRotatef(-angle,
0
,
0
,
1
);
51
gl.glTranslatef(
2
,
0
,
0
);
52
//Scaleitto50%ofStarB
53
gl.glScalef(.5f,.5f,.5f);
54
//Rotatearoundit'sowncenter.
55
gl.glRotatef(angle*
10
,
0
,
0
,
1
);
56
gl.glColor4f(
1
.0f,
1
.0f,
1
.0f,
1
.0f);
57
//DrawStarC.
58
moon.draw(gl);
59
//RestoretothematrixasitwasbeforeC.
60
gl.glPopMatrix();
61
//RestoretothematrixasitwasbeforeB.
62
gl.glPopMatrix();
63
//Incresetheangle.
64
angle++;
65
66
}

67
68
}
使用GLU的gluLookAt来定义modelviewMatrix,把相机放在正对太阳中心(0,0,0),距离15(0,0,15)。

使用glPushMatrix和glPopMatrix来将当前Matrix入栈或是出栈。

首先将当前matrix入栈,以红色绘制太阳,并逆向转动,将当前matrix入栈的目的是在能够在绘制地球时恢复当前栈。

然后绘制地球,使用局部坐标系来想象地球和太阳之间的相对运动,地球离开一距离绕太阳公转,相当于先旋转地球的局部坐标系,然后再平移地球的局部坐标系。对应到代码为先glRotatef,然后glTranslate.

最后是绘制月亮,使用类似的空间想象方法。



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: