尝试在立方体面上渲染纹理

时间:2017-11-30 17:43:06

标签: java android opengl-es 3d

我有以下纹理:

enter image description here

我正在尝试让纹理中的每个骰子面在OpenGL ES中呈现在立方体的每个面上。但是,使用我当前的代码,它呈现如下:

enter image description here

我知道我需要为每个面部获得纹理坐标,但每次我尝试扩展纹理坐标数组时,它都会破坏我的代码。

最终,如何在纹理文件中获取骰子的每个面部,在3D立方体的面上绘制?

这是3D立方体对象类:

public class Dice3D {
private FloatBuffer vertexBuffer; // Buffer for vertex-array
private FloatBuffer texBuffer;    // Buffer for texture-coords-array (NEW)

private float[] vertices = { // Vertices for a face
        -1.0f, -1.0f, 0.0f,  // 0. left-bottom-front
        1.0f, -1.0f, 0.0f,  // 1. right-bottom-front
        -1.0f,  1.0f, 0.0f,  // 2. left-top-front
        1.0f,  1.0f, 0.0f   // 3. right-top-front
};

float[] texCoords = { // Texture coords for the above face (NEW)
        0.0f, 1.0f,  // A. left-bottom (NEW)
        1.0f, 1.0f,  // B. right-bottom (NEW)
        0.0f, 0.0f,  // C. left-top (NEW)
        1.0f, 0.0f // D. right-top (NEW)
};

int[] textureIDs = new int[1];   // Array for 1 texture-ID (NEW)

// Constructor - Set up the buffers
public Dice3D(Context context) {
    // Setup vertex-array buffer. Vertices in float. An float has 4 bytes
    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4 * 6);
    vbb.order(ByteOrder.nativeOrder()); // Use native byte order
    vertexBuffer = vbb.asFloatBuffer(); // Convert from byte to float

    for (int face = 0; face < 6; face++) {
        vertexBuffer.put(vertices);
    }

    vertexBuffer.position(0);

    /*vertexBuffer.put(vertices);         // Copy data into buffer
    vertexBuffer.position(0);           // Rewind*/

    // Setup texture-coords-array buffer, in float. An float has 4 bytes (NEW)
    ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4);
    tbb.order(ByteOrder.nativeOrder());
    texBuffer = tbb.asFloatBuffer();
    texBuffer.put(texCoords);
    texBuffer.position(0);
}

// Draw the shape
public void draw(GL10 gl) {
    gl.glFrontFace(GL10.GL_CCW);    // Front face in counter-clockwise orientation
    gl.glEnable(GL10.GL_CULL_FACE); // Enable cull face
    gl.glCullFace(GL10.GL_BACK);    // Cull the back face (don't display)

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  // Enable texture-coords-array (NEW)
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // Define texture-coords buffer (NEW)

    // front
    gl.glPushMatrix();
    gl.glTranslatef(0.0f, 0.0f, 1.0f);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
    gl.glPopMatrix();

    // left
    gl.glPushMatrix();
    gl.glRotatef(270.0f, 0.0f, 1.0f, 0.0f);
    gl.glTranslatef(0.0f, 0.0f, 1.0f);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
    gl.glPopMatrix();

    // back
    gl.glPushMatrix();
    gl.glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
    gl.glTranslatef(0.0f, 0.0f, 1.0f);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
    gl.glPopMatrix();

    // right
    gl.glPushMatrix();
    gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
    gl.glTranslatef(0.0f, 0.0f, 1.0f);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
    gl.glPopMatrix();

    // top
    gl.glPushMatrix();
    gl.glRotatef(270.0f, 1.0f, 0.0f, 0.0f);
    gl.glTranslatef(0.0f, 0.0f, 1.0f);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
    gl.glPopMatrix();

    // bottom
    gl.glPushMatrix();
    gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
    gl.glTranslatef(0.0f, 0.0f, 1.0f);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
    gl.glPopMatrix();

    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  // Disable texture-coords-array (NEW)
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisable(GL10.GL_CULL_FACE);


}

// Load an image into GL texture
public void loadTexture(GL10 gl, Context context) {
    gl.glGenTextures(1, textureIDs, 0); // Generate texture-ID array

    gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]);   // Bind to texture ID
    // Set up texture filters
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    // Allocate texture buffer
    ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4 * 6);
    tbb.order(ByteOrder.nativeOrder());
    texBuffer = tbb.asFloatBuffer();
    // All the 6 faces have the same texture coords, repeat 6 times
    for (int face = 0; face < 6; face++) {

        Log.i("Face", String.valueOf(face));

        float[] texCoords = {        // Texture coords for the above face (NEW)
                0.0f, (5.0f-face)/6.0f,  // A. left-bottom (NEW)
                1.0f, (5.0f-face)/6.0f,  // B. right-bottom (NEW)
                0.0f, (6.0f-face)/6.0f,  // C. left-top (NEW)
                1.0f, (6.0f-face)/6.0f   // D. right-top (NEW)
        };
        texBuffer.put(texCoords);
    }
    texBuffer.position(0);     // Rewind


    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer);

    for (int face = 0; face < 6; face++) {
        // Render each face in TRIANGLE_STRIP using 4 vertices
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, face*4, 4);
    }

    // Construct an input stream to texture image "res\drawable\nehe.png"
    InputStream istream = context.getResources().openRawResource(R.drawable.completetexture);
    Bitmap bitmap;
    try {
        // Read and decode input as bitmap
        bitmap = BitmapFactory.decodeStream(istream);
    } finally {
        try {
            istream.close();
        } catch(IOException e) { }
    }

    // Build Texture from loaded bitmap for the currently-bind texture ID
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
    bitmap.recycle();
}

}

1 个答案:

答案 0 :(得分:1)

您必须分离多维数据集每个面的纹理坐标。立方体的每个部分沿垂直方向占据纹理的六分之一。

面部的纹理坐标为:

  • 1:(0,5 / 6) - (1,6 / 6)
  • 2:(0,4 / 6) - (1,5 / 6)
  • 3:(0,3 / 6) - (1,4 / 6)
  • 4:(0,2 / 6) - (1,3 / 6)
  • 5:(0,1 / 6) - (1,2 / 6)
  • 6:(0,0 / 6) - (1,1 / 6)

这意味着你可以为这样的面部调整纹理coordiantes:

for (int face = 0; face < 6; face++) {

    float[] texCoords = {        // Texture coords for the above face (NEW)
        0.0f, (5.0f-face)/6.0f,  // A. left-bottom (NEW)
        1.0f, (5.0f-face)/6.0f,  // B. right-bottom (NEW)
        0.0f, (6.0f-face)/6.0f,  // C. left-top (NEW)
        1.0f, (6.0f-face)/6.0f   // D. right-top (NEW)
    };

    texBuffer.put(texCoords);
}

当然,您还必须为每个面添加顶点坐标:

private float[] vertices = { // Vertices for a face
    -1.0f, -1.0f, 0.0f,  // 0. left-bottom-front
     1.0f, -1.0f, 0.0f,  // 1. right-bottom-front
    -1.0f,  1.0f, 0.0f,  // 2. left-top-front
     1.0f,  1.0f, 0.0f   // 3. right-top-front
};

for (int face = 0; face < 6; face++) {
    vertexBuffer.put(vertices);
} 

你必须为每个面绘制顶点数组的正确部分:

    // front
    gl.glPushMatrix();
    gl.glTranslatef(0.0f, 0.0f, 1.0f);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
    gl.glPopMatrix();

    // left
    gl.glPushMatrix();
    gl.glRotatef(270.0f, 0.0f, 1.0f, 0.0f);
    gl.glTranslatef(0.0f, 0.0f, 1.0f);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);
    gl.glPopMatrix();

    // back
    gl.glPushMatrix();
    gl.glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
    gl.glTranslatef(0.0f, 0.0f, 1.0f);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);
    gl.glPopMatrix();

    // right
    gl.glPushMatrix();
    gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
    gl.glTranslatef(0.0f, 0.0f, 1.0f);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);
    gl.glPopMatrix();

    // top
    gl.glPushMatrix();
    gl.glRotatef(270.0f, 1.0f, 0.0f, 0.0f);
    gl.glTranslatef(0.0f, 0.0f, 1.0f);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);
    gl.glPopMatrix();

    // bottom
    gl.glPushMatrix();
    gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
    gl.glTranslatef(0.0f, 0.0f, 1.0f);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);
    gl.glPopMatrix();


请注意,您可以放弃所有矩阵旋转和平移操作,如果为每个面生成单独的顶点坐标,则可以通过单次调用gl.glDrawArrays绘制整个多维数据集:

float[] vertices = { // Vertices for a 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, 
    -1.0f,  1.0f,  1.0f, 
     1.0f,  1.0f,  1.0f   
};

indices [] = {
    0, 1, 2, 3, // front
    4, 0, 6, 2, // left
    5, 4, 7, 6, // back
    1, 5, 3, 7, // right
    2, 3, 6, 7, // top   
    4, 5, 0, 1  // bottom
}

for (int i = 0; i < 24; i++) {
   int vi = indices[i]*3;
   vertexBuffer.put(vertices[vi + 0]);
   vertexBuffer.put(vertices[vi + 1]);
   vertexBuffer.put(vertices[vi + 2]);
}

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 24);