Search code examples
objective-cgraphicsopengl-estexture-mapping

Mapping a square texture to a triangle


I started to play with a OpenGL ES 1.0 and I run into some (beginners) problem: I tried to map a square texture to the cube described by triangles.

    // Turn necessary features on
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_SRC_COLOR);
    glEnable(GL_CULL_FACE);
    //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  

    // Bind the number of textures we need, in this case one.
    glGenTextures(1, &texture[0]);
    glBindTexture(GL_TEXTURE_2D, texture[0]);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

//Drawing code
static GLfloat rot = 0.0;

static const Vertex3D vertices[] = {
    -1.0f,-1.0f,-1.0f, //0  00  
     1.0f,-1.0f,-1.0f, //1  10
     1.0f, 1.0f,-1.0f, //2  11
    -1.0f, 1.0f,-1.0f, //3  01      
};


static const int vertexCnt = 3 * 2;

static const GLubyte cube[] = {
    3,0,2,
    1,2,0,
};

static const GLfloat texCoords[] = {
    0,1,
    0,0,
    1,1,
    1,0,
    1,1,
    0,0,
};


glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

glTranslatef(0.0f, 0.0f, -3.0f);

glBindTexture(GL_TEXTURE_2D, texture[0]);

glEnableClientState(GL_VERTEX_ARRAY);
//glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_COLOR_MATERIAL);


glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glVertexPointer(3, GL_FLOAT, 0, vertices);

//glColorPointer(4, GL_FLOAT, 0, colors);
glNormalPointer(GL_FLOAT, 0, normals);



glDrawElements(GL_TRIANGLES, vertexCnt, GL_UNSIGNED_BYTE, cube);


glDisableClientState(GL_VERTEX_ARRAY);
//glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

Now, after a zillion attempts, I just can't get it work for other sides... Is there some rule of thumb for case when mapping square texture to triangles?

EDIT: I think I figure out how the mapping should be done. But it doesn't work for this example (one face). Can someone just please verify if I done mapping correctly (assuming that the rest of code is working)?

Many thanks


Solution

  • Just like others, I don't think there is a trick to map your quad textures onto triangles.

    The main problem you're experiencing is because of discontinuities in texture coords for each corner. If one corner as some UV coords {u,v} for one face, it doesn't mean it will have the same value for the other two faces that share the vertex. It is possible to find a mapping so that UV is unique at each corner of the cube (shared by 3 faces) and so that all 4 UV values ({0,0}, {1,0}, {1,1} and {0,1}) are present on each face but then some textures would be completely distorted. Try to verify this on a piece of paper: {1,1} is not always at the opposite of {0,0}.

    The easiest way to start with, would be to declare explicitly 6 quads, each one of them composed of 2 triangles. That gives you a total of 24 vertices (24 positions and 24 tex coords, interleaved or not) and 36 indices (6 quads composed of two triangles, 6 * 2 * 3 = 36 ).

    Here is your code updated to display a cube (there might be some winding problem so I disabled face culling to be sure):

    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glEnable(GL_DEPTH_TEST);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    glDisable(GL_CULL_FACE);
    
    static const float vertices[] = {
            0.0f, 1.0f, 0.0f,
            1.0f, 1.0f, 0.0f,
            0.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 0.0f,
    
            0.0f, 1.0f, 1.0f,
            0.0f, 0.0f, 1.0f,
            1.0f, 1.0f, 1.0f,
            1.0f, 0.0f, 1.0f,
    
            0.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f,
            0.0f, 1.0f, 0.0f,
            1.0f, 1.0f, 0.0f,
    
            0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 1.0f,
            1.0f, 0.0f, 0.0f,
    
            1.0f, 1.0f, 0.0f,
            1.0f, 1.0f, 1.0f,
            1.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 1.0f,
    
            0.0f, 1.0f, 0.0f,
            0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 1.0f,
            0.0f, 0.0f, 1.0f
            };
    
    
    static const int vertexCnt = 6 * 4;
    
    static const GLubyte cube[] = {
         0,  1,  2,  1,  2,  3,
         4,  5,  6,  5,  6,  7,
         8,  9, 10,  9, 10, 11,
        12, 13, 14, 13, 14, 15,
        16, 17, 18, 17, 18, 19,
        20, 21, 22, 21, 22, 23 
    };
    
    static const GLfloat texCoords[] = {
        0.0f, 0.0f,
        1.0f, 0.0f,
        0.0f, 1.0f,
        1.0f, 1.0f,
    
        1.0f, 0.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        0.0f, 1.0f,
    
        0.0f, 0.0f,
        1.0f, 0.0f,
        0.0f, 1.0f,
        1.0f, 1.0f,
    
        0.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 1.0f,
        1.0f, 0.0f,
    
        0.0f, 0.0f,
        1.0f, 0.0f,
        0.0f, 1.0f,
        1.0f, 1.0f,
    
        1.0f, 0.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        0.0f, 1.0f
        };
    
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    //glLoadIdentity();
    
    //glTranslatef(0.0f, 0.0f, -3.0f);
    glRotatef(3.1415927f, 1.0f, 1.0f, 0.0f);
    
    glBindTexture(GL_TEXTURE_2D, spriteTexture);
    
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, cube);