X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fdnalogo.c;h=ec58540c37813726ab35cf1c1b09bb13808a62f1;hp=0051ca5f635b19df440756c1175f30b5bed689e4;hb=5f9c47ca98dd43d8f59b7c27d3fde6edfde4fe21;hpb=50be9bb40dc60130c99ffa568e6677779904ff70 diff --git a/hacks/glx/dnalogo.c b/hacks/glx/dnalogo.c index 0051ca5f..ec58540c 100644 --- a/hacks/glx/dnalogo.c +++ b/hacks/glx/dnalogo.c @@ -1,4 +1,15 @@ -/* DNA Logo, Copyright (c) 2001-2010 Jamie Zawinski +/* DNA Logo, Copyright (c) 2001-2011 Jamie Zawinski + * + * 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" \ @@ -43,6 +55,18 @@ #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; } + +/* 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; +} + + /* 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]; } }