1 /* DNA Logo, Copyright (c) 2001-2011 Jamie Zawinski <jwz@jwz.org>
5 * Restaurant -- Bar -- Nightclub -- Cafe -- Est. 1985.
11 * http://www.dnalounge.com/
12 * http://www.dnapizza.com/
14 * Permission to use, copy, modify, distribute, and sell this software and its
15 * documentation for any purpose is hereby granted without fee, provided that
16 * the above copyright notice appear in all copies and that both that
17 * copyright notice and this permission notice appear in supporting
18 * documentation. No representations are made about the suitability of this
19 * software for any purpose. It is provided "as is" without express or
23 #define DEFAULTS __extension__ \
25 "*showFPS: False \n" \
26 "*wireframe: False \n" \
27 "*doGasket: True \n" \
29 "*doLadder: True \n" \
31 "*wallFacets: 360 \n" \
33 "*clockwise: False \n" \
35 "*turnSpacing: 2.2 \n" \
36 "*barSpacing: 0.24 \n" \
37 "*wallHeight: 0.45 \n" \
38 "*wallThickness: 0.12 \n" \
39 "*barThickness: 0.058 \n" \
40 "*wallTaper: 0.95 \n" \
41 "*gasketSize: 1.88 \n" \
42 "*gasketDepth: 0.15 \n" \
43 "*gasketThickness: 0.4 \n" \
44 "*frameSize: 1.20 \n" \
45 "*frameDepth: 0.01 \n" \
46 "*frameThickness: 0.03 \n" \
47 "*triangleSize: 0.045 \n" \
50 ".foreground: #00AA00 \n" \
51 "*geometry: =640x640\n" \
53 # define refresh_logo 0
54 # define release_logo 0
56 #define countof(x) (sizeof((x))/sizeof((*x)))
58 #ifdef DXF_OUTPUT_HACK /* When this is defined, instead of rendering
59 to the screen, we write a DXF CAD file to stdout.
60 This is a kludge of shocking magnitude...
61 Maybe there's some other way to intercept all
62 glVertex3f calls than with a #define? */
63 # define unit_tube dxf_unit_tube
64 # define unit_cone dxf_unit_cone
65 # define tube_1 dxf_tube_1
66 # define tube dxf_tube
67 # define cone dxf_cone
68 #endif /* DXF_OUTPUT_HACK */
70 #include "xlockmore.h"
74 #include "gltrackball.h"
76 #ifdef USE_GL /* whole file */
79 HELIX_IN, HELIX, HELIX_OUT,
80 PIZZA_IN, PIZZA, PIZZA_OUT,
86 GLfloat position; /* 0.0 - 1.0 */
87 GLfloat speed; /* how far along the path (may be negative) */
88 GLfloat probability; /* relative likelyhood to start spinning */
92 GLXContext *glx_context;
94 GLuint helix_list, helix_list_wire, helix_list_facetted;
95 GLuint pizza_list, pizza_list_wire, pizza_list_facetted;
96 GLuint gasket_list, gasket_list_wire;
97 GLuint frame_list, frame_list_wire;
106 GLfloat turn_spacing;
109 GLfloat wall_thickness;
110 GLfloat bar_thickness;
114 GLfloat gasket_depth;
115 GLfloat gasket_thickness;
119 GLfloat frame_thickness;
120 GLfloat triangle_size;
124 glyph_mode anim_state;
127 spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz;
128 spinner scene_spinnerx, scene_spinnery;
129 spinner helix_spinnerz;
130 spinner pizza_spinnery, pizza_spinnerz;
131 spinner frame_spinner;
133 trackball_state *trackball;
136 int wire_overlay; /* frame countdown */
138 } logo_configuration;
140 static logo_configuration *dcs = NULL;
142 static XrmOptionDescRec opts[] = {
143 { "-speed", ".speed", XrmoptionSepArg, 0 },
144 { "-mode", ".mode", XrmoptionSepArg, 0 },
145 { "-pizza", ".mode", XrmoptionNoArg, "pizza" },
146 { "-helix", ".mode", XrmoptionNoArg, "helix" },
147 { "-both", ".mode", XrmoptionNoArg, "both" },
150 ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
152 #define PROBABILITY_SCALE 600
155 #ifdef DXF_OUTPUT_HACK
157 # define glBegin dxf_glBegin
158 # define glVertex3f dxf_glVertex3f
159 # define glVertex3dv dxf_glVertex3dv
160 # define glEnd dxf_glEnd
161 # define glVertexPointer dxf_glVertexPointer
162 # define glDrawArrays dxf_glDrawArrays
164 static int dxf_type, dxf_point, dxf_point_total, dxf_layer, dxf_color;
165 static GLfloat dxf_quads[4*4];
168 dxf_glBegin (int type)
176 dxf_glVertex3f (GLfloat ox, GLfloat oy, GLfloat oz)
182 /* Transform the point into modelview space. */
183 glGetFloatv (GL_MODELVIEW_MATRIX, m);
184 x = ox * m[0] + oy * m[4] + oz * m[8] + m[12];
185 y = ox * m[1] + oy * m[5] + oz * m[9] + m[13];
186 z = ox * m[2] + oy * m[6] + oz * m[10] + m[14];
188 dxf_quads[dxf_point*3+0] = x;
189 dxf_quads[dxf_point*3+1] = y;
190 dxf_quads[dxf_point*3+2] = z;
196 if (dxf_point < 4) return;
198 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
199 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
200 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
201 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
203 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
204 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
205 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
207 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
208 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
209 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
211 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]);
212 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
213 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
218 if (dxf_point < 4) return;
220 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
221 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
222 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
223 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
225 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
226 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
227 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
229 fprintf (stdout, "12\n%.6f\n", dxf_quads[i+3]); /* funky quad strip */
230 fprintf (stdout, "22\n%.6f\n", dxf_quads[i+4]); /* vert order: 1243. */
231 fprintf (stdout, "32\n%.6f\n", dxf_quads[i+5]);
233 fprintf (stdout, "13\n%.6f\n", dxf_quads[i]);
234 fprintf (stdout, "23\n%.6f\n", dxf_quads[i+1]);
235 fprintf (stdout, "33\n%.6f\n", dxf_quads[i+2]);
238 dxf_quads[0] = dxf_quads[6]; /* copy point 3 to pos 1 */
239 dxf_quads[1] = dxf_quads[7];
240 dxf_quads[2] = dxf_quads[8];
241 dxf_quads[3] = dxf_quads[9]; /* copy point 4 to pos 2 */
242 dxf_quads[4] = dxf_quads[10];
243 dxf_quads[5] = dxf_quads[11];
244 dxf_point = 2; /* leave those two points in queue */
248 case GL_TRIANGLE_FAN:
249 if (dxf_point < 3) return;
251 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
252 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
253 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
254 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
256 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
257 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
258 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
260 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
261 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
262 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
265 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
266 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
267 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
270 if (dxf_type == GL_TRIANGLE_FAN)
272 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to point 2 */
273 dxf_quads[4] = dxf_quads[7];
274 dxf_quads[5] = dxf_quads[8];
275 dxf_point = 2; /* leave two points in queue */
279 case GL_TRIANGLE_STRIP:
280 if (dxf_point < 3) return;
282 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
284 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
285 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
286 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
288 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
289 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
290 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
292 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
293 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
294 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
297 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
298 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
299 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
301 dxf_quads[0] = dxf_quads[3]; /* copy point 2 to pos 1 */
302 dxf_quads[1] = dxf_quads[4];
303 dxf_quads[2] = dxf_quads[5];
304 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to pos 2 */
305 dxf_quads[4] = dxf_quads[7];
306 dxf_quads[5] = dxf_quads[8];
307 dxf_point = 2; /* leave those two points in queue */
314 if (dxf_point_total == 1)
321 if (dxf_point < 2) return;
323 fprintf (stdout, "0\nLINE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
325 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
326 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
327 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
329 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
330 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
331 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
334 if (dxf_type != GL_LINES)
336 dxf_quads[0] = dxf_quads[3];
337 dxf_quads[1] = dxf_quads[4];
338 dxf_quads[2] = dxf_quads[5];
351 dxf_glVertex3dv (const GLdouble *v)
353 glVertex3f (v[0], v[1], v[2]);
360 if (dxf_type == GL_LINE_LOOP) /* close loop */
361 glVertex3f (dxf_quads[6], dxf_quads[7], dxf_quads[8]);
371 fprintf (stdout, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n");
372 fprintf (stdout, "0\nSECTION\n2\nENTITIES\n");
378 fprintf (stdout, "0\nENDSEC\n0\nEOF\n");
383 static const GLvoid *dxf_vp;
384 static GLsizei dxf_vp_size;
385 static GLsizei dxf_vp_stride;
388 dxf_glVertexPointer (GLint size, GLenum type, GLsizei stride,
389 const GLvoid *pointer)
391 if (type != GL_FLOAT) abort();
392 if (stride <= 0) abort();
395 dxf_vp_stride = stride;
399 dxf_glDrawArrays (GLenum mode, GLint first, GLsizei count)
402 unsigned char *a = (unsigned char *) dxf_vp;
404 for (i = first; i < first+count; i++)
406 GLfloat *fa = (GLfloat *) a;
407 dxf_glVertex3f (fa[0], fa[1], fa[2]);
414 # define XYZ tube_XYZ /* avoid conflict with normals.h */
415 # include "tube.c" /* Yes, I really am including a C file. */
418 #endif /* DXF_OUTPUT_HACK */
422 /* Calculate the angle (in degrees) between two vectors.
425 vector_angle (double ax, double ay, double az,
426 double bx, double by, double bz)
428 double La = sqrt (ax*ax + ay*ay + az*az);
429 double Lb = sqrt (bx*bx + by*by + bz*bz);
432 if (La == 0 || Lb == 0) return 0;
433 if (ax == bx && ay == by && az == bz) return 0;
435 /* dot product of two vectors is defined as:
436 La * Lb * cos(angle between vectors)
437 and is also defined as:
438 ax*bx + ay*by + az*bz
440 La * Lb * cos(angle) = ax*bx + ay*by + az*bz
441 cos(angle) = (ax*bx + ay*by + az*bz) / (La * Lb)
442 angle = acos ((ax*bx + ay*by + az*bz) / (La * Lb));
444 cc = (ax*bx + ay*by + az*bz) / (La * Lb);
445 if (cc > 1) cc = 1; /* avoid fp rounding error (1.000001 => sqrt error) */
448 return (angle * M_PI / 180);
456 make_helix (logo_configuration *dc, int facetted, int wire)
459 int wall_facets = dc->wall_facets / (facetted ? 10 : 1);
461 GLfloat max_th = M_PI * 2 * dc->turns;
462 GLfloat th_inc = M_PI * 2 / wall_facets;
464 GLfloat x1=0, y1=0, x2=0, y2=0;
465 GLfloat x1b=0, y1b=0, x2b=0, y2b=0;
468 GLfloat h1off=0, h2off=0;
469 GLfloat z_inc = dc->turn_spacing / wall_facets;
474 x1b = 1 - dc->wall_thickness;
477 z1 = -(dc->turn_spacing * dc->turns / 2);
479 h1 = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2);
480 h1off = (dc->wall_taper > 0 ? -dc->wall_height / 2 : 0);
483 z1 = -z1, z_inc = -z_inc, h1off = -h1off;
492 nx = cos (th + M_PI/2);
493 ny = sin (th + M_PI/2);
494 glNormal3f(nx, ny, 0);
495 glVertex3f( x1, y1, z1 - h1 + h1off);
496 glVertex3f( x1, y1, z1 + h1 + h1off);
497 glVertex3f(x1b, y1b, z1 + h1 + h1off);
498 glVertex3f(x1b, y1b, z1 - h1 + h1off);
503 while (th + th_inc <= max_th)
510 x2b = x2 * (1 - dc->wall_thickness);
511 y2b = y2 * (1 - dc->wall_thickness);
516 if (dc->wall_taper > 0)
519 if (th < dc->wall_taper)
521 h2 = dc->wall_height/2 * cos (M_PI / 2
522 * (1 - (th / dc->wall_taper)));
524 h2off = h2 - dc->wall_height/2;
526 h2off = dc->wall_height/2 - h2;
528 else if (th >= max_th - dc->wall_taper)
530 if (th + th_inc > max_th) /* edge case: always come to a point */
533 h2 = dc->wall_height/2 * cos (M_PI / 2
534 * (1 - ((max_th - th)
537 h2off = dc->wall_height/2 - h2;
539 h2off = h2 - dc->wall_height/2;
546 glBegin(wire ? GL_LINES : GL_QUADS);
547 glNormal3f(x1, y1, 0);
548 glVertex3f(x1, y1, z1 - h1 + h1off);
549 glVertex3f(x1, y1, z1 + h1 + h1off);
550 glNormal3f(x2, y2, 0);
551 glVertex3f(x2, y2, z2 + h2 + h2off);
552 glVertex3f(x2, y2, z2 - h2 + h2off);
559 glBegin(wire ? GL_LINES : GL_QUADS);
560 glNormal3f(-x1b, -y1b, 0);
561 glVertex3f( x1b, y1b, z1 - h1 + h1off);
562 glVertex3f( x1b, y1b, z1 + h1 + h1off);
563 glNormal3f(-x2b, -y2b, 0);
564 glVertex3f( x2b, y2b, z2 + h2 + h2off);
565 glVertex3f( x2b, y2b, z2 - h2 + h2off);
572 /* glNormal3f(0, 0, 1);*/
573 do_normal (x2, y2, z2 + h2 + h2off,
574 x2b, y2b, z2 + h2 + h2off,
575 x1b, y1b, z1 + h1 + h1off);
576 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
577 glVertex3f( x2, y2, z2 + h2 + h2off);
578 glVertex3f( x2b, y2b, z2 + h2 + h2off);
579 glVertex3f( x1b, y1b, z1 + h1 + h1off);
580 glVertex3f( x1, y1, z1 + h1 + h1off);
587 do_normal ( x1, y1, z1 - h1 + h1off,
588 x1b, y1b, z1 - h1 + h1off,
589 x2b, y2b, z2 - h2 + h2off);
590 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
591 glNormal3f(0, 0, -1);
592 glVertex3f( x1, y1, z1 - h1 + h1off);
593 glVertex3f( x1b, y1b, z1 - h1 + h1off);
594 glVertex3f( x2b, y2b, z2 - h2 + h2off);
595 glVertex3f( x2, y2, z2 - h2 + h2off);
615 nx = cos (th + M_PI/2);
616 ny = sin (th + M_PI/2);
617 glNormal3f(nx, ny, 0);
618 glVertex3f(x2, y2, z1 - h2 + h2off);
619 glVertex3f(x2, y2, z1 + h2 + h2off);
620 glVertex3f(x2b, y2b, z1 + h2 + h2off);
621 glVertex3f(x2b, y2b, z1 - h2 + h2off);
630 make_ladder (logo_configuration *dc, int facetted, int wire)
634 GLfloat max_th = dc->turns * M_PI * 2;
635 GLfloat max_z = dc->turns * dc->turn_spacing;
636 GLfloat z_inc = dc->bar_spacing;
637 GLfloat th_inc = M_PI * 2 * (dc->bar_spacing / dc->turn_spacing);
640 /* skip forward to center the bars in the helix... */
642 GLfloat usable_th = max_th - dc->wall_taper;
643 GLfloat usable_z = max_z / (max_th / usable_th);
644 int nbars = usable_z / dc->bar_spacing;
645 GLfloat used_z, pad_z, pad_ratio;
647 if (! (nbars & 1)) nbars--; /* always an odd number of bars */
649 used_z = (nbars - 1) * dc->bar_spacing;
650 pad_z = max_z - used_z;
651 pad_ratio = pad_z / max_z;
653 th = (max_th * pad_ratio/2);
654 z = -(max_z / 2) + (max_z * pad_ratio/2);
657 z = -z, z_inc = -z_inc;
660 for (i = 0; i < nbars; i++)
662 int facets = dc->bar_facets / (facetted ? 14 : 1);
663 if (facets <= 3) facets = 3;
664 x = cos (th) * (1 - dc->wall_thickness);
665 y = sin (th) * (1 - dc->wall_thickness);
666 polys += tube ( x, y, z,
668 dc->bar_thickness, 0, facets,
683 make_gasket (logo_configuration *dc, int wire)
691 GLfloat d2r = M_PI / 180;
693 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 2;
695 GLfloat *pointsx0, *pointsy0, *pointsx1, *pointsy1, *normals;
697 GLfloat r0 = 0.750; /* 395 */
698 GLfloat r1a = 0.825; /* bottom of wall below upper left hole */
699 GLfloat r1b = 0.867; /* center of upper left hole */
700 GLfloat r1c = 0.909; /* top of wall above hole */
701 GLfloat r1 = 0.916; /* 471 */
702 GLfloat r2 = 0.963; /* 490 */
703 GLfloat r3 = 0.960; /* 499 */
704 GLfloat r4 = 1.000; /* 507 */
705 GLfloat r5 = 1.080; /* 553 */
707 GLfloat ctrl_r[100], ctrl_th[100];
711 # ifdef DXF_OUTPUT_HACK
712 if (! wire) res *= 8;
715 # define POINT(r,th) \
716 ctrl_r [nctrls] = r, \
717 ctrl_th[nctrls] = (th * d2r), \
720 POINT (0.829, 0); /* top indentation, right half */
728 POINT (r4, 4.0); /* moving clockwise... */
749 POINT (r4, 316.8); /* upper left indentation */
750 POINT (0.990, 316.87);
751 POINT (0.880, 317.21);
752 POINT (0.872, 317.45);
753 POINT (0.869, 317.80);
754 POINT (0.867, 318.10);
756 POINT (0.867, 318.85);
757 POINT (0.869, 319.15);
758 POINT (0.872, 319.50);
759 POINT (0.880, 319.74);
760 POINT (0.990, 320.08);
765 POINT (r1a, 338.0); /* cut-out disc */
771 POINT (0.872, 356.05); /* top indentation, left half */
772 POINT (0.862, 356.19);
773 POINT (0.851, 356.70);
774 POINT (0.841, 357.35);
775 POINT (0.835, 358.19);
776 POINT (0.831, 359.15);
780 points_size = res + (nctrls * 2);
781 pointsx0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
782 pointsy0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
783 pointsx1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
784 pointsy1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
785 normals = (GLfloat *) malloc (points_size * sizeof(GLfloat) * 2);
788 for (i = 1; i < nctrls; i++)
790 GLfloat from_r = ctrl_r [i-1];
791 GLfloat from_th = ctrl_th[i-1];
792 GLfloat to_r = ctrl_r [i];
793 GLfloat to_th = ctrl_th[i];
795 GLfloat step = 2*M_PI / res;
796 int nsteps = 1 + ((to_th - from_th) / step);
799 for (j = 0; j < nsteps + (i == nctrls-1); j++)
801 GLfloat r = from_r + (j * (to_r - from_r) / nsteps);
802 GLfloat th = from_th + (j * (to_th - from_th) / nsteps);
804 GLfloat cth = cos(th) * dc->gasket_size;
805 GLfloat sth = sin(th) * dc->gasket_size;
807 pointsx0[npoints] = r0 * cth; /* inner ring */
808 pointsy0[npoints] = r0 * sth;
809 pointsx1[npoints] = r * cth; /* outer ring */
810 pointsy1[npoints] = r * sth;
813 if (npoints >= points_size) abort();
817 /* normals for the outer ring */
818 for (i = 1; i < npoints; i++)
829 n = calc_normal (a, b, c);
830 normals[(i-1)*2 ] = n.x;
831 normals[(i-1)*2+1] = n.y;
834 glRotatef(-90, 0, 1, 0);
835 glRotatef(180, 0, 0, 1);
840 for (z = -thick2; z <= thick2; z += thick2*2)
844 glBegin (GL_LINE_LOOP);
845 for (i = 0; i < npoints; i++)
846 glVertex3f (pointsx0[i], pointsy0[i], z);
851 glBegin (GL_LINE_LOOP);
852 for (i = 0; i < npoints; i++)
853 glVertex3f (pointsx1[i], pointsy1[i], z);
857 for (i = 1; i < npoints; i++)
859 glBegin (GL_LINE_STRIP);
860 glVertex3f (pointsx0[i-1], pointsy0[i-1], z);
861 glVertex3f (pointsx0[i ], pointsy0[i ], z);
862 glVertex3f (pointsx1[i ], pointsy1[i ], z);
863 glVertex3f (pointsx1[i-1], pointsy1[i-1], z);
871 for (i = 0; i < npoints; i++)
874 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
875 glVertex3f (pointsx0[i], pointsy0[i], thick2);
877 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
878 glVertex3f (pointsx1[i], pointsy1[i], thick2);
888 glNormal3f(0, 0, -1);
889 glBegin (GL_QUAD_STRIP);
890 for (i = 0; i < npoints; i++)
892 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
893 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
901 glBegin (GL_QUAD_STRIP);
902 for (i = 0; i < npoints; i++)
904 glVertex3f (pointsx0[i], pointsy0[i], thick2);
905 glVertex3f (pointsx1[i], pointsy1[i], thick2);
912 glBegin (GL_QUAD_STRIP);
913 for (i = 0; i < npoints; i++)
915 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
916 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
917 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
926 for (i = 0; i < npoints-1; i++)
928 int ia = (i == 0 ? npoints-2 : i-1);
929 int iz = (i == npoints-2 ? 0 : i+1);
930 GLfloat x = pointsx1[i];
931 GLfloat y = pointsy1[i];
932 GLfloat xz = pointsx1[iz];
933 GLfloat yz = pointsy1[iz];
935 GLfloat nxa = normals[ia*2]; /* normal of [i-1 - i] face */
936 GLfloat nya = normals[ia*2+1];
937 GLfloat nx = normals[i*2]; /* normal of [i - i+1] face */
938 GLfloat ny = normals[i*2+1];
939 GLfloat nxz = normals[iz*2]; /* normal of [i+1 - i+2] face */
940 GLfloat nyz = normals[iz*2+1];
942 GLfloat anglea = vector_angle (nx, ny, 0, nxa, nya, 0);
943 GLfloat anglez = vector_angle (nx, ny, 0, nxz, nyz, 0);
944 GLfloat pointy = 0.005;
948 glNormal3f (nx, ny, 0);
949 glVertex3f (x, y, thick2);
950 glVertex3f (x, y, -thick2);
954 glNormal3f ((nxa + nx) / 2, (nya + ny) / 2, 0);
955 glVertex3f (x, y, thick2);
956 glVertex3f (x, y, -thick2);
961 glNormal3f (nx, ny, 0);
962 glVertex3f (xz, yz, -thick2);
963 glVertex3f (xz, yz, thick2);
967 glNormal3f ((nx + nxz) / 2, (ny + nyz) / 2, 0);
968 glVertex3f (xz, yz, -thick2);
969 glVertex3f (xz, yz, thick2);
977 /* Fill in the upper left hole...
984 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
985 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
987 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
988 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
992 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
993 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
995 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
996 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
1001 glNormal3f (0, 0, -1);
1003 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1004 glVertex3f (pointsx0[0], pointsy0[0], -thick2);
1005 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1006 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1007 glVertex3f (pointsx0[2], pointsy0[2], -thick2);
1012 glNormal3f (0, 0, 1);
1013 glFrontFace(GL_CCW);
1014 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1015 glVertex3f (pointsx0[0], pointsy0[0], thick2);
1016 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1017 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1018 glVertex3f (pointsx0[2], pointsy0[2], thick2);
1025 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1026 glNormal3f (pointsx0[1], pointsy0[1], 0);
1027 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1028 glNormal3f (pointsx0[3], pointsy0[3], 0);
1029 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1030 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1031 glNormal3f (pointsx0[1], pointsy0[1], 0);
1032 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1037 /* Now make a donut.
1040 int nsteps = (wire ? 12 : 64);
1043 GLfloat th, cth, sth;
1047 th = ((339.0 + 343.0) / 2) * d2r;
1049 glTranslatef (r1b * cos(th) * dc->gasket_size,
1050 r1b * sin(th) * dc->gasket_size,
1054 for (i = 0; i < nsteps; i++)
1056 th = 2 * M_PI * i / nsteps;
1057 cth = cos (th) * dc->gasket_size;
1058 sth = sin (th) * dc->gasket_size;
1059 pointsx0[npoints] = r0 * cth;
1060 pointsy0[npoints] = r0 * sth;
1061 pointsx1[npoints] = r1 * cth;
1062 pointsy1[npoints] = r1 * sth;
1067 pointsx0[npoints] = pointsx0[0];
1068 pointsy0[npoints] = pointsy0[0];
1069 pointsx1[npoints] = pointsx1[0];
1070 pointsy1[npoints] = pointsy1[0];
1075 glBegin (GL_LINE_LOOP);
1076 for (i = 0; i < npoints; i++)
1077 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1080 glBegin (GL_LINE_LOOP);
1081 for (i = 0; i < npoints; i++)
1082 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1086 glBegin (GL_LINE_LOOP);
1087 for (i = 0; i < npoints; i++)
1088 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1091 glBegin (GL_LINE_LOOP);
1092 for (i = 0; i < npoints; i++)
1093 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1102 glNormal3f(0, 0, -1);
1103 glBegin (GL_QUAD_STRIP);
1104 for (i = 0; i < npoints; i++)
1106 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1107 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1113 glFrontFace(GL_CCW);
1114 glNormal3f(0, 0, 1);
1115 glBegin (GL_QUAD_STRIP);
1116 for (i = 0; i < npoints; i++)
1118 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1119 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1127 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1128 for (i = 0; i < npoints; i++)
1130 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
1131 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
1132 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
1142 /* Attach the bottom-right dingus...
1149 glRotatef (49.5, 0, 0, 1);
1150 glScalef (dc->gasket_size, dc->gasket_size, 1);
1151 glTranslatef (0, (r0+r1)/2, 0);
1156 glFrontFace(GL_CCW);
1157 glBegin (wire ? GL_LINE_STRIP : GL_QUADS);
1158 glNormal3f (0, 0, -1);
1159 glVertex3f (-w/2, -h/2, -thick2); glVertex3f (-w/2, h/2, -thick2);
1160 glVertex3f ( w/2, h/2, -thick2); glVertex3f ( w/2, -h/2, -thick2);
1161 glNormal3f (1, 0, 0);
1162 glVertex3f ( w/2, -h/2, -thick2); glVertex3f ( w/2, h/2, -thick2);
1163 glVertex3f ( w/2, h/2, thick2); glVertex3f ( w/2, -h/2, thick2);
1164 glNormal3f (0, 0, 1);
1165 glVertex3f ( w/2, -h/2, thick2); glVertex3f ( w/2, h/2, thick2);
1166 glVertex3f (-w/2, h/2, thick2); glVertex3f (-w/2, -h/2, thick2);
1167 glNormal3f (-1, 0, 0);
1168 glVertex3f (-w/2, -h/2, thick2); glVertex3f (-w/2, h/2, thick2);
1169 glVertex3f (-w/2, h/2, -thick2); glVertex3f (-w/2, -h/2, -thick2);
1175 for (th = (wire ? 0 : -0.1);
1177 th += (M_PI / (wire ? 5 : 32)))
1179 pointsx0[npoints] = w/2 * cos(th);
1180 pointsy0[npoints] = w/2 * sin(th);
1185 /* front inside curve */
1186 glNormal3f (0, 0, -1);
1188 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1189 if (! wire) glVertex3f (0, h/2, -thick2);
1190 for (i = 0; i < npoints; i++)
1191 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1195 /* front outside curve */
1196 glFrontFace(GL_CCW);
1197 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1198 if (! wire) glVertex3f (0, -h/2, -thick2);
1199 for (i = 0; i < npoints; i++)
1200 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1204 /* back inside curve */
1205 glNormal3f (0, 0, 1);
1206 glFrontFace(GL_CCW);
1207 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1208 if (! wire) glVertex3f (0, h/2, thick2);
1209 for (i = 0; i < npoints; i++)
1210 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1214 /* back outside curve */
1216 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1217 if (! wire) glVertex3f (0, -h/2, thick2);
1218 for (i = 0; i < npoints; i++)
1219 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1224 glFrontFace(GL_CCW);
1225 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1226 for (i = 0; i < npoints; i++)
1228 glNormal3f (pointsx0[i], pointsy0[i], 0);
1229 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1230 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1237 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1238 for (i = 0; i < npoints; i++)
1240 glNormal3f (pointsx0[i], -pointsy0[i], 0);
1241 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1242 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1259 make_frame (logo_configuration *dc, int wire)
1263 GLfloat x[20], y[20];
1264 GLfloat corner_cut = 0.5;
1267 glRotatef (90, 0, 1, 0);
1268 glScalef (4 * dc->frame_size,
1270 4 * dc->frame_size);
1272 x[0] = -dc->frame_thickness;
1273 x[1] = -dc->frame_thickness * corner_cut;
1275 x[3] = 0.5 - dc->triangle_size;
1277 x[5] = 0.5 + dc->triangle_size;
1279 x[7] = 1 + dc->frame_thickness * corner_cut;
1280 x[8] = 1 + dc->frame_thickness;
1282 y[0] = -dc->frame_thickness;
1283 y[1] = -dc->frame_thickness * corner_cut;
1285 y[3] = dc->triangle_size;
1289 glTranslatef (-0.5, -0.5, dc->frame_depth / 4);
1291 for (j = 0; j <= 1; j++)
1293 if (j) glTranslatef (0, 0, -dc->frame_depth / 2);
1294 glFrontFace (j ? GL_CCW : GL_CW);
1295 for (i = 0; i < 4; i++)
1297 glNormal3f (0, 0, (j ? -1 : 1));
1298 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1299 glVertex3f (x[0], y[1], 0); glVertex3f (x[0], y[2], 0);
1300 glVertex3f (x[1], y[0], 0); glVertex3f (x[1], y[2], 0);
1301 glVertex3f (x[3], y[0], 0); glVertex3f (x[3], y[2], 0);
1302 glVertex3f (x[4], y[0], 0); glVertex3f (x[4], y[3], 0);
1303 glVertex3f (x[5], y[0], 0); glVertex3f (x[5], y[2], 0);
1304 glVertex3f (x[7], y[0], 0); glVertex3f (x[7], y[2], 0);
1305 glVertex3f (x[8], y[1], 0); glVertex3f (x[8], y[2], 0);
1308 glTranslatef (0.5, 0.5, 0);
1309 glRotatef (90, 0, 0, 1);
1310 glTranslatef (-0.5, -0.5, 0);
1316 glFrontFace (GL_CCW);
1317 for (i = 0; i < 4; i++)
1319 glNormal3f (0, 1, 0);
1320 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1321 glVertex3f (x[2], y[2], 0); glVertex3f (x[2], y[2], dc->frame_depth/2);
1322 glVertex3f (x[3], y[2], 0); glVertex3f (x[3], y[2], dc->frame_depth/2);
1323 glVertex3f (x[4], y[3], 0); glVertex3f (x[4], y[3], dc->frame_depth/2);
1324 glVertex3f (x[5], y[2], 0); glVertex3f (x[5], y[2], dc->frame_depth/2);
1325 glVertex3f (x[6], y[2], 0); glVertex3f (x[6], y[2], dc->frame_depth/2);
1329 glNormal3f (0, -1, 0);
1330 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1331 glVertex3f (x[7], y[0], 0);
1332 glVertex3f (x[7], y[0], dc->frame_depth/2);
1333 glVertex3f (x[1], y[0], dc->frame_depth/2);
1334 glVertex3f (x[1], y[0], 0);
1338 glNormal3f (1, -1, 0);
1339 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1340 glVertex3f (x[8], y[1], 0);
1341 glVertex3f (x[8], y[1], dc->frame_depth/2);
1342 glVertex3f (x[7], y[0], dc->frame_depth/2);
1343 glVertex3f (x[7], y[0], 0);
1349 glNormal3f (0, 1, 0);
1350 for (j = 0; j <= 1; j++)
1352 glBegin (GL_LINE_STRIP);
1353 glVertex3f (x[2], y[2], j*dc->frame_depth/2);
1354 glVertex3f (x[3], y[2], j*dc->frame_depth/2);
1355 glVertex3f (x[4], y[3], j*dc->frame_depth/2);
1356 glVertex3f (x[5], y[2], j*dc->frame_depth/2);
1357 glVertex3f (x[6], y[2], j*dc->frame_depth/2);
1363 glTranslatef (0.5, 0.5, 0);
1364 glRotatef (90, 0, 0, 1);
1365 glTranslatef (-0.5, -0.5, 0);
1383 tess_error_cb (GLenum errorCode)
1385 fprintf (stderr, "%s: tesselation error: %s\n",
1386 progname, gluErrorString(errorCode));
1391 tess_combine_cb (GLdouble coords[3], GLdouble *d[4], GLfloat w[4],
1392 GLdouble **data_out)
1394 GLdouble *new = (GLdouble *) malloc (3 * sizeof(*new));
1404 tess_vertex_cb (void *vertex_data, void *closure)
1406 tess_out *to = (tess_out *) closure;
1407 GLdouble *v = (GLdouble *) vertex_data;
1408 to->points[to->i++] = v[0];
1409 to->points[to->i++] = v[1];
1410 to->points[to->i++] = v[2];
1415 tess_begin_cb (GLenum which)
1428 make_pizza (logo_configuration *dc, int facetted, int wire)
1432 int topfaces = (facetted ? 48 : 120);
1433 int discfaces = (facetted ? 12 : 120);
1434 int npoints = topfaces * 2 + 100;
1435 GLdouble *points = (GLdouble *) calloc (npoints * 3, sizeof(GLdouble));
1437 GLdouble *holes = (GLdouble *) calloc (topfaces*nholes*3, sizeof(GLdouble));
1439 GLfloat step = M_PI * 2 / 6 / topfaces;
1440 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 4;
1441 GLfloat th, x, y, s;
1443 tess_out TO, *to = &TO;
1444 GLUtesselator *tess = gluNewTess();
1448 to->points = (GLdouble *) calloc (topfaces * 20, sizeof(GLdouble));
1452 # ifndef _GLUfuncptr
1453 # define _GLUfuncptr void(*)(void)
1456 gluTessCallback(tess,GLU_TESS_BEGIN, (_GLUfuncptr)tess_begin_cb);
1457 gluTessCallback(tess,GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv);
1458 gluTessCallback(tess,GLU_TESS_END, (_GLUfuncptr)tess_end_cb);
1459 gluTessCallback(tess,GLU_TESS_COMBINE, (_GLUfuncptr)tess_combine_cb);
1460 gluTessCallback(tess,GLU_TESS_ERROR, (_GLUfuncptr)tess_error_cb);
1462 gluTessProperty (tess, GLU_TESS_BOUNDARY_ONLY, wire);
1463 gluTessProperty (tess,GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
1468 glRotatef (180, 0, 0, 1);
1470 glRotatef (90, 0, 1, 0);
1471 glTranslatef (-0.53, 0, 0);
1472 glRotatef (-30, 0, 0, 1);
1474 /* Compute the wedge */
1487 for (i = 0; i < countof(edge)/2; i++)
1489 points[j++] = edge[i*2+1];
1490 points[j++] = edge[i*2];
1496 s = 0.798; /* radius of end of slice, before crust gap */
1497 for (i = 0; i < topfaces; i++)
1499 points[j++] = cos(th) * s;
1500 points[j++] = sin(th) * s;
1517 for (i = 0; i < countof(edge)/2; i++)
1519 points[j++] = edge[i*2+1];
1520 points[j++] = edge[i*2];
1527 /* Draw the rim of the slice */
1528 glBegin (wire ? GL_LINES : GL_QUADS);
1531 for (i = (wire ? 0 : 1); i < endpoints; i++)
1533 GLdouble *p = points + (i*3);
1535 do_normal (p[0], p[1], -thick2,
1540 glVertex3f (x, y, -thick2);
1541 glVertex3f (x, y, thick2);
1543 glVertex3f (p[0], p[1], thick2);
1544 glVertex3f (p[0], p[1], -thick2);
1549 do_normal (points[0], points[1], -thick2,
1550 points[0], points[1], thick2,
1552 glVertex3f (x, y, -thick2);
1553 glVertex3f (x, y, thick2);
1554 glVertex3f (points[0], points[1], thick2);
1555 glVertex3f (points[0], points[1], -thick2);
1559 /* Compute the holes */
1560 step = M_PI * 2 / discfaces;
1561 for (k = 0; k < nholes; k++)
1563 GLdouble *p = holes + (discfaces * 3 * k);
1567 case 0: x = 0.34; y = 0.17; s = 0.05; break;
1568 case 1: x = 0.54; y = 0.17; s = 0.06; break;
1569 case 2: x = 0.55; y = 0.36; s = 0.06; break;
1570 default: abort(); break;
1572 for (i = 0; i < discfaces; i++)
1574 p[j++] = x + cos(M_PI*2 - th) * s;
1575 p[j++] = y + sin(M_PI*2 - th) * s;
1582 /* Draw the inside rim of the holes */
1583 for (k = 0; k < nholes; k++)
1585 GLdouble *p = holes + (discfaces * 3 * k);
1586 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1587 for (i = 0; i < discfaces; i++)
1589 GLdouble *p2 = p + (i*3);
1591 do_normal (p2[0], p2[1], -thick2,
1592 p2[0], p2[1], thick2,
1593 p2[-3], p2[-2], thick2);
1594 glVertex3f (p2[0], p2[1], -thick2);
1595 glVertex3f (p2[0], p2[1], thick2);
1598 glVertex3f (p[0], p[1], -thick2);
1599 glVertex3f (p[0], p[1], thick2);
1604 glTranslatef (0, 0, -thick2);
1605 for (y = 0; y <= 1; y++)
1607 if (y) glTranslatef (0, 0, thick2*2);
1609 /* A non-convex polygon */
1610 gluTessBeginPolygon (tess, to);
1612 glNormal3f (0, 0, (y > 0 ? 1 : -1));
1613 gluTessNormal (tess, 0, 0, (y > 0 ? 1 : -1));
1614 glFrontFace (GL_CCW);
1616 /* Tess the wedge */
1617 gluTessBeginContour (tess);
1618 for (i = 0; i < endpoints; i++)
1620 GLdouble *p = points + (i*3);
1621 gluTessVertex (tess, p, p);
1624 gluTessVertex (tess, points, points);
1625 gluTessEndContour (tess);
1627 /* Tess the holes */
1628 for (k = 0; k < nholes; k++)
1630 GLdouble *p = holes + (discfaces * 3 * k);
1631 gluTessBeginContour (tess);
1632 for (i = 0; i < discfaces; i++)
1634 GLdouble *p2 = p + (i*3);
1635 gluTessVertex (tess, p2, p2);
1638 gluTessEndContour (tess);
1641 gluTessEndPolygon (tess);
1643 glTranslatef (0, 0, -thick2);
1646 /* Compute the crust */
1648 s = 0.861; /* radius of inside of crust */
1649 step = M_PI * 2 / 6 / topfaces;
1652 for (i = 0; i < topfaces; i++)
1654 points[j++] = cos(th) * s;
1655 points[j++] = sin(th) * s;
1661 for (i = 0; i < topfaces; i++)
1663 points[j++] = cos(th) * s;
1664 points[j++] = sin(th) * s;
1669 /* Draw the rim of the crust */
1670 glFrontFace (GL_CCW);
1671 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1672 for (i = 0; i < topfaces * 2; i++)
1674 GLdouble *p = points + (i*3);
1675 if (i == 0 || i == (topfaces*2)-1)
1676 glNormal3f (0, -1, 0);
1677 else if (i == topfaces-1 || i == topfaces)
1678 glNormal3f (0, 1, 0);
1680 do_normal (p[-3], p[-2], thick2,
1682 p[0], p[1], -thick2);
1683 glVertex3f (p[0], p[1], -thick2);
1684 glVertex3f (p[0], p[1], thick2);
1687 glVertex3f (points[0], points[1], -thick2);
1688 glVertex3f (points[0], points[1], thick2);
1694 glBegin (GL_LINE_STRIP);
1695 for (i = 0; i < topfaces * 2; i++)
1697 GLdouble *p = points + (i*3);
1698 glVertex3f (p[0], p[1], -thick2);
1701 glVertex3f (points[0], points[1], -thick2);
1704 glBegin (GL_LINE_STRIP);
1705 for (i = 0; i < topfaces * 2; i++)
1707 GLdouble *p = points + (i*3);
1708 glVertex3f (p[0], p[1], thick2);
1711 glVertex3f (points[0], points[1], thick2);
1715 /* Draw the top of the crust */
1718 glFrontFace (GL_CW);
1719 glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP);
1720 glNormal3f (0, 0, -1);
1722 for (i = 0; i < topfaces; i++)
1724 int ii = topfaces + (topfaces - i - 1);
1725 GLdouble *p1 = points + (i*3);
1726 GLdouble *p2 = points + (ii*3);
1727 glVertex3f (p1[0], p1[1], -thick2);
1728 glVertex3f (p2[0], p2[1], -thick2);
1734 /* Draw the bottom of the crust */
1735 glFrontFace (GL_CCW);
1736 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1737 glNormal3f (0, 0, 1);
1738 for (i = 0; i < topfaces; i++)
1740 int ii = topfaces + (topfaces - i - 1);
1741 GLdouble *p1 = points + (i*3);
1742 GLdouble *p2 = points + (ii*3);
1743 glVertex3f (p1[0], p1[1], thick2);
1744 glVertex3f (p2[0], p2[1], thick2);
1751 gluDeleteTess (tess);
1764 /* Window management, etc
1767 reshape_logo (ModeInfo *mi, int width, int height)
1769 GLfloat h = (GLfloat) height / (GLfloat) width;
1771 glViewport (0, 0, (GLint) width, (GLint) height);
1773 glMatrixMode(GL_PROJECTION);
1775 gluPerspective (30.0, 1/h, 1.0, 100.0);
1777 glMatrixMode(GL_MODELVIEW);
1779 gluLookAt( 0.0, 0.0, 30.0,
1783 glClear(GL_COLOR_BUFFER_BIT);
1788 gl_init (ModeInfo *mi)
1790 /* logo_configuration *dc = &dcs[MI_SCREEN(mi)]; */
1791 int wire = MI_IS_WIREFRAME(mi);
1793 GLfloat position[] = {0, 0, 0, 0};
1794 GLfloat direction[] = {3, -1, -3};
1796 position[0] = -direction[0];
1797 position[1] = -direction[1];
1798 position[2] = -direction[2];
1802 glLightfv(GL_LIGHT0, GL_POSITION, position);
1803 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction);
1804 glShadeModel(GL_SMOOTH);
1805 glEnable(GL_NORMALIZE);
1806 glEnable(GL_CULL_FACE);
1807 glEnable(GL_LIGHTING);
1808 glEnable(GL_LIGHT0);
1809 glEnable(GL_DEPTH_TEST);
1815 init_logo (ModeInfo *mi)
1817 logo_configuration *dc;
1818 int do_gasket = get_boolean_resource(mi->dpy, "doGasket", "Boolean");
1819 int do_helix = get_boolean_resource(mi->dpy, "doHelix", "Boolean");
1820 int do_ladder = (do_helix &&
1821 get_boolean_resource(mi->dpy, "doLadder", "Boolean"));
1822 int do_frame = get_boolean_resource(mi->dpy, "doFrame", "Boolean");
1823 GLfloat helix_rot = 147.0;
1825 if (!do_gasket && !do_helix)
1827 fprintf (stderr, "%s: no helix or gasket?\n", progname);
1832 dcs = (logo_configuration *)
1833 calloc (MI_NUM_SCREENS(mi), sizeof (logo_configuration));
1835 fprintf(stderr, "%s: out of memory\n", progname);
1840 dc = &dcs[MI_SCREEN(mi)];
1842 if ((dc->glx_context = init_GL(mi)) != NULL) {
1844 reshape_logo (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1847 dc->wall_facets = get_integer_resource(mi->dpy, "wallFacets", "Integer");
1848 dc->bar_facets = get_integer_resource(mi->dpy, "barFacets", "Integer");
1849 dc->clockwise = get_boolean_resource(mi->dpy, "clockwise", "Boolean");
1850 dc->turns = get_float_resource(mi->dpy, "turns", "Float");
1851 dc->turn_spacing = get_float_resource(mi->dpy, "turnSpacing", "Float");
1852 dc->bar_spacing = get_float_resource(mi->dpy, "barSpacing", "Float");
1853 dc->wall_height = get_float_resource(mi->dpy, "wallHeight", "Float");
1854 dc->wall_thickness = get_float_resource(mi->dpy, "wallThickness", "Float");
1855 dc->bar_thickness = get_float_resource(mi->dpy, "barThickness", "Float");
1856 dc->wall_taper = get_float_resource(mi->dpy, "wallTaper", "Float");
1858 dc->gasket_size = get_float_resource(mi->dpy,"gasketSize", "Float");
1859 dc->gasket_depth = get_float_resource(mi->dpy,"gasketDepth", "Float");
1860 dc->gasket_thickness = get_float_resource(mi->dpy,"gasketThickness","Float");
1862 dc->frame_size = get_float_resource(mi->dpy, "frameSize", "Float");
1863 dc->frame_depth = get_float_resource(mi->dpy, "frameDepth", "Float");
1864 dc->frame_thickness = get_float_resource(mi->dpy, "frameThickness", "Float");
1865 dc->triangle_size = get_float_resource(mi->dpy, "triangleSize", "Float");
1867 dc->speed = get_float_resource(mi->dpy, "speed", "Float");
1870 char *s = get_string_resource (MI_DISPLAY (mi), "mode", "String");
1871 if (!s || !*s || !strcasecmp (s, "helix"))
1873 else if (!strcasecmp (s, "pizza"))
1875 else if (!strcasecmp (s, "both"))
1879 fprintf (stderr, "%s: mode must be helix, pizza or both, not \"%s\"\n",
1885 dc->anim_state = (dc->mode == BOTH
1886 ? ((random() & 1) ? HELIX : PIZZA)
1894 char *color_name = get_string_resource (mi->dpy, "foreground", "Foreground");
1896 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
1897 if (*s2 == ' ' || *s2 == '\t')
1902 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
1904 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
1908 dc->color[0] = xcolor.red / 65535.0;
1909 dc->color[1] = xcolor.green / 65535.0;
1910 dc->color[2] = xcolor.blue / 65535.0;
1914 dc->trackball = gltrackball_init ();
1916 dc->gasket_spinnerx.probability = 0.1;
1917 dc->gasket_spinnery.probability = 0.1;
1918 dc->gasket_spinnerz.probability = 1.0;
1920 dc->helix_spinnerz.probability = 0.6;
1922 dc->pizza_spinnerz.probability = 0.6;
1923 dc->pizza_spinnery.probability = 0.6;
1925 dc->scene_spinnerx.probability = 0.1;
1926 dc->scene_spinnery.probability = 0.0;
1928 dc->frame_spinner.probability = 5.0;
1930 /* start the frame off-screen */
1931 dc->frame_spinner.spinning_p = True;
1932 dc->frame_spinner.position = 0.3;
1933 dc->frame_spinner.speed = 0.001;
1935 if (dc->speed > 0) /* start off with the gasket in motion */
1937 dc->gasket_spinnerz.spinning_p = True;
1938 dc->gasket_spinnerz.speed = (0.002
1939 * ((random() & 1) ? 1 : -1)
1943 # ifdef DXF_OUTPUT_HACK
1945 dc->frame_depth = dc->gasket_depth;
1950 glRotatef(90, 1, 0, 0);
1951 glRotatef(90, 0, 0, 1);
1952 make_pizza (dc, 0, 0);
1955 glRotatef(helix_rot, 0, 0, 1);
1956 make_ladder (dc, 0, 0);
1957 make_helix (dc, 0, 0);
1958 glRotatef (180, 0, 0, 1);
1959 make_helix (dc, 0, 0);
1963 make_gasket (dc, 0);
1972 dc->helix_list = glGenLists (1);
1973 glNewList (dc->helix_list, GL_COMPILE);
1974 glRotatef(helix_rot, 0, 0, 1);
1975 if (do_ladder) dc->polys[0] += make_ladder (dc, 0, 0);
1976 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
1977 glRotatef(180, 0, 0, 1);
1978 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
1983 dc->helix_list_wire = glGenLists (1);
1984 glNewList (dc->helix_list_wire, GL_COMPILE);
1985 /* glRotatef(helix_rot, 0, 0, 1); wtf? */
1986 if (do_ladder) dc->polys[1] += make_ladder (dc, 1, 1);
1987 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
1988 glRotatef(180, 0, 0, 1);
1989 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
1994 dc->helix_list_facetted = glGenLists (1);
1995 glNewList (dc->helix_list_facetted, GL_COMPILE);
1996 glRotatef(helix_rot, 0, 0, 1);
1997 if (do_ladder) dc->polys[2] += make_ladder (dc, 1, 0);
1998 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
1999 glRotatef(180, 0, 0, 1);
2000 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
2004 dc->pizza_list = glGenLists (1);
2005 glNewList (dc->pizza_list, GL_COMPILE);
2006 if (do_frame) dc->polys[5] += make_pizza (dc, 0, 0);
2009 dc->pizza_list_wire = glGenLists (1);
2010 glNewList (dc->pizza_list_wire, GL_COMPILE);
2011 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 1);
2014 dc->pizza_list_facetted = glGenLists (1);
2015 glNewList (dc->pizza_list_facetted, GL_COMPILE);
2016 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 0);
2019 dc->gasket_list = glGenLists (1);
2020 glNewList (dc->gasket_list, GL_COMPILE);
2021 if (do_gasket) dc->polys[3] += make_gasket (dc, 0);
2024 dc->gasket_list_wire = glGenLists (1);
2025 glNewList (dc->gasket_list_wire, GL_COMPILE);
2026 if (do_gasket) dc->polys[4] += make_gasket (dc, 1);
2029 dc->frame_list = glGenLists (1);
2030 glNewList (dc->frame_list, GL_COMPILE);
2031 if (do_frame) dc->polys[5] += make_frame (dc, 0);
2034 dc->frame_list_wire = glGenLists (1);
2035 glNewList (dc->frame_list_wire, GL_COMPILE);
2036 if (do_frame) dc->polys[6] += make_frame (dc, 1);
2039 /* When drawing both solid and wireframe objects,
2040 make sure the wireframe actually shows up! */
2041 glEnable (GL_POLYGON_OFFSET_FILL);
2042 glPolygonOffset (1.0, 1.0);
2047 logo_handle_event (ModeInfo *mi, XEvent *event)
2049 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2051 if (event->xany.type == ButtonPress &&
2052 event->xbutton.button == Button1)
2054 dc->button_down_p = True;
2055 gltrackball_start (dc->trackball,
2056 event->xbutton.x, event->xbutton.y,
2057 MI_WIDTH (mi), MI_HEIGHT (mi));
2060 else if (event->xany.type == ButtonRelease &&
2061 event->xbutton.button == Button1)
2063 dc->button_down_p = False;
2066 else if (event->xany.type == ButtonPress &&
2067 (event->xbutton.button == Button4 ||
2068 event->xbutton.button == Button5 ||
2069 event->xbutton.button == Button6 ||
2070 event->xbutton.button == Button7))
2072 gltrackball_mousewheel (dc->trackball, event->xbutton.button, 10,
2073 !!event->xbutton.state);
2076 else if (event->xany.type == MotionNotify &&
2079 gltrackball_track (dc->trackball,
2080 event->xmotion.x, event->xmotion.y,
2081 MI_WIDTH (mi), MI_HEIGHT (mi));
2090 tick_spinner (ModeInfo *mi, spinner *s)
2092 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2094 if (dc->speed == 0) return;
2095 if (dc->button_down_p) return;
2099 s->position += s->speed;
2100 if (s->position >= 1.0 || s->position <= -1.0)
2104 s->spinning_p = False;
2107 else if (s->probability &&
2108 (random() % (int) (PROBABILITY_SCALE / s->probability)) == 0)
2111 s->spinning_p = True;
2114 s->speed = dc->speed * (frand(ss/3) + frand(ss/3) + frand(ss/3));
2115 } while (s->speed <= 0);
2117 s->speed = -s->speed;
2123 link_spinners (ModeInfo *mi, spinner *s0, spinner *s1)
2125 if (s0->spinning_p && !s1->spinning_p)
2127 GLfloat op = s1->probability;
2128 s1->probability = PROBABILITY_SCALE;
2129 tick_spinner (mi, s1);
2130 s1->probability = op;
2136 draw_logo (ModeInfo *mi)
2138 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2139 Display *dpy = MI_DISPLAY(mi);
2140 Window window = MI_WINDOW(mi);
2141 int wire = MI_IS_WIREFRAME(mi);
2143 GLfloat specular[] = {0.8, 0.8, 0.8, 1.0};
2144 GLfloat shininess = 50.0;
2147 if (!dc->glx_context)
2150 mi->polygon_count = 0;
2151 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(dc->glx_context));
2154 dc->wire_overlay == 0 &&
2155 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
2156 dc->wire_overlay = ((random() % 200) +
2160 tick_spinner (mi, &dc->gasket_spinnerx);
2161 tick_spinner (mi, &dc->gasket_spinnery);
2162 tick_spinner (mi, &dc->gasket_spinnerz);
2163 tick_spinner (mi, &dc->helix_spinnerz);
2164 tick_spinner (mi, &dc->pizza_spinnery);
2165 tick_spinner (mi, &dc->pizza_spinnerz);
2166 tick_spinner (mi, &dc->scene_spinnerx);
2167 tick_spinner (mi, &dc->scene_spinnery);
2168 tick_spinner (mi, &dc->frame_spinner);
2169 link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery);
2171 switch (dc->anim_state)
2174 if (dc->mode == BOTH &&
2175 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
2176 dc->anim_state = HELIX_OUT;
2180 dc->anim_ratio += 0.1 * dc->speed;
2181 if (dc->anim_ratio >= 1.0)
2183 dc->anim_ratio = 0.0;
2184 dc->anim_state = PIZZA_IN;
2189 dc->anim_ratio += 0.1 * dc->speed;
2190 if (dc->anim_ratio >= 1.0)
2192 dc->anim_ratio = 0.0;
2193 dc->anim_state = PIZZA;
2198 if (dc->mode == BOTH &&
2199 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
2200 dc->anim_state = PIZZA_OUT;
2204 dc->anim_ratio += 0.1 * dc->speed;
2205 if (dc->anim_ratio >= 1.0)
2207 dc->anim_ratio = 0.0;
2208 dc->anim_state = HELIX_IN;
2213 dc->anim_ratio += 0.1 * dc->speed;
2214 if (dc->anim_ratio >= 1.0)
2216 dc->anim_ratio = 0.0;
2217 dc->anim_state = HELIX;
2226 pizza_p = (dc->anim_state == PIZZA ||
2227 dc->anim_state == PIZZA_IN ||
2228 dc->anim_state == PIZZA_OUT);
2230 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2237 glColor3f(dc->color[0], dc->color[1], dc->color[2]);
2239 /* Draw frame before trackball rotation */
2241 GLfloat p = (dc->frame_spinner.position >= 0
2242 ? dc->frame_spinner.position
2243 : -dc->frame_spinner.position);
2244 GLfloat size = (p > 0.5 ? 1-p : p);
2245 scale = 1 + (size * 10);
2247 /* gltrackball_rotate (dc->trackball); */
2248 glRotatef(90, 1, 0, 0);
2249 glRotatef(90, 0, 0, 1);
2251 glScalef (1, scale, scale);
2254 glCallList (dc->frame_list_wire);
2255 mi->polygon_count += dc->polys[6];
2257 else if (dc->wire_overlay != 0)
2259 glCallList (dc->frame_list);
2260 glDisable (GL_LIGHTING);
2261 glCallList (dc->frame_list_wire);
2262 mi->polygon_count += dc->polys[6];
2263 if (!wire) glEnable (GL_LIGHTING);
2267 glCallList (dc->frame_list);
2268 mi->polygon_count += dc->polys[5];
2273 gltrackball_rotate (dc->trackball);
2275 glRotatef(90, 1, 0, 0);
2276 glRotatef(90, 0, 0, 1);
2278 glRotatef (360 * sin (M_PI/2 * dc->scene_spinnerx.position), 0, 1, 0);
2279 glRotatef (360 * sin (M_PI/2 * dc->scene_spinnery.position), 0, 0, 1);
2283 glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnerx.position), 0, 1, 0);
2284 glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnery.position), 0, 0, 1);
2285 glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnerz.position), 1, 0, 0);
2287 memcpy (gcolor, dc->color, sizeof (dc->color));
2288 if (dc->wire_overlay != 0)
2290 gcolor[0] = gcolor[1] = gcolor[2] = 0;
2291 specular[0] = specular[1] = specular[2] = 0;
2294 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
2295 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
2296 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shininess);
2300 glCallList (dc->gasket_list_wire);
2301 mi->polygon_count += dc->polys[4];
2303 else if (dc->wire_overlay != 0)
2305 glCallList (dc->gasket_list);
2306 glDisable (GL_LIGHTING);
2307 glCallList (dc->gasket_list_wire);
2308 mi->polygon_count += dc->polys[4];
2309 if (!wire) glEnable (GL_LIGHTING);
2313 glCallList (dc->gasket_list);
2314 mi->polygon_count += dc->polys[3];
2321 glRotatef (360 * sin (M_PI/2 * dc->pizza_spinnery.position), 1, 0, 0);
2322 glRotatef (360 * sin (M_PI/2 * dc->pizza_spinnerz.position), 0, 0, 1);
2326 glRotatef (360 * sin (M_PI/2 * dc->helix_spinnerz.position), 0, 0, 1);
2329 scale = ((dc->anim_state == PIZZA_IN || dc->anim_state == HELIX_IN)
2331 : ((dc->anim_state == PIZZA_OUT || dc->anim_state == HELIX_OUT)
2332 ? 1.0 - dc->anim_ratio
2334 if (scale <= 0) scale = 0.001;
2335 glScalef (scale, scale, scale);
2340 glCallList (dc->pizza_list_wire);
2342 glCallList (dc->helix_list_wire);
2343 mi->polygon_count += dc->polys[1];
2345 else if (dc->wire_overlay != 0)
2348 glCallList (dc->pizza_list_facetted);
2350 glCallList (dc->helix_list_facetted);
2352 glDisable (GL_LIGHTING);
2355 glCallList (dc->pizza_list_wire);
2357 glCallList (dc->helix_list_wire);
2359 mi->polygon_count += dc->polys[2];
2360 if (!wire) glEnable (GL_LIGHTING);
2365 glCallList (dc->pizza_list);
2367 glCallList (dc->helix_list);
2368 mi->polygon_count += dc->polys[0];
2373 if (dc->wire_overlay > 0)
2376 if (mi->fps_p) do_fps (mi);
2379 glXSwapBuffers(dpy, window);
2382 XSCREENSAVER_MODULE_2 ("DNAlogo", dnalogo, logo)