1 /* DNA Logo, Copyright (c) 2001-2016 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-*-*-*-*-*-*"
70 # define refresh_logo 0
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,
110 CODEWORD_IN, CODEWORD, CODEWORD_OUT, CODEWORD_BLANK
115 GLfloat position; /* 0.0 - 1.0 */
116 GLfloat position_eased; /* 0.0 - 1.0, eased in and out */
117 GLfloat easement; /* portion of path that is eased. <= 0.5 */
118 GLfloat speed; /* how far along the path (may be negative) */
119 GLfloat probability; /* relative likelyhood to start spinning */
123 GLXContext *glx_context;
125 GLuint helix_list, helix_list_wire, helix_list_facetted;
126 GLuint pizza_list, pizza_list_wire, pizza_list_facetted;
127 GLuint gasket_list, gasket_list_wire;
128 GLuint frame_list, frame_list_wire;
137 GLfloat turn_spacing;
140 GLfloat wall_thickness;
141 GLfloat bar_thickness;
145 GLfloat gasket_depth;
146 GLfloat gasket_thickness;
150 GLfloat frame_thickness;
151 GLfloat triangle_size;
153 int codeword_facets, codeword_disc_facets;
154 GLfloat codeword_spread, codeword_line_width, codeword_thickness;
155 GLfloat codeword_cap_size;
156 const char *codeword_text;
157 char *codeword_text_out;
158 int *codeword_text_points;
160 int codeword_path_npoints;
161 int codeword_nguides;
162 XYZ *codeword_guides;
163 GLfloat codeword_color[4], codeword_bg[4];
164 texture_font_data *font;
168 glyph_mode anim_state;
171 spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz;
172 spinner scene_spinnerx, scene_spinnery; /* for DNA */
173 rotator *scene_rot; /* for Codeword */
174 spinner helix_spinnerz;
175 spinner pizza_spinnery, pizza_spinnerz;
176 spinner frame_spinner;
178 trackball_state *trackball;
181 int wire_overlay; /* frame countdown */
183 } logo_configuration;
185 static logo_configuration *dcs = NULL;
187 static XrmOptionDescRec opts[] = {
188 { "-speed", ".speed", XrmoptionSepArg, 0 },
189 { "-mode", ".mode", XrmoptionSepArg, 0 },
190 { "-pizza", ".mode", XrmoptionNoArg, "pizza" },
191 { "-helix", ".mode", XrmoptionNoArg, "helix" },
192 { "-both", ".mode", XrmoptionNoArg, "both" },
193 { "-codeword", ".mode", XrmoptionNoArg, "codeword" },
194 { "-cw", ".mode", XrmoptionNoArg, "codeword" },
195 { "-text", ".text", XrmoptionSepArg, 0 },
198 ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
200 #define PROBABILITY_SCALE 600
203 #ifdef DXF_OUTPUT_HACK
205 # define glBegin dxf_glBegin
206 # define glVertex3f dxf_glVertex3f
207 # define glVertex3dv dxf_glVertex3dv
208 # define glEnd dxf_glEnd
209 # define glVertexPointer dxf_glVertexPointer
210 # define glDrawArrays dxf_glDrawArrays
212 static int dxf_type, dxf_point, dxf_point_total, dxf_layer, dxf_color;
213 static GLfloat dxf_quads[4*4];
216 dxf_glBegin (int type)
224 dxf_glVertex3f (GLfloat ox, GLfloat oy, GLfloat oz)
230 /* Transform the point into modelview space. */
231 glGetFloatv (GL_MODELVIEW_MATRIX, m);
232 x = ox * m[0] + oy * m[4] + oz * m[8] + m[12];
233 y = ox * m[1] + oy * m[5] + oz * m[9] + m[13];
234 z = ox * m[2] + oy * m[6] + oz * m[10] + m[14];
236 dxf_quads[dxf_point*3+0] = x;
237 dxf_quads[dxf_point*3+1] = y;
238 dxf_quads[dxf_point*3+2] = z;
244 if (dxf_point < 4) return;
246 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
247 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
248 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
249 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
251 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
252 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
253 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
255 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
256 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
257 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
259 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]);
260 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
261 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
266 if (dxf_point < 4) return;
268 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
269 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
270 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
271 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
273 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
274 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
275 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
277 fprintf (stdout, "12\n%.6f\n", dxf_quads[i+3]); /* funky quad strip */
278 fprintf (stdout, "22\n%.6f\n", dxf_quads[i+4]); /* vert order: 1243. */
279 fprintf (stdout, "32\n%.6f\n", dxf_quads[i+5]);
281 fprintf (stdout, "13\n%.6f\n", dxf_quads[i]);
282 fprintf (stdout, "23\n%.6f\n", dxf_quads[i+1]);
283 fprintf (stdout, "33\n%.6f\n", dxf_quads[i+2]);
286 dxf_quads[0] = dxf_quads[6]; /* copy point 3 to pos 1 */
287 dxf_quads[1] = dxf_quads[7];
288 dxf_quads[2] = dxf_quads[8];
289 dxf_quads[3] = dxf_quads[9]; /* copy point 4 to pos 2 */
290 dxf_quads[4] = dxf_quads[10];
291 dxf_quads[5] = dxf_quads[11];
292 dxf_point = 2; /* leave those two points in queue */
296 case GL_TRIANGLE_FAN:
297 if (dxf_point < 3) return;
299 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
300 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
301 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
302 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
304 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
305 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
306 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
308 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
309 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
310 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
313 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
314 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
315 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
318 if (dxf_type == GL_TRIANGLE_FAN)
320 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to point 2 */
321 dxf_quads[4] = dxf_quads[7];
322 dxf_quads[5] = dxf_quads[8];
323 dxf_point = 2; /* leave two points in queue */
327 case GL_TRIANGLE_STRIP:
328 if (dxf_point < 3) return;
330 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
332 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
333 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
334 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
336 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
337 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
338 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
340 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
341 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
342 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
345 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
346 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
347 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
349 dxf_quads[0] = dxf_quads[3]; /* copy point 2 to pos 1 */
350 dxf_quads[1] = dxf_quads[4];
351 dxf_quads[2] = dxf_quads[5];
352 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to pos 2 */
353 dxf_quads[4] = dxf_quads[7];
354 dxf_quads[5] = dxf_quads[8];
355 dxf_point = 2; /* leave those two points in queue */
362 if (dxf_point_total == 1)
369 if (dxf_point < 2) return;
371 fprintf (stdout, "0\nLINE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
373 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
374 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
375 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
377 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
378 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
379 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
382 if (dxf_type != GL_LINES)
384 dxf_quads[0] = dxf_quads[3];
385 dxf_quads[1] = dxf_quads[4];
386 dxf_quads[2] = dxf_quads[5];
399 dxf_glVertex3dv (const GLdouble *v)
401 glVertex3f (v[0], v[1], v[2]);
408 if (dxf_type == GL_LINE_LOOP) /* close loop */
409 glVertex3f (dxf_quads[6], dxf_quads[7], dxf_quads[8]);
419 fprintf (stdout, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n");
420 fprintf (stdout, "0\nSECTION\n2\nENTITIES\n");
426 fprintf (stdout, "0\nENDSEC\n0\nEOF\n");
431 static const GLvoid *dxf_vp;
432 static GLsizei dxf_vp_size;
433 static GLsizei dxf_vp_stride;
436 dxf_glVertexPointer (GLint size, GLenum type, GLsizei stride,
437 const GLvoid *pointer)
439 if (type != GL_FLOAT) abort();
440 if (stride <= 0) abort();
443 dxf_vp_stride = stride;
447 dxf_glDrawArrays (GLenum mode, GLint first, GLsizei count)
450 unsigned char *a = (unsigned char *) dxf_vp;
452 for (i = first; i < first+count; i++)
454 GLfloat *fa = (GLfloat *) a;
455 dxf_glVertex3f (fa[0], fa[1], fa[2]);
462 # define XYZ tube_XYZ /* avoid conflict with normals.h */
463 # include "tube.c" /* Yes, I really am including a C file. */
465 # define XYZ sphere_XYZ
466 # define unit_sphere unit_sphere_dxf
467 # define unit_dome unit_dome_dxf
471 #endif /* DXF_OUTPUT_HACK */
475 /* Calculate the angle (in radians) between two vectors.
478 vector_angle (double ax, double ay, double az,
479 double bx, double by, double bz)
481 double La = sqrt (ax*ax + ay*ay + az*az);
482 double Lb = sqrt (bx*bx + by*by + bz*bz);
485 if (La == 0 || Lb == 0) return 0;
486 if (ax == bx && ay == by && az == bz) return 0;
488 /* dot product of two vectors is defined as:
489 La * Lb * cos(angle between vectors)
490 and is also defined as:
491 ax*bx + ay*by + az*bz
493 La * Lb * cos(angle) = ax*bx + ay*by + az*bz
494 cos(angle) = (ax*bx + ay*by + az*bz) / (La * Lb)
495 angle = acos ((ax*bx + ay*by + az*bz) / (La * Lb));
497 cc = (ax*bx + ay*by + az*bz) / (La * Lb);
498 if (cc > 1) cc = 1; /* avoid fp rounding error (1.000001 => sqrt error) */
507 GLfloat d = sqrt (p->x*p->x + p->y*p->y + p->z*p->z);
516 p->x = p->y = p->z = 0;
522 dot (const XYZ u, const XYZ v)
524 return (u.x * v.x) + (u.y * v.y) + (u.z * v.z);
532 make_helix (logo_configuration *dc, int facetted, int wire)
535 int wall_facets = dc->wall_facets / (facetted ? 10 : 1);
537 GLfloat max_th = M_PI * 2 * dc->turns;
538 GLfloat th_inc = M_PI * 2 / wall_facets;
540 GLfloat x1=0, y1=0, x2=0, y2=0;
541 GLfloat x1b=0, y1b=0, x2b=0, y2b=0;
544 GLfloat h1off=0, h2off=0;
545 GLfloat z_inc = dc->turn_spacing / wall_facets;
550 x1b = 1 - dc->wall_thickness;
553 z1 = -(dc->turn_spacing * dc->turns / 2);
555 h1 = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2);
556 h1off = (dc->wall_taper > 0 ? -dc->wall_height / 2 : 0);
559 z1 = -z1, z_inc = -z_inc, h1off = -h1off;
568 nx = cos (th + M_PI/2);
569 ny = sin (th + M_PI/2);
570 glNormal3f(nx, ny, 0);
571 glVertex3f( x1, y1, z1 - h1 + h1off);
572 glVertex3f( x1, y1, z1 + h1 + h1off);
573 glVertex3f(x1b, y1b, z1 + h1 + h1off);
574 glVertex3f(x1b, y1b, z1 - h1 + h1off);
579 while (th + th_inc <= max_th)
586 x2b = x2 * (1 - dc->wall_thickness);
587 y2b = y2 * (1 - dc->wall_thickness);
592 if (dc->wall_taper > 0)
595 if (th < dc->wall_taper)
597 h2 = dc->wall_height/2 * cos (M_PI / 2
598 * (1 - (th / dc->wall_taper)));
600 h2off = h2 - dc->wall_height/2;
602 h2off = dc->wall_height/2 - h2;
604 else if (th >= max_th - dc->wall_taper)
606 if (th + th_inc > max_th) /* edge case: always come to a point */
609 h2 = dc->wall_height/2 * cos (M_PI / 2
610 * (1 - ((max_th - th)
613 h2off = dc->wall_height/2 - h2;
615 h2off = h2 - dc->wall_height/2;
622 glBegin(wire ? GL_LINES : GL_QUADS);
623 glNormal3f(x1, y1, 0);
624 glVertex3f(x1, y1, z1 - h1 + h1off);
625 glVertex3f(x1, y1, z1 + h1 + h1off);
626 glNormal3f(x2, y2, 0);
627 glVertex3f(x2, y2, z2 + h2 + h2off);
628 glVertex3f(x2, y2, z2 - h2 + h2off);
635 glBegin(wire ? GL_LINES : GL_QUADS);
636 glNormal3f(-x1b, -y1b, 0);
637 glVertex3f( x1b, y1b, z1 - h1 + h1off);
638 glVertex3f( x1b, y1b, z1 + h1 + h1off);
639 glNormal3f(-x2b, -y2b, 0);
640 glVertex3f( x2b, y2b, z2 + h2 + h2off);
641 glVertex3f( x2b, y2b, z2 - h2 + h2off);
648 /* glNormal3f(0, 0, 1);*/
649 do_normal (x2, y2, z2 + h2 + h2off,
650 x2b, y2b, z2 + h2 + h2off,
651 x1b, y1b, z1 + h1 + h1off);
652 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
653 glVertex3f( x2, y2, z2 + h2 + h2off);
654 glVertex3f( x2b, y2b, z2 + h2 + h2off);
655 glVertex3f( x1b, y1b, z1 + h1 + h1off);
656 glVertex3f( x1, y1, z1 + h1 + h1off);
663 do_normal ( x1, y1, z1 - h1 + h1off,
664 x1b, y1b, z1 - h1 + h1off,
665 x2b, y2b, z2 - h2 + h2off);
666 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
667 glNormal3f(0, 0, -1);
668 glVertex3f( x1, y1, z1 - h1 + h1off);
669 glVertex3f( x1b, y1b, z1 - h1 + h1off);
670 glVertex3f( x2b, y2b, z2 - h2 + h2off);
671 glVertex3f( x2, y2, z2 - h2 + h2off);
691 nx = cos (th + M_PI/2);
692 ny = sin (th + M_PI/2);
693 glNormal3f(nx, ny, 0);
694 glVertex3f(x2, y2, z1 - h2 + h2off);
695 glVertex3f(x2, y2, z1 + h2 + h2off);
696 glVertex3f(x2b, y2b, z1 + h2 + h2off);
697 glVertex3f(x2b, y2b, z1 - h2 + h2off);
706 make_ladder (logo_configuration *dc, int facetted, int wire)
710 GLfloat max_th = dc->turns * M_PI * 2;
711 GLfloat max_z = dc->turns * dc->turn_spacing;
712 GLfloat z_inc = dc->bar_spacing;
713 GLfloat th_inc = M_PI * 2 * (dc->bar_spacing / dc->turn_spacing);
716 /* skip forward to center the bars in the helix... */
718 GLfloat usable_th = max_th - dc->wall_taper;
719 GLfloat usable_z = max_z / (max_th / usable_th);
720 int nbars = usable_z / dc->bar_spacing;
721 GLfloat used_z, pad_z, pad_ratio;
723 if (! (nbars & 1)) nbars--; /* always an odd number of bars */
725 used_z = (nbars - 1) * dc->bar_spacing;
726 pad_z = max_z - used_z;
727 pad_ratio = pad_z / max_z;
729 th = (max_th * pad_ratio/2);
730 z = -(max_z / 2) + (max_z * pad_ratio/2);
733 z = -z, z_inc = -z_inc;
736 for (i = 0; i < nbars; i++)
738 int facets = dc->bar_facets / (facetted ? 14 : 1);
739 if (facets <= 3) facets = 3;
740 x = cos (th) * (1 - dc->wall_thickness);
741 y = sin (th) * (1 - dc->wall_thickness);
742 polys += tube ( x, y, z,
744 dc->bar_thickness, 0, facets,
759 make_gasket (logo_configuration *dc, int wire)
767 GLfloat d2r = M_PI / 180;
769 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 2;
771 GLfloat *pointsx0, *pointsy0, *pointsx1, *pointsy1, *normals;
773 GLfloat r0 = 0.750; /* 395 */
774 GLfloat r1a = 0.825; /* bottom of wall below upper left hole */
775 GLfloat r1b = 0.867; /* center of upper left hole */
776 GLfloat r1c = 0.909; /* top of wall above hole */
777 GLfloat r1 = 0.916; /* 471 */
778 GLfloat r2 = 0.963; /* 490 */
779 GLfloat r3 = 0.960; /* 499 */
780 GLfloat r4 = 1.000; /* 507 */
781 GLfloat r5 = 1.080; /* 553 */
783 GLfloat ctrl_r[100], ctrl_th[100];
787 # ifdef DXF_OUTPUT_HACK
788 if (! wire) res *= 8;
791 # define POINT(r,th) \
792 ctrl_r [nctrls] = r, \
793 ctrl_th[nctrls] = (th * d2r), \
796 POINT (0.829, 0); /* top indentation, right half */
804 POINT (r4, 4.0); /* moving clockwise... */
825 POINT (r4, 316.8); /* upper left indentation */
826 POINT (0.990, 316.87);
827 POINT (0.880, 317.21);
828 POINT (0.872, 317.45);
829 POINT (0.869, 317.80);
830 POINT (0.867, 318.10);
832 POINT (0.867, 318.85);
833 POINT (0.869, 319.15);
834 POINT (0.872, 319.50);
835 POINT (0.880, 319.74);
836 POINT (0.990, 320.08);
841 POINT (r1a, 338.0); /* cut-out disc */
847 POINT (0.872, 356.05); /* top indentation, left half */
848 POINT (0.862, 356.19);
849 POINT (0.851, 356.70);
850 POINT (0.841, 357.35);
851 POINT (0.835, 358.19);
852 POINT (0.831, 359.15);
856 points_size = res + (nctrls * 2);
857 pointsx0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
858 pointsy0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
859 pointsx1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
860 pointsy1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
861 normals = (GLfloat *) malloc (points_size * sizeof(GLfloat) * 2);
864 for (i = 1; i < nctrls; i++)
866 GLfloat from_r = ctrl_r [i-1];
867 GLfloat from_th = ctrl_th[i-1];
868 GLfloat to_r = ctrl_r [i];
869 GLfloat to_th = ctrl_th[i];
871 GLfloat step = 2*M_PI / res;
872 int nsteps = 1 + ((to_th - from_th) / step);
875 for (j = 0; j < nsteps + (i == nctrls-1); j++)
877 GLfloat r = from_r + (j * (to_r - from_r) / nsteps);
878 GLfloat th = from_th + (j * (to_th - from_th) / nsteps);
880 GLfloat cth = cos(th) * dc->gasket_size;
881 GLfloat sth = sin(th) * dc->gasket_size;
883 pointsx0[npoints] = r0 * cth; /* inner ring */
884 pointsy0[npoints] = r0 * sth;
885 pointsx1[npoints] = r * cth; /* outer ring */
886 pointsy1[npoints] = r * sth;
889 if (npoints >= points_size) abort();
893 /* normals for the outer ring */
894 for (i = 1; i < npoints; i++)
905 n = calc_normal (a, b, c);
906 normals[(i-1)*2 ] = n.x;
907 normals[(i-1)*2+1] = n.y;
910 glRotatef(-90, 0, 1, 0);
911 glRotatef(180, 0, 0, 1);
916 for (z = -thick2; z <= thick2; z += thick2*2)
920 glBegin (GL_LINE_LOOP);
921 for (i = 0; i < npoints; i++)
922 glVertex3f (pointsx0[i], pointsy0[i], z);
927 glBegin (GL_LINE_LOOP);
928 for (i = 0; i < npoints; i++)
929 glVertex3f (pointsx1[i], pointsy1[i], z);
933 for (i = 1; i < npoints; i++)
935 glBegin (GL_LINE_STRIP);
936 glVertex3f (pointsx0[i-1], pointsy0[i-1], z);
937 glVertex3f (pointsx0[i ], pointsy0[i ], z);
938 glVertex3f (pointsx1[i ], pointsy1[i ], z);
939 glVertex3f (pointsx1[i-1], pointsy1[i-1], z);
947 for (i = 0; i < npoints; i++)
950 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
951 glVertex3f (pointsx0[i], pointsy0[i], thick2);
953 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
954 glVertex3f (pointsx1[i], pointsy1[i], thick2);
964 glNormal3f(0, 0, -1);
965 glBegin (GL_QUAD_STRIP);
966 for (i = 0; i < npoints; i++)
968 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
969 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
977 glBegin (GL_QUAD_STRIP);
978 for (i = 0; i < npoints; i++)
980 glVertex3f (pointsx0[i], pointsy0[i], thick2);
981 glVertex3f (pointsx1[i], pointsy1[i], thick2);
988 glBegin (GL_QUAD_STRIP);
989 for (i = 0; i < npoints; i++)
991 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
992 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
993 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
1002 for (i = 0; i < npoints-1; i++)
1004 int ia = (i == 0 ? npoints-2 : i-1);
1005 int iz = (i == npoints-2 ? 0 : i+1);
1006 GLfloat x = pointsx1[i];
1007 GLfloat y = pointsy1[i];
1008 GLfloat xz = pointsx1[iz];
1009 GLfloat yz = pointsy1[iz];
1011 GLfloat nxa = normals[ia*2]; /* normal of [i-1 - i] face */
1012 GLfloat nya = normals[ia*2+1];
1013 GLfloat nx = normals[i*2]; /* normal of [i - i+1] face */
1014 GLfloat ny = normals[i*2+1];
1015 GLfloat nxz = normals[iz*2]; /* normal of [i+1 - i+2] face */
1016 GLfloat nyz = normals[iz*2+1];
1018 GLfloat anglea = vector_angle (nx, ny, 0, nxa, nya, 0);
1019 GLfloat anglez = vector_angle (nx, ny, 0, nxz, nyz, 0);
1020 GLfloat pointy = 0.6;
1022 if (anglea > pointy)
1024 glNormal3f (nx, ny, 0);
1025 glVertex3f (x, y, thick2);
1026 glVertex3f (x, y, -thick2);
1030 glNormal3f ((nxa + nx) / 2, (nya + ny) / 2, 0);
1031 glVertex3f (x, y, thick2);
1032 glVertex3f (x, y, -thick2);
1035 if (anglez > pointy)
1037 glNormal3f (nx, ny, 0);
1038 glVertex3f (xz, yz, -thick2);
1039 glVertex3f (xz, yz, thick2);
1043 glNormal3f ((nx + nxz) / 2, (ny + nyz) / 2, 0);
1044 glVertex3f (xz, yz, -thick2);
1045 glVertex3f (xz, yz, thick2);
1053 /* Fill in the upper left hole...
1060 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
1061 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
1063 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
1064 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
1068 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
1069 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
1071 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
1072 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
1077 glNormal3f (0, 0, -1);
1079 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1080 glVertex3f (pointsx0[0], pointsy0[0], -thick2);
1081 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1082 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1083 glVertex3f (pointsx0[2], pointsy0[2], -thick2);
1088 glNormal3f (0, 0, 1);
1089 glFrontFace(GL_CCW);
1090 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1091 glVertex3f (pointsx0[0], pointsy0[0], thick2);
1092 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1093 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1094 glVertex3f (pointsx0[2], pointsy0[2], thick2);
1101 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1102 glNormal3f (pointsx0[1], pointsy0[1], 0);
1103 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1104 glNormal3f (pointsx0[3], pointsy0[3], 0);
1105 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1106 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1107 glNormal3f (pointsx0[1], pointsy0[1], 0);
1108 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1113 /* Now make a donut.
1116 int nsteps = (wire ? 12 : 64);
1119 GLfloat th, cth, sth;
1123 th = ((339.0 + 343.0) / 2) * d2r;
1125 glTranslatef (r1b * cos(th) * dc->gasket_size,
1126 r1b * sin(th) * dc->gasket_size,
1130 for (i = 0; i < nsteps; i++)
1132 th = 2 * M_PI * i / nsteps;
1133 cth = cos (th) * dc->gasket_size;
1134 sth = sin (th) * dc->gasket_size;
1135 pointsx0[npoints] = r0 * cth;
1136 pointsy0[npoints] = r0 * sth;
1137 pointsx1[npoints] = r1 * cth;
1138 pointsy1[npoints] = r1 * sth;
1143 pointsx0[npoints] = pointsx0[0];
1144 pointsy0[npoints] = pointsy0[0];
1145 pointsx1[npoints] = pointsx1[0];
1146 pointsy1[npoints] = pointsy1[0];
1151 glBegin (GL_LINE_LOOP);
1152 for (i = 0; i < npoints; i++)
1153 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1156 glBegin (GL_LINE_LOOP);
1157 for (i = 0; i < npoints; i++)
1158 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1162 glBegin (GL_LINE_LOOP);
1163 for (i = 0; i < npoints; i++)
1164 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1167 glBegin (GL_LINE_LOOP);
1168 for (i = 0; i < npoints; i++)
1169 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1178 glNormal3f(0, 0, -1);
1179 glBegin (GL_QUAD_STRIP);
1180 for (i = 0; i < npoints; i++)
1182 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1183 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1189 glFrontFace(GL_CCW);
1190 glNormal3f(0, 0, 1);
1191 glBegin (GL_QUAD_STRIP);
1192 for (i = 0; i < npoints; i++)
1194 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1195 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1203 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1204 for (i = 0; i < npoints; i++)
1206 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
1207 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
1208 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
1218 /* Attach the bottom-right dingus...
1225 glRotatef (49.5, 0, 0, 1);
1226 glScalef (dc->gasket_size, dc->gasket_size, 1);
1227 glTranslatef (0, (r0+r1)/2, 0);
1232 glFrontFace(GL_CCW);
1233 glBegin (wire ? GL_LINE_STRIP : GL_QUADS);
1234 glNormal3f (0, 0, -1);
1235 glVertex3f (-w/2, -h/2, -thick2); glVertex3f (-w/2, h/2, -thick2);
1236 glVertex3f ( w/2, h/2, -thick2); glVertex3f ( w/2, -h/2, -thick2);
1237 glNormal3f (1, 0, 0);
1238 glVertex3f ( w/2, -h/2, -thick2); glVertex3f ( w/2, h/2, -thick2);
1239 glVertex3f ( w/2, h/2, thick2); glVertex3f ( w/2, -h/2, thick2);
1240 glNormal3f (0, 0, 1);
1241 glVertex3f ( w/2, -h/2, thick2); glVertex3f ( w/2, h/2, thick2);
1242 glVertex3f (-w/2, h/2, thick2); glVertex3f (-w/2, -h/2, thick2);
1243 glNormal3f (-1, 0, 0);
1244 glVertex3f (-w/2, -h/2, thick2); glVertex3f (-w/2, h/2, thick2);
1245 glVertex3f (-w/2, h/2, -thick2); glVertex3f (-w/2, -h/2, -thick2);
1251 for (th = (wire ? 0 : -0.1);
1253 th += (M_PI / (wire ? 5 : 32)))
1255 pointsx0[npoints] = w/2 * cos(th);
1256 pointsy0[npoints] = w/2 * sin(th);
1261 /* front inside curve */
1262 glNormal3f (0, 0, -1);
1264 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1265 if (! wire) glVertex3f (0, h/2, -thick2);
1266 for (i = 0; i < npoints; i++)
1267 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1271 /* front outside curve */
1272 glFrontFace(GL_CCW);
1273 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1274 if (! wire) glVertex3f (0, -h/2, -thick2);
1275 for (i = 0; i < npoints; i++)
1276 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1280 /* back inside curve */
1281 glNormal3f (0, 0, 1);
1282 glFrontFace(GL_CCW);
1283 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1284 if (! wire) glVertex3f (0, h/2, thick2);
1285 for (i = 0; i < npoints; i++)
1286 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1290 /* back outside curve */
1292 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1293 if (! wire) glVertex3f (0, -h/2, thick2);
1294 for (i = 0; i < npoints; i++)
1295 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1300 glFrontFace(GL_CCW);
1301 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1302 for (i = 0; i < npoints; i++)
1304 glNormal3f (pointsx0[i], pointsy0[i], 0);
1305 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1306 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1313 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1314 for (i = 0; i < npoints; i++)
1316 glNormal3f (pointsx0[i], -pointsy0[i], 0);
1317 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1318 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1335 make_frame (logo_configuration *dc, int wire)
1339 GLfloat x[20], y[20];
1340 GLfloat corner_cut = 0.5;
1343 glRotatef (90, 0, 1, 0);
1344 glScalef (4 * dc->frame_size,
1346 4 * dc->frame_size);
1348 x[0] = -dc->frame_thickness;
1349 x[1] = -dc->frame_thickness * corner_cut;
1351 x[3] = 0.5 - dc->triangle_size;
1353 x[5] = 0.5 + dc->triangle_size;
1355 x[7] = 1 + dc->frame_thickness * corner_cut;
1356 x[8] = 1 + dc->frame_thickness;
1358 y[0] = -dc->frame_thickness;
1359 y[1] = -dc->frame_thickness * corner_cut;
1361 y[3] = dc->triangle_size;
1365 glTranslatef (-0.5, -0.5, dc->frame_depth / 4);
1367 for (j = 0; j <= 1; j++)
1369 if (j) glTranslatef (0, 0, -dc->frame_depth / 2);
1370 glFrontFace (j ? GL_CCW : GL_CW);
1371 for (i = 0; i < 4; i++)
1373 glNormal3f (0, 0, (j ? -1 : 1));
1374 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1375 glVertex3f (x[0], y[1], 0); glVertex3f (x[0], y[2], 0);
1376 glVertex3f (x[1], y[0], 0); glVertex3f (x[1], y[2], 0);
1377 glVertex3f (x[3], y[0], 0); glVertex3f (x[3], y[2], 0);
1378 glVertex3f (x[4], y[0], 0); glVertex3f (x[4], y[3], 0);
1379 glVertex3f (x[5], y[0], 0); glVertex3f (x[5], y[2], 0);
1380 glVertex3f (x[7], y[0], 0); glVertex3f (x[7], y[2], 0);
1381 glVertex3f (x[8], y[1], 0); glVertex3f (x[8], y[2], 0);
1384 glTranslatef (0.5, 0.5, 0);
1385 glRotatef (90, 0, 0, 1);
1386 glTranslatef (-0.5, -0.5, 0);
1392 glFrontFace (GL_CCW);
1393 for (i = 0; i < 4; i++)
1395 glNormal3f (0, 1, 0);
1396 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1397 glVertex3f (x[2], y[2], 0); glVertex3f (x[2], y[2], dc->frame_depth/2);
1398 glVertex3f (x[3], y[2], 0); glVertex3f (x[3], y[2], dc->frame_depth/2);
1399 glVertex3f (x[4], y[3], 0); glVertex3f (x[4], y[3], dc->frame_depth/2);
1400 glVertex3f (x[5], y[2], 0); glVertex3f (x[5], y[2], dc->frame_depth/2);
1401 glVertex3f (x[6], y[2], 0); glVertex3f (x[6], y[2], dc->frame_depth/2);
1405 glNormal3f (0, -1, 0);
1406 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1407 glVertex3f (x[7], y[0], 0);
1408 glVertex3f (x[7], y[0], dc->frame_depth/2);
1409 glVertex3f (x[1], y[0], dc->frame_depth/2);
1410 glVertex3f (x[1], y[0], 0);
1414 glNormal3f (1, -1, 0);
1415 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1416 glVertex3f (x[8], y[1], 0);
1417 glVertex3f (x[8], y[1], dc->frame_depth/2);
1418 glVertex3f (x[7], y[0], dc->frame_depth/2);
1419 glVertex3f (x[7], y[0], 0);
1425 glNormal3f (0, 1, 0);
1426 for (j = 0; j <= 1; j++)
1428 glBegin (GL_LINE_STRIP);
1429 glVertex3f (x[2], y[2], j*dc->frame_depth/2);
1430 glVertex3f (x[3], y[2], j*dc->frame_depth/2);
1431 glVertex3f (x[4], y[3], j*dc->frame_depth/2);
1432 glVertex3f (x[5], y[2], j*dc->frame_depth/2);
1433 glVertex3f (x[6], y[2], j*dc->frame_depth/2);
1439 glTranslatef (0.5, 0.5, 0);
1440 glRotatef (90, 0, 0, 1);
1441 glTranslatef (-0.5, -0.5, 0);
1461 tess_error_cb (GLenum errorCode)
1463 fprintf (stderr, "%s: tesselation error: %s\n",
1464 progname, gluErrorString(errorCode));
1469 tess_combine_cb (GLdouble coords[3], GLdouble *d[4], GLfloat w[4],
1470 GLdouble **data_out)
1472 GLdouble *new = (GLdouble *) malloc (3 * sizeof(*new));
1482 tess_vertex_cb (void *vertex_data, void *closure)
1484 tess_out *to = (tess_out *) closure;
1485 GLdouble *v = (GLdouble *) vertex_data;
1486 to->points[to->i++] = v[0];
1487 to->points[to->i++] = v[1];
1488 to->points[to->i++] = v[2];
1493 tess_begin_cb (GLenum which)
1504 #endif /* HAVE_TESS */
1508 make_pizza (logo_configuration *dc, int facetted, int wire)
1511 int topfaces = (facetted ? 48 : 120);
1512 int discfaces = (facetted ? 12 : 120);
1513 int npoints = topfaces * 2 + 100;
1514 GLdouble *points = (GLdouble *) calloc (npoints * 3, sizeof(GLdouble));
1516 GLdouble *holes = (GLdouble *) calloc (topfaces*nholes*3, sizeof(GLdouble));
1518 GLfloat step = M_PI * 2 / 6 / topfaces;
1519 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 4;
1520 GLfloat th, x, y, s;
1525 tess_out TO, *to = &TO;
1526 GLUtesselator *tess = gluNewTess();
1528 to->points = (GLdouble *) calloc (topfaces * 20, sizeof(GLdouble));
1531 # ifndef _GLUfuncptr
1532 # define _GLUfuncptr void(*)(void)
1535 gluTessCallback(tess,GLU_TESS_BEGIN, (_GLUfuncptr)tess_begin_cb);
1536 gluTessCallback(tess,GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv);
1537 gluTessCallback(tess,GLU_TESS_END, (_GLUfuncptr)tess_end_cb);
1538 gluTessCallback(tess,GLU_TESS_COMBINE, (_GLUfuncptr)tess_combine_cb);
1539 gluTessCallback(tess,GLU_TESS_ERROR, (_GLUfuncptr)tess_error_cb);
1541 gluTessProperty (tess, GLU_TESS_BOUNDARY_ONLY, wire);
1542 gluTessProperty (tess,GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
1544 # endif /* HAVE_TESS */
1549 glRotatef (180, 0, 0, 1);
1551 glRotatef (90, 0, 1, 0);
1552 glTranslatef (-0.53, 0, 0);
1553 glRotatef (-30, 0, 0, 1);
1555 /* Compute the wedge */
1568 for (i = 0; i < countof(edge)/2; i++)
1570 points[j++] = edge[i*2+1];
1571 points[j++] = edge[i*2];
1576 s = 0.798; /* radius of end of slice, before crust gap */
1577 for (i = 0; i < topfaces; i++)
1579 points[j++] = cos(th) * s;
1580 points[j++] = sin(th) * s;
1597 for (i = 0; i < countof(edge)/2; i++)
1599 points[j++] = edge[i*2+1];
1600 points[j++] = edge[i*2];
1607 /* Draw the rim of the slice */
1608 glBegin (wire ? GL_LINES : GL_QUADS);
1611 for (i = (wire ? 0 : 1); i < endpoints; i++)
1613 GLdouble *p = points + (i*3);
1615 do_normal (p[0], p[1], -thick2,
1620 glVertex3f (x, y, -thick2);
1621 glVertex3f (x, y, thick2);
1623 glVertex3f (p[0], p[1], thick2);
1624 glVertex3f (p[0], p[1], -thick2);
1630 do_normal (points[0], points[1], -thick2,
1631 points[0], points[1], thick2,
1633 glVertex3f (x, y, -thick2);
1634 glVertex3f (x, y, thick2);
1635 glVertex3f (points[0], points[1], thick2);
1636 glVertex3f (points[0], points[1], -thick2);
1643 /* Outline of slice */
1644 glBegin (GL_LINE_LOOP);
1645 for (i = 0; i < endpoints; i++)
1646 glVertex3f (points[i*3], points[i*3+1], -thick2);
1648 glBegin (GL_LINE_LOOP);
1649 for (i = 0; i < endpoints; i++)
1650 glVertex3f (points[i*3], points[i*3+1], thick2);
1653 # endif /* HAVE_TESS */
1655 /* Compute the holes */
1656 step = M_PI * 2 / discfaces;
1657 for (k = 0; k < nholes; k++)
1659 GLdouble *p = holes + (discfaces * 3 * k);
1663 case 0: x = 0.34; y = 0.17; s = 0.05; break;
1664 case 1: x = 0.54; y = 0.17; s = 0.06; break;
1665 case 2: x = 0.55; y = 0.36; s = 0.06; break;
1666 default: abort(); break;
1668 for (i = 0; i < discfaces; i++)
1670 p[j++] = x + cos(M_PI*2 - th) * s;
1671 p[j++] = y + sin(M_PI*2 - th) * s;
1678 /* Draw the inside rim of the holes */
1679 for (k = 0; k < nholes; k++)
1681 GLdouble *p = holes + (discfaces * 3 * k);
1683 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1684 for (i = 0; i < discfaces; i++)
1686 GLdouble *p2 = p + (i*3);
1688 do_normal (p2[0], p2[1], -thick2,
1689 p2[0], p2[1], thick2,
1690 p2[-3], p2[-2], thick2);
1691 glVertex3f (p2[0], p2[1], -thick2);
1692 glVertex3f (p2[0], p2[1], thick2);
1695 glVertex3f (p[0], p[1], -thick2);
1696 glVertex3f (p[0], p[1], thick2);
1702 /* Outline of holes */
1703 glBegin (GL_LINE_LOOP);
1704 for (i = 0; i < discfaces; i++)
1705 glVertex3f (p[i*3], p[i*3+1], -thick2);
1707 glBegin (GL_LINE_LOOP);
1708 for (i = 0; i < discfaces; i++)
1709 glVertex3f (p[i*3], p[i*3+1], thick2);
1712 # endif /* !HAVE_TESS */
1716 glTranslatef (0, 0, -thick2);
1717 for (y = 0; y <= 1; y++)
1719 if (y) glTranslatef (0, 0, thick2*2);
1721 /* A non-convex polygon */
1722 gluTessBeginPolygon (tess, to);
1724 glNormal3f (0, 0, (y > 0 ? 1 : -1));
1725 gluTessNormal (tess, 0, 0, (y > 0 ? 1 : -1));
1726 glFrontFace (GL_CCW);
1728 /* Tess the wedge */
1729 gluTessBeginContour (tess);
1730 for (i = 0; i < endpoints; i++)
1732 GLdouble *p = points + (i*3);
1733 gluTessVertex (tess, p, p);
1736 gluTessVertex (tess, points, points);
1737 gluTessEndContour (tess);
1739 /* Tess the holes */
1740 for (k = 0; k < nholes; k++)
1742 GLdouble *p = holes + (discfaces * 3 * k);
1743 gluTessBeginContour (tess);
1744 for (i = 0; i < discfaces; i++)
1746 GLdouble *p2 = p + (i*3);
1747 gluTessVertex (tess, p2, p2);
1750 gluTessEndContour (tess);
1753 gluTessEndPolygon (tess);
1756 glTranslatef (0, 0, -thick2);
1758 # else /* !HAVE_TESS */
1761 glTranslatef(0, 0, thick2);
1762 glNormal3f (0, 0, 1);
1763 glFrontFace (GL_CW);
1765 /* Sadly, jwzgl's glVertexPointer seems not to be recordable inside
1768 glDisableClientState (GL_COLOR_ARRAY);
1769 glDisableClientState (GL_NORMAL_ARRAY);
1770 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1771 glEnableClientState (GL_VERTEX_ARRAY);
1772 glVertexPointer (3, GL_FLOAT, 0, dnapizza_triangles);
1773 glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
1775 glBegin (GL_TRIANGLES);
1776 for (i = 0; i < countof (dnapizza_triangles); i += 3)
1777 glVertex3fv (dnapizza_triangles + i);
1781 glTranslatef(0, 0, -thick2*2);
1782 glNormal3f (0, 0, -1);
1783 glFrontFace (GL_CCW);
1786 glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
1789 glBegin (GL_TRIANGLES);
1790 for (i = 0; i < countof (dnapizza_triangles); i += 3)
1791 glVertex3fv (dnapizza_triangles + i);
1795 glTranslatef(0, 0, thick2);
1797 # endif /* !HAVE_TESS */
1800 /* Compute the crust */
1802 s = 0.861; /* radius of inside of crust */
1803 step = M_PI * 2 / 6 / topfaces;
1806 for (i = 0; i < topfaces; i++)
1808 points[j++] = cos(th) * s;
1809 points[j++] = sin(th) * s;
1815 for (i = 0; i < topfaces; i++)
1817 points[j++] = cos(th) * s;
1818 points[j++] = sin(th) * s;
1823 /* Draw the rim of the crust */
1824 glFrontFace (GL_CCW);
1825 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1826 for (i = 0; i < topfaces * 2; i++)
1828 GLdouble *p = points + (i*3);
1829 if (i == 0 || i == (topfaces*2)-1)
1830 glNormal3f (0, -1, 0);
1831 else if (i == topfaces-1 || i == topfaces)
1832 glNormal3f (0, 1, 0);
1834 do_normal (p[-3], p[-2], thick2,
1836 p[0], p[1], -thick2);
1837 glVertex3f (p[0], p[1], -thick2);
1838 glVertex3f (p[0], p[1], thick2);
1841 glVertex3f (points[0], points[1], -thick2);
1842 glVertex3f (points[0], points[1], thick2);
1848 glBegin (GL_LINE_STRIP);
1849 for (i = 0; i < topfaces * 2; i++)
1851 GLdouble *p = points + (i*3);
1852 glVertex3f (p[0], p[1], -thick2);
1855 glVertex3f (points[0], points[1], -thick2);
1858 glBegin (GL_LINE_STRIP);
1859 for (i = 0; i < topfaces * 2; i++)
1861 GLdouble *p = points + (i*3);
1862 glVertex3f (p[0], p[1], thick2);
1865 glVertex3f (points[0], points[1], thick2);
1869 /* Draw the top of the crust */
1872 glFrontFace (GL_CW);
1873 glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP);
1874 glNormal3f (0, 0, -1);
1876 for (i = 0; i < topfaces; i++)
1878 int ii = topfaces + (topfaces - i - 1);
1879 GLdouble *p1 = points + (i*3);
1880 GLdouble *p2 = points + (ii*3);
1881 glVertex3f (p1[0], p1[1], -thick2);
1882 glVertex3f (p2[0], p2[1], -thick2);
1888 /* Draw the bottom of the crust */
1889 glFrontFace (GL_CCW);
1890 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1891 glNormal3f (0, 0, 1);
1892 for (i = 0; i < topfaces; i++)
1894 int ii = topfaces + (topfaces - i - 1);
1895 GLdouble *p1 = points + (i*3);
1896 GLdouble *p2 = points + (ii*3);
1897 glVertex3f (p1[0], p1[1], thick2);
1898 glVertex3f (p2[0], p2[1], thick2);
1906 gluDeleteTess (tess);
1908 # endif /* HAVE_TESS */
1919 /* Upcase string, convert Unicrud to ASCII, remove any non-letters.
1922 codeword_simplify_text (const char *s0)
1924 char *s1 = utf8_to_latin1 ((s0 ? s0 : ""), True);
1926 char *s2 = (char *) malloc (L + 10);
1929 for (i = 0; i < L; i++)
1932 if (c >= 'a' && c <= 'z')
1934 if (c >= 'A' && c <= 'Z')
1939 strcpy (s2, "CODEWORD");
1945 make_codeword_path (ModeInfo *mi)
1947 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
1948 int letters = strlen (dc->codeword_text);
1950 GLfloat rtick = dc->codeword_spread;
1951 GLfloat iradius = rtick * dc->codeword_cap_size;
1957 GLfloat inner_circum = M_PI * 2 * (iradius + rtick * 2);
1958 GLfloat outer_circum = M_PI * 2 * (iradius + rtick * (letters + 1));
1959 GLfloat facet_length = inner_circum / (26 * dc->codeword_facets);
1960 int outer_facets = ceil (outer_circum / facet_length);
1962 int *histo = (int *) calloc (letters * 26, sizeof(*histo));
1963 XYZ *points = (XYZ *) calloc (letters * outer_facets, sizeof (*points));
1966 for (letter = -1; letter < letters; letter++)
1968 if (letter == -1) /* Inner starting point */
1970 points[npoints].x = iradius;
1971 points[npoints].y = 0;
1975 else /* Add arc for this letter */
1977 int direction = (letter & 1 ? -1 : 1);
1978 int v = (dc->codeword_text[letter] - 'A' + 1);
1979 int dial1 = dial + v * direction;
1982 GLfloat th0 = M_PI * 2 / 26 * dial;
1983 GLfloat th1 = M_PI * 2 / 26 * dial1;
1984 GLfloat r = iradius + rtick * (letter + 2);
1985 GLfloat circum = M_PI * 2 * r;
1986 GLfloat arc_length = circum * v / 26;
1987 int arc_facets = ceil (fabs (arc_length / facet_length));
1988 GLfloat facet_th = (th1 - th0) / arc_facets;
1990 if (arc_facets > outer_facets) abort();
1992 /* Let's put some intermediate facets on the crossbars too,
1993 so that the animation doesn't speed up on those. */
1996 for (rr = last_r + facet_length;
1997 rr <= r - facet_length;
2000 points[npoints].x = rr * cos (th0);
2001 points[npoints].y = rr * sin (th0);
2010 ? th <= th1 + facet_th
2011 : th >= th1 + facet_th);
2015 if (th0 < th1 && th > th1)
2017 if (th0 > th1 && th < th1)
2019 points[npoints].x = r * cos (th2);
2020 points[npoints].y = r * sin (th2);
2022 /* Ugh, add point only if it differs from prev.
2023 Not sure how this happens. */
2025 points[npoints-1].x != points[npoints].x ||
2026 points[npoints-1].y != points[npoints].y)
2030 /* Mark up the histo array to find the outer border. */
2039 int x = (i + 26) % 26;
2041 for (y = 0; y <= letter; y++)
2042 histo[y * 26 + x]++;
2046 dc->codeword_text_points[letter] = npoints;
2052 if (npoints >= letters * outer_facets) abort();
2057 for (y = 0; y < letters; y++)
2059 fprintf (stderr, "%2d: ", y);
2060 for (x = 0; x < 26; x++)
2061 fprintf (stderr, "%x", histo[y * 26 + x]);
2062 fprintf (stderr, "\n");
2064 fprintf (stderr, "\n");
2069 /* Find a gap in the outer edge, to draw guide dots. */
2072 int last_row = letters;
2073 int start_dial = -1, end_dial = -1;
2075 for (y = letters-1; y >= 0; y--)
2077 for (x = 0; x < 26; x++)
2079 if (histo[y * 26 + x] == 0)
2082 start_dial = end_dial = -1;
2084 if (start_dial == -1)
2091 if (last_row < letters-1 && start_dial >= 0)
2093 GLfloat r = iradius + rtick * (last_row + 2);
2096 dc->codeword_nguides = 0;
2097 dc->codeword_guides = (XYZ *)
2098 calloc (end_dial - start_dial + 1, sizeof (*dc->codeword_guides));
2099 for (i = start_dial; i <= end_dial; i++)
2101 GLfloat th = i * M_PI * 2 / 26;
2102 GLfloat x = r * cos (th);
2103 GLfloat y = r * sin (th);
2104 dc->codeword_guides[dc->codeword_nguides].x = x;
2105 dc->codeword_guides[dc->codeword_nguides].y = y;
2106 dc->codeword_nguides++;
2113 dc->codeword_path_npoints = npoints;
2114 dc->codeword_path = points;
2119 draw_codeword_cap (ModeInfo *mi)
2121 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2122 int wire = MI_IS_WIREFRAME(mi);
2125 int segments = dc->codeword_disc_facets;
2126 GLfloat size = dc->codeword_spread * dc->codeword_cap_size;
2127 GLfloat width = dc->codeword_line_width / 2;
2128 GLfloat thick = dc->codeword_thickness / 2;
2129 GLfloat r1 = size + width/2;
2130 GLfloat r2 = size - width/2;
2131 GLfloat facet, th, z;
2133 if (wire) segments = 12;
2134 facet = M_PI * 2 / segments;
2138 /* Top and bottom */
2140 for (z = -thick; z <= thick; z += thick*2)
2142 glNormal3f (0, 0, (z < 0 ? -1 : 1));
2143 glFrontFace (z < 0 ? GL_CCW : GL_CW);
2145 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
2146 for (th = 0; th <= M_PI*2; th += facet)
2148 GLfloat x = cos (th);
2149 GLfloat y = sin (th);
2150 glVertex3f (r1 * x, r1 * y, z);
2151 glVertex3f (r2 * x, r2 * y, z);
2157 glBegin (GL_LINE_LOOP);
2158 for (th = 0; th <= M_PI*2; th += facet)
2160 GLfloat x = cos (th);
2161 GLfloat y = sin (th);
2162 glVertex3f (r1 * x, r1 * y, z);
2165 glBegin (GL_LINE_LOOP);
2166 for (th = 0; th <= M_PI*2; th += facet)
2168 GLfloat x = cos (th);
2169 GLfloat y = sin (th);
2170 glVertex3f (r2 * x, r2 * y, z);
2176 /* Inside and outside */
2178 for (z = -1; z <= 1; z += 2)
2180 glFrontFace (z < 0 ? GL_CCW : GL_CW);
2182 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
2183 for (th = 0; th <= M_PI*2; th += facet)
2185 GLfloat th1 = th + facet;
2186 GLfloat x0 = cos (th);
2187 GLfloat y0 = sin (th);
2188 GLfloat x1 = cos (th1);
2189 GLfloat y1 = sin (th1);
2190 GLfloat r = z < 0 ? r1 : r2;
2193 do_normal (r * x0, r * y0, thick,
2194 r * x0, r * y0, -thick,
2195 r * x1, r * y1, -thick);
2197 do_normal (r * x1, r * y1, thick,
2198 r * x1, r * y1, -thick,
2199 r * x0, r * y0, -thick);
2201 glVertex3f (r * x0, r * y0, thick);
2202 glVertex3f (r * x0, r * y0, -thick);
2214 draw_codeword_guides (ModeInfo *mi, GLfloat anim_ratio)
2216 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2217 int wire = MI_IS_WIREFRAME(mi);
2220 int segments = dc->codeword_disc_facets;
2221 GLfloat s = dc->codeword_line_width / 2;
2222 GLfloat each = 1.0 / dc->codeword_nguides;
2225 if (wire) segments = 6;
2227 for (i = 0; i < dc->codeword_nguides; i++)
2230 if (anim_ratio < i*each) ratio = 0;
2231 else if (anim_ratio >= (i+1)*each) ratio = 1;
2232 else ratio = (anim_ratio - i*each) / each;
2234 if (ratio <= 0) continue;
2235 if (ratio == 0) ratio = 0.001;
2238 glTranslatef (dc->codeword_guides[i].x,
2239 dc->codeword_guides[i].y,
2240 dc->codeword_guides[i].z);
2242 glScalef (ratio, ratio, ratio);
2244 /* If the line width and thickness are pretty close to each other,
2245 use spheres. Otherwise use tubes.
2247 if (dc->codeword_thickness < dc->codeword_line_width * 1.3 &&
2248 dc->codeword_thickness > dc->codeword_line_width / 1.3)
2251 glFrontFace (GL_CCW);
2252 polys += unit_sphere (segments, segments, wire);
2256 polys += tube (0, 0, -dc->codeword_thickness / 2,
2257 0, 0, dc->codeword_thickness / 2,
2258 s, 0, segments, True, True, wire);
2268 /* Compute the characters at which the cursor is currently pointing,
2269 and render it on the logo.
2272 codeword_text_output (ModeInfo *mi, GLfloat anim_ratio)
2274 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2276 int L = strlen (dc->codeword_text);
2277 int point = dc->codeword_path_npoints * anim_ratio;
2280 if (dc->anim_state == CODEWORD_BLANK)
2283 for (i = 0; i < L; i++)
2285 if (point >= dc->codeword_text_points[i])
2286 dc->codeword_text_out[i] = dc->codeword_text[i];
2288 dc->codeword_text_out[i] = 0;
2291 int steps = dc->codeword_text[i] - 'A' + 1;
2292 int last = (i > 0 ? dc->codeword_text_points[i-1] : 0);
2293 double ratio = ((point - last) /
2294 (double) (dc->codeword_text_points[i] - last));
2295 char chr = 'A' + (ratio * steps);
2296 if (ratio < 0.1) chr = 0;
2297 dc->codeword_text_out[i] = chr;
2301 dc->codeword_text_out[i] = 0;
2303 if (*dc->codeword_text_out &&
2304 !strcmp (dc->codeword_text, "CODEWORD"))
2307 int L2 = strlen (dc->codeword_text_out);
2309 int ascent, descent;
2312 glColor4fv (dc->codeword_color);
2313 glRotatef (90, 0, 1, 0);
2314 glRotatef (-90, 0, 0, 1);
2316 for (i = 0; i < L2; i++)
2321 glRotatef ((i + 0.5) * 360 / 26.0, 0, 0, 1);
2326 glDisable(GL_LIGHTING);
2331 glBegin(GL_LINE_STRIP);
2332 for (th = M_PI * 1.45; th < M_PI * 1.55; th += 0.1)
2335 glVertex3f (r * cos(th), r * sin(th), 0);
2338 if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING);
2342 glTranslatef (0, -dc->codeword_spread * (L - 1), 0);
2343 glScalef (ss, ss, ss);
2344 buf[0] = dc->codeword_text_out[i] + ('a' - 'A');
2346 texture_string_metrics (dc->font, buf, &e, &ascent, &descent);
2349 /* #### Magic magic magic WTF... */
2350 glScalef (0.5, 0.5, 0.5);
2353 glTranslatef (-e.width * 1.0,
2354 -(ascent + descent + e.descent * 2.4), /* #### WTF */
2360 glDisable(GL_LIGHTING);
2361 glBegin(GL_LINE_LOOP);
2362 glVertex3f(0, 0, 0);
2363 glVertex3f(e.width, 0, 0);
2364 glVertex3f(e.width, e.ascent + e.descent, 0);
2365 glVertex3f(0, e.ascent + e.descent, 0);
2367 if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING);
2370 glDisable(GL_CULL_FACE); /* tell texfont.c to draw both sides */
2371 print_texture_string (dc->font, buf);
2372 glEnable(GL_CULL_FACE);
2381 /* Convert the precomputed path to a thick line of polygons.
2382 We could actually precompute all of these polygons too,
2383 but it's fast enough.
2386 draw_codeword_path (ModeInfo *mi)
2388 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2389 int wire = MI_IS_WIREFRAME(mi);
2392 GLfloat anim_ratio = (dc->anim_state == CODEWORD_IN ? dc->anim_ratio :
2393 dc->anim_state == CODEWORD_OUT ? 1 - dc->anim_ratio :
2394 dc->anim_state == CODEWORD_BLANK ? 0 :
2396 int last_anim_point = 0;
2398 GLfloat width = dc->codeword_line_width / 2;
2399 GLfloat thick = dc->codeword_thickness / 2;
2403 int quad_size = (dc->codeword_path_npoints + 1) * 2;
2404 XYZ *quads = (XYZ *) calloc (quad_size, sizeof(*quads));
2405 XYZ *norms = (XYZ *) calloc (quad_size, sizeof(*norms));
2408 for (i = 0; i < dc->codeword_path_npoints; i++)
2410 XYZ p1 = dc->codeword_path[i];
2411 XYZ p2 = (i < dc->codeword_path_npoints-1
2412 ? dc->codeword_path[i+1]
2413 : dc->codeword_path[i-1]);
2416 XYZ n; /* normal of the first line segment */
2417 n.x = -(p2.y - p1.y);
2418 n.y = (p2.x - p1.x);
2424 p1a.x = p1.x - width / 2 * n.x;
2425 p1a.y = p1.y - width / 2 * n.y;
2428 p1b.x = p1.x + width / 2 * n.x;
2429 p1b.y = p1.y + width / 2 * n.y;
2432 else if (i == dc->codeword_path_npoints - 1)
2434 p1b.x = p1.x - width / 2 * n.x;
2435 p1b.y = p1.y - width / 2 * n.y;
2438 p1a.x = p1.x + width / 2 * n.x;
2439 p1a.y = p1.y + width / 2 * n.y;
2444 XYZ p0 = dc->codeword_path[i-1];
2446 XYZ t, t0, t1; /* tangent of corner between two line segments */
2447 XYZ m; /* miter line: normal of tangent */
2448 GLfloat d; /* length of miter */
2469 /* find length of miter by projecting it on one of the normals */
2470 d = width / 2 / dot (m, n);
2472 p1a.x = p1.x - d * m.x;
2473 p1a.y = p1.y - d * m.y;
2476 p1b.x = p1.x + d * m.x;
2477 p1b.y = p1.y + d * m.y;
2481 quads[nquads++] = p1a;
2482 quads[nquads++] = p1b;
2484 if (nquads >= quad_size) abort();
2486 if (i / (double) dc->codeword_path_npoints > anim_ratio)
2489 last_anim_point = i;
2493 /* Compute normals for each point along the interior edge */
2494 for (k = 0; k <= 1; k++)
2496 for (i = k; i < nquads-2; i += 2)
2499 XYZ p2a = quads[i+2];
2502 p1a.z = thick; /* a: top */
2503 p1b.z = -thick; /* b: bottom */
2508 ? calc_normal (p1a, p1b, p2b)
2509 : calc_normal (p2a, p2b, p1a));
2514 glColor4fv (dc->codeword_color);
2515 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, dc->codeword_color);
2517 # ifdef HAVE_MOBILE /* Make the whole thing fit on the phone screen */
2519 GLfloat size = MI_WIDTH(mi) < MI_HEIGHT(mi) ? MI_WIDTH(mi) : MI_HEIGHT(mi);
2520 glScalef (0.9, 0.9, 0.9);
2521 if (size <= 768) /* iPad retina / iPhone 6 */
2522 glScalef (0.7, 0.7, 0.7);
2526 codeword_text_output (mi, anim_ratio);
2528 glRotatef (90, 1, 0, 0);
2529 glRotatef (90, 0, 1, 0);
2530 glRotatef (-90, 0, 0, 1);
2531 glScalef (0.8, 0.8, 0.8);
2533 glNormal3f (0, 0, -1);
2535 if (anim_ratio <= 0)
2537 polys += draw_codeword_cap (mi);
2542 glColor3f (1, 0, 0);
2543 glBegin(GL_LINE_STRIP);
2544 for (i = 0; i < dc->codeword_path_npoints; i++)
2546 glVertex3f (dc->codeword_path[i].x,
2547 dc->codeword_path[i].y,
2548 dc->codeword_path[i].z);
2552 glColor4fv (dc->codeword_color);
2559 for (i = 0; i <= 1; i++)
2560 for (j = -thick; j <= thick; j += thick*2)
2562 glBegin (GL_LINE_STRIP);
2563 for (k = i; k < nquads; k += 2)
2565 glVertex3f (quads[k].x, quads[k].y, j);
2572 /* Top and bottom */
2574 for (j = -thick; j <= thick; j += thick*2)
2578 glNormal3f (0, 0, -1);
2579 glFrontFace (GL_CW);
2583 glNormal3f (0, 0, 1);
2584 glFrontFace (GL_CCW);
2586 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
2587 for (i = 0; i < nquads; i += 2)
2589 glVertex3f (quads[i+1].x, quads[i+1].y, j);
2590 glVertex3f (quads[i].x, quads[i].y, j);
2598 for (k = 0; k <= 1; k++)
2602 glNormal3f (0, 0, -1);
2603 glFrontFace (GL_CW);
2607 glNormal3f (0, 0, 1);
2608 glFrontFace (GL_CCW);
2611 glBegin (wire ? GL_LINES : GL_QUADS);
2612 for (i = k; i < nquads; i += 2)
2615 XYZ p2a = (i < nquads-2) ? quads[i+2] : p1a;
2620 XYZ n2 = (i < nquads-2) ? norms[i+2] : n1;
2622 /* If the two normals are very similar, smooth the face.
2623 If they are different, it's a sharp turn, and use the
2624 same normal for both edges (not quite right, but close).
2626 GLfloat angle = vector_angle (n1.x, n1.y, n1.z,
2628 GLfloat pointy = 0.8;
2635 glNormal3f (n1.x, n1.y, n1.z);
2636 glVertex3f (p1a.x, p1a.y, p1a.z);
2637 glVertex3f (p1b.x, p1b.y, p1b.z);
2640 glNormal3f (n2.x, n2.y, n2.z);
2641 glVertex3f (p2b.x, p2b.y, p2b.z);
2642 glVertex3f (p2a.x, p2a.y, p2a.z);
2649 /* Only draw the guides when the path is almost complete;
2650 fade them in and out based on completeness. */
2652 GLfloat size = 0.95;
2653 GLfloat r = (anim_ratio > size
2654 ? (anim_ratio - size) / (1 - size)
2656 polys += draw_codeword_guides (mi, r);
2660 /* Draw the start and end caps */
2663 GLfloat x, y, z, x2, y2, z2, X, Y, Z;
2664 GLfloat r = dc->codeword_spread * dc->codeword_cap_size;
2667 x = dc->codeword_path[i].x;
2668 y = dc->codeword_path[i].y;
2669 z = dc->codeword_path[i].z;
2674 glTranslatef (x, y, z);
2675 polys += draw_codeword_cap (mi);
2680 i = last_anim_point + 1;
2681 if (i > dc->codeword_path_npoints - 1)
2682 i = dc->codeword_path_npoints - 1;
2684 x = dc->codeword_path[i].x;
2685 y = dc->codeword_path[i].y;
2686 z = dc->codeword_path[i].z;
2689 x2 = dc->codeword_path[i].x;
2690 y2 = dc->codeword_path[i].y;
2691 z2 = dc->codeword_path[i].z;
2698 glTranslatef (x, y, z);
2699 glRotatef (-atan2 (X, Y) * (180 / M_PI), 0, 0, 1);
2700 glRotatef ( atan2 (Z, sqrt(X*X + Y*Y)) * (180 / M_PI), 1, 0, 0);
2701 glTranslatef (0, -r, 0);
2702 polys += draw_codeword_cap (mi);
2718 /* Window management, etc
2721 reshape_logo (ModeInfo *mi, int width, int height)
2723 GLfloat h = (GLfloat) height / (GLfloat) width;
2725 glViewport (0, 0, (GLint) width, (GLint) height);
2727 glMatrixMode(GL_PROJECTION);
2729 gluPerspective (30.0, 1/h, 1.0, 100.0);
2731 glMatrixMode(GL_MODELVIEW);
2733 gluLookAt( 0.0, 0.0, 30.0,
2737 # ifdef HAVE_MOBILE /* Keep it the same relative size when rotated. */
2739 int o = (int) current_device_rotation();
2740 if (o != 0 && o != 180 && o != -180)
2741 glScalef (1/h, 1/h, 1/h); /* #### Why does this change the lighting? */
2745 glClear(GL_COLOR_BUFFER_BIT);
2750 gl_init (ModeInfo *mi)
2752 /* logo_configuration *dc = &dcs[MI_SCREEN(mi)]; */
2753 int wire = MI_IS_WIREFRAME(mi);
2755 GLfloat position[] = {0, 0, 0, 0};
2756 GLfloat direction[] = {3, -1, -3};
2758 position[0] = -direction[0];
2759 position[1] = -direction[1];
2760 position[2] = -direction[2];
2764 glLightfv(GL_LIGHT0, GL_POSITION, position);
2765 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction);
2766 glShadeModel(GL_SMOOTH);
2767 glEnable(GL_NORMALIZE);
2768 glEnable(GL_CULL_FACE);
2769 glEnable(GL_LIGHTING);
2770 glEnable(GL_LIGHT0);
2771 glEnable(GL_DEPTH_TEST);
2777 init_logo (ModeInfo *mi)
2779 logo_configuration *dc;
2780 int do_gasket = get_boolean_resource(mi->dpy, "doGasket", "Boolean");
2781 int do_helix = get_boolean_resource(mi->dpy, "doHelix", "Boolean");
2782 int do_ladder = (do_helix &&
2783 get_boolean_resource(mi->dpy, "doLadder", "Boolean"));
2784 int do_frame = get_boolean_resource(mi->dpy, "doFrame", "Boolean");
2785 GLfloat helix_rot = 147.0;
2787 if (!do_gasket && !do_helix)
2789 fprintf (stderr, "%s: no helix or gasket?\n", progname);
2794 dcs = (logo_configuration *)
2795 calloc (MI_NUM_SCREENS(mi), sizeof (logo_configuration));
2797 fprintf(stderr, "%s: out of memory\n", progname);
2802 dc = &dcs[MI_SCREEN(mi)];
2804 if ((dc->glx_context = init_GL(mi)) != NULL) {
2806 reshape_logo (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
2809 dc->wall_facets = get_integer_resource(mi->dpy, "wallFacets", "Integer");
2810 dc->bar_facets = get_integer_resource(mi->dpy, "barFacets", "Integer");
2811 dc->clockwise = get_boolean_resource(mi->dpy, "clockwise", "Boolean");
2812 dc->turns = get_float_resource(mi->dpy, "turns", "Float");
2813 dc->turn_spacing = get_float_resource(mi->dpy, "turnSpacing", "Float");
2814 dc->bar_spacing = get_float_resource(mi->dpy, "barSpacing", "Float");
2815 dc->wall_height = get_float_resource(mi->dpy, "wallHeight", "Float");
2816 dc->wall_thickness = get_float_resource(mi->dpy, "wallThickness", "Float");
2817 dc->bar_thickness = get_float_resource(mi->dpy, "barThickness", "Float");
2818 dc->wall_taper = get_float_resource(mi->dpy, "wallTaper", "Float");
2820 dc->gasket_size = get_float_resource(mi->dpy,"gasketSize", "Float");
2821 dc->gasket_depth = get_float_resource(mi->dpy,"gasketDepth", "Float");
2822 dc->gasket_thickness = get_float_resource(mi->dpy,"gasketThickness","Float");
2824 dc->frame_size = get_float_resource(mi->dpy, "frameSize", "Float");
2825 dc->frame_depth = get_float_resource(mi->dpy, "frameDepth", "Float");
2826 dc->frame_thickness = get_float_resource(mi->dpy, "frameThickness", "Float");
2827 dc->triangle_size = get_float_resource(mi->dpy, "triangleSize", "Float");
2829 dc->speed = get_float_resource(mi->dpy, "speed", "Float");
2830 dc->codeword_text = get_string_resource(mi->dpy, "text", "String");
2831 dc->codeword_text = codeword_simplify_text (dc->codeword_text);
2832 dc->codeword_text_out =
2833 calloc (strlen(dc->codeword_text) + 1, sizeof(*dc->codeword_text_out));
2834 dc->codeword_text_points =
2835 (int *) calloc (strlen(dc->codeword_text) + 1,
2836 sizeof(*dc->codeword_text_points));
2838 dc->codeword_facets = get_integer_resource(mi->dpy, "cwFacets", "Integer");
2839 dc->codeword_disc_facets = get_integer_resource(mi->dpy,
2840 "cwDiscFacets", "Integer");
2841 dc->codeword_spread = get_float_resource(mi->dpy, "cwSpread", "Float");
2842 dc->codeword_line_width = get_float_resource(mi->dpy, "cwLineWidth", "Float");
2843 dc->codeword_thickness = get_float_resource(mi->dpy, "cwThickness", "Float");
2844 dc->codeword_cap_size = get_float_resource(mi->dpy, "cwCapSize", "Float");
2847 char *s = get_string_resource (MI_DISPLAY (mi), "mode", "String");
2848 if (!s || !*s || !strcasecmp (s, "helix"))
2850 else if (!strcasecmp (s, "pizza"))
2852 else if (!strcasecmp (s, "both"))
2853 dc->mode = HELIX_AND_PIZZA;
2854 else if (!strcasecmp (s, "codeword"))
2855 dc->mode = CODEWORD_IN;
2859 "%s: mode must be helix, pizza, both or codeword, not \"%s\"\n",
2865 dc->anim_state = (dc->mode == HELIX_AND_PIZZA
2866 ? ((random() & 1) ? HELIX : PIZZA)
2871 if (dc->mode == CODEWORD_IN)
2872 dc->font = load_texture_font (MI_DISPLAY(mi), "cwFont");
2878 get_string_resource (mi->dpy, "foreground", "Foreground");
2880 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
2881 if (*s2 == ' ' || *s2 == '\t')
2886 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
2888 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
2892 dc->color[0] = xcolor.red / 65535.0;
2893 dc->color[1] = xcolor.green / 65535.0;
2894 dc->color[2] = xcolor.blue / 65535.0;
2897 color_name = get_string_resource (mi->dpy, "cwForeground", "Foreground");
2898 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
2899 if (*s2 == ' ' || *s2 == '\t')
2904 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
2906 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
2910 dc->codeword_color[0] = xcolor.red / 65535.0;
2911 dc->codeword_color[1] = xcolor.green / 65535.0;
2912 dc->codeword_color[2] = xcolor.blue / 65535.0;
2913 dc->codeword_color[3] = 1.0;
2915 color_name = get_string_resource (mi->dpy, "cwBackground", "Background");
2916 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
2917 if (*s2 == ' ' || *s2 == '\t')
2922 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
2924 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
2928 dc->codeword_bg[0] = xcolor.red / 65535.0;
2929 dc->codeword_bg[1] = xcolor.green / 65535.0;
2930 dc->codeword_bg[2] = xcolor.blue / 65535.0;
2931 dc->codeword_bg[3] = 1.0;
2934 dc->trackball = gltrackball_init (False);
2936 dc->gasket_spinnerx.probability = 0.1;
2937 dc->gasket_spinnery.probability = 0.1;
2938 dc->gasket_spinnerz.probability = 1.0;
2939 dc->gasket_spinnerx.easement = 0.08;
2940 dc->gasket_spinnery.easement = 0.08;
2941 dc->gasket_spinnerz.easement = 0.08;
2943 dc->helix_spinnerz.probability = 0.6;
2944 dc->helix_spinnerz.easement = 0.2;
2946 dc->pizza_spinnerz.probability = 0.6;
2947 dc->pizza_spinnery.probability = 0.6;
2948 dc->pizza_spinnerz.easement = 0.2;
2949 dc->pizza_spinnery.easement = 0.2;
2951 dc->frame_spinner.probability = 5.0;
2952 dc->frame_spinner.easement = 0.2;
2954 dc->scene_spinnerx.probability = 0.1;
2955 dc->scene_spinnery.probability = 0.0;
2956 dc->scene_spinnerx.easement = 0.1;
2957 dc->scene_spinnery.easement = 0.1;
2959 if (dc->mode == CODEWORD_IN)
2961 double tilt_speed = 0.003;
2962 dc->scene_rot = make_rotator (0, 0, 0, 0, tilt_speed, True);
2965 /* start the frame off-screen */
2966 dc->frame_spinner.spinning_p = True;
2967 dc->frame_spinner.position = 0.3;
2968 dc->frame_spinner.speed = 0.001;
2970 if (dc->speed > 0) /* start off with the gasket in motion */
2972 dc->gasket_spinnerz.spinning_p = True;
2973 dc->gasket_spinnerz.speed = (0.002
2974 * ((random() & 1) ? 1 : -1)
2978 # ifdef DXF_OUTPUT_HACK
2981 dc->frame_depth = dc->gasket_depth;
2986 glRotatef(90, 1, 0, 0);
2987 glRotatef(90, 0, 0, 1);
2988 make_pizza (dc, 0, 0);
2991 glRotatef(helix_rot, 0, 0, 1);
2992 make_ladder (dc, 0, 0);
2993 make_helix (dc, 0, 0);
2994 glRotatef (180, 0, 0, 1);
2995 make_helix (dc, 0, 0);
2999 make_gasket (dc, 0);
3007 glRotatef(90, 1, 0, 0);
3008 glRotatef(90, 0, 0, 1);
3009 dc->anim_state = CODEWORD;
3010 make_codeword_path (mi);
3011 draw_codeword_path (mi);
3019 dc->helix_list = glGenLists (1);
3020 glNewList (dc->helix_list, GL_COMPILE);
3021 glRotatef(helix_rot, 0, 0, 1);
3022 if (do_ladder) dc->polys[0] += make_ladder (dc, 0, 0);
3023 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
3024 glRotatef(180, 0, 0, 1);
3025 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
3030 dc->helix_list_wire = glGenLists (1);
3031 glNewList (dc->helix_list_wire, GL_COMPILE);
3032 /* glRotatef(helix_rot, 0, 0, 1); wtf? */
3033 if (do_ladder) dc->polys[1] += make_ladder (dc, 1, 1);
3034 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
3035 glRotatef(180, 0, 0, 1);
3036 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
3041 dc->helix_list_facetted = glGenLists (1);
3042 glNewList (dc->helix_list_facetted, GL_COMPILE);
3043 glRotatef(helix_rot, 0, 0, 1);
3044 if (do_ladder) dc->polys[2] += make_ladder (dc, 1, 0);
3045 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
3046 glRotatef(180, 0, 0, 1);
3047 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
3051 dc->pizza_list = glGenLists (1);
3052 glNewList (dc->pizza_list, GL_COMPILE);
3053 if (do_frame) dc->polys[5] += make_pizza (dc, 0, 0);
3056 dc->pizza_list_wire = glGenLists (1);
3057 glNewList (dc->pizza_list_wire, GL_COMPILE);
3058 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 1);
3061 dc->pizza_list_facetted = glGenLists (1);
3062 glNewList (dc->pizza_list_facetted, GL_COMPILE);
3063 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 0);
3066 dc->gasket_list = glGenLists (1);
3067 glNewList (dc->gasket_list, GL_COMPILE);
3068 if (do_gasket) dc->polys[3] += make_gasket (dc, 0);
3071 dc->gasket_list_wire = glGenLists (1);
3072 glNewList (dc->gasket_list_wire, GL_COMPILE);
3073 if (do_gasket) dc->polys[4] += make_gasket (dc, 1);
3076 dc->frame_list = glGenLists (1);
3077 glNewList (dc->frame_list, GL_COMPILE);
3078 if (do_frame) dc->polys[5] += make_frame (dc, 0);
3081 dc->frame_list_wire = glGenLists (1);
3082 glNewList (dc->frame_list_wire, GL_COMPILE);
3083 if (do_frame) dc->polys[6] += make_frame (dc, 1);
3086 make_codeword_path (mi);
3089 /* When drawing both solid and wireframe objects,
3090 make sure the wireframe actually shows up! */
3091 glEnable (GL_POLYGON_OFFSET_FILL);
3092 glPolygonOffset (1.0, 1.0);
3097 logo_handle_event (ModeInfo *mi, XEvent *event)
3099 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
3101 if (gltrackball_event_handler (event, dc->trackball,
3102 MI_WIDTH (mi), MI_HEIGHT (mi),
3103 &dc->button_down_p))
3105 else if (event->xany.type == KeyPress)
3109 XLookupString (&event->xkey, &c, 1, &keysym, 0);
3110 if (c == ' ' || c == '\t')
3112 switch (dc->anim_state) {
3114 dc->anim_state = HELIX_OUT;
3115 dc->anim_ratio = 0.0;
3118 dc->anim_state = PIZZA_OUT;
3119 dc->anim_ratio = 0.0;
3122 dc->anim_state = CODEWORD_OUT;
3123 dc->anim_ratio = 0.0;
3136 spinner_ease (GLfloat x)
3138 /* Smooth curve up, ending at slope = 1. */
3139 return cos ((x/2 + 1) * M_PI) + 1;
3144 tick_spinner (ModeInfo *mi, spinner *s)
3146 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
3148 if (dc->speed == 0) return;
3149 if (dc->button_down_p) return;
3153 s->position += s->speed;
3154 if (s->position >= 1.0 || s->position <= 0.0)
3157 s->position_eased = 0;
3158 s->spinning_p = False;
3160 else if (s->easement > 0 && s->position <= s->easement)
3161 s->position_eased = (s->easement *
3162 spinner_ease (s->position / s->easement));
3163 else if (s->easement > 0 && s->position >= 1-s->easement)
3164 s->position_eased = (1 - s->easement *
3165 spinner_ease ((1 - s->position) / s->easement));
3167 s->position_eased = s->position;
3169 else if (s->probability &&
3170 (random() % (int) (PROBABILITY_SCALE / s->probability)) == 0)
3173 s->spinning_p = True;
3176 s->speed = dc->speed * (frand(ss/3) + frand(ss/3) + frand(ss/3));
3177 } while (s->speed <= 0);
3180 s->speed = -s->speed;
3188 link_spinners (ModeInfo *mi, spinner *s0, spinner *s1)
3190 if (s0->spinning_p && !s1->spinning_p)
3192 GLfloat op = s1->probability;
3193 s1->probability = PROBABILITY_SCALE;
3194 tick_spinner (mi, s1);
3195 s1->probability = op;
3201 draw_logo (ModeInfo *mi)
3203 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
3204 Display *dpy = MI_DISPLAY(mi);
3205 Window window = MI_WINDOW(mi);
3206 int wire = MI_IS_WIREFRAME(mi);
3208 GLfloat specular[] = {0.8, 0.8, 0.8, 1.0};
3209 GLfloat shininess = 50.0;
3213 if (!dc->glx_context)
3216 mi->polygon_count = 0;
3217 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(dc->glx_context));
3220 dc->wire_overlay == 0 &&
3221 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
3222 dc->wire_overlay = ((random() % 200) +
3226 tick_spinner (mi, &dc->gasket_spinnerx);
3227 tick_spinner (mi, &dc->gasket_spinnery);
3228 tick_spinner (mi, &dc->gasket_spinnerz);
3229 tick_spinner (mi, &dc->helix_spinnerz);
3230 tick_spinner (mi, &dc->pizza_spinnery);
3231 tick_spinner (mi, &dc->pizza_spinnerz);
3232 tick_spinner (mi, &dc->scene_spinnerx);
3233 tick_spinner (mi, &dc->scene_spinnery);
3234 tick_spinner (mi, &dc->frame_spinner);
3235 link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery);
3237 switch (dc->anim_state)
3240 if (dc->mode == HELIX_AND_PIZZA &&
3241 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
3242 dc->anim_state = HELIX_OUT;
3246 dc->anim_ratio += 0.1 * dc->speed;
3247 if (dc->anim_ratio >= 1.0)
3249 dc->anim_ratio = 0.0;
3250 dc->anim_state = PIZZA_IN;
3255 dc->anim_ratio += 0.1 * dc->speed;
3256 if (dc->anim_ratio >= 1.0)
3258 dc->anim_ratio = 0.0;
3259 dc->anim_state = PIZZA;
3264 if (dc->mode == HELIX_AND_PIZZA &&
3265 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
3266 dc->anim_state = PIZZA_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 = HELIX_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 = HELIX;
3289 dc->scene_spinnerx.probability = 0.2;
3290 dc->scene_spinnery.probability = 0.05;
3291 if (! dc->button_down_p)
3292 dc->anim_ratio += 0.004 * dc->speed;
3293 if (dc->anim_ratio >= 1.0)
3295 dc->anim_state = CODEWORD;
3296 dc->anim_ratio = frand (0.5);
3301 dc->scene_spinnerx.probability = 0.5;
3302 dc->scene_spinnery.probability = 0.2;
3303 if (! dc->button_down_p)
3304 dc->anim_ratio += (0.0005 + frand(0.002)) * dc->speed;
3305 if (dc->anim_ratio >= 1.0)
3307 dc->anim_ratio = 0.0;
3308 dc->anim_state = CODEWORD_OUT;
3313 dc->scene_spinnerx.probability = 0;
3314 dc->scene_spinnery.probability = 0;
3315 if (! dc->button_down_p)
3316 dc->anim_ratio += 0.02 * dc->speed;
3317 if (dc->anim_ratio >= 1.0)
3319 dc->anim_ratio = 0.0;
3320 dc->anim_state = CODEWORD_BLANK;
3324 case CODEWORD_BLANK:
3325 dc->scene_spinnerx.probability = 0;
3326 dc->scene_spinnery.probability = 0;
3327 if (! dc->button_down_p)
3328 dc->anim_ratio += 0.01 * dc->speed;
3329 if (dc->anim_ratio >= 1.0)
3331 dc->anim_ratio = 0.0;
3332 dc->anim_state = CODEWORD_IN;
3341 pizza_p = (dc->anim_state == PIZZA ||
3342 dc->anim_state == PIZZA_IN ||
3343 dc->anim_state == PIZZA_OUT);
3345 codeword_p = (dc->anim_state == CODEWORD ||
3346 dc->anim_state == CODEWORD_IN ||
3347 dc->anim_state == CODEWORD_OUT ||
3348 dc->anim_state == CODEWORD_BLANK);
3350 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3353 glRotatef(current_device_rotation(), 0, 0, 1);
3355 GLfloat scale = 1.8;
3356 glScalef(scale, scale, scale);
3358 glColor3f(dc->color[0], dc->color[1], dc->color[2]);
3361 /* Draw frame before trackball rotation */
3364 GLfloat p = (dc->frame_spinner.position_eased >= 0
3365 ? dc->frame_spinner.position_eased
3366 : -dc->frame_spinner.position_eased);
3367 GLfloat size = (p > 0.5 ? 1-p : p);
3368 scale = 1 + (size * 10);
3370 /* gltrackball_rotate (dc->trackball); */
3371 glRotatef(90, 1, 0, 0);
3372 glRotatef(90, 0, 0, 1);
3374 glScalef (1, scale, scale);
3377 glDisable (GL_LIGHTING);
3378 glCallList (dc->frame_list_wire);
3379 mi->polygon_count += dc->polys[6];
3381 else if (dc->wire_overlay != 0)
3383 glCallList (dc->frame_list);
3384 glDisable (GL_LIGHTING);
3385 glColor3fv (dc->color);
3386 glCallList (dc->frame_list_wire);
3387 mi->polygon_count += dc->polys[6];
3388 if (!wire) glEnable (GL_LIGHTING);
3392 glCallList (dc->frame_list);
3393 mi->polygon_count += dc->polys[5];
3398 gltrackball_rotate (dc->trackball);
3400 glRotatef(90, 1, 0, 0);
3401 glRotatef(90, 0, 0, 1);
3405 glRotatef (360 * dc->scene_spinnerx.position_eased, 0, 1, 0);
3406 glRotatef (360 * dc->scene_spinnery.position_eased, 0, 0, 1);
3410 glRotatef (360 * dc->gasket_spinnerx.position_eased, 0, 1, 0);
3411 glRotatef (360 * dc->gasket_spinnery.position_eased, 0, 0, 1);
3412 glRotatef (360 * dc->gasket_spinnerz.position_eased, 1, 0, 0);
3414 memcpy (gcolor, dc->color, sizeof (dc->color));
3415 if (dc->wire_overlay != 0)
3417 gcolor[0] = gcolor[1] = gcolor[2] = 0;
3418 specular[0] = specular[1] = specular[2] = 0;
3421 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
3422 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
3423 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shininess);
3427 glDisable (GL_LIGHTING);
3428 glCallList (dc->gasket_list_wire);
3429 mi->polygon_count += dc->polys[4];
3431 else if (dc->wire_overlay != 0)
3433 glCallList (dc->gasket_list);
3434 glDisable (GL_LIGHTING);
3435 glColor3fv (dc->color);
3436 glCallList (dc->gasket_list_wire);
3437 mi->polygon_count += dc->polys[4];
3438 if (!wire) glEnable (GL_LIGHTING);
3439 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
3443 glCallList (dc->gasket_list);
3444 mi->polygon_count += dc->polys[3];
3450 glRotatef (360 * dc->pizza_spinnery.position_eased, 1, 0, 0);
3451 glRotatef (360 * dc->pizza_spinnerz.position_eased, 0, 0, 1);
3455 glRotatef (360 * dc->helix_spinnerz.position_eased, 0, 0, 1);
3458 scale = ((dc->anim_state == PIZZA_IN || dc->anim_state == HELIX_IN)
3460 : ((dc->anim_state == PIZZA_OUT || dc->anim_state == HELIX_OUT)
3461 ? 1.0 - dc->anim_ratio
3463 if (scale <= 0) scale = 0.001;
3464 glScalef (scale, scale, scale);
3468 glDisable (GL_LIGHTING);
3470 glCallList (dc->pizza_list_wire);
3472 glCallList (dc->helix_list_wire);
3473 mi->polygon_count += dc->polys[1];
3475 else if (dc->wire_overlay != 0)
3478 glCallList (dc->pizza_list_facetted);
3480 glCallList (dc->helix_list_facetted);
3482 glDisable (GL_LIGHTING);
3483 glColor3fv (dc->color);
3486 glCallList (dc->pizza_list_wire);
3488 glCallList (dc->helix_list_wire);
3490 mi->polygon_count += dc->polys[2];
3491 if (!wire) glEnable (GL_LIGHTING);
3496 glCallList (dc->pizza_list);
3498 glCallList (dc->helix_list);
3499 mi->polygon_count += dc->polys[0];
3502 else /* codeword_p */
3505 double max = 70; /* face front */
3507 get_position (dc->scene_rot, &x, &y, &z, !dc->button_down_p);
3508 glRotatef (max/2 - x*max, 0, 0, 1);
3509 glRotatef (max/2 - y*max, 0, 1, 0);
3510 /* glRotatef (max/2 - z*max, 1, 0, 0); */
3512 glRotatef (360 * dc->scene_spinnerx.position_eased, 0, 1, 0);
3513 glRotatef (360 * dc->scene_spinnery.position_eased, 0, 0, 1);
3516 glClearColor (dc->codeword_bg[0],
3519 dc->codeword_bg[3]);
3520 mi->polygon_count += draw_codeword_path (mi);
3525 if (dc->wire_overlay > 0)
3528 if (mi->fps_p) do_fps (mi);
3531 glXSwapBuffers(dpy, window);
3534 XSCREENSAVER_MODULE_2 ("DNALogo", dnalogo, logo)