【附源码】【Android 3D OpenGL】开发之四——投影中的正交与透视【MacroCheng原创】

一、正交与透视

1.1、正交Orthographic (无消失点投影)

正交视图无法看到一个物体是远离自己还是正在我们面前。为什么?因为它不会根据距离收缩。所以如果你如果你画一个固定大小的物体在视点前面,同时画一个同样大小的物体在第一个物体的远后方,你无法说那个物体是第一个。因为两个都是一样的大小,根距离无关。他们不会随着距离而收缩。

1.2、透视Perspective (有消失点投影)

    透视视图和我们从眼睛看到的视图是一样的。例如,一个高个子的人站在你面前,你看上去是很高的。如果这个人站在100米以外,他甚至还没有你的拇指大。他看上去会随着距离而缩小,但是我们实际上都知道,它依然是个高个子。这种效果叫做透视。上面例子中提到的两个物体,第二个物体将会显示地更小,所以我们可以区分哪个是离我们近的物体,那个是离我们远的物体。

 

二、关键方法说明

2.1glMatrixMode(GL_PROJECTION)

指明接下来的两行代码将影响projection matrix(投影矩阵)。投影矩阵负责为我们的场景增加透视。

2.2glMatrixMode(GL_MODELVIEW)

指明任何新的变换将会影响 modelview matrix(模型观察矩阵)。模型观察矩阵中存放了我们的物体讯息。

2.3gl.glOrthof()

    设置我们的视点来做orthographic view。这些参数是为边界设定,顺序是这样的:left, right, bottom, top, zNear, zFar

2.4glFrustumf()

    glFrustumf()函数的参数和glOrthof()的参数略有不同。因为我们没有缩小物体,但是我们定义的锥体将被漏斗状切开。

 

三、正交和透视效果对比

3.1、正交图片

跟只有一个金字塔看起来效果是一摸一样的,但是其实我们有建立10个金字塔的,看下面透视效果就知道了。

3.2、正交的核心语句

gl.glOrthof(-1,1,-1/ratio,1/ratio,0.01f,100.0f);

//gl.glFrustumf(-size, size, -size / ratio, size / ratio, 0.01f, 100.0f);

3.3、透视图片

3.4、透视核心语句

//gl.glOrthof(-1,1,-1/ratio,1/ratio,0.01f,100.0f);

gl.glFrustumf(-size, size, -size / ratio, size / ratio, 0.01f, 100.0f);

 

四、OpenGLRenderer.java

因为其他的都没动,就动了这个类,所以仅贴出这个类得代码

package com.macrocheng.opengl3d01;

 

import javax.microedition.khronos.egl.EGLConfig;

import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView;

 

public class OpenGLRenderer implements GLSurfaceView.Renderer {

    private static final String LOG = OpenGLRenderer.class.getSimpleName();

    private float red = 0.9f;

    private float green = 0.2f;

    private float blue = 0.2f;

   

    private Triangle tr;

   

    private float xAngle;

    private float yAngle;

   

    private Pyramid py;

   

    private float _width = 320f ;

    private float _height = 480f ;

   

    @Override

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

        // TODO Auto-generated method stub

        //tr = new Triangle();

        /**

         * 指明接下来的两行代码将影响projection matrix(投影矩阵)

         * 投影矩阵负责为我们的场景增加透视。

         */

        gl.glMatrixMode(GL10.GL_PROJECTION);

       

        float size = 0.01f*(float)Math.tan(Math.toRadians(45.0)/2);

        float ratio = _width/_height;

        gl.glOrthof(-1,1,-1/ratio,1/ratio,0.01f,100.0f);

        //gl.glFrustumf(-size, size, -size / ratio, size / ratio, 0.01f, 100.0f);

        gl.glViewport(0, 0, (int)_width, (int)_height);

        /**

         * 指明任何新的变换将会影响 modelview matrix(模型观察矩阵)

         * 模型观察矩阵中存放了我们的物体讯息。

         */

        gl.glMatrixMode(GL10.GL_MODELVIEW);

        /**

         * 这使OpenGL ES检查对象的z-order

         * 如果我们没有enable它,我们将看到最后被绘制的对象一直显示在最前面。

         * 这意味着,及时即使这个物体本来应该被更近更大的物体遮盖,我们依然可以看到它。

         */

        gl.glEnable(GL10.GL_DEPTH_TEST);

       

        py = new Pyramid();

        /**

         * 决定哪一面可见,让正面可见

         */

        gl.glEnable(GL10.GL_CULL_FACE);

        /**

         * 逆时针方向的面为前面,前面就被画出来

         */

        gl.glFrontFace(GL10.GL_CCW);

        /**

         * 后面就不需要被画出来

         */

        gl.glCullFace(GL10.GL_BACK);

       

        /**

         * 设置OpenGL使用vertex数组来画

         */

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        /**

         * 设置颜色来自数组

         */

        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);       

    }

   

    @Override

    public void onSurfaceChanged(GL10 gl, int width, int height) {

        // TODO Auto-generated method stub

        _width = width;

        _height = height;

        gl.glViewport(0, 0, width, height);

    }

   

    @Override

    public void onDrawFrame(GL10 gl) {

        // TODO Auto-generated method stub

        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        /**

         * 为了让颜色变化可见,我们必须调用glClear()以及颜色缓冲的Mask来清空buffer

         * 然后为我们的底色使用新的底色。

         */

        //gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

       

        /**

         * 我们通过glClearColor()方法为底色定义了颜色。

         * 底色是在我们能看到的所有东西的后面,所以所有在底色后面的东西都是不可见的。

         * 可以想象这种东西为浓雾,挡住了所有的东西。

         */

        gl.glClearColor(red, green, blue, 1.0f);

       

        //清除颜色的Buffer然后让现实上面我们通过glClearColor来定义的颜色

        for(int i=0;i<10;i++)

        {

            /**

             *  重置当前的模型观察矩阵

             *  近似于重置。它将所选的矩阵状态恢复成其原始状态

             */

            gl.glLoadIdentity();

            gl.glTranslatef(0.0f, -1f, -1.0f + -1.5f * i);

            /**

             * 旋转,四个参数分别是旋转度、x轴、y轴、z

             * 后面三个值来决定围绕那个轴线来旋转

             */

            gl.glRotatef(xAngle, 1f, 0f, 0f);

            gl.glRotatef(yAngle, 0f, 1f, 0f);

            /**

             * 第一个参数是大小,也是顶点的维数。我们使用的是x,y,z三维坐标。

             * 第二个参数,GL_FLOAT定义buffer中使用的数据类型。

             * 第三个变量是0,是因为我们的坐标是在数组中紧凑的排列的,没有使用offset

             * 最后,第四个参数顶点缓冲。

             */

            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, py.getVertexBuffer());

            /**

             * 参数4表示RGBA(RGBA刚好是四个值),其余的几个参数大家都比较熟悉了。

             */

            gl.glColorPointer(4, GL10.GL_FLOAT, 0, py.getColorBuffer());

            /**

             * 将所有这些元素画出来。第一个参数定义了什么样的图元将被画出来。

             * 第二个参数定义有多少个元素,

             * 第三个是indices使用的数据类型。

             * 最后一个是绘制顶点使用的索引缓冲。

             */

            gl.glDrawElements(GL10.GL_TRIANGLES, py.getNumberOfPoint(), GL10.GL_UNSIGNED_SHORT, py.getIndexBuffer());

        }

    }

   

    public float getXAngle() {

        return xAngle;

    }

 

    public float getYAngle() {

        return yAngle;

    }

 

    public void setYAngle(float angle) {

        yAngle = angle;

    }

 

    public void setXAngle(float angle) {

        xAngle = angle;

    }

 

    /**

     * 设置颜色的值

     * @param r Red

     * @param g Green

     * @param b Blue

     */

    public void setColor(float r,float g,float b)

    {

        red = r;

        green = g;

        blue = b;

    }

   

    /**

     * 设置三角形的旋转度

     * @param x x轴上的旋转度

     * @param y y轴上的旋转度

     */

    public void setAngle(float x,float y)

    {

        xAngle = x;

        yAngle = y;

    }

}

 

 

源码下载地址

posted @ 2011-09-21 10:06  MacroCheng  阅读(4084)  评论(0编辑  收藏  举报