bug(?) in glu tesselation algorithm

i’ve tested this code on linux and windows(both opengl shipped with vs2008 and mesa implementation). neither works properly.
the problem appears to be in the glu tesselation algorithm. my suggestion is that something strange happens in file “sweep.c” in function CheckForIntersect, line 657-677. this code seems to move the correct intersection point, computed previously at line 650, to the completly incorrect location resulting in an incorrect tesselation result. this situation happens due to very tight input data(notice that 427.00000000000011 and 427.00000000000006 differs only in the last bit). if we substitute 427.00000000000006 for 427.00000000000000, making difference two “epsilons” large, then algorithm performs correctly. could someone suggest me how to patch this situation correctly or provide me some emails of the sgi glu reference implementation authors(which algorithms I suppose is used in all popular glu implementations)?


#include <windows.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <stdio.h>
#include <stdlib.h>

void __stdcall errorCallback(GLenum error)
{
	const GLubyte * errstring = gluErrorString(error);
	fprintf(stderr, "Error : %s
", errstring);
}

GLdouble g_cache[1000];
int g_cacheMax = 0;

void __stdcall combineCallback(GLdouble coords[3], GLdouble * vertex_data[4], GLfloat weight[4], GLdouble **dataOut)
{
	GLdouble * vertex = g_cache + g_cacheMax;
	vertex[0] = coords[0];
	vertex[1] = coords[1];
	vertex[2] = coords[2];
	*dataOut = vertex;
	g_cacheMax += 3;
}

GLdouble tri1[3][3] = {427.00000000000011, 242.19929463020139, 0, 
                       77.468120999492129, 524.93719412910195, 0,
					   427.00000000000006, 836.00000000000011, 0};
GLdouble tri2[3][3] = {427.00000000000011, 521.97505956130124, 0,
                       77.468120999492129, 524.93719412910195, 0,
					   427.00000000000011, 242.19929463020139, 0};

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0, 1.0, 1.0);
	GLUtesselator * t = gluNewTess();
	gluTessProperty(t, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE);
	gluTessNormal(t, 0, 0, 1);
	gluTessCallback(t, GLU_TESS_VERTEX, (void (__stdcall*)())glVertex3dv);
	gluTessCallback(t, GLU_TESS_BEGIN, (void (__stdcall*)())glBegin);
	gluTessCallback(t, GLU_TESS_END, (void (__stdcall*)())glEnd);
	gluTessCallback(t, GLU_TESS_ERROR, (void (__stdcall*)())errorCallback);
	gluTessCallback(t, GLU_TESS_COMBINE, (void (__stdcall*)())combineCallback);

	gluTessBeginPolygon(t, NULL);
	  gluTessBeginContour(t);
		  gluTessVertex(t, tri1[0], tri1[0]);
		  gluTessVertex(t, tri1[1], tri1[1]);
		  gluTessVertex(t, tri1[2], tri1[2]);
	  gluTessEndContour(t);
	  gluTessBeginContour(t);
	      gluTessVertex(t, tri2[0], tri2[0]);
		  gluTessVertex(t, tri2[1], tri2[1]);
		  gluTessVertex(t, tri2[2], tri2[2]);
	  gluTessEndContour(t);
	gluTessEndPolygon(t);
	
	gluDeleteTess(t);

	glEnd();
	glFlush();
	glutSwapBuffers();
}

void reshape(int w, int h)
{
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, w, h, 0, -10.0, 10.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(1280, 800);
	glutInitWindowPosition(0, 00);
	glutCreateWindow(argv[0]);
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutMainLoop();
	return 0;
}