(四)使用投影和相机视角(Applying Projection and Camera Views)

字数 1262阅读 266

原文:https://developer.android.com/training/graphics/opengl/projection.html##transform

In the OpenGL ES environment, projection and camera views allow you to display drawn objects in a way that more closely resembles how you see physical objects with your eyes. This simulation of physical viewing is done with mathematical transformations of drawn object coordinates:
在 OpenGL ES环境中,投影和相机视角可以让画出来的图形模拟一种人眼看真实物体的方式显示。这种视角是通过将绘制图形的坐标进行数学变换实现的。

  • Projection - This transformation adjusts the coordinates of drawn objects based on the width and height of the GLSurfaceView where they are displayed. Without this calculation, objects drawn by OpenGL ES are skewed by the unequal proportions of the view window. A projection transformation typically only has to be calculated when the proportions of the OpenGL view are established or changed in the onSurfaceChanged() method of your renderer. For more information about OpenGL ES projections and coordinate mapping, see Mapping Coordinates for Drawn Objects.
    投影- 这个变换根据GLSurfaceView的宽高来调节绘制物体的坐标。没有这些转换计算,OpenGL ES 绘制出来的形状会因为GLSurfaceView所在的window比例不同而变形。只需要在OpenGL view建立时,或者在render的onSurfaceChanged()方法中进行投影变换。关于更多的OpenGL ES 投影和坐标映射,可以看映射绘制物体的坐标

  • Camera View - This transformation adjusts the coordinates of drawn objects based on a virtual camera position. It’s important to note that OpenGL ES does not define an actual camera object, but instead provides utility methods that simulate a camera by transforming the display of drawn objects. A camera view transformation might be calculated only once when you establish your GLSurfaceView, or might change dynamically based on user actions or your application’s function.
    This lesson describes how to create a projection and camera view and apply it to shapes drawn in your GLSurfaceView.
    相机视角- 这个转换是根据一个虚拟的相机位置来调节绘制物体的坐标。需要注意的是,OpenGL ES并没有定义一个真实的相机对象,而且提供一个转变绘制形状显示的方法来模拟一个相机。相机视角转换可能只计算一次,也可能因为应用功能的不同而动态变换。
    这里主要讲解如何建立投影和相机视角,并把它应用到GLSurfaceView绘制的图形上。

Define a Projection

定义投射

The data for a projection transformation is calculated in the onSurfaceChanged() method of your GLSurfaceView.Renderer class. The following example code takes the height and width of the GLSurfaceView and uses it to populate a projection transformation Matrix using the Matrix.frustumM() method:
投影变换的数据是在GLSurfaceView.Renderer的onSurfaceChanged() 方法中进行计算的。接下来的示例代码中,利用GLSurfaceView的宽高和Matrix.frustumM() 方法来生成一个投影变换矩阵(Maxtrix)。

// mMVPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];

@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
    GLES20.glViewport(0, 0, width, height);

    float ratio = (float) width / height;

    // this projection matrix is applied to object coordinates
    // in the onDrawFrame() method
    Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);//wtf is -1,1,3,7?
}

This code populates a projection matrix, mProjectionMatrix which you can then combine with a camera view transformation in the onDrawFrame() method, which is shown in the next section.
这段代码生成了一个投影矩阵(mProjectionMatrix),在下一节中的onDrawFrame() 方法中,你可以把它和相机视角矩阵结合起来

  • Note: Just applying a projection transformation to your drawing objects typically results in a very empty display. In general, you must also apply a camera view transformation in order for anything to show up on screen.
    注意:对绘制图形只使用投影变换会导致没有任何内容显示。一般来说,为了让屏幕上显示正确的内容,你必须应用相机视角变换。

Define a Camera View

定义相机视角

Complete the process of transforming your drawn objects by adding a camera view transformation as part of the drawing process in your renderer. In the following example code, the camera view transformation is calculated using the Matrix.setLookAtM() method and then combined with the previously calculated projection matrix. The combined transformation matrices are then passed to the drawn shape.
做为renderer绘制的一部分,需要把相机视角变换加进来完善转换过程。在下面的代码中,用Matrix.setLookAtM() 方法来计算相机视角,然后把之前计算好的投影矩阵结合使用。把结合后的变换矩阵再传递给绘制图形。

@Override
public void onDrawFrame(GL10 unused) {
    ...
    // Set the camera position (View matrix)
    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    // Calculate the projection and view transformation
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);

    // Draw shape
    mTriangle.draw(mMVPMatrix);
}

Apply Projection and Camera Transformations

应用投影和相机视频变换

In order to use the combined projection and camera view transformation matrix shown in the previews sections, first add a matrix variable to the vertex shader previously defined in the Triangle class:
为了使用前的小节中投影和相机视角变换结合后的矩阵,首先添加一个矩阵变量到之前定义的Triangle类的顶点shader中。

public class Triangle {

    private final String vertexShaderCode =
        // This matrix member variable provides a hook to manipulate
        // the coordinates of the objects that use this vertex shader
        "uniform mat4 uMVPMatrix;" +
        "attribute vec4 vPosition;" +
        "void main() {" +
        // the matrix must be included as a modifier of gl_Position
        // Note that the uMVPMatrix factor *must be first* in order
        // for the matrix multiplication product to be correct.
        "  gl_Position = uMVPMatrix * vPosition;" +
        "}";

    // Use to access and set the view transformation
    private int mMVPMatrixHandle;

    ...
}

Next, modify the draw() method of your graphic objects to accept the combined transformation matrix and apply it to the shape:
接下来,修改形状的draw()方法,增加一个结合的变换矩阵做为参数,把这个参数应用到形状上来。

public void draw(float[] mvpMatrix) { // pass in the calculated transformation matrix
    ...

    // get handle to shape's transformation matrix
    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");

    // Pass the projection and view transformation to the shader
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

    // Draw the triangle
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

    // Disable vertex array
    GLES20.glDisableVertexAttribArray(mPositionHandle);
}

Once you have correctly calculated and applied the projection and camera view transformations, your graphic objects are drawn in correct proportions and should look like this:
如果你的正确地计算和应用了投影和相机视角变换,你的图形正确地绘制如下图所示:

Figure 1. Triangle drawn with a projection and camera view applied.

Now that you have an application that displays your shapes in correct proportions, it's time to add motion to your shapes.
现在你的应用能正确地显示形状了,该让形状动起来了。下一课

推荐阅读更多精彩内容