Yes.
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <vector>
#define array_len(a) ( sizeof ( a ) / sizeof ( *a ) )
//------------------------------------------------------------------------------
// heap memory management for GLUtesselator ...
//------------------------------------------------------------------------------
typedef std::vector< GLdouble* > Vectors;
Vectors vectors;
GLdouble* NewVector(GLdouble x, GLdouble y)
{
GLdouble *vert = new GLdouble[3];
vert[0] = x;
vert[1] = y;
vert[2] = 0;
vectors.push_back(vert);
return vert;
}
//------------------------------------------------------------------------------
void ClearVectors()
{
for (Vectors::size_type i = 0; i < vectors.size(); ++i)
delete[] vectors[i];
vectors.clear();
}
//------------------------------------------------------------------------------
// GLUtesselator callback functions ...
//------------------------------------------------------------------------------
void CALLBACK BeginCallback(GLenum type)
{
glBegin(type);
}
//------------------------------------------------------------------------------
void CALLBACK EndCallback()
{
glEnd();
}
//------------------------------------------------------------------------------
void CALLBACK VertexCallback(GLvoid *vertex)
{
glVertex3dv( (const double *)vertex );
}
//------------------------------------------------------------------------------
void CALLBACK CombineCallback(GLdouble coords[3],
GLdouble *data[4], GLfloat weight[4], GLdouble **dataOut )
{
GLdouble *vert = NewVector(coords[0], coords[1]);
*dataOut = vert;
}
//------------------------------------------------------------------------------
void CALLBACK ErrorCallback(GLenum errorCode)
{
fprintf(stderr,"Tessellation Error: %s
", gluErrorString(errorCode));
exit(1);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void display()
{
//Erase the window and the depth buffer
glClearColor(1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT);
GLUtesselator* tess = gluNewTess();
gluTessCallback(tess, GLU_TESS_BEGIN, (void (CALLBACK*)())&BeginCallback);
gluTessCallback(tess, GLU_TESS_VERTEX, (void (CALLBACK*)())&VertexCallback);
gluTessCallback(tess, GLU_TESS_END, (void (CALLBACK*)())&EndCallback);
gluTessCallback(tess, GLU_TESS_COMBINE, (void (CALLBACK*)())&CombineCallback);
gluTessCallback(tess, GLU_TESS_ERROR, (void (CALLBACK*)())&ErrorCallback);
gluTessNormal(tess, 0.0, 0.0, 1.0);
gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE); //GL_FALSE
gluTessBeginPolygon(tess, NULL);
gluTessBeginContour(tess);
glColor4f(0.0f, 0.0f, 1.0f, 0.062f);
//these coordinates don't render the polygon as expected using the GLU_TESS_WINDING_ODD winding rule ...
GLdouble poly[][2] = {{280.0, 290.0}, {170.0, 250.0}, {501.0, 188.0}, {140.0, 393.0}, {140.0, 61.0}};
//however, repositioning the first coordinate above just a little, it does render as expected ...
//GLdouble poly[][2] = {{280.0, 330.0}, {170.0, 250.0}, {501.0, 188.0}, {140.0, 393.0}, {140.0, 61.0}};
for (int i = 0; i < array_len(poly); ++i)
{
GLdouble *vert = NewVector(poly[i][0], poly[i][1]);
gluTessVertex(tess, vert, vert);
}
gluTessEndContour(tess);
gluTessEndPolygon(tess);
ClearVectors();
glFlush();
glutSwapBuffers();
}
//------------------------------------------------------------------------------
void key(unsigned char ch,int x,int y)
{
// Exit on ESC
if (ch == 27) exit(0);
}
//------------------------------------------------------------------------------
void reshape(int width,int height)
{
//setup 2D projection with origin at top-left corner ...
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 0, 1);
glViewport(0, 0, width, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//------------------------------------------------------------------------------
int main(int argc,char* argv[])
{
//Initialize GLUT
glutInit(&argc, argv);
//Request double buffered, true color window with Z buffering at 600x600
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize(600,600);
glutCreateWindow("Polygon test");
//Set callbacks
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(key);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTranslatef (0.375, 0.375, 0);
//Pass control to GLUT so it can interact with the user
glutMainLoop();
return 0;
}