官术网_书友最值得收藏!

Hello, cube!

A flat triangle floating in 3D space may be amazing, but it's nothing compared to what we're going to do next: a 3D cube!

The cube model data

The triangle, with just three vertices, was declared in the MainActivity class to keep the example simple. Now, we will introduce more complex geometry. We'll put it in a class named Cube.

Okay, it's just a cube that is composed of eight distinct vertices, forming six faces, right?

Well, GPUs prefer to render triangles rather than quads, so subdivide each face into two triangles; that's 12 triangles in total. To define each triangle separately, that's a total of 36 vertices, with proper winding directions, defining our model, as shown in CUBE_COORDS. Why not just define eight vertices and reuse them? We'll show you how to do this later.

Note

Remember that we always need to be careful of the winding order of the vertices (counter-clockwise) so that the visible side of each triangle is facing outward.

In Android Studio, in the Android project hierarchy pane on the left-hand side, find your Java code folder (such as com.cardbookvr.cardboardbox). Right-click on it, and go to New | Java Class. Then, set Name: Cube, and click on OK. Then, edit the file, as follows (remember that the code for the projects in this book are available for download from the publisher's website and from the book's public GitHub repositories):

package com.cardbookvr.cardboardbox;

public class Cube {

    public static final float[] CUBE_COORDS = new float[] {
        // Front face
        -1.0f, 1.0f, 1.0f,
        -1.0f, -1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,
        -1.0f, -1.0f, 1.0f,
        1.0f, -1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,

        // Right face
        1.0f, 1.0f, 1.0f,
        1.0f, -1.0f, 1.0f,
        1.0f, 1.0f, -1.0f,
        1.0f, -1.0f, 1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f, 1.0f, -1.0f,

        // Back face
        1.0f, 1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        -1.0f, 1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f, -1.0f,
        -1.0f, 1.0f, -1.0f,

        // Left face
        -1.0f, 1.0f, -1.0f,
        -1.0f, -1.0f, -1.0f,
        -1.0f, 1.0f, 1.0f,
        -1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f,

        // Top face
        -1.0f, 1.0f, -1.0f,
        -1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, -1.0f,
        -1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, -1.0f,

        // Bottom face
        1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, 1.0f,
        -1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, 1.0f,
        -1.0f, -1.0f, 1.0f,
        -1.0f, -1.0f, -1.0f,
    };
}

Cube code

Returning to the MainActivity file, we'll just copy/paste/edit the triangle code and reuse it for the cube. Obviously, this isn't ideal, and once we see a good pattern, we can abstract out some of this into reusable methods. Also, we'll use the same shaders as those of the triangle, and then in the next section, we'll replace them with a better lighting model. That is to say, we'll implement lighting or what a 2D artist might call shading, which we haven't done so far.

Like the triangle, we declare a bunch of variables that we are going to need. The vertex count, obviously, should come from the new Cube.CUBE_COORDS array:

    // Model variables
    private static float cubeCoords[] = Cube.CUBE_COORDS;
    private final int cubeVertexCount = cubeCoords.length / COORDS_PER_VERTEX;
    private float cubeColor[] = { 0.8f, 0.6f, 0.2f, 0.0f }; // yellow-ish
    private float[] cubeTransform;
    private float cubeDistance = 5f;

    // Viewing variables
    private float[] cubeView;

    // Rendering variables
    private FloatBuffer cubeVerticesBuffer;
    private int cubeProgram;
    private int cubePositionParam;
    private int cubeColorParam;
    private int cubeMVPMatrixParam;

Add the following code to onCreate:

        cubeTransform = new float[16];
        cubeView = new float[16];

Add the following code to onSurfaceCreated:

        prepareRenderingCube();

Write the prepareRenderingCube method, as follows:

private void prepareRenderingCube() {
        // Allocate buffers
        ByteBuffer bb = ByteBuffer.allocateDirect(cubeCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        cubeVerticesBuffer = bb.asFloatBuffer();
        cubeVerticesBuffer.put(cubeCoords);
        cubeVerticesBuffer.position(0);

        // Create GL program
        cubeProgram = GLES20.glCreateProgram();
        GLES20.glAttachShader(cubeProgram, simpleVertexShader);
        GLES20.glAttachShader(cubeProgram, simpleFragmentShader);
        GLES20.glLinkProgram(cubeProgram);
        GLES20.glUseProgram(cubeProgram);

        // Get shader params
        cubePositionParam = GLES20.glGetAttribLocation(cubeProgram, "a_Position");
        cubeColorParam = GLES20.glGetUniformLocation(cubeProgram, "u_Color");
        cubeMVPMatrixParam = GLES20.glGetUniformLocation(cubeProgram, "u_MVP");

        // Enable arrays
        GLES20.glEnableVertexAttribArray(cubePositionParam);
    }

We will position the cube 5 units away and rotate it 30 degrees on a diagonal axis of (1, 1, 0). Without the rotation, we'll just see the square of the front face. Add the following code to initializeScene:

        // Rotate and position the cube
        Matrix.setIdentityM(cubeTransform, 0);
        Matrix.translateM(cubeTransform, 0, 0, 0, -cubeDistance);
        Matrix.rotateM(cubeTransform, 0, 30, 1, 1, 0);

Add the following code to onDrawEye to calculate the MVP matrix, including the cubeTransform matrix, and then draw the cube:

        Matrix.multiplyMM(cubeView, 0, view, 0, cubeTransform, 0);
        Matrix.multiplyMM(modelViewProjection, 0, perspective, 0, cubeView, 0);
        drawCube();

Write the drawCube method, which is very similar to the drawTri method, as follows:

    private void drawCube() {
        GLES20.glUseProgram(cubeProgram);
        GLES20.glUniformMatrix4fv(cubeMVPMatrixParam, 1, false, modelViewProjection, 0);
        GLES20.glVertexAttribPointer(cubePositionParam, COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false, 0, cubeVerticesBuffer);
        GLES20.glUniform4fv(cubeColorParam, 1, cubeColor, 0);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, cubeVertexCount);
    }

Build and run it. You will now see a 3D view of the cube, as shown in the following screenshot. It needs shading.

Cube code
主站蜘蛛池模板: 威信县| 米林县| 乡宁县| 吴忠市| 延津县| 贡觉县| 富阳市| 彭州市| 永宁县| 内黄县| 伽师县| 贵溪市| 株洲市| 深圳市| 安乡县| 泸水县| 金阳县| 兴安县| 安乡县| 茌平县| 滁州市| 磴口县| 台中市| 革吉县| 成都市| 盖州市| 大化| 昌江| 北辰区| 罗定市| 邯郸市| 荃湾区| 平和县| 略阳县| 宜良县| 张家港市| 新巴尔虎右旗| 静海县| 石门县| 伊通| 十堰市|