http://www.jwz.org/xscreensaver/xscreensaver-5.13.tar.gz
[xscreensaver] / hacks / glx / dnalogo.c
index 0051ca5f635b19df440756c1175f30b5bed689e4..ec58540c37813726ab35cf1c1b09bb13808a62f1 100644 (file)
@@ -1,4 +1,15 @@
-/* DNA Logo, Copyright (c) 2001-2010 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
@@ -35,6 +46,7 @@
                        "*frameThickness:   0.03    \n" \
                        "*triangleSize:     0.045   \n" \
                        "*speed:            1.0     \n" \
+                       "*pizza:            False   \n" \
                        ".foreground:       #00AA00 \n" \
                        "*geometry:         =640x640\n" \
 
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
+#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"
@@ -62,6 +86,7 @@ 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];
@@ -89,10 +114,11 @@ typedef struct {
   GLfloat triangle_size;
 
   GLfloat speed;
+  Bool pizza_p;
 
   spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz;
   spinner scene_spinnerx,  scene_spinnery;
-  spinner helix_spinnerz;
+  spinner helix_spinnery, helix_spinnerz;
   spinner frame_spinner;
 
   trackball_state *trackball;
@@ -106,6 +132,7 @@ static logo_configuration *dcs = NULL;
 
 static XrmOptionDescRec opts[] = {
   { "-speed",  ".speed",  XrmoptionSepArg, 0 },
+  { "-pizza",  ".pizza",  XrmoptionNoArg, "True" },
 };
 
 ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
@@ -113,16 +140,14 @@ ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
 #define PROBABILITY_SCALE 600
 
 
-#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?
-                          */
+#ifdef DXF_OUTPUT_HACK
 
-# define glBegin    dxf_glBegin
-# define glVertex3f dxf_glVertex3f
-# define glEnd      dxf_glEnd
+# 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];
@@ -198,13 +223,13 @@ dxf_glVertex3f (GLfloat ox, GLfloat oy, GLfloat oz)
     fprintf (stdout, "33\n%.6f\n", dxf_quads[i+2]);
     i += 6;
 
-    dxf_quads[0] = dxf_quads[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];
+    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;
+    dxf_point = 2;                     /* leave those two points in queue */
     break;
 
   case GL_TRIANGLES:
@@ -232,13 +257,44 @@ dxf_glVertex3f (GLfloat ox, GLfloat oy, GLfloat oz)
     dxf_point = 0;
     if (dxf_type == GL_TRIANGLE_FAN)
       {
-        dxf_quads[3] = dxf_quads[6];
+        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;
+        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:
@@ -278,6 +334,14 @@ dxf_glVertex3f (GLfloat ox, GLfloat oy, GLfloat oz)
   }
 }
 
+
+static void
+dxf_glVertex3dv (const GLdouble *v)
+{
+  glVertex3f (v[0], v[1], v[2]);
+}
+
+
 static void
 dxf_glEnd(void)
 {
@@ -303,12 +367,41 @@ dxf_end (void)
   exit (0);
 }
 
-# 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
-# include "tube.c"
+
+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 */
 
@@ -1264,6 +1357,394 @@ make_frame (logo_configuration *dc, int wire)
   return polys;
 }
 
+\f
+/* Make some pizza.
+ */
+
+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;
+}
+
+
+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];
+}
+
+static void
+tess_begin_cb (GLenum which)
+{
+  glBegin(which);
+}
+
+static void
+tess_end_cb (void)
+{
+  glEnd();
+}
+
+
+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;
+  tess_out TO, *to = &TO;
+  GLUtesselator *tess = gluNewTess();
+  int endpoints;
+  int endedge1;
+
+  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);
+
+  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();
+
+  /* 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();
+    }
+
+  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);
+
+
+  /* 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();
+    }
+
+  gluDeleteTess (tess);
+  free (points);
+  free (holes);
+  free (to->points);
+
+  glPopMatrix();
+
+  return polys;
+}
+
+
 
 \f
 /* Window management, etc
@@ -1369,7 +1850,8 @@ init_logo (ModeInfo *mi)
   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");
+  dc->speed          = get_float_resource(mi->dpy,   "speed",         "Float");
+  dc->pizza_p        = get_boolean_resource(mi->dpy, "pizza",       "Boolean");
 
   {
     XColor xcolor;
@@ -1400,6 +1882,7 @@ init_logo (ModeInfo *mi)
   dc->gasket_spinnerx.probability = 0.1;
   dc->gasket_spinnerz.probability = 1.0;
   dc->helix_spinnerz.probability  = 0.6;
+  dc->helix_spinnery.probability  = (dc->pizza_p ? 0.6 : 0);
   dc->scene_spinnerx.probability  = 0.1;
   dc->scene_spinnery.probability  = 0.0;
   dc->frame_spinner.probability   = 5.0;
@@ -1426,13 +1909,18 @@ init_logo (ModeInfo *mi)
     glPushMatrix();
     glRotatef(90, 1, 0, 0);
     glRotatef(90, 0, 0, 1);
-    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();
+    if (dc->pizza_p)
+      make_pizza (dc, 0, 0);
+    else
+      {
+        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++;
@@ -1475,6 +1963,21 @@ init_logo (ModeInfo *mi)
   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) dc->polys[3] += make_gasket (dc, 0);
@@ -1617,6 +2120,7 @@ draw_logo (ModeInfo *mi)
   tick_spinner (mi, &dc->gasket_spinnerx);
   tick_spinner (mi, &dc->gasket_spinnery);
   tick_spinner (mi, &dc->gasket_spinnerz);
+  tick_spinner (mi, &dc->helix_spinnery);
   tick_spinner (mi, &dc->helix_spinnerz);
   tick_spinner (mi, &dc->scene_spinnerx);
   tick_spinner (mi, &dc->scene_spinnery);
@@ -1711,24 +2215,40 @@ draw_logo (ModeInfo *mi)
     }
     glPopMatrix();
 
+    glRotatef (360 * sin (M_PI/2 * dc->helix_spinnery.position), 1, 0, 0);
     glRotatef (360 * sin (M_PI/2 * dc->helix_spinnerz.position), 0, 0, 1);
 
     if (wire)
       {
-        glCallList (dc->helix_list_wire);
+        if (dc->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 (dc->pizza_p)
+          glCallList (dc->pizza_list_facetted);
+        else
+          glCallList (dc->helix_list_facetted);
+
         glDisable (GL_LIGHTING);
-        glCallList (dc->helix_list_wire);
+
+        if (dc->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 (dc->pizza_p)
+          glCallList (dc->pizza_list);
+        else
+          glCallList (dc->helix_list);
         mi->polygon_count += dc->polys[0];
       }
   }