From http://www.jwz.org/xscreensaver/xscreensaver-5.24.tar.gz
[xscreensaver] / hacks / glx / dnalogo.c
index 8cdca30fc1ad43b52de48308074dcddbb6bf6662..075fb55877e9ad3c5e7c2e6fc2a23f4f1a765aee 100644 (file)
@@ -1,4 +1,15 @@
-/* DNA Logo, Copyright (c) 2001, 2002, 2003 Jamie Zawinski <jwz@jwz.org>
+/* DNA Logo, Copyright (c) 2001-2011 Jamie Zawinski <jwz@jwz.org>
+ *
+ *      DNA Lounge
+ *
+ *      Restaurant -- Bar -- Nightclub -- Cafe -- Est. 1985.
+ *
+ *      375 Eleventh Street
+ *      San Francisco, CA
+ *      94103
+ *
+ *      http://www.dnalounge.com/
+ *      http://www.dnapizza.com/
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
                        "*doGasket:         True    \n" \
                        "*doHelix:          True    \n" \
                        "*doLadder:         True    \n" \
+                       "*doFrame:          True    \n" \
                        "*wallFacets:       360     \n" \
-                       "*tubeFacets:       90      \n" \
+                       "*barFacets:        90      \n" \
                        "*clockwise:        False   \n" \
-                       "*turns:            0.    \n" \
-                       "*turnSpacing:      2.40    \n" \
-                       "*barSpacing:       0.30    \n" \
-                       "*wallHeight:       0.4     \n" \
-                       "*wallThickness:    0.1     \n" \
-                       "*tubeThickness:    0.075   \n" \
-                       "*wallTaper:        1.047   \n" \
-                       "*gasketSize:       2.15    \n" \
+                       "*turns:            0.69    \n" \
+                       "*turnSpacing:      2.    \n" \
+                       "*barSpacing:       0.24    \n" \
+                       "*wallHeight:       0.45    \n" \
+                       "*wallThickness:    0.12    \n" \
+                       "*barThickness:     0.058   \n" \
+                       "*wallTaper:        0.95    \n" \
+                       "*gasketSize:       1.88    \n" \
                        "*gasketDepth:      0.15    \n" \
                        "*gasketThickness:  0.4     \n" \
+                       "*frameSize:        1.20    \n" \
+                       "*frameDepth:       0.01    \n" \
+                       "*frameThickness:   0.03    \n" \
+                       "*triangleSize:     0.045   \n" \
                        "*speed:            1.0     \n" \
+                       "*mode:             both"  "\n" \
                        ".foreground:       #00AA00 \n" \
+                       "*geometry:         =640x640\n" \
 
 # define refresh_logo 0
 # define release_logo 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
+#undef LINEAR
+#undef DXF_OUTPUT_HACK
+
+#ifdef DXF_OUTPUT_HACK   /* When this is defined, instead of rendering
+                            to the screen, we write a DXF CAD file to stdout.
+                            This is a kludge of shocking magnitude...
+                            Maybe there's some other way to intercept all
+                            glVertex3f calls than with a #define? */
+# define unit_tube dxf_unit_tube
+# define unit_cone dxf_unit_cone
+# define tube_1    dxf_tube_1
+# define tube      dxf_tube
+# define cone      dxf_cone
+#endif /* DXF_OUTPUT_HACK */
+
 #include "xlockmore.h"
 #include "normals.h"
 #include "tube.h"
 
 #ifdef USE_GL /* whole file */
 
+#ifdef HAVE_JWZGLES
+# include "dnapizza.h"
+#else
+# define HAVE_TESS
+#endif
+
+typedef enum {
+  HELIX_IN, HELIX, HELIX_OUT, 
+  PIZZA_IN, PIZZA, PIZZA_OUT,
+  BOTH
+} glyph_mode;
+
 typedef struct {
   Bool spinning_p;
   GLfloat position;     /* 0.0 - 1.0 */
@@ -56,10 +101,13 @@ typedef struct {
   GLXContext *glx_context;
 
   GLuint helix_list,  helix_list_wire,  helix_list_facetted;
+  GLuint pizza_list,  pizza_list_wire,  pizza_list_facetted;
   GLuint gasket_list, gasket_list_wire;
+  GLuint frame_list,  frame_list_wire;
+  int polys[7];
 
   int wall_facets;
-  int tube_facets;
+  int bar_facets;
   Bool clockwise;
   GLfloat color[4];
 
@@ -68,18 +116,28 @@ typedef struct {
   GLfloat bar_spacing;
   GLfloat wall_height;
   GLfloat wall_thickness;
-  GLfloat tube_thickness;
+  GLfloat bar_thickness;
   GLfloat wall_taper;
 
   GLfloat gasket_size;
   GLfloat gasket_depth;
   GLfloat gasket_thickness;
 
+  GLfloat frame_size;
+  GLfloat frame_depth;
+  GLfloat frame_thickness;
+  GLfloat triangle_size;
+
   GLfloat speed;
+  glyph_mode mode;
+  glyph_mode anim_state;
+  GLfloat anim_ratio;
 
   spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz;
   spinner scene_spinnerx,  scene_spinnery;
   spinner helix_spinnerz;
+  spinner pizza_spinnery, pizza_spinnerz;
+  spinner frame_spinner;
 
   trackball_state *trackball;
   Bool button_down_p;
@@ -91,7 +149,11 @@ typedef struct {
 static logo_configuration *dcs = NULL;
 
 static XrmOptionDescRec opts[] = {
-  { "-speed",  ".speed",  XrmoptionSepArg, 0 },
+  { "-speed",  ".speed",  XrmoptionSepArg, 0       },
+  { "-mode",   ".mode",   XrmoptionSepArg, 0       },
+  { "-pizza",  ".mode",   XrmoptionNoArg,  "pizza" },
+  { "-helix",  ".mode",   XrmoptionNoArg,  "helix" },
+  { "-both",   ".mode",   XrmoptionNoArg,  "both"  },
 };
 
 ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
@@ -99,6 +161,272 @@ ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
 #define PROBABILITY_SCALE 600
 
 
+#ifdef DXF_OUTPUT_HACK
+
+# define glBegin         dxf_glBegin
+# define glVertex3f      dxf_glVertex3f
+# define glVertex3dv     dxf_glVertex3dv
+# define glEnd           dxf_glEnd
+# define glVertexPointer dxf_glVertexPointer
+# define glDrawArrays    dxf_glDrawArrays
+
+static int dxf_type, dxf_point, dxf_point_total, dxf_layer, dxf_color;
+static GLfloat dxf_quads[4*4];
+
+static void
+dxf_glBegin (int type)
+{
+  dxf_type = type; 
+  dxf_point = 0;
+  dxf_point_total = 0;
+}
+
+static void
+dxf_glVertex3f (GLfloat ox, GLfloat oy, GLfloat oz)
+{
+  int i = 0;
+  GLfloat m[4*4];
+  GLfloat x, y, z;
+
+  /* Transform the point into modelview space. */
+  glGetFloatv (GL_MODELVIEW_MATRIX, m);
+  x = ox * m[0] + oy * m[4] + oz * m[8]  + m[12];
+  y = ox * m[1] + oy * m[5] + oz * m[9]  + m[13];
+  z = ox * m[2] + oy * m[6] + oz * m[10] + m[14];
+
+  dxf_quads[dxf_point*3+0] = x;
+  dxf_quads[dxf_point*3+1] = y;
+  dxf_quads[dxf_point*3+2] = z;
+  dxf_point++;
+  dxf_point_total++;
+
+  switch (dxf_type) {
+  case GL_QUADS:
+    if (dxf_point < 4) return;
+
+    fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
+    fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
+
+    fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
+
+    fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
+
+    fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
+    dxf_point = 0;
+    break;
+
+  case GL_QUAD_STRIP:
+    if (dxf_point < 4) return;
+
+    fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
+    fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
+
+    fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
+
+    fprintf (stdout, "12\n%.6f\n", dxf_quads[i+3]);  /* funky quad strip */
+    fprintf (stdout, "22\n%.6f\n", dxf_quads[i+4]);  /* vert order: 1243. */
+    fprintf (stdout, "32\n%.6f\n", dxf_quads[i+5]);
+
+    fprintf (stdout, "13\n%.6f\n", dxf_quads[i]);
+    fprintf (stdout, "23\n%.6f\n", dxf_quads[i+1]);
+    fprintf (stdout, "33\n%.6f\n", dxf_quads[i+2]);
+    i += 6;
+
+    dxf_quads[0] = dxf_quads[6];       /* copy point 3 to pos 1 */
+    dxf_quads[1] = dxf_quads[7];
+    dxf_quads[2] = dxf_quads[8];
+    dxf_quads[3] = dxf_quads[9];       /* copy point 4 to pos 2 */
+    dxf_quads[4] = dxf_quads[10];
+    dxf_quads[5] = dxf_quads[11];
+    dxf_point = 2;                     /* leave those two points in queue */
+    break;
+
+  case GL_TRIANGLES:
+  case GL_TRIANGLE_FAN:
+    if (dxf_point < 3) return;
+
+    fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
+    fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
+
+    fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
+
+    fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
+
+    i -= 3;
+    fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]);  /* dup pt 4 as pt 3. */
+    fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
+
+    dxf_point = 0;
+    if (dxf_type == GL_TRIANGLE_FAN)
+      {
+        dxf_quads[3] = dxf_quads[6];   /* copy point 3 to point 2 */
+        dxf_quads[4] = dxf_quads[7];
+        dxf_quads[5] = dxf_quads[8];
+        dxf_point = 2;                 /* leave two points in queue */
+      }
+    break;
+
+  case GL_TRIANGLE_STRIP:
+    if (dxf_point < 3) return;
+
+    fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
+
+    fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
+
+    fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
+
+    fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
+
+    i -= 3;
+    fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]);  /* dup pt 4 as pt 3. */
+    fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
+
+    dxf_quads[0] = dxf_quads[3];       /* copy point 2 to pos 1 */
+    dxf_quads[1] = dxf_quads[4];
+    dxf_quads[2] = dxf_quads[5];
+    dxf_quads[3] = dxf_quads[6];       /* copy point 3 to pos 2 */
+    dxf_quads[4] = dxf_quads[7];
+    dxf_quads[5] = dxf_quads[8];
+    dxf_point = 2;                     /* leave those two points in queue */
+    break;
+
+  case GL_LINES:
+  case GL_LINE_STRIP:
+  case GL_LINE_LOOP:
+
+    if (dxf_point_total == 1)
+      {
+        dxf_quads[6] = ox;
+        dxf_quads[7] = oy;
+        dxf_quads[8] = oz;
+      }
+
+    if (dxf_point < 2) return;
+
+    fprintf (stdout, "0\nLINE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
+
+    fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
+
+    fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
+    fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
+
+    dxf_point = 0;
+    if (dxf_type != GL_LINES)
+      {
+        dxf_quads[0] = dxf_quads[3];
+        dxf_quads[1] = dxf_quads[4];
+        dxf_quads[2] = dxf_quads[5];
+        dxf_point = 1;
+      }
+    break;
+
+  default:
+    abort();
+    break;
+  }
+}
+
+
+static void
+dxf_glVertex3dv (const GLdouble *v)
+{
+  glVertex3f (v[0], v[1], v[2]);
+}
+
+
+static void
+dxf_glEnd(void)
+{
+  if (dxf_type == GL_LINE_LOOP)  /* close loop */
+    glVertex3f (dxf_quads[6], dxf_quads[7], dxf_quads[8]);
+  dxf_type = -1;
+  dxf_point = 0;
+  dxf_point_total = 0;
+}
+
+
+static void
+dxf_start (void)
+{
+  fprintf (stdout, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n");
+  fprintf (stdout, "0\nSECTION\n2\nENTITIES\n");
+}
+
+static void
+dxf_end (void)
+{
+  fprintf (stdout, "0\nENDSEC\n0\nEOF\n");
+  exit (0);
+}
+
+
+static const GLvoid *dxf_vp;
+static GLsizei dxf_vp_size;
+static GLsizei dxf_vp_stride;
+
+static void
+dxf_glVertexPointer (GLint size, GLenum type, GLsizei stride,
+                     const GLvoid *pointer)
+{
+  if (type != GL_FLOAT) abort();
+  if (stride <= 0) abort();
+  dxf_vp = pointer;
+  dxf_vp_size = size;
+  dxf_vp_stride = stride;
+}
+
+static void
+dxf_glDrawArrays (GLenum mode, GLint first, GLsizei count)
+{
+  int i;
+  unsigned char *a = (unsigned char *) dxf_vp;
+  dxf_glBegin (mode);
+  for (i = first; i < first+count; i++)
+    {
+      GLfloat *fa = (GLfloat *) a;
+      dxf_glVertex3f (fa[0], fa[1], fa[2]);
+      a += dxf_vp_stride;
+    }
+  dxf_glEnd();
+}
+
+
+# define XYZ tube_XYZ /* avoid conflict with normals.h */
+# include "tube.c"    /* Yes, I really am including a C file. */
+# undef XYZ
+
+#endif /* DXF_OUTPUT_HACK */
+
+
 \f
 /* Calculate the angle (in degrees) between two vectors.
  */
@@ -133,10 +461,11 @@ vector_angle (double ax, double ay, double az,
 /* Make the helix
  */
 
-static void
+static int
 make_helix (logo_configuration *dc, int facetted, int wire)
 {
-  int wall_facets = dc->wall_facets / (facetted ? 15 : 1);
+  int polys = 0;
+  int wall_facets = dc->wall_facets / (facetted ? 10 : 1);
   GLfloat th;
   GLfloat max_th = M_PI * 2 * dc->turns;
   GLfloat th_inc = M_PI * 2 / wall_facets;
@@ -156,8 +485,8 @@ make_helix (logo_configuration *dc, int facetted, int wire)
 
   z1 = -(dc->turn_spacing * dc->turns / 2);
 
-  h1 = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2);
-  h1off = (dc->wall_taper > 0 ? -dc->wall_height / 2 : 0);
+  h1    = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2);
+  h1off = (dc->wall_taper > 0 ?    -dc->wall_height / 2 : 0);
 
   if (!dc->clockwise)
     z1 = -z1, z_inc = -z_inc, h1off = -h1off;
@@ -176,6 +505,7 @@ make_helix (logo_configuration *dc, int facetted, int wire)
       glVertex3f( x1, y1,  z1 + h1 + h1off);
       glVertex3f(x1b, y1b, z1 + h1 + h1off);
       glVertex3f(x1b, y1b, z1 - h1 + h1off);
+      polys++;
       glEnd();
     }
 
@@ -229,6 +559,7 @@ make_helix (logo_configuration *dc, int facetted, int wire)
       glNormal3f(x2, y2, 0);
       glVertex3f(x2, y2, z2 + h2 + h2off);
       glVertex3f(x2, y2, z2 - h2 + h2off);
+      polys++;
       glEnd();
 
       /* inner face
@@ -241,6 +572,7 @@ make_helix (logo_configuration *dc, int facetted, int wire)
       glNormal3f(-x2b, -y2b, 0);
       glVertex3f( x2b,  y2b, z2 + h2 + h2off);
       glVertex3f( x2b,  y2b, z2 - h2 + h2off);
+      polys++;
       glEnd();
 
       /* top face
@@ -255,7 +587,7 @@ make_helix (logo_configuration *dc, int facetted, int wire)
       glVertex3f( x2b,  y2b, z2 + h2 + h2off);
       glVertex3f( x1b,  y1b, z1 + h1 + h1off);
       glVertex3f( x1,   y1,  z1 + h1 + h1off);
-
+      polys++;
       glEnd();
 
       /* bottom face
@@ -270,6 +602,7 @@ make_helix (logo_configuration *dc, int facetted, int wire)
       glVertex3f( x1b,  y1b, z1 - h1 + h1off);
       glVertex3f( x2b,  y2b, z2 - h2 + h2off);
       glVertex3f( x2,   y2,  z2 - h2 + h2off);
+      polys++;
       glEnd();
 
       x1 = x2;
@@ -295,14 +628,17 @@ make_helix (logo_configuration *dc, int facetted, int wire)
       glVertex3f(x2,  y2,  z1 + h2 + h2off);
       glVertex3f(x2b, y2b, z1 + h2 + h2off);
       glVertex3f(x2b, y2b, z1 - h2 + h2off);
+      polys++;
       glEnd();
     }
+  return polys;
 }
 
 
-static void
+static int
 make_ladder (logo_configuration *dc, int facetted, int wire)
 {
+  int polys = 0;
   GLfloat th;
   GLfloat max_th = dc->turns * M_PI * 2;
   GLfloat max_z  = dc->turns * dc->turn_spacing;
@@ -315,9 +651,13 @@ make_ladder (logo_configuration *dc, int facetted, int wire)
   GLfloat usable_th = max_th - dc->wall_taper;
   GLfloat usable_z  = max_z / (max_th / usable_th);
   int nbars = usable_z / dc->bar_spacing;
-  GLfloat used_z = (nbars - 1) * dc->bar_spacing;
-  GLfloat pad_z = max_z - used_z;
-  GLfloat pad_ratio = pad_z / max_z;
+  GLfloat used_z, pad_z, pad_ratio;
+
+  if (! (nbars & 1)) nbars--;  /* always an odd number of bars */
+
+  used_z = (nbars - 1) * dc->bar_spacing;
+  pad_z = max_z - used_z;
+  pad_ratio = pad_z / max_z;
 
   th = (max_th * pad_ratio/2);
   z  = -(max_z / 2) + (max_z * pad_ratio/2);
@@ -325,19 +665,21 @@ make_ladder (logo_configuration *dc, int facetted, int wire)
   if (!dc->clockwise)
     z = -z, z_inc = -z_inc;
 
+  glFrontFace(GL_CCW);
   for (i = 0; i < nbars; i++)
     {
-      int facets = dc->tube_facets / (facetted ? 14 : 1);
+      int facets = dc->bar_facets / (facetted ? 14 : 1);
       if (facets <= 3) facets = 3;
       x = cos (th) * (1 - dc->wall_thickness);
       y = sin (th) * (1 - dc->wall_thickness);
-      tube ( x,  y, z,
-            -x, -y, z,
-             dc->tube_thickness, 0, facets,
-             True, True, wire);
+      polys += tube ( x,  y, z,
+                     -x, -y, z,
+                      dc->bar_thickness, 0, facets,
+                      True, True, wire);
       z  += z_inc;
       th += th_inc;
     }
+  return polys;
 }
 
 
@@ -346,9 +688,10 @@ make_ladder (logo_configuration *dc, int facetted, int wire)
  */
 
 
-static void
+static int
 make_gasket (logo_configuration *dc, int wire)
 {
+  int polys = 0;
   int i;
   int points_size;
   int npoints = 0;
@@ -360,20 +703,24 @@ make_gasket (logo_configuration *dc, int wire)
 
   GLfloat *pointsx0, *pointsy0, *pointsx1, *pointsy1, *normals;
 
-  GLfloat r0  = 0.780;  /* 395 */
-  GLfloat r1a = 0.855;                /* top of wall below upper left hole */
-  GLfloat r1b = 0.890;                /* center of upper left hole */
-  GLfloat r1c = 0.922;                /* bottom of wall above hole */
-  GLfloat r1  = 0.928;  /* 471 */
-  GLfloat r2  = 0.966;  /* 490 */
-  GLfloat r3  = 0.984;  /* 499 */
+  GLfloat r0  = 0.750;  /* 395 */
+  GLfloat r1a = 0.825;                /* bottom of wall below upper left hole */
+  GLfloat r1b = 0.867;                /* center of upper left hole */
+  GLfloat r1c = 0.909;                /* top of wall above hole */
+  GLfloat r1  = 0.916;  /* 471 */
+  GLfloat r2  = 0.963;  /* 490 */
+  GLfloat r3  = 0.960;  /* 499 */
   GLfloat r4  = 1.000;  /* 507 */
-  GLfloat r5  = 1.090;  /* 553 */
+  GLfloat r5  = 1.080;  /* 553 */
 
   GLfloat ctrl_r[100], ctrl_th[100];
 
   glPushMatrix();
 
+# ifdef DXF_OUTPUT_HACK
+  if (! wire) res *= 8;
+# endif
+
 # define POINT(r,th) \
     ctrl_r [nctrls] = r, \
     ctrl_th[nctrls] = (th * d2r), \
@@ -388,46 +735,46 @@ make_gasket (logo_configuration *dc, int wire)
   POINT (0.872, 3.95);
 
   POINT (r4,    4.0);   /* moving clockwise... */
-  POINT (r4,   48.2);
-  POINT (r1,   48.2);
-  POINT (r1,   54.2);
-  POINT (r2,   55.8);
-  POINT (r2,   73.2);
-  POINT (r1,   74.8);
-  POINT (r1,  101.2);
-  POINT (r3,  103.4);
+  POINT (r4,   47.0);
+  POINT (r1,   47.0);
+  POINT (r1,   53.0);
+  POINT (r2,   55.5);
+  POINT (r2,   72.3);
+  POINT (r1,   74.0);
+  POINT (r1,  100.0);
+  POINT (r3,  102.5);
   POINT (r3,  132.0);
-  POINT (r1,  133.4);
+  POINT (r1,  133.0);
 
   POINT (r1,  180.7);
   POINT (r2,  183.6);
-  POINT (r2,  209.8);
-  POINT (r1,  211.0);
-  POINT (r1,  221.8);
-  POINT (r5,  221.8);
+  POINT (r2,  210.0);
+  POINT (r1,  212.0);
+  POINT (r1,  223.2);
   POINT (r5,  223.2);
-  POINT (r4,  223.2);
-
-  POINT (r4,  316.8);      /* upper left indentation */
-  POINT (0.990, 326.87);
-  POINT (0.880, 327.21);
-  POINT (0.872, 327.45);
-  POINT (0.869, 327.80);
-  POINT (0.867, 328.10);
-
-  POINT (0.867, 328.85);
-  POINT (0.869, 329.15);
-  POINT (0.872, 329.50);
-  POINT (0.880, 329.74);
-  POINT (0.990, 330.08);
-
-  POINT (r4,  339.0);
+  POINT (r5,  225.0);
+  POINT (r4,  225.0);
+
+  POINT (r4,    316.8);      /* upper left indentation */
+  POINT (0.990, 316.87);
+  POINT (0.880, 317.21);
+  POINT (0.872, 317.45);
+  POINT (0.869, 317.80);
+  POINT (0.867, 318.10);
+
+  POINT (0.867, 318.85);
+  POINT (0.869, 319.15);
+  POINT (0.872, 319.50);
+  POINT (0.880, 319.74);
+  POINT (0.990, 320.08);
+
+  POINT (r4,  338.0);
   if (! wire)
     {
-      POINT (r1a, 339.0);      /* cut-out disc */
-      POINT (r1a, 343.0);
+      POINT (r1a, 338.0);      /* cut-out disc */
+      POINT (r1a, 344.0);
     }
-  POINT (r4,  343.0);
+  POINT (r4,  344.0);
   POINT (r4,  356.0);
 
   POINT (0.872, 356.05);   /* top indentation, left half */
@@ -506,12 +853,14 @@ make_gasket (logo_configuration *dc, int wire)
           glBegin (GL_LINE_LOOP);
           for (i = 0; i < npoints; i++)
             glVertex3f (pointsx0[i], pointsy0[i], z);
+          polys += npoints;
           glEnd();
 
           /* outside edge */
           glBegin (GL_LINE_LOOP);
           for (i = 0; i < npoints; i++)
             glVertex3f (pointsx1[i], pointsy1[i], z);
+          polys += npoints;
           glEnd();
 # else
           for (i = 1; i < npoints; i++)
@@ -523,6 +872,7 @@ make_gasket (logo_configuration *dc, int wire)
               glVertex3f (pointsx1[i-1], pointsy1[i-1], z);
               glEnd();
             }
+          polys += npoints;
 # endif
         }
 #if 1
@@ -536,6 +886,7 @@ make_gasket (logo_configuration *dc, int wire)
           glVertex3f (pointsx1[i], pointsy1[i], -thick2);
           glVertex3f (pointsx1[i], pointsy1[i],  thick2);
         }
+      polys += npoints;
       glEnd();
 #endif
     }
@@ -550,6 +901,7 @@ make_gasket (logo_configuration *dc, int wire)
           glVertex3f (pointsx0[i], pointsy0[i], -thick2);
           glVertex3f (pointsx1[i], pointsy1[i], -thick2);
         }
+      polys += npoints;
       glEnd();
 
       /* bottom */
@@ -561,6 +913,7 @@ make_gasket (logo_configuration *dc, int wire)
           glVertex3f (pointsx0[i], pointsy0[i], thick2);
           glVertex3f (pointsx1[i], pointsy1[i], thick2);
         }
+      polys += npoints;
       glEnd();
 
       /* inside edge */
@@ -572,6 +925,7 @@ make_gasket (logo_configuration *dc, int wire)
           glVertex3f ( pointsx0[i],  pointsy0[i],  thick2);
           glVertex3f ( pointsx0[i],  pointsy0[i], -thick2);
         }
+      polys += npoints;
       glEnd();
 
       /* outside edge */
@@ -624,6 +978,7 @@ make_gasket (logo_configuration *dc, int wire)
                 glVertex3f (xz, yz,  thick2);
               }
           }
+        polys += npoints;
       }
       glEnd();
     }
@@ -634,7 +989,7 @@ make_gasket (logo_configuration *dc, int wire)
     GLfloat th;
     npoints = 0;
 
-    th = 339.0 * d2r;
+    th = 338.0 * d2r;
     pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
     pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
     npoints++;
@@ -642,13 +997,12 @@ make_gasket (logo_configuration *dc, int wire)
     pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
     npoints++;
 
-    th = 343.0 * d2r;
+    th = 344.0 * d2r;
     pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
     pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
     npoints++;
     pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
     pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
-    npoints++;
 
     if (! wire)
       {
@@ -661,6 +1015,7 @@ make_gasket (logo_configuration *dc, int wire)
         glVertex3f (pointsx0[3], pointsy0[3], -thick2);
         glVertex3f (pointsx0[2], pointsy0[2], -thick2);
         glEnd();
+        polys++;
 
         /* back wall */
         glNormal3f (0, 0, 1);
@@ -671,6 +1026,7 @@ make_gasket (logo_configuration *dc, int wire)
         glVertex3f (pointsx0[3], pointsy0[3],  thick2);
         glVertex3f (pointsx0[2], pointsy0[2],  thick2);
         glEnd();
+        polys++;
       }
 
     /* top wall */
@@ -684,14 +1040,15 @@ make_gasket (logo_configuration *dc, int wire)
     glNormal3f (pointsx0[1], pointsy0[1], 0);
     glVertex3f (pointsx0[1], pointsy0[1], -thick2);
     glEnd();
+    polys++;
 
 
     /* Now make a donut.
      */
     {
-      int nsteps = 12;
-      GLfloat r0 = 0.026;
-      GLfloat r1 = 0.060;
+      int nsteps = (wire ? 12 : 64);
+      GLfloat r0 = 0.04;
+      GLfloat r1 = 0.070;
       GLfloat th, cth, sth;
 
       glPushMatrix ();
@@ -713,6 +1070,7 @@ make_gasket (logo_configuration *dc, int wire)
           pointsx1[npoints] = r1 * cth;
           pointsy1[npoints] = r1 * sth;
           npoints++;
+          polys++;
         }
 
       pointsx0[npoints] = pointsx0[0];
@@ -726,19 +1084,23 @@ make_gasket (logo_configuration *dc, int wire)
           glBegin (GL_LINE_LOOP);
           for (i = 0; i < npoints; i++)
             glVertex3f (pointsx0[i], pointsy0[i], -thick2);
+          polys += npoints;
           glEnd();
           glBegin (GL_LINE_LOOP);
           for (i = 0; i < npoints; i++)
             glVertex3f (pointsx0[i], pointsy0[i],  thick2);
+          polys += npoints;
           glEnd();
 # if 0
           glBegin (GL_LINE_LOOP);
           for (i = 0; i < npoints; i++)
             glVertex3f (pointsx1[i], pointsy1[i], -thick2);
+          polys += npoints;
           glEnd();
           glBegin (GL_LINE_LOOP);
           for (i = 0; i < npoints; i++)
             glVertex3f (pointsx1[i], pointsy1[i],  thick2);
+          polys += npoints;
           glEnd();
 # endif
         }
@@ -753,6 +1115,7 @@ make_gasket (logo_configuration *dc, int wire)
               glVertex3f (pointsx0[i], pointsy0[i], -thick2);
               glVertex3f (pointsx1[i], pointsy1[i], -thick2);
             }
+          polys += npoints;
           glEnd();
 
           /* bottom */
@@ -764,6 +1127,7 @@ make_gasket (logo_configuration *dc, int wire)
               glVertex3f (pointsx0[i], pointsy0[i],  thick2);
               glVertex3f (pointsx1[i], pointsy1[i],  thick2);
             }
+          polys += npoints;
           glEnd();
         }
 
@@ -776,6 +1140,7 @@ make_gasket (logo_configuration *dc, int wire)
           glVertex3f ( pointsx0[i],  pointsy0[i],  thick2);
           glVertex3f ( pointsx0[i],  pointsy0[i], -thick2);
         }
+      polys += npoints;
       glEnd();
 
       glPopMatrix();
@@ -786,11 +1151,11 @@ make_gasket (logo_configuration *dc, int wire)
   /* Attach the bottom-right dingus...
    */
   {
-    GLfloat w = 0.04;
-    GLfloat h = 0.17;
+    GLfloat w = 0.05;
+    GLfloat h = 0.19;
     GLfloat th;
 
-    glRotatef (50, 0, 0, 1);
+    glRotatef (49.5, 0, 0, 1);
     glScalef (dc->gasket_size, dc->gasket_size, 1);
     glTranslatef (0, (r0+r1)/2, 0);
 
@@ -811,15 +1176,19 @@ make_gasket (logo_configuration *dc, int wire)
         glNormal3f (-1, 0, 0);
         glVertex3f (-w/2, -h/2,  thick2); glVertex3f (-w/2,  h/2,  thick2);
         glVertex3f (-w/2,  h/2, -thick2); glVertex3f (-w/2, -h/2, -thick2);
+        polys++;
         glEnd();
       }
 
     npoints = 0;
-    for (th = 0; th < M_PI; th += (M_PI / 6))
+    for (th = (wire ? 0 : -0.1);
+         th <= M_PI + 0.1;
+         th += (M_PI / (wire ? 5 : 32)))
       {
         pointsx0[npoints] = w/2 * cos(th);
         pointsy0[npoints] = w/2 * sin(th);
         npoints++;
+        polys++;
       }
 
     /* front inside curve */
@@ -829,6 +1198,7 @@ make_gasket (logo_configuration *dc, int wire)
     if (! wire) glVertex3f (0, h/2, -thick2);
     for (i = 0; i < npoints; i++)
       glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
+    polys += npoints;
     glEnd();
 
     /* front outside curve */
@@ -837,6 +1207,7 @@ make_gasket (logo_configuration *dc, int wire)
     if (! wire) glVertex3f (0, -h/2, -thick2);
     for (i = 0; i < npoints; i++)
       glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
+    polys += npoints;
     glEnd();
 
     /* back inside curve */
@@ -846,6 +1217,7 @@ make_gasket (logo_configuration *dc, int wire)
     if (! wire) glVertex3f (0, h/2, thick2);
     for (i = 0; i < npoints; i++)
       glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
+    polys += npoints;
     glEnd();
 
     /* back outside curve */
@@ -854,6 +1226,7 @@ make_gasket (logo_configuration *dc, int wire)
     if (! wire) glVertex3f (0, -h/2, thick2);
     for (i = 0; i < npoints; i++)
       glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
+    polys += npoints;
     glEnd();
 
     /* inside curve */
@@ -865,6 +1238,7 @@ make_gasket (logo_configuration *dc, int wire)
         glVertex3f (pointsx0[i], h/2 + pointsy0[i],  thick2);
         glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
       }
+    polys += npoints;
     glEnd();
 
     /* outside curve */
@@ -876,6 +1250,7 @@ make_gasket (logo_configuration *dc, int wire)
         glVertex3f (pointsx0[i], -h/2 - pointsy0[i],  thick2);
         glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
       }
+    polys += npoints;
     glEnd();
   }
 
@@ -886,8 +1261,579 @@ make_gasket (logo_configuration *dc, int wire)
   free (normals);
 
   glPopMatrix();
+  return polys;
+}
+
+static int
+make_frame (logo_configuration *dc, int wire)
+{
+  int polys = 0;
+  int i, j;
+  GLfloat x[20], y[20];
+  GLfloat corner_cut = 0.5;
+
+  glPushMatrix();
+  glRotatef (90, 0, 1, 0);
+  glScalef (4 * dc->frame_size,
+            4 * dc->frame_size,
+            4 * dc->frame_size);
+
+  x[0] = -dc->frame_thickness;
+  x[1] = -dc->frame_thickness * corner_cut;
+  x[2] = 0;
+  x[3] = 0.5 - dc->triangle_size;
+  x[4] = 0.5;
+  x[5] = 0.5 + dc->triangle_size;
+  x[6] = 1;
+  x[7] = 1 + dc->frame_thickness * corner_cut;
+  x[8] = 1 + dc->frame_thickness;
+
+  y[0] = -dc->frame_thickness;
+  y[1] = -dc->frame_thickness * corner_cut;
+  y[2] = 0;
+  y[3] = dc->triangle_size;
+
+  /* front and back
+   */
+  glTranslatef (-0.5, -0.5, dc->frame_depth / 4);
+  if (! wire)
+    for (j = 0; j <= 1; j++)
+      {
+        if (j) glTranslatef (0, 0, -dc->frame_depth / 2);
+        glFrontFace (j ? GL_CCW : GL_CW);
+        for (i = 0; i < 4; i++)
+          {
+            glNormal3f (0, 0, (j ? -1 : 1));
+            glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
+            glVertex3f (x[0], y[1], 0); glVertex3f (x[0], y[2], 0);
+            glVertex3f (x[1], y[0], 0); glVertex3f (x[1], y[2], 0);
+            glVertex3f (x[3], y[0], 0); glVertex3f (x[3], y[2], 0);
+            glVertex3f (x[4], y[0], 0); glVertex3f (x[4], y[3], 0);
+            glVertex3f (x[5], y[0], 0); glVertex3f (x[5], y[2], 0); 
+            glVertex3f (x[7], y[0], 0); glVertex3f (x[7], y[2], 0);
+            glVertex3f (x[8], y[1], 0); glVertex3f (x[8], y[2], 0);
+            polys += 6;
+            glEnd ();
+            glTranslatef (0.5, 0.5, 0);
+            glRotatef (90, 0, 0, 1);
+            glTranslatef (-0.5, -0.5, 0);
+          }
+      }
+
+  /* ledges
+   */
+  glFrontFace (GL_CCW);
+  for (i = 0; i < 4; i++)
+    {
+      glNormal3f (0, 1, 0);
+      glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
+      glVertex3f (x[2], y[2], 0); glVertex3f (x[2], y[2], dc->frame_depth/2); 
+      glVertex3f (x[3], y[2], 0); glVertex3f (x[3], y[2], dc->frame_depth/2); 
+      glVertex3f (x[4], y[3], 0); glVertex3f (x[4], y[3], dc->frame_depth/2); 
+      glVertex3f (x[5], y[2], 0); glVertex3f (x[5], y[2], dc->frame_depth/2); 
+      glVertex3f (x[6], y[2], 0); glVertex3f (x[6], y[2], dc->frame_depth/2); 
+      polys += 4;
+      glEnd ();
+
+      glNormal3f (0, -1, 0);
+      glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
+      glVertex3f (x[7], y[0], 0); 
+      glVertex3f (x[7], y[0], dc->frame_depth/2); 
+      glVertex3f (x[1], y[0], dc->frame_depth/2); 
+      glVertex3f (x[1], y[0], 0); 
+      polys++;
+      glEnd ();
+
+      glNormal3f (1, -1, 0);
+      glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
+      glVertex3f (x[8], y[1], 0); 
+      glVertex3f (x[8], y[1], dc->frame_depth/2); 
+      glVertex3f (x[7], y[0], dc->frame_depth/2); 
+      glVertex3f (x[7], y[0], 0); 
+      polys++;
+      glEnd ();
+
+      if (wire) 
+        {
+          glNormal3f (0, 1, 0);
+          for (j = 0; j <= 1; j++)
+            {
+              glBegin (GL_LINE_STRIP);
+              glVertex3f (x[2], y[2], j*dc->frame_depth/2);
+              glVertex3f (x[3], y[2], j*dc->frame_depth/2);
+              glVertex3f (x[4], y[3], j*dc->frame_depth/2);
+              glVertex3f (x[5], y[2], j*dc->frame_depth/2);
+              glVertex3f (x[6], y[2], j*dc->frame_depth/2);
+              polys += 4;
+              glEnd ();
+            }
+        }
+
+      glTranslatef (0.5, 0.5, 0);
+      glRotatef (90, 0, 0, 1);
+      glTranslatef (-0.5, -0.5, 0);
+    }
+
+  glPopMatrix();
+  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;
 }
 
+
+
 \f
 /* Window management, etc
  */
@@ -945,7 +1891,10 @@ init_logo (ModeInfo *mi)
   logo_configuration *dc;
   int do_gasket = get_boolean_resource(mi->dpy, "doGasket", "Boolean");
   int do_helix = get_boolean_resource(mi->dpy, "doHelix", "Boolean");
-  int do_ladder = do_helix && get_boolean_resource(mi->dpy, "doLadder", "Boolean");
+  int do_ladder = (do_helix && 
+                   get_boolean_resource(mi->dpy, "doLadder", "Boolean"));
+  int do_frame = get_boolean_resource(mi->dpy, "doFrame", "Boolean");
+  GLfloat helix_rot = 147.0;
 
   if (!do_gasket && !do_helix)
     {
@@ -970,21 +1919,48 @@ init_logo (ModeInfo *mi)
   }
 
   dc->wall_facets    = get_integer_resource(mi->dpy, "wallFacets",  "Integer");
-  dc->tube_facets    = get_integer_resource(mi->dpy, "tubeFacets",  "Integer");
+  dc->bar_facets     = get_integer_resource(mi->dpy, "barFacets",   "Integer");
   dc->clockwise      = get_boolean_resource(mi->dpy, "clockwise",   "Boolean");
   dc->turns          = get_float_resource(mi->dpy, "turns",         "Float");
   dc->turn_spacing   = get_float_resource(mi->dpy, "turnSpacing",   "Float");
   dc->bar_spacing    = get_float_resource(mi->dpy, "barSpacing",    "Float");
   dc->wall_height    = get_float_resource(mi->dpy, "wallHeight",    "Float");
   dc->wall_thickness = get_float_resource(mi->dpy, "wallThickness", "Float");
-  dc->tube_thickness = get_float_resource(mi->dpy, "tubeThickness", "Float");
+  dc->bar_thickness  = get_float_resource(mi->dpy, "barThickness",  "Float");
   dc->wall_taper     = get_float_resource(mi->dpy, "wallTaper",     "Float");
 
-  dc->gasket_size      = get_float_resource(mi->dpy, "gasketSize",      "Float");
-  dc->gasket_depth     = get_float_resource(mi->dpy, "gasketDepth",     "Float");
-  dc->gasket_thickness = get_float_resource(mi->dpy, "gasketThickness", "Float");
+  dc->gasket_size      = get_float_resource(mi->dpy,"gasketSize",     "Float");
+  dc->gasket_depth     = get_float_resource(mi->dpy,"gasketDepth",    "Float");
+  dc->gasket_thickness = get_float_resource(mi->dpy,"gasketThickness","Float");
 
-  dc->speed          = get_float_resource(mi->dpy, "speed",         "Float");
+  dc->frame_size      = get_float_resource(mi->dpy, "frameSize",      "Float");
+  dc->frame_depth     = get_float_resource(mi->dpy, "frameDepth",     "Float");
+  dc->frame_thickness = get_float_resource(mi->dpy, "frameThickness", "Float");
+  dc->triangle_size   = get_float_resource(mi->dpy, "triangleSize",   "Float");
+
+  dc->speed          = get_float_resource(mi->dpy,   "speed",         "Float");
+
+  {
+    char *s = get_string_resource (MI_DISPLAY (mi), "mode", "String");
+    if (!s || !*s || !strcasecmp (s, "helix"))
+      dc->mode = HELIX;
+    else if (!strcasecmp (s, "pizza"))
+      dc->mode = PIZZA;
+    else if (!strcasecmp (s, "both"))
+      dc->mode = BOTH;
+    else
+      {
+        fprintf (stderr, "%s: mode must be helix, pizza or both, not \"%s\"\n", 
+                 progname, s);
+        exit (1);
+      }
+    if (s) free (s);
+
+    dc->anim_state = (dc->mode == BOTH
+                      ? ((random() & 1) ? HELIX : PIZZA)
+                      : dc->mode);
+    dc->anim_ratio = 0;
+  }
 
   {
     XColor xcolor;
@@ -1011,13 +1987,25 @@ init_logo (ModeInfo *mi)
 
   dc->trackball = gltrackball_init ();
 
-  dc->gasket_spinnery.probability = 0.1;
   dc->gasket_spinnerx.probability = 0.1;
+  dc->gasket_spinnery.probability = 0.1;
   dc->gasket_spinnerz.probability = 1.0;
+
   dc->helix_spinnerz.probability  = 0.6;
+
+  dc->pizza_spinnerz.probability  = 0.6;
+  dc->pizza_spinnery.probability  = 0.6;
+
   dc->scene_spinnerx.probability  = 0.1;
   dc->scene_spinnery.probability  = 0.0;
 
+  dc->frame_spinner.probability   = 5.0;
+
+  /* start the frame off-screen */
+  dc->frame_spinner.spinning_p = True;
+  dc->frame_spinner.position = 0.3;
+  dc->frame_spinner.speed = 0.001;
+
   if (dc->speed > 0)    /* start off with the gasket in motion */
     {
       dc->gasket_spinnerz.spinning_p = True;
@@ -1026,47 +2014,100 @@ init_logo (ModeInfo *mi)
                                    * dc->speed);
     }
 
+# ifdef DXF_OUTPUT_HACK
+  {
+    dc->frame_depth = dc->gasket_depth;
+    dxf_layer = 1;
+    dxf_color = 3;
+    dxf_start();
+    glPushMatrix();
+    glRotatef(90, 1, 0, 0);
+    glRotatef(90, 0, 0, 1);
+    make_pizza (dc, 0, 0);
+
+    glPushMatrix();
+    glRotatef(helix_rot, 0, 0, 1);
+    make_ladder (dc, 0, 0);
+    make_helix  (dc, 0, 0);
+    glRotatef (180, 0, 0, 1);
+    make_helix  (dc, 0, 0);
+    glPopMatrix();
+
+    dxf_layer++;
+    make_gasket (dc, 0);
+    dxf_layer++;
+    make_frame (dc, 0);
+    glPopMatrix();
+    dxf_end();
+  }
+# endif
+
   glPushMatrix();
   dc->helix_list = glGenLists (1);
   glNewList (dc->helix_list, GL_COMPILE);
-  glRotatef(126, 0, 0, 1);
-  if (do_ladder) make_ladder (dc, 0, 0);
-  if (do_helix)  make_helix  (dc, 0, 0);
+  glRotatef(helix_rot, 0, 0, 1);
+  if (do_ladder) dc->polys[0] += make_ladder (dc, 0, 0);
+  if (do_helix)  dc->polys[0] += make_helix  (dc, 0, 0);
   glRotatef(180, 0, 0, 1);
-  if (do_helix)  make_helix  (dc, 0, 0);
+  if (do_helix)  dc->polys[0] += make_helix  (dc, 0, 0);
   glEndList ();
   glPopMatrix();
 
   glPushMatrix();
   dc->helix_list_wire = glGenLists (1);
   glNewList (dc->helix_list_wire, GL_COMPILE);
-  /* glRotatef(126, 0, 0, 1); wtf? */
-  if (do_ladder) make_ladder (dc, 1, 1);
-  if (do_helix)  make_helix  (dc, 1, 1);
+/*  glRotatef(helix_rot, 0, 0, 1); wtf? */
+  if (do_ladder) dc->polys[1] += make_ladder (dc, 1, 1);
+  if (do_helix)  dc->polys[1] += make_helix  (dc, 1, 1);
   glRotatef(180, 0, 0, 1);
-  if (do_helix)  make_helix  (dc, 1, 1);
+  if (do_helix)  dc->polys[1] += make_helix  (dc, 1, 1);
   glEndList ();
   glPopMatrix();
 
   glPushMatrix();
   dc->helix_list_facetted = glGenLists (1);
   glNewList (dc->helix_list_facetted, GL_COMPILE);
-  glRotatef(126, 0, 0, 1);
-  if (do_ladder) make_ladder (dc, 1, 0);
-  if (do_helix)  make_helix  (dc, 1, 0);
+  glRotatef(helix_rot, 0, 0, 1);
+  if (do_ladder) dc->polys[2] += make_ladder (dc, 1, 0);
+  if (do_helix)  dc->polys[2] += make_helix  (dc, 1, 0);
   glRotatef(180, 0, 0, 1);
-  if (do_helix)  make_helix  (dc, 1, 0);
+  if (do_helix)  dc->polys[2] += make_helix  (dc, 1, 0);
   glEndList ();
   glPopMatrix();
 
+  dc->pizza_list = glGenLists (1);
+  glNewList (dc->pizza_list, GL_COMPILE);
+  if (do_frame) dc->polys[5] += make_pizza (dc, 0, 0);
+  glEndList ();
+
+  dc->pizza_list_wire = glGenLists (1);
+  glNewList (dc->pizza_list_wire, GL_COMPILE);
+  if (do_frame) dc->polys[6] += make_pizza (dc, 1, 1);
+  glEndList ();
+
+  dc->pizza_list_facetted = glGenLists (1);
+  glNewList (dc->pizza_list_facetted, GL_COMPILE);
+  if (do_frame) dc->polys[6] += make_pizza (dc, 1, 0);
+  glEndList ();
+
   dc->gasket_list = glGenLists (1);
   glNewList (dc->gasket_list, GL_COMPILE);
-  if (do_gasket) make_gasket (dc, 0);
+  if (do_gasket) dc->polys[3] += make_gasket (dc, 0);
   glEndList ();
 
   dc->gasket_list_wire = glGenLists (1);
   glNewList (dc->gasket_list_wire, GL_COMPILE);
-  if (do_gasket) make_gasket (dc, 1);
+  if (do_gasket) dc->polys[4] += make_gasket (dc, 1);
+  glEndList ();
+
+  dc->frame_list = glGenLists (1);
+  glNewList (dc->frame_list, GL_COMPILE);
+  if (do_frame) dc->polys[5] += make_frame (dc, 0);
+  glEndList ();
+
+  dc->frame_list_wire = glGenLists (1);
+  glNewList (dc->frame_list_wire, GL_COMPILE);
+  if (do_frame) dc->polys[6] += make_frame (dc, 1);
   glEndList ();
 
   /* When drawing both solid and wireframe objects,
@@ -1175,13 +2216,16 @@ draw_logo (ModeInfo *mi)
   GLfloat gcolor[4];
   GLfloat specular[]  = {0.8, 0.8, 0.8, 1.0};
   GLfloat shininess   = 50.0;
+  Bool pizza_p;
 
   if (!dc->glx_context)
     return;
 
+  mi->polygon_count = 0;
   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(dc->glx_context));
 
-  if (dc->wire_overlay == 0 &&
+  if (!wire &&
+      dc->wire_overlay == 0 &&
       (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
     dc->wire_overlay = ((random() % 200) +
                         (random() % 200) +
@@ -1191,31 +2235,162 @@ draw_logo (ModeInfo *mi)
   tick_spinner (mi, &dc->gasket_spinnery);
   tick_spinner (mi, &dc->gasket_spinnerz);
   tick_spinner (mi, &dc->helix_spinnerz);
+  tick_spinner (mi, &dc->pizza_spinnery);
+  tick_spinner (mi, &dc->pizza_spinnerz);
   tick_spinner (mi, &dc->scene_spinnerx);
   tick_spinner (mi, &dc->scene_spinnery);
+  tick_spinner (mi, &dc->frame_spinner);
   link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery);
 
+# ifdef LINEAR
+  {
+    static double i = 0.0;
+    dc->anim_state = HELIX;
+    dc->wire_overlay = 0;
+    dc->gasket_spinnerx.spinning_p = 0;
+    dc->gasket_spinnery.spinning_p = 0;
+    dc->gasket_spinnerz.spinning_p = 0;
+    dc->helix_spinnerz.spinning_p = 0;
+    dc->pizza_spinnery.spinning_p = 0;
+    dc->pizza_spinnerz.spinning_p = 0;
+    dc->scene_spinnerx.spinning_p = 0;
+    dc->scene_spinnery.spinning_p = 0;
+    dc->frame_spinner.spinning_p = 0;
+    dc->frame_spinner.position = 0.3;
+    dc->gasket_spinnerz.position = i;
+    dc->helix_spinnerz.position = i;
+    i += 0.005;
+    if (i > 1) i = 0;
+  }
+# endif /* LINEAR */
+
+  switch (dc->anim_state)
+    {
+    case HELIX:
+      if (dc->mode == BOTH &&
+          (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
+        dc->anim_state = HELIX_OUT;
+      break;
+
+    case HELIX_OUT:
+      dc->anim_ratio += 0.1 * dc->speed;
+      if (dc->anim_ratio >= 1.0)
+        {
+          dc->anim_ratio = 0.0;
+          dc->anim_state = PIZZA_IN;
+        }
+      break;
+
+    case PIZZA_IN:
+      dc->anim_ratio += 0.1 * dc->speed;
+      if (dc->anim_ratio >= 1.0)
+        {
+          dc->anim_ratio = 0.0;
+          dc->anim_state = PIZZA;
+        }
+      break;
+
+    case PIZZA:
+      if (dc->mode == BOTH &&
+          (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
+        dc->anim_state = PIZZA_OUT;
+      break;
+
+    case PIZZA_OUT:
+      dc->anim_ratio += 0.1 * dc->speed;
+      if (dc->anim_ratio >= 1.0)
+        {
+          dc->anim_ratio = 0.0;
+          dc->anim_state = HELIX_IN;
+        }
+      break;
+
+    case HELIX_IN:
+      dc->anim_ratio += 0.1 * dc->speed;
+      if (dc->anim_ratio >= 1.0)
+        {
+          dc->anim_ratio = 0.0;
+          dc->anim_state = HELIX;
+        }
+      break;
+
+    default:
+      abort();
+      break;
+    }
+
+  pizza_p = (dc->anim_state == PIZZA ||
+             dc->anim_state == PIZZA_IN ||
+             dc->anim_state == PIZZA_OUT);
+
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   glPushMatrix ();
+  glRotatef(current_device_rotation(), 0, 0, 1);
   {
-    glScalef(3.3, 3.3, 3.3);
+    GLfloat scale = 1.8;
+# ifdef LINEAR
+    scale = 3.85;
+# endif
+    glScalef(scale, scale, scale);
+
+    glColor3f(dc->color[0], dc->color[1], dc->color[2]);
+
+    /* Draw frame before trackball rotation */
+    {
+      GLfloat p = (dc->frame_spinner.position >= 0
+                   ? dc->frame_spinner.position
+                   : -dc->frame_spinner.position);
+      GLfloat size = (p > 0.5 ? 1-p : p);
+      scale = 1 + (size * 10);
+      glPushMatrix();
+      /* gltrackball_rotate (dc->trackball); */
+      glRotatef(90, 1, 0, 0);
+      glRotatef(90, 0, 0, 1);
+
+      glScalef (1, scale, scale);
+      if (wire)
+        {
+          glDisable (GL_LIGHTING);
+          glCallList (dc->frame_list_wire);
+          mi->polygon_count += dc->polys[6];
+        }
+      else if (dc->wire_overlay != 0)
+        {
+          glCallList (dc->frame_list);
+          glDisable (GL_LIGHTING);
+          glColor3fv (dc->color);
+          glCallList (dc->frame_list_wire);
+          mi->polygon_count += dc->polys[6];
+          if (!wire) glEnable (GL_LIGHTING);
+        }
+      else
+        {
+          glCallList (dc->frame_list);
+          mi->polygon_count += dc->polys[5];
+        }
+      glPopMatrix();
+    }
 
     gltrackball_rotate (dc->trackball);
 
     glRotatef(90, 1, 0, 0);
     glRotatef(90, 0, 0, 1);
 
-    glColor3f(dc->color[0], dc->color[1], dc->color[2]);
+# ifdef LINEAR
+#  define SINIFY(I) (I)
+# else
+#  define SINIFY(I) sin (M_PI/2 * (I))
+# endif
 
-    glRotatef (360 * sin (M_PI/2 * dc->scene_spinnerx.position), 0, 1, 0);
-    glRotatef (360 * sin (M_PI/2 * dc->scene_spinnery.position), 0, 0, 1);
+    glRotatef (360 * SINIFY (dc->scene_spinnerx.position), 0, 1, 0);
+    glRotatef (360 * SINIFY (dc->scene_spinnery.position), 0, 0, 1);
 
     glPushMatrix();
     {
-      glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnerx.position), 0, 1, 0);
-      glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnery.position), 0, 0, 1);
-      glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnerz.position), 1, 0, 0);
+      glRotatef (360 * SINIFY (dc->gasket_spinnerx.position), 0, 1, 0);
+      glRotatef (360 * SINIFY (dc->gasket_spinnery.position), 0, 0, 1);
+      glRotatef (360 * SINIFY (dc->gasket_spinnerz.position), 1, 0, 0);
 
       memcpy (gcolor, dc->color, sizeof (dc->color));
       if (dc->wire_overlay != 0)
@@ -1229,32 +2404,82 @@ draw_logo (ModeInfo *mi)
       glMaterialf  (GL_FRONT_AND_BACK, GL_SHININESS, shininess);
 
       if (wire)
-        glCallList (dc->gasket_list_wire);
+        {
+          glDisable (GL_LIGHTING);
+          glCallList (dc->gasket_list_wire);
+          mi->polygon_count += dc->polys[4];
+        }
       else if (dc->wire_overlay != 0)
         {
           glCallList (dc->gasket_list);
           glDisable (GL_LIGHTING);
+          glColor3fv (dc->color);
           glCallList (dc->gasket_list_wire);
+          mi->polygon_count += dc->polys[4];
           if (!wire) glEnable (GL_LIGHTING);
+          glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
         }
       else
-        glCallList (dc->gasket_list);
+        {
+          glCallList (dc->gasket_list);
+          mi->polygon_count += dc->polys[3];
+        }
     }
     glPopMatrix();
 
-    glRotatef (360 * sin (M_PI/2 * dc->helix_spinnerz.position), 0, 0, 1);
+    if (pizza_p)
+      {
+        glRotatef (360 * SINIFY (dc->pizza_spinnery.position), 1, 0, 0);
+        glRotatef (360 * SINIFY (dc->pizza_spinnerz.position), 0, 0, 1);
+      }
+    else
+      {
+        glRotatef (360 * SINIFY (dc->helix_spinnerz.position), 0, 0, 1);
+      }
+
+    scale = ((dc->anim_state == PIZZA_IN || dc->anim_state == HELIX_IN)
+             ? dc->anim_ratio
+             : ((dc->anim_state == PIZZA_OUT || dc->anim_state == HELIX_OUT)
+                ? 1.0 - dc->anim_ratio
+                : 1.0));
+    if (scale <= 0) scale = 0.001;
+    glScalef (scale, scale, scale);
 
     if (wire)
-      glCallList (dc->helix_list_wire);
+      {
+        glDisable (GL_LIGHTING);
+        if (pizza_p)
+          glCallList (dc->pizza_list_wire);
+        else
+          glCallList (dc->helix_list_wire);
+        mi->polygon_count += dc->polys[1];
+      }
     else if (dc->wire_overlay != 0)
       {
-        glCallList (dc->helix_list_facetted);
+        if (pizza_p)
+          glCallList (dc->pizza_list_facetted);
+        else
+          glCallList (dc->helix_list_facetted);
+
         glDisable (GL_LIGHTING);
-        glCallList (dc->helix_list_wire);
+        glColor3fv (dc->color);
+
+        if (pizza_p)
+          glCallList (dc->pizza_list_wire);
+        else
+          glCallList (dc->helix_list_wire);
+
+        mi->polygon_count += dc->polys[2];
         if (!wire) glEnable (GL_LIGHTING);
       }
     else
-      glCallList (dc->helix_list);
+      {
+        if (pizza_p)
+          glCallList (dc->pizza_list);
+        else
+          glCallList (dc->helix_list);
+        mi->polygon_count += dc->polys[0];
+      }
   }
   glPopMatrix();
 
@@ -1267,6 +2492,6 @@ draw_logo (ModeInfo *mi)
   glXSwapBuffers(dpy, window);
 }
 
-XSCREENSAVER_MODULE_2 ("DNAlogo", dnalogo, logo)
+XSCREENSAVER_MODULE_2 ("DNALogo", dnalogo, logo)
 
 #endif /* USE_GL */