2015-05-12 65 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 
};