纹理化多维数据集的问题

时间:2011-10-19 08:40:16

标签: android opengl-es textures

我试图在每张脸上制作一个不同纹理的立方体。

我的前脸和后脸现在都在工作。现在我正试图制作立方体的正确面孔。但是有些事情出错了,因为我做了正确的面孔,但纹理显示有错误(就像拉伸和切碎一样),我的代码中有一些不好的东西,我不知道是什么。

这是我的代码

public class Cube {

private FloatBuffer vertexBuffer;//Vertices
private FloatBuffer textureBuffer;//Texture coordinates
private ByteBuffer indexBuffer;//Indices
private int[] textures = new int[6];//Texture pointer

private float vertices[] = { //8 vertices of the cube
        -1.0f, -1.0f, 1.0f, // 0
        1.0f, -1.0f, 1.0f,  // 1
        -1.0f, 1.0f, 1.0f,  // 2
        1.0f, 1.0f, 1.0f,   // 3

        -1.0f, -1.0f, -1.0f,// 4
        1.0f, -1.0f, -1.0f, // 5
        -1.0f, 1.0f, -1.0f, // 6
        1.0f, 1.0f, -1.0f,  // 7
};

private byte indices[] = { //Faces definition
        0,1,2, 1,3,2, //front face (*)
        6,7,5, 6,5,4, //rear face (**)
        1,5,3, 5,7,3, //right face (***) //problems here
};

private float texture[] = {//Mapping coordinates for the vertices
        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,

        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,

        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,
};

public Cube() 
{
    ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    vertexBuffer = byteBuf.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

    byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    textureBuffer = byteBuf.asFloatBuffer();
    textureBuffer.put(texture);
    textureBuffer.position(0);

    indexBuffer = ByteBuffer.allocateDirect(indices.length);
    indexBuffer.put(indices);
    indexBuffer.position(0);
}

public void draw(GL10 gl) {
    //Point to our buffers
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    //Set the face rotation
    gl.glFrontFace(GL10.GL_CCW);
    //Enable the vertex and texture state
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
    //para que no pinte los poligonos que no se ven
    //gl.glEnable(GL10.GL_CULL_FACE);
    for(int i=0; i<3; i++) //<6 por que tenemos 6 texturas que queremos poner en las 6 caras de un cubo.
    {
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[i]);
        indexBuffer.position(6*i); //como cada dos triangulos (cuadrado) forman una cara, estos dos triangulos son 6 indices del array de indices, por lo tanto avanzamos 6 posiciones en el indexBuffer para pintar el siguiente cuadrado.
        gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_BYTE, indexBuffer); //el segundo parametro es 6 por que solo queremos pintar una cara (cuadrado) por textura.
    }
    //gl.glDisable(GL10.GL_CULL_FACE); //para que no pinte los poligonos que no se ven
    //Disable the client state before leaving
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}

public void loadGLTexture(GL10 gl, Context context) {
    loadTexture(gl,context,R.drawable.s1,0);
    loadTexture(gl,context,R.drawable.s2,1);
    loadTexture(gl,context,R.drawable.s3,2);
    loadTexture(gl,context,R.drawable.s4,3);
    loadTexture(gl,context,R.drawable.s5,4);
    loadTexture(gl,context,R.drawable.s6,5);
}

public void loadTexture(GL10 gl, Context context, int drawable, int textureNumber)
{
    //Get the texture from the Android resource directory
    InputStream is = context.getResources().openRawResource(drawable);
    Bitmap bitmap = null;
    try {
        //BitmapFactory is an Android graphics utility for images
        bitmap = BitmapFactory.decodeStream(is);
    } finally {
        //Always clear and close
        try {
            is.close();
            is = null;
        } catch (IOException e) {
        }
    }
    //Generate one texture pointer...
    gl.glGenTextures(1, textures, textureNumber);
    //...and bind it to our array
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[textureNumber]);
    //Create Nearest Filtered Texture
    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);
    //Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
    //Use the Android GLUtils to specify a two-dimensional texture image from our bitmap
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
    //Clean up
    bitmap.recycle();
}
}

1 个答案:

答案 0 :(得分:2)

在OpenGL中,顶点是位置和/或纹理坐标和/或颜色和/或任意更多属性的组合。因此,尽管列出了12个纹理坐标,但是从数据中获取的所有OpenGL都是8个不同的顶点,每个顶点都有一个位置和一个纹理坐标。

你的右脸由两个三角形组成,一个有顶点1,5和3,另一个有顶点5,7和3.因此,它在概念上与顶点1,5,7和3的四边形相同。

根据您自己的数据,该四边形具有顶点:

location: 1.0f, -1.0f,  1.0f; coordinate: 1.0f, 1.0f
location: 1.0f, -1.0f, -1.0f; coordinate: 1.0f, 1.0f
location: 1.0f,  1.0f, -1.0f; coordinate: 1.0f, 0.0f
location: 1.0f,  1.0f,  1.0f; coordinate: 1.0f, 0.0f

因此,您希望它能够显示沿着纹理右侧延伸的一维直线,并在整个面上展开。这就是你所看到的吗?

如果要为侧面的角提供唯一的纹理坐标,则需要为它们提供唯一的顶点(尽管它们位于其他顶点的顶部)。