+ return polys;
+}
+
+\f
+/* Make some pizza.
+ */
+
+#ifdef HAVE_TESS
+
+typedef struct {
+ GLdouble *points;
+ int i;
+} tess_out;
+
+
+static void
+tess_error_cb (GLenum errorCode)
+{
+ fprintf (stderr, "%s: tesselation error: %s\n",
+ progname, gluErrorString(errorCode));
+ exit (0);
+}
+
+static void
+tess_combine_cb (GLdouble coords[3], GLdouble *d[4], GLfloat w[4],
+ GLdouble **data_out)
+{
+ GLdouble *new = (GLdouble *) malloc (3 * sizeof(*new));
+ new[0] = coords[0];
+ new[1] = coords[1];
+ new[2] = coords[2];
+ *data_out = new;
+}
+
+
+#if 0
+static void
+tess_vertex_cb (void *vertex_data, void *closure)
+{
+ tess_out *to = (tess_out *) closure;
+ GLdouble *v = (GLdouble *) vertex_data;
+ to->points[to->i++] = v[0];
+ to->points[to->i++] = v[1];
+ to->points[to->i++] = v[2];
+}
+#endif
+
+static void
+tess_begin_cb (GLenum which)
+{
+ glBegin(which);
+}
+
+static void
+tess_end_cb (void)
+{
+ glEnd();
+}
+
+#endif /* HAVE_TESS */
+
+
+static int
+make_pizza (logo_configuration *dc, int facetted, int wire)
+{
+ int polys = 0;
+ int topfaces = (facetted ? 48 : 120);
+ int discfaces = (facetted ? 12 : 120);
+ int npoints = topfaces * 2 + 100;
+ GLdouble *points = (GLdouble *) calloc (npoints * 3, sizeof(GLdouble));
+ int nholes = 3;
+ GLdouble *holes = (GLdouble *) calloc (topfaces*nholes*3, sizeof(GLdouble));
+
+ GLfloat step = M_PI * 2 / 6 / topfaces;
+ GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 4;
+ GLfloat th, x, y, s;
+ int i, j, k;
+ int endpoints;
+ int endedge1;
+
+# ifdef HAVE_TESS
+ tess_out TO, *to = &TO;
+ GLUtesselator *tess = gluNewTess();
+
+ to->points = (GLdouble *) calloc (topfaces * 20, sizeof(GLdouble));
+ to->i = 0;
+
+# ifndef _GLUfuncptr
+# define _GLUfuncptr void(*)(void)
+# endif
+
+ gluTessCallback(tess,GLU_TESS_BEGIN, (_GLUfuncptr)tess_begin_cb);
+ gluTessCallback(tess,GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv);
+ gluTessCallback(tess,GLU_TESS_END, (_GLUfuncptr)tess_end_cb);
+ gluTessCallback(tess,GLU_TESS_COMBINE, (_GLUfuncptr)tess_combine_cb);
+ gluTessCallback(tess,GLU_TESS_ERROR, (_GLUfuncptr)tess_error_cb);
+
+ gluTessProperty (tess, GLU_TESS_BOUNDARY_ONLY, wire);
+ gluTessProperty (tess,GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
+
+# endif /* HAVE_TESS */
+
+ glPushMatrix();
+
+ s = 1.9;
+ glRotatef (180, 0, 0, 1);
+ glScalef (s, s, s);
+ glRotatef (90, 0, 1, 0);
+ glTranslatef (-0.53, 0, 0);
+ glRotatef (-30, 0, 0, 1);
+
+ /* Compute the wedge */
+ th = 0;
+ j = 0;
+
+ /* Edge 1 */
+ {
+ GLfloat edge[] = {
+ 0.000, 0.000,
+ 0.000, 0.210,
+ 0.042, 0.230,
+ 0.042, 0.616,
+ 0.000, 0.641,
+ };
+ for (i = 0; i < countof(edge)/2; i++)
+ {
+ points[j++] = edge[i*2+1];
+ points[j++] = edge[i*2];
+ points[j++] = 0;
+ }
+ endedge1 = i;
+ }
+
+ s = 0.798; /* radius of end of slice, before crust gap */
+ for (i = 0; i < topfaces; i++)
+ {
+ points[j++] = cos(th) * s;
+ points[j++] = sin(th) * s;
+ points[j++] = 0;
+ th += step;
+ }
+
+ /* Edge 2 */
+ {
+ GLfloat edge[] = {
+ 0.613, 0.353,
+ 0.572, 0.376,
+ 0.455, 0.309,
+ 0.452, 0.260,
+ 0.332, 0.192,
+ 0.293, 0.216,
+ 0.178, 0.149,
+ 0.178, 0.102,
+ };
+ for (i = 0; i < countof(edge)/2; i++)
+ {
+ points[j++] = edge[i*2+1];
+ points[j++] = edge[i*2];
+ points[j++] = 0;
+ }
+ endpoints = j/3;
+ }
+
+
+ /* Draw the rim of the slice */
+ glBegin (wire ? GL_LINES : GL_QUADS);
+ x = points[0];
+ y = points[1];
+ for (i = (wire ? 0 : 1); i < endpoints; i++)
+ {
+ GLdouble *p = points + (i*3);
+
+ do_normal (p[0], p[1], -thick2,
+ p[0], p[1], thick2,
+ x, y, thick2);
+ if (!wire)
+ {
+ glVertex3f (x, y, -thick2);
+ glVertex3f (x, y, thick2);
+ }
+ glVertex3f (p[0], p[1], thick2);
+ glVertex3f (p[0], p[1], -thick2);
+ x = p[0];
+ y = p[1];
+ polys++;
+ }
+
+ do_normal (points[0], points[1], -thick2,
+ points[0], points[1], thick2,
+ x, y, thick2);
+ glVertex3f (x, y, -thick2);
+ glVertex3f (x, y, thick2);
+ glVertex3f (points[0], points[1], thick2);
+ glVertex3f (points[0], points[1], -thick2);
+ polys++;
+ glEnd();
+
+# ifndef HAVE_TESS
+ if (wire)
+ {
+ /* Outline of slice */
+ glBegin (GL_LINE_LOOP);
+ for (i = 0; i < endpoints; i++)
+ glVertex3f (points[i*3], points[i*3+1], -thick2);
+ glEnd();
+ glBegin (GL_LINE_LOOP);
+ for (i = 0; i < endpoints; i++)
+ glVertex3f (points[i*3], points[i*3+1], thick2);
+ glEnd();
+ }
+# endif /* HAVE_TESS */
+
+ /* Compute the holes */
+ step = M_PI * 2 / discfaces;
+ for (k = 0; k < nholes; k++)
+ {
+ GLdouble *p = holes + (discfaces * 3 * k);
+ th = 0;
+ j = 0;
+ switch (k) {
+ case 0: x = 0.34; y = 0.17; s = 0.05; break;
+ case 1: x = 0.54; y = 0.17; s = 0.06; break;
+ case 2: x = 0.55; y = 0.36; s = 0.06; break;
+ default: abort(); break;
+ }
+ for (i = 0; i < discfaces; i++)
+ {
+ p[j++] = x + cos(M_PI*2 - th) * s;
+ p[j++] = y + sin(M_PI*2 - th) * s;
+ p[j++] = 0;
+ th += step;
+ }
+ }
+
+
+ /* Draw the inside rim of the holes */
+ for (k = 0; k < nholes; k++)
+ {
+ GLdouble *p = holes + (discfaces * 3 * k);
+
+ glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
+ for (i = 0; i < discfaces; i++)
+ {
+ GLdouble *p2 = p + (i*3);
+ if (i > 0)
+ do_normal (p2[0], p2[1], -thick2,
+ p2[0], p2[1], thick2,
+ p2[-3], p2[-2], thick2);
+ glVertex3f (p2[0], p2[1], -thick2);
+ glVertex3f (p2[0], p2[1], thick2);
+ polys++;
+ }
+ glVertex3f (p[0], p[1], -thick2);
+ glVertex3f (p[0], p[1], thick2);
+ polys++;
+ glEnd();
+# ifndef HAVE_TESS
+ if (wire)
+ {
+ /* Outline of holes */
+ glBegin (GL_LINE_LOOP);
+ for (i = 0; i < discfaces; i++)
+ glVertex3f (p[i*3], p[i*3+1], -thick2);
+ glEnd();
+ glBegin (GL_LINE_LOOP);
+ for (i = 0; i < discfaces; i++)
+ glVertex3f (p[i*3], p[i*3+1], thick2);
+ glEnd();
+ }
+# endif /* !HAVE_TESS */
+ }
+
+# ifdef HAVE_TESS
+ glTranslatef (0, 0, -thick2);
+ for (y = 0; y <= 1; y++)
+ {
+ if (y) glTranslatef (0, 0, thick2*2);
+
+ /* A non-convex polygon */
+ gluTessBeginPolygon (tess, to);
+
+ glNormal3f (0, 0, (y > 0 ? 1 : -1));
+ gluTessNormal (tess, 0, 0, (y > 0 ? 1 : -1));
+ glFrontFace (GL_CCW);
+
+ /* Tess the wedge */
+ gluTessBeginContour (tess);
+ for (i = 0; i < endpoints; i++)
+ {
+ GLdouble *p = points + (i*3);
+ gluTessVertex (tess, p, p);
+ polys++;
+ }
+ gluTessVertex (tess, points, points);
+ gluTessEndContour (tess);
+
+ /* Tess the holes */
+ for (k = 0; k < nholes; k++)
+ {
+ GLdouble *p = holes + (discfaces * 3 * k);
+ gluTessBeginContour (tess);
+ for (i = 0; i < discfaces; i++)
+ {
+ GLdouble *p2 = p + (i*3);
+ gluTessVertex (tess, p2, p2);
+ polys++;
+ }
+ gluTessEndContour (tess);
+ }
+
+ gluTessEndPolygon (tess);
+ }
+
+ glTranslatef (0, 0, -thick2);
+
+# else /* !HAVE_TESS */
+ if (! wire)
+ {
+ glDisableClientState (GL_COLOR_ARRAY);
+ glDisableClientState (GL_NORMAL_ARRAY);
+ glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState (GL_VERTEX_ARRAY);
+ glVertexPointer (3, GL_FLOAT, 0, dnapizza_triangles);
+
+ glTranslatef(0, 0, thick2);
+ glNormal3f (0, 0, 1);
+ glFrontFace (GL_CW);
+ glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
+
+ glTranslatef(0, 0, -thick2*2);
+ glNormal3f (0, 0, -1);
+ glFrontFace (GL_CCW);
+ glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
+
+ glTranslatef(0, 0, thick2);
+ }
+# endif /* !HAVE_TESS */
+
+
+ /* Compute the crust */
+
+ s = 0.861; /* radius of inside of crust */
+ step = M_PI * 2 / 6 / topfaces;
+ th = 0;
+ j = 0;
+ for (i = 0; i < topfaces; i++)
+ {
+ points[j++] = cos(th) * s;
+ points[j++] = sin(th) * s;
+ points[j++] = 0;
+ th += step;
+ }
+
+ s = 1;
+ for (i = 0; i < topfaces; i++)
+ {
+ points[j++] = cos(th) * s;
+ points[j++] = sin(th) * s;
+ points[j++] = 0;
+ th -= step;
+ }
+
+ /* Draw the rim of the crust */
+ glFrontFace (GL_CCW);
+ glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
+ for (i = 0; i < topfaces * 2; i++)
+ {
+ GLdouble *p = points + (i*3);
+ if (i == 0 || i == (topfaces*2)-1)
+ glNormal3f (0, -1, 0);
+ else if (i == topfaces-1 || i == topfaces)
+ glNormal3f (0, 1, 0);
+ else
+ do_normal (p[-3], p[-2], thick2,
+ p[0], p[1], thick2,
+ p[0], p[1], -thick2);
+ glVertex3f (p[0], p[1], -thick2);
+ glVertex3f (p[0], p[1], thick2);
+ polys++;
+ }
+ glVertex3f (points[0], points[1], -thick2);
+ glVertex3f (points[0], points[1], thick2);
+ polys++;
+ glEnd();
+
+ if (wire)
+ {
+ glBegin (GL_LINE_STRIP);
+ for (i = 0; i < topfaces * 2; i++)
+ {
+ GLdouble *p = points + (i*3);
+ glVertex3f (p[0], p[1], -thick2);
+ polys++;
+ }
+ glVertex3f (points[0], points[1], -thick2);
+ glEnd();
+
+ glBegin (GL_LINE_STRIP);
+ for (i = 0; i < topfaces * 2; i++)
+ {
+ GLdouble *p = points + (i*3);
+ glVertex3f (p[0], p[1], thick2);
+ polys++;
+ }
+ glVertex3f (points[0], points[1], thick2);
+ glEnd();
+ }
+
+ /* Draw the top of the crust */
+ if (! wire)
+ {
+ glFrontFace (GL_CW);
+ glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP);
+ glNormal3f (0, 0, -1);
+ if (!wire)
+ for (i = 0; i < topfaces; i++)
+ {
+ int ii = topfaces + (topfaces - i - 1);
+ GLdouble *p1 = points + (i*3);
+ GLdouble *p2 = points + (ii*3);
+ glVertex3f (p1[0], p1[1], -thick2);
+ glVertex3f (p2[0], p2[1], -thick2);
+ polys++;
+ }
+ polys++;
+ glEnd();
+
+ /* Draw the bottom of the crust */
+ glFrontFace (GL_CCW);
+ glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
+ glNormal3f (0, 0, 1);
+ for (i = 0; i < topfaces; i++)
+ {
+ int ii = topfaces + (topfaces - i - 1);
+ GLdouble *p1 = points + (i*3);
+ GLdouble *p2 = points + (ii*3);
+ glVertex3f (p1[0], p1[1], thick2);
+ glVertex3f (p2[0], p2[1], thick2);
+ polys++;
+ }
+ polys++;
+ glEnd();
+ }
+
+# ifdef HAVE_TESS
+ gluDeleteTess (tess);
+ free (to->points);
+# endif /* HAVE_TESS */
+
+ free (points);
+ free (holes);
+
+ glPopMatrix();
+
+ return polys;