1 /* DNA Logo, Copyright (c) 2001-2017 Jamie Zawinski <jwz@jwz.org>
5 * Restaurant -- Bar -- Nightclub -- Cafe -- Est. 1985.
11 * https://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" \
49 "*cwDiscFacets: 64 \n" \
51 "*cwLineWidth: 0.18 \n" \
52 "*cwThickness: 0.15 \n" \
53 "*cwCapSize: 0.4 \n" \
57 ".background: #000000\n" \
58 ".foreground: #00AA00\n" \
59 ".cwForeground: #FCA816\n" \
60 ".cwBackground: #943225\n" \
61 "*cwFont: " CWFONT "\n" \
62 "*geometry: =640x640\n" \
64 # if defined(HAVE_COCOA) || defined(HAVE_ANDROID)
65 # define CWFONT "Yearling 28, OCR A Std 24"
67 # define CWFONT "-*-helvetica-medium-r-normal-*-*-240-*-*-*-*-*-*"
71 # define release_logo 0
73 #define countof(x) (sizeof((x))/sizeof((*x)))
75 #undef DXF_OUTPUT_HACK
77 #ifdef DXF_OUTPUT_HACK /* When this is defined, instead of rendering
78 to the screen, we write a DXF CAD file to stdout.
79 This is a kludge of shocking magnitude...
80 Maybe there's some other way to intercept all
81 glVertex3f calls than with a #define? */
82 # define unit_tube dxf_unit_tube
83 # define unit_cone dxf_unit_cone
84 # define tube_1 dxf_tube_1
85 # define tube dxf_tube
86 # define cone dxf_cone
87 #endif /* DXF_OUTPUT_HACK */
89 #include "xlockmore.h"
94 #include "gltrackball.h"
98 #ifdef USE_GL /* whole file */
101 # include "dnapizza.h"
107 HELIX_IN, HELIX, HELIX_OUT,
108 PIZZA_IN, PIZZA, PIZZA_OUT,
111 CODEWORD_IN, CODEWORD, CODEWORD_OUT, CODEWORD_BLANK
117 GLfloat position; /* 0.0 - 1.0 */
118 GLfloat position_eased; /* 0.0 - 1.0, eased in and out */
119 GLfloat easement; /* portion of path that is eased. <= 0.5 */
120 GLfloat speed; /* how far along the path (may be negative) */
121 GLfloat probability; /* relative likelyhood to start spinning */
125 GLXContext *glx_context;
127 GLuint helix_list, helix_list_wire, helix_list_facetted;
128 GLuint pizza_list, pizza_list_wire, pizza_list_facetted;
129 GLuint gasket_list, gasket_list_wire;
130 GLuint frame_list, frame_list_wire;
139 GLfloat turn_spacing;
142 GLfloat wall_thickness;
143 GLfloat bar_thickness;
147 GLfloat gasket_depth;
148 GLfloat gasket_thickness;
152 GLfloat frame_thickness;
153 GLfloat triangle_size;
156 int codeword_facets, codeword_disc_facets;
157 GLfloat codeword_spread, codeword_line_width, codeword_thickness;
158 GLfloat codeword_cap_size;
159 const char *codeword_text;
160 char *codeword_text_out;
161 int *codeword_text_points;
163 int codeword_path_npoints;
164 int codeword_nguides;
165 XYZ *codeword_guides;
166 GLfloat codeword_color[4], codeword_bg[4];
167 texture_font_data *font;
172 glyph_mode anim_state;
175 spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz;
176 spinner scene_spinnerx, scene_spinnery; /* for DNA */
178 rotator *scene_rot; /* for Codeword */
180 spinner helix_spinnerz;
181 spinner pizza_spinnery, pizza_spinnerz;
182 spinner frame_spinner;
184 trackball_state *trackball;
187 int wire_overlay; /* frame countdown */
189 } logo_configuration;
191 static logo_configuration *dcs = NULL;
193 static XrmOptionDescRec opts[] = {
194 { "-speed", ".speed", XrmoptionSepArg, 0 },
195 { "-mode", ".mode", XrmoptionSepArg, 0 },
196 { "-pizza", ".mode", XrmoptionNoArg, "pizza" },
197 { "-helix", ".mode", XrmoptionNoArg, "helix" },
198 { "-both", ".mode", XrmoptionNoArg, "both" },
200 { "-codeword", ".mode", XrmoptionNoArg, "codeword" },
201 { "-cw", ".mode", XrmoptionNoArg, "codeword" },
202 { "-text", ".text", XrmoptionSepArg, 0 },
206 ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
208 #define PROBABILITY_SCALE 600
211 #ifdef DXF_OUTPUT_HACK
213 # define glBegin dxf_glBegin
214 # define glVertex3f dxf_glVertex3f
215 # define glVertex3dv dxf_glVertex3dv
216 # define glEnd dxf_glEnd
217 # define glVertexPointer dxf_glVertexPointer
218 # define glDrawArrays dxf_glDrawArrays
220 static int dxf_type, dxf_point, dxf_point_total, dxf_layer, dxf_color;
221 static GLfloat dxf_quads[4*4];
224 dxf_glBegin (int type)
232 dxf_glVertex3f (GLfloat ox, GLfloat oy, GLfloat oz)
238 /* Transform the point into modelview space. */
239 glGetFloatv (GL_MODELVIEW_MATRIX, m);
240 x = ox * m[0] + oy * m[4] + oz * m[8] + m[12];
241 y = ox * m[1] + oy * m[5] + oz * m[9] + m[13];
242 z = ox * m[2] + oy * m[6] + oz * m[10] + m[14];
244 dxf_quads[dxf_point*3+0] = x;
245 dxf_quads[dxf_point*3+1] = y;
246 dxf_quads[dxf_point*3+2] = z;
252 if (dxf_point < 4) return;
254 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
255 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
256 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
257 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
259 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
260 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
261 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
263 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
264 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
265 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
267 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]);
268 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
269 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
274 if (dxf_point < 4) return;
276 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
277 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
278 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
279 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
281 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
282 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
283 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
285 fprintf (stdout, "12\n%.6f\n", dxf_quads[i+3]); /* funky quad strip */
286 fprintf (stdout, "22\n%.6f\n", dxf_quads[i+4]); /* vert order: 1243. */
287 fprintf (stdout, "32\n%.6f\n", dxf_quads[i+5]);
289 fprintf (stdout, "13\n%.6f\n", dxf_quads[i]);
290 fprintf (stdout, "23\n%.6f\n", dxf_quads[i+1]);
291 fprintf (stdout, "33\n%.6f\n", dxf_quads[i+2]);
294 dxf_quads[0] = dxf_quads[6]; /* copy point 3 to pos 1 */
295 dxf_quads[1] = dxf_quads[7];
296 dxf_quads[2] = dxf_quads[8];
297 dxf_quads[3] = dxf_quads[9]; /* copy point 4 to pos 2 */
298 dxf_quads[4] = dxf_quads[10];
299 dxf_quads[5] = dxf_quads[11];
300 dxf_point = 2; /* leave those two points in queue */
304 case GL_TRIANGLE_FAN:
305 if (dxf_point < 3) return;
307 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
308 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
309 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
310 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
312 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
313 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
314 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
316 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
317 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
318 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
321 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
322 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
323 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
326 if (dxf_type == GL_TRIANGLE_FAN)
328 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to point 2 */
329 dxf_quads[4] = dxf_quads[7];
330 dxf_quads[5] = dxf_quads[8];
331 dxf_point = 2; /* leave two points in queue */
335 case GL_TRIANGLE_STRIP:
336 if (dxf_point < 3) return;
338 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
340 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
341 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
342 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
344 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
345 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
346 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
348 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
349 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
350 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
353 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
354 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
355 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
357 dxf_quads[0] = dxf_quads[3]; /* copy point 2 to pos 1 */
358 dxf_quads[1] = dxf_quads[4];
359 dxf_quads[2] = dxf_quads[5];
360 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to pos 2 */
361 dxf_quads[4] = dxf_quads[7];
362 dxf_quads[5] = dxf_quads[8];
363 dxf_point = 2; /* leave those two points in queue */
370 if (dxf_point_total == 1)
377 if (dxf_point < 2) return;
379 fprintf (stdout, "0\nLINE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
381 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
382 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
383 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
385 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
386 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
387 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
390 if (dxf_type != GL_LINES)
392 dxf_quads[0] = dxf_quads[3];
393 dxf_quads[1] = dxf_quads[4];
394 dxf_quads[2] = dxf_quads[5];
407 dxf_glVertex3dv (const GLdouble *v)
409 glVertex3f (v[0], v[1], v[2]);
416 if (dxf_type == GL_LINE_LOOP) /* close loop */
417 glVertex3f (dxf_quads[6], dxf_quads[7], dxf_quads[8]);
427 fprintf (stdout, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n");
428 fprintf (stdout, "0\nSECTION\n2\nENTITIES\n");
434 fprintf (stdout, "0\nENDSEC\n0\nEOF\n");
439 static const GLvoid *dxf_vp;
440 static GLsizei dxf_vp_size;
441 static GLsizei dxf_vp_stride;
444 dxf_glVertexPointer (GLint size, GLenum type, GLsizei stride,
445 const GLvoid *pointer)
447 if (type != GL_FLOAT) abort();
448 if (stride <= 0) abort();
451 dxf_vp_stride = stride;
455 dxf_glDrawArrays (GLenum mode, GLint first, GLsizei count)
458 unsigned char *a = (unsigned char *) dxf_vp;
460 for (i = first; i < first+count; i++)
462 GLfloat *fa = (GLfloat *) a;
463 dxf_glVertex3f (fa[0], fa[1], fa[2]);
470 # define XYZ tube_XYZ /* avoid conflict with normals.h */
471 # include "tube.c" /* Yes, I really am including a C file. */
473 # define XYZ sphere_XYZ
474 # define unit_sphere unit_sphere_dxf
475 # define unit_dome unit_dome_dxf
479 #endif /* DXF_OUTPUT_HACK */
483 /* Calculate the angle (in radians) between two vectors.
486 vector_angle (double ax, double ay, double az,
487 double bx, double by, double bz)
489 double La = sqrt (ax*ax + ay*ay + az*az);
490 double Lb = sqrt (bx*bx + by*by + bz*bz);
493 if (La == 0 || Lb == 0) return 0;
494 if (ax == bx && ay == by && az == bz) return 0;
496 /* dot product of two vectors is defined as:
497 La * Lb * cos(angle between vectors)
498 and is also defined as:
499 ax*bx + ay*by + az*bz
501 La * Lb * cos(angle) = ax*bx + ay*by + az*bz
502 cos(angle) = (ax*bx + ay*by + az*bz) / (La * Lb)
503 angle = acos ((ax*bx + ay*by + az*bz) / (La * Lb));
505 cc = (ax*bx + ay*by + az*bz) / (La * Lb);
506 if (cc > 1) cc = 1; /* avoid fp rounding error (1.000001 => sqrt error) */
518 GLfloat d = sqrt (p->x*p->x + p->y*p->y + p->z*p->z);
527 p->x = p->y = p->z = 0;
533 dot (const XYZ u, const XYZ v)
535 return (u.x * v.x) + (u.y * v.y) + (u.z * v.z);
545 make_helix (logo_configuration *dc, int facetted, int wire)
548 int wall_facets = dc->wall_facets / (facetted ? 10 : 1);
550 GLfloat max_th = M_PI * 2 * dc->turns;
551 GLfloat th_inc = M_PI * 2 / wall_facets;
553 GLfloat x1=0, y1=0, x2=0, y2=0;
554 GLfloat x1b=0, y1b=0, x2b=0, y2b=0;
557 GLfloat h1off=0, h2off=0;
558 GLfloat z_inc = dc->turn_spacing / wall_facets;
563 x1b = 1 - dc->wall_thickness;
566 z1 = -(dc->turn_spacing * dc->turns / 2);
568 h1 = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2);
569 h1off = (dc->wall_taper > 0 ? -dc->wall_height / 2 : 0);
572 z1 = -z1, z_inc = -z_inc, h1off = -h1off;
581 nx = cos (th + M_PI/2);
582 ny = sin (th + M_PI/2);
583 glNormal3f(nx, ny, 0);
584 glVertex3f( x1, y1, z1 - h1 + h1off);
585 glVertex3f( x1, y1, z1 + h1 + h1off);
586 glVertex3f(x1b, y1b, z1 + h1 + h1off);
587 glVertex3f(x1b, y1b, z1 - h1 + h1off);
592 while (th + th_inc <= max_th)
599 x2b = x2 * (1 - dc->wall_thickness);
600 y2b = y2 * (1 - dc->wall_thickness);
605 if (dc->wall_taper > 0)
608 if (th < dc->wall_taper)
610 h2 = dc->wall_height/2 * cos (M_PI / 2
611 * (1 - (th / dc->wall_taper)));
613 h2off = h2 - dc->wall_height/2;
615 h2off = dc->wall_height/2 - h2;
617 else if (th >= max_th - dc->wall_taper)
619 if (th + th_inc > max_th) /* edge case: always come to a point */
622 h2 = dc->wall_height/2 * cos (M_PI / 2
623 * (1 - ((max_th - th)
626 h2off = dc->wall_height/2 - h2;
628 h2off = h2 - dc->wall_height/2;
635 glBegin(wire ? GL_LINES : GL_QUADS);
636 glNormal3f(x1, y1, 0);
637 glVertex3f(x1, y1, z1 - h1 + h1off);
638 glVertex3f(x1, y1, z1 + h1 + h1off);
639 glNormal3f(x2, y2, 0);
640 glVertex3f(x2, y2, z2 + h2 + h2off);
641 glVertex3f(x2, y2, z2 - h2 + h2off);
648 glBegin(wire ? GL_LINES : GL_QUADS);
649 glNormal3f(-x1b, -y1b, 0);
650 glVertex3f( x1b, y1b, z1 - h1 + h1off);
651 glVertex3f( x1b, y1b, z1 + h1 + h1off);
652 glNormal3f(-x2b, -y2b, 0);
653 glVertex3f( x2b, y2b, z2 + h2 + h2off);
654 glVertex3f( x2b, y2b, z2 - h2 + h2off);
661 /* glNormal3f(0, 0, 1);*/
662 do_normal (x2, y2, z2 + h2 + h2off,
663 x2b, y2b, z2 + h2 + h2off,
664 x1b, y1b, z1 + h1 + h1off);
665 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
666 glVertex3f( x2, y2, z2 + h2 + h2off);
667 glVertex3f( x2b, y2b, z2 + h2 + h2off);
668 glVertex3f( x1b, y1b, z1 + h1 + h1off);
669 glVertex3f( x1, y1, z1 + h1 + h1off);
676 do_normal ( x1, y1, z1 - h1 + h1off,
677 x1b, y1b, z1 - h1 + h1off,
678 x2b, y2b, z2 - h2 + h2off);
679 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
680 glNormal3f(0, 0, -1);
681 glVertex3f( x1, y1, z1 - h1 + h1off);
682 glVertex3f( x1b, y1b, z1 - h1 + h1off);
683 glVertex3f( x2b, y2b, z2 - h2 + h2off);
684 glVertex3f( x2, y2, z2 - h2 + h2off);
704 nx = cos (th + M_PI/2);
705 ny = sin (th + M_PI/2);
706 glNormal3f(nx, ny, 0);
707 glVertex3f(x2, y2, z1 - h2 + h2off);
708 glVertex3f(x2, y2, z1 + h2 + h2off);
709 glVertex3f(x2b, y2b, z1 + h2 + h2off);
710 glVertex3f(x2b, y2b, z1 - h2 + h2off);
719 make_ladder (logo_configuration *dc, int facetted, int wire)
723 GLfloat max_th = dc->turns * M_PI * 2;
724 GLfloat max_z = dc->turns * dc->turn_spacing;
725 GLfloat z_inc = dc->bar_spacing;
726 GLfloat th_inc = M_PI * 2 * (dc->bar_spacing / dc->turn_spacing);
729 /* skip forward to center the bars in the helix... */
731 GLfloat usable_th = max_th - dc->wall_taper;
732 GLfloat usable_z = max_z / (max_th / usable_th);
733 int nbars = usable_z / dc->bar_spacing;
734 GLfloat used_z, pad_z, pad_ratio;
736 if (! (nbars & 1)) nbars--; /* always an odd number of bars */
738 used_z = (nbars - 1) * dc->bar_spacing;
739 pad_z = max_z - used_z;
740 pad_ratio = pad_z / max_z;
742 th = (max_th * pad_ratio/2);
743 z = -(max_z / 2) + (max_z * pad_ratio/2);
746 z = -z, z_inc = -z_inc;
749 for (i = 0; i < nbars; i++)
751 int facets = dc->bar_facets / (facetted ? 14 : 1);
752 if (facets <= 3) facets = 3;
753 x = cos (th) * (1 - dc->wall_thickness);
754 y = sin (th) * (1 - dc->wall_thickness);
755 polys += tube ( x, y, z,
757 dc->bar_thickness, 0, facets,
772 make_gasket (logo_configuration *dc, int wire)
780 GLfloat d2r = M_PI / 180;
782 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 2;
784 GLfloat *pointsx0, *pointsy0, *pointsx1, *pointsy1, *normals;
786 GLfloat r0 = 0.750; /* 395 */
787 GLfloat r1a = 0.825; /* bottom of wall below upper left hole */
788 GLfloat r1b = 0.867; /* center of upper left hole */
789 GLfloat r1c = 0.909; /* top of wall above hole */
790 GLfloat r1 = 0.916; /* 471 */
791 GLfloat r2 = 0.963; /* 490 */
792 GLfloat r3 = 0.960; /* 499 */
793 GLfloat r4 = 1.000; /* 507 */
794 GLfloat r5 = 1.080; /* 553 */
796 GLfloat ctrl_r[100], ctrl_th[100];
800 # ifdef DXF_OUTPUT_HACK
801 if (! wire) res *= 8;
804 # define POINT(r,th) \
805 ctrl_r [nctrls] = r, \
806 ctrl_th[nctrls] = (th * d2r), \
809 POINT (0.829, 0); /* top indentation, right half */
817 POINT (r4, 4.0); /* moving clockwise... */
838 POINT (r4, 316.8); /* upper left indentation */
839 POINT (0.990, 316.87);
840 POINT (0.880, 317.21);
841 POINT (0.872, 317.45);
842 POINT (0.869, 317.80);
843 POINT (0.867, 318.10);
845 POINT (0.867, 318.85);
846 POINT (0.869, 319.15);
847 POINT (0.872, 319.50);
848 POINT (0.880, 319.74);
849 POINT (0.990, 320.08);
854 POINT (r1a, 338.0); /* cut-out disc */
860 POINT (0.872, 356.05); /* top indentation, left half */
861 POINT (0.862, 356.19);
862 POINT (0.851, 356.70);
863 POINT (0.841, 357.35);
864 POINT (0.835, 358.19);
865 POINT (0.831, 359.15);
869 points_size = res + (nctrls * 2);
870 pointsx0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
871 pointsy0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
872 pointsx1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
873 pointsy1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
874 normals = (GLfloat *) malloc (points_size * sizeof(GLfloat) * 2);
877 for (i = 1; i < nctrls; i++)
879 GLfloat from_r = ctrl_r [i-1];
880 GLfloat from_th = ctrl_th[i-1];
881 GLfloat to_r = ctrl_r [i];
882 GLfloat to_th = ctrl_th[i];
884 GLfloat step = 2*M_PI / res;
885 int nsteps = 1 + ((to_th - from_th) / step);
888 for (j = 0; j < nsteps + (i == nctrls-1); j++)
890 GLfloat r = from_r + (j * (to_r - from_r) / nsteps);
891 GLfloat th = from_th + (j * (to_th - from_th) / nsteps);
893 GLfloat cth = cos(th) * dc->gasket_size;
894 GLfloat sth = sin(th) * dc->gasket_size;
896 pointsx0[npoints] = r0 * cth; /* inner ring */
897 pointsy0[npoints] = r0 * sth;
898 pointsx1[npoints] = r * cth; /* outer ring */
899 pointsy1[npoints] = r * sth;
902 if (npoints >= points_size) abort();
906 /* normals for the outer ring */
907 for (i = 1; i < npoints; i++)
918 n = calc_normal (a, b, c);
919 normals[(i-1)*2 ] = n.x;
920 normals[(i-1)*2+1] = n.y;
923 glRotatef(-90, 0, 1, 0);
924 glRotatef(180, 0, 0, 1);
929 for (z = -thick2; z <= thick2; z += thick2*2)
933 glBegin (GL_LINE_LOOP);
934 for (i = 0; i < npoints; i++)
935 glVertex3f (pointsx0[i], pointsy0[i], z);
940 glBegin (GL_LINE_LOOP);
941 for (i = 0; i < npoints; i++)
942 glVertex3f (pointsx1[i], pointsy1[i], z);
946 for (i = 1; i < npoints; i++)
948 glBegin (GL_LINE_STRIP);
949 glVertex3f (pointsx0[i-1], pointsy0[i-1], z);
950 glVertex3f (pointsx0[i ], pointsy0[i ], z);
951 glVertex3f (pointsx1[i ], pointsy1[i ], z);
952 glVertex3f (pointsx1[i-1], pointsy1[i-1], z);
960 for (i = 0; i < npoints; i++)
963 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
964 glVertex3f (pointsx0[i], pointsy0[i], thick2);
966 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
967 glVertex3f (pointsx1[i], pointsy1[i], thick2);
977 glNormal3f(0, 0, -1);
978 glBegin (GL_QUAD_STRIP);
979 for (i = 0; i < npoints; i++)
981 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
982 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
990 glBegin (GL_QUAD_STRIP);
991 for (i = 0; i < npoints; i++)
993 glVertex3f (pointsx0[i], pointsy0[i], thick2);
994 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1001 glBegin (GL_QUAD_STRIP);
1002 for (i = 0; i < npoints; i++)
1004 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
1005 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
1006 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
1012 glFrontFace(GL_CCW);
1015 for (i = 0; i < npoints-1; i++)
1017 int ia = (i == 0 ? npoints-2 : i-1);
1018 int iz = (i == npoints-2 ? 0 : i+1);
1019 GLfloat x = pointsx1[i];
1020 GLfloat y = pointsy1[i];
1021 GLfloat xz = pointsx1[iz];
1022 GLfloat yz = pointsy1[iz];
1024 GLfloat nxa = normals[ia*2]; /* normal of [i-1 - i] face */
1025 GLfloat nya = normals[ia*2+1];
1026 GLfloat nx = normals[i*2]; /* normal of [i - i+1] face */
1027 GLfloat ny = normals[i*2+1];
1028 GLfloat nxz = normals[iz*2]; /* normal of [i+1 - i+2] face */
1029 GLfloat nyz = normals[iz*2+1];
1031 GLfloat anglea = vector_angle (nx, ny, 0, nxa, nya, 0);
1032 GLfloat anglez = vector_angle (nx, ny, 0, nxz, nyz, 0);
1033 GLfloat pointy = 0.6;
1035 if (anglea > pointy)
1037 glNormal3f (nx, ny, 0);
1038 glVertex3f (x, y, thick2);
1039 glVertex3f (x, y, -thick2);
1043 glNormal3f ((nxa + nx) / 2, (nya + ny) / 2, 0);
1044 glVertex3f (x, y, thick2);
1045 glVertex3f (x, y, -thick2);
1048 if (anglez > pointy)
1050 glNormal3f (nx, ny, 0);
1051 glVertex3f (xz, yz, -thick2);
1052 glVertex3f (xz, yz, thick2);
1056 glNormal3f ((nx + nxz) / 2, (ny + nyz) / 2, 0);
1057 glVertex3f (xz, yz, -thick2);
1058 glVertex3f (xz, yz, thick2);
1066 /* Fill in the upper left hole...
1073 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
1074 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
1076 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
1077 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
1081 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
1082 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
1084 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
1085 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
1090 glNormal3f (0, 0, -1);
1092 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1093 glVertex3f (pointsx0[0], pointsy0[0], -thick2);
1094 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1095 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1096 glVertex3f (pointsx0[2], pointsy0[2], -thick2);
1101 glNormal3f (0, 0, 1);
1102 glFrontFace(GL_CCW);
1103 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1104 glVertex3f (pointsx0[0], pointsy0[0], thick2);
1105 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1106 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1107 glVertex3f (pointsx0[2], pointsy0[2], thick2);
1114 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1115 glNormal3f (pointsx0[1], pointsy0[1], 0);
1116 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1117 glNormal3f (pointsx0[3], pointsy0[3], 0);
1118 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1119 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1120 glNormal3f (pointsx0[1], pointsy0[1], 0);
1121 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1126 /* Now make a donut.
1129 int nsteps = (wire ? 12 : 64);
1132 GLfloat th, cth, sth;
1136 th = ((339.0 + 343.0) / 2) * d2r;
1138 glTranslatef (r1b * cos(th) * dc->gasket_size,
1139 r1b * sin(th) * dc->gasket_size,
1143 for (i = 0; i < nsteps; i++)
1145 th = 2 * M_PI * i / nsteps;
1146 cth = cos (th) * dc->gasket_size;
1147 sth = sin (th) * dc->gasket_size;
1148 pointsx0[npoints] = r0 * cth;
1149 pointsy0[npoints] = r0 * sth;
1150 pointsx1[npoints] = r1 * cth;
1151 pointsy1[npoints] = r1 * sth;
1156 pointsx0[npoints] = pointsx0[0];
1157 pointsy0[npoints] = pointsy0[0];
1158 pointsx1[npoints] = pointsx1[0];
1159 pointsy1[npoints] = pointsy1[0];
1164 glBegin (GL_LINE_LOOP);
1165 for (i = 0; i < npoints; i++)
1166 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1169 glBegin (GL_LINE_LOOP);
1170 for (i = 0; i < npoints; i++)
1171 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1175 glBegin (GL_LINE_LOOP);
1176 for (i = 0; i < npoints; i++)
1177 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1180 glBegin (GL_LINE_LOOP);
1181 for (i = 0; i < npoints; i++)
1182 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1191 glNormal3f(0, 0, -1);
1192 glBegin (GL_QUAD_STRIP);
1193 for (i = 0; i < npoints; i++)
1195 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1196 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1202 glFrontFace(GL_CCW);
1203 glNormal3f(0, 0, 1);
1204 glBegin (GL_QUAD_STRIP);
1205 for (i = 0; i < npoints; i++)
1207 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1208 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1216 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1217 for (i = 0; i < npoints; i++)
1219 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
1220 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
1221 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
1231 /* Attach the bottom-right dingus...
1238 glRotatef (49.5, 0, 0, 1);
1239 glScalef (dc->gasket_size, dc->gasket_size, 1);
1240 glTranslatef (0, (r0+r1)/2, 0);
1245 glFrontFace(GL_CCW);
1246 glBegin (wire ? GL_LINE_STRIP : GL_QUADS);
1247 glNormal3f (0, 0, -1);
1248 glVertex3f (-w/2, -h/2, -thick2); glVertex3f (-w/2, h/2, -thick2);
1249 glVertex3f ( w/2, h/2, -thick2); glVertex3f ( w/2, -h/2, -thick2);
1250 glNormal3f (1, 0, 0);
1251 glVertex3f ( w/2, -h/2, -thick2); glVertex3f ( w/2, h/2, -thick2);
1252 glVertex3f ( w/2, h/2, thick2); glVertex3f ( w/2, -h/2, thick2);
1253 glNormal3f (0, 0, 1);
1254 glVertex3f ( w/2, -h/2, thick2); glVertex3f ( w/2, h/2, thick2);
1255 glVertex3f (-w/2, h/2, thick2); glVertex3f (-w/2, -h/2, thick2);
1256 glNormal3f (-1, 0, 0);
1257 glVertex3f (-w/2, -h/2, thick2); glVertex3f (-w/2, h/2, thick2);
1258 glVertex3f (-w/2, h/2, -thick2); glVertex3f (-w/2, -h/2, -thick2);
1264 for (th = (wire ? 0 : -0.1);
1266 th += (M_PI / (wire ? 5 : 32)))
1268 pointsx0[npoints] = w/2 * cos(th);
1269 pointsy0[npoints] = w/2 * sin(th);
1274 /* front inside curve */
1275 glNormal3f (0, 0, -1);
1277 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1278 if (! wire) glVertex3f (0, h/2, -thick2);
1279 for (i = 0; i < npoints; i++)
1280 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1284 /* front outside curve */
1285 glFrontFace(GL_CCW);
1286 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1287 if (! wire) glVertex3f (0, -h/2, -thick2);
1288 for (i = 0; i < npoints; i++)
1289 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1293 /* back inside curve */
1294 glNormal3f (0, 0, 1);
1295 glFrontFace(GL_CCW);
1296 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1297 if (! wire) glVertex3f (0, h/2, thick2);
1298 for (i = 0; i < npoints; i++)
1299 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1303 /* back outside curve */
1305 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1306 if (! wire) glVertex3f (0, -h/2, thick2);
1307 for (i = 0; i < npoints; i++)
1308 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1313 glFrontFace(GL_CCW);
1314 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1315 for (i = 0; i < npoints; i++)
1317 glNormal3f (pointsx0[i], pointsy0[i], 0);
1318 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1319 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1326 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1327 for (i = 0; i < npoints; i++)
1329 glNormal3f (pointsx0[i], -pointsy0[i], 0);
1330 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1331 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1348 make_frame (logo_configuration *dc, int wire)
1352 GLfloat x[20], y[20];
1353 GLfloat corner_cut = 0.5;
1356 glRotatef (90, 0, 1, 0);
1357 glScalef (4 * dc->frame_size,
1359 4 * dc->frame_size);
1361 x[0] = -dc->frame_thickness;
1362 x[1] = -dc->frame_thickness * corner_cut;
1364 x[3] = 0.5 - dc->triangle_size;
1366 x[5] = 0.5 + dc->triangle_size;
1368 x[7] = 1 + dc->frame_thickness * corner_cut;
1369 x[8] = 1 + dc->frame_thickness;
1371 y[0] = -dc->frame_thickness;
1372 y[1] = -dc->frame_thickness * corner_cut;
1374 y[3] = dc->triangle_size;
1378 glTranslatef (-0.5, -0.5, dc->frame_depth / 4);
1380 for (j = 0; j <= 1; j++)
1382 if (j) glTranslatef (0, 0, -dc->frame_depth / 2);
1383 glFrontFace (j ? GL_CCW : GL_CW);
1384 for (i = 0; i < 4; i++)
1386 glNormal3f (0, 0, (j ? -1 : 1));
1387 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1388 glVertex3f (x[0], y[1], 0); glVertex3f (x[0], y[2], 0);
1389 glVertex3f (x[1], y[0], 0); glVertex3f (x[1], y[2], 0);
1390 glVertex3f (x[3], y[0], 0); glVertex3f (x[3], y[2], 0);
1391 glVertex3f (x[4], y[0], 0); glVertex3f (x[4], y[3], 0);
1392 glVertex3f (x[5], y[0], 0); glVertex3f (x[5], y[2], 0);
1393 glVertex3f (x[7], y[0], 0); glVertex3f (x[7], y[2], 0);
1394 glVertex3f (x[8], y[1], 0); glVertex3f (x[8], y[2], 0);
1397 glTranslatef (0.5, 0.5, 0);
1398 glRotatef (90, 0, 0, 1);
1399 glTranslatef (-0.5, -0.5, 0);
1405 glFrontFace (GL_CCW);
1406 for (i = 0; i < 4; i++)
1408 glNormal3f (0, 1, 0);
1409 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1410 glVertex3f (x[2], y[2], 0); glVertex3f (x[2], y[2], dc->frame_depth/2);
1411 glVertex3f (x[3], y[2], 0); glVertex3f (x[3], y[2], dc->frame_depth/2);
1412 glVertex3f (x[4], y[3], 0); glVertex3f (x[4], y[3], dc->frame_depth/2);
1413 glVertex3f (x[5], y[2], 0); glVertex3f (x[5], y[2], dc->frame_depth/2);
1414 glVertex3f (x[6], y[2], 0); glVertex3f (x[6], y[2], dc->frame_depth/2);
1418 glNormal3f (0, -1, 0);
1419 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1420 glVertex3f (x[7], y[0], 0);
1421 glVertex3f (x[7], y[0], dc->frame_depth/2);
1422 glVertex3f (x[1], y[0], dc->frame_depth/2);
1423 glVertex3f (x[1], y[0], 0);
1427 glNormal3f (1, -1, 0);
1428 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1429 glVertex3f (x[8], y[1], 0);
1430 glVertex3f (x[8], y[1], dc->frame_depth/2);
1431 glVertex3f (x[7], y[0], dc->frame_depth/2);
1432 glVertex3f (x[7], y[0], 0);
1438 glNormal3f (0, 1, 0);
1439 for (j = 0; j <= 1; j++)
1441 glBegin (GL_LINE_STRIP);
1442 glVertex3f (x[2], y[2], j*dc->frame_depth/2);
1443 glVertex3f (x[3], y[2], j*dc->frame_depth/2);
1444 glVertex3f (x[4], y[3], j*dc->frame_depth/2);
1445 glVertex3f (x[5], y[2], j*dc->frame_depth/2);
1446 glVertex3f (x[6], y[2], j*dc->frame_depth/2);
1452 glTranslatef (0.5, 0.5, 0);
1453 glRotatef (90, 0, 0, 1);
1454 glTranslatef (-0.5, -0.5, 0);
1474 tess_error_cb (GLenum errorCode)
1476 fprintf (stderr, "%s: tesselation error: %s\n",
1477 progname, gluErrorString(errorCode));
1482 tess_combine_cb (GLdouble coords[3], GLdouble *d[4], GLfloat w[4],
1483 GLdouble **data_out)
1485 GLdouble *new = (GLdouble *) malloc (3 * sizeof(*new));
1495 tess_vertex_cb (void *vertex_data, void *closure)
1497 tess_out *to = (tess_out *) closure;
1498 GLdouble *v = (GLdouble *) vertex_data;
1499 to->points[to->i++] = v[0];
1500 to->points[to->i++] = v[1];
1501 to->points[to->i++] = v[2];
1506 tess_begin_cb (GLenum which)
1517 #endif /* HAVE_TESS */
1521 make_pizza (logo_configuration *dc, int facetted, int wire)
1524 int topfaces = (facetted ? 48 : 120);
1525 int discfaces = (facetted ? 12 : 120);
1526 int npoints = topfaces * 2 + 100;
1527 GLdouble *points = (GLdouble *) calloc (npoints * 3, sizeof(GLdouble));
1529 GLdouble *holes = (GLdouble *) calloc (topfaces*nholes*3, sizeof(GLdouble));
1531 GLfloat step = M_PI * 2 / 6 / topfaces;
1532 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 4;
1533 GLfloat th, x, y, s;
1538 tess_out TO, *to = &TO;
1539 GLUtesselator *tess = gluNewTess();
1541 to->points = (GLdouble *) calloc (topfaces * 20, sizeof(GLdouble));
1544 # ifndef _GLUfuncptr
1545 # define _GLUfuncptr void(*)(void)
1548 gluTessCallback(tess,GLU_TESS_BEGIN, (_GLUfuncptr)tess_begin_cb);
1549 gluTessCallback(tess,GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv);
1550 gluTessCallback(tess,GLU_TESS_END, (_GLUfuncptr)tess_end_cb);
1551 gluTessCallback(tess,GLU_TESS_COMBINE, (_GLUfuncptr)tess_combine_cb);
1552 gluTessCallback(tess,GLU_TESS_ERROR, (_GLUfuncptr)tess_error_cb);
1554 gluTessProperty (tess, GLU_TESS_BOUNDARY_ONLY, wire);
1555 gluTessProperty (tess,GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
1557 # endif /* HAVE_TESS */
1562 glRotatef (180, 0, 0, 1);
1564 glRotatef (90, 0, 1, 0);
1565 glTranslatef (-0.53, 0, 0);
1566 glRotatef (-30, 0, 0, 1);
1568 /* Compute the wedge */
1581 for (i = 0; i < countof(edge)/2; i++)
1583 points[j++] = edge[i*2+1];
1584 points[j++] = edge[i*2];
1589 s = 0.798; /* radius of end of slice, before crust gap */
1590 for (i = 0; i < topfaces; i++)
1592 points[j++] = cos(th) * s;
1593 points[j++] = sin(th) * s;
1610 for (i = 0; i < countof(edge)/2; i++)
1612 points[j++] = edge[i*2+1];
1613 points[j++] = edge[i*2];
1620 /* Draw the rim of the slice */
1621 glBegin (wire ? GL_LINES : GL_QUADS);
1624 for (i = (wire ? 0 : 1); i < endpoints; i++)
1626 GLdouble *p = points + (i*3);
1628 do_normal (p[0], p[1], -thick2,
1633 glVertex3f (x, y, -thick2);
1634 glVertex3f (x, y, thick2);
1636 glVertex3f (p[0], p[1], thick2);
1637 glVertex3f (p[0], p[1], -thick2);
1643 do_normal (points[0], points[1], -thick2,
1644 points[0], points[1], thick2,
1646 glVertex3f (x, y, -thick2);
1647 glVertex3f (x, y, thick2);
1648 glVertex3f (points[0], points[1], thick2);
1649 glVertex3f (points[0], points[1], -thick2);
1656 /* Outline of slice */
1657 glBegin (GL_LINE_LOOP);
1658 for (i = 0; i < endpoints; i++)
1659 glVertex3f (points[i*3], points[i*3+1], -thick2);
1661 glBegin (GL_LINE_LOOP);
1662 for (i = 0; i < endpoints; i++)
1663 glVertex3f (points[i*3], points[i*3+1], thick2);
1666 # endif /* HAVE_TESS */
1668 /* Compute the holes */
1669 step = M_PI * 2 / discfaces;
1670 for (k = 0; k < nholes; k++)
1672 GLdouble *p = holes + (discfaces * 3 * k);
1676 case 0: x = 0.34; y = 0.17; s = 0.05; break;
1677 case 1: x = 0.54; y = 0.17; s = 0.06; break;
1678 case 2: x = 0.55; y = 0.36; s = 0.06; break;
1679 default: abort(); break;
1681 for (i = 0; i < discfaces; i++)
1683 p[j++] = x + cos(M_PI*2 - th) * s;
1684 p[j++] = y + sin(M_PI*2 - th) * s;
1691 /* Draw the inside rim of the holes */
1692 for (k = 0; k < nholes; k++)
1694 GLdouble *p = holes + (discfaces * 3 * k);
1696 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1697 for (i = 0; i < discfaces; i++)
1699 GLdouble *p2 = p + (i*3);
1701 do_normal (p2[0], p2[1], -thick2,
1702 p2[0], p2[1], thick2,
1703 p2[-3], p2[-2], thick2);
1704 glVertex3f (p2[0], p2[1], -thick2);
1705 glVertex3f (p2[0], p2[1], thick2);
1708 glVertex3f (p[0], p[1], -thick2);
1709 glVertex3f (p[0], p[1], thick2);
1715 /* Outline of holes */
1716 glBegin (GL_LINE_LOOP);
1717 for (i = 0; i < discfaces; i++)
1718 glVertex3f (p[i*3], p[i*3+1], -thick2);
1720 glBegin (GL_LINE_LOOP);
1721 for (i = 0; i < discfaces; i++)
1722 glVertex3f (p[i*3], p[i*3+1], thick2);
1725 # endif /* !HAVE_TESS */
1729 glTranslatef (0, 0, -thick2);
1730 for (y = 0; y <= 1; y++)
1732 if (y) glTranslatef (0, 0, thick2*2);
1734 /* A non-convex polygon */
1735 gluTessBeginPolygon (tess, to);
1737 glNormal3f (0, 0, (y > 0 ? 1 : -1));
1738 gluTessNormal (tess, 0, 0, (y > 0 ? 1 : -1));
1739 glFrontFace (GL_CCW);
1741 /* Tess the wedge */
1742 gluTessBeginContour (tess);
1743 for (i = 0; i < endpoints; i++)
1745 GLdouble *p = points + (i*3);
1746 gluTessVertex (tess, p, p);
1749 gluTessVertex (tess, points, points);
1750 gluTessEndContour (tess);
1752 /* Tess the holes */
1753 for (k = 0; k < nholes; k++)
1755 GLdouble *p = holes + (discfaces * 3 * k);
1756 gluTessBeginContour (tess);
1757 for (i = 0; i < discfaces; i++)
1759 GLdouble *p2 = p + (i*3);
1760 gluTessVertex (tess, p2, p2);
1763 gluTessEndContour (tess);
1766 gluTessEndPolygon (tess);
1769 glTranslatef (0, 0, -thick2);
1771 # else /* !HAVE_TESS */
1774 glTranslatef(0, 0, thick2);
1775 glNormal3f (0, 0, 1);
1776 glFrontFace (GL_CW);
1778 /* Sadly, jwzgl's glVertexPointer seems not to be recordable inside
1781 glDisableClientState (GL_COLOR_ARRAY);
1782 glDisableClientState (GL_NORMAL_ARRAY);
1783 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1784 glEnableClientState (GL_VERTEX_ARRAY);
1785 glVertexPointer (3, GL_FLOAT, 0, dnapizza_triangles);
1786 glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
1788 glBegin (GL_TRIANGLES);
1789 for (i = 0; i < countof (dnapizza_triangles); i += 3)
1790 glVertex3fv (dnapizza_triangles + i);
1794 glTranslatef(0, 0, -thick2*2);
1795 glNormal3f (0, 0, -1);
1796 glFrontFace (GL_CCW);
1799 glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
1802 glBegin (GL_TRIANGLES);
1803 for (i = 0; i < countof (dnapizza_triangles); i += 3)
1804 glVertex3fv (dnapizza_triangles + i);
1808 glTranslatef(0, 0, thick2);
1810 # endif /* !HAVE_TESS */
1813 /* Compute the crust */
1815 s = 0.861; /* radius of inside of crust */
1816 step = M_PI * 2 / 6 / topfaces;
1819 for (i = 0; i < topfaces; i++)
1821 points[j++] = cos(th) * s;
1822 points[j++] = sin(th) * s;
1828 for (i = 0; i < topfaces; i++)
1830 points[j++] = cos(th) * s;
1831 points[j++] = sin(th) * s;
1836 /* Draw the rim of the crust */
1837 glFrontFace (GL_CCW);
1838 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1839 for (i = 0; i < topfaces * 2; i++)
1841 GLdouble *p = points + (i*3);
1842 if (i == 0 || i == (topfaces*2)-1)
1843 glNormal3f (0, -1, 0);
1844 else if (i == topfaces-1 || i == topfaces)
1845 glNormal3f (0, 1, 0);
1847 do_normal (p[-3], p[-2], thick2,
1849 p[0], p[1], -thick2);
1850 glVertex3f (p[0], p[1], -thick2);
1851 glVertex3f (p[0], p[1], thick2);
1854 glVertex3f (points[0], points[1], -thick2);
1855 glVertex3f (points[0], points[1], thick2);
1861 glBegin (GL_LINE_STRIP);
1862 for (i = 0; i < topfaces * 2; i++)
1864 GLdouble *p = points + (i*3);
1865 glVertex3f (p[0], p[1], -thick2);
1868 glVertex3f (points[0], points[1], -thick2);
1871 glBegin (GL_LINE_STRIP);
1872 for (i = 0; i < topfaces * 2; i++)
1874 GLdouble *p = points + (i*3);
1875 glVertex3f (p[0], p[1], thick2);
1878 glVertex3f (points[0], points[1], thick2);
1882 /* Draw the top of the crust */
1885 glFrontFace (GL_CW);
1886 glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP);
1887 glNormal3f (0, 0, -1);
1889 for (i = 0; i < topfaces; i++)
1891 int ii = topfaces + (topfaces - i - 1);
1892 GLdouble *p1 = points + (i*3);
1893 GLdouble *p2 = points + (ii*3);
1894 glVertex3f (p1[0], p1[1], -thick2);
1895 glVertex3f (p2[0], p2[1], -thick2);
1901 /* Draw the bottom of the crust */
1902 glFrontFace (GL_CCW);
1903 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1904 glNormal3f (0, 0, 1);
1905 for (i = 0; i < topfaces; i++)
1907 int ii = topfaces + (topfaces - i - 1);
1908 GLdouble *p1 = points + (i*3);
1909 GLdouble *p2 = points + (ii*3);
1910 glVertex3f (p1[0], p1[1], thick2);
1911 glVertex3f (p2[0], p2[1], thick2);
1919 gluDeleteTess (tess);
1921 # endif /* HAVE_TESS */
1934 /* Upcase string, convert Unicrud to ASCII, remove any non-letters.
1937 codeword_simplify_text (const char *s0)
1939 char *s1 = utf8_to_latin1 ((s0 ? s0 : ""), True);
1941 char *s2 = (char *) malloc (L + 10);
1944 for (i = 0; i < L; i++)
1947 if (c >= 'a' && c <= 'z')
1949 if (c >= 'A' && c <= 'Z')
1954 strcpy (s2, "CODEWORD");
1960 make_codeword_path (ModeInfo *mi)
1962 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
1963 int letters = strlen (dc->codeword_text);
1965 GLfloat rtick = dc->codeword_spread;
1966 GLfloat iradius = rtick * dc->codeword_cap_size;
1972 GLfloat inner_circum = M_PI * 2 * (iradius + rtick * 2);
1973 GLfloat outer_circum = M_PI * 2 * (iradius + rtick * (letters + 1));
1974 GLfloat facet_length = inner_circum / (26 * dc->codeword_facets);
1975 int outer_facets = ceil (outer_circum / facet_length);
1977 int *histo = (int *) calloc (letters * 26, sizeof(*histo));
1978 XYZ *points = (XYZ *) calloc (letters * outer_facets, sizeof (*points));
1981 for (letter = -1; letter < letters; letter++)
1983 if (letter == -1) /* Inner starting point */
1985 points[npoints].x = iradius;
1986 points[npoints].y = 0;
1990 else /* Add arc for this letter */
1992 int direction = (letter & 1 ? -1 : 1);
1993 int v = (dc->codeword_text[letter] - 'A' + 1);
1994 int dial1 = dial + v * direction;
1997 GLfloat th0 = M_PI * 2 / 26 * dial;
1998 GLfloat th1 = M_PI * 2 / 26 * dial1;
1999 GLfloat r = iradius + rtick * (letter + 2);
2000 GLfloat circum = M_PI * 2 * r;
2001 GLfloat arc_length = circum * v / 26;
2002 int arc_facets = ceil (fabs (arc_length / facet_length));
2003 GLfloat facet_th = (th1 - th0) / arc_facets;
2005 if (arc_facets > outer_facets) abort();
2007 /* Let's put some intermediate facets on the crossbars too,
2008 so that the animation doesn't speed up on those. */
2011 for (rr = last_r + facet_length;
2012 rr <= r - facet_length;
2015 points[npoints].x = rr * cos (th0);
2016 points[npoints].y = rr * sin (th0);
2025 ? th <= th1 + facet_th
2026 : th >= th1 + facet_th);
2030 if (th0 < th1 && th > th1)
2032 if (th0 > th1 && th < th1)
2034 points[npoints].x = r * cos (th2);
2035 points[npoints].y = r * sin (th2);
2037 /* Ugh, add point only if it differs from prev.
2038 Not sure how this happens. */
2040 points[npoints-1].x != points[npoints].x ||
2041 points[npoints-1].y != points[npoints].y)
2045 /* Mark up the histo array to find the outer border. */
2054 int x = (i + 26) % 26;
2056 for (y = 0; y <= letter; y++)
2057 histo[y * 26 + x]++;
2061 dc->codeword_text_points[letter] = npoints;
2067 if (npoints >= letters * outer_facets) abort();
2072 for (y = 0; y < letters; y++)
2074 fprintf (stderr, "%2d: ", y);
2075 for (x = 0; x < 26; x++)
2076 fprintf (stderr, "%x", histo[y * 26 + x]);
2077 fprintf (stderr, "\n");
2079 fprintf (stderr, "\n");
2084 /* Find a gap in the outer edge, to draw guide dots. */
2087 int last_row = letters;
2088 int start_dial = -1, end_dial = -1;
2090 for (y = letters-1; y >= 0; y--)
2092 for (x = 0; x < 26; x++)
2094 if (histo[y * 26 + x] == 0)
2097 start_dial = end_dial = -1;
2099 if (start_dial == -1)
2106 if (last_row < letters-1 && start_dial >= 0)
2108 GLfloat r = iradius + rtick * (last_row + 2);
2111 dc->codeword_nguides = 0;
2112 dc->codeword_guides = (XYZ *)
2113 calloc (end_dial - start_dial + 1, sizeof (*dc->codeword_guides));
2114 for (i = start_dial; i <= end_dial; i++)
2116 GLfloat th = i * M_PI * 2 / 26;
2117 GLfloat x = r * cos (th);
2118 GLfloat y = r * sin (th);
2119 dc->codeword_guides[dc->codeword_nguides].x = x;
2120 dc->codeword_guides[dc->codeword_nguides].y = y;
2121 dc->codeword_nguides++;
2128 dc->codeword_path_npoints = npoints;
2129 dc->codeword_path = points;
2134 draw_codeword_cap (ModeInfo *mi)
2136 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2137 int wire = MI_IS_WIREFRAME(mi);
2140 int segments = dc->codeword_disc_facets;
2141 GLfloat size = dc->codeword_spread * dc->codeword_cap_size;
2142 GLfloat width = dc->codeword_line_width / 2;
2143 GLfloat thick = dc->codeword_thickness / 2;
2144 GLfloat r1 = size + width/2;
2145 GLfloat r2 = size - width/2;
2146 GLfloat facet, th, z;
2148 if (wire) segments = 12;
2149 facet = M_PI * 2 / segments;
2153 /* Top and bottom */
2155 for (z = -thick; z <= thick; z += thick*2)
2157 glNormal3f (0, 0, (z < 0 ? -1 : 1));
2158 glFrontFace (z < 0 ? GL_CCW : GL_CW);
2160 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
2161 for (th = 0; th <= M_PI*2; th += facet)
2163 GLfloat x = cos (th);
2164 GLfloat y = sin (th);
2165 glVertex3f (r1 * x, r1 * y, z);
2166 glVertex3f (r2 * x, r2 * y, z);
2172 glBegin (GL_LINE_LOOP);
2173 for (th = 0; th <= M_PI*2; th += facet)
2175 GLfloat x = cos (th);
2176 GLfloat y = sin (th);
2177 glVertex3f (r1 * x, r1 * y, z);
2180 glBegin (GL_LINE_LOOP);
2181 for (th = 0; th <= M_PI*2; th += facet)
2183 GLfloat x = cos (th);
2184 GLfloat y = sin (th);
2185 glVertex3f (r2 * x, r2 * y, z);
2191 /* Inside and outside */
2193 for (z = -1; z <= 1; z += 2)
2195 glFrontFace (z < 0 ? GL_CCW : GL_CW);
2197 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
2198 for (th = 0; th <= M_PI*2; th += facet)
2200 GLfloat th1 = th + facet;
2201 GLfloat x0 = cos (th);
2202 GLfloat y0 = sin (th);
2203 GLfloat x1 = cos (th1);
2204 GLfloat y1 = sin (th1);
2205 GLfloat r = z < 0 ? r1 : r2;
2208 do_normal (r * x0, r * y0, thick,
2209 r * x0, r * y0, -thick,
2210 r * x1, r * y1, -thick);
2212 do_normal (r * x1, r * y1, thick,
2213 r * x1, r * y1, -thick,
2214 r * x0, r * y0, -thick);
2216 glVertex3f (r * x0, r * y0, thick);
2217 glVertex3f (r * x0, r * y0, -thick);
2229 draw_codeword_guides (ModeInfo *mi, GLfloat anim_ratio)
2231 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2232 int wire = MI_IS_WIREFRAME(mi);
2235 int segments = dc->codeword_disc_facets;
2236 GLfloat s = dc->codeword_line_width / 2;
2237 GLfloat each = 1.0 / dc->codeword_nguides;
2240 if (wire) segments = 6;
2242 for (i = 0; i < dc->codeword_nguides; i++)
2245 if (anim_ratio < i*each) ratio = 0;
2246 else if (anim_ratio >= (i+1)*each) ratio = 1;
2247 else ratio = (anim_ratio - i*each) / each;
2249 if (ratio <= 0) continue;
2250 if (ratio == 0) ratio = 0.001;
2253 glTranslatef (dc->codeword_guides[i].x,
2254 dc->codeword_guides[i].y,
2255 dc->codeword_guides[i].z);
2257 glScalef (ratio, ratio, ratio);
2259 /* If the line width and thickness are pretty close to each other,
2260 use spheres. Otherwise use tubes.
2262 if (dc->codeword_thickness < dc->codeword_line_width * 1.3 &&
2263 dc->codeword_thickness > dc->codeword_line_width / 1.3)
2266 glFrontFace (GL_CCW);
2267 polys += unit_sphere (segments, segments, wire);
2271 polys += tube (0, 0, -dc->codeword_thickness / 2,
2272 0, 0, dc->codeword_thickness / 2,
2273 s, 0, segments, True, True, wire);
2283 /* Compute the characters at which the cursor is currently pointing,
2284 and render it on the logo.
2287 codeword_text_output (ModeInfo *mi, GLfloat anim_ratio)
2289 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2291 int L = strlen (dc->codeword_text);
2292 int point = dc->codeword_path_npoints * anim_ratio;
2295 if (dc->anim_state == CODEWORD_BLANK)
2298 for (i = 0; i < L; i++)
2300 if (point >= dc->codeword_text_points[i])
2301 dc->codeword_text_out[i] = dc->codeword_text[i];
2303 dc->codeword_text_out[i] = 0;
2306 int steps = dc->codeword_text[i] - 'A' + 1;
2307 int last = (i > 0 ? dc->codeword_text_points[i-1] : 0);
2308 double ratio = ((point - last) /
2309 (double) (dc->codeword_text_points[i] - last));
2310 char chr = 'A' + (ratio * steps);
2311 if (ratio < 0.1) chr = 0;
2312 dc->codeword_text_out[i] = chr;
2316 dc->codeword_text_out[i] = 0;
2318 if (*dc->codeword_text_out &&
2319 !strcmp (dc->codeword_text, "CODEWORD"))
2322 int L2 = strlen (dc->codeword_text_out);
2324 int ascent, descent;
2327 glColor4fv (dc->codeword_color);
2328 glRotatef (90, 0, 1, 0);
2329 glRotatef (-90, 0, 0, 1);
2331 for (i = 0; i < L2; i++)
2336 glRotatef ((i + 0.5) * 360 / 26.0, 0, 0, 1);
2341 glDisable(GL_LIGHTING);
2346 glBegin(GL_LINE_STRIP);
2347 for (th = M_PI * 1.45; th < M_PI * 1.55; th += 0.1)
2350 glVertex3f (r * cos(th), r * sin(th), 0);
2353 if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING);
2357 glTranslatef (0, -dc->codeword_spread * (L - 1), 0);
2358 glScalef (ss, ss, ss);
2359 buf[0] = dc->codeword_text_out[i] + ('a' - 'A');
2361 texture_string_metrics (dc->font, buf, &e, &ascent, &descent);
2364 /* #### Magic magic magic WTF... */
2365 glScalef (0.5, 0.5, 0.5);
2368 glTranslatef (-e.width * 1.0,
2369 -(ascent + descent + e.descent * 2.4), /* #### WTF */
2375 glDisable(GL_LIGHTING);
2376 glBegin(GL_LINE_LOOP);
2377 glVertex3f(0, 0, 0);
2378 glVertex3f(e.width, 0, 0);
2379 glVertex3f(e.width, e.ascent + e.descent, 0);
2380 glVertex3f(0, e.ascent + e.descent, 0);
2382 if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING);
2385 glDisable(GL_CULL_FACE); /* tell texfont.c to draw both sides */
2386 print_texture_string (dc->font, buf);
2387 glEnable(GL_CULL_FACE);
2396 /* Convert the precomputed path to a thick line of polygons.
2397 We could actually precompute all of these polygons too,
2398 but it's fast enough.
2401 draw_codeword_path (ModeInfo *mi)
2403 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2404 int wire = MI_IS_WIREFRAME(mi);
2407 GLfloat anim_ratio = (dc->anim_state == CODEWORD_IN ? dc->anim_ratio :
2408 dc->anim_state == CODEWORD_OUT ? 1 - dc->anim_ratio :
2409 dc->anim_state == CODEWORD_BLANK ? 0 :
2411 int last_anim_point = 0;
2413 GLfloat width = dc->codeword_line_width / 2;
2414 GLfloat thick = dc->codeword_thickness / 2;
2418 int quad_size = (dc->codeword_path_npoints + 1) * 2;
2419 XYZ *quads = (XYZ *) calloc (quad_size, sizeof(*quads));
2420 XYZ *norms = (XYZ *) calloc (quad_size, sizeof(*norms));
2423 for (i = 0; i < dc->codeword_path_npoints; i++)
2425 XYZ p1 = dc->codeword_path[i];
2426 XYZ p2 = (i < dc->codeword_path_npoints-1
2427 ? dc->codeword_path[i+1]
2428 : dc->codeword_path[i-1]);
2431 XYZ n; /* normal of the first line segment */
2432 n.x = -(p2.y - p1.y);
2433 n.y = (p2.x - p1.x);
2439 p1a.x = p1.x - width / 2 * n.x;
2440 p1a.y = p1.y - width / 2 * n.y;
2443 p1b.x = p1.x + width / 2 * n.x;
2444 p1b.y = p1.y + width / 2 * n.y;
2447 else if (i == dc->codeword_path_npoints - 1)
2449 p1b.x = p1.x - width / 2 * n.x;
2450 p1b.y = p1.y - width / 2 * n.y;
2453 p1a.x = p1.x + width / 2 * n.x;
2454 p1a.y = p1.y + width / 2 * n.y;
2459 XYZ p0 = dc->codeword_path[i-1];
2461 XYZ t, t0, t1; /* tangent of corner between two line segments */
2462 XYZ m; /* miter line: normal of tangent */
2463 GLfloat d; /* length of miter */
2484 /* find length of miter by projecting it on one of the normals */
2485 d = width / 2 / dot (m, n);
2487 p1a.x = p1.x - d * m.x;
2488 p1a.y = p1.y - d * m.y;
2491 p1b.x = p1.x + d * m.x;
2492 p1b.y = p1.y + d * m.y;
2496 quads[nquads++] = p1a;
2497 quads[nquads++] = p1b;
2499 if (nquads >= quad_size) abort();
2501 if (i / (double) dc->codeword_path_npoints > anim_ratio)
2504 last_anim_point = i;
2508 /* Compute normals for each point along the interior edge */
2509 for (k = 0; k <= 1; k++)
2511 for (i = k; i < nquads-2; i += 2)
2514 XYZ p2a = quads[i+2];
2517 p1a.z = thick; /* a: top */
2518 p1b.z = -thick; /* b: bottom */
2523 ? calc_normal (p1a, p1b, p2b)
2524 : calc_normal (p2a, p2b, p1a));
2529 glColor4fv (dc->codeword_color);
2530 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, dc->codeword_color);
2532 # ifdef HAVE_MOBILE /* Make the whole thing fit on the phone screen */
2534 GLfloat size = MI_WIDTH(mi) < MI_HEIGHT(mi) ? MI_WIDTH(mi) : MI_HEIGHT(mi);
2535 glScalef (0.9, 0.9, 0.9);
2536 if (size <= 768) /* iPad retina / iPhone 6 */
2537 glScalef (0.7, 0.7, 0.7);
2541 codeword_text_output (mi, anim_ratio);
2543 glRotatef (90, 1, 0, 0);
2544 glRotatef (90, 0, 1, 0);
2545 glRotatef (-90, 0, 0, 1);
2546 glScalef (0.8, 0.8, 0.8);
2548 glNormal3f (0, 0, -1);
2550 if (anim_ratio <= 0)
2552 polys += draw_codeword_cap (mi);
2557 glColor3f (1, 0, 0);
2558 glBegin(GL_LINE_STRIP);
2559 for (i = 0; i < dc->codeword_path_npoints; i++)
2561 glVertex3f (dc->codeword_path[i].x,
2562 dc->codeword_path[i].y,
2563 dc->codeword_path[i].z);
2567 glColor4fv (dc->codeword_color);
2574 for (i = 0; i <= 1; i++)
2575 for (j = -thick; j <= thick; j += thick*2)
2577 glBegin (GL_LINE_STRIP);
2578 for (k = i; k < nquads; k += 2)
2580 glVertex3f (quads[k].x, quads[k].y, j);
2587 /* Top and bottom */
2589 for (j = -thick; j <= thick; j += thick*2)
2593 glNormal3f (0, 0, -1);
2594 glFrontFace (GL_CW);
2598 glNormal3f (0, 0, 1);
2599 glFrontFace (GL_CCW);
2601 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
2602 for (i = 0; i < nquads; i += 2)
2604 glVertex3f (quads[i+1].x, quads[i+1].y, j);
2605 glVertex3f (quads[i].x, quads[i].y, j);
2613 for (k = 0; k <= 1; k++)
2617 glNormal3f (0, 0, -1);
2618 glFrontFace (GL_CW);
2622 glNormal3f (0, 0, 1);
2623 glFrontFace (GL_CCW);
2626 glBegin (wire ? GL_LINES : GL_QUADS);
2627 for (i = k; i < nquads; i += 2)
2630 XYZ p2a = (i < nquads-2) ? quads[i+2] : p1a;
2635 XYZ n2 = (i < nquads-2) ? norms[i+2] : n1;
2637 /* If the two normals are very similar, smooth the face.
2638 If they are different, it's a sharp turn, and use the
2639 same normal for both edges (not quite right, but close).
2641 GLfloat angle = vector_angle (n1.x, n1.y, n1.z,
2643 GLfloat pointy = 0.8;
2650 glNormal3f (n1.x, n1.y, n1.z);
2651 glVertex3f (p1a.x, p1a.y, p1a.z);
2652 glVertex3f (p1b.x, p1b.y, p1b.z);
2655 glNormal3f (n2.x, n2.y, n2.z);
2656 glVertex3f (p2b.x, p2b.y, p2b.z);
2657 glVertex3f (p2a.x, p2a.y, p2a.z);
2664 /* Only draw the guides when the path is almost complete;
2665 fade them in and out based on completeness. */
2667 GLfloat size = 0.95;
2668 GLfloat r = (anim_ratio > size
2669 ? (anim_ratio - size) / (1 - size)
2671 polys += draw_codeword_guides (mi, r);
2675 /* Draw the start and end caps */
2678 GLfloat x, y, z, x2, y2, z2, X, Y, Z;
2679 GLfloat r = dc->codeword_spread * dc->codeword_cap_size;
2682 x = dc->codeword_path[i].x;
2683 y = dc->codeword_path[i].y;
2684 z = dc->codeword_path[i].z;
2689 glTranslatef (x, y, z);
2690 polys += draw_codeword_cap (mi);
2695 i = last_anim_point + 1;
2696 if (i > dc->codeword_path_npoints - 1)
2697 i = dc->codeword_path_npoints - 1;
2699 x = dc->codeword_path[i].x;
2700 y = dc->codeword_path[i].y;
2701 z = dc->codeword_path[i].z;
2704 x2 = dc->codeword_path[i].x;
2705 y2 = dc->codeword_path[i].y;
2706 z2 = dc->codeword_path[i].z;
2713 glTranslatef (x, y, z);
2714 glRotatef (-atan2 (X, Y) * (180 / M_PI), 0, 0, 1);
2715 glRotatef ( atan2 (Z, sqrt(X*X + Y*Y)) * (180 / M_PI), 1, 0, 0);
2716 glTranslatef (0, -r, 0);
2717 polys += draw_codeword_cap (mi);
2734 /* Window management, etc
2737 reshape_logo (ModeInfo *mi, int width, int height)
2739 GLfloat h = (GLfloat) height / (GLfloat) width;
2741 glViewport (0, 0, (GLint) width, (GLint) height);
2743 glMatrixMode(GL_PROJECTION);
2745 gluPerspective (30.0, 1/h, 1.0, 100.0);
2747 glMatrixMode(GL_MODELVIEW);
2749 gluLookAt( 0.0, 0.0, 30.0,
2753 # ifdef HAVE_MOBILE /* Keep it the same relative size when rotated. */
2755 int o = (int) current_device_rotation();
2756 if (o != 0 && o != 180 && o != -180)
2757 glScalef (1/h, 1/h, 1/h); /* #### Why does this change the lighting? */
2761 glClear(GL_COLOR_BUFFER_BIT);
2766 gl_init (ModeInfo *mi)
2768 /* logo_configuration *dc = &dcs[MI_SCREEN(mi)]; */
2769 int wire = MI_IS_WIREFRAME(mi);
2771 GLfloat position[] = {0, 0, 0, 0};
2772 GLfloat direction[] = {3, -1, -3};
2774 position[0] = -direction[0];
2775 position[1] = -direction[1];
2776 position[2] = -direction[2];
2780 glLightfv(GL_LIGHT0, GL_POSITION, position);
2781 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction);
2782 glShadeModel(GL_SMOOTH);
2783 glEnable(GL_NORMALIZE);
2784 glEnable(GL_CULL_FACE);
2785 glEnable(GL_LIGHTING);
2786 glEnable(GL_LIGHT0);
2787 glEnable(GL_DEPTH_TEST);
2793 init_logo (ModeInfo *mi)
2795 logo_configuration *dc;
2796 int do_gasket = get_boolean_resource(mi->dpy, "doGasket", "Boolean");
2797 int do_helix = get_boolean_resource(mi->dpy, "doHelix", "Boolean");
2798 int do_ladder = (do_helix &&
2799 get_boolean_resource(mi->dpy, "doLadder", "Boolean"));
2800 int do_frame = get_boolean_resource(mi->dpy, "doFrame", "Boolean");
2801 GLfloat helix_rot = 147.0;
2803 if (!do_gasket && !do_helix)
2805 fprintf (stderr, "%s: no helix or gasket?\n", progname);
2811 dc = &dcs[MI_SCREEN(mi)];
2813 if ((dc->glx_context = init_GL(mi)) != NULL) {
2815 reshape_logo (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
2818 dc->wall_facets = get_integer_resource(mi->dpy, "wallFacets", "Integer");
2819 dc->bar_facets = get_integer_resource(mi->dpy, "barFacets", "Integer");
2820 dc->clockwise = get_boolean_resource(mi->dpy, "clockwise", "Boolean");
2821 dc->turns = get_float_resource(mi->dpy, "turns", "Float");
2822 dc->turn_spacing = get_float_resource(mi->dpy, "turnSpacing", "Float");
2823 dc->bar_spacing = get_float_resource(mi->dpy, "barSpacing", "Float");
2824 dc->wall_height = get_float_resource(mi->dpy, "wallHeight", "Float");
2825 dc->wall_thickness = get_float_resource(mi->dpy, "wallThickness", "Float");
2826 dc->bar_thickness = get_float_resource(mi->dpy, "barThickness", "Float");
2827 dc->wall_taper = get_float_resource(mi->dpy, "wallTaper", "Float");
2829 dc->gasket_size = get_float_resource(mi->dpy,"gasketSize", "Float");
2830 dc->gasket_depth = get_float_resource(mi->dpy,"gasketDepth", "Float");
2831 dc->gasket_thickness = get_float_resource(mi->dpy,"gasketThickness","Float");
2833 dc->frame_size = get_float_resource(mi->dpy, "frameSize", "Float");
2834 dc->frame_depth = get_float_resource(mi->dpy, "frameDepth", "Float");
2835 dc->frame_thickness = get_float_resource(mi->dpy, "frameThickness", "Float");
2836 dc->triangle_size = get_float_resource(mi->dpy, "triangleSize", "Float");
2838 dc->speed = get_float_resource(mi->dpy, "speed", "Float");
2840 dc->codeword_text = get_string_resource(mi->dpy, "text", "String");
2841 dc->codeword_text = codeword_simplify_text (dc->codeword_text);
2842 dc->codeword_text_out =
2843 calloc (strlen(dc->codeword_text) + 1, sizeof(*dc->codeword_text_out));
2844 dc->codeword_text_points =
2845 (int *) calloc (strlen(dc->codeword_text) + 1,
2846 sizeof(*dc->codeword_text_points));
2848 dc->codeword_facets = get_integer_resource(mi->dpy, "cwFacets", "Integer");
2849 dc->codeword_disc_facets = get_integer_resource(mi->dpy,
2850 "cwDiscFacets", "Integer");
2851 dc->codeword_spread = get_float_resource(mi->dpy, "cwSpread", "Float");
2852 dc->codeword_line_width = get_float_resource(mi->dpy, "cwLineWidth", "Float");
2853 dc->codeword_thickness = get_float_resource(mi->dpy, "cwThickness", "Float");
2854 dc->codeword_cap_size = get_float_resource(mi->dpy, "cwCapSize", "Float");
2858 char *s = get_string_resource (MI_DISPLAY (mi), "mode", "String");
2859 if (!s || !*s || !strcasecmp (s, "helix"))
2861 else if (!strcasecmp (s, "pizza"))
2863 else if (!strcasecmp (s, "both"))
2864 dc->mode = HELIX_AND_PIZZA;
2866 else if (!strcasecmp (s, "codeword"))
2867 dc->mode = CODEWORD_IN;
2872 "%s: mode must be helix, pizza or both, not \"%s\"\n",
2878 dc->anim_state = (dc->mode == HELIX_AND_PIZZA
2879 ? ((random() & 1) ? HELIX : PIZZA)
2885 if (dc->mode == CODEWORD_IN)
2886 dc->font = load_texture_font (MI_DISPLAY(mi), "cwFont");
2893 get_string_resource (mi->dpy, "foreground", "Foreground");
2895 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
2896 if (*s2 == ' ' || *s2 == '\t')
2901 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
2903 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
2907 dc->color[0] = xcolor.red / 65535.0;
2908 dc->color[1] = xcolor.green / 65535.0;
2909 dc->color[2] = xcolor.blue / 65535.0;
2912 color_name = get_string_resource (mi->dpy, "cwForeground", "Foreground");
2913 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
2914 if (*s2 == ' ' || *s2 == '\t')
2919 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
2921 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
2926 dc->codeword_color[0] = xcolor.red / 65535.0;
2927 dc->codeword_color[1] = xcolor.green / 65535.0;
2928 dc->codeword_color[2] = xcolor.blue / 65535.0;
2929 dc->codeword_color[3] = 1.0;
2931 color_name = get_string_resource (mi->dpy, "cwBackground", "Background");
2932 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
2933 if (*s2 == ' ' || *s2 == '\t')
2938 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
2940 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
2944 dc->codeword_bg[0] = xcolor.red / 65535.0;
2945 dc->codeword_bg[1] = xcolor.green / 65535.0;
2946 dc->codeword_bg[2] = xcolor.blue / 65535.0;
2947 dc->codeword_bg[3] = 1.0;
2951 dc->trackball = gltrackball_init (False);
2953 dc->gasket_spinnerx.probability = 0.1;
2954 dc->gasket_spinnery.probability = 0.1;
2955 dc->gasket_spinnerz.probability = 1.0;
2956 dc->gasket_spinnerx.easement = 0.08;
2957 dc->gasket_spinnery.easement = 0.08;
2958 dc->gasket_spinnerz.easement = 0.08;
2960 dc->helix_spinnerz.probability = 0.6;
2961 dc->helix_spinnerz.easement = 0.2;
2963 dc->pizza_spinnerz.probability = 0.6;
2964 dc->pizza_spinnery.probability = 0.6;
2965 dc->pizza_spinnerz.easement = 0.2;
2966 dc->pizza_spinnery.easement = 0.2;
2968 dc->frame_spinner.probability = 5.0;
2969 dc->frame_spinner.easement = 0.2;
2971 dc->scene_spinnerx.probability = 0.1;
2972 dc->scene_spinnery.probability = 0.0;
2973 dc->scene_spinnerx.easement = 0.1;
2974 dc->scene_spinnery.easement = 0.1;
2977 if (dc->mode == CODEWORD_IN)
2979 double tilt_speed = 0.003;
2980 dc->scene_rot = make_rotator (0, 0, 0, 0, tilt_speed, True);
2984 /* start the frame off-screen */
2985 dc->frame_spinner.spinning_p = True;
2986 dc->frame_spinner.position = 0.3;
2987 dc->frame_spinner.speed = 0.001;
2989 if (dc->speed > 0) /* start off with the gasket in motion */
2991 dc->gasket_spinnerz.spinning_p = True;
2992 dc->gasket_spinnerz.speed = (0.002
2993 * ((random() & 1) ? 1 : -1)
2997 # ifdef DXF_OUTPUT_HACK
3000 dc->frame_depth = dc->gasket_depth;
3005 glRotatef(90, 1, 0, 0);
3006 glRotatef(90, 0, 0, 1);
3007 make_pizza (dc, 0, 0);
3010 glRotatef(helix_rot, 0, 0, 1);
3011 make_ladder (dc, 0, 0);
3012 make_helix (dc, 0, 0);
3013 glRotatef (180, 0, 0, 1);
3014 make_helix (dc, 0, 0);
3018 make_gasket (dc, 0);
3026 glRotatef(90, 1, 0, 0);
3027 glRotatef(90, 0, 0, 1);
3028 dc->anim_state = CODEWORD;
3029 make_codeword_path (mi);
3030 draw_codeword_path (mi);
3038 dc->helix_list = glGenLists (1);
3039 glNewList (dc->helix_list, GL_COMPILE);
3040 glRotatef(helix_rot, 0, 0, 1);
3041 if (do_ladder) dc->polys[0] += make_ladder (dc, 0, 0);
3042 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
3043 glRotatef(180, 0, 0, 1);
3044 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
3049 dc->helix_list_wire = glGenLists (1);
3050 glNewList (dc->helix_list_wire, GL_COMPILE);
3051 /* glRotatef(helix_rot, 0, 0, 1); wtf? */
3052 if (do_ladder) dc->polys[1] += make_ladder (dc, 1, 1);
3053 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
3054 glRotatef(180, 0, 0, 1);
3055 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
3060 dc->helix_list_facetted = glGenLists (1);
3061 glNewList (dc->helix_list_facetted, GL_COMPILE);
3062 glRotatef(helix_rot, 0, 0, 1);
3063 if (do_ladder) dc->polys[2] += make_ladder (dc, 1, 0);
3064 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
3065 glRotatef(180, 0, 0, 1);
3066 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
3070 dc->pizza_list = glGenLists (1);
3071 glNewList (dc->pizza_list, GL_COMPILE);
3072 if (do_frame) dc->polys[5] += make_pizza (dc, 0, 0);
3075 dc->pizza_list_wire = glGenLists (1);
3076 glNewList (dc->pizza_list_wire, GL_COMPILE);
3077 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 1);
3080 dc->pizza_list_facetted = glGenLists (1);
3081 glNewList (dc->pizza_list_facetted, GL_COMPILE);
3082 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 0);
3085 dc->gasket_list = glGenLists (1);
3086 glNewList (dc->gasket_list, GL_COMPILE);
3087 if (do_gasket) dc->polys[3] += make_gasket (dc, 0);
3090 dc->gasket_list_wire = glGenLists (1);
3091 glNewList (dc->gasket_list_wire, GL_COMPILE);
3092 if (do_gasket) dc->polys[4] += make_gasket (dc, 1);
3095 dc->frame_list = glGenLists (1);
3096 glNewList (dc->frame_list, GL_COMPILE);
3097 if (do_frame) dc->polys[5] += make_frame (dc, 0);
3100 dc->frame_list_wire = glGenLists (1);
3101 glNewList (dc->frame_list_wire, GL_COMPILE);
3102 if (do_frame) dc->polys[6] += make_frame (dc, 1);
3106 make_codeword_path (mi);
3109 /* When drawing both solid and wireframe objects,
3110 make sure the wireframe actually shows up! */
3111 glEnable (GL_POLYGON_OFFSET_FILL);
3112 glPolygonOffset (1.0, 1.0);
3117 logo_handle_event (ModeInfo *mi, XEvent *event)
3119 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
3121 if (gltrackball_event_handler (event, dc->trackball,
3122 MI_WIDTH (mi), MI_HEIGHT (mi),
3123 &dc->button_down_p))
3125 else if (event->xany.type == KeyPress)
3129 XLookupString (&event->xkey, &c, 1, &keysym, 0);
3130 if (c == ' ' || c == '\t')
3132 switch (dc->anim_state) {
3134 dc->anim_state = HELIX_OUT;
3135 dc->anim_ratio = 0.0;
3138 dc->anim_state = PIZZA_OUT;
3139 dc->anim_ratio = 0.0;
3143 dc->anim_state = CODEWORD_OUT;
3144 dc->anim_ratio = 0.0;
3158 spinner_ease (GLfloat x)
3160 /* Smooth curve up, ending at slope = 1. */
3161 return cos ((x/2 + 1) * M_PI) + 1;
3166 tick_spinner (ModeInfo *mi, spinner *s)
3168 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
3170 if (dc->speed == 0) return;
3171 if (dc->button_down_p) return;
3175 s->position += s->speed;
3176 if (s->position >= 1.0 || s->position <= 0.0)
3179 s->position_eased = 0;
3180 s->spinning_p = False;
3182 else if (s->easement > 0 && s->position <= s->easement)
3183 s->position_eased = (s->easement *
3184 spinner_ease (s->position / s->easement));
3185 else if (s->easement > 0 && s->position >= 1-s->easement)
3186 s->position_eased = (1 - s->easement *
3187 spinner_ease ((1 - s->position) / s->easement));
3189 s->position_eased = s->position;
3191 else if (s->probability &&
3192 (random() % (int) (PROBABILITY_SCALE / s->probability)) == 0)
3195 s->spinning_p = True;
3198 s->speed = dc->speed * (frand(ss/3) + frand(ss/3) + frand(ss/3));
3199 } while (s->speed <= 0);
3202 s->speed = -s->speed;
3210 link_spinners (ModeInfo *mi, spinner *s0, spinner *s1)
3212 if (s0->spinning_p && !s1->spinning_p)
3214 GLfloat op = s1->probability;
3215 s1->probability = PROBABILITY_SCALE;
3216 tick_spinner (mi, s1);
3217 s1->probability = op;
3223 draw_logo (ModeInfo *mi)
3225 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
3226 Display *dpy = MI_DISPLAY(mi);
3227 Window window = MI_WINDOW(mi);
3228 int wire = MI_IS_WIREFRAME(mi);
3230 GLfloat specular[] = {0.8, 0.8, 0.8, 1.0};
3231 GLfloat shininess = 50.0;
3237 if (!dc->glx_context)
3240 mi->polygon_count = 0;
3241 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(dc->glx_context));
3244 dc->wire_overlay == 0 &&
3245 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
3246 dc->wire_overlay = ((random() % 200) +
3250 tick_spinner (mi, &dc->gasket_spinnerx);
3251 tick_spinner (mi, &dc->gasket_spinnery);
3252 tick_spinner (mi, &dc->gasket_spinnerz);
3253 tick_spinner (mi, &dc->helix_spinnerz);
3254 tick_spinner (mi, &dc->pizza_spinnery);
3255 tick_spinner (mi, &dc->pizza_spinnerz);
3256 tick_spinner (mi, &dc->scene_spinnerx);
3257 tick_spinner (mi, &dc->scene_spinnery);
3258 tick_spinner (mi, &dc->frame_spinner);
3259 link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery);
3261 switch (dc->anim_state)
3264 if (dc->mode == HELIX_AND_PIZZA &&
3265 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
3266 dc->anim_state = HELIX_OUT;
3270 dc->anim_ratio += 0.1 * dc->speed;
3271 if (dc->anim_ratio >= 1.0)
3273 dc->anim_ratio = 0.0;
3274 dc->anim_state = PIZZA_IN;
3279 dc->anim_ratio += 0.1 * dc->speed;
3280 if (dc->anim_ratio >= 1.0)
3282 dc->anim_ratio = 0.0;
3283 dc->anim_state = PIZZA;
3288 if (dc->mode == HELIX_AND_PIZZA &&
3289 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
3290 dc->anim_state = PIZZA_OUT;
3294 dc->anim_ratio += 0.1 * dc->speed;
3295 if (dc->anim_ratio >= 1.0)
3297 dc->anim_ratio = 0.0;
3298 dc->anim_state = HELIX_IN;
3303 dc->anim_ratio += 0.1 * dc->speed;
3304 if (dc->anim_ratio >= 1.0)
3306 dc->anim_ratio = 0.0;
3307 dc->anim_state = HELIX;
3314 dc->scene_spinnerx.probability = 0.2;
3315 dc->scene_spinnery.probability = 0.05;
3316 if (! dc->button_down_p)
3317 dc->anim_ratio += 0.004 * dc->speed;
3318 if (dc->anim_ratio >= 1.0)
3320 dc->anim_state = CODEWORD;
3321 dc->anim_ratio = frand (0.5);
3326 dc->scene_spinnerx.probability = 0.5;
3327 dc->scene_spinnery.probability = 0.2;
3328 if (! dc->button_down_p)
3329 dc->anim_ratio += (0.0005 + frand(0.002)) * dc->speed;
3330 if (dc->anim_ratio >= 1.0)
3332 dc->anim_ratio = 0.0;
3333 dc->anim_state = CODEWORD_OUT;
3338 dc->scene_spinnerx.probability = 0;
3339 dc->scene_spinnery.probability = 0;
3340 if (! dc->button_down_p)
3341 dc->anim_ratio += 0.02 * dc->speed;
3342 if (dc->anim_ratio >= 1.0)
3344 dc->anim_ratio = 0.0;
3345 dc->anim_state = CODEWORD_BLANK;
3349 case CODEWORD_BLANK:
3350 dc->scene_spinnerx.probability = 0;
3351 dc->scene_spinnery.probability = 0;
3352 if (! dc->button_down_p)
3353 dc->anim_ratio += 0.01 * dc->speed;
3354 if (dc->anim_ratio >= 1.0)
3356 dc->anim_ratio = 0.0;
3357 dc->anim_state = CODEWORD_IN;
3367 pizza_p = (dc->anim_state == PIZZA ||
3368 dc->anim_state == PIZZA_IN ||
3369 dc->anim_state == PIZZA_OUT);
3372 codeword_p = (dc->anim_state == CODEWORD ||
3373 dc->anim_state == CODEWORD_IN ||
3374 dc->anim_state == CODEWORD_OUT ||
3375 dc->anim_state == CODEWORD_BLANK);
3378 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3381 glRotatef(current_device_rotation(), 0, 0, 1);
3383 GLfloat scale = 1.8;
3384 glScalef(scale, scale, scale);
3386 glColor3f(dc->color[0], dc->color[1], dc->color[2]);
3389 /* Draw frame before trackball rotation */
3394 GLfloat p = (dc->frame_spinner.position_eased >= 0
3395 ? dc->frame_spinner.position_eased
3396 : -dc->frame_spinner.position_eased);
3397 GLfloat size = (p > 0.5 ? 1-p : p);
3398 scale = 1 + (size * 10);
3400 /* gltrackball_rotate (dc->trackball); */
3401 glRotatef(90, 1, 0, 0);
3402 glRotatef(90, 0, 0, 1);
3404 glScalef (1, scale, scale);
3407 glDisable (GL_LIGHTING);
3408 glCallList (dc->frame_list_wire);
3409 mi->polygon_count += dc->polys[6];
3411 else if (dc->wire_overlay != 0)
3413 glCallList (dc->frame_list);
3414 glDisable (GL_LIGHTING);
3415 glColor3fv (dc->color);
3416 glCallList (dc->frame_list_wire);
3417 mi->polygon_count += dc->polys[6];
3418 if (!wire) glEnable (GL_LIGHTING);
3422 glCallList (dc->frame_list);
3423 mi->polygon_count += dc->polys[5];
3428 gltrackball_rotate (dc->trackball);
3430 glRotatef(90, 1, 0, 0);
3431 glRotatef(90, 0, 0, 1);
3437 glRotatef (360 * dc->scene_spinnerx.position_eased, 0, 1, 0);
3438 glRotatef (360 * dc->scene_spinnery.position_eased, 0, 0, 1);
3442 glRotatef (360 * dc->gasket_spinnerx.position_eased, 0, 1, 0);
3443 glRotatef (360 * dc->gasket_spinnery.position_eased, 0, 0, 1);
3444 glRotatef (360 * dc->gasket_spinnerz.position_eased, 1, 0, 0);
3446 memcpy (gcolor, dc->color, sizeof (dc->color));
3447 if (dc->wire_overlay != 0)
3449 gcolor[0] = gcolor[1] = gcolor[2] = 0;
3450 specular[0] = specular[1] = specular[2] = 0;
3453 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
3454 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
3455 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shininess);
3459 glDisable (GL_LIGHTING);
3460 glCallList (dc->gasket_list_wire);
3461 mi->polygon_count += dc->polys[4];
3463 else if (dc->wire_overlay != 0)
3465 glCallList (dc->gasket_list);
3466 glDisable (GL_LIGHTING);
3467 glColor3fv (dc->color);
3468 glCallList (dc->gasket_list_wire);
3469 mi->polygon_count += dc->polys[4];
3470 if (!wire) glEnable (GL_LIGHTING);
3471 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
3475 glCallList (dc->gasket_list);
3476 mi->polygon_count += dc->polys[3];
3482 glRotatef (360 * dc->pizza_spinnery.position_eased, 1, 0, 0);
3483 glRotatef (360 * dc->pizza_spinnerz.position_eased, 0, 0, 1);
3487 glRotatef (360 * dc->helix_spinnerz.position_eased, 0, 0, 1);
3490 scale = ((dc->anim_state == PIZZA_IN || dc->anim_state == HELIX_IN)
3492 : ((dc->anim_state == PIZZA_OUT || dc->anim_state == HELIX_OUT)
3493 ? 1.0 - dc->anim_ratio
3495 if (scale <= 0) scale = 0.001;
3496 glScalef (scale, scale, scale);
3500 glDisable (GL_LIGHTING);
3502 glCallList (dc->pizza_list_wire);
3504 glCallList (dc->helix_list_wire);
3505 mi->polygon_count += dc->polys[1];
3507 else if (dc->wire_overlay != 0)
3510 glCallList (dc->pizza_list_facetted);
3512 glCallList (dc->helix_list_facetted);
3514 glDisable (GL_LIGHTING);
3515 glColor3fv (dc->color);
3518 glCallList (dc->pizza_list_wire);
3520 glCallList (dc->helix_list_wire);
3522 mi->polygon_count += dc->polys[2];
3523 if (!wire) glEnable (GL_LIGHTING);
3528 glCallList (dc->pizza_list);
3530 glCallList (dc->helix_list);
3531 mi->polygon_count += dc->polys[0];
3535 else /* codeword_p */
3538 double max = 70; /* face front */
3540 get_position (dc->scene_rot, &x, &y, &z, !dc->button_down_p);
3541 glRotatef (max/2 - x*max, 0, 0, 1);
3542 glRotatef (max/2 - y*max, 0, 1, 0);
3543 /* glRotatef (max/2 - z*max, 1, 0, 0); */
3545 glRotatef (360 * dc->scene_spinnerx.position_eased, 0, 1, 0);
3546 glRotatef (360 * dc->scene_spinnery.position_eased, 0, 0, 1);
3549 glClearColor (dc->codeword_bg[0],
3552 dc->codeword_bg[3]);
3553 mi->polygon_count += draw_codeword_path (mi);
3559 if (dc->wire_overlay > 0)
3562 if (mi->fps_p) do_fps (mi);
3565 glXSwapBuffers(dpy, window);
3568 XSCREENSAVER_MODULE_2 ("DNALogo", dnalogo, logo)