Question

I'm trying to take a concave polygon and apply an image to it as a texture. The polygon can have multiple contours, both internal holes and external "islands". It can be any shape, but will be smaller than the image and will fit inside it. It does not necessarily touch the edges of the image.

I've successfully displayed the tessellated polygon, and textured a simple square, but can't get the two to work together.

Here's how I'm loading the texture:

    GLuint texture;
    int width, height;
    BYTE * data;
    FILE * file;

    // open texture data
    file = fopen( filename, "rb" );
    if ( file == NULL ) return 0;

    // allocate buffer
    width = 256;
    height = 256;
    data = (BYTE *)malloc( width * height * 3 );

    // read texture data
    fread( data, width * height * 3, 1, file );
    fclose( file );

    glGenTextures( 1, &texture );
    glBindTexture( GL_TEXTURE_2D, texture );
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap ? GL_REPEAT : GL_CLAMP );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap ? GL_REPEAT : GL_CLAMP );

    gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width,height, GL_RGB, GL_UNSIGNED_BYTE, data );

    free( data );

    return texture;

Here's the tessellation function:

GLuint tessellate1()
{
GLuint id = glGenLists(1);  // create a display list
if(!id) return id;          // failed to create a list, return 0

GLUtesselator *tess = gluNewTess(); // create a tessellator
if(!tess) return 0;  // failed to create tessellation object, return 0

GLdouble quad1[4][3] = { {-1,3,0}, {0,0,0}, {1,3,0}, {0,2,0} };

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, GLTexture::LoadTextureRAW("texture.raw", true));

// register callback functions
gluTessCallback(tess, GLU_TESS_BEGIN, (void (CALLBACK *)())tessBeginCB);
gluTessCallback(tess, GLU_TESS_END, (void (CALLBACK *)())tessEndCB);
gluTessCallback(tess, GLU_TESS_ERROR, (void (CALLBACK *)())tessErrorCB);
gluTessCallback(tess, GLU_TESS_VERTEX, (void (CALLBACK *)())tessVertexCB);

glNewList(id, GL_COMPILE);
glColor3f(1,1,1);
gluTessBeginPolygon(tess, 0);                   // with NULL data
    gluTessBeginContour(tess);
        gluTessVertex(tess, quad1[0], quad1[0]);
        gluTessVertex(tess, quad1[1], quad1[1]);
        gluTessVertex(tess, quad1[2], quad1[2]);
        gluTessVertex(tess, quad1[3], quad1[3]);
    gluTessEndContour(tess);
gluTessEndPolygon(tess);
glEndList();

gluDeleteTess(tess);        // delete after tessellation

glDisable(GL_TEXTURE_2D);

setCamera(0, 0, 5, 0, 0, 0);

return id;      // return handle ID of a display list
}

Here's the tessellation vertex callback function:

// cast back to double type
const GLdouble *ptr = (const GLdouble*)data;

double dImageX = -1, dImageY = -1;

//hardcoded extents of the polygon for the purposes of testing
int minX = 607011, maxX = 616590;
int minY = 4918219, maxY = 4923933;

//get the % coord of the texture for a poly vertex.  Assumes image and poly bounds are the same for the purposes of testing
dImageX = (ptr[0] - minX) / (maxX - minX);
dImageY = (ptr[1] - minY) / (maxY - minY);

glTexCoord2d(dImageX, dImageY);
glVertex2d(ptr[0], ptr[1]);

And here's the display callback:

void displayCB()
{
// clear buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

// save the initial ModelView matrix before modifying ModelView matrix
glPushMatrix();

// tramsform camera
glTranslatef(0, 0, cameraDistance);
glRotatef(cameraAngleX, 1, 0, 0);   // pitch
glRotatef(cameraAngleY, 0, 1, 0);   // heading

// draw meshes
glCallList(listId1);  //id of the tessellated poly

// draw info messages
showInfo();

glPopMatrix();

glutSwapBuffers();
}

The results of this are a correctly drawn polygon with no texture applied.

Was it helpful?

Solution 3

The problem was the glDisable(GL_TEXTURE_2D) call in the tessellation function. After removing it, the texture was applied correctly.

OTHER TIPS

// init
glGenTextures( 1, &texture );

// vertex callback
glBindTexture(GL_TEXTURE_2D, 1);

I don't think the first ID returned by glGenTextures() is required to be 1.

Try using texture instead of 1 in your glBindTexture() call.

Also, there's really no reason to enable texturing and re-bind the texture for every vertex. Just do it once before you call into the tesselator.

You're not capturing the texture binding and Enable inside the display list, so it's not going to be taken into account when you replay it. So, either:

  • Capture the BindTexture and Enable inside the display list, or
  • BindTexture and Enable(TEXTURE_2D) before calling CallList
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top