2015-05-12 64 views
1

我想在自己的場景上製作3D立方體。不幸的是,在合併來自各個網站的代碼後,我仍然無法制作多維數據集。使用Android OpenGL ES 2.0創建3D立方體

有人可以看看我的代碼和建議我做錯了什麼?我的想法是讓立方體的每個面都以不同的顏色顯示,並且所有東西都以屏幕爲中心。

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); 
    } 
} 

目前,我接受這樣的結局:

enter image description here

回答

8

你的指數根本不符合您的頂點。我們只看第一張臉。第一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, 

繪製的這在x/y平面草圖,用指數來表示:

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

索引陣列,用於第一面中的條目有:

​​

映射到這一點前面的圖,這些指數定義以下兩個三角形:

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

正如您所看到的,兩個三角形重疊,並且不覆蓋整個四邊形。你需要的是以下情況:

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

因此,對於這個面對一個正確的索引順序是:

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

第3個第2 3個指標現在匹配兩個三角形。另外請注意,它們都是逆時針方向枚舉的,如果您啓用了背面剔除,這將變得非常重要。您將需要以相同的方式修復所有其他面部的索引序列。

有一個在你的代碼中的第二個問題,這將防止顏色的工作,一旦你有索引整理出來:

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); 
} 

既然你不設置每個均勻值後繪製什麼,這裏有一個循環沒用。最後,將爲該顏色設置最後一個值,其他顏色不用於任何其他顏色。

爲了得到這個工作,你必須在這個循環內一次只繪製一個面(6個索引)。或者你必須爲顏色引入一個頂點屬性,就像你用於位置的顏色一樣。

+0

謝謝。現在正在工作。 – sebap123

0

正確的是:

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 
};