Android 3D game tutorial – Part VI

Updated to be Android 2.0.1 compatible.

You are new to this series? Please start with the first part .

The sixth part of this series will show you how you create the correct perspective because 3D is nothing without the correct perspective.

Before we start we should discuss the two possible “views” OpenGL offers: orthographic and perspective.

Orthographic (non vanish point projection)
The orthographic view is a view that makes it impossible to see if a object is right in front of us or far away. Why? Because it doesn’t shrink in the distance. So if you will draw an object with the a specific size near the viewport and another object with the same size far behind the first one but a bit to one side (to be sure that the first object doesn’t stand in the view), you won’t be able to say which element is the first one. Because both will have the same size independent of their distance. They simply don’t shrink with the distance.

Perspective (vanish point projection)
The perspective view is the view we know from our eyes. An example: A tall guy in front of you is, of course, tall. If this guy is 100 meter away, he is not as tall as your thumb. He seems to shrink in the distance but we know of course, he stays tall. That effect is called perspective. For our example with the two objects, the second one will be much smaller so we can say in an instance, that this is far away and the other one is right in front of us.

Because my example might confuse you, I recommend again a blog post of iPhone development: OpenGL ES From the Ground Up, Part 3: Viewports in Perspective which uses railroad tracks as an example.

The first view we want to create is the one using the orthographic. The view setup is something we usually do just once or, in case we change the rotation, we do it every time the surface is created. Thats the reason why we should change a bit. So some code we have in our onDrawFrame() method will be moved to the onSurfaceCreated() method. There it should only be executed if we start the application or change the rotation.

You see that we didn’t move the glClear() and the glLoadIdentity() method from onDrawFrame() to onSurfaceCreated(). The reason is easy: they should be called on every frame.

Because we need the screen size to calculate the ratio of our screen we introduce two object variables called _width and _height. An we need to set them in the method onSurfaceChanged() which will be called on every rotation change.

Now we have everything we need to start with the viewport. We need to change the onSurfaceCreated() method.

Wow this is a lot of new code! Don’t worry we will go step by step.
On line 3 we see the glMatrixMode() with GL10.GL_PROJECTION as parameter and on line 8 we see the method again but with the GL10.GL_MODELVIEW as parameter. The reasons are in the lines between line 3 and line 8. In the lines 4 till 7 we set up our viewport, so we set up our projection. On line 9 till 17 we set up our model environment. In this context both calls with different parameter should be understandable. Tip: As always simply try to get rid of some code lines and see the result. Thats the best way to understand what line of code is responsible for what.
On line 4 we calculate our screen ratio we need for the next line. On this line (line 6) we set our viewport to make a orthographic view. The parameter are for the border in the order of left, right, bottom, top, zNear, zFar.
On line 7 we set the viewport. We know this method because we already used it in onSurfaceChanged().
On line 8 we switch the MatrixMode to GL10.GL_MODELVIEW which set OpenGL to accept some calls which change the way models should be drawn.
On line 9 we call glEnable() with the parameter GL10.GL_DEPTH_TEST. That enabled that OpenGL ES check which z-order the objects have. If we don’t enable that, we will see the last drawn object always in front of all other objects. That means even if this object should be hidden by another much nearer and bigger object, we will see the first one in front of it.
The other lines of code we already know from the previous parts of this series.

The perspective view is nearly the same but instead of calling glOrthof() we will call glFrustumf().
The parameters for glFrustumf() will be a bit different from the parameters we used for glOrthof(). The reason therefor is, that we didn’t shrink the objects but we the defined frustum will be funnel-formed. Look at these pictures to see the difference between glOrthof() and glFrustumf():

Orthographic:
tutorial_orthographic

Perspective:
tutorial_perspective

Back to the code:

Information: The calculation of our variable size (on line 5) is something
we should take on faith, we will see why it works when we talk about matrices.

On line 8 we now have glFrustumf() instead of glOrthof(). Thats all we have to change between orthographic view and perspective view.

But hey, with just one object we won’t see any changes. Ok lets change the method onDrawFrame().

Ok, what have changed?
On line 3 we have now modified parameter to be sure that the depth buffer will be cleared to.
On line 9 we started a loop to create 10 objects.
On line 10 we see the missing glLoadIdentity(). It is now located here to reset the matrix. Thats have to be done because we will use glRotatef() and glTranslatef() to modify our objects. But to be sure that we only modify the object we are currently looping over, we call glLoadIdentity(). So we “reset” every glTranslatef() and glRotatef() call we made for the previous object.
On line 11 we see the new glTranslatef() method which will move our object to another location. In our case we don’t change the location on the x axis, but we change -1.0f on the y axis which means it will be near the bottom of our screen. The last calculation you see is simply to modify the position on the z axis, which means the depth, of your object. The first object will be on -2.5f, the second on -4.0f and so on. So we should see 10 objects lined up to the middle of our screen.

If you compile that using the glFrustumf() call, you should see that:

3d-part-six-line-frustum

If you switch the lines glFrustumf() and glOrthof() you should see that:

3d-part-six-line-ortho

Hey wait, why do we not see more than one object? Because in orthographic we don’t have any kind of perspective. So every single object has the same size and doesn’t shrink so it won’t follow any vanish point and without that, each object is exactly behind the first one.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值