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 # include "dnapizza.h"
85 HELIX_IN, HELIX, HELIX_OUT,
86 PIZZA_IN, PIZZA, PIZZA_OUT,
92 GLfloat position; /* 0.0 - 1.0 */
93 GLfloat speed; /* how far along the path (may be negative) */
94 GLfloat probability; /* relative likelyhood to start spinning */
98 GLXContext *glx_context;
100 GLuint helix_list, helix_list_wire, helix_list_facetted;
101 GLuint pizza_list, pizza_list_wire, pizza_list_facetted;
102 GLuint gasket_list, gasket_list_wire;
103 GLuint frame_list, frame_list_wire;
112 GLfloat turn_spacing;
115 GLfloat wall_thickness;
116 GLfloat bar_thickness;
120 GLfloat gasket_depth;
121 GLfloat gasket_thickness;
125 GLfloat frame_thickness;
126 GLfloat triangle_size;
130 glyph_mode anim_state;
133 spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz;
134 spinner scene_spinnerx, scene_spinnery;
135 spinner helix_spinnerz;
136 spinner pizza_spinnery, pizza_spinnerz;
137 spinner frame_spinner;
139 trackball_state *trackball;
142 int wire_overlay; /* frame countdown */
144 } logo_configuration;
146 static logo_configuration *dcs = NULL;
148 static XrmOptionDescRec opts[] = {
149 { "-speed", ".speed", XrmoptionSepArg, 0 },
150 { "-mode", ".mode", XrmoptionSepArg, 0 },
151 { "-pizza", ".mode", XrmoptionNoArg, "pizza" },
152 { "-helix", ".mode", XrmoptionNoArg, "helix" },
153 { "-both", ".mode", XrmoptionNoArg, "both" },
156 ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
158 #define PROBABILITY_SCALE 600
161 #ifdef DXF_OUTPUT_HACK
163 # define glBegin dxf_glBegin
164 # define glVertex3f dxf_glVertex3f
165 # define glVertex3dv dxf_glVertex3dv
166 # define glEnd dxf_glEnd
167 # define glVertexPointer dxf_glVertexPointer
168 # define glDrawArrays dxf_glDrawArrays
170 static int dxf_type, dxf_point, dxf_point_total, dxf_layer, dxf_color;
171 static GLfloat dxf_quads[4*4];
174 dxf_glBegin (int type)
182 dxf_glVertex3f (GLfloat ox, GLfloat oy, GLfloat oz)
188 /* Transform the point into modelview space. */
189 glGetFloatv (GL_MODELVIEW_MATRIX, m);
190 x = ox * m[0] + oy * m[4] + oz * m[8] + m[12];
191 y = ox * m[1] + oy * m[5] + oz * m[9] + m[13];
192 z = ox * m[2] + oy * m[6] + oz * m[10] + m[14];
194 dxf_quads[dxf_point*3+0] = x;
195 dxf_quads[dxf_point*3+1] = y;
196 dxf_quads[dxf_point*3+2] = z;
202 if (dxf_point < 4) return;
204 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
205 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
206 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
207 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
209 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
210 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
211 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
213 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
214 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
215 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
217 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]);
218 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
219 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
224 if (dxf_point < 4) return;
226 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
227 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
228 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
229 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
231 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
232 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
233 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
235 fprintf (stdout, "12\n%.6f\n", dxf_quads[i+3]); /* funky quad strip */
236 fprintf (stdout, "22\n%.6f\n", dxf_quads[i+4]); /* vert order: 1243. */
237 fprintf (stdout, "32\n%.6f\n", dxf_quads[i+5]);
239 fprintf (stdout, "13\n%.6f\n", dxf_quads[i]);
240 fprintf (stdout, "23\n%.6f\n", dxf_quads[i+1]);
241 fprintf (stdout, "33\n%.6f\n", dxf_quads[i+2]);
244 dxf_quads[0] = dxf_quads[6]; /* copy point 3 to pos 1 */
245 dxf_quads[1] = dxf_quads[7];
246 dxf_quads[2] = dxf_quads[8];
247 dxf_quads[3] = dxf_quads[9]; /* copy point 4 to pos 2 */
248 dxf_quads[4] = dxf_quads[10];
249 dxf_quads[5] = dxf_quads[11];
250 dxf_point = 2; /* leave those two points in queue */
254 case GL_TRIANGLE_FAN:
255 if (dxf_point < 3) return;
257 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
258 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
259 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
260 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
262 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
263 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
264 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
266 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
267 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
268 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
271 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
272 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
273 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
276 if (dxf_type == GL_TRIANGLE_FAN)
278 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to point 2 */
279 dxf_quads[4] = dxf_quads[7];
280 dxf_quads[5] = dxf_quads[8];
281 dxf_point = 2; /* leave two points in queue */
285 case GL_TRIANGLE_STRIP:
286 if (dxf_point < 3) return;
288 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
290 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
291 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
292 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
294 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
295 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
296 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
298 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
299 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
300 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
303 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
304 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
305 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
307 dxf_quads[0] = dxf_quads[3]; /* copy point 2 to pos 1 */
308 dxf_quads[1] = dxf_quads[4];
309 dxf_quads[2] = dxf_quads[5];
310 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to pos 2 */
311 dxf_quads[4] = dxf_quads[7];
312 dxf_quads[5] = dxf_quads[8];
313 dxf_point = 2; /* leave those two points in queue */
320 if (dxf_point_total == 1)
327 if (dxf_point < 2) return;
329 fprintf (stdout, "0\nLINE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
331 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
332 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
333 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
335 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
336 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
337 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
340 if (dxf_type != GL_LINES)
342 dxf_quads[0] = dxf_quads[3];
343 dxf_quads[1] = dxf_quads[4];
344 dxf_quads[2] = dxf_quads[5];
357 dxf_glVertex3dv (const GLdouble *v)
359 glVertex3f (v[0], v[1], v[2]);
366 if (dxf_type == GL_LINE_LOOP) /* close loop */
367 glVertex3f (dxf_quads[6], dxf_quads[7], dxf_quads[8]);
377 fprintf (stdout, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n");
378 fprintf (stdout, "0\nSECTION\n2\nENTITIES\n");
384 fprintf (stdout, "0\nENDSEC\n0\nEOF\n");
389 static const GLvoid *dxf_vp;
390 static GLsizei dxf_vp_size;
391 static GLsizei dxf_vp_stride;
394 dxf_glVertexPointer (GLint size, GLenum type, GLsizei stride,
395 const GLvoid *pointer)
397 if (type != GL_FLOAT) abort();
398 if (stride <= 0) abort();
401 dxf_vp_stride = stride;
405 dxf_glDrawArrays (GLenum mode, GLint first, GLsizei count)
408 unsigned char *a = (unsigned char *) dxf_vp;
410 for (i = first; i < first+count; i++)
412 GLfloat *fa = (GLfloat *) a;
413 dxf_glVertex3f (fa[0], fa[1], fa[2]);
420 # define XYZ tube_XYZ /* avoid conflict with normals.h */
421 # include "tube.c" /* Yes, I really am including a C file. */
424 #endif /* DXF_OUTPUT_HACK */
428 /* Calculate the angle (in degrees) between two vectors.
431 vector_angle (double ax, double ay, double az,
432 double bx, double by, double bz)
434 double La = sqrt (ax*ax + ay*ay + az*az);
435 double Lb = sqrt (bx*bx + by*by + bz*bz);
438 if (La == 0 || Lb == 0) return 0;
439 if (ax == bx && ay == by && az == bz) return 0;
441 /* dot product of two vectors is defined as:
442 La * Lb * cos(angle between vectors)
443 and is also defined as:
444 ax*bx + ay*by + az*bz
446 La * Lb * cos(angle) = ax*bx + ay*by + az*bz
447 cos(angle) = (ax*bx + ay*by + az*bz) / (La * Lb)
448 angle = acos ((ax*bx + ay*by + az*bz) / (La * Lb));
450 cc = (ax*bx + ay*by + az*bz) / (La * Lb);
451 if (cc > 1) cc = 1; /* avoid fp rounding error (1.000001 => sqrt error) */
454 return (angle * M_PI / 180);
462 make_helix (logo_configuration *dc, int facetted, int wire)
465 int wall_facets = dc->wall_facets / (facetted ? 10 : 1);
467 GLfloat max_th = M_PI * 2 * dc->turns;
468 GLfloat th_inc = M_PI * 2 / wall_facets;
470 GLfloat x1=0, y1=0, x2=0, y2=0;
471 GLfloat x1b=0, y1b=0, x2b=0, y2b=0;
474 GLfloat h1off=0, h2off=0;
475 GLfloat z_inc = dc->turn_spacing / wall_facets;
480 x1b = 1 - dc->wall_thickness;
483 z1 = -(dc->turn_spacing * dc->turns / 2);
485 h1 = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2);
486 h1off = (dc->wall_taper > 0 ? -dc->wall_height / 2 : 0);
489 z1 = -z1, z_inc = -z_inc, h1off = -h1off;
498 nx = cos (th + M_PI/2);
499 ny = sin (th + M_PI/2);
500 glNormal3f(nx, ny, 0);
501 glVertex3f( x1, y1, z1 - h1 + h1off);
502 glVertex3f( x1, y1, z1 + h1 + h1off);
503 glVertex3f(x1b, y1b, z1 + h1 + h1off);
504 glVertex3f(x1b, y1b, z1 - h1 + h1off);
509 while (th + th_inc <= max_th)
516 x2b = x2 * (1 - dc->wall_thickness);
517 y2b = y2 * (1 - dc->wall_thickness);
522 if (dc->wall_taper > 0)
525 if (th < dc->wall_taper)
527 h2 = dc->wall_height/2 * cos (M_PI / 2
528 * (1 - (th / dc->wall_taper)));
530 h2off = h2 - dc->wall_height/2;
532 h2off = dc->wall_height/2 - h2;
534 else if (th >= max_th - dc->wall_taper)
536 if (th + th_inc > max_th) /* edge case: always come to a point */
539 h2 = dc->wall_height/2 * cos (M_PI / 2
540 * (1 - ((max_th - th)
543 h2off = dc->wall_height/2 - h2;
545 h2off = h2 - dc->wall_height/2;
552 glBegin(wire ? GL_LINES : GL_QUADS);
553 glNormal3f(x1, y1, 0);
554 glVertex3f(x1, y1, z1 - h1 + h1off);
555 glVertex3f(x1, y1, z1 + h1 + h1off);
556 glNormal3f(x2, y2, 0);
557 glVertex3f(x2, y2, z2 + h2 + h2off);
558 glVertex3f(x2, y2, z2 - h2 + h2off);
565 glBegin(wire ? GL_LINES : GL_QUADS);
566 glNormal3f(-x1b, -y1b, 0);
567 glVertex3f( x1b, y1b, z1 - h1 + h1off);
568 glVertex3f( x1b, y1b, z1 + h1 + h1off);
569 glNormal3f(-x2b, -y2b, 0);
570 glVertex3f( x2b, y2b, z2 + h2 + h2off);
571 glVertex3f( x2b, y2b, z2 - h2 + h2off);
578 /* glNormal3f(0, 0, 1);*/
579 do_normal (x2, y2, z2 + h2 + h2off,
580 x2b, y2b, z2 + h2 + h2off,
581 x1b, y1b, z1 + h1 + h1off);
582 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
583 glVertex3f( x2, y2, z2 + h2 + h2off);
584 glVertex3f( x2b, y2b, z2 + h2 + h2off);
585 glVertex3f( x1b, y1b, z1 + h1 + h1off);
586 glVertex3f( x1, y1, z1 + h1 + h1off);
593 do_normal ( x1, y1, z1 - h1 + h1off,
594 x1b, y1b, z1 - h1 + h1off,
595 x2b, y2b, z2 - h2 + h2off);
596 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
597 glNormal3f(0, 0, -1);
598 glVertex3f( x1, y1, z1 - h1 + h1off);
599 glVertex3f( x1b, y1b, z1 - h1 + h1off);
600 glVertex3f( x2b, y2b, z2 - h2 + h2off);
601 glVertex3f( x2, y2, z2 - h2 + h2off);
621 nx = cos (th + M_PI/2);
622 ny = sin (th + M_PI/2);
623 glNormal3f(nx, ny, 0);
624 glVertex3f(x2, y2, z1 - h2 + h2off);
625 glVertex3f(x2, y2, z1 + h2 + h2off);
626 glVertex3f(x2b, y2b, z1 + h2 + h2off);
627 glVertex3f(x2b, y2b, z1 - h2 + h2off);
636 make_ladder (logo_configuration *dc, int facetted, int wire)
640 GLfloat max_th = dc->turns * M_PI * 2;
641 GLfloat max_z = dc->turns * dc->turn_spacing;
642 GLfloat z_inc = dc->bar_spacing;
643 GLfloat th_inc = M_PI * 2 * (dc->bar_spacing / dc->turn_spacing);
646 /* skip forward to center the bars in the helix... */
648 GLfloat usable_th = max_th - dc->wall_taper;
649 GLfloat usable_z = max_z / (max_th / usable_th);
650 int nbars = usable_z / dc->bar_spacing;
651 GLfloat used_z, pad_z, pad_ratio;
653 if (! (nbars & 1)) nbars--; /* always an odd number of bars */
655 used_z = (nbars - 1) * dc->bar_spacing;
656 pad_z = max_z - used_z;
657 pad_ratio = pad_z / max_z;
659 th = (max_th * pad_ratio/2);
660 z = -(max_z / 2) + (max_z * pad_ratio/2);
663 z = -z, z_inc = -z_inc;
666 for (i = 0; i < nbars; i++)
668 int facets = dc->bar_facets / (facetted ? 14 : 1);
669 if (facets <= 3) facets = 3;
670 x = cos (th) * (1 - dc->wall_thickness);
671 y = sin (th) * (1 - dc->wall_thickness);
672 polys += tube ( x, y, z,
674 dc->bar_thickness, 0, facets,
689 make_gasket (logo_configuration *dc, int wire)
697 GLfloat d2r = M_PI / 180;
699 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 2;
701 GLfloat *pointsx0, *pointsy0, *pointsx1, *pointsy1, *normals;
703 GLfloat r0 = 0.750; /* 395 */
704 GLfloat r1a = 0.825; /* bottom of wall below upper left hole */
705 GLfloat r1b = 0.867; /* center of upper left hole */
706 GLfloat r1c = 0.909; /* top of wall above hole */
707 GLfloat r1 = 0.916; /* 471 */
708 GLfloat r2 = 0.963; /* 490 */
709 GLfloat r3 = 0.960; /* 499 */
710 GLfloat r4 = 1.000; /* 507 */
711 GLfloat r5 = 1.080; /* 553 */
713 GLfloat ctrl_r[100], ctrl_th[100];
717 # ifdef DXF_OUTPUT_HACK
718 if (! wire) res *= 8;
721 # define POINT(r,th) \
722 ctrl_r [nctrls] = r, \
723 ctrl_th[nctrls] = (th * d2r), \
726 POINT (0.829, 0); /* top indentation, right half */
734 POINT (r4, 4.0); /* moving clockwise... */
755 POINT (r4, 316.8); /* upper left indentation */
756 POINT (0.990, 316.87);
757 POINT (0.880, 317.21);
758 POINT (0.872, 317.45);
759 POINT (0.869, 317.80);
760 POINT (0.867, 318.10);
762 POINT (0.867, 318.85);
763 POINT (0.869, 319.15);
764 POINT (0.872, 319.50);
765 POINT (0.880, 319.74);
766 POINT (0.990, 320.08);
771 POINT (r1a, 338.0); /* cut-out disc */
777 POINT (0.872, 356.05); /* top indentation, left half */
778 POINT (0.862, 356.19);
779 POINT (0.851, 356.70);
780 POINT (0.841, 357.35);
781 POINT (0.835, 358.19);
782 POINT (0.831, 359.15);
786 points_size = res + (nctrls * 2);
787 pointsx0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
788 pointsy0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
789 pointsx1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
790 pointsy1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
791 normals = (GLfloat *) malloc (points_size * sizeof(GLfloat) * 2);
794 for (i = 1; i < nctrls; i++)
796 GLfloat from_r = ctrl_r [i-1];
797 GLfloat from_th = ctrl_th[i-1];
798 GLfloat to_r = ctrl_r [i];
799 GLfloat to_th = ctrl_th[i];
801 GLfloat step = 2*M_PI / res;
802 int nsteps = 1 + ((to_th - from_th) / step);
805 for (j = 0; j < nsteps + (i == nctrls-1); j++)
807 GLfloat r = from_r + (j * (to_r - from_r) / nsteps);
808 GLfloat th = from_th + (j * (to_th - from_th) / nsteps);
810 GLfloat cth = cos(th) * dc->gasket_size;
811 GLfloat sth = sin(th) * dc->gasket_size;
813 pointsx0[npoints] = r0 * cth; /* inner ring */
814 pointsy0[npoints] = r0 * sth;
815 pointsx1[npoints] = r * cth; /* outer ring */
816 pointsy1[npoints] = r * sth;
819 if (npoints >= points_size) abort();
823 /* normals for the outer ring */
824 for (i = 1; i < npoints; i++)
835 n = calc_normal (a, b, c);
836 normals[(i-1)*2 ] = n.x;
837 normals[(i-1)*2+1] = n.y;
840 glRotatef(-90, 0, 1, 0);
841 glRotatef(180, 0, 0, 1);
846 for (z = -thick2; z <= thick2; z += thick2*2)
850 glBegin (GL_LINE_LOOP);
851 for (i = 0; i < npoints; i++)
852 glVertex3f (pointsx0[i], pointsy0[i], z);
857 glBegin (GL_LINE_LOOP);
858 for (i = 0; i < npoints; i++)
859 glVertex3f (pointsx1[i], pointsy1[i], z);
863 for (i = 1; i < npoints; i++)
865 glBegin (GL_LINE_STRIP);
866 glVertex3f (pointsx0[i-1], pointsy0[i-1], z);
867 glVertex3f (pointsx0[i ], pointsy0[i ], z);
868 glVertex3f (pointsx1[i ], pointsy1[i ], z);
869 glVertex3f (pointsx1[i-1], pointsy1[i-1], z);
877 for (i = 0; i < npoints; i++)
880 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
881 glVertex3f (pointsx0[i], pointsy0[i], thick2);
883 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
884 glVertex3f (pointsx1[i], pointsy1[i], thick2);
894 glNormal3f(0, 0, -1);
895 glBegin (GL_QUAD_STRIP);
896 for (i = 0; i < npoints; i++)
898 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
899 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
907 glBegin (GL_QUAD_STRIP);
908 for (i = 0; i < npoints; i++)
910 glVertex3f (pointsx0[i], pointsy0[i], thick2);
911 glVertex3f (pointsx1[i], pointsy1[i], thick2);
918 glBegin (GL_QUAD_STRIP);
919 for (i = 0; i < npoints; i++)
921 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
922 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
923 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
932 for (i = 0; i < npoints-1; i++)
934 int ia = (i == 0 ? npoints-2 : i-1);
935 int iz = (i == npoints-2 ? 0 : i+1);
936 GLfloat x = pointsx1[i];
937 GLfloat y = pointsy1[i];
938 GLfloat xz = pointsx1[iz];
939 GLfloat yz = pointsy1[iz];
941 GLfloat nxa = normals[ia*2]; /* normal of [i-1 - i] face */
942 GLfloat nya = normals[ia*2+1];
943 GLfloat nx = normals[i*2]; /* normal of [i - i+1] face */
944 GLfloat ny = normals[i*2+1];
945 GLfloat nxz = normals[iz*2]; /* normal of [i+1 - i+2] face */
946 GLfloat nyz = normals[iz*2+1];
948 GLfloat anglea = vector_angle (nx, ny, 0, nxa, nya, 0);
949 GLfloat anglez = vector_angle (nx, ny, 0, nxz, nyz, 0);
950 GLfloat pointy = 0.005;
954 glNormal3f (nx, ny, 0);
955 glVertex3f (x, y, thick2);
956 glVertex3f (x, y, -thick2);
960 glNormal3f ((nxa + nx) / 2, (nya + ny) / 2, 0);
961 glVertex3f (x, y, thick2);
962 glVertex3f (x, y, -thick2);
967 glNormal3f (nx, ny, 0);
968 glVertex3f (xz, yz, -thick2);
969 glVertex3f (xz, yz, thick2);
973 glNormal3f ((nx + nxz) / 2, (ny + nyz) / 2, 0);
974 glVertex3f (xz, yz, -thick2);
975 glVertex3f (xz, yz, thick2);
983 /* Fill in the upper left hole...
990 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
991 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
993 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
994 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
998 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
999 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
1001 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
1002 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
1007 glNormal3f (0, 0, -1);
1009 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1010 glVertex3f (pointsx0[0], pointsy0[0], -thick2);
1011 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1012 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1013 glVertex3f (pointsx0[2], pointsy0[2], -thick2);
1018 glNormal3f (0, 0, 1);
1019 glFrontFace(GL_CCW);
1020 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1021 glVertex3f (pointsx0[0], pointsy0[0], thick2);
1022 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1023 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1024 glVertex3f (pointsx0[2], pointsy0[2], thick2);
1031 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1032 glNormal3f (pointsx0[1], pointsy0[1], 0);
1033 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1034 glNormal3f (pointsx0[3], pointsy0[3], 0);
1035 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1036 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1037 glNormal3f (pointsx0[1], pointsy0[1], 0);
1038 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1043 /* Now make a donut.
1046 int nsteps = (wire ? 12 : 64);
1049 GLfloat th, cth, sth;
1053 th = ((339.0 + 343.0) / 2) * d2r;
1055 glTranslatef (r1b * cos(th) * dc->gasket_size,
1056 r1b * sin(th) * dc->gasket_size,
1060 for (i = 0; i < nsteps; i++)
1062 th = 2 * M_PI * i / nsteps;
1063 cth = cos (th) * dc->gasket_size;
1064 sth = sin (th) * dc->gasket_size;
1065 pointsx0[npoints] = r0 * cth;
1066 pointsy0[npoints] = r0 * sth;
1067 pointsx1[npoints] = r1 * cth;
1068 pointsy1[npoints] = r1 * sth;
1073 pointsx0[npoints] = pointsx0[0];
1074 pointsy0[npoints] = pointsy0[0];
1075 pointsx1[npoints] = pointsx1[0];
1076 pointsy1[npoints] = pointsy1[0];
1081 glBegin (GL_LINE_LOOP);
1082 for (i = 0; i < npoints; i++)
1083 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1086 glBegin (GL_LINE_LOOP);
1087 for (i = 0; i < npoints; i++)
1088 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1092 glBegin (GL_LINE_LOOP);
1093 for (i = 0; i < npoints; i++)
1094 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1097 glBegin (GL_LINE_LOOP);
1098 for (i = 0; i < npoints; i++)
1099 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1108 glNormal3f(0, 0, -1);
1109 glBegin (GL_QUAD_STRIP);
1110 for (i = 0; i < npoints; i++)
1112 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1113 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1119 glFrontFace(GL_CCW);
1120 glNormal3f(0, 0, 1);
1121 glBegin (GL_QUAD_STRIP);
1122 for (i = 0; i < npoints; i++)
1124 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1125 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1133 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1134 for (i = 0; i < npoints; i++)
1136 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
1137 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
1138 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
1148 /* Attach the bottom-right dingus...
1155 glRotatef (49.5, 0, 0, 1);
1156 glScalef (dc->gasket_size, dc->gasket_size, 1);
1157 glTranslatef (0, (r0+r1)/2, 0);
1162 glFrontFace(GL_CCW);
1163 glBegin (wire ? GL_LINE_STRIP : GL_QUADS);
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);
1170 glNormal3f (0, 0, 1);
1171 glVertex3f ( w/2, -h/2, thick2); glVertex3f ( w/2, h/2, thick2);
1172 glVertex3f (-w/2, h/2, thick2); glVertex3f (-w/2, -h/2, thick2);
1173 glNormal3f (-1, 0, 0);
1174 glVertex3f (-w/2, -h/2, thick2); glVertex3f (-w/2, h/2, thick2);
1175 glVertex3f (-w/2, h/2, -thick2); glVertex3f (-w/2, -h/2, -thick2);
1181 for (th = (wire ? 0 : -0.1);
1183 th += (M_PI / (wire ? 5 : 32)))
1185 pointsx0[npoints] = w/2 * cos(th);
1186 pointsy0[npoints] = w/2 * sin(th);
1191 /* front inside curve */
1192 glNormal3f (0, 0, -1);
1194 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1195 if (! wire) glVertex3f (0, h/2, -thick2);
1196 for (i = 0; i < npoints; i++)
1197 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1201 /* front outside curve */
1202 glFrontFace(GL_CCW);
1203 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1204 if (! wire) glVertex3f (0, -h/2, -thick2);
1205 for (i = 0; i < npoints; i++)
1206 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1210 /* back inside curve */
1211 glNormal3f (0, 0, 1);
1212 glFrontFace(GL_CCW);
1213 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1214 if (! wire) glVertex3f (0, h/2, thick2);
1215 for (i = 0; i < npoints; i++)
1216 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1220 /* back outside curve */
1222 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1223 if (! wire) glVertex3f (0, -h/2, thick2);
1224 for (i = 0; i < npoints; i++)
1225 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1230 glFrontFace(GL_CCW);
1231 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1232 for (i = 0; i < npoints; i++)
1234 glNormal3f (pointsx0[i], pointsy0[i], 0);
1235 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1236 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1243 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1244 for (i = 0; i < npoints; i++)
1246 glNormal3f (pointsx0[i], -pointsy0[i], 0);
1247 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1248 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1265 make_frame (logo_configuration *dc, int wire)
1269 GLfloat x[20], y[20];
1270 GLfloat corner_cut = 0.5;
1273 glRotatef (90, 0, 1, 0);
1274 glScalef (4 * dc->frame_size,
1276 4 * dc->frame_size);
1278 x[0] = -dc->frame_thickness;
1279 x[1] = -dc->frame_thickness * corner_cut;
1281 x[3] = 0.5 - dc->triangle_size;
1283 x[5] = 0.5 + dc->triangle_size;
1285 x[7] = 1 + dc->frame_thickness * corner_cut;
1286 x[8] = 1 + dc->frame_thickness;
1288 y[0] = -dc->frame_thickness;
1289 y[1] = -dc->frame_thickness * corner_cut;
1291 y[3] = dc->triangle_size;
1295 glTranslatef (-0.5, -0.5, dc->frame_depth / 4);
1297 for (j = 0; j <= 1; j++)
1299 if (j) glTranslatef (0, 0, -dc->frame_depth / 2);
1300 glFrontFace (j ? GL_CCW : GL_CW);
1301 for (i = 0; i < 4; i++)
1303 glNormal3f (0, 0, (j ? -1 : 1));
1304 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1305 glVertex3f (x[0], y[1], 0); glVertex3f (x[0], y[2], 0);
1306 glVertex3f (x[1], y[0], 0); glVertex3f (x[1], y[2], 0);
1307 glVertex3f (x[3], y[0], 0); glVertex3f (x[3], y[2], 0);
1308 glVertex3f (x[4], y[0], 0); glVertex3f (x[4], y[3], 0);
1309 glVertex3f (x[5], y[0], 0); glVertex3f (x[5], y[2], 0);
1310 glVertex3f (x[7], y[0], 0); glVertex3f (x[7], y[2], 0);
1311 glVertex3f (x[8], y[1], 0); glVertex3f (x[8], y[2], 0);
1314 glTranslatef (0.5, 0.5, 0);
1315 glRotatef (90, 0, 0, 1);
1316 glTranslatef (-0.5, -0.5, 0);
1322 glFrontFace (GL_CCW);
1323 for (i = 0; i < 4; i++)
1325 glNormal3f (0, 1, 0);
1326 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1327 glVertex3f (x[2], y[2], 0); glVertex3f (x[2], y[2], dc->frame_depth/2);
1328 glVertex3f (x[3], y[2], 0); glVertex3f (x[3], y[2], dc->frame_depth/2);
1329 glVertex3f (x[4], y[3], 0); glVertex3f (x[4], y[3], dc->frame_depth/2);
1330 glVertex3f (x[5], y[2], 0); glVertex3f (x[5], y[2], dc->frame_depth/2);
1331 glVertex3f (x[6], y[2], 0); glVertex3f (x[6], y[2], dc->frame_depth/2);
1335 glNormal3f (0, -1, 0);
1336 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1337 glVertex3f (x[7], y[0], 0);
1338 glVertex3f (x[7], y[0], dc->frame_depth/2);
1339 glVertex3f (x[1], y[0], dc->frame_depth/2);
1340 glVertex3f (x[1], y[0], 0);
1344 glNormal3f (1, -1, 0);
1345 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1346 glVertex3f (x[8], y[1], 0);
1347 glVertex3f (x[8], y[1], dc->frame_depth/2);
1348 glVertex3f (x[7], y[0], dc->frame_depth/2);
1349 glVertex3f (x[7], y[0], 0);
1355 glNormal3f (0, 1, 0);
1356 for (j = 0; j <= 1; j++)
1358 glBegin (GL_LINE_STRIP);
1359 glVertex3f (x[2], y[2], j*dc->frame_depth/2);
1360 glVertex3f (x[3], y[2], j*dc->frame_depth/2);
1361 glVertex3f (x[4], y[3], j*dc->frame_depth/2);
1362 glVertex3f (x[5], y[2], j*dc->frame_depth/2);
1363 glVertex3f (x[6], y[2], j*dc->frame_depth/2);
1369 glTranslatef (0.5, 0.5, 0);
1370 glRotatef (90, 0, 0, 1);
1371 glTranslatef (-0.5, -0.5, 0);
1391 tess_error_cb (GLenum errorCode)
1393 fprintf (stderr, "%s: tesselation error: %s\n",
1394 progname, gluErrorString(errorCode));
1399 tess_combine_cb (GLdouble coords[3], GLdouble *d[4], GLfloat w[4],
1400 GLdouble **data_out)
1402 GLdouble *new = (GLdouble *) malloc (3 * sizeof(*new));
1412 tess_vertex_cb (void *vertex_data, void *closure)
1414 tess_out *to = (tess_out *) closure;
1415 GLdouble *v = (GLdouble *) vertex_data;
1416 to->points[to->i++] = v[0];
1417 to->points[to->i++] = v[1];
1418 to->points[to->i++] = v[2];
1423 tess_begin_cb (GLenum which)
1434 #endif /* HAVE_TESS */
1438 make_pizza (logo_configuration *dc, int facetted, int wire)
1441 int topfaces = (facetted ? 48 : 120);
1442 int discfaces = (facetted ? 12 : 120);
1443 int npoints = topfaces * 2 + 100;
1444 GLdouble *points = (GLdouble *) calloc (npoints * 3, sizeof(GLdouble));
1446 GLdouble *holes = (GLdouble *) calloc (topfaces*nholes*3, sizeof(GLdouble));
1448 GLfloat step = M_PI * 2 / 6 / topfaces;
1449 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 4;
1450 GLfloat th, x, y, s;
1456 tess_out TO, *to = &TO;
1457 GLUtesselator *tess = gluNewTess();
1459 to->points = (GLdouble *) calloc (topfaces * 20, sizeof(GLdouble));
1462 # ifndef _GLUfuncptr
1463 # define _GLUfuncptr void(*)(void)
1466 gluTessCallback(tess,GLU_TESS_BEGIN, (_GLUfuncptr)tess_begin_cb);
1467 gluTessCallback(tess,GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv);
1468 gluTessCallback(tess,GLU_TESS_END, (_GLUfuncptr)tess_end_cb);
1469 gluTessCallback(tess,GLU_TESS_COMBINE, (_GLUfuncptr)tess_combine_cb);
1470 gluTessCallback(tess,GLU_TESS_ERROR, (_GLUfuncptr)tess_error_cb);
1472 gluTessProperty (tess, GLU_TESS_BOUNDARY_ONLY, wire);
1473 gluTessProperty (tess,GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
1475 # endif /* HAVE_TESS */
1480 glRotatef (180, 0, 0, 1);
1482 glRotatef (90, 0, 1, 0);
1483 glTranslatef (-0.53, 0, 0);
1484 glRotatef (-30, 0, 0, 1);
1486 /* Compute the wedge */
1499 for (i = 0; i < countof(edge)/2; i++)
1501 points[j++] = edge[i*2+1];
1502 points[j++] = edge[i*2];
1508 s = 0.798; /* radius of end of slice, before crust gap */
1509 for (i = 0; i < topfaces; i++)
1511 points[j++] = cos(th) * s;
1512 points[j++] = sin(th) * s;
1529 for (i = 0; i < countof(edge)/2; i++)
1531 points[j++] = edge[i*2+1];
1532 points[j++] = edge[i*2];
1539 /* Draw the rim of the slice */
1540 glBegin (wire ? GL_LINES : GL_QUADS);
1543 for (i = (wire ? 0 : 1); i < endpoints; i++)
1545 GLdouble *p = points + (i*3);
1547 do_normal (p[0], p[1], -thick2,
1552 glVertex3f (x, y, -thick2);
1553 glVertex3f (x, y, thick2);
1555 glVertex3f (p[0], p[1], thick2);
1556 glVertex3f (p[0], p[1], -thick2);
1562 do_normal (points[0], points[1], -thick2,
1563 points[0], points[1], thick2,
1565 glVertex3f (x, y, -thick2);
1566 glVertex3f (x, y, thick2);
1567 glVertex3f (points[0], points[1], thick2);
1568 glVertex3f (points[0], points[1], -thick2);
1575 /* Outline of slice */
1576 glBegin (GL_LINE_LOOP);
1577 for (i = 0; i < endpoints; i++)
1578 glVertex3f (points[i*3], points[i*3+1], -thick2);
1580 glBegin (GL_LINE_LOOP);
1581 for (i = 0; i < endpoints; i++)
1582 glVertex3f (points[i*3], points[i*3+1], thick2);
1585 # endif /* HAVE_TESS */
1587 /* Compute the holes */
1588 step = M_PI * 2 / discfaces;
1589 for (k = 0; k < nholes; k++)
1591 GLdouble *p = holes + (discfaces * 3 * k);
1595 case 0: x = 0.34; y = 0.17; s = 0.05; break;
1596 case 1: x = 0.54; y = 0.17; s = 0.06; break;
1597 case 2: x = 0.55; y = 0.36; s = 0.06; break;
1598 default: abort(); break;
1600 for (i = 0; i < discfaces; i++)
1602 p[j++] = x + cos(M_PI*2 - th) * s;
1603 p[j++] = y + sin(M_PI*2 - th) * s;
1610 /* Draw the inside rim of the holes */
1611 for (k = 0; k < nholes; k++)
1613 GLdouble *p = holes + (discfaces * 3 * k);
1615 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1616 for (i = 0; i < discfaces; i++)
1618 GLdouble *p2 = p + (i*3);
1620 do_normal (p2[0], p2[1], -thick2,
1621 p2[0], p2[1], thick2,
1622 p2[-3], p2[-2], thick2);
1623 glVertex3f (p2[0], p2[1], -thick2);
1624 glVertex3f (p2[0], p2[1], thick2);
1627 glVertex3f (p[0], p[1], -thick2);
1628 glVertex3f (p[0], p[1], thick2);
1634 /* Outline of holes */
1635 glBegin (GL_LINE_LOOP);
1636 for (i = 0; i < discfaces; i++)
1637 glVertex3f (p[i*3], p[i*3+1], -thick2);
1639 glBegin (GL_LINE_LOOP);
1640 for (i = 0; i < discfaces; i++)
1641 glVertex3f (p[i*3], p[i*3+1], thick2);
1644 # endif /* !HAVE_TESS */
1648 glTranslatef (0, 0, -thick2);
1649 for (y = 0; y <= 1; y++)
1651 if (y) glTranslatef (0, 0, thick2*2);
1653 /* A non-convex polygon */
1654 gluTessBeginPolygon (tess, to);
1656 glNormal3f (0, 0, (y > 0 ? 1 : -1));
1657 gluTessNormal (tess, 0, 0, (y > 0 ? 1 : -1));
1658 glFrontFace (GL_CCW);
1660 /* Tess the wedge */
1661 gluTessBeginContour (tess);
1662 for (i = 0; i < endpoints; i++)
1664 GLdouble *p = points + (i*3);
1665 gluTessVertex (tess, p, p);
1668 gluTessVertex (tess, points, points);
1669 gluTessEndContour (tess);
1671 /* Tess the holes */
1672 for (k = 0; k < nholes; k++)
1674 GLdouble *p = holes + (discfaces * 3 * k);
1675 gluTessBeginContour (tess);
1676 for (i = 0; i < discfaces; i++)
1678 GLdouble *p2 = p + (i*3);
1679 gluTessVertex (tess, p2, p2);
1682 gluTessEndContour (tess);
1685 gluTessEndPolygon (tess);
1688 glTranslatef (0, 0, -thick2);
1690 # else /* !HAVE_TESS */
1693 glDisableClientState (GL_COLOR_ARRAY);
1694 glDisableClientState (GL_NORMAL_ARRAY);
1695 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1696 glEnableClientState (GL_VERTEX_ARRAY);
1697 glVertexPointer (3, GL_FLOAT, 0, dnapizza_triangles);
1699 glTranslatef(0, 0, thick2);
1700 glNormal3f (0, 0, 1);
1701 glFrontFace (GL_CW);
1702 glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
1704 glTranslatef(0, 0, -thick2*2);
1705 glNormal3f (0, 0, -1);
1706 glFrontFace (GL_CCW);
1707 glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
1709 glTranslatef(0, 0, thick2);
1711 # endif /* !HAVE_TESS */
1714 /* Compute the crust */
1716 s = 0.861; /* radius of inside of crust */
1717 step = M_PI * 2 / 6 / topfaces;
1720 for (i = 0; i < topfaces; i++)
1722 points[j++] = cos(th) * s;
1723 points[j++] = sin(th) * s;
1729 for (i = 0; i < topfaces; i++)
1731 points[j++] = cos(th) * s;
1732 points[j++] = sin(th) * s;
1737 /* Draw the rim of the crust */
1738 glFrontFace (GL_CCW);
1739 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1740 for (i = 0; i < topfaces * 2; i++)
1742 GLdouble *p = points + (i*3);
1743 if (i == 0 || i == (topfaces*2)-1)
1744 glNormal3f (0, -1, 0);
1745 else if (i == topfaces-1 || i == topfaces)
1746 glNormal3f (0, 1, 0);
1748 do_normal (p[-3], p[-2], thick2,
1750 p[0], p[1], -thick2);
1751 glVertex3f (p[0], p[1], -thick2);
1752 glVertex3f (p[0], p[1], thick2);
1755 glVertex3f (points[0], points[1], -thick2);
1756 glVertex3f (points[0], points[1], thick2);
1762 glBegin (GL_LINE_STRIP);
1763 for (i = 0; i < topfaces * 2; i++)
1765 GLdouble *p = points + (i*3);
1766 glVertex3f (p[0], p[1], -thick2);
1769 glVertex3f (points[0], points[1], -thick2);
1772 glBegin (GL_LINE_STRIP);
1773 for (i = 0; i < topfaces * 2; i++)
1775 GLdouble *p = points + (i*3);
1776 glVertex3f (p[0], p[1], thick2);
1779 glVertex3f (points[0], points[1], thick2);
1783 /* Draw the top of the crust */
1786 glFrontFace (GL_CW);
1787 glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP);
1788 glNormal3f (0, 0, -1);
1790 for (i = 0; i < topfaces; i++)
1792 int ii = topfaces + (topfaces - i - 1);
1793 GLdouble *p1 = points + (i*3);
1794 GLdouble *p2 = points + (ii*3);
1795 glVertex3f (p1[0], p1[1], -thick2);
1796 glVertex3f (p2[0], p2[1], -thick2);
1802 /* Draw the bottom of the crust */
1803 glFrontFace (GL_CCW);
1804 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1805 glNormal3f (0, 0, 1);
1806 for (i = 0; i < topfaces; i++)
1808 int ii = topfaces + (topfaces - i - 1);
1809 GLdouble *p1 = points + (i*3);
1810 GLdouble *p2 = points + (ii*3);
1811 glVertex3f (p1[0], p1[1], thick2);
1812 glVertex3f (p2[0], p2[1], thick2);
1820 gluDeleteTess (tess);
1822 # endif /* HAVE_TESS */
1835 /* Window management, etc
1838 reshape_logo (ModeInfo *mi, int width, int height)
1840 GLfloat h = (GLfloat) height / (GLfloat) width;
1842 glViewport (0, 0, (GLint) width, (GLint) height);
1844 glMatrixMode(GL_PROJECTION);
1846 gluPerspective (30.0, 1/h, 1.0, 100.0);
1848 glMatrixMode(GL_MODELVIEW);
1850 gluLookAt( 0.0, 0.0, 30.0,
1854 glClear(GL_COLOR_BUFFER_BIT);
1859 gl_init (ModeInfo *mi)
1861 /* logo_configuration *dc = &dcs[MI_SCREEN(mi)]; */
1862 int wire = MI_IS_WIREFRAME(mi);
1864 GLfloat position[] = {0, 0, 0, 0};
1865 GLfloat direction[] = {3, -1, -3};
1867 position[0] = -direction[0];
1868 position[1] = -direction[1];
1869 position[2] = -direction[2];
1873 glLightfv(GL_LIGHT0, GL_POSITION, position);
1874 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction);
1875 glShadeModel(GL_SMOOTH);
1876 glEnable(GL_NORMALIZE);
1877 glEnable(GL_CULL_FACE);
1878 glEnable(GL_LIGHTING);
1879 glEnable(GL_LIGHT0);
1880 glEnable(GL_DEPTH_TEST);
1886 init_logo (ModeInfo *mi)
1888 logo_configuration *dc;
1889 int do_gasket = get_boolean_resource(mi->dpy, "doGasket", "Boolean");
1890 int do_helix = get_boolean_resource(mi->dpy, "doHelix", "Boolean");
1891 int do_ladder = (do_helix &&
1892 get_boolean_resource(mi->dpy, "doLadder", "Boolean"));
1893 int do_frame = get_boolean_resource(mi->dpy, "doFrame", "Boolean");
1894 GLfloat helix_rot = 147.0;
1896 if (!do_gasket && !do_helix)
1898 fprintf (stderr, "%s: no helix or gasket?\n", progname);
1903 dcs = (logo_configuration *)
1904 calloc (MI_NUM_SCREENS(mi), sizeof (logo_configuration));
1906 fprintf(stderr, "%s: out of memory\n", progname);
1911 dc = &dcs[MI_SCREEN(mi)];
1913 if ((dc->glx_context = init_GL(mi)) != NULL) {
1915 reshape_logo (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1918 dc->wall_facets = get_integer_resource(mi->dpy, "wallFacets", "Integer");
1919 dc->bar_facets = get_integer_resource(mi->dpy, "barFacets", "Integer");
1920 dc->clockwise = get_boolean_resource(mi->dpy, "clockwise", "Boolean");
1921 dc->turns = get_float_resource(mi->dpy, "turns", "Float");
1922 dc->turn_spacing = get_float_resource(mi->dpy, "turnSpacing", "Float");
1923 dc->bar_spacing = get_float_resource(mi->dpy, "barSpacing", "Float");
1924 dc->wall_height = get_float_resource(mi->dpy, "wallHeight", "Float");
1925 dc->wall_thickness = get_float_resource(mi->dpy, "wallThickness", "Float");
1926 dc->bar_thickness = get_float_resource(mi->dpy, "barThickness", "Float");
1927 dc->wall_taper = get_float_resource(mi->dpy, "wallTaper", "Float");
1929 dc->gasket_size = get_float_resource(mi->dpy,"gasketSize", "Float");
1930 dc->gasket_depth = get_float_resource(mi->dpy,"gasketDepth", "Float");
1931 dc->gasket_thickness = get_float_resource(mi->dpy,"gasketThickness","Float");
1933 dc->frame_size = get_float_resource(mi->dpy, "frameSize", "Float");
1934 dc->frame_depth = get_float_resource(mi->dpy, "frameDepth", "Float");
1935 dc->frame_thickness = get_float_resource(mi->dpy, "frameThickness", "Float");
1936 dc->triangle_size = get_float_resource(mi->dpy, "triangleSize", "Float");
1938 dc->speed = get_float_resource(mi->dpy, "speed", "Float");
1941 char *s = get_string_resource (MI_DISPLAY (mi), "mode", "String");
1942 if (!s || !*s || !strcasecmp (s, "helix"))
1944 else if (!strcasecmp (s, "pizza"))
1946 else if (!strcasecmp (s, "both"))
1950 fprintf (stderr, "%s: mode must be helix, pizza or both, not \"%s\"\n",
1956 dc->anim_state = (dc->mode == BOTH
1957 ? ((random() & 1) ? HELIX : PIZZA)
1965 char *color_name = get_string_resource (mi->dpy, "foreground", "Foreground");
1967 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
1968 if (*s2 == ' ' || *s2 == '\t')
1973 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
1975 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
1979 dc->color[0] = xcolor.red / 65535.0;
1980 dc->color[1] = xcolor.green / 65535.0;
1981 dc->color[2] = xcolor.blue / 65535.0;
1985 dc->trackball = gltrackball_init ();
1987 dc->gasket_spinnerx.probability = 0.1;
1988 dc->gasket_spinnery.probability = 0.1;
1989 dc->gasket_spinnerz.probability = 1.0;
1991 dc->helix_spinnerz.probability = 0.6;
1993 dc->pizza_spinnerz.probability = 0.6;
1994 dc->pizza_spinnery.probability = 0.6;
1996 dc->scene_spinnerx.probability = 0.1;
1997 dc->scene_spinnery.probability = 0.0;
1999 dc->frame_spinner.probability = 5.0;
2001 /* start the frame off-screen */
2002 dc->frame_spinner.spinning_p = True;
2003 dc->frame_spinner.position = 0.3;
2004 dc->frame_spinner.speed = 0.001;
2006 if (dc->speed > 0) /* start off with the gasket in motion */
2008 dc->gasket_spinnerz.spinning_p = True;
2009 dc->gasket_spinnerz.speed = (0.002
2010 * ((random() & 1) ? 1 : -1)
2014 # ifdef DXF_OUTPUT_HACK
2016 dc->frame_depth = dc->gasket_depth;
2021 glRotatef(90, 1, 0, 0);
2022 glRotatef(90, 0, 0, 1);
2023 make_pizza (dc, 0, 0);
2026 glRotatef(helix_rot, 0, 0, 1);
2027 make_ladder (dc, 0, 0);
2028 make_helix (dc, 0, 0);
2029 glRotatef (180, 0, 0, 1);
2030 make_helix (dc, 0, 0);
2034 make_gasket (dc, 0);
2043 dc->helix_list = glGenLists (1);
2044 glNewList (dc->helix_list, GL_COMPILE);
2045 glRotatef(helix_rot, 0, 0, 1);
2046 if (do_ladder) dc->polys[0] += make_ladder (dc, 0, 0);
2047 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
2048 glRotatef(180, 0, 0, 1);
2049 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
2054 dc->helix_list_wire = glGenLists (1);
2055 glNewList (dc->helix_list_wire, GL_COMPILE);
2056 /* glRotatef(helix_rot, 0, 0, 1); wtf? */
2057 if (do_ladder) dc->polys[1] += make_ladder (dc, 1, 1);
2058 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
2059 glRotatef(180, 0, 0, 1);
2060 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
2065 dc->helix_list_facetted = glGenLists (1);
2066 glNewList (dc->helix_list_facetted, GL_COMPILE);
2067 glRotatef(helix_rot, 0, 0, 1);
2068 if (do_ladder) dc->polys[2] += make_ladder (dc, 1, 0);
2069 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
2070 glRotatef(180, 0, 0, 1);
2071 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
2075 dc->pizza_list = glGenLists (1);
2076 glNewList (dc->pizza_list, GL_COMPILE);
2077 if (do_frame) dc->polys[5] += make_pizza (dc, 0, 0);
2080 dc->pizza_list_wire = glGenLists (1);
2081 glNewList (dc->pizza_list_wire, GL_COMPILE);
2082 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 1);
2085 dc->pizza_list_facetted = glGenLists (1);
2086 glNewList (dc->pizza_list_facetted, GL_COMPILE);
2087 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 0);
2090 dc->gasket_list = glGenLists (1);
2091 glNewList (dc->gasket_list, GL_COMPILE);
2092 if (do_gasket) dc->polys[3] += make_gasket (dc, 0);
2095 dc->gasket_list_wire = glGenLists (1);
2096 glNewList (dc->gasket_list_wire, GL_COMPILE);
2097 if (do_gasket) dc->polys[4] += make_gasket (dc, 1);
2100 dc->frame_list = glGenLists (1);
2101 glNewList (dc->frame_list, GL_COMPILE);
2102 if (do_frame) dc->polys[5] += make_frame (dc, 0);
2105 dc->frame_list_wire = glGenLists (1);
2106 glNewList (dc->frame_list_wire, GL_COMPILE);
2107 if (do_frame) dc->polys[6] += make_frame (dc, 1);
2110 /* When drawing both solid and wireframe objects,
2111 make sure the wireframe actually shows up! */
2112 glEnable (GL_POLYGON_OFFSET_FILL);
2113 glPolygonOffset (1.0, 1.0);
2118 logo_handle_event (ModeInfo *mi, XEvent *event)
2120 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2122 if (event->xany.type == ButtonPress &&
2123 event->xbutton.button == Button1)
2125 dc->button_down_p = True;
2126 gltrackball_start (dc->trackball,
2127 event->xbutton.x, event->xbutton.y,
2128 MI_WIDTH (mi), MI_HEIGHT (mi));
2131 else if (event->xany.type == ButtonRelease &&
2132 event->xbutton.button == Button1)
2134 dc->button_down_p = False;
2137 else if (event->xany.type == ButtonPress &&
2138 (event->xbutton.button == Button4 ||
2139 event->xbutton.button == Button5 ||
2140 event->xbutton.button == Button6 ||
2141 event->xbutton.button == Button7))
2143 gltrackball_mousewheel (dc->trackball, event->xbutton.button, 10,
2144 !!event->xbutton.state);
2147 else if (event->xany.type == MotionNotify &&
2150 gltrackball_track (dc->trackball,
2151 event->xmotion.x, event->xmotion.y,
2152 MI_WIDTH (mi), MI_HEIGHT (mi));
2161 tick_spinner (ModeInfo *mi, spinner *s)
2163 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2165 if (dc->speed == 0) return;
2166 if (dc->button_down_p) return;
2170 s->position += s->speed;
2171 if (s->position >= 1.0 || s->position <= -1.0)
2175 s->spinning_p = False;
2178 else if (s->probability &&
2179 (random() % (int) (PROBABILITY_SCALE / s->probability)) == 0)
2182 s->spinning_p = True;
2185 s->speed = dc->speed * (frand(ss/3) + frand(ss/3) + frand(ss/3));
2186 } while (s->speed <= 0);
2188 s->speed = -s->speed;
2194 link_spinners (ModeInfo *mi, spinner *s0, spinner *s1)
2196 if (s0->spinning_p && !s1->spinning_p)
2198 GLfloat op = s1->probability;
2199 s1->probability = PROBABILITY_SCALE;
2200 tick_spinner (mi, s1);
2201 s1->probability = op;
2207 draw_logo (ModeInfo *mi)
2209 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2210 Display *dpy = MI_DISPLAY(mi);
2211 Window window = MI_WINDOW(mi);
2212 int wire = MI_IS_WIREFRAME(mi);
2214 GLfloat specular[] = {0.8, 0.8, 0.8, 1.0};
2215 GLfloat shininess = 50.0;
2218 if (!dc->glx_context)
2221 mi->polygon_count = 0;
2222 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(dc->glx_context));
2225 dc->wire_overlay == 0 &&
2226 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
2227 dc->wire_overlay = ((random() % 200) +
2231 tick_spinner (mi, &dc->gasket_spinnerx);
2232 tick_spinner (mi, &dc->gasket_spinnery);
2233 tick_spinner (mi, &dc->gasket_spinnerz);
2234 tick_spinner (mi, &dc->helix_spinnerz);
2235 tick_spinner (mi, &dc->pizza_spinnery);
2236 tick_spinner (mi, &dc->pizza_spinnerz);
2237 tick_spinner (mi, &dc->scene_spinnerx);
2238 tick_spinner (mi, &dc->scene_spinnery);
2239 tick_spinner (mi, &dc->frame_spinner);
2240 link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery);
2242 switch (dc->anim_state)
2245 if (dc->mode == BOTH &&
2246 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
2247 dc->anim_state = HELIX_OUT;
2251 dc->anim_ratio += 0.1 * dc->speed;
2252 if (dc->anim_ratio >= 1.0)
2254 dc->anim_ratio = 0.0;
2255 dc->anim_state = PIZZA_IN;
2260 dc->anim_ratio += 0.1 * dc->speed;
2261 if (dc->anim_ratio >= 1.0)
2263 dc->anim_ratio = 0.0;
2264 dc->anim_state = PIZZA;
2269 if (dc->mode == BOTH &&
2270 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
2271 dc->anim_state = PIZZA_OUT;
2275 dc->anim_ratio += 0.1 * dc->speed;
2276 if (dc->anim_ratio >= 1.0)
2278 dc->anim_ratio = 0.0;
2279 dc->anim_state = HELIX_IN;
2284 dc->anim_ratio += 0.1 * dc->speed;
2285 if (dc->anim_ratio >= 1.0)
2287 dc->anim_ratio = 0.0;
2288 dc->anim_state = HELIX;
2297 pizza_p = (dc->anim_state == PIZZA ||
2298 dc->anim_state == PIZZA_IN ||
2299 dc->anim_state == PIZZA_OUT);
2301 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2304 glRotatef(current_device_rotation(), 0, 0, 1);
2310 glScalef (0.7, 0.7, 0.7); /* make room for the frame */
2313 glColor3f(dc->color[0], dc->color[1], dc->color[2]);
2315 /* Draw frame before trackball rotation */
2317 GLfloat p = (dc->frame_spinner.position >= 0
2318 ? dc->frame_spinner.position
2319 : -dc->frame_spinner.position);
2320 GLfloat size = (p > 0.5 ? 1-p : p);
2321 scale = 1 + (size * 10);
2323 /* gltrackball_rotate (dc->trackball); */
2324 glRotatef(90, 1, 0, 0);
2325 glRotatef(90, 0, 0, 1);
2327 glScalef (1, scale, scale);
2330 glDisable (GL_LIGHTING);
2331 glCallList (dc->frame_list_wire);
2332 mi->polygon_count += dc->polys[6];
2334 else if (dc->wire_overlay != 0)
2336 glCallList (dc->frame_list);
2337 glDisable (GL_LIGHTING);
2338 glColor3fv (dc->color);
2339 glCallList (dc->frame_list_wire);
2340 mi->polygon_count += dc->polys[6];
2341 if (!wire) glEnable (GL_LIGHTING);
2345 glCallList (dc->frame_list);
2346 mi->polygon_count += dc->polys[5];
2351 gltrackball_rotate (dc->trackball);
2353 glRotatef(90, 1, 0, 0);
2354 glRotatef(90, 0, 0, 1);
2356 glRotatef (360 * sin (M_PI/2 * dc->scene_spinnerx.position), 0, 1, 0);
2357 glRotatef (360 * sin (M_PI/2 * dc->scene_spinnery.position), 0, 0, 1);
2361 glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnerx.position), 0, 1, 0);
2362 glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnery.position), 0, 0, 1);
2363 glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnerz.position), 1, 0, 0);
2365 memcpy (gcolor, dc->color, sizeof (dc->color));
2366 if (dc->wire_overlay != 0)
2368 gcolor[0] = gcolor[1] = gcolor[2] = 0;
2369 specular[0] = specular[1] = specular[2] = 0;
2372 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
2373 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
2374 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shininess);
2378 glDisable (GL_LIGHTING);
2379 glCallList (dc->gasket_list_wire);
2380 mi->polygon_count += dc->polys[4];
2382 else if (dc->wire_overlay != 0)
2384 glCallList (dc->gasket_list);
2385 glDisable (GL_LIGHTING);
2386 glColor3fv (dc->color);
2387 glCallList (dc->gasket_list_wire);
2388 mi->polygon_count += dc->polys[4];
2389 if (!wire) glEnable (GL_LIGHTING);
2390 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
2394 glCallList (dc->gasket_list);
2395 mi->polygon_count += dc->polys[3];
2402 glRotatef (360 * sin (M_PI/2 * dc->pizza_spinnery.position), 1, 0, 0);
2403 glRotatef (360 * sin (M_PI/2 * dc->pizza_spinnerz.position), 0, 0, 1);
2407 glRotatef (360 * sin (M_PI/2 * dc->helix_spinnerz.position), 0, 0, 1);
2410 scale = ((dc->anim_state == PIZZA_IN || dc->anim_state == HELIX_IN)
2412 : ((dc->anim_state == PIZZA_OUT || dc->anim_state == HELIX_OUT)
2413 ? 1.0 - dc->anim_ratio
2415 if (scale <= 0) scale = 0.001;
2416 glScalef (scale, scale, scale);
2420 glDisable (GL_LIGHTING);
2422 glCallList (dc->pizza_list_wire);
2424 glCallList (dc->helix_list_wire);
2425 mi->polygon_count += dc->polys[1];
2427 else if (dc->wire_overlay != 0)
2430 glCallList (dc->pizza_list_facetted);
2432 glCallList (dc->helix_list_facetted);
2434 glDisable (GL_LIGHTING);
2435 glColor3fv (dc->color);
2438 glCallList (dc->pizza_list_wire);
2440 glCallList (dc->helix_list_wire);
2442 mi->polygon_count += dc->polys[2];
2443 if (!wire) glEnable (GL_LIGHTING);
2448 glCallList (dc->pizza_list);
2450 glCallList (dc->helix_list);
2451 mi->polygon_count += dc->polys[0];
2456 if (dc->wire_overlay > 0)
2459 if (mi->fps_p) do_fps (mi);
2462 glXSwapBuffers(dpy, window);
2465 XSCREENSAVER_MODULE_2 ("DNALogo", dnalogo, logo)