1 /* DNA Logo, Copyright (c) 2001-2018 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.3 \n" \
36 "*barSpacing: 0.268 \n" \
37 "*wallHeight: 0.42 \n" \
38 "*wallThickness: 0.12 \n" \
39 "*barThickness: 0.058 \n" \
40 "*wallTaper: 0.95 \n" \
41 "*gasketSize: 2.0 \n" \
42 "*gasketDepth: 0.15 \n" \
43 "*gasketThickness: 0.4 \n" \
44 "*frameSize: 1.28 \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;
171 GLfloat persp_off, pos_off;
172 texture_font_data *label_font;
177 glyph_mode anim_state;
180 spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz;
181 spinner scene_spinnerx, scene_spinnery; /* for DNA */
183 rotator *scene_rot; /* for Codeword */
185 spinner helix_spinnerz;
186 spinner pizza_spinnery, pizza_spinnerz;
187 spinner frame_spinner;
189 trackball_state *trackball;
192 int wire_overlay; /* frame countdown */
194 } logo_configuration;
196 static logo_configuration *dcs = NULL;
198 static XrmOptionDescRec opts[] = {
199 { "-speed", ".speed", XrmoptionSepArg, 0 },
200 { "-mode", ".mode", XrmoptionSepArg, 0 },
201 { "-pizza", ".mode", XrmoptionNoArg, "pizza" },
202 { "-helix", ".mode", XrmoptionNoArg, "helix" },
203 { "-both", ".mode", XrmoptionNoArg, "both" },
205 { "-codeword", ".mode", XrmoptionNoArg, "codeword" },
206 { "-cw", ".mode", XrmoptionNoArg, "codeword" },
207 { "-text", ".text", XrmoptionSepArg, 0 },
211 ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
213 #define PROBABILITY_SCALE 600
216 #ifdef DXF_OUTPUT_HACK
218 # define glBegin dxf_glBegin
219 # define glVertex3f dxf_glVertex3f
220 # define glVertex3dv dxf_glVertex3dv
221 # define glEnd dxf_glEnd
222 # define glVertexPointer dxf_glVertexPointer
223 # define glDrawArrays dxf_glDrawArrays
225 static int dxf_type, dxf_point, dxf_point_total, dxf_layer, dxf_color;
226 static GLfloat dxf_quads[4*4];
229 dxf_glBegin (int type)
237 dxf_glVertex3f (GLfloat ox, GLfloat oy, GLfloat oz)
243 /* Transform the point into modelview space. */
244 glGetFloatv (GL_MODELVIEW_MATRIX, m);
245 x = ox * m[0] + oy * m[4] + oz * m[8] + m[12];
246 y = ox * m[1] + oy * m[5] + oz * m[9] + m[13];
247 z = ox * m[2] + oy * m[6] + oz * m[10] + m[14];
249 dxf_quads[dxf_point*3+0] = x;
250 dxf_quads[dxf_point*3+1] = y;
251 dxf_quads[dxf_point*3+2] = z;
257 if (dxf_point < 4) return;
259 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
260 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
261 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
262 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
264 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
265 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
266 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
268 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
269 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
270 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
272 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]);
273 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
274 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
279 if (dxf_point < 4) return;
281 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
282 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
283 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
284 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
286 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
287 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
288 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
290 fprintf (stdout, "12\n%.6f\n", dxf_quads[i+3]); /* funky quad strip */
291 fprintf (stdout, "22\n%.6f\n", dxf_quads[i+4]); /* vert order: 1243. */
292 fprintf (stdout, "32\n%.6f\n", dxf_quads[i+5]);
294 fprintf (stdout, "13\n%.6f\n", dxf_quads[i]);
295 fprintf (stdout, "23\n%.6f\n", dxf_quads[i+1]);
296 fprintf (stdout, "33\n%.6f\n", dxf_quads[i+2]);
299 dxf_quads[0] = dxf_quads[6]; /* copy point 3 to pos 1 */
300 dxf_quads[1] = dxf_quads[7];
301 dxf_quads[2] = dxf_quads[8];
302 dxf_quads[3] = dxf_quads[9]; /* copy point 4 to pos 2 */
303 dxf_quads[4] = dxf_quads[10];
304 dxf_quads[5] = dxf_quads[11];
305 dxf_point = 2; /* leave those two points in queue */
309 case GL_TRIANGLE_FAN:
310 if (dxf_point < 3) return;
312 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
313 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
314 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
315 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
317 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
318 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
319 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
321 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
322 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
323 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
326 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
327 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
328 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
331 if (dxf_type == GL_TRIANGLE_FAN)
333 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to point 2 */
334 dxf_quads[4] = dxf_quads[7];
335 dxf_quads[5] = dxf_quads[8];
336 dxf_point = 2; /* leave two points in queue */
340 case GL_TRIANGLE_STRIP:
341 if (dxf_point < 3) return;
343 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
345 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
346 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
347 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
349 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
350 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
351 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
353 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
354 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
355 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
358 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
359 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
360 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
362 dxf_quads[0] = dxf_quads[3]; /* copy point 2 to pos 1 */
363 dxf_quads[1] = dxf_quads[4];
364 dxf_quads[2] = dxf_quads[5];
365 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to pos 2 */
366 dxf_quads[4] = dxf_quads[7];
367 dxf_quads[5] = dxf_quads[8];
368 dxf_point = 2; /* leave those two points in queue */
375 if (dxf_point_total == 1)
382 if (dxf_point < 2) return;
384 fprintf (stdout, "0\nLINE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
386 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
387 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
388 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
390 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
391 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
392 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
395 if (dxf_type != GL_LINES)
397 dxf_quads[0] = dxf_quads[3];
398 dxf_quads[1] = dxf_quads[4];
399 dxf_quads[2] = dxf_quads[5];
412 dxf_glVertex3dv (const GLdouble *v)
414 glVertex3f (v[0], v[1], v[2]);
421 if (dxf_type == GL_LINE_LOOP) /* close loop */
422 glVertex3f (dxf_quads[6], dxf_quads[7], dxf_quads[8]);
432 fprintf (stdout, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n");
433 fprintf (stdout, "0\nSECTION\n2\nENTITIES\n");
439 fprintf (stdout, "0\nENDSEC\n0\nEOF\n");
444 static const GLvoid *dxf_vp;
445 static GLsizei dxf_vp_size;
446 static GLsizei dxf_vp_stride;
449 dxf_glVertexPointer (GLint size, GLenum type, GLsizei stride,
450 const GLvoid *pointer)
452 if (type != GL_FLOAT) abort();
453 if (stride <= 0) abort();
456 dxf_vp_stride = stride;
460 dxf_glDrawArrays (GLenum mode, GLint first, GLsizei count)
463 unsigned char *a = (unsigned char *) dxf_vp;
465 for (i = first; i < first+count; i++)
467 GLfloat *fa = (GLfloat *) a;
468 dxf_glVertex3f (fa[0], fa[1], fa[2]);
475 # define XYZ tube_XYZ /* avoid conflict with normals.h */
476 # include "tube.c" /* Yes, I really am including a C file. */
478 # define XYZ sphere_XYZ
479 # define unit_sphere unit_sphere_dxf
480 # define unit_dome unit_dome_dxf
484 #endif /* DXF_OUTPUT_HACK */
488 /* Calculate the angle (in radians) between two vectors.
491 vector_angle (double ax, double ay, double az,
492 double bx, double by, double bz)
494 double La = sqrt (ax*ax + ay*ay + az*az);
495 double Lb = sqrt (bx*bx + by*by + bz*bz);
498 if (La == 0 || Lb == 0) return 0;
499 if (ax == bx && ay == by && az == bz) return 0;
501 /* dot product of two vectors is defined as:
502 La * Lb * cos(angle between vectors)
503 and is also defined as:
504 ax*bx + ay*by + az*bz
506 La * Lb * cos(angle) = ax*bx + ay*by + az*bz
507 cos(angle) = (ax*bx + ay*by + az*bz) / (La * Lb)
508 angle = acos ((ax*bx + ay*by + az*bz) / (La * Lb));
510 cc = (ax*bx + ay*by + az*bz) / (La * Lb);
511 if (cc > 1) cc = 1; /* avoid fp rounding error (1.000001 => sqrt error) */
523 GLfloat d = sqrt (p->x*p->x + p->y*p->y + p->z*p->z);
532 p->x = p->y = p->z = 0;
538 dot (const XYZ u, const XYZ v)
540 return (u.x * v.x) + (u.y * v.y) + (u.z * v.z);
550 make_helix (logo_configuration *dc, int facetted, int wire)
553 int wall_facets = dc->wall_facets / (facetted ? 10 : 1);
555 GLfloat max_th = M_PI * 2 * dc->turns;
556 GLfloat th_inc = M_PI * 2 / wall_facets;
558 GLfloat x1=0, y1=0, x2=0, y2=0;
559 GLfloat x1b=0, y1b=0, x2b=0, y2b=0;
562 GLfloat h1off=0, h2off=0;
563 GLfloat z_inc = dc->turn_spacing / wall_facets;
571 z1 = -(dc->turn_spacing * dc->turns / 2);
573 h1 = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2);
574 h1off = (dc->wall_taper > 0 ? -dc->wall_height / 2 : 0);
577 z1 = -z1, z_inc = -z_inc, h1off = -h1off;
586 nx = cos (th + M_PI/2);
587 ny = sin (th + M_PI/2);
588 glNormal3f(nx, ny, 0);
589 glVertex3f( x1, y1, z1 - h1 + h1off);
590 glVertex3f( x1, y1, z1 + h1 + h1off);
591 glVertex3f(x1b, y1b, z1 + h1 + h1off);
592 glVertex3f(x1b, y1b, z1 - h1 + h1off);
597 while (th + th_inc <= max_th)
599 GLfloat thick = dc->wall_thickness;
610 if (dc->wall_taper > 0)
613 if (th < dc->wall_taper)
615 h2 = dc->wall_height/2 * cos (M_PI / 2
616 * (1 - (th / dc->wall_taper)));
618 h2off = h2 - dc->wall_height/2;
620 h2off = dc->wall_height/2 - h2;
622 if (th + th_inc <= 0)
625 thick *= cos (M_PI / 2 * (1 - (th / dc->wall_taper)));
627 else if (th >= max_th - dc->wall_taper)
629 if (th + th_inc > max_th) /* edge case: always come to a point */
632 h2 = dc->wall_height/2 * cos (M_PI / 2
633 * (1 - ((max_th - th)
636 h2off = dc->wall_height/2 - h2;
638 h2off = h2 - dc->wall_height/2;
640 if (th + th_inc > max_th)
643 thick *= cos(M_PI / 2 * (1 - ((max_th - th)/dc->wall_taper)));
647 x2b = x2 * (1 - thick);
648 y2b = y2 * (1 - thick);
653 glBegin(wire ? GL_LINES : GL_QUADS);
654 glNormal3f(x1, y1, 0);
655 glVertex3f(x1, y1, z1 - h1 + h1off);
656 glVertex3f(x1, y1, z1 + h1 + h1off);
657 glNormal3f(x2, y2, 0);
658 glVertex3f(x2, y2, z2 + h2 + h2off);
659 glVertex3f(x2, y2, z2 - h2 + h2off);
666 glBegin(wire ? GL_LINES : GL_QUADS);
667 glNormal3f(-x1b, -y1b, 0);
668 glVertex3f( x1b, y1b, z1 - h1 + h1off);
669 glVertex3f( x1b, y1b, z1 + h1 + h1off);
670 glNormal3f(-x2b, -y2b, 0);
671 glVertex3f( x2b, y2b, z2 + h2 + h2off);
672 glVertex3f( x2b, y2b, z2 - h2 + h2off);
679 /* glNormal3f(0, 0, 1);*/
680 do_normal (x2, y2, z2 + h2 + h2off,
681 x2b, y2b, z2 + h2 + h2off,
682 x1b, y1b, z1 + h1 + h1off);
683 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
684 glVertex3f( x2, y2, z2 + h2 + h2off);
685 glVertex3f( x2b, y2b, z2 + h2 + h2off);
686 glVertex3f( x1b, y1b, z1 + h1 + h1off);
687 glVertex3f( x1, y1, z1 + h1 + h1off);
694 do_normal ( x1, y1, z1 - h1 + h1off,
695 x1b, y1b, z1 - h1 + h1off,
696 x2b, y2b, z2 - h2 + h2off);
697 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
698 glNormal3f(0, 0, -1);
699 glVertex3f( x1, y1, z1 - h1 + h1off);
700 glVertex3f( x1b, y1b, z1 - h1 + h1off);
701 glVertex3f( x2b, y2b, z2 - h2 + h2off);
702 glVertex3f( x2, y2, z2 - h2 + h2off);
722 nx = cos (th + M_PI/2);
723 ny = sin (th + M_PI/2);
724 glNormal3f(nx, ny, 0);
725 glVertex3f(x2, y2, z1 - h2 + h2off);
726 glVertex3f(x2, y2, z1 + h2 + h2off);
727 glVertex3f(x2b, y2b, z1 + h2 + h2off);
728 glVertex3f(x2b, y2b, z1 - h2 + h2off);
737 make_ladder (logo_configuration *dc, int facetted, int wire)
741 GLfloat max_th = dc->turns * M_PI * 2;
742 GLfloat max_z = dc->turns * dc->turn_spacing;
743 GLfloat z_inc = dc->bar_spacing;
744 GLfloat th_inc = M_PI * 2 * (dc->bar_spacing / dc->turn_spacing);
747 /* skip forward to center the bars in the helix... */
749 GLfloat usable_th = max_th - dc->wall_taper;
750 GLfloat usable_z = max_z / (max_th / usable_th);
751 int nbars = usable_z / dc->bar_spacing;
752 GLfloat used_z, pad_z, pad_ratio;
754 if (! (nbars & 1)) nbars--; /* always an odd number of bars */
756 used_z = (nbars - 1) * dc->bar_spacing;
757 pad_z = max_z - used_z;
758 pad_ratio = pad_z / max_z;
760 th = (max_th * pad_ratio/2);
761 z = -(max_z / 2) + (max_z * pad_ratio/2);
764 /* The image is not reflected across line y = -x and I don't know why. */
769 z = -z, z_inc = -z_inc;
772 for (i = 0; i < nbars; i++)
774 int facets = dc->bar_facets / (facetted ? 14 : 1);
775 if (facets <= 3) facets = 3;
776 x = cos (th) * (1 - dc->wall_thickness);
777 y = sin (th) * (1 - dc->wall_thickness);
778 polys += tube ( x, y, z,
780 dc->bar_thickness, 0, facets,
795 make_gasket (logo_configuration *dc, int wire)
803 GLfloat d2r = M_PI / 180;
805 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 2;
807 GLfloat *pointsx0, *pointsy0, *pointsx1, *pointsy1, *normals;
809 GLfloat r0 = 0.750; /* 395 */
810 GLfloat r1a = 0.825; /* bottom of wall below upper left hole */
811 GLfloat r1b = 0.867; /* center of upper left hole */
812 GLfloat r1c = 0.909; /* top of wall above hole */
813 GLfloat r1 = 0.916; /* 471 */
814 GLfloat r2 = 0.963; /* 490 */
815 GLfloat r3 = 0.960; /* 499 */
816 GLfloat r4 = 1.000; /* 507 */
817 GLfloat r5 = 1.080; /* 553 */
819 GLfloat ctrl_r[100], ctrl_th[100];
823 # ifdef DXF_OUTPUT_HACK
824 if (! wire) res *= 8;
827 # define POINT(r,th) \
828 ctrl_r [nctrls] = r, \
829 ctrl_th[nctrls] = (th * d2r), \
832 POINT (0.829, 0); /* top indentation, right half */
840 POINT (r4, 4.0); /* moving clockwise... */
861 POINT (r4, 316.8); /* upper left indentation */
862 POINT (0.990, 316.87);
863 POINT (0.880, 317.21);
864 POINT (0.872, 317.45);
865 POINT (0.869, 317.80);
866 POINT (0.867, 318.10);
868 POINT (0.867, 318.85);
869 POINT (0.869, 319.15);
870 POINT (0.872, 319.50);
871 POINT (0.880, 319.74);
872 POINT (0.990, 320.08);
877 POINT (r1a, 338.0); /* cut-out disc */
883 POINT (0.872, 356.05); /* top indentation, left half */
884 POINT (0.862, 356.19);
885 POINT (0.851, 356.70);
886 POINT (0.841, 357.35);
887 POINT (0.835, 358.19);
888 POINT (0.831, 359.15);
892 points_size = res + (nctrls * 2);
893 pointsx0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
894 pointsy0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
895 pointsx1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
896 pointsy1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
897 normals = (GLfloat *) malloc (points_size * sizeof(GLfloat) * 2);
900 for (i = 1; i < nctrls; i++)
902 GLfloat from_r = ctrl_r [i-1];
903 GLfloat from_th = ctrl_th[i-1];
904 GLfloat to_r = ctrl_r [i];
905 GLfloat to_th = ctrl_th[i];
907 GLfloat step = 2*M_PI / res;
908 int nsteps = 1 + ((to_th - from_th) / step);
911 for (j = 0; j < nsteps + (i == nctrls-1); j++)
913 GLfloat r = from_r + (j * (to_r - from_r) / nsteps);
914 GLfloat th = from_th + (j * (to_th - from_th) / nsteps);
916 GLfloat cth = cos(th) * dc->gasket_size;
917 GLfloat sth = sin(th) * dc->gasket_size;
919 pointsx0[npoints] = r0 * cth; /* inner ring */
920 pointsy0[npoints] = r0 * sth;
921 pointsx1[npoints] = r * cth; /* outer ring */
922 pointsy1[npoints] = r * sth;
925 if (npoints >= points_size) abort();
929 /* normals for the outer ring */
930 for (i = 1; i < npoints; i++)
941 n = calc_normal (a, b, c);
942 normals[(i-1)*2 ] = n.x;
943 normals[(i-1)*2+1] = n.y;
946 glRotatef(-90, 0, 1, 0);
947 glRotatef(180, 0, 0, 1);
952 for (z = -thick2; z <= thick2; z += thick2*2)
956 glBegin (GL_LINE_LOOP);
957 for (i = 0; i < npoints; i++)
958 glVertex3f (pointsx0[i], pointsy0[i], z);
963 glBegin (GL_LINE_LOOP);
964 for (i = 0; i < npoints; i++)
965 glVertex3f (pointsx1[i], pointsy1[i], z);
969 for (i = 1; i < npoints; i++)
971 glBegin (GL_LINE_STRIP);
972 glVertex3f (pointsx0[i-1], pointsy0[i-1], z);
973 glVertex3f (pointsx0[i ], pointsy0[i ], z);
974 glVertex3f (pointsx1[i ], pointsy1[i ], z);
975 glVertex3f (pointsx1[i-1], pointsy1[i-1], z);
983 for (i = 0; i < npoints; i++)
986 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
987 glVertex3f (pointsx0[i], pointsy0[i], thick2);
989 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
990 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1000 glNormal3f(0, 0, -1);
1001 glBegin (GL_QUAD_STRIP);
1002 for (i = 0; i < npoints; i++)
1004 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1005 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1011 glFrontFace(GL_CCW);
1012 glNormal3f(0, 0, 1);
1013 glBegin (GL_QUAD_STRIP);
1014 for (i = 0; i < npoints; i++)
1016 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1017 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1024 glBegin (GL_QUAD_STRIP);
1025 for (i = 0; i < npoints; i++)
1027 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
1028 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
1029 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
1035 glFrontFace(GL_CCW);
1038 for (i = 0; i < npoints-1; i++)
1040 int ia = (i == 0 ? npoints-2 : i-1);
1041 int iz = (i == npoints-2 ? 0 : i+1);
1042 GLfloat x = pointsx1[i];
1043 GLfloat y = pointsy1[i];
1044 GLfloat xz = pointsx1[iz];
1045 GLfloat yz = pointsy1[iz];
1047 GLfloat nxa = normals[ia*2]; /* normal of [i-1 - i] face */
1048 GLfloat nya = normals[ia*2+1];
1049 GLfloat nx = normals[i*2]; /* normal of [i - i+1] face */
1050 GLfloat ny = normals[i*2+1];
1051 GLfloat nxz = normals[iz*2]; /* normal of [i+1 - i+2] face */
1052 GLfloat nyz = normals[iz*2+1];
1054 GLfloat anglea = vector_angle (nx, ny, 0, nxa, nya, 0);
1055 GLfloat anglez = vector_angle (nx, ny, 0, nxz, nyz, 0);
1056 GLfloat pointy = 0.6;
1058 if (anglea > pointy)
1060 glNormal3f (nx, ny, 0);
1061 glVertex3f (x, y, thick2);
1062 glVertex3f (x, y, -thick2);
1066 glNormal3f ((nxa + nx) / 2, (nya + ny) / 2, 0);
1067 glVertex3f (x, y, thick2);
1068 glVertex3f (x, y, -thick2);
1071 if (anglez > pointy)
1073 glNormal3f (nx, ny, 0);
1074 glVertex3f (xz, yz, -thick2);
1075 glVertex3f (xz, yz, thick2);
1079 glNormal3f ((nx + nxz) / 2, (ny + nyz) / 2, 0);
1080 glVertex3f (xz, yz, -thick2);
1081 glVertex3f (xz, yz, thick2);
1089 /* Fill in the upper left hole...
1096 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
1097 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
1099 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
1100 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
1104 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
1105 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
1107 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
1108 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
1113 glNormal3f (0, 0, -1);
1115 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1116 glVertex3f (pointsx0[0], pointsy0[0], -thick2);
1117 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1118 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1119 glVertex3f (pointsx0[2], pointsy0[2], -thick2);
1124 glNormal3f (0, 0, 1);
1125 glFrontFace(GL_CCW);
1126 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1127 glVertex3f (pointsx0[0], pointsy0[0], thick2);
1128 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1129 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1130 glVertex3f (pointsx0[2], pointsy0[2], thick2);
1137 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1138 glNormal3f (pointsx0[1], pointsy0[1], 0);
1139 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1140 glNormal3f (pointsx0[3], pointsy0[3], 0);
1141 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1142 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1143 glNormal3f (pointsx0[1], pointsy0[1], 0);
1144 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1149 /* Now make a donut.
1152 int nsteps = (wire ? 12 : 64);
1155 GLfloat th, cth, sth;
1159 th = ((339.0 + 343.0) / 2) * d2r;
1161 glTranslatef (r1b * cos(th) * dc->gasket_size,
1162 r1b * sin(th) * dc->gasket_size,
1166 for (i = 0; i < nsteps; i++)
1168 th = 2 * M_PI * i / nsteps;
1169 cth = cos (th) * dc->gasket_size;
1170 sth = sin (th) * dc->gasket_size;
1171 pointsx0[npoints] = r0 * cth;
1172 pointsy0[npoints] = r0 * sth;
1173 pointsx1[npoints] = r1 * cth;
1174 pointsy1[npoints] = r1 * sth;
1179 pointsx0[npoints] = pointsx0[0];
1180 pointsy0[npoints] = pointsy0[0];
1181 pointsx1[npoints] = pointsx1[0];
1182 pointsy1[npoints] = pointsy1[0];
1187 glBegin (GL_LINE_LOOP);
1188 for (i = 0; i < npoints; i++)
1189 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1192 glBegin (GL_LINE_LOOP);
1193 for (i = 0; i < npoints; i++)
1194 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1198 glBegin (GL_LINE_LOOP);
1199 for (i = 0; i < npoints; i++)
1200 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1203 glBegin (GL_LINE_LOOP);
1204 for (i = 0; i < npoints; i++)
1205 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1214 glNormal3f(0, 0, -1);
1215 glBegin (GL_QUAD_STRIP);
1216 for (i = 0; i < npoints; i++)
1218 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1219 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1225 glFrontFace(GL_CCW);
1226 glNormal3f(0, 0, 1);
1227 glBegin (GL_QUAD_STRIP);
1228 for (i = 0; i < npoints; i++)
1230 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1231 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1239 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1240 for (i = 0; i < npoints; i++)
1242 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
1243 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
1244 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
1254 /* Attach the bottom-right dingus...
1261 glRotatef (49.5, 0, 0, 1);
1262 glScalef (dc->gasket_size, dc->gasket_size, 1);
1263 glTranslatef (0, (r0+r1)/2, 0);
1268 glFrontFace(GL_CCW);
1269 glBegin (wire ? GL_LINE_STRIP : GL_QUADS);
1270 glNormal3f (0, 0, -1);
1271 glVertex3f (-w/2, -h/2, -thick2); glVertex3f (-w/2, h/2, -thick2);
1272 glVertex3f ( w/2, h/2, -thick2); glVertex3f ( w/2, -h/2, -thick2);
1273 glNormal3f (1, 0, 0);
1274 glVertex3f ( w/2, -h/2, -thick2); glVertex3f ( w/2, h/2, -thick2);
1275 glVertex3f ( w/2, h/2, thick2); glVertex3f ( w/2, -h/2, thick2);
1276 glNormal3f (0, 0, 1);
1277 glVertex3f ( w/2, -h/2, thick2); glVertex3f ( w/2, h/2, thick2);
1278 glVertex3f (-w/2, h/2, thick2); glVertex3f (-w/2, -h/2, thick2);
1279 glNormal3f (-1, 0, 0);
1280 glVertex3f (-w/2, -h/2, thick2); glVertex3f (-w/2, h/2, thick2);
1281 glVertex3f (-w/2, h/2, -thick2); glVertex3f (-w/2, -h/2, -thick2);
1287 for (th = (wire ? 0 : -0.1);
1289 th += (M_PI / (wire ? 5 : 32)))
1291 pointsx0[npoints] = w/2 * cos(th);
1292 pointsy0[npoints] = w/2 * sin(th);
1297 /* front inside curve */
1298 glNormal3f (0, 0, -1);
1300 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1301 if (! wire) glVertex3f (0, h/2, -thick2);
1302 for (i = 0; i < npoints; i++)
1303 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1307 /* front outside curve */
1308 glFrontFace(GL_CCW);
1309 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1310 if (! wire) glVertex3f (0, -h/2, -thick2);
1311 for (i = 0; i < npoints; i++)
1312 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1316 /* back inside curve */
1317 glNormal3f (0, 0, 1);
1318 glFrontFace(GL_CCW);
1319 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1320 if (! wire) glVertex3f (0, h/2, thick2);
1321 for (i = 0; i < npoints; i++)
1322 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1326 /* back outside curve */
1328 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1329 if (! wire) glVertex3f (0, -h/2, thick2);
1330 for (i = 0; i < npoints; i++)
1331 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1336 glFrontFace(GL_CCW);
1337 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1338 for (i = 0; i < npoints; i++)
1340 glNormal3f (pointsx0[i], pointsy0[i], 0);
1341 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1342 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1349 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1350 for (i = 0; i < npoints; i++)
1352 glNormal3f (pointsx0[i], -pointsy0[i], 0);
1353 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1354 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1371 make_frame (logo_configuration *dc, int wire)
1375 GLfloat x[20], y[20];
1376 GLfloat corner_cut = 0.5;
1379 glRotatef (90, 0, 1, 0);
1380 glScalef (4 * dc->frame_size,
1382 4 * dc->frame_size);
1384 x[0] = -dc->frame_thickness;
1385 x[1] = -dc->frame_thickness * corner_cut;
1387 x[3] = 0.5 - dc->triangle_size;
1389 x[5] = 0.5 + dc->triangle_size;
1391 x[7] = 1 + dc->frame_thickness * corner_cut;
1392 x[8] = 1 + dc->frame_thickness;
1394 y[0] = -dc->frame_thickness;
1395 y[1] = -dc->frame_thickness * corner_cut;
1397 y[3] = dc->triangle_size;
1401 glTranslatef (-0.5, -0.5, dc->frame_depth / 4);
1403 for (j = 0; j <= 1; j++)
1405 if (j) glTranslatef (0, 0, -dc->frame_depth / 2);
1406 glFrontFace (j ? GL_CCW : GL_CW);
1407 for (i = 0; i < 4; i++)
1409 glNormal3f (0, 0, (j ? -1 : 1));
1410 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1411 glVertex3f (x[0], y[1], 0); glVertex3f (x[0], y[2], 0);
1412 glVertex3f (x[1], y[0], 0); glVertex3f (x[1], y[2], 0);
1413 glVertex3f (x[3], y[0], 0); glVertex3f (x[3], y[2], 0);
1414 glVertex3f (x[4], y[0], 0); glVertex3f (x[4], y[3], 0);
1415 glVertex3f (x[5], y[0], 0); glVertex3f (x[5], y[2], 0);
1416 glVertex3f (x[7], y[0], 0); glVertex3f (x[7], y[2], 0);
1417 glVertex3f (x[8], y[1], 0); glVertex3f (x[8], y[2], 0);
1420 glTranslatef (0.5, 0.5, 0);
1421 glRotatef (90, 0, 0, 1);
1422 glTranslatef (-0.5, -0.5, 0);
1428 glFrontFace (GL_CCW);
1429 for (i = 0; i < 4; i++)
1431 glNormal3f (0, 1, 0);
1432 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1433 glVertex3f (x[2], y[2], 0); glVertex3f (x[2], y[2], dc->frame_depth/2);
1434 glVertex3f (x[3], y[2], 0); glVertex3f (x[3], y[2], dc->frame_depth/2);
1435 glVertex3f (x[4], y[3], 0); glVertex3f (x[4], y[3], dc->frame_depth/2);
1436 glVertex3f (x[5], y[2], 0); glVertex3f (x[5], y[2], dc->frame_depth/2);
1437 glVertex3f (x[6], y[2], 0); glVertex3f (x[6], y[2], dc->frame_depth/2);
1441 glNormal3f (0, -1, 0);
1442 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1443 glVertex3f (x[7], y[0], 0);
1444 glVertex3f (x[7], y[0], dc->frame_depth/2);
1445 glVertex3f (x[1], y[0], dc->frame_depth/2);
1446 glVertex3f (x[1], y[0], 0);
1450 glNormal3f (1, -1, 0);
1451 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1452 glVertex3f (x[8], y[1], 0);
1453 glVertex3f (x[8], y[1], dc->frame_depth/2);
1454 glVertex3f (x[7], y[0], dc->frame_depth/2);
1455 glVertex3f (x[7], y[0], 0);
1461 glNormal3f (0, 1, 0);
1462 for (j = 0; j <= 1; j++)
1464 glBegin (GL_LINE_STRIP);
1465 glVertex3f (x[2], y[2], j*dc->frame_depth/2);
1466 glVertex3f (x[3], y[2], j*dc->frame_depth/2);
1467 glVertex3f (x[4], y[3], j*dc->frame_depth/2);
1468 glVertex3f (x[5], y[2], j*dc->frame_depth/2);
1469 glVertex3f (x[6], y[2], j*dc->frame_depth/2);
1475 glTranslatef (0.5, 0.5, 0);
1476 glRotatef (90, 0, 0, 1);
1477 glTranslatef (-0.5, -0.5, 0);
1497 tess_error_cb (GLenum errorCode)
1499 fprintf (stderr, "%s: tesselation error: %s\n",
1500 progname, gluErrorString(errorCode));
1505 tess_combine_cb (GLdouble coords[3], GLdouble *d[4], GLfloat w[4],
1506 GLdouble **data_out)
1508 GLdouble *new = (GLdouble *) malloc (3 * sizeof(*new));
1518 tess_vertex_cb (void *vertex_data, void *closure)
1520 tess_out *to = (tess_out *) closure;
1521 GLdouble *v = (GLdouble *) vertex_data;
1522 to->points[to->i++] = v[0];
1523 to->points[to->i++] = v[1];
1524 to->points[to->i++] = v[2];
1529 tess_begin_cb (GLenum which)
1540 #endif /* HAVE_TESS */
1544 make_pizza (logo_configuration *dc, int facetted, int wire)
1547 int topfaces = (facetted ? 48 : 120);
1548 int discfaces = (facetted ? 12 : 120);
1549 int npoints = topfaces * 2 + 100;
1550 GLdouble *points = (GLdouble *) calloc (npoints * 3, sizeof(GLdouble));
1552 GLdouble *holes = (GLdouble *) calloc (topfaces*nholes*3, sizeof(GLdouble));
1554 GLfloat step = M_PI * 2 / 6 / topfaces;
1555 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 4;
1556 GLfloat th, x, y, s;
1561 tess_out TO, *to = &TO;
1562 GLUtesselator *tess = gluNewTess();
1564 to->points = (GLdouble *) calloc (topfaces * 20, sizeof(GLdouble));
1567 # ifndef _GLUfuncptr
1568 # define _GLUfuncptr void(*)(void)
1571 gluTessCallback(tess,GLU_TESS_BEGIN, (_GLUfuncptr)tess_begin_cb);
1572 gluTessCallback(tess,GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv);
1573 gluTessCallback(tess,GLU_TESS_END, (_GLUfuncptr)tess_end_cb);
1574 gluTessCallback(tess,GLU_TESS_COMBINE, (_GLUfuncptr)tess_combine_cb);
1575 gluTessCallback(tess,GLU_TESS_ERROR, (_GLUfuncptr)tess_error_cb);
1577 gluTessProperty (tess, GLU_TESS_BOUNDARY_ONLY, wire);
1578 gluTessProperty (tess,GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
1580 # endif /* HAVE_TESS */
1585 glRotatef (180, 0, 0, 1);
1587 glRotatef (90, 0, 1, 0);
1588 glTranslatef (-0.53, 0, 0);
1589 glRotatef (-30, 0, 0, 1);
1591 /* Compute the wedge */
1604 for (i = 0; i < countof(edge)/2; i++)
1606 points[j++] = edge[i*2+1];
1607 points[j++] = edge[i*2];
1612 s = 0.798; /* radius of end of slice, before crust gap */
1613 for (i = 0; i < topfaces; i++)
1615 points[j++] = cos(th) * s;
1616 points[j++] = sin(th) * s;
1633 for (i = 0; i < countof(edge)/2; i++)
1635 points[j++] = edge[i*2+1];
1636 points[j++] = edge[i*2];
1643 /* Draw the rim of the slice */
1644 glBegin (wire ? GL_LINES : GL_QUADS);
1647 for (i = (wire ? 0 : 1); i < endpoints; i++)
1649 GLdouble *p = points + (i*3);
1651 do_normal (p[0], p[1], -thick2,
1656 glVertex3f (x, y, -thick2);
1657 glVertex3f (x, y, thick2);
1659 glVertex3f (p[0], p[1], thick2);
1660 glVertex3f (p[0], p[1], -thick2);
1666 do_normal (points[0], points[1], -thick2,
1667 points[0], points[1], thick2,
1669 glVertex3f (x, y, -thick2);
1670 glVertex3f (x, y, thick2);
1671 glVertex3f (points[0], points[1], thick2);
1672 glVertex3f (points[0], points[1], -thick2);
1679 /* Outline of slice */
1680 glBegin (GL_LINE_LOOP);
1681 for (i = 0; i < endpoints; i++)
1682 glVertex3f (points[i*3], points[i*3+1], -thick2);
1684 glBegin (GL_LINE_LOOP);
1685 for (i = 0; i < endpoints; i++)
1686 glVertex3f (points[i*3], points[i*3+1], thick2);
1689 # endif /* HAVE_TESS */
1691 /* Compute the holes */
1692 step = M_PI * 2 / discfaces;
1693 for (k = 0; k < nholes; k++)
1695 GLdouble *p = holes + (discfaces * 3 * k);
1699 case 0: x = 0.34; y = 0.17; s = 0.05; break;
1700 case 1: x = 0.54; y = 0.17; s = 0.06; break;
1701 case 2: x = 0.55; y = 0.36; s = 0.06; break;
1702 default: abort(); break;
1704 for (i = 0; i < discfaces; i++)
1706 p[j++] = x + cos(M_PI*2 - th) * s;
1707 p[j++] = y + sin(M_PI*2 - th) * s;
1714 /* Draw the inside rim of the holes */
1715 for (k = 0; k < nholes; k++)
1717 GLdouble *p = holes + (discfaces * 3 * k);
1719 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1720 for (i = 0; i < discfaces; i++)
1722 GLdouble *p2 = p + (i*3);
1724 do_normal (p2[0], p2[1], -thick2,
1725 p2[0], p2[1], thick2,
1726 p2[-3], p2[-2], thick2);
1727 glVertex3f (p2[0], p2[1], -thick2);
1728 glVertex3f (p2[0], p2[1], thick2);
1731 glVertex3f (p[0], p[1], -thick2);
1732 glVertex3f (p[0], p[1], thick2);
1738 /* Outline of holes */
1739 glBegin (GL_LINE_LOOP);
1740 for (i = 0; i < discfaces; i++)
1741 glVertex3f (p[i*3], p[i*3+1], -thick2);
1743 glBegin (GL_LINE_LOOP);
1744 for (i = 0; i < discfaces; i++)
1745 glVertex3f (p[i*3], p[i*3+1], thick2);
1748 # endif /* !HAVE_TESS */
1752 glTranslatef (0, 0, -thick2);
1753 for (y = 0; y <= 1; y++)
1755 if (y) glTranslatef (0, 0, thick2*2);
1757 /* A non-convex polygon */
1758 gluTessBeginPolygon (tess, to);
1760 glNormal3f (0, 0, (y > 0 ? 1 : -1));
1761 gluTessNormal (tess, 0, 0, (y > 0 ? 1 : -1));
1762 glFrontFace (GL_CCW);
1764 /* Tess the wedge */
1765 gluTessBeginContour (tess);
1766 for (i = 0; i < endpoints; i++)
1768 GLdouble *p = points + (i*3);
1769 gluTessVertex (tess, p, p);
1772 gluTessVertex (tess, points, points);
1773 gluTessEndContour (tess);
1775 /* Tess the holes */
1776 for (k = 0; k < nholes; k++)
1778 GLdouble *p = holes + (discfaces * 3 * k);
1779 gluTessBeginContour (tess);
1780 for (i = 0; i < discfaces; i++)
1782 GLdouble *p2 = p + (i*3);
1783 gluTessVertex (tess, p2, p2);
1786 gluTessEndContour (tess);
1789 gluTessEndPolygon (tess);
1792 glTranslatef (0, 0, -thick2);
1794 # else /* !HAVE_TESS */
1797 glTranslatef(0, 0, thick2);
1798 glNormal3f (0, 0, 1);
1799 glFrontFace (GL_CW);
1801 /* Sadly, jwzgl's glVertexPointer seems not to be recordable inside
1804 glDisableClientState (GL_COLOR_ARRAY);
1805 glDisableClientState (GL_NORMAL_ARRAY);
1806 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1807 glEnableClientState (GL_VERTEX_ARRAY);
1808 glVertexPointer (3, GL_FLOAT, 0, dnapizza_triangles);
1809 glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
1811 glBegin (GL_TRIANGLES);
1812 for (i = 0; i < countof (dnapizza_triangles); i += 3)
1813 glVertex3fv (dnapizza_triangles + i);
1817 glTranslatef(0, 0, -thick2*2);
1818 glNormal3f (0, 0, -1);
1819 glFrontFace (GL_CCW);
1822 glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
1825 glBegin (GL_TRIANGLES);
1826 for (i = 0; i < countof (dnapizza_triangles); i += 3)
1827 glVertex3fv (dnapizza_triangles + i);
1831 glTranslatef(0, 0, thick2);
1833 # endif /* !HAVE_TESS */
1836 /* Compute the crust */
1838 s = 0.861; /* radius of inside of crust */
1839 step = M_PI * 2 / 6 / topfaces;
1842 for (i = 0; i < topfaces; i++)
1844 points[j++] = cos(th) * s;
1845 points[j++] = sin(th) * s;
1851 for (i = 0; i < topfaces; i++)
1853 points[j++] = cos(th) * s;
1854 points[j++] = sin(th) * s;
1859 /* Draw the rim of the crust */
1860 glFrontFace (GL_CCW);
1861 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1862 for (i = 0; i < topfaces * 2; i++)
1864 GLdouble *p = points + (i*3);
1865 if (i == 0 || i == (topfaces*2)-1)
1866 glNormal3f (0, -1, 0);
1867 else if (i == topfaces-1 || i == topfaces)
1868 glNormal3f (0, 1, 0);
1870 do_normal (p[-3], p[-2], thick2,
1872 p[0], p[1], -thick2);
1873 glVertex3f (p[0], p[1], -thick2);
1874 glVertex3f (p[0], p[1], thick2);
1877 glVertex3f (points[0], points[1], -thick2);
1878 glVertex3f (points[0], points[1], thick2);
1884 glBegin (GL_LINE_STRIP);
1885 for (i = 0; i < topfaces * 2; i++)
1887 GLdouble *p = points + (i*3);
1888 glVertex3f (p[0], p[1], -thick2);
1891 glVertex3f (points[0], points[1], -thick2);
1894 glBegin (GL_LINE_STRIP);
1895 for (i = 0; i < topfaces * 2; i++)
1897 GLdouble *p = points + (i*3);
1898 glVertex3f (p[0], p[1], thick2);
1901 glVertex3f (points[0], points[1], thick2);
1905 /* Draw the top of the crust */
1908 glFrontFace (GL_CW);
1909 glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP);
1910 glNormal3f (0, 0, -1);
1912 for (i = 0; i < topfaces; i++)
1914 int ii = topfaces + (topfaces - i - 1);
1915 GLdouble *p1 = points + (i*3);
1916 GLdouble *p2 = points + (ii*3);
1917 glVertex3f (p1[0], p1[1], -thick2);
1918 glVertex3f (p2[0], p2[1], -thick2);
1924 /* Draw the bottom of the crust */
1925 glFrontFace (GL_CCW);
1926 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1927 glNormal3f (0, 0, 1);
1928 for (i = 0; i < topfaces; i++)
1930 int ii = topfaces + (topfaces - i - 1);
1931 GLdouble *p1 = points + (i*3);
1932 GLdouble *p2 = points + (ii*3);
1933 glVertex3f (p1[0], p1[1], thick2);
1934 glVertex3f (p2[0], p2[1], thick2);
1942 gluDeleteTess (tess);
1944 # endif /* HAVE_TESS */
1957 /* Upcase string, convert Unicrud to ASCII, remove any non-letters.
1960 codeword_simplify_text (const char *s0)
1962 char *s1 = utf8_to_latin1 ((s0 ? s0 : ""), True);
1964 char *s2 = (char *) malloc (L + 10);
1967 for (i = 0; i < L; i++)
1970 if (c >= 'a' && c <= 'z')
1972 if (c >= 'A' && c <= 'Z')
1977 strcpy (s2, "CODEWORD");
1983 make_codeword_path (ModeInfo *mi)
1985 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
1986 int letters = strlen (dc->codeword_text);
1988 GLfloat rtick = dc->codeword_spread;
1989 GLfloat iradius = rtick * dc->codeword_cap_size;
1995 GLfloat inner_circum = M_PI * 2 * (iradius + rtick * 2);
1996 GLfloat outer_circum = M_PI * 2 * (iradius + rtick * (letters + 1));
1997 GLfloat facet_length = inner_circum / (26 * dc->codeword_facets);
1998 int outer_facets = ceil (outer_circum / facet_length);
2000 int *histo = (int *) calloc (letters * 26, sizeof(*histo));
2001 XYZ *points = (XYZ *) calloc (letters * outer_facets, sizeof (*points));
2004 for (letter = -1; letter < letters; letter++)
2006 if (letter == -1) /* Inner starting point */
2008 points[npoints].x = iradius;
2009 points[npoints].y = 0;
2013 else /* Add arc for this letter */
2015 int direction = (letter & 1 ? -1 : 1);
2016 int v = (dc->codeword_text[letter] - 'A' + 1);
2017 int dial1 = dial + v * direction;
2020 GLfloat th0 = M_PI * 2 / 26 * dial;
2021 GLfloat th1 = M_PI * 2 / 26 * dial1;
2022 GLfloat r = iradius + rtick * (letter + 2);
2023 GLfloat circum = M_PI * 2 * r;
2024 GLfloat arc_length = circum * v / 26;
2025 int arc_facets = ceil (fabs (arc_length / facet_length));
2026 GLfloat facet_th = (th1 - th0) / arc_facets;
2028 if (arc_facets > outer_facets) abort();
2030 /* Let's put some intermediate facets on the crossbars too,
2031 so that the animation doesn't speed up on those. */
2034 for (rr = last_r + facet_length;
2035 rr <= r - facet_length;
2038 points[npoints].x = rr * cos (th0);
2039 points[npoints].y = rr * sin (th0);
2048 ? th <= th1 + facet_th
2049 : th >= th1 + facet_th);
2053 if (th0 < th1 && th > th1)
2055 if (th0 > th1 && th < th1)
2057 points[npoints].x = r * cos (th2);
2058 points[npoints].y = r * sin (th2);
2060 /* Ugh, add point only if it differs from prev.
2061 Not sure how this happens. */
2063 points[npoints-1].x != points[npoints].x ||
2064 points[npoints-1].y != points[npoints].y)
2068 /* Mark up the histo array to find the outer border. */
2077 int x = (i + 26) % 26;
2079 for (y = 0; y <= letter; y++)
2080 histo[y * 26 + x]++;
2084 dc->codeword_text_points[letter] = npoints;
2090 if (npoints >= letters * outer_facets) abort();
2095 for (y = 0; y < letters; y++)
2097 fprintf (stderr, "%2d: ", y);
2098 for (x = 0; x < 26; x++)
2099 fprintf (stderr, "%x", histo[y * 26 + x]);
2100 fprintf (stderr, "\n");
2102 fprintf (stderr, "\n");
2107 /* Find a gap in the outer edge, to draw guide dots. */
2110 int last_row = letters;
2111 int start_dial = -1, end_dial = -1;
2113 for (y = letters-1; y >= 0; y--)
2115 for (x = 0; x < 26; x++)
2117 if (histo[y * 26 + x] == 0)
2120 start_dial = end_dial = -1;
2122 if (start_dial == -1)
2129 if (last_row < letters-1 && start_dial >= 0)
2131 GLfloat r = iradius + rtick * (last_row + 2);
2134 dc->codeword_nguides = 0;
2135 dc->codeword_guides = (XYZ *)
2136 calloc (end_dial - start_dial + 1, sizeof (*dc->codeword_guides));
2137 for (i = start_dial; i <= end_dial; i++)
2139 GLfloat th = i * M_PI * 2 / 26;
2140 GLfloat x = r * cos (th);
2141 GLfloat y = r * sin (th);
2142 dc->codeword_guides[dc->codeword_nguides].x = x;
2143 dc->codeword_guides[dc->codeword_nguides].y = y;
2144 dc->codeword_nguides++;
2151 dc->codeword_path_npoints = npoints;
2152 dc->codeword_path = points;
2157 draw_codeword_cap (ModeInfo *mi)
2159 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2160 int wire = MI_IS_WIREFRAME(mi);
2163 int segments = dc->codeword_disc_facets;
2164 GLfloat size = dc->codeword_spread * dc->codeword_cap_size;
2165 GLfloat width = dc->codeword_line_width / 2;
2166 GLfloat thick = dc->codeword_thickness / 2;
2167 GLfloat r1 = size + width/2;
2168 GLfloat r2 = size - width/2;
2169 GLfloat facet, th, z;
2171 if (wire) segments = 12;
2172 facet = M_PI * 2 / segments;
2176 /* Top and bottom */
2178 for (z = -thick; z <= thick; z += thick*2)
2180 glNormal3f (0, 0, (z < 0 ? -1 : 1));
2181 glFrontFace (z < 0 ? GL_CCW : GL_CW);
2183 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
2184 for (th = 0; th <= M_PI*2; th += facet)
2186 GLfloat x = cos (th);
2187 GLfloat y = sin (th);
2188 glVertex3f (r1 * x, r1 * y, z);
2189 glVertex3f (r2 * x, r2 * y, z);
2195 glBegin (GL_LINE_LOOP);
2196 for (th = 0; th <= M_PI*2; th += facet)
2198 GLfloat x = cos (th);
2199 GLfloat y = sin (th);
2200 glVertex3f (r1 * x, r1 * y, z);
2203 glBegin (GL_LINE_LOOP);
2204 for (th = 0; th <= M_PI*2; th += facet)
2206 GLfloat x = cos (th);
2207 GLfloat y = sin (th);
2208 glVertex3f (r2 * x, r2 * y, z);
2214 /* Inside and outside */
2216 for (z = -1; z <= 1; z += 2)
2218 glFrontFace (z < 0 ? GL_CCW : GL_CW);
2220 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
2221 for (th = 0; th <= M_PI*2; th += facet)
2223 GLfloat th1 = th + facet;
2224 GLfloat x0 = cos (th);
2225 GLfloat y0 = sin (th);
2226 GLfloat x1 = cos (th1);
2227 GLfloat y1 = sin (th1);
2228 GLfloat r = z < 0 ? r1 : r2;
2231 do_normal (r * x0, r * y0, thick,
2232 r * x0, r * y0, -thick,
2233 r * x1, r * y1, -thick);
2235 do_normal (r * x1, r * y1, thick,
2236 r * x1, r * y1, -thick,
2237 r * x0, r * y0, -thick);
2239 glVertex3f (r * x0, r * y0, thick);
2240 glVertex3f (r * x0, r * y0, -thick);
2252 draw_codeword_guides (ModeInfo *mi, GLfloat anim_ratio)
2254 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2255 int wire = MI_IS_WIREFRAME(mi);
2258 int segments = dc->codeword_disc_facets;
2259 GLfloat s = dc->codeword_line_width / 2;
2260 GLfloat each = 1.0 / dc->codeword_nguides;
2263 if (wire) segments = 6;
2265 for (i = 0; i < dc->codeword_nguides; i++)
2268 if (anim_ratio < i*each) ratio = 0;
2269 else if (anim_ratio >= (i+1)*each) ratio = 1;
2270 else ratio = (anim_ratio - i*each) / each;
2272 if (ratio <= 0) continue;
2273 if (ratio == 0) ratio = 0.001;
2276 glTranslatef (dc->codeword_guides[i].x,
2277 dc->codeword_guides[i].y,
2278 dc->codeword_guides[i].z);
2280 glScalef (ratio, ratio, ratio);
2282 /* If the line width and thickness are pretty close to each other,
2283 use spheres. Otherwise use tubes.
2285 if (dc->codeword_thickness < dc->codeword_line_width * 1.3 &&
2286 dc->codeword_thickness > dc->codeword_line_width / 1.3)
2289 glFrontFace (GL_CCW);
2290 polys += unit_sphere (segments, segments, wire);
2294 polys += tube (0, 0, -dc->codeword_thickness / 2,
2295 0, 0, dc->codeword_thickness / 2,
2296 s, 0, segments, True, True, wire);
2306 /* Compute the characters at which the cursor is currently pointing,
2307 and render it on the logo.
2310 codeword_text_output (ModeInfo *mi, GLfloat anim_ratio)
2312 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2314 int L = strlen (dc->codeword_text);
2315 int point = dc->codeword_path_npoints * anim_ratio;
2318 if (dc->anim_state == CODEWORD_BLANK)
2321 for (i = 0; i < L; i++)
2323 if (point >= dc->codeword_text_points[i])
2324 dc->codeword_text_out[i] = dc->codeword_text[i];
2326 dc->codeword_text_out[i] = 0;
2329 int steps = dc->codeword_text[i] - 'A' + 1;
2330 int last = (i > 0 ? dc->codeword_text_points[i-1] : 0);
2331 double ratio = ((point - last) /
2332 (double) (dc->codeword_text_points[i] - last));
2333 char chr = 'A' + (ratio * steps);
2334 if (ratio < 0.1) chr = 0;
2335 dc->codeword_text_out[i] = chr;
2339 dc->codeword_text_out[i] = 0;
2341 if (*dc->codeword_text_out &&
2342 !strcmp (dc->codeword_text, "CODEWORD"))
2345 int L2 = strlen (dc->codeword_text_out);
2347 int ascent, descent;
2350 glColor4fv (dc->codeword_color);
2351 glRotatef (90, 0, 1, 0);
2352 glRotatef (-90, 0, 0, 1);
2354 for (i = 0; i < L2; i++)
2359 glRotatef ((i + 0.5) * 360 / 26.0, 0, 0, 1);
2364 glDisable(GL_LIGHTING);
2369 glBegin(GL_LINE_STRIP);
2370 for (th = M_PI * 1.45; th < M_PI * 1.55; th += 0.1)
2373 glVertex3f (r * cos(th), r * sin(th), 0);
2376 if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING);
2380 glTranslatef (0, -dc->codeword_spread * (L - 1), 0);
2381 glScalef (ss, ss, ss);
2382 buf[0] = dc->codeword_text_out[i] + ('a' - 'A');
2384 texture_string_metrics (dc->font, buf, &e, &ascent, &descent);
2387 /* #### Magic magic magic WTF... */
2388 glScalef (0.5, 0.5, 0.5);
2391 glTranslatef (-e.width * 1.0,
2392 -(ascent + descent + e.descent * 2.4), /* #### WTF */
2398 glDisable(GL_LIGHTING);
2399 glBegin(GL_LINE_LOOP);
2400 glVertex3f(0, 0, 0);
2401 glVertex3f(e.width, 0, 0);
2402 glVertex3f(e.width, e.ascent + e.descent, 0);
2403 glVertex3f(0, e.ascent + e.descent, 0);
2405 if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING);
2408 glDisable(GL_CULL_FACE); /* tell texfont.c to draw both sides */
2409 print_texture_string (dc->font, buf);
2410 glEnable(GL_CULL_FACE);
2419 /* Convert the precomputed path to a thick line of polygons.
2420 We could actually precompute all of these polygons too,
2421 but it's fast enough.
2424 draw_codeword_path (ModeInfo *mi)
2426 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2427 int wire = MI_IS_WIREFRAME(mi);
2430 GLfloat anim_ratio = (dc->anim_state == CODEWORD_IN ? dc->anim_ratio :
2431 dc->anim_state == CODEWORD_OUT ? 1 - dc->anim_ratio :
2432 dc->anim_state == CODEWORD_BLANK ? 0 :
2434 int last_anim_point = 0;
2436 GLfloat width = dc->codeword_line_width / 2;
2437 GLfloat thick = dc->codeword_thickness / 2;
2441 int quad_size = (dc->codeword_path_npoints + 1) * 2;
2442 XYZ *quads = (XYZ *) calloc (quad_size, sizeof(*quads));
2443 XYZ *norms = (XYZ *) calloc (quad_size, sizeof(*norms));
2446 for (i = 0; i < dc->codeword_path_npoints; i++)
2448 XYZ p1 = dc->codeword_path[i];
2449 XYZ p2 = (i < dc->codeword_path_npoints-1
2450 ? dc->codeword_path[i+1]
2451 : dc->codeword_path[i-1]);
2454 XYZ n; /* normal of the first line segment */
2455 n.x = -(p2.y - p1.y);
2456 n.y = (p2.x - p1.x);
2462 p1a.x = p1.x - width / 2 * n.x;
2463 p1a.y = p1.y - width / 2 * n.y;
2466 p1b.x = p1.x + width / 2 * n.x;
2467 p1b.y = p1.y + width / 2 * n.y;
2470 else if (i == dc->codeword_path_npoints - 1)
2472 p1b.x = p1.x - width / 2 * n.x;
2473 p1b.y = p1.y - width / 2 * n.y;
2476 p1a.x = p1.x + width / 2 * n.x;
2477 p1a.y = p1.y + width / 2 * n.y;
2482 XYZ p0 = dc->codeword_path[i-1];
2484 XYZ t, t0, t1; /* tangent of corner between two line segments */
2485 XYZ m; /* miter line: normal of tangent */
2486 GLfloat d; /* length of miter */
2507 /* find length of miter by projecting it on one of the normals */
2508 d = width / 2 / dot (m, n);
2510 p1a.x = p1.x - d * m.x;
2511 p1a.y = p1.y - d * m.y;
2514 p1b.x = p1.x + d * m.x;
2515 p1b.y = p1.y + d * m.y;
2519 quads[nquads++] = p1a;
2520 quads[nquads++] = p1b;
2522 if (nquads >= quad_size) abort();
2524 if (i / (double) dc->codeword_path_npoints > anim_ratio)
2527 last_anim_point = i;
2531 /* Compute normals for each point along the interior edge */
2532 for (k = 0; k <= 1; k++)
2534 for (i = k; i < nquads-2; i += 2)
2537 XYZ p2a = quads[i+2];
2540 p1a.z = thick; /* a: top */
2541 p1b.z = -thick; /* b: bottom */
2546 ? calc_normal (p1a, p1b, p2b)
2547 : calc_normal (p2a, p2b, p1a));
2552 glColor4fv (dc->codeword_color);
2553 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, dc->codeword_color);
2555 # ifdef HAVE_MOBILE /* Make the whole thing fit on the phone screen */
2557 GLfloat size = MI_WIDTH(mi) < MI_HEIGHT(mi) ? MI_WIDTH(mi) : MI_HEIGHT(mi);
2558 glScalef (0.9, 0.9, 0.9);
2559 if (size <= 768) /* iPad retina / iPhone 6 */
2560 glScalef (0.7, 0.7, 0.7);
2564 codeword_text_output (mi, anim_ratio);
2566 glRotatef (90, 1, 0, 0);
2567 glRotatef (90, 0, 1, 0);
2568 glRotatef (-90, 0, 0, 1);
2569 glScalef (0.8, 0.8, 0.8);
2571 glNormal3f (0, 0, -1);
2573 if (anim_ratio <= 0)
2575 polys += draw_codeword_cap (mi);
2580 glColor3f (1, 0, 0);
2581 glBegin(GL_LINE_STRIP);
2582 for (i = 0; i < dc->codeword_path_npoints; i++)
2584 glVertex3f (dc->codeword_path[i].x,
2585 dc->codeword_path[i].y,
2586 dc->codeword_path[i].z);
2590 glColor4fv (dc->codeword_color);
2597 for (i = 0; i <= 1; i++)
2598 for (j = -thick; j <= thick; j += thick*2)
2600 glBegin (GL_LINE_STRIP);
2601 for (k = i; k < nquads; k += 2)
2603 glVertex3f (quads[k].x, quads[k].y, j);
2610 /* Top and bottom */
2612 for (j = -thick; j <= thick; j += thick*2)
2616 glNormal3f (0, 0, -1);
2617 glFrontFace (GL_CW);
2621 glNormal3f (0, 0, 1);
2622 glFrontFace (GL_CCW);
2624 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
2625 for (i = 0; i < nquads; i += 2)
2627 glVertex3f (quads[i+1].x, quads[i+1].y, j);
2628 glVertex3f (quads[i].x, quads[i].y, j);
2636 for (k = 0; k <= 1; k++)
2640 glNormal3f (0, 0, -1);
2641 glFrontFace (GL_CW);
2645 glNormal3f (0, 0, 1);
2646 glFrontFace (GL_CCW);
2649 glBegin (wire ? GL_LINES : GL_QUADS);
2650 for (i = k; i < nquads; i += 2)
2653 XYZ p2a = (i < nquads-2) ? quads[i+2] : p1a;
2658 XYZ n2 = (i < nquads-2) ? norms[i+2] : n1;
2660 /* If the two normals are very similar, smooth the face.
2661 If they are different, it's a sharp turn, and use the
2662 same normal for both edges (not quite right, but close).
2664 GLfloat angle = vector_angle (n1.x, n1.y, n1.z,
2666 GLfloat pointy = 0.8;
2673 glNormal3f (n1.x, n1.y, n1.z);
2674 glVertex3f (p1a.x, p1a.y, p1a.z);
2675 glVertex3f (p1b.x, p1b.y, p1b.z);
2678 glNormal3f (n2.x, n2.y, n2.z);
2679 glVertex3f (p2b.x, p2b.y, p2b.z);
2680 glVertex3f (p2a.x, p2a.y, p2a.z);
2687 /* Only draw the guides when the path is almost complete;
2688 fade them in and out based on completeness. */
2690 GLfloat size = 0.95;
2691 GLfloat r = (anim_ratio > size
2692 ? (anim_ratio - size) / (1 - size)
2694 polys += draw_codeword_guides (mi, r);
2698 /* Draw the start and end caps */
2701 GLfloat x, y, z, x2, y2, z2, X, Y, Z;
2702 GLfloat r = dc->codeword_spread * dc->codeword_cap_size;
2705 x = dc->codeword_path[i].x;
2706 y = dc->codeword_path[i].y;
2707 z = dc->codeword_path[i].z;
2712 glTranslatef (x, y, z);
2713 polys += draw_codeword_cap (mi);
2718 i = last_anim_point + 1;
2719 if (i > dc->codeword_path_npoints - 1)
2720 i = dc->codeword_path_npoints - 1;
2722 x = dc->codeword_path[i].x;
2723 y = dc->codeword_path[i].y;
2724 z = dc->codeword_path[i].z;
2727 x2 = dc->codeword_path[i].x;
2728 y2 = dc->codeword_path[i].y;
2729 z2 = dc->codeword_path[i].z;
2736 glTranslatef (x, y, z);
2737 glRotatef (-atan2 (X, Y) * (180 / M_PI), 0, 0, 1);
2738 glRotatef ( atan2 (Z, sqrt(X*X + Y*Y)) * (180 / M_PI), 1, 0, 0);
2739 glTranslatef (0, -r, 0);
2740 polys += draw_codeword_cap (mi);
2758 reshape_logo (ModeInfo *mi, int width, int height)
2761 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2763 GLfloat h = (GLfloat) height / (GLfloat) width;
2764 GLfloat persp = 64; /* 30 */
2765 GLfloat pos = 13; /* 30 */
2768 persp += dc->persp_off;
2772 glViewport (0, 0, (GLint) width, (GLint) height);
2774 glMatrixMode(GL_PROJECTION);
2776 gluPerspective (persp, 1/h, 1, 100);
2778 glMatrixMode(GL_MODELVIEW);
2780 gluLookAt( 0, 0, pos,
2784 # ifdef HAVE_MOBILE /* Keep it the same relative size when rotated. */
2786 int o = (int) current_device_rotation();
2787 if (o != 0 && o != 180 && o != -180)
2788 glScalef (1/h, 1/h, 1/h); /* #### Why does this change the lighting? */
2792 glClear(GL_COLOR_BUFFER_BIT);
2797 gl_init (ModeInfo *mi)
2799 /* logo_configuration *dc = &dcs[MI_SCREEN(mi)]; */
2800 int wire = MI_IS_WIREFRAME(mi);
2802 GLfloat position[] = {0, 0, 0, 0};
2803 GLfloat direction[] = {3, -1, -3};
2805 position[0] = -direction[0];
2806 position[1] = -direction[1];
2807 position[2] = -direction[2];
2811 glLightfv(GL_LIGHT0, GL_POSITION, position);
2812 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction);
2813 glShadeModel(GL_SMOOTH);
2814 glEnable(GL_NORMALIZE);
2815 glEnable(GL_CULL_FACE);
2816 glEnable(GL_LIGHTING);
2817 glEnable(GL_LIGHT0);
2818 glEnable(GL_DEPTH_TEST);
2824 init_logo (ModeInfo *mi)
2826 logo_configuration *dc;
2827 int do_gasket = get_boolean_resource(mi->dpy, "doGasket", "Boolean");
2828 int do_helix = get_boolean_resource(mi->dpy, "doHelix", "Boolean");
2829 int do_ladder = (do_helix &&
2830 get_boolean_resource(mi->dpy, "doLadder", "Boolean"));
2831 int do_frame = get_boolean_resource(mi->dpy, "doFrame", "Boolean");
2832 GLfloat helix_rot = 147.0;
2834 if (!do_gasket && !do_helix)
2836 fprintf (stderr, "%s: no helix or gasket?\n", progname);
2842 dc = &dcs[MI_SCREEN(mi)];
2844 if ((dc->glx_context = init_GL(mi)) != NULL) {
2846 reshape_logo (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
2849 dc->wall_facets = get_integer_resource(mi->dpy, "wallFacets", "Integer");
2850 dc->bar_facets = get_integer_resource(mi->dpy, "barFacets", "Integer");
2851 dc->clockwise = get_boolean_resource(mi->dpy, "clockwise", "Boolean");
2852 dc->turns = get_float_resource(mi->dpy, "turns", "Float");
2853 dc->turn_spacing = get_float_resource(mi->dpy, "turnSpacing", "Float");
2854 dc->bar_spacing = get_float_resource(mi->dpy, "barSpacing", "Float");
2855 dc->wall_height = get_float_resource(mi->dpy, "wallHeight", "Float");
2856 dc->wall_thickness = get_float_resource(mi->dpy, "wallThickness", "Float");
2857 dc->bar_thickness = get_float_resource(mi->dpy, "barThickness", "Float");
2858 dc->wall_taper = get_float_resource(mi->dpy, "wallTaper", "Float");
2860 dc->gasket_size = get_float_resource(mi->dpy,"gasketSize", "Float");
2861 dc->gasket_depth = get_float_resource(mi->dpy,"gasketDepth", "Float");
2862 dc->gasket_thickness = get_float_resource(mi->dpy,"gasketThickness","Float");
2864 dc->frame_size = get_float_resource(mi->dpy, "frameSize", "Float");
2865 dc->frame_depth = get_float_resource(mi->dpy, "frameDepth", "Float");
2866 dc->frame_thickness = get_float_resource(mi->dpy, "frameThickness", "Float");
2867 dc->triangle_size = get_float_resource(mi->dpy, "triangleSize", "Float");
2869 dc->speed = get_float_resource(mi->dpy, "speed", "Float");
2871 dc->codeword_text = get_string_resource(mi->dpy, "text", "String");
2872 dc->codeword_text = codeword_simplify_text (dc->codeword_text);
2873 dc->codeword_text_out =
2874 calloc (strlen(dc->codeword_text) + 1, sizeof(*dc->codeword_text_out));
2875 dc->codeword_text_points =
2876 (int *) calloc (strlen(dc->codeword_text) + 1,
2877 sizeof(*dc->codeword_text_points));
2879 dc->codeword_facets = get_integer_resource(mi->dpy, "cwFacets", "Integer");
2880 dc->codeword_disc_facets = get_integer_resource(mi->dpy,
2881 "cwDiscFacets", "Integer");
2882 dc->codeword_spread = get_float_resource(mi->dpy, "cwSpread", "Float");
2883 dc->codeword_line_width = get_float_resource(mi->dpy, "cwLineWidth", "Float");
2884 dc->codeword_thickness = get_float_resource(mi->dpy, "cwThickness", "Float");
2885 dc->codeword_cap_size = get_float_resource(mi->dpy, "cwCapSize", "Float");
2889 char *s = get_string_resource (MI_DISPLAY (mi), "mode", "String");
2890 if (!s || !*s || !strcasecmp (s, "helix"))
2892 else if (!strcasecmp (s, "pizza"))
2894 else if (!strcasecmp (s, "both"))
2895 dc->mode = HELIX_AND_PIZZA;
2897 else if (!strcasecmp (s, "codeword"))
2898 dc->mode = CODEWORD_IN;
2903 "%s: mode must be helix, pizza or both, not \"%s\"\n",
2909 dc->anim_state = (dc->mode == HELIX_AND_PIZZA
2910 ? ((random() & 1) ? HELIX : PIZZA)
2916 if (dc->mode == CODEWORD_IN)
2917 dc->font = load_texture_font (MI_DISPLAY(mi), "cwFont");
2921 dc->label_font = load_texture_font (MI_DISPLAY(mi), "fpsFont");
2928 get_string_resource (mi->dpy, "foreground", "Foreground");
2930 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
2931 if (*s2 == ' ' || *s2 == '\t')
2936 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
2938 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
2942 dc->color[0] = xcolor.red / 65535.0;
2943 dc->color[1] = xcolor.green / 65535.0;
2944 dc->color[2] = xcolor.blue / 65535.0;
2947 color_name = get_string_resource (mi->dpy, "cwForeground", "Foreground");
2948 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
2949 if (*s2 == ' ' || *s2 == '\t')
2954 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
2956 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
2961 dc->codeword_color[0] = xcolor.red / 65535.0;
2962 dc->codeword_color[1] = xcolor.green / 65535.0;
2963 dc->codeword_color[2] = xcolor.blue / 65535.0;
2964 dc->codeword_color[3] = 1.0;
2966 color_name = get_string_resource (mi->dpy, "cwBackground", "Background");
2967 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
2968 if (*s2 == ' ' || *s2 == '\t')
2973 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
2975 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
2979 dc->codeword_bg[0] = xcolor.red / 65535.0;
2980 dc->codeword_bg[1] = xcolor.green / 65535.0;
2981 dc->codeword_bg[2] = xcolor.blue / 65535.0;
2982 dc->codeword_bg[3] = 1.0;
2986 dc->trackball = gltrackball_init (False);
2988 dc->gasket_spinnerx.probability = 0.1;
2989 dc->gasket_spinnery.probability = 0.1;
2990 dc->gasket_spinnerz.probability = 1.0;
2991 dc->gasket_spinnerx.easement = 0.08;
2992 dc->gasket_spinnery.easement = 0.08;
2993 dc->gasket_spinnerz.easement = 0.08;
2995 dc->helix_spinnerz.probability = 0.6;
2996 dc->helix_spinnerz.easement = 0.2;
2998 dc->pizza_spinnerz.probability = 0.6;
2999 dc->pizza_spinnery.probability = 0.6;
3000 dc->pizza_spinnerz.easement = 0.2;
3001 dc->pizza_spinnery.easement = 0.2;
3003 dc->frame_spinner.probability = 5.0;
3004 dc->frame_spinner.easement = 0.2;
3006 dc->scene_spinnerx.probability = 0.1;
3007 dc->scene_spinnery.probability = 0.0;
3008 dc->scene_spinnerx.easement = 0.1;
3009 dc->scene_spinnery.easement = 0.1;
3012 if (dc->mode == CODEWORD_IN)
3014 double tilt_speed = 0.003;
3015 dc->scene_rot = make_rotator (0, 0, 0, 0, tilt_speed, True);
3019 /* start the frame off-screen */
3020 dc->frame_spinner.spinning_p = True;
3021 dc->frame_spinner.position = 0.3;
3022 dc->frame_spinner.speed = 0.001;
3024 if (dc->speed > 0) /* start off with the gasket in motion */
3026 dc->gasket_spinnerz.spinning_p = True;
3027 dc->gasket_spinnerz.speed = (0.002
3028 * ((random() & 1) ? 1 : -1)
3032 # ifdef DXF_OUTPUT_HACK
3035 dc->frame_depth = dc->gasket_depth;
3040 glRotatef(90, 1, 0, 0);
3041 glRotatef(90, 0, 0, 1);
3042 make_pizza (dc, 0, 0);
3045 glRotatef(helix_rot, 0, 0, 1);
3046 make_ladder (dc, 0, 0);
3047 make_helix (dc, 0, 0);
3048 glRotatef (180, 0, 0, 1);
3049 make_helix (dc, 0, 0);
3053 make_gasket (dc, 0);
3061 glRotatef(90, 1, 0, 0);
3062 glRotatef(90, 0, 0, 1);
3063 dc->anim_state = CODEWORD;
3064 make_codeword_path (mi);
3065 draw_codeword_path (mi);
3073 dc->helix_list = glGenLists (1);
3074 glNewList (dc->helix_list, GL_COMPILE);
3075 glRotatef(helix_rot, 0, 0, 1);
3076 if (do_ladder) dc->polys[0] += make_ladder (dc, 0, 0);
3077 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
3078 glRotatef(180, 0, 0, 1);
3079 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
3084 dc->helix_list_wire = glGenLists (1);
3085 glNewList (dc->helix_list_wire, GL_COMPILE);
3086 /* glRotatef(helix_rot, 0, 0, 1); wtf? */
3087 if (do_ladder) dc->polys[1] += make_ladder (dc, 1, 1);
3088 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
3089 glRotatef(180, 0, 0, 1);
3090 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
3095 dc->helix_list_facetted = glGenLists (1);
3096 glNewList (dc->helix_list_facetted, GL_COMPILE);
3097 glRotatef(helix_rot, 0, 0, 1);
3098 if (do_ladder) dc->polys[2] += make_ladder (dc, 1, 0);
3099 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
3100 glRotatef(180, 0, 0, 1);
3101 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
3105 dc->pizza_list = glGenLists (1);
3106 glNewList (dc->pizza_list, GL_COMPILE);
3107 if (do_frame) dc->polys[5] += make_pizza (dc, 0, 0);
3110 dc->pizza_list_wire = glGenLists (1);
3111 glNewList (dc->pizza_list_wire, GL_COMPILE);
3112 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 1);
3115 dc->pizza_list_facetted = glGenLists (1);
3116 glNewList (dc->pizza_list_facetted, GL_COMPILE);
3117 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 0);
3120 dc->gasket_list = glGenLists (1);
3121 glNewList (dc->gasket_list, GL_COMPILE);
3122 if (do_gasket) dc->polys[3] += make_gasket (dc, 0);
3125 dc->gasket_list_wire = glGenLists (1);
3126 glNewList (dc->gasket_list_wire, GL_COMPILE);
3127 if (do_gasket) dc->polys[4] += make_gasket (dc, 1);
3130 dc->frame_list = glGenLists (1);
3131 glNewList (dc->frame_list, GL_COMPILE);
3132 if (do_frame) dc->polys[5] += make_frame (dc, 0);
3135 dc->frame_list_wire = glGenLists (1);
3136 glNewList (dc->frame_list_wire, GL_COMPILE);
3137 if (do_frame) dc->polys[6] += make_frame (dc, 1);
3141 make_codeword_path (mi);
3144 /* When drawing both solid and wireframe objects,
3145 make sure the wireframe actually shows up! */
3146 glEnable (GL_POLYGON_OFFSET_FILL);
3147 glPolygonOffset (1.0, 1.0);
3152 logo_handle_event (ModeInfo *mi, XEvent *event)
3154 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
3156 if (gltrackball_event_handler (event, dc->trackball,
3157 MI_WIDTH (mi), MI_HEIGHT (mi),
3158 &dc->button_down_p))
3160 else if (event->xany.type == KeyPress)
3164 XLookupString (&event->xkey, &c, 1, &keysym, 0);
3169 if (c == 'a') dc->persp_off += step;
3170 else if (c == 'z') dc->persp_off -= step;
3171 else if (c == 's') dc->pos_off += step;
3172 else if (c == 'x') dc->pos_off -= step;
3175 /* dc->pos_off = -dc->persp_off; */
3176 reshape_logo (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
3181 if (c == ' ' || c == '\t')
3183 switch (dc->anim_state) {
3185 dc->anim_state = HELIX_OUT;
3186 dc->anim_ratio = 0.0;
3189 dc->anim_state = PIZZA_OUT;
3190 dc->anim_ratio = 0.0;
3194 dc->anim_state = CODEWORD_OUT;
3195 dc->anim_ratio = 0.0;
3209 spinner_ease (GLfloat x)
3211 /* Smooth curve up, ending at slope = 1. */
3212 return cos ((x/2 + 1) * M_PI) + 1;
3217 tick_spinner (ModeInfo *mi, spinner *s)
3219 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
3221 if (dc->speed == 0) return;
3222 if (dc->button_down_p) return;
3226 s->position += s->speed;
3227 if (s->position >= 1.0 || s->position <= 0.0)
3230 s->position_eased = 0;
3231 s->spinning_p = False;
3233 else if (s->easement > 0 && s->position <= s->easement)
3234 s->position_eased = (s->easement *
3235 spinner_ease (s->position / s->easement));
3236 else if (s->easement > 0 && s->position >= 1-s->easement)
3237 s->position_eased = (1 - s->easement *
3238 spinner_ease ((1 - s->position) / s->easement));
3240 s->position_eased = s->position;
3242 else if (s->probability &&
3243 (random() % (int) (PROBABILITY_SCALE / s->probability)) == 0)
3246 s->spinning_p = True;
3249 s->speed = dc->speed * (frand(ss/3) + frand(ss/3) + frand(ss/3));
3250 } while (s->speed <= 0);
3253 s->speed = -s->speed;
3261 link_spinners (ModeInfo *mi, spinner *s0, spinner *s1)
3263 if (s0->spinning_p && !s1->spinning_p)
3265 GLfloat op = s1->probability;
3266 s1->probability = PROBABILITY_SCALE;
3267 tick_spinner (mi, s1);
3268 s1->probability = op;
3274 draw_logo (ModeInfo *mi)
3276 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
3277 Display *dpy = MI_DISPLAY(mi);
3278 Window window = MI_WINDOW(mi);
3279 int wire = MI_IS_WIREFRAME(mi);
3281 GLfloat specular[] = {0.8, 0.8, 0.8, 1.0};
3282 GLfloat shininess = 50.0;
3288 if (!dc->glx_context)
3291 mi->polygon_count = 0;
3292 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(dc->glx_context));
3295 dc->wire_overlay == 0 &&
3296 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
3297 dc->wire_overlay = ((random() % 200) +
3302 tick_spinner (mi, &dc->gasket_spinnerx);
3303 tick_spinner (mi, &dc->gasket_spinnery);
3304 tick_spinner (mi, &dc->gasket_spinnerz);
3305 tick_spinner (mi, &dc->helix_spinnerz);
3306 tick_spinner (mi, &dc->pizza_spinnery);
3307 tick_spinner (mi, &dc->pizza_spinnerz);
3308 tick_spinner (mi, &dc->scene_spinnerx);
3309 tick_spinner (mi, &dc->scene_spinnery);
3310 tick_spinner (mi, &dc->frame_spinner);
3311 link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery);
3314 switch (dc->anim_state)
3317 if (dc->mode == HELIX_AND_PIZZA &&
3318 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
3319 dc->anim_state = HELIX_OUT;
3323 dc->anim_ratio += 0.1 * dc->speed;
3324 if (dc->anim_ratio >= 1.0)
3326 dc->anim_ratio = 0.0;
3327 dc->anim_state = PIZZA_IN;
3332 dc->anim_ratio += 0.1 * dc->speed;
3333 if (dc->anim_ratio >= 1.0)
3335 dc->anim_ratio = 0.0;
3336 dc->anim_state = PIZZA;
3341 if (dc->mode == HELIX_AND_PIZZA &&
3342 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
3343 dc->anim_state = PIZZA_OUT;
3347 dc->anim_ratio += 0.1 * dc->speed;
3348 if (dc->anim_ratio >= 1.0)
3350 dc->anim_ratio = 0.0;
3351 dc->anim_state = HELIX_IN;
3356 dc->anim_ratio += 0.1 * dc->speed;
3357 if (dc->anim_ratio >= 1.0)
3359 dc->anim_ratio = 0.0;
3360 dc->anim_state = HELIX;
3367 dc->scene_spinnerx.probability = 0.2;
3368 dc->scene_spinnery.probability = 0.05;
3369 if (! dc->button_down_p)
3370 dc->anim_ratio += 0.004 * dc->speed;
3371 if (dc->anim_ratio >= 1.0)
3373 dc->anim_state = CODEWORD;
3374 dc->anim_ratio = frand (0.5);
3379 dc->scene_spinnerx.probability = 0.5;
3380 dc->scene_spinnery.probability = 0.2;
3381 if (! dc->button_down_p)
3382 dc->anim_ratio += (0.0005 + frand(0.002)) * dc->speed;
3383 if (dc->anim_ratio >= 1.0)
3385 dc->anim_ratio = 0.0;
3386 dc->anim_state = CODEWORD_OUT;
3391 dc->scene_spinnerx.probability = 0;
3392 dc->scene_spinnery.probability = 0;
3393 if (! dc->button_down_p)
3394 dc->anim_ratio += 0.02 * dc->speed;
3395 if (dc->anim_ratio >= 1.0)
3397 dc->anim_ratio = 0.0;
3398 dc->anim_state = CODEWORD_BLANK;
3402 case CODEWORD_BLANK:
3403 dc->scene_spinnerx.probability = 0;
3404 dc->scene_spinnery.probability = 0;
3405 if (! dc->button_down_p)
3406 dc->anim_ratio += 0.01 * dc->speed;
3407 if (dc->anim_ratio >= 1.0)
3409 dc->anim_ratio = 0.0;
3410 dc->anim_state = CODEWORD_IN;
3421 dc->anim_state = HELIX;
3422 dc->wire_overlay = 0;
3425 pizza_p = (dc->anim_state == PIZZA ||
3426 dc->anim_state == PIZZA_IN ||
3427 dc->anim_state == PIZZA_OUT);
3430 codeword_p = (dc->anim_state == CODEWORD ||
3431 dc->anim_state == CODEWORD_IN ||
3432 dc->anim_state == CODEWORD_OUT ||
3433 dc->anim_state == CODEWORD_BLANK);
3436 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3439 glRotatef(current_device_rotation(), 0, 0, 1);
3441 GLfloat scale = 1.8;
3442 glScalef(scale, scale, scale);
3444 glColor3f(dc->color[0], dc->color[1], dc->color[2]);
3447 /* Draw frame before trackball rotation */
3452 GLfloat p = (dc->frame_spinner.position_eased >= 0
3453 ? dc->frame_spinner.position_eased
3454 : -dc->frame_spinner.position_eased);
3455 GLfloat size = (p > 0.5 ? 1-p : p);
3456 scale = 1 + (size * 10);
3458 /* gltrackball_rotate (dc->trackball); */
3459 glRotatef(90, 1, 0, 0);
3460 glRotatef(90, 0, 0, 1);
3462 glScalef (1, scale, scale);
3465 glDisable (GL_LIGHTING);
3466 glCallList (dc->frame_list_wire);
3467 mi->polygon_count += dc->polys[6];
3469 else if (dc->wire_overlay != 0)
3471 glCallList (dc->frame_list);
3472 glDisable (GL_LIGHTING);
3473 glColor3fv (dc->color);
3474 glCallList (dc->frame_list_wire);
3475 mi->polygon_count += dc->polys[6];
3476 if (!wire) glEnable (GL_LIGHTING);
3480 glCallList (dc->frame_list);
3481 mi->polygon_count += dc->polys[5];
3486 gltrackball_rotate (dc->trackball);
3488 glRotatef(90, 1, 0, 0);
3489 glRotatef(90, 0, 0, 1);
3495 glRotatef (360 * dc->scene_spinnerx.position_eased, 0, 1, 0);
3496 glRotatef (360 * dc->scene_spinnery.position_eased, 0, 0, 1);
3500 glRotatef (360 * dc->gasket_spinnerx.position_eased, 0, 1, 0);
3501 glRotatef (360 * dc->gasket_spinnery.position_eased, 0, 0, 1);
3502 glRotatef (360 * dc->gasket_spinnerz.position_eased, 1, 0, 0);
3504 memcpy (gcolor, dc->color, sizeof (dc->color));
3505 if (dc->wire_overlay != 0)
3507 gcolor[0] = gcolor[1] = gcolor[2] = 0;
3508 specular[0] = specular[1] = specular[2] = 0;
3511 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
3512 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
3513 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shininess);
3517 glDisable (GL_LIGHTING);
3518 glCallList (dc->gasket_list_wire);
3519 mi->polygon_count += dc->polys[4];
3521 else if (dc->wire_overlay != 0)
3523 glCallList (dc->gasket_list);
3524 glDisable (GL_LIGHTING);
3525 glColor3fv (dc->color);
3526 glCallList (dc->gasket_list_wire);
3527 mi->polygon_count += dc->polys[4];
3528 if (!wire) glEnable (GL_LIGHTING);
3529 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
3533 glCallList (dc->gasket_list);
3534 mi->polygon_count += dc->polys[3];
3540 glRotatef (360 * dc->pizza_spinnery.position_eased, 1, 0, 0);
3541 glRotatef (360 * dc->pizza_spinnerz.position_eased, 0, 0, 1);
3545 glRotatef (360 * dc->helix_spinnerz.position_eased, 0, 0, 1);
3548 scale = ((dc->anim_state == PIZZA_IN || dc->anim_state == HELIX_IN)
3550 : ((dc->anim_state == PIZZA_OUT || dc->anim_state == HELIX_OUT)
3551 ? 1.0 - dc->anim_ratio
3553 if (scale <= 0) scale = 0.001;
3554 glScalef (scale, scale, scale);
3558 glDisable (GL_LIGHTING);
3560 glCallList (dc->pizza_list_wire);
3562 glCallList (dc->helix_list_wire);
3563 mi->polygon_count += dc->polys[1];
3565 else if (dc->wire_overlay != 0)
3568 glCallList (dc->pizza_list_facetted);
3570 glCallList (dc->helix_list_facetted);
3572 glDisable (GL_LIGHTING);
3573 glColor3fv (dc->color);
3576 glCallList (dc->pizza_list_wire);
3578 glCallList (dc->helix_list_wire);
3580 mi->polygon_count += dc->polys[2];
3581 if (!wire) glEnable (GL_LIGHTING);
3586 glCallList (dc->pizza_list);
3588 glCallList (dc->helix_list);
3589 mi->polygon_count += dc->polys[0];
3593 else /* codeword_p */
3596 double max = 70; /* face front */
3598 get_position (dc->scene_rot, &x, &y, &z, !dc->button_down_p);
3599 glRotatef (max/2 - x*max, 0, 0, 1);
3600 glRotatef (max/2 - y*max, 0, 1, 0);
3601 /* glRotatef (max/2 - z*max, 1, 0, 0); */
3603 glRotatef (360 * dc->scene_spinnerx.position_eased, 0, 1, 0);
3604 glRotatef (360 * dc->scene_spinnery.position_eased, 0, 0, 1);
3607 glClearColor (dc->codeword_bg[0],
3610 dc->codeword_bg[3]);
3611 mi->polygon_count += draw_codeword_path (mi);
3617 if (dc->wire_overlay > 0)
3623 sprintf (s, "a/z, s/x; per = %0.2f pos = %0.2f",
3624 dc->persp_off, dc->pos_off);
3626 print_texture_label (dpy, dc->label_font, MI_WIDTH(mi), MI_HEIGHT(mi),
3631 if (mi->fps_p) do_fps (mi);
3634 glXSwapBuffers(dpy, window);
3637 XSCREENSAVER_MODULE_2 ("DNALogo", dnalogo, logo)