有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java正在尝试跨立方体面渲染纹理

我有以下纹理:

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) 个答案

  1. # 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)

    这意味着您可以计算这样一张脸的纹理坐标:

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