1 /* DNA Logo, Copyright (c) 2001-2015 Jamie Zawinski <jwz@jwz.org>
5 * Restaurant -- Bar -- Nightclub -- Cafe -- Est. 1985.
11 * http://www.dnalounge.com/
12 * http://www.dnapizza.com/
14 * Permission to use, copy, modify, distribute, and sell this software and its
15 * documentation for any purpose is hereby granted without fee, provided that
16 * the above copyright notice appear in all copies and that both that
17 * copyright notice and this permission notice appear in supporting
18 * documentation. No representations are made about the suitability of this
19 * software for any purpose. It is provided "as is" without express or
23 #define DEFAULTS __extension__ \
25 "*showFPS: False \n" \
26 "*wireframe: False \n" \
27 "*doGasket: True \n" \
29 "*doLadder: True \n" \
31 "*wallFacets: 360 \n" \
33 "*clockwise: False \n" \
35 "*turnSpacing: 2.2 \n" \
36 "*barSpacing: 0.24 \n" \
37 "*wallHeight: 0.45 \n" \
38 "*wallThickness: 0.12 \n" \
39 "*barThickness: 0.058 \n" \
40 "*wallTaper: 0.95 \n" \
41 "*gasketSize: 1.88 \n" \
42 "*gasketDepth: 0.15 \n" \
43 "*gasketThickness: 0.4 \n" \
44 "*frameSize: 1.20 \n" \
45 "*frameDepth: 0.01 \n" \
46 "*frameThickness: 0.03 \n" \
47 "*triangleSize: 0.045 \n" \
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)
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)))
76 #undef DXF_OUTPUT_HACK
78 #ifdef DXF_OUTPUT_HACK /* When this is defined, instead of rendering
79 to the screen, we write a DXF CAD file to stdout.
80 This is a kludge of shocking magnitude...
81 Maybe there's some other way to intercept all
82 glVertex3f calls than with a #define? */
83 # define unit_tube dxf_unit_tube
84 # define unit_cone dxf_unit_cone
85 # define tube_1 dxf_tube_1
86 # define tube dxf_tube
87 # define cone dxf_cone
88 #endif /* DXF_OUTPUT_HACK */
90 #include "xlockmore.h"
95 #include "gltrackball.h"
99 #ifdef USE_GL /* whole file */
102 # include "dnapizza.h"
108 HELIX_IN, HELIX, HELIX_OUT,
109 PIZZA_IN, PIZZA, PIZZA_OUT,
111 CODEWORD_IN, CODEWORD, CODEWORD_OUT, CODEWORD_BLANK
116 GLfloat position; /* 0.0 - 1.0 */
117 GLfloat speed; /* how far along the path (may be negative) */
118 GLfloat probability; /* relative likelyhood to start spinning */
122 GLXContext *glx_context;
124 GLuint helix_list, helix_list_wire, helix_list_facetted;
125 GLuint pizza_list, pizza_list_wire, pizza_list_facetted;
126 GLuint gasket_list, gasket_list_wire;
127 GLuint frame_list, frame_list_wire;
136 GLfloat turn_spacing;
139 GLfloat wall_thickness;
140 GLfloat bar_thickness;
144 GLfloat gasket_depth;
145 GLfloat gasket_thickness;
149 GLfloat frame_thickness;
150 GLfloat triangle_size;
152 int codeword_facets, codeword_disc_facets;
153 GLfloat codeword_spread, codeword_line_width, codeword_thickness;
154 GLfloat codeword_cap_size;
155 const char *codeword_text;
156 char *codeword_text_out;
157 int *codeword_text_points;
159 int codeword_path_npoints;
160 int codeword_nguides;
161 XYZ *codeword_guides;
162 GLfloat codeword_color[4], codeword_bg[4];
163 texture_font_data *font;
167 glyph_mode anim_state;
170 spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz;
171 spinner scene_spinnerx, scene_spinnery; /* for DNA */
172 rotator *scene_rot; /* for Codeword */
173 spinner helix_spinnerz;
174 spinner pizza_spinnery, pizza_spinnerz;
175 spinner frame_spinner;
177 trackball_state *trackball;
180 int wire_overlay; /* frame countdown */
182 } logo_configuration;
184 static logo_configuration *dcs = NULL;
186 static XrmOptionDescRec opts[] = {
187 { "-speed", ".speed", XrmoptionSepArg, 0 },
188 { "-mode", ".mode", XrmoptionSepArg, 0 },
189 { "-pizza", ".mode", XrmoptionNoArg, "pizza" },
190 { "-helix", ".mode", XrmoptionNoArg, "helix" },
191 { "-both", ".mode", XrmoptionNoArg, "both" },
192 { "-codeword", ".mode", XrmoptionNoArg, "codeword" },
193 { "-cw", ".mode", XrmoptionNoArg, "codeword" },
194 { "-text", ".text", XrmoptionSepArg, 0 },
197 ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
199 #define PROBABILITY_SCALE 600
202 #ifdef DXF_OUTPUT_HACK
204 # define glBegin dxf_glBegin
205 # define glVertex3f dxf_glVertex3f
206 # define glVertex3dv dxf_glVertex3dv
207 # define glEnd dxf_glEnd
208 # define glVertexPointer dxf_glVertexPointer
209 # define glDrawArrays dxf_glDrawArrays
211 static int dxf_type, dxf_point, dxf_point_total, dxf_layer, dxf_color;
212 static GLfloat dxf_quads[4*4];
215 dxf_glBegin (int type)
223 dxf_glVertex3f (GLfloat ox, GLfloat oy, GLfloat oz)
229 /* Transform the point into modelview space. */
230 glGetFloatv (GL_MODELVIEW_MATRIX, m);
231 x = ox * m[0] + oy * m[4] + oz * m[8] + m[12];
232 y = ox * m[1] + oy * m[5] + oz * m[9] + m[13];
233 z = ox * m[2] + oy * m[6] + oz * m[10] + m[14];
235 dxf_quads[dxf_point*3+0] = x;
236 dxf_quads[dxf_point*3+1] = y;
237 dxf_quads[dxf_point*3+2] = z;
243 if (dxf_point < 4) return;
245 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
246 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
247 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
248 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
250 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
251 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
252 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
254 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
255 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
256 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
258 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]);
259 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
260 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
265 if (dxf_point < 4) return;
267 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
268 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
269 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
270 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
272 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
273 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
274 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
276 fprintf (stdout, "12\n%.6f\n", dxf_quads[i+3]); /* funky quad strip */
277 fprintf (stdout, "22\n%.6f\n", dxf_quads[i+4]); /* vert order: 1243. */
278 fprintf (stdout, "32\n%.6f\n", dxf_quads[i+5]);
280 fprintf (stdout, "13\n%.6f\n", dxf_quads[i]);
281 fprintf (stdout, "23\n%.6f\n", dxf_quads[i+1]);
282 fprintf (stdout, "33\n%.6f\n", dxf_quads[i+2]);
285 dxf_quads[0] = dxf_quads[6]; /* copy point 3 to pos 1 */
286 dxf_quads[1] = dxf_quads[7];
287 dxf_quads[2] = dxf_quads[8];
288 dxf_quads[3] = dxf_quads[9]; /* copy point 4 to pos 2 */
289 dxf_quads[4] = dxf_quads[10];
290 dxf_quads[5] = dxf_quads[11];
291 dxf_point = 2; /* leave those two points in queue */
295 case GL_TRIANGLE_FAN:
296 if (dxf_point < 3) return;
298 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
299 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
300 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
301 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
303 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
304 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
305 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
307 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
308 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
309 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
312 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
313 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
314 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
317 if (dxf_type == GL_TRIANGLE_FAN)
319 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to point 2 */
320 dxf_quads[4] = dxf_quads[7];
321 dxf_quads[5] = dxf_quads[8];
322 dxf_point = 2; /* leave two points in queue */
326 case GL_TRIANGLE_STRIP:
327 if (dxf_point < 3) return;
329 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
331 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
332 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
333 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
335 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
336 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
337 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
339 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
340 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
341 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
344 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
345 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
346 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
348 dxf_quads[0] = dxf_quads[3]; /* copy point 2 to pos 1 */
349 dxf_quads[1] = dxf_quads[4];
350 dxf_quads[2] = dxf_quads[5];
351 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to pos 2 */
352 dxf_quads[4] = dxf_quads[7];
353 dxf_quads[5] = dxf_quads[8];
354 dxf_point = 2; /* leave those two points in queue */
361 if (dxf_point_total == 1)
368 if (dxf_point < 2) return;
370 fprintf (stdout, "0\nLINE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
372 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
373 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
374 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
376 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
377 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
378 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
381 if (dxf_type != GL_LINES)
383 dxf_quads[0] = dxf_quads[3];
384 dxf_quads[1] = dxf_quads[4];
385 dxf_quads[2] = dxf_quads[5];
398 dxf_glVertex3dv (const GLdouble *v)
400 glVertex3f (v[0], v[1], v[2]);
407 if (dxf_type == GL_LINE_LOOP) /* close loop */
408 glVertex3f (dxf_quads[6], dxf_quads[7], dxf_quads[8]);
418 fprintf (stdout, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n");
419 fprintf (stdout, "0\nSECTION\n2\nENTITIES\n");
425 fprintf (stdout, "0\nENDSEC\n0\nEOF\n");
430 static const GLvoid *dxf_vp;
431 static GLsizei dxf_vp_size;
432 static GLsizei dxf_vp_stride;
435 dxf_glVertexPointer (GLint size, GLenum type, GLsizei stride,
436 const GLvoid *pointer)
438 if (type != GL_FLOAT) abort();
439 if (stride <= 0) abort();
442 dxf_vp_stride = stride;
446 dxf_glDrawArrays (GLenum mode, GLint first, GLsizei count)
449 unsigned char *a = (unsigned char *) dxf_vp;
451 for (i = first; i < first+count; i++)
453 GLfloat *fa = (GLfloat *) a;
454 dxf_glVertex3f (fa[0], fa[1], fa[2]);
461 # define XYZ tube_XYZ /* avoid conflict with normals.h */
462 # include "tube.c" /* Yes, I really am including a C file. */
464 # define XYZ sphere_XYZ
465 # define unit_sphere unit_sphere_dxf
466 # define unit_dome unit_dome_dxf
470 #endif /* DXF_OUTPUT_HACK */
474 /* Calculate the angle (in radians) between two vectors.
477 vector_angle (double ax, double ay, double az,
478 double bx, double by, double bz)
480 double La = sqrt (ax*ax + ay*ay + az*az);
481 double Lb = sqrt (bx*bx + by*by + bz*bz);
484 if (La == 0 || Lb == 0) return 0;
485 if (ax == bx && ay == by && az == bz) return 0;
487 /* dot product of two vectors is defined as:
488 La * Lb * cos(angle between vectors)
489 and is also defined as:
490 ax*bx + ay*by + az*bz
492 La * Lb * cos(angle) = ax*bx + ay*by + az*bz
493 cos(angle) = (ax*bx + ay*by + az*bz) / (La * Lb)
494 angle = acos ((ax*bx + ay*by + az*bz) / (La * Lb));
496 cc = (ax*bx + ay*by + az*bz) / (La * Lb);
497 if (cc > 1) cc = 1; /* avoid fp rounding error (1.000001 => sqrt error) */
506 GLfloat d = sqrt (p->x*p->x + p->y*p->y + p->z*p->z);
515 p->x = p->y = p->z = 0;
521 dot (const XYZ u, const XYZ v)
523 return (u.x * v.x) + (u.y * v.y) + (u.z * v.z);
531 make_helix (logo_configuration *dc, int facetted, int wire)
534 int wall_facets = dc->wall_facets / (facetted ? 10 : 1);
536 GLfloat max_th = M_PI * 2 * dc->turns;
537 GLfloat th_inc = M_PI * 2 / wall_facets;
539 GLfloat x1=0, y1=0, x2=0, y2=0;
540 GLfloat x1b=0, y1b=0, x2b=0, y2b=0;
543 GLfloat h1off=0, h2off=0;
544 GLfloat z_inc = dc->turn_spacing / wall_facets;
549 x1b = 1 - dc->wall_thickness;
552 z1 = -(dc->turn_spacing * dc->turns / 2);
554 h1 = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2);
555 h1off = (dc->wall_taper > 0 ? -dc->wall_height / 2 : 0);
558 z1 = -z1, z_inc = -z_inc, h1off = -h1off;
567 nx = cos (th + M_PI/2);
568 ny = sin (th + M_PI/2);
569 glNormal3f(nx, ny, 0);
570 glVertex3f( x1, y1, z1 - h1 + h1off);
571 glVertex3f( x1, y1, z1 + h1 + h1off);
572 glVertex3f(x1b, y1b, z1 + h1 + h1off);
573 glVertex3f(x1b, y1b, z1 - h1 + h1off);
578 while (th + th_inc <= max_th)
585 x2b = x2 * (1 - dc->wall_thickness);
586 y2b = y2 * (1 - dc->wall_thickness);
591 if (dc->wall_taper > 0)
594 if (th < dc->wall_taper)
596 h2 = dc->wall_height/2 * cos (M_PI / 2
597 * (1 - (th / dc->wall_taper)));
599 h2off = h2 - dc->wall_height/2;
601 h2off = dc->wall_height/2 - h2;
603 else if (th >= max_th - dc->wall_taper)
605 if (th + th_inc > max_th) /* edge case: always come to a point */
608 h2 = dc->wall_height/2 * cos (M_PI / 2
609 * (1 - ((max_th - th)
612 h2off = dc->wall_height/2 - h2;
614 h2off = h2 - dc->wall_height/2;
621 glBegin(wire ? GL_LINES : GL_QUADS);
622 glNormal3f(x1, y1, 0);
623 glVertex3f(x1, y1, z1 - h1 + h1off);
624 glVertex3f(x1, y1, z1 + h1 + h1off);
625 glNormal3f(x2, y2, 0);
626 glVertex3f(x2, y2, z2 + h2 + h2off);
627 glVertex3f(x2, y2, z2 - h2 + h2off);
634 glBegin(wire ? GL_LINES : GL_QUADS);
635 glNormal3f(-x1b, -y1b, 0);
636 glVertex3f( x1b, y1b, z1 - h1 + h1off);
637 glVertex3f( x1b, y1b, z1 + h1 + h1off);
638 glNormal3f(-x2b, -y2b, 0);
639 glVertex3f( x2b, y2b, z2 + h2 + h2off);
640 glVertex3f( x2b, y2b, z2 - h2 + h2off);
647 /* glNormal3f(0, 0, 1);*/
648 do_normal (x2, y2, z2 + h2 + h2off,
649 x2b, y2b, z2 + h2 + h2off,
650 x1b, y1b, z1 + h1 + h1off);
651 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
652 glVertex3f( x2, y2, z2 + h2 + h2off);
653 glVertex3f( x2b, y2b, z2 + h2 + h2off);
654 glVertex3f( x1b, y1b, z1 + h1 + h1off);
655 glVertex3f( x1, y1, z1 + h1 + h1off);
662 do_normal ( x1, y1, z1 - h1 + h1off,
663 x1b, y1b, z1 - h1 + h1off,
664 x2b, y2b, z2 - h2 + h2off);
665 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
666 glNormal3f(0, 0, -1);
667 glVertex3f( x1, y1, z1 - h1 + h1off);
668 glVertex3f( x1b, y1b, z1 - h1 + h1off);
669 glVertex3f( x2b, y2b, z2 - h2 + h2off);
670 glVertex3f( x2, y2, z2 - h2 + h2off);
690 nx = cos (th + M_PI/2);
691 ny = sin (th + M_PI/2);
692 glNormal3f(nx, ny, 0);
693 glVertex3f(x2, y2, z1 - h2 + h2off);
694 glVertex3f(x2, y2, z1 + h2 + h2off);
695 glVertex3f(x2b, y2b, z1 + h2 + h2off);
696 glVertex3f(x2b, y2b, z1 - h2 + h2off);
705 make_ladder (logo_configuration *dc, int facetted, int wire)
709 GLfloat max_th = dc->turns * M_PI * 2;
710 GLfloat max_z = dc->turns * dc->turn_spacing;
711 GLfloat z_inc = dc->bar_spacing;
712 GLfloat th_inc = M_PI * 2 * (dc->bar_spacing / dc->turn_spacing);
715 /* skip forward to center the bars in the helix... */
717 GLfloat usable_th = max_th - dc->wall_taper;
718 GLfloat usable_z = max_z / (max_th / usable_th);
719 int nbars = usable_z / dc->bar_spacing;
720 GLfloat used_z, pad_z, pad_ratio;
722 if (! (nbars & 1)) nbars--; /* always an odd number of bars */
724 used_z = (nbars - 1) * dc->bar_spacing;
725 pad_z = max_z - used_z;
726 pad_ratio = pad_z / max_z;
728 th = (max_th * pad_ratio/2);
729 z = -(max_z / 2) + (max_z * pad_ratio/2);
732 z = -z, z_inc = -z_inc;
735 for (i = 0; i < nbars; i++)
737 int facets = dc->bar_facets / (facetted ? 14 : 1);
738 if (facets <= 3) facets = 3;
739 x = cos (th) * (1 - dc->wall_thickness);
740 y = sin (th) * (1 - dc->wall_thickness);
741 polys += tube ( x, y, z,
743 dc->bar_thickness, 0, facets,
758 make_gasket (logo_configuration *dc, int wire)
766 GLfloat d2r = M_PI / 180;
768 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 2;
770 GLfloat *pointsx0, *pointsy0, *pointsx1, *pointsy1, *normals;
772 GLfloat r0 = 0.750; /* 395 */
773 GLfloat r1a = 0.825; /* bottom of wall below upper left hole */
774 GLfloat r1b = 0.867; /* center of upper left hole */
775 GLfloat r1c = 0.909; /* top of wall above hole */
776 GLfloat r1 = 0.916; /* 471 */
777 GLfloat r2 = 0.963; /* 490 */
778 GLfloat r3 = 0.960; /* 499 */
779 GLfloat r4 = 1.000; /* 507 */
780 GLfloat r5 = 1.080; /* 553 */
782 GLfloat ctrl_r[100], ctrl_th[100];
786 # ifdef DXF_OUTPUT_HACK
787 if (! wire) res *= 8;
790 # define POINT(r,th) \
791 ctrl_r [nctrls] = r, \
792 ctrl_th[nctrls] = (th * d2r), \
795 POINT (0.829, 0); /* top indentation, right half */
803 POINT (r4, 4.0); /* moving clockwise... */
824 POINT (r4, 316.8); /* upper left indentation */
825 POINT (0.990, 316.87);
826 POINT (0.880, 317.21);
827 POINT (0.872, 317.45);
828 POINT (0.869, 317.80);
829 POINT (0.867, 318.10);
831 POINT (0.867, 318.85);
832 POINT (0.869, 319.15);
833 POINT (0.872, 319.50);
834 POINT (0.880, 319.74);
835 POINT (0.990, 320.08);
840 POINT (r1a, 338.0); /* cut-out disc */
846 POINT (0.872, 356.05); /* top indentation, left half */
847 POINT (0.862, 356.19);
848 POINT (0.851, 356.70);
849 POINT (0.841, 357.35);
850 POINT (0.835, 358.19);
851 POINT (0.831, 359.15);
855 points_size = res + (nctrls * 2);
856 pointsx0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
857 pointsy0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
858 pointsx1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
859 pointsy1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
860 normals = (GLfloat *) malloc (points_size * sizeof(GLfloat) * 2);
863 for (i = 1; i < nctrls; i++)
865 GLfloat from_r = ctrl_r [i-1];
866 GLfloat from_th = ctrl_th[i-1];
867 GLfloat to_r = ctrl_r [i];
868 GLfloat to_th = ctrl_th[i];
870 GLfloat step = 2*M_PI / res;
871 int nsteps = 1 + ((to_th - from_th) / step);
874 for (j = 0; j < nsteps + (i == nctrls-1); j++)
876 GLfloat r = from_r + (j * (to_r - from_r) / nsteps);
877 GLfloat th = from_th + (j * (to_th - from_th) / nsteps);
879 GLfloat cth = cos(th) * dc->gasket_size;
880 GLfloat sth = sin(th) * dc->gasket_size;
882 pointsx0[npoints] = r0 * cth; /* inner ring */
883 pointsy0[npoints] = r0 * sth;
884 pointsx1[npoints] = r * cth; /* outer ring */
885 pointsy1[npoints] = r * sth;
888 if (npoints >= points_size) abort();
892 /* normals for the outer ring */
893 for (i = 1; i < npoints; i++)
904 n = calc_normal (a, b, c);
905 normals[(i-1)*2 ] = n.x;
906 normals[(i-1)*2+1] = n.y;
909 glRotatef(-90, 0, 1, 0);
910 glRotatef(180, 0, 0, 1);
915 for (z = -thick2; z <= thick2; z += thick2*2)
919 glBegin (GL_LINE_LOOP);
920 for (i = 0; i < npoints; i++)
921 glVertex3f (pointsx0[i], pointsy0[i], z);
926 glBegin (GL_LINE_LOOP);
927 for (i = 0; i < npoints; i++)
928 glVertex3f (pointsx1[i], pointsy1[i], z);
932 for (i = 1; i < npoints; i++)
934 glBegin (GL_LINE_STRIP);
935 glVertex3f (pointsx0[i-1], pointsy0[i-1], z);
936 glVertex3f (pointsx0[i ], pointsy0[i ], z);
937 glVertex3f (pointsx1[i ], pointsy1[i ], z);
938 glVertex3f (pointsx1[i-1], pointsy1[i-1], z);
946 for (i = 0; i < npoints; i++)
949 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
950 glVertex3f (pointsx0[i], pointsy0[i], thick2);
952 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
953 glVertex3f (pointsx1[i], pointsy1[i], thick2);
963 glNormal3f(0, 0, -1);
964 glBegin (GL_QUAD_STRIP);
965 for (i = 0; i < npoints; i++)
967 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
968 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
976 glBegin (GL_QUAD_STRIP);
977 for (i = 0; i < npoints; i++)
979 glVertex3f (pointsx0[i], pointsy0[i], thick2);
980 glVertex3f (pointsx1[i], pointsy1[i], thick2);
987 glBegin (GL_QUAD_STRIP);
988 for (i = 0; i < npoints; i++)
990 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
991 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
992 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
1001 for (i = 0; i < npoints-1; i++)
1003 int ia = (i == 0 ? npoints-2 : i-1);
1004 int iz = (i == npoints-2 ? 0 : i+1);
1005 GLfloat x = pointsx1[i];
1006 GLfloat y = pointsy1[i];
1007 GLfloat xz = pointsx1[iz];
1008 GLfloat yz = pointsy1[iz];
1010 GLfloat nxa = normals[ia*2]; /* normal of [i-1 - i] face */
1011 GLfloat nya = normals[ia*2+1];
1012 GLfloat nx = normals[i*2]; /* normal of [i - i+1] face */
1013 GLfloat ny = normals[i*2+1];
1014 GLfloat nxz = normals[iz*2]; /* normal of [i+1 - i+2] face */
1015 GLfloat nyz = normals[iz*2+1];
1017 GLfloat anglea = vector_angle (nx, ny, 0, nxa, nya, 0);
1018 GLfloat anglez = vector_angle (nx, ny, 0, nxz, nyz, 0);
1019 GLfloat pointy = 0.6;
1021 if (anglea > pointy)
1023 glNormal3f (nx, ny, 0);
1024 glVertex3f (x, y, thick2);
1025 glVertex3f (x, y, -thick2);
1029 glNormal3f ((nxa + nx) / 2, (nya + ny) / 2, 0);
1030 glVertex3f (x, y, thick2);
1031 glVertex3f (x, y, -thick2);
1034 if (anglez > pointy)
1036 glNormal3f (nx, ny, 0);
1037 glVertex3f (xz, yz, -thick2);
1038 glVertex3f (xz, yz, thick2);
1042 glNormal3f ((nx + nxz) / 2, (ny + nyz) / 2, 0);
1043 glVertex3f (xz, yz, -thick2);
1044 glVertex3f (xz, yz, thick2);
1052 /* Fill in the upper left hole...
1059 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
1060 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
1062 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
1063 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
1067 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
1068 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
1070 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
1071 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
1076 glNormal3f (0, 0, -1);
1078 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1079 glVertex3f (pointsx0[0], pointsy0[0], -thick2);
1080 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1081 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1082 glVertex3f (pointsx0[2], pointsy0[2], -thick2);
1087 glNormal3f (0, 0, 1);
1088 glFrontFace(GL_CCW);
1089 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1090 glVertex3f (pointsx0[0], pointsy0[0], thick2);
1091 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1092 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1093 glVertex3f (pointsx0[2], pointsy0[2], thick2);
1100 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1101 glNormal3f (pointsx0[1], pointsy0[1], 0);
1102 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1103 glNormal3f (pointsx0[3], pointsy0[3], 0);
1104 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1105 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1106 glNormal3f (pointsx0[1], pointsy0[1], 0);
1107 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1112 /* Now make a donut.
1115 int nsteps = (wire ? 12 : 64);
1118 GLfloat th, cth, sth;
1122 th = ((339.0 + 343.0) / 2) * d2r;
1124 glTranslatef (r1b * cos(th) * dc->gasket_size,
1125 r1b * sin(th) * dc->gasket_size,
1129 for (i = 0; i < nsteps; i++)
1131 th = 2 * M_PI * i / nsteps;
1132 cth = cos (th) * dc->gasket_size;
1133 sth = sin (th) * dc->gasket_size;
1134 pointsx0[npoints] = r0 * cth;
1135 pointsy0[npoints] = r0 * sth;
1136 pointsx1[npoints] = r1 * cth;
1137 pointsy1[npoints] = r1 * sth;
1142 pointsx0[npoints] = pointsx0[0];
1143 pointsy0[npoints] = pointsy0[0];
1144 pointsx1[npoints] = pointsx1[0];
1145 pointsy1[npoints] = pointsy1[0];
1150 glBegin (GL_LINE_LOOP);
1151 for (i = 0; i < npoints; i++)
1152 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1155 glBegin (GL_LINE_LOOP);
1156 for (i = 0; i < npoints; i++)
1157 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1161 glBegin (GL_LINE_LOOP);
1162 for (i = 0; i < npoints; i++)
1163 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1166 glBegin (GL_LINE_LOOP);
1167 for (i = 0; i < npoints; i++)
1168 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1177 glNormal3f(0, 0, -1);
1178 glBegin (GL_QUAD_STRIP);
1179 for (i = 0; i < npoints; i++)
1181 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1182 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1188 glFrontFace(GL_CCW);
1189 glNormal3f(0, 0, 1);
1190 glBegin (GL_QUAD_STRIP);
1191 for (i = 0; i < npoints; i++)
1193 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1194 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1202 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1203 for (i = 0; i < npoints; i++)
1205 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
1206 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
1207 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
1217 /* Attach the bottom-right dingus...
1224 glRotatef (49.5, 0, 0, 1);
1225 glScalef (dc->gasket_size, dc->gasket_size, 1);
1226 glTranslatef (0, (r0+r1)/2, 0);
1231 glFrontFace(GL_CCW);
1232 glBegin (wire ? GL_LINE_STRIP : GL_QUADS);
1233 glNormal3f (0, 0, -1);
1234 glVertex3f (-w/2, -h/2, -thick2); glVertex3f (-w/2, h/2, -thick2);
1235 glVertex3f ( w/2, h/2, -thick2); glVertex3f ( w/2, -h/2, -thick2);
1236 glNormal3f (1, 0, 0);
1237 glVertex3f ( w/2, -h/2, -thick2); glVertex3f ( w/2, h/2, -thick2);
1238 glVertex3f ( w/2, h/2, thick2); glVertex3f ( w/2, -h/2, thick2);
1239 glNormal3f (0, 0, 1);
1240 glVertex3f ( w/2, -h/2, thick2); glVertex3f ( w/2, h/2, thick2);
1241 glVertex3f (-w/2, h/2, thick2); glVertex3f (-w/2, -h/2, thick2);
1242 glNormal3f (-1, 0, 0);
1243 glVertex3f (-w/2, -h/2, thick2); glVertex3f (-w/2, h/2, thick2);
1244 glVertex3f (-w/2, h/2, -thick2); glVertex3f (-w/2, -h/2, -thick2);
1250 for (th = (wire ? 0 : -0.1);
1252 th += (M_PI / (wire ? 5 : 32)))
1254 pointsx0[npoints] = w/2 * cos(th);
1255 pointsy0[npoints] = w/2 * sin(th);
1260 /* front inside curve */
1261 glNormal3f (0, 0, -1);
1263 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1264 if (! wire) glVertex3f (0, h/2, -thick2);
1265 for (i = 0; i < npoints; i++)
1266 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1270 /* front outside curve */
1271 glFrontFace(GL_CCW);
1272 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1273 if (! wire) glVertex3f (0, -h/2, -thick2);
1274 for (i = 0; i < npoints; i++)
1275 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1279 /* back inside curve */
1280 glNormal3f (0, 0, 1);
1281 glFrontFace(GL_CCW);
1282 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1283 if (! wire) glVertex3f (0, h/2, thick2);
1284 for (i = 0; i < npoints; i++)
1285 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1289 /* back outside curve */
1291 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1292 if (! wire) glVertex3f (0, -h/2, thick2);
1293 for (i = 0; i < npoints; i++)
1294 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1299 glFrontFace(GL_CCW);
1300 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1301 for (i = 0; i < npoints; i++)
1303 glNormal3f (pointsx0[i], pointsy0[i], 0);
1304 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1305 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1312 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1313 for (i = 0; i < npoints; i++)
1315 glNormal3f (pointsx0[i], -pointsy0[i], 0);
1316 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1317 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1334 make_frame (logo_configuration *dc, int wire)
1338 GLfloat x[20], y[20];
1339 GLfloat corner_cut = 0.5;
1342 glRotatef (90, 0, 1, 0);
1343 glScalef (4 * dc->frame_size,
1345 4 * dc->frame_size);
1347 x[0] = -dc->frame_thickness;
1348 x[1] = -dc->frame_thickness * corner_cut;
1350 x[3] = 0.5 - dc->triangle_size;
1352 x[5] = 0.5 + dc->triangle_size;
1354 x[7] = 1 + dc->frame_thickness * corner_cut;
1355 x[8] = 1 + dc->frame_thickness;
1357 y[0] = -dc->frame_thickness;
1358 y[1] = -dc->frame_thickness * corner_cut;
1360 y[3] = dc->triangle_size;
1364 glTranslatef (-0.5, -0.5, dc->frame_depth / 4);
1366 for (j = 0; j <= 1; j++)
1368 if (j) glTranslatef (0, 0, -dc->frame_depth / 2);
1369 glFrontFace (j ? GL_CCW : GL_CW);
1370 for (i = 0; i < 4; i++)
1372 glNormal3f (0, 0, (j ? -1 : 1));
1373 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1374 glVertex3f (x[0], y[1], 0); glVertex3f (x[0], y[2], 0);
1375 glVertex3f (x[1], y[0], 0); glVertex3f (x[1], y[2], 0);
1376 glVertex3f (x[3], y[0], 0); glVertex3f (x[3], y[2], 0);
1377 glVertex3f (x[4], y[0], 0); glVertex3f (x[4], y[3], 0);
1378 glVertex3f (x[5], y[0], 0); glVertex3f (x[5], y[2], 0);
1379 glVertex3f (x[7], y[0], 0); glVertex3f (x[7], y[2], 0);
1380 glVertex3f (x[8], y[1], 0); glVertex3f (x[8], y[2], 0);
1383 glTranslatef (0.5, 0.5, 0);
1384 glRotatef (90, 0, 0, 1);
1385 glTranslatef (-0.5, -0.5, 0);
1391 glFrontFace (GL_CCW);
1392 for (i = 0; i < 4; i++)
1394 glNormal3f (0, 1, 0);
1395 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1396 glVertex3f (x[2], y[2], 0); glVertex3f (x[2], y[2], dc->frame_depth/2);
1397 glVertex3f (x[3], y[2], 0); glVertex3f (x[3], y[2], dc->frame_depth/2);
1398 glVertex3f (x[4], y[3], 0); glVertex3f (x[4], y[3], dc->frame_depth/2);
1399 glVertex3f (x[5], y[2], 0); glVertex3f (x[5], y[2], dc->frame_depth/2);
1400 glVertex3f (x[6], y[2], 0); glVertex3f (x[6], y[2], dc->frame_depth/2);
1404 glNormal3f (0, -1, 0);
1405 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1406 glVertex3f (x[7], y[0], 0);
1407 glVertex3f (x[7], y[0], dc->frame_depth/2);
1408 glVertex3f (x[1], y[0], dc->frame_depth/2);
1409 glVertex3f (x[1], y[0], 0);
1413 glNormal3f (1, -1, 0);
1414 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1415 glVertex3f (x[8], y[1], 0);
1416 glVertex3f (x[8], y[1], dc->frame_depth/2);
1417 glVertex3f (x[7], y[0], dc->frame_depth/2);
1418 glVertex3f (x[7], y[0], 0);
1424 glNormal3f (0, 1, 0);
1425 for (j = 0; j <= 1; j++)
1427 glBegin (GL_LINE_STRIP);
1428 glVertex3f (x[2], y[2], j*dc->frame_depth/2);
1429 glVertex3f (x[3], y[2], j*dc->frame_depth/2);
1430 glVertex3f (x[4], y[3], j*dc->frame_depth/2);
1431 glVertex3f (x[5], y[2], j*dc->frame_depth/2);
1432 glVertex3f (x[6], y[2], j*dc->frame_depth/2);
1438 glTranslatef (0.5, 0.5, 0);
1439 glRotatef (90, 0, 0, 1);
1440 glTranslatef (-0.5, -0.5, 0);
1460 tess_error_cb (GLenum errorCode)
1462 fprintf (stderr, "%s: tesselation error: %s\n",
1463 progname, gluErrorString(errorCode));
1468 tess_combine_cb (GLdouble coords[3], GLdouble *d[4], GLfloat w[4],
1469 GLdouble **data_out)
1471 GLdouble *new = (GLdouble *) malloc (3 * sizeof(*new));
1481 tess_vertex_cb (void *vertex_data, void *closure)
1483 tess_out *to = (tess_out *) closure;
1484 GLdouble *v = (GLdouble *) vertex_data;
1485 to->points[to->i++] = v[0];
1486 to->points[to->i++] = v[1];
1487 to->points[to->i++] = v[2];
1492 tess_begin_cb (GLenum which)
1503 #endif /* HAVE_TESS */
1507 make_pizza (logo_configuration *dc, int facetted, int wire)
1510 int topfaces = (facetted ? 48 : 120);
1511 int discfaces = (facetted ? 12 : 120);
1512 int npoints = topfaces * 2 + 100;
1513 GLdouble *points = (GLdouble *) calloc (npoints * 3, sizeof(GLdouble));
1515 GLdouble *holes = (GLdouble *) calloc (topfaces*nholes*3, sizeof(GLdouble));
1517 GLfloat step = M_PI * 2 / 6 / topfaces;
1518 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 4;
1519 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];
1577 s = 0.798; /* radius of end of slice, before crust gap */
1578 for (i = 0; i < topfaces; i++)
1580 points[j++] = cos(th) * s;
1581 points[j++] = sin(th) * s;
1598 for (i = 0; i < countof(edge)/2; i++)
1600 points[j++] = edge[i*2+1];
1601 points[j++] = edge[i*2];
1608 /* Draw the rim of the slice */
1609 glBegin (wire ? GL_LINES : GL_QUADS);
1612 for (i = (wire ? 0 : 1); i < endpoints; i++)
1614 GLdouble *p = points + (i*3);
1616 do_normal (p[0], p[1], -thick2,
1621 glVertex3f (x, y, -thick2);
1622 glVertex3f (x, y, thick2);
1624 glVertex3f (p[0], p[1], thick2);
1625 glVertex3f (p[0], p[1], -thick2);
1631 do_normal (points[0], points[1], -thick2,
1632 points[0], points[1], thick2,
1634 glVertex3f (x, y, -thick2);
1635 glVertex3f (x, y, thick2);
1636 glVertex3f (points[0], points[1], thick2);
1637 glVertex3f (points[0], points[1], -thick2);
1644 /* Outline of slice */
1645 glBegin (GL_LINE_LOOP);
1646 for (i = 0; i < endpoints; i++)
1647 glVertex3f (points[i*3], points[i*3+1], -thick2);
1649 glBegin (GL_LINE_LOOP);
1650 for (i = 0; i < endpoints; i++)
1651 glVertex3f (points[i*3], points[i*3+1], thick2);
1654 # endif /* HAVE_TESS */
1656 /* Compute the holes */
1657 step = M_PI * 2 / discfaces;
1658 for (k = 0; k < nholes; k++)
1660 GLdouble *p = holes + (discfaces * 3 * k);
1664 case 0: x = 0.34; y = 0.17; s = 0.05; break;
1665 case 1: x = 0.54; y = 0.17; s = 0.06; break;
1666 case 2: x = 0.55; y = 0.36; s = 0.06; break;
1667 default: abort(); break;
1669 for (i = 0; i < discfaces; i++)
1671 p[j++] = x + cos(M_PI*2 - th) * s;
1672 p[j++] = y + sin(M_PI*2 - th) * s;
1679 /* Draw the inside rim of the holes */
1680 for (k = 0; k < nholes; k++)
1682 GLdouble *p = holes + (discfaces * 3 * k);
1684 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1685 for (i = 0; i < discfaces; i++)
1687 GLdouble *p2 = p + (i*3);
1689 do_normal (p2[0], p2[1], -thick2,
1690 p2[0], p2[1], thick2,
1691 p2[-3], p2[-2], thick2);
1692 glVertex3f (p2[0], p2[1], -thick2);
1693 glVertex3f (p2[0], p2[1], thick2);
1696 glVertex3f (p[0], p[1], -thick2);
1697 glVertex3f (p[0], p[1], thick2);
1703 /* Outline of holes */
1704 glBegin (GL_LINE_LOOP);
1705 for (i = 0; i < discfaces; i++)
1706 glVertex3f (p[i*3], p[i*3+1], -thick2);
1708 glBegin (GL_LINE_LOOP);
1709 for (i = 0; i < discfaces; i++)
1710 glVertex3f (p[i*3], p[i*3+1], thick2);
1713 # endif /* !HAVE_TESS */
1717 glTranslatef (0, 0, -thick2);
1718 for (y = 0; y <= 1; y++)
1720 if (y) glTranslatef (0, 0, thick2*2);
1722 /* A non-convex polygon */
1723 gluTessBeginPolygon (tess, to);
1725 glNormal3f (0, 0, (y > 0 ? 1 : -1));
1726 gluTessNormal (tess, 0, 0, (y > 0 ? 1 : -1));
1727 glFrontFace (GL_CCW);
1729 /* Tess the wedge */
1730 gluTessBeginContour (tess);
1731 for (i = 0; i < endpoints; i++)
1733 GLdouble *p = points + (i*3);
1734 gluTessVertex (tess, p, p);
1737 gluTessVertex (tess, points, points);
1738 gluTessEndContour (tess);
1740 /* Tess the holes */
1741 for (k = 0; k < nholes; k++)
1743 GLdouble *p = holes + (discfaces * 3 * k);
1744 gluTessBeginContour (tess);
1745 for (i = 0; i < discfaces; i++)
1747 GLdouble *p2 = p + (i*3);
1748 gluTessVertex (tess, p2, p2);
1751 gluTessEndContour (tess);
1754 gluTessEndPolygon (tess);
1757 glTranslatef (0, 0, -thick2);
1759 # else /* !HAVE_TESS */
1762 glDisableClientState (GL_COLOR_ARRAY);
1763 glDisableClientState (GL_NORMAL_ARRAY);
1764 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1765 glEnableClientState (GL_VERTEX_ARRAY);
1766 glVertexPointer (3, GL_FLOAT, 0, dnapizza_triangles);
1768 glTranslatef(0, 0, thick2);
1769 glNormal3f (0, 0, 1);
1770 glFrontFace (GL_CW);
1771 glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
1773 glTranslatef(0, 0, -thick2*2);
1774 glNormal3f (0, 0, -1);
1775 glFrontFace (GL_CCW);
1776 glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
1778 glTranslatef(0, 0, thick2);
1780 # endif /* !HAVE_TESS */
1783 /* Compute the crust */
1785 s = 0.861; /* radius of inside of crust */
1786 step = M_PI * 2 / 6 / topfaces;
1789 for (i = 0; i < topfaces; i++)
1791 points[j++] = cos(th) * s;
1792 points[j++] = sin(th) * s;
1798 for (i = 0; i < topfaces; i++)
1800 points[j++] = cos(th) * s;
1801 points[j++] = sin(th) * s;
1806 /* Draw the rim of the crust */
1807 glFrontFace (GL_CCW);
1808 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1809 for (i = 0; i < topfaces * 2; i++)
1811 GLdouble *p = points + (i*3);
1812 if (i == 0 || i == (topfaces*2)-1)
1813 glNormal3f (0, -1, 0);
1814 else if (i == topfaces-1 || i == topfaces)
1815 glNormal3f (0, 1, 0);
1817 do_normal (p[-3], p[-2], thick2,
1819 p[0], p[1], -thick2);
1820 glVertex3f (p[0], p[1], -thick2);
1821 glVertex3f (p[0], p[1], thick2);
1824 glVertex3f (points[0], points[1], -thick2);
1825 glVertex3f (points[0], points[1], thick2);
1831 glBegin (GL_LINE_STRIP);
1832 for (i = 0; i < topfaces * 2; i++)
1834 GLdouble *p = points + (i*3);
1835 glVertex3f (p[0], p[1], -thick2);
1838 glVertex3f (points[0], points[1], -thick2);
1841 glBegin (GL_LINE_STRIP);
1842 for (i = 0; i < topfaces * 2; i++)
1844 GLdouble *p = points + (i*3);
1845 glVertex3f (p[0], p[1], thick2);
1848 glVertex3f (points[0], points[1], thick2);
1852 /* Draw the top of the crust */
1855 glFrontFace (GL_CW);
1856 glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP);
1857 glNormal3f (0, 0, -1);
1859 for (i = 0; i < topfaces; i++)
1861 int ii = topfaces + (topfaces - i - 1);
1862 GLdouble *p1 = points + (i*3);
1863 GLdouble *p2 = points + (ii*3);
1864 glVertex3f (p1[0], p1[1], -thick2);
1865 glVertex3f (p2[0], p2[1], -thick2);
1871 /* Draw the bottom of the crust */
1872 glFrontFace (GL_CCW);
1873 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1874 glNormal3f (0, 0, 1);
1875 for (i = 0; i < topfaces; i++)
1877 int ii = topfaces + (topfaces - i - 1);
1878 GLdouble *p1 = points + (i*3);
1879 GLdouble *p2 = points + (ii*3);
1880 glVertex3f (p1[0], p1[1], thick2);
1881 glVertex3f (p2[0], p2[1], thick2);
1889 gluDeleteTess (tess);
1891 # endif /* HAVE_TESS */
1902 /* Upcase string, convert Unicrud to ASCII, remove any non-letters.
1905 codeword_simplify_text (const char *s0)
1907 char *s1 = utf8_to_latin1 ((s0 ? s0 : ""), True);
1909 char *s2 = (char *) malloc (L + 10);
1912 for (i = 0; i < L; i++)
1915 if (c >= 'a' && c <= 'z')
1917 if (c >= 'A' && c <= 'Z')
1922 strcpy (s2, "CODEWORD");
1928 make_codeword_path (ModeInfo *mi)
1930 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
1931 int letters = strlen (dc->codeword_text);
1933 GLfloat rtick = dc->codeword_spread;
1934 GLfloat iradius = rtick * dc->codeword_cap_size;
1940 GLfloat inner_circum = M_PI * 2 * (iradius + rtick * 2);
1941 GLfloat outer_circum = M_PI * 2 * (iradius + rtick * (letters + 1));
1942 GLfloat facet_length = inner_circum / (26 * dc->codeword_facets);
1943 int outer_facets = ceil (outer_circum / facet_length);
1945 int *histo = (int *) calloc (letters * 26, sizeof(*histo));
1946 XYZ *points = (XYZ *) calloc (letters * outer_facets, sizeof (*points));
1949 for (letter = -1; letter < letters; letter++)
1951 if (letter == -1) /* Inner starting point */
1953 points[npoints].x = iradius;
1954 points[npoints].y = 0;
1958 else /* Add arc for this letter */
1960 int direction = (letter & 1 ? -1 : 1);
1961 int v = (dc->codeword_text[letter] - 'A' + 1);
1962 int dial1 = dial + v * direction;
1965 GLfloat th0 = M_PI * 2 / 26 * dial;
1966 GLfloat th1 = M_PI * 2 / 26 * dial1;
1967 GLfloat r = iradius + rtick * (letter + 2);
1968 GLfloat circum = M_PI * 2 * r;
1969 GLfloat arc_length = circum * v / 26;
1970 int arc_facets = ceil (fabs (arc_length / facet_length));
1971 GLfloat facet_th = (th1 - th0) / arc_facets;
1973 if (arc_facets > outer_facets) abort();
1975 /* Let's put some intermediate facets on the crossbars too,
1976 so that the animation doesn't speed up on those. */
1979 for (rr = last_r + facet_length;
1980 rr <= r - facet_length;
1983 points[npoints].x = rr * cos (th0);
1984 points[npoints].y = rr * sin (th0);
1993 ? th <= th1 + facet_th
1994 : th >= th1 + facet_th);
1998 if (th0 < th1 && th > th1)
2000 if (th0 > th1 && th < th1)
2002 points[npoints].x = r * cos (th2);
2003 points[npoints].y = r * sin (th2);
2005 /* Ugh, add point only if it differs from prev.
2006 Not sure how this happens. */
2008 points[npoints-1].x != points[npoints].x ||
2009 points[npoints-1].y != points[npoints].y)
2013 /* Mark up the histo array to find the outer border. */
2022 int x = (i + 26) % 26;
2024 for (y = 0; y <= letter; y++)
2025 histo[y * 26 + x]++;
2029 dc->codeword_text_points[letter] = npoints;
2035 if (npoints >= letters * outer_facets) abort();
2040 for (y = 0; y < letters; y++)
2042 fprintf (stderr, "%2d: ", y);
2043 for (x = 0; x < 26; x++)
2044 fprintf (stderr, "%x", histo[y * 26 + x]);
2045 fprintf (stderr, "\n");
2047 fprintf (stderr, "\n");
2052 /* Find a gap in the outer edge, to draw guide dots. */
2055 int last_row = letters;
2056 int start_dial = -1, end_dial = -1;
2058 for (y = letters-1; y >= 0; y--)
2060 for (x = 0; x < 26; x++)
2062 if (histo[y * 26 + x] == 0)
2065 start_dial = end_dial = -1;
2067 if (start_dial == -1)
2074 if (last_row < letters-1 && start_dial >= 0)
2076 GLfloat r = iradius + rtick * (last_row + 2);
2079 dc->codeword_nguides = 0;
2080 dc->codeword_guides = (XYZ *)
2081 calloc (end_dial - start_dial + 1, sizeof (*dc->codeword_guides));
2082 for (i = start_dial; i <= end_dial; i++)
2084 GLfloat th = i * M_PI * 2 / 26;
2085 GLfloat x = r * cos (th);
2086 GLfloat y = r * sin (th);
2087 dc->codeword_guides[dc->codeword_nguides].x = x;
2088 dc->codeword_guides[dc->codeword_nguides].y = y;
2089 dc->codeword_nguides++;
2096 dc->codeword_path_npoints = npoints;
2097 dc->codeword_path = points;
2102 draw_codeword_cap (ModeInfo *mi)
2104 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2105 int wire = MI_IS_WIREFRAME(mi);
2108 int segments = dc->codeword_disc_facets;
2109 GLfloat size = dc->codeword_spread * dc->codeword_cap_size;
2110 GLfloat width = dc->codeword_line_width / 2;
2111 GLfloat thick = dc->codeword_thickness / 2;
2112 GLfloat r1 = size + width/2;
2113 GLfloat r2 = size - width/2;
2114 GLfloat facet, th, z;
2116 if (wire) segments = 12;
2117 facet = M_PI * 2 / segments;
2121 /* Top and bottom */
2123 for (z = -thick; z <= thick; z += thick*2)
2125 glNormal3f (0, 0, (z < 0 ? -1 : 1));
2126 glFrontFace (z < 0 ? GL_CCW : GL_CW);
2128 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
2129 for (th = 0; th <= M_PI*2; th += facet)
2131 GLfloat x = cos (th);
2132 GLfloat y = sin (th);
2133 glVertex3f (r1 * x, r1 * y, z);
2134 glVertex3f (r2 * x, r2 * y, z);
2140 glBegin (GL_LINE_LOOP);
2141 for (th = 0; th <= M_PI*2; th += facet)
2143 GLfloat x = cos (th);
2144 GLfloat y = sin (th);
2145 glVertex3f (r1 * x, r1 * y, z);
2148 glBegin (GL_LINE_LOOP);
2149 for (th = 0; th <= M_PI*2; th += facet)
2151 GLfloat x = cos (th);
2152 GLfloat y = sin (th);
2153 glVertex3f (r2 * x, r2 * y, z);
2159 /* Inside and outside */
2161 for (z = -1; z <= 1; z += 2)
2163 glFrontFace (z < 0 ? GL_CCW : GL_CW);
2165 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
2166 for (th = 0; th <= M_PI*2; th += facet)
2168 GLfloat th1 = th + facet;
2169 GLfloat x0 = cos (th);
2170 GLfloat y0 = sin (th);
2171 GLfloat x1 = cos (th1);
2172 GLfloat y1 = sin (th1);
2173 GLfloat r = z < 0 ? r1 : r2;
2176 do_normal (r * x0, r * y0, thick,
2177 r * x0, r * y0, -thick,
2178 r * x1, r * y1, -thick);
2180 do_normal (r * x1, r * y1, thick,
2181 r * x1, r * y1, -thick,
2182 r * x0, r * y0, -thick);
2184 glVertex3f (r * x0, r * y0, thick);
2185 glVertex3f (r * x0, r * y0, -thick);
2197 draw_codeword_guides (ModeInfo *mi, GLfloat anim_ratio)
2199 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2200 int wire = MI_IS_WIREFRAME(mi);
2203 int segments = dc->codeword_disc_facets;
2204 GLfloat s = dc->codeword_line_width / 2;
2205 GLfloat each = 1.0 / dc->codeword_nguides;
2208 if (wire) segments = 6;
2210 for (i = 0; i < dc->codeword_nguides; i++)
2213 if (anim_ratio < i*each) ratio = 0;
2214 else if (anim_ratio >= (i+1)*each) ratio = 1;
2215 else ratio = (anim_ratio - i*each) / each;
2217 if (ratio <= 0) continue;
2218 if (ratio == 0) ratio = 0.001;
2221 glTranslatef (dc->codeword_guides[i].x,
2222 dc->codeword_guides[i].y,
2223 dc->codeword_guides[i].z);
2225 glScalef (ratio, ratio, ratio);
2227 /* If the line width and thickness are pretty close to each other,
2228 use spheres. Otherwise use tubes.
2230 if (dc->codeword_thickness < dc->codeword_line_width * 1.3 &&
2231 dc->codeword_thickness > dc->codeword_line_width / 1.3)
2234 glFrontFace (GL_CCW);
2235 polys += unit_sphere (segments, segments, wire);
2239 polys += tube (0, 0, -dc->codeword_thickness / 2,
2240 0, 0, dc->codeword_thickness / 2,
2241 s, 0, segments, True, True, wire);
2251 /* Compute the characters at which the cursor is currently pointing,
2252 and render it on the logo.
2255 codeword_text_output (ModeInfo *mi, GLfloat anim_ratio)
2257 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2259 int L = strlen (dc->codeword_text);
2260 int point = dc->codeword_path_npoints * anim_ratio;
2263 if (dc->anim_state == CODEWORD_BLANK)
2266 for (i = 0; i < L; i++)
2268 if (point >= dc->codeword_text_points[i])
2269 dc->codeword_text_out[i] = dc->codeword_text[i];
2271 dc->codeword_text_out[i] = 0;
2274 int steps = dc->codeword_text[i] - 'A' + 1;
2275 int last = (i > 0 ? dc->codeword_text_points[i-1] : 0);
2276 double ratio = ((point - last) /
2277 (double) (dc->codeword_text_points[i] - last));
2278 char chr = 'A' + (ratio * steps);
2279 if (ratio < 0.1) chr = 0;
2280 dc->codeword_text_out[i] = chr;
2284 dc->codeword_text_out[i] = 0;
2286 if (*dc->codeword_text_out &&
2287 !strcmp (dc->codeword_text, "CODEWORD"))
2290 int L2 = strlen (dc->codeword_text_out);
2292 int ascent, descent;
2295 glColor4fv (dc->codeword_color);
2296 glRotatef (90, 0, 1, 0);
2297 glRotatef (-90, 0, 0, 1);
2299 for (i = 0; i < L2; i++)
2304 glRotatef ((i + 0.5) * 360 / 26.0, 0, 0, 1);
2309 glDisable(GL_LIGHTING);
2314 glBegin(GL_LINE_STRIP);
2315 for (th = M_PI * 1.45; th < M_PI * 1.55; th += 0.1)
2318 glVertex3f (r * cos(th), r * sin(th), 0);
2321 if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING);
2325 glTranslatef (0, -dc->codeword_spread * (L - 1), 0);
2326 glScalef (ss, ss, ss);
2327 buf[0] = dc->codeword_text_out[i] + ('a' - 'A');
2329 texture_string_metrics (dc->font, buf, &e, &ascent, &descent);
2332 /* #### Magic magic magic WTF... */
2333 glScalef (0.5, 0.5, 0.5);
2336 glTranslatef (-e.width * 1.0,
2337 -(ascent + descent + e.descent * 2.4), /* #### WTF */
2343 glDisable(GL_LIGHTING);
2344 glBegin(GL_LINE_LOOP);
2345 glVertex3f(0, 0, 0);
2346 glVertex3f(e.width, 0, 0);
2347 glVertex3f(e.width, e.ascent + e.descent, 0);
2348 glVertex3f(0, e.ascent + e.descent, 0);
2350 if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING);
2353 glDisable(GL_CULL_FACE); /* tell texfont.c to draw both sides */
2354 print_texture_string (dc->font, buf);
2355 glEnable(GL_CULL_FACE);
2364 /* Convert the precomputed path to a thick line of polygons.
2365 We could actually precompute all of these polygons too,
2366 but it's fast enough.
2369 draw_codeword_path (ModeInfo *mi)
2371 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2372 int wire = MI_IS_WIREFRAME(mi);
2375 GLfloat anim_ratio = (dc->anim_state == CODEWORD_IN ? dc->anim_ratio :
2376 dc->anim_state == CODEWORD_OUT ? 1 - dc->anim_ratio :
2377 dc->anim_state == CODEWORD_BLANK ? 0 :
2379 int last_anim_point = 0;
2381 GLfloat width = dc->codeword_line_width / 2;
2382 GLfloat thick = dc->codeword_thickness / 2;
2386 int quad_size = (dc->codeword_path_npoints + 1) * 2;
2387 XYZ *quads = (XYZ *) calloc (quad_size, sizeof(*quads));
2388 XYZ *norms = (XYZ *) calloc (quad_size, sizeof(*norms));
2391 for (i = 0; i < dc->codeword_path_npoints; i++)
2393 XYZ p1 = dc->codeword_path[i];
2394 XYZ p2 = (i < dc->codeword_path_npoints-1
2395 ? dc->codeword_path[i+1]
2396 : dc->codeword_path[i-1]);
2399 XYZ n; /* normal of the first line segment */
2400 n.x = -(p2.y - p1.y);
2401 n.y = (p2.x - p1.x);
2407 p1a.x = p1.x - width / 2 * n.x;
2408 p1a.y = p1.y - width / 2 * n.y;
2411 p1b.x = p1.x + width / 2 * n.x;
2412 p1b.y = p1.y + width / 2 * n.y;
2415 else if (i == dc->codeword_path_npoints - 1)
2417 p1b.x = p1.x - width / 2 * n.x;
2418 p1b.y = p1.y - width / 2 * n.y;
2421 p1a.x = p1.x + width / 2 * n.x;
2422 p1a.y = p1.y + width / 2 * n.y;
2427 XYZ p0 = dc->codeword_path[i-1];
2429 XYZ t, t0, t1; /* tangent of corner between two line segments */
2430 XYZ m; /* miter line: normal of tangent */
2431 GLfloat d; /* length of miter */
2452 /* find length of miter by projecting it on one of the normals */
2453 d = width / 2 / dot (m, n);
2455 p1a.x = p1.x - d * m.x;
2456 p1a.y = p1.y - d * m.y;
2459 p1b.x = p1.x + d * m.x;
2460 p1b.y = p1.y + d * m.y;
2464 quads[nquads++] = p1a;
2465 quads[nquads++] = p1b;
2467 if (nquads >= quad_size) abort();
2469 if (i / (double) dc->codeword_path_npoints > anim_ratio)
2472 last_anim_point = i;
2476 /* Compute normals for each point along the interior edge */
2477 for (k = 0; k <= 1; k++)
2479 for (i = k; i < nquads-2; i += 2)
2482 XYZ p2a = quads[i+2];
2485 p1a.z = thick; /* a: top */
2486 p1b.z = -thick; /* b: bottom */
2491 ? calc_normal (p1a, p1b, p2b)
2492 : calc_normal (p2a, p2b, p1a));
2497 glColor4fv (dc->codeword_color);
2498 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, dc->codeword_color);
2500 # ifdef USE_IPHONE /* Make the whole thing fit on the phone screen */
2502 GLfloat size = MI_WIDTH(mi) < MI_HEIGHT(mi) ? MI_WIDTH(mi) : MI_HEIGHT(mi);
2503 glScalef (0.9, 0.9, 0.9);
2504 if (size <= 768) /* iPad retina / iPhone 6 */
2505 glScalef (0.7, 0.7, 0.7);
2509 codeword_text_output (mi, anim_ratio);
2511 glRotatef (90, 1, 0, 0);
2512 glRotatef (90, 0, 1, 0);
2513 glRotatef (-90, 0, 0, 1);
2514 glScalef (0.8, 0.8, 0.8);
2516 glNormal3f (0, 0, -1);
2518 if (anim_ratio <= 0)
2520 polys += draw_codeword_cap (mi);
2525 glColor3f (1, 0, 0);
2526 glBegin(GL_LINE_STRIP);
2527 for (i = 0; i < dc->codeword_path_npoints; i++)
2529 glVertex3f (dc->codeword_path[i].x,
2530 dc->codeword_path[i].y,
2531 dc->codeword_path[i].z);
2535 glColor4fv (dc->codeword_color);
2542 for (i = 0; i <= 1; i++)
2543 for (j = -thick; j <= thick; j += thick*2)
2545 glBegin (GL_LINE_STRIP);
2546 for (k = i; k < nquads; k += 2)
2548 glVertex3f (quads[k].x, quads[k].y, j);
2555 /* Top and bottom */
2557 for (j = -thick; j <= thick; j += thick*2)
2561 glNormal3f (0, 0, -1);
2562 glFrontFace (GL_CW);
2566 glNormal3f (0, 0, 1);
2567 glFrontFace (GL_CCW);
2569 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
2570 for (i = 0; i < nquads; i += 2)
2572 glVertex3f (quads[i+1].x, quads[i+1].y, j);
2573 glVertex3f (quads[i].x, quads[i].y, j);
2581 for (k = 0; k <= 1; k++)
2585 glNormal3f (0, 0, -1);
2586 glFrontFace (GL_CW);
2590 glNormal3f (0, 0, 1);
2591 glFrontFace (GL_CCW);
2594 glBegin (wire ? GL_LINES : GL_QUADS);
2595 for (i = k; i < nquads; i += 2)
2598 XYZ p2a = (i < nquads-2) ? quads[i+2] : p1a;
2603 XYZ n2 = (i < nquads-2) ? norms[i+2] : n1;
2605 /* If the two normals are very similar, smooth the face.
2606 If they are different, it's a sharp turn, and use the
2607 same normal for both edges (not quite right, but close).
2609 GLfloat angle = vector_angle (n1.x, n1.y, n1.z,
2611 GLfloat pointy = 0.8;
2618 glNormal3f (n1.x, n1.y, n1.z);
2619 glVertex3f (p1a.x, p1a.y, p1a.z);
2620 glVertex3f (p1b.x, p1b.y, p1b.z);
2623 glNormal3f (n2.x, n2.y, n2.z);
2624 glVertex3f (p2b.x, p2b.y, p2b.z);
2625 glVertex3f (p2a.x, p2a.y, p2a.z);
2632 /* Only draw the guides when the path is almost complete;
2633 fade them in and out based on completeness. */
2635 GLfloat size = 0.95;
2636 GLfloat r = (anim_ratio > size
2637 ? (anim_ratio - size) / (1 - size)
2639 polys += draw_codeword_guides (mi, r);
2643 /* Draw the start and end caps */
2646 GLfloat x, y, z, x2, y2, z2, X, Y, Z, L;
2647 GLfloat r = dc->codeword_spread * dc->codeword_cap_size;
2650 x = dc->codeword_path[i].x;
2651 y = dc->codeword_path[i].y;
2652 z = dc->codeword_path[i].z;
2657 glTranslatef (x, y, z);
2658 polys += draw_codeword_cap (mi);
2663 i = last_anim_point + 1;
2664 if (i > dc->codeword_path_npoints - 1)
2665 i = dc->codeword_path_npoints - 1;
2667 x = dc->codeword_path[i].x;
2668 y = dc->codeword_path[i].y;
2669 z = dc->codeword_path[i].z;
2672 x2 = dc->codeword_path[i].x;
2673 y2 = dc->codeword_path[i].y;
2674 z2 = dc->codeword_path[i].z;
2679 L = sqrt (X*X + Y*Y + Z*Z);
2682 glTranslatef (x, y, z);
2683 glRotatef (-atan2 (X, Y) * (180 / M_PI), 0, 0, 1);
2684 glRotatef ( atan2 (Z, sqrt(X*X + Y*Y)) * (180 / M_PI), 1, 0, 0);
2685 glTranslatef (0, -r, 0);
2686 polys += draw_codeword_cap (mi);
2702 /* Window management, etc
2705 reshape_logo (ModeInfo *mi, int width, int height)
2707 GLfloat h = (GLfloat) height / (GLfloat) width;
2709 glViewport (0, 0, (GLint) width, (GLint) height);
2711 glMatrixMode(GL_PROJECTION);
2713 gluPerspective (30.0, 1/h, 1.0, 100.0);
2715 glMatrixMode(GL_MODELVIEW);
2717 gluLookAt( 0.0, 0.0, 30.0,
2721 glClear(GL_COLOR_BUFFER_BIT);
2726 gl_init (ModeInfo *mi)
2728 /* logo_configuration *dc = &dcs[MI_SCREEN(mi)]; */
2729 int wire = MI_IS_WIREFRAME(mi);
2731 GLfloat position[] = {0, 0, 0, 0};
2732 GLfloat direction[] = {3, -1, -3};
2734 position[0] = -direction[0];
2735 position[1] = -direction[1];
2736 position[2] = -direction[2];
2740 glLightfv(GL_LIGHT0, GL_POSITION, position);
2741 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction);
2742 glShadeModel(GL_SMOOTH);
2743 glEnable(GL_NORMALIZE);
2744 glEnable(GL_CULL_FACE);
2745 glEnable(GL_LIGHTING);
2746 glEnable(GL_LIGHT0);
2747 glEnable(GL_DEPTH_TEST);
2753 init_logo (ModeInfo *mi)
2755 logo_configuration *dc;
2756 int do_gasket = get_boolean_resource(mi->dpy, "doGasket", "Boolean");
2757 int do_helix = get_boolean_resource(mi->dpy, "doHelix", "Boolean");
2758 int do_ladder = (do_helix &&
2759 get_boolean_resource(mi->dpy, "doLadder", "Boolean"));
2760 int do_frame = get_boolean_resource(mi->dpy, "doFrame", "Boolean");
2761 GLfloat helix_rot = 147.0;
2763 if (!do_gasket && !do_helix)
2765 fprintf (stderr, "%s: no helix or gasket?\n", progname);
2770 dcs = (logo_configuration *)
2771 calloc (MI_NUM_SCREENS(mi), sizeof (logo_configuration));
2773 fprintf(stderr, "%s: out of memory\n", progname);
2778 dc = &dcs[MI_SCREEN(mi)];
2780 if ((dc->glx_context = init_GL(mi)) != NULL) {
2782 reshape_logo (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
2785 dc->wall_facets = get_integer_resource(mi->dpy, "wallFacets", "Integer");
2786 dc->bar_facets = get_integer_resource(mi->dpy, "barFacets", "Integer");
2787 dc->clockwise = get_boolean_resource(mi->dpy, "clockwise", "Boolean");
2788 dc->turns = get_float_resource(mi->dpy, "turns", "Float");
2789 dc->turn_spacing = get_float_resource(mi->dpy, "turnSpacing", "Float");
2790 dc->bar_spacing = get_float_resource(mi->dpy, "barSpacing", "Float");
2791 dc->wall_height = get_float_resource(mi->dpy, "wallHeight", "Float");
2792 dc->wall_thickness = get_float_resource(mi->dpy, "wallThickness", "Float");
2793 dc->bar_thickness = get_float_resource(mi->dpy, "barThickness", "Float");
2794 dc->wall_taper = get_float_resource(mi->dpy, "wallTaper", "Float");
2796 dc->gasket_size = get_float_resource(mi->dpy,"gasketSize", "Float");
2797 dc->gasket_depth = get_float_resource(mi->dpy,"gasketDepth", "Float");
2798 dc->gasket_thickness = get_float_resource(mi->dpy,"gasketThickness","Float");
2800 dc->frame_size = get_float_resource(mi->dpy, "frameSize", "Float");
2801 dc->frame_depth = get_float_resource(mi->dpy, "frameDepth", "Float");
2802 dc->frame_thickness = get_float_resource(mi->dpy, "frameThickness", "Float");
2803 dc->triangle_size = get_float_resource(mi->dpy, "triangleSize", "Float");
2805 dc->speed = get_float_resource(mi->dpy, "speed", "Float");
2806 dc->codeword_text = get_string_resource(mi->dpy, "text", "String");
2807 dc->codeword_text = codeword_simplify_text (dc->codeword_text);
2808 dc->codeword_text_out =
2809 calloc (strlen(dc->codeword_text) + 1, sizeof(*dc->codeword_text_out));
2810 dc->codeword_text_points =
2811 (int *) calloc (strlen(dc->codeword_text) + 1,
2812 sizeof(*dc->codeword_text_points));
2814 dc->codeword_facets = get_integer_resource(mi->dpy, "cwFacets", "Integer");
2815 dc->codeword_disc_facets = get_integer_resource(mi->dpy,
2816 "cwDiscFacets", "Integer");
2817 dc->codeword_spread = get_float_resource(mi->dpy, "cwSpread", "Float");
2818 dc->codeword_line_width = get_float_resource(mi->dpy, "cwLineWidth", "Float");
2819 dc->codeword_thickness = get_float_resource(mi->dpy, "cwThickness", "Float");
2820 dc->codeword_cap_size = get_float_resource(mi->dpy, "cwCapSize", "Float");
2823 char *s = get_string_resource (MI_DISPLAY (mi), "mode", "String");
2824 if (!s || !*s || !strcasecmp (s, "helix"))
2826 else if (!strcasecmp (s, "pizza"))
2828 else if (!strcasecmp (s, "both"))
2829 dc->mode = HELIX_AND_PIZZA;
2830 else if (!strcasecmp (s, "codeword"))
2831 dc->mode = CODEWORD_IN;
2835 "%s: mode must be helix, pizza, both or codeword, not \"%s\"\n",
2841 dc->anim_state = (dc->mode == HELIX_AND_PIZZA
2842 ? ((random() & 1) ? HELIX : PIZZA)
2847 if (dc->mode == CODEWORD_IN)
2848 dc->font = load_texture_font (MI_DISPLAY(mi), "cwFont");
2854 get_string_resource (mi->dpy, "foreground", "Foreground");
2856 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
2857 if (*s2 == ' ' || *s2 == '\t')
2862 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
2864 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
2868 dc->color[0] = xcolor.red / 65535.0;
2869 dc->color[1] = xcolor.green / 65535.0;
2870 dc->color[2] = xcolor.blue / 65535.0;
2873 color_name = get_string_resource (mi->dpy, "cwForeground", "Foreground");
2874 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
2875 if (*s2 == ' ' || *s2 == '\t')
2880 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
2882 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
2886 dc->codeword_color[0] = xcolor.red / 65535.0;
2887 dc->codeword_color[1] = xcolor.green / 65535.0;
2888 dc->codeword_color[2] = xcolor.blue / 65535.0;
2889 dc->codeword_color[3] = 1.0;
2891 color_name = get_string_resource (mi->dpy, "cwBackground", "Background");
2892 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
2893 if (*s2 == ' ' || *s2 == '\t')
2898 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
2900 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
2904 dc->codeword_bg[0] = xcolor.red / 65535.0;
2905 dc->codeword_bg[1] = xcolor.green / 65535.0;
2906 dc->codeword_bg[2] = xcolor.blue / 65535.0;
2907 dc->codeword_bg[3] = 1.0;
2910 dc->trackball = gltrackball_init (False);
2912 dc->gasket_spinnerx.probability = 0.1;
2913 dc->gasket_spinnery.probability = 0.1;
2914 dc->gasket_spinnerz.probability = 1.0;
2916 dc->helix_spinnerz.probability = 0.6;
2918 dc->pizza_spinnerz.probability = 0.6;
2919 dc->pizza_spinnery.probability = 0.6;
2921 dc->frame_spinner.probability = 5.0;
2923 dc->scene_spinnerx.probability = 0.1;
2924 dc->scene_spinnery.probability = 0.0;
2926 if (dc->mode == CODEWORD_IN)
2928 double tilt_speed = 0.003;
2929 dc->scene_rot = make_rotator (0, 0, 0, 0, tilt_speed, True);
2932 /* start the frame off-screen */
2933 dc->frame_spinner.spinning_p = True;
2934 dc->frame_spinner.position = 0.3;
2935 dc->frame_spinner.speed = 0.001;
2937 if (dc->speed > 0) /* start off with the gasket in motion */
2939 dc->gasket_spinnerz.spinning_p = True;
2940 dc->gasket_spinnerz.speed = (0.002
2941 * ((random() & 1) ? 1 : -1)
2945 # ifdef DXF_OUTPUT_HACK
2948 dc->frame_depth = dc->gasket_depth;
2953 glRotatef(90, 1, 0, 0);
2954 glRotatef(90, 0, 0, 1);
2955 make_pizza (dc, 0, 0);
2958 glRotatef(helix_rot, 0, 0, 1);
2959 make_ladder (dc, 0, 0);
2960 make_helix (dc, 0, 0);
2961 glRotatef (180, 0, 0, 1);
2962 make_helix (dc, 0, 0);
2966 make_gasket (dc, 0);
2974 glRotatef(90, 1, 0, 0);
2975 glRotatef(90, 0, 0, 1);
2976 dc->anim_state = CODEWORD;
2977 make_codeword_path (mi);
2978 draw_codeword_path (mi);
2986 dc->helix_list = glGenLists (1);
2987 glNewList (dc->helix_list, GL_COMPILE);
2988 glRotatef(helix_rot, 0, 0, 1);
2989 if (do_ladder) dc->polys[0] += make_ladder (dc, 0, 0);
2990 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
2991 glRotatef(180, 0, 0, 1);
2992 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
2997 dc->helix_list_wire = glGenLists (1);
2998 glNewList (dc->helix_list_wire, GL_COMPILE);
2999 /* glRotatef(helix_rot, 0, 0, 1); wtf? */
3000 if (do_ladder) dc->polys[1] += make_ladder (dc, 1, 1);
3001 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
3002 glRotatef(180, 0, 0, 1);
3003 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
3008 dc->helix_list_facetted = glGenLists (1);
3009 glNewList (dc->helix_list_facetted, GL_COMPILE);
3010 glRotatef(helix_rot, 0, 0, 1);
3011 if (do_ladder) dc->polys[2] += make_ladder (dc, 1, 0);
3012 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
3013 glRotatef(180, 0, 0, 1);
3014 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
3018 dc->pizza_list = glGenLists (1);
3019 glNewList (dc->pizza_list, GL_COMPILE);
3020 if (do_frame) dc->polys[5] += make_pizza (dc, 0, 0);
3023 dc->pizza_list_wire = glGenLists (1);
3024 glNewList (dc->pizza_list_wire, GL_COMPILE);
3025 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 1);
3028 dc->pizza_list_facetted = glGenLists (1);
3029 glNewList (dc->pizza_list_facetted, GL_COMPILE);
3030 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 0);
3033 dc->gasket_list = glGenLists (1);
3034 glNewList (dc->gasket_list, GL_COMPILE);
3035 if (do_gasket) dc->polys[3] += make_gasket (dc, 0);
3038 dc->gasket_list_wire = glGenLists (1);
3039 glNewList (dc->gasket_list_wire, GL_COMPILE);
3040 if (do_gasket) dc->polys[4] += make_gasket (dc, 1);
3043 dc->frame_list = glGenLists (1);
3044 glNewList (dc->frame_list, GL_COMPILE);
3045 if (do_frame) dc->polys[5] += make_frame (dc, 0);
3048 dc->frame_list_wire = glGenLists (1);
3049 glNewList (dc->frame_list_wire, GL_COMPILE);
3050 if (do_frame) dc->polys[6] += make_frame (dc, 1);
3053 make_codeword_path (mi);
3056 /* When drawing both solid and wireframe objects,
3057 make sure the wireframe actually shows up! */
3058 glEnable (GL_POLYGON_OFFSET_FILL);
3059 glPolygonOffset (1.0, 1.0);
3064 logo_handle_event (ModeInfo *mi, XEvent *event)
3066 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
3068 if (gltrackball_event_handler (event, dc->trackball,
3069 MI_WIDTH (mi), MI_HEIGHT (mi),
3070 &dc->button_down_p))
3072 else if (event->xany.type == KeyPress)
3076 XLookupString (&event->xkey, &c, 1, &keysym, 0);
3077 if (c == ' ' || c == '\t')
3079 switch (dc->anim_state) {
3081 dc->anim_state = HELIX_OUT;
3082 dc->anim_ratio = 0.0;
3085 dc->anim_state = PIZZA_OUT;
3086 dc->anim_ratio = 0.0;
3089 dc->anim_state = CODEWORD_OUT;
3090 dc->anim_ratio = 0.0;
3103 tick_spinner (ModeInfo *mi, spinner *s)
3105 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
3107 if (dc->speed == 0) return;
3108 if (dc->button_down_p) return;
3112 s->position += s->speed;
3113 if (s->position >= 1.0 || s->position <= -1.0)
3117 s->spinning_p = False;
3120 else if (s->probability &&
3121 (random() % (int) (PROBABILITY_SCALE / s->probability)) == 0)
3124 s->spinning_p = True;
3127 s->speed = dc->speed * (frand(ss/3) + frand(ss/3) + frand(ss/3));
3128 } while (s->speed <= 0);
3130 s->speed = -s->speed;
3136 link_spinners (ModeInfo *mi, spinner *s0, spinner *s1)
3138 if (s0->spinning_p && !s1->spinning_p)
3140 GLfloat op = s1->probability;
3141 s1->probability = PROBABILITY_SCALE;
3142 tick_spinner (mi, s1);
3143 s1->probability = op;
3149 draw_logo (ModeInfo *mi)
3151 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
3152 Display *dpy = MI_DISPLAY(mi);
3153 Window window = MI_WINDOW(mi);
3154 int wire = MI_IS_WIREFRAME(mi);
3156 GLfloat specular[] = {0.8, 0.8, 0.8, 1.0};
3157 GLfloat shininess = 50.0;
3161 if (!dc->glx_context)
3164 mi->polygon_count = 0;
3165 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(dc->glx_context));
3168 dc->wire_overlay == 0 &&
3169 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
3170 dc->wire_overlay = ((random() % 200) +
3174 tick_spinner (mi, &dc->gasket_spinnerx);
3175 tick_spinner (mi, &dc->gasket_spinnery);
3176 tick_spinner (mi, &dc->gasket_spinnerz);
3177 tick_spinner (mi, &dc->helix_spinnerz);
3178 tick_spinner (mi, &dc->pizza_spinnery);
3179 tick_spinner (mi, &dc->pizza_spinnerz);
3180 tick_spinner (mi, &dc->scene_spinnerx);
3181 tick_spinner (mi, &dc->scene_spinnery);
3182 tick_spinner (mi, &dc->frame_spinner);
3183 link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery);
3187 static double i = 0.0;
3188 dc->anim_state = HELIX;
3189 dc->wire_overlay = 0;
3190 dc->gasket_spinnerx.spinning_p = 0;
3191 dc->gasket_spinnery.spinning_p = 0;
3192 dc->gasket_spinnerz.spinning_p = 0;
3193 dc->helix_spinnerz.spinning_p = 0;
3194 dc->pizza_spinnery.spinning_p = 0;
3195 dc->pizza_spinnerz.spinning_p = 0;
3196 dc->scene_spinnerx.spinning_p = 0;
3197 dc->scene_spinnery.spinning_p = 0;
3198 dc->frame_spinner.spinning_p = 0;
3199 dc->frame_spinner.position = 0.3;
3200 dc->gasket_spinnerz.position = i;
3201 dc->helix_spinnerz.position = i;
3205 # endif /* LINEAR */
3207 switch (dc->anim_state)
3210 if (dc->mode == HELIX_AND_PIZZA &&
3211 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
3212 dc->anim_state = HELIX_OUT;
3216 dc->anim_ratio += 0.1 * dc->speed;
3217 if (dc->anim_ratio >= 1.0)
3219 dc->anim_ratio = 0.0;
3220 dc->anim_state = PIZZA_IN;
3225 dc->anim_ratio += 0.1 * dc->speed;
3226 if (dc->anim_ratio >= 1.0)
3228 dc->anim_ratio = 0.0;
3229 dc->anim_state = PIZZA;
3234 if (dc->mode == HELIX_AND_PIZZA &&
3235 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
3236 dc->anim_state = PIZZA_OUT;
3240 dc->anim_ratio += 0.1 * dc->speed;
3241 if (dc->anim_ratio >= 1.0)
3243 dc->anim_ratio = 0.0;
3244 dc->anim_state = HELIX_IN;
3249 dc->anim_ratio += 0.1 * dc->speed;
3250 if (dc->anim_ratio >= 1.0)
3252 dc->anim_ratio = 0.0;
3253 dc->anim_state = HELIX;
3259 dc->scene_spinnerx.probability = 0.2;
3260 dc->scene_spinnery.probability = 0.05;
3261 if (! dc->button_down_p)
3262 dc->anim_ratio += 0.004 * dc->speed;
3263 if (dc->anim_ratio >= 1.0)
3265 dc->anim_state = CODEWORD;
3266 dc->anim_ratio = frand (0.5);
3271 dc->scene_spinnerx.probability = 2.5;
3272 dc->scene_spinnery.probability = 0.2;
3273 if (! dc->button_down_p)
3274 dc->anim_ratio += (0.0005 + frand(0.002)) * dc->speed;
3275 if (dc->anim_ratio >= 1.0)
3277 dc->anim_ratio = 0.0;
3278 dc->anim_state = CODEWORD_OUT;
3283 dc->scene_spinnerx.probability = 0;
3284 dc->scene_spinnery.probability = 0;
3285 if (! dc->button_down_p)
3286 dc->anim_ratio += 0.02 * dc->speed;
3287 if (dc->anim_ratio >= 1.0)
3289 dc->anim_ratio = 0.0;
3290 dc->anim_state = CODEWORD_BLANK;
3294 case CODEWORD_BLANK:
3295 dc->scene_spinnerx.probability = 0;
3296 dc->scene_spinnery.probability = 0;
3297 if (! dc->button_down_p)
3298 dc->anim_ratio += 0.01 * dc->speed;
3299 if (dc->anim_ratio >= 1.0)
3301 dc->anim_ratio = 0.0;
3302 dc->anim_state = CODEWORD_IN;
3311 pizza_p = (dc->anim_state == PIZZA ||
3312 dc->anim_state == PIZZA_IN ||
3313 dc->anim_state == PIZZA_OUT);
3315 codeword_p = (dc->anim_state == CODEWORD ||
3316 dc->anim_state == CODEWORD_IN ||
3317 dc->anim_state == CODEWORD_OUT ||
3318 dc->anim_state == CODEWORD_BLANK);
3320 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3323 glRotatef(current_device_rotation(), 0, 0, 1);
3325 GLfloat scale = 1.8;
3329 glScalef(scale, scale, scale);
3331 glColor3f(dc->color[0], dc->color[1], dc->color[2]);
3334 /* Draw frame before trackball rotation */
3337 GLfloat p = (dc->frame_spinner.position >= 0
3338 ? dc->frame_spinner.position
3339 : -dc->frame_spinner.position);
3340 GLfloat size = (p > 0.5 ? 1-p : p);
3341 scale = 1 + (size * 10);
3343 /* gltrackball_rotate (dc->trackball); */
3344 glRotatef(90, 1, 0, 0);
3345 glRotatef(90, 0, 0, 1);
3347 glScalef (1, scale, scale);
3350 glDisable (GL_LIGHTING);
3351 glCallList (dc->frame_list_wire);
3352 mi->polygon_count += dc->polys[6];
3354 else if (dc->wire_overlay != 0)
3356 glCallList (dc->frame_list);
3357 glDisable (GL_LIGHTING);
3358 glColor3fv (dc->color);
3359 glCallList (dc->frame_list_wire);
3360 mi->polygon_count += dc->polys[6];
3361 if (!wire) glEnable (GL_LIGHTING);
3365 glCallList (dc->frame_list);
3366 mi->polygon_count += dc->polys[5];
3371 gltrackball_rotate (dc->trackball);
3373 glRotatef(90, 1, 0, 0);
3374 glRotatef(90, 0, 0, 1);
3377 # define SINIFY(I) (I)
3379 # define SINIFY(I) sin (M_PI/2 * (I))
3384 glRotatef (360 * SINIFY (dc->scene_spinnerx.position), 0, 1, 0);
3385 glRotatef (360 * SINIFY (dc->scene_spinnery.position), 0, 0, 1);
3389 glRotatef (360 * SINIFY (dc->gasket_spinnerx.position), 0, 1, 0);
3390 glRotatef (360 * SINIFY (dc->gasket_spinnery.position), 0, 0, 1);
3391 glRotatef (360 * SINIFY (dc->gasket_spinnerz.position), 1, 0, 0);
3393 memcpy (gcolor, dc->color, sizeof (dc->color));
3394 if (dc->wire_overlay != 0)
3396 gcolor[0] = gcolor[1] = gcolor[2] = 0;
3397 specular[0] = specular[1] = specular[2] = 0;
3400 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
3401 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
3402 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shininess);
3406 glDisable (GL_LIGHTING);
3407 glCallList (dc->gasket_list_wire);
3408 mi->polygon_count += dc->polys[4];
3410 else if (dc->wire_overlay != 0)
3412 glCallList (dc->gasket_list);
3413 glDisable (GL_LIGHTING);
3414 glColor3fv (dc->color);
3415 glCallList (dc->gasket_list_wire);
3416 mi->polygon_count += dc->polys[4];
3417 if (!wire) glEnable (GL_LIGHTING);
3418 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
3422 glCallList (dc->gasket_list);
3423 mi->polygon_count += dc->polys[3];
3429 glRotatef (360 * SINIFY (dc->pizza_spinnery.position), 1, 0, 0);
3430 glRotatef (360 * SINIFY (dc->pizza_spinnerz.position), 0, 0, 1);
3434 glRotatef (360 * SINIFY (dc->helix_spinnerz.position), 0, 0, 1);
3437 scale = ((dc->anim_state == PIZZA_IN || dc->anim_state == HELIX_IN)
3439 : ((dc->anim_state == PIZZA_OUT || dc->anim_state == HELIX_OUT)
3440 ? 1.0 - dc->anim_ratio
3442 if (scale <= 0) scale = 0.001;
3443 glScalef (scale, scale, scale);
3447 glDisable (GL_LIGHTING);
3449 glCallList (dc->pizza_list_wire);
3451 glCallList (dc->helix_list_wire);
3452 mi->polygon_count += dc->polys[1];
3454 else if (dc->wire_overlay != 0)
3457 glCallList (dc->pizza_list_facetted);
3459 glCallList (dc->helix_list_facetted);
3461 glDisable (GL_LIGHTING);
3462 glColor3fv (dc->color);
3465 glCallList (dc->pizza_list_wire);
3467 glCallList (dc->helix_list_wire);
3469 mi->polygon_count += dc->polys[2];
3470 if (!wire) glEnable (GL_LIGHTING);
3475 glCallList (dc->pizza_list);
3477 glCallList (dc->helix_list);
3478 mi->polygon_count += dc->polys[0];
3481 else /* codeword_p */
3484 double max = 70; /* face front */
3486 get_position (dc->scene_rot, &x, &y, &z, !dc->button_down_p);
3487 glRotatef (max/2 - x*max, 0, 0, 1);
3488 glRotatef (max/2 - y*max, 0, 1, 0);
3489 /* glRotatef (max/2 - z*max, 1, 0, 0); */
3491 glRotatef (360 * SINIFY (dc->scene_spinnerx.position), 0, 1, 0);
3492 glRotatef (360 * SINIFY (dc->scene_spinnery.position), 0, 0, 1);
3495 glClearColor (dc->codeword_bg[0],
3498 dc->codeword_bg[3]);
3499 mi->polygon_count += draw_codeword_path (mi);
3504 if (dc->wire_overlay > 0)
3507 if (mi->fps_p) do_fps (mi);
3510 glXSwapBuffers(dpy, window);
3513 XSCREENSAVER_MODULE_2 ("DNALogo", dnalogo, logo)