使用Android OpenGL ES 2.0创建3D立方体

时间:2022-09-10 22:02:53

I wanted to make 3D cube on my sceen. Unfortunately after combining some code from various sites I am still unable to make cube.

我想在我的场景上制作3D立方体。不幸的是,在结合来自不同网站的一些代码之后,我仍然无法制作多维数

Can someone take a look at my code and advice what am I doing wrong? My idea is to make each face of a cube in different color and everything centered on the screen.

有人可以看看我的代码,并建议我做错了什么?我的想法是让立方体的每个面都有不同的颜色,一切都以屏幕为中心。

import android.opengl.GLES20;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.opengles.GL10;

public class Cube {
    private FloatBuffer vertexBuffer;  // Buffer for vertex-array
    private ShortBuffer indexBuffer;
    private int numFaces = 6;
    private int colorHandle;
    private final String vertexShaderCode =
            "uniform mat4 uMVPMatrix;" +
                    "attribute vec4 vPosition;" +
                    "void main() {" +
                    "  gl_Position = uMVPMatrix * vPosition;" +
                    "}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";
    private int MVPMatrixHandle;
    private int positionHandle;
    private final int program;

    static final int COORDS_PER_VERTEX = 3;
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

    private float[][] colors = {  // Colors of the 6 faces
            {1.0f, 0.5f, 0.0f, 1.0f},  // 0. orange
            {1.0f, 0.0f, 1.0f, 1.0f},  // 1. violet
            {0.0f, 1.0f, 0.0f, 1.0f},  // 2. green
            {0.0f, 0.0f, 1.0f, 1.0f},  // 3. blue
            {1.0f, 0.0f, 0.0f, 1.0f},  // 4. red
            {1.0f, 1.0f, 0.0f, 1.0f}   // 5. yellow
    };

    private float[] vertices = {  // Vertices of the 6 faces
            // FRONT
            -1.0f, -1.0f,  1.0f,  // 0. left-bottom-front
            1.0f, -1.0f,  1.0f,  // 1. right-bottom-front
            -1.0f,  1.0f,  1.0f,  // 2. left-top-front
            1.0f,  1.0f,  1.0f,  // 3. right-top-front
            // BACK
            1.0f, -1.0f, -1.0f,  // 6. right-bottom-back
            -1.0f, -1.0f, -1.0f,  // 4. left-bottom-back
            1.0f,  1.0f, -1.0f,  // 7. right-top-back
            -1.0f,  1.0f, -1.0f,  // 5. left-top-back
            // LEFT
            -1.0f, -1.0f, -1.0f,  // 4. left-bottom-back
            -1.0f, -1.0f,  1.0f,  // 0. left-bottom-front 
            -1.0f,  1.0f, -1.0f,  // 5. left-top-back
            -1.0f,  1.0f,  1.0f,  // 2. left-top-front
            // RIGHT
            1.0f, -1.0f,  1.0f,  // 1. right-bottom-front
            1.0f, -1.0f, -1.0f,  // 6. right-bottom-back
            1.0f,  1.0f,  1.0f,  // 3. right-top-front
            1.0f,  1.0f, -1.0f,  // 7. right-top-back
            // TOP
            -1.0f,  1.0f,  1.0f,  // 2. left-top-front
            1.0f,  1.0f,  1.0f,  // 3. right-top-front
            -1.0f,  1.0f, -1.0f,  // 5. left-top-back
            1.0f,  1.0f, -1.0f,  // 7. right-top-back
            // BOTTOM
            -1.0f, -1.0f, -1.0f,  // 4. left-bottom-back
            1.0f, -1.0f, -1.0f,  // 6. right-bottom-back
            -1.0f, -1.0f,  1.0f,  // 0. left-bottom-front
            1.0f, -1.0f,  1.0f   // 1. right-bottom-front
    };

    short[] indeces = {
            0, 1, 3, 1, 2, 3,
            4, 5, 7, 5, 6, 7,
            8, 9, 11, 9, 10, 11,
            12, 13, 15, 13, 14, 15,
            16, 17, 19, 17, 18, 19,
            20, 21, 23, 21, 22, 23,

    };

    // Constructor - Set up the buffers
    public Cube() {
        // Setup vertex-array buffer. Vertices in float. An float has 4 bytes
        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
        vbb.order(ByteOrder.nativeOrder()); // Use native byte order
        vertexBuffer = vbb.asFloatBuffer(); // Convert from byte to float
        vertexBuffer.put(vertices);         // Copy data into buffer
        vertexBuffer.position(0);           // Rewind

        indexBuffer = ByteBuffer.allocateDirect(indeces.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
        indexBuffer.put(indeces).position(0);

        int vertexShader = StageRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = StageRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

        program = GLES20.glCreateProgram();
        GLES20.glAttachShader(program, vertexShader);
        GLES20.glAttachShader(program, fragmentShader);
        GLES20.glLinkProgram(program);
    }

    // Draw the shape
    public void draw(float[] mvpMatrix) {
        GLES20.glUseProgram(program);

        positionHandle = GLES20.glGetAttribLocation(program, "vPosition");
        GLES20.glEnableVertexAttribArray(positionHandle);
        GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);

        MVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix");
        GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, mvpMatrix, 0);
        // Render all the faces
        for (int face = 0; face < numFaces; face++) {
            // Set the color for each of the faces
            colorHandle = GLES20.glGetUniformLocation(program, "vColor");
            GLES20.glUniform4fv(colorHandle, 1, colors[face], 0);
        }

        GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT, indexBuffer);

        GLES20.glDisableVertexAttribArray(positionHandle);
    }
}

Currently I am receiving such outcome:

目前我收到了这样的结果:

使用Android OpenGL ES 2.0创建3D立方体

2 个解决方案

#1


8  

Your indices simply do not match your vertices. Let's just look at the first face. The coordinates of the first 4 vertices are:

您的索引与您的顶点不匹配。让我们看看第一张脸。前4个顶点的坐标是:

-1.0f, -1.0f,  1.0f,
 1.0f, -1.0f,  1.0f,
-1.0f,  1.0f,  1.0f,
 1.0f,  1.0f,  1.0f,

Drawing a sketch of this in the x/y plane, with the indices indicated:

在x / y平面上绘制一个草图,指示指示:

2---3
|   |
|   |
|   |
0---1

The entries in the index array for the first face are:

第一个面的索引数组中的条目是:

0, 1, 3, 1, 2, 3,

Mapping that into the previous figure, these indices define the following two triangles:

将其映射到上图中,这些索引定义了以下两个三角形:

    3    2---3
   /|     \  |
  / |      \ |
 /  |       \|
0---1        1

As you can tell, the two triangles overlap, and do not cover the entire quad. What you need is the following:

如您所知,两个三角形重叠,并不覆盖整个四边形。您需要的是以下内容:

2---3
|\  |
| \ |
|  \|
0---1

So one correct index sequence for this face is:

因此,这个面的一个正确的索引序列是:

0, 1, 2, 2, 1, 3,

The first 3 and second 3 indices now match the two triangles. Also note that both of them are enumerated in counter-clockwise direction, which becomes important if you ever enable backface culling. You will need to fix the index sequence in the same way for all other faces.

现在,前3个和后3个索引与两个三角形匹配。另请注意,它们都是逆时针方向枚举的,如果您启用背面剔除,这一点很重要。您需要以相同的方式为所有其他面修复索引序列。

There's a secondary problem in your code that will prevent the colors from working once you have the indices sorted out:

您的代码中存在一个次要问题,一旦您将索引排序后,这些问题将阻止颜色工作:

for (int face = 0; face < numFaces; face++) {
    // Set the color for each of the faces
    colorHandle = GLES20.glGetUniformLocation(program, "vColor");
    GLES20.glUniform4fv(colorHandle, 1, colors[face], 0);
}

Since you're not drawing anything after setting each uniform value, having a loop here is not useful. At the end, the last value will be set for the color, and the other colors are not used for anything.

由于在设置每个统一值后没有绘制任何内容,因此在此处使用循环无用。最后,将为颜色设置最后一个值,其他颜色不用于任何颜色。

To get this working, you will either have to draw only one face (6 indices) at a time, inside this loop. Or you have to introduce a vertex attribute for the colors just like the one you use for the positions.

为了实现这一点,你必须在这个循环中一次只绘制一个面(6个索引)。或者您必须为颜色引入顶点属性,就像您用于位置的属性一样。

#2


0  

Correct would be:

正确的是:

private float[] vertices = {  // Vertices of the 6 faces
        // FRONT
        -1.0f, -1.0f,  1.0f,  // 0. left-bottom-front
        1.0f, -1.0f,  1.0f,  // 1. right-bottom-front
        -1.0f,  1.0f,  1.0f,  // 2. left-top-front
        -1.0f,  1.0f,  1.0f,  // 2. left-top-front
        1.0f, -1.0f,  1.0f,  // 1. right-bottom-front
        1.0f,  1.0f,  1.0f,  // 3. right-top-front
        // BACK
        1.0f, -1.0f, -1.0f,  // 6. right-bottom-back
        1.0f,  1.0f, -1.0f,  // 7. right-top-back
        -1.0f, -1.0f, -1.0f,  // 4. left-bottom-back
        -1.0f, -1.0f, -1.0f,  // 4. left-bottom-back
        -1.0f,  1.0f, -1.0f,  // 5. left-top-back
        1.0f,  1.0f, -1.0f,  // 7. right-top-back
        // LEFT
        -1.0f, -1.0f, -1.0f,  // 4. left-bottom-back
        -1.0f, -1.0f,  1.0f,  // 0. left-bottom-front
        -1.0f,  1.0f,  1.0f,  // 2. left-top-front
        -1.0f,  1.0f,  1.0f,  // 2. left-top-front
        -1.0f,  1.0f, -1.0f,  // 5. left-top-back
        -1.0f, -1.0f, -1.0f,  // 4. left-bottom-back
        // RIGHT
        1.0f, -1.0f,  1.0f,  // 1. right-bottom-front
        1.0f, -1.0f, -1.0f,  // 6. right-bottom-back
        1.0f,  1.0f, -1.0f,  // 7. right-top-back
        1.0f,  1.0f, -1.0f,  // 7. right-top-back
        1.0f,  1.0f,  1.0f,  // 3. right-top-front
        1.0f, -1.0f,  1.0f,  // 1. right-bottom-front
        // TOP
        -1.0f,  1.0f,  1.0f,  // 2. left-top-front
        1.0f,  1.0f,  1.0f,  // 3. right-top-front
        1.0f,  1.0f, -1.0f,  // 7. right-top-back
        1.0f,  1.0f, -1.0f,  // 7. right-top-back
        -1.0f,  1.0f, -1.0f,  // 5. left-top-back
        -1.0f,  1.0f,  1.0f,  // 2. left-top-front
        // BOTTOM
        -1.0f, -1.0f, -1.0f,  // 4. left-bottom-back
        1.0f, -1.0f, -1.0f,  // 6. right-bottom-back
        1.0f, -1.0f,  1.0f,   // 1. right-bottom-front
        1.0f, -1.0f,  1.0f,   // 1. right-bottom-front
        -1.0f, -1.0f,  1.0f,  // 0. left-bottom-front
        -1.0f, -1.0f, -1.0f  // 4. left-bottom-back
};

#1


8  

Your indices simply do not match your vertices. Let's just look at the first face. The coordinates of the first 4 vertices are:

您的索引与您的顶点不匹配。让我们看看第一张脸。前4个顶点的坐标是:

-1.0f, -1.0f,  1.0f,
 1.0f, -1.0f,  1.0f,
-1.0f,  1.0f,  1.0f,
 1.0f,  1.0f,  1.0f,

Drawing a sketch of this in the x/y plane, with the indices indicated:

在x / y平面上绘制一个草图,指示指示:

2---3
|   |
|   |
|   |
0---1

The entries in the index array for the first face are:

第一个面的索引数组中的条目是:

0, 1, 3, 1, 2, 3,

Mapping that into the previous figure, these indices define the following two triangles:

将其映射到上图中,这些索引定义了以下两个三角形:

    3    2---3
   /|     \  |
  / |      \ |
 /  |       \|
0---1        1

As you can tell, the two triangles overlap, and do not cover the entire quad. What you need is the following:

如您所知,两个三角形重叠,并不覆盖整个四边形。您需要的是以下内容:

2---3
|\  |
| \ |
|  \|
0---1

So one correct index sequence for this face is:

因此,这个面的一个正确的索引序列是:

0, 1, 2, 2, 1, 3,

The first 3 and second 3 indices now match the two triangles. Also note that both of them are enumerated in counter-clockwise direction, which becomes important if you ever enable backface culling. You will need to fix the index sequence in the same way for all other faces.

现在,前3个和后3个索引与两个三角形匹配。另请注意,它们都是逆时针方向枚举的,如果您启用背面剔除,这一点很重要。您需要以相同的方式为所有其他面修复索引序列。

There's a secondary problem in your code that will prevent the colors from working once you have the indices sorted out:

您的代码中存在一个次要问题,一旦您将索引排序后,这些问题将阻止颜色工作:

for (int face = 0; face < numFaces; face++) {
    // Set the color for each of the faces
    colorHandle = GLES20.glGetUniformLocation(program, "vColor");
    GLES20.glUniform4fv(colorHandle, 1, colors[face], 0);
}

Since you're not drawing anything after setting each uniform value, having a loop here is not useful. At the end, the last value will be set for the color, and the other colors are not used for anything.

由于在设置每个统一值后没有绘制任何内容,因此在此处使用循环无用。最后,将为颜色设置最后一个值,其他颜色不用于任何颜色。

To get this working, you will either have to draw only one face (6 indices) at a time, inside this loop. Or you have to introduce a vertex attribute for the colors just like the one you use for the positions.

为了实现这一点,你必须在这个循环中一次只绘制一个面(6个索引)。或者您必须为颜色引入顶点属性,就像您用于位置的属性一样。

#2


0  

Correct would be:

正确的是:

private float[] vertices = {  // Vertices of the 6 faces
        // FRONT
        -1.0f, -1.0f,  1.0f,  // 0. left-bottom-front
        1.0f, -1.0f,  1.0f,  // 1. right-bottom-front
        -1.0f,  1.0f,  1.0f,  // 2. left-top-front
        -1.0f,  1.0f,  1.0f,  // 2. left-top-front
        1.0f, -1.0f,  1.0f,  // 1. right-bottom-front
        1.0f,  1.0f,  1.0f,  // 3. right-top-front
        // BACK
        1.0f, -1.0f, -1.0f,  // 6. right-bottom-back
        1.0f,  1.0f, -1.0f,  // 7. right-top-back
        -1.0f, -1.0f, -1.0f,  // 4. left-bottom-back
        -1.0f, -1.0f, -1.0f,  // 4. left-bottom-back
        -1.0f,  1.0f, -1.0f,  // 5. left-top-back
        1.0f,  1.0f, -1.0f,  // 7. right-top-back
        // LEFT
        -1.0f, -1.0f, -1.0f,  // 4. left-bottom-back
        -1.0f, -1.0f,  1.0f,  // 0. left-bottom-front
        -1.0f,  1.0f,  1.0f,  // 2. left-top-front
        -1.0f,  1.0f,  1.0f,  // 2. left-top-front
        -1.0f,  1.0f, -1.0f,  // 5. left-top-back
        -1.0f, -1.0f, -1.0f,  // 4. left-bottom-back
        // RIGHT
        1.0f, -1.0f,  1.0f,  // 1. right-bottom-front
        1.0f, -1.0f, -1.0f,  // 6. right-bottom-back
        1.0f,  1.0f, -1.0f,  // 7. right-top-back
        1.0f,  1.0f, -1.0f,  // 7. right-top-back
        1.0f,  1.0f,  1.0f,  // 3. right-top-front
        1.0f, -1.0f,  1.0f,  // 1. right-bottom-front
        // TOP
        -1.0f,  1.0f,  1.0f,  // 2. left-top-front
        1.0f,  1.0f,  1.0f,  // 3. right-top-front
        1.0f,  1.0f, -1.0f,  // 7. right-top-back
        1.0f,  1.0f, -1.0f,  // 7. right-top-back
        -1.0f,  1.0f, -1.0f,  // 5. left-top-back
        -1.0f,  1.0f,  1.0f,  // 2. left-top-front
        // BOTTOM
        -1.0f, -1.0f, -1.0f,  // 4. left-bottom-back
        1.0f, -1.0f, -1.0f,  // 6. right-bottom-back
        1.0f, -1.0f,  1.0f,   // 1. right-bottom-front
        1.0f, -1.0f,  1.0f,   // 1. right-bottom-front
        -1.0f, -1.0f,  1.0f,  // 0. left-bottom-front
        -1.0f, -1.0f, -1.0f  // 4. left-bottom-back
};