1 /* DNA Logo, Copyright (c) 2001, 2002, 2003 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 #define DEFAULTS __extension__ \
14 "*showFPS: False \n" \
15 "*wireframe: False \n" \
16 "*doGasket: True \n" \
18 "*doLadder: True \n" \
20 "*wallFacets: 360 \n" \
22 "*clockwise: False \n" \
24 "*turnSpacing: 2.2 \n" \
25 "*barSpacing: 0.24 \n" \
26 "*wallHeight: 0.45 \n" \
27 "*wallThickness: 0.12 \n" \
28 "*barThickness: 0.058 \n" \
29 "*wallTaper: 0.95 \n" \
30 "*gasketSize: 1.88 \n" \
31 "*gasketDepth: 0.15 \n" \
32 "*gasketThickness: 0.4 \n" \
33 "*frameSize: 1.20 \n" \
34 "*frameDepth: 0.01 \n" \
35 "*frameThickness: 0.03 \n" \
36 "*triangleSize: 0.045 \n" \
38 ".foreground: #00AA00 \n" \
39 "*geometry: =640x640\n" \
41 # define refresh_logo 0
42 # define release_logo 0
44 #define countof(x) (sizeof((x))/sizeof((*x)))
46 #include "xlockmore.h"
50 #include "gltrackball.h"
52 #ifdef USE_GL /* whole file */
56 GLfloat position; /* 0.0 - 1.0 */
57 GLfloat speed; /* how far along the path (may be negative) */
58 GLfloat probability; /* relative likelyhood to start spinning */
62 GLXContext *glx_context;
64 GLuint helix_list, helix_list_wire, helix_list_facetted;
65 GLuint gasket_list, gasket_list_wire;
66 GLuint frame_list, frame_list_wire;
78 GLfloat wall_thickness;
79 GLfloat bar_thickness;
84 GLfloat gasket_thickness;
88 GLfloat frame_thickness;
89 GLfloat triangle_size;
93 spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz;
94 spinner scene_spinnerx, scene_spinnery;
95 spinner helix_spinnerz;
96 spinner frame_spinner;
98 trackball_state *trackball;
101 int wire_overlay; /* frame countdown */
103 } logo_configuration;
105 static logo_configuration *dcs = NULL;
107 static XrmOptionDescRec opts[] = {
108 { "-speed", ".speed", XrmoptionSepArg, 0 },
111 ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
113 #define PROBABILITY_SCALE 600
117 /* Calculate the angle (in degrees) between two vectors.
120 vector_angle (double ax, double ay, double az,
121 double bx, double by, double bz)
123 double La = sqrt (ax*ax + ay*ay + az*az);
124 double Lb = sqrt (bx*bx + by*by + bz*bz);
127 if (La == 0 || Lb == 0) return 0;
128 if (ax == bx && ay == by && az == bz) return 0;
130 /* dot product of two vectors is defined as:
131 La * Lb * cos(angle between vectors)
132 and is also defined as:
133 ax*bx + ay*by + az*bz
135 La * Lb * cos(angle) = ax*bx + ay*by + az*bz
136 cos(angle) = (ax*bx + ay*by + az*bz) / (La * Lb)
137 angle = acos ((ax*bx + ay*by + az*bz) / (La * Lb));
139 cc = (ax*bx + ay*by + az*bz) / (La * Lb);
140 if (cc > 1) cc = 1; /* avoid fp rounding error (1.000001 => sqrt error) */
143 return (angle * M_PI / 180);
151 make_helix (logo_configuration *dc, int facetted, int wire)
154 int wall_facets = dc->wall_facets / (facetted ? 10 : 1);
156 GLfloat max_th = M_PI * 2 * dc->turns;
157 GLfloat th_inc = M_PI * 2 / wall_facets;
159 GLfloat x1=0, y1=0, x2=0, y2=0;
160 GLfloat x1b=0, y1b=0, x2b=0, y2b=0;
163 GLfloat h1off=0, h2off=0;
164 GLfloat z_inc = dc->turn_spacing / wall_facets;
169 x1b = 1 - dc->wall_thickness;
172 z1 = -(dc->turn_spacing * dc->turns / 2);
174 h1 = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2);
175 h1off = (dc->wall_taper > 0 ? -dc->wall_height / 2 : 0);
178 z1 = -z1, z_inc = -z_inc, h1off = -h1off;
187 nx = cos (th + M_PI/2);
188 ny = sin (th + M_PI/2);
189 glNormal3f(nx, ny, 0);
190 glVertex3f( x1, y1, z1 - h1 + h1off);
191 glVertex3f( x1, y1, z1 + h1 + h1off);
192 glVertex3f(x1b, y1b, z1 + h1 + h1off);
193 glVertex3f(x1b, y1b, z1 - h1 + h1off);
198 while (th + th_inc <= max_th)
205 x2b = x2 * (1 - dc->wall_thickness);
206 y2b = y2 * (1 - dc->wall_thickness);
211 if (dc->wall_taper > 0)
214 if (th < dc->wall_taper)
216 h2 = dc->wall_height/2 * cos (M_PI / 2
217 * (1 - (th / dc->wall_taper)));
219 h2off = h2 - dc->wall_height/2;
221 h2off = dc->wall_height/2 - h2;
223 else if (th >= max_th - dc->wall_taper)
225 if (th + th_inc > max_th) /* edge case: always come to a point */
228 h2 = dc->wall_height/2 * cos (M_PI / 2
229 * (1 - ((max_th - th)
232 h2off = dc->wall_height/2 - h2;
234 h2off = h2 - dc->wall_height/2;
241 glBegin(wire ? GL_LINES : GL_QUADS);
242 glNormal3f(x1, y1, 0);
243 glVertex3f(x1, y1, z1 - h1 + h1off);
244 glVertex3f(x1, y1, z1 + h1 + h1off);
245 glNormal3f(x2, y2, 0);
246 glVertex3f(x2, y2, z2 + h2 + h2off);
247 glVertex3f(x2, y2, z2 - h2 + h2off);
254 glBegin(wire ? GL_LINES : GL_QUADS);
255 glNormal3f(-x1b, -y1b, 0);
256 glVertex3f( x1b, y1b, z1 - h1 + h1off);
257 glVertex3f( x1b, y1b, z1 + h1 + h1off);
258 glNormal3f(-x2b, -y2b, 0);
259 glVertex3f( x2b, y2b, z2 + h2 + h2off);
260 glVertex3f( x2b, y2b, z2 - h2 + h2off);
267 /* glNormal3f(0, 0, 1);*/
268 do_normal (x2, y2, z2 + h2 + h2off,
269 x2b, y2b, z2 + h2 + h2off,
270 x1b, y1b, z1 + h1 + h1off);
271 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
272 glVertex3f( x2, y2, z2 + h2 + h2off);
273 glVertex3f( x2b, y2b, z2 + h2 + h2off);
274 glVertex3f( x1b, y1b, z1 + h1 + h1off);
275 glVertex3f( x1, y1, z1 + h1 + h1off);
282 do_normal ( x1, y1, z1 - h1 + h1off,
283 x1b, y1b, z1 - h1 + h1off,
284 x2b, y2b, z2 - h2 + h2off);
285 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
286 glNormal3f(0, 0, -1);
287 glVertex3f( x1, y1, z1 - h1 + h1off);
288 glVertex3f( x1b, y1b, z1 - h1 + h1off);
289 glVertex3f( x2b, y2b, z2 - h2 + h2off);
290 glVertex3f( x2, y2, z2 - h2 + h2off);
310 nx = cos (th + M_PI/2);
311 ny = sin (th + M_PI/2);
312 glNormal3f(nx, ny, 0);
313 glVertex3f(x2, y2, z1 - h2 + h2off);
314 glVertex3f(x2, y2, z1 + h2 + h2off);
315 glVertex3f(x2b, y2b, z1 + h2 + h2off);
316 glVertex3f(x2b, y2b, z1 - h2 + h2off);
325 make_ladder (logo_configuration *dc, int facetted, int wire)
329 GLfloat max_th = dc->turns * M_PI * 2;
330 GLfloat max_z = dc->turns * dc->turn_spacing;
331 GLfloat z_inc = dc->bar_spacing;
332 GLfloat th_inc = M_PI * 2 * (dc->bar_spacing / dc->turn_spacing);
335 /* skip forward to center the bars in the helix... */
337 GLfloat usable_th = max_th - dc->wall_taper;
338 GLfloat usable_z = max_z / (max_th / usable_th);
339 int nbars = usable_z / dc->bar_spacing;
340 GLfloat used_z, pad_z, pad_ratio;
342 if (! (nbars & 1)) nbars--; /* always an odd number of bars */
344 used_z = (nbars - 1) * dc->bar_spacing;
345 pad_z = max_z - used_z;
346 pad_ratio = pad_z / max_z;
348 th = (max_th * pad_ratio/2);
349 z = -(max_z / 2) + (max_z * pad_ratio/2);
352 z = -z, z_inc = -z_inc;
354 for (i = 0; i < nbars; i++)
356 int facets = dc->bar_facets / (facetted ? 14 : 1);
357 if (facets <= 3) facets = 3;
358 x = cos (th) * (1 - dc->wall_thickness);
359 y = sin (th) * (1 - dc->wall_thickness);
360 polys += tube ( x, y, z,
362 dc->bar_thickness, 0, facets,
377 make_gasket (logo_configuration *dc, int wire)
385 GLfloat d2r = M_PI / 180;
387 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 2;
389 GLfloat *pointsx0, *pointsy0, *pointsx1, *pointsy1, *normals;
391 GLfloat r0 = 0.750; /* 395 */
392 GLfloat r1a = 0.825; /* bottom of wall below upper left hole */
393 GLfloat r1b = 0.867; /* center of upper left hole */
394 GLfloat r1c = 0.909; /* top of wall above hole */
395 GLfloat r1 = 0.916; /* 471 */
396 GLfloat r2 = 0.963; /* 490 */
397 GLfloat r3 = 0.960; /* 499 */
398 GLfloat r4 = 1.000; /* 507 */
399 GLfloat r5 = 1.080; /* 553 */
401 GLfloat ctrl_r[100], ctrl_th[100];
405 # define POINT(r,th) \
406 ctrl_r [nctrls] = r, \
407 ctrl_th[nctrls] = (th * d2r), \
410 POINT (0.829, 0); /* top indentation, right half */
418 POINT (r4, 4.0); /* moving clockwise... */
439 POINT (r4, 316.8); /* upper left indentation */
440 POINT (0.990, 316.87);
441 POINT (0.880, 317.21);
442 POINT (0.872, 317.45);
443 POINT (0.869, 317.80);
444 POINT (0.867, 318.10);
446 POINT (0.867, 318.85);
447 POINT (0.869, 319.15);
448 POINT (0.872, 319.50);
449 POINT (0.880, 319.74);
450 POINT (0.990, 320.08);
455 POINT (r1a, 338.5); /* cut-out disc */
461 POINT (0.872, 356.05); /* top indentation, left half */
462 POINT (0.862, 356.19);
463 POINT (0.851, 356.70);
464 POINT (0.841, 357.35);
465 POINT (0.835, 358.19);
466 POINT (0.831, 359.15);
470 points_size = res + (nctrls * 2);
471 pointsx0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
472 pointsy0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
473 pointsx1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
474 pointsy1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
475 normals = (GLfloat *) malloc (points_size * sizeof(GLfloat) * 2);
478 for (i = 1; i < nctrls; i++)
480 GLfloat from_r = ctrl_r [i-1];
481 GLfloat from_th = ctrl_th[i-1];
482 GLfloat to_r = ctrl_r [i];
483 GLfloat to_th = ctrl_th[i];
485 GLfloat step = 2*M_PI / res;
486 int nsteps = 1 + ((to_th - from_th) / step);
489 for (j = 0; j < nsteps + (i == nctrls-1); j++)
491 GLfloat r = from_r + (j * (to_r - from_r) / nsteps);
492 GLfloat th = from_th + (j * (to_th - from_th) / nsteps);
494 GLfloat cth = cos(th) * dc->gasket_size;
495 GLfloat sth = sin(th) * dc->gasket_size;
497 pointsx0[npoints] = r0 * cth; /* inner ring */
498 pointsy0[npoints] = r0 * sth;
499 pointsx1[npoints] = r * cth; /* outer ring */
500 pointsy1[npoints] = r * sth;
503 if (npoints >= points_size) abort();
507 /* normals for the outer ring */
508 for (i = 1; i < npoints; i++)
519 n = calc_normal (a, b, c);
520 normals[(i-1)*2 ] = n.x;
521 normals[(i-1)*2+1] = n.y;
524 glRotatef(-90, 0, 1, 0);
525 glRotatef(180, 0, 0, 1);
530 for (z = -thick2; z <= thick2; z += thick2*2)
534 glBegin (GL_LINE_LOOP);
535 for (i = 0; i < npoints; i++)
536 glVertex3f (pointsx0[i], pointsy0[i], z);
541 glBegin (GL_LINE_LOOP);
542 for (i = 0; i < npoints; i++)
543 glVertex3f (pointsx1[i], pointsy1[i], z);
547 for (i = 1; i < npoints; i++)
549 glBegin (GL_LINE_STRIP);
550 glVertex3f (pointsx0[i-1], pointsy0[i-1], z);
551 glVertex3f (pointsx0[i ], pointsy0[i ], z);
552 glVertex3f (pointsx1[i ], pointsy1[i ], z);
553 glVertex3f (pointsx1[i-1], pointsy1[i-1], z);
561 for (i = 0; i < npoints; i++)
564 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
565 glVertex3f (pointsx0[i], pointsy0[i], thick2);
567 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
568 glVertex3f (pointsx1[i], pointsy1[i], thick2);
578 glNormal3f(0, 0, -1);
579 glBegin (GL_QUAD_STRIP);
580 for (i = 0; i < npoints; i++)
582 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
583 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
591 glBegin (GL_QUAD_STRIP);
592 for (i = 0; i < npoints; i++)
594 glVertex3f (pointsx0[i], pointsy0[i], thick2);
595 glVertex3f (pointsx1[i], pointsy1[i], thick2);
602 glBegin (GL_QUAD_STRIP);
603 for (i = 0; i < npoints; i++)
605 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
606 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
607 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
616 for (i = 0; i < npoints-1; i++)
618 int ia = (i == 0 ? npoints-2 : i-1);
619 int iz = (i == npoints-2 ? 0 : i+1);
620 GLfloat x = pointsx1[i];
621 GLfloat y = pointsy1[i];
622 GLfloat xz = pointsx1[iz];
623 GLfloat yz = pointsy1[iz];
625 GLfloat nxa = normals[ia*2]; /* normal of [i-1 - i] face */
626 GLfloat nya = normals[ia*2+1];
627 GLfloat nx = normals[i*2]; /* normal of [i - i+1] face */
628 GLfloat ny = normals[i*2+1];
629 GLfloat nxz = normals[iz*2]; /* normal of [i+1 - i+2] face */
630 GLfloat nyz = normals[iz*2+1];
632 GLfloat anglea = vector_angle (nx, ny, 0, nxa, nya, 0);
633 GLfloat anglez = vector_angle (nx, ny, 0, nxz, nyz, 0);
634 GLfloat pointy = 0.005;
638 glNormal3f (nx, ny, 0);
639 glVertex3f (x, y, thick2);
640 glVertex3f (x, y, -thick2);
644 glNormal3f ((nxa + nx) / 2, (nya + ny) / 2, 0);
645 glVertex3f (x, y, thick2);
646 glVertex3f (x, y, -thick2);
651 glNormal3f (nx, ny, 0);
652 glVertex3f (xz, yz, -thick2);
653 glVertex3f (xz, yz, thick2);
657 glNormal3f ((nx + nxz) / 2, (ny + nyz) / 2, 0);
658 glVertex3f (xz, yz, -thick2);
659 glVertex3f (xz, yz, thick2);
667 /* Fill in the upper left hole...
674 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
675 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
677 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
678 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
682 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
683 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
685 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
686 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
692 glNormal3f (0, 0, -1);
694 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
695 glVertex3f (pointsx0[0], pointsy0[0], -thick2);
696 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
697 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
698 glVertex3f (pointsx0[2], pointsy0[2], -thick2);
703 glNormal3f (0, 0, 1);
705 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
706 glVertex3f (pointsx0[0], pointsy0[0], thick2);
707 glVertex3f (pointsx0[1], pointsy0[1], thick2);
708 glVertex3f (pointsx0[3], pointsy0[3], thick2);
709 glVertex3f (pointsx0[2], pointsy0[2], thick2);
716 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
717 glNormal3f (pointsx0[1], pointsy0[1], 0);
718 glVertex3f (pointsx0[1], pointsy0[1], thick2);
719 glNormal3f (pointsx0[3], pointsy0[3], 0);
720 glVertex3f (pointsx0[3], pointsy0[3], thick2);
721 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
722 glNormal3f (pointsx0[1], pointsy0[1], 0);
723 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
734 GLfloat th, cth, sth;
738 th = ((339.0 + 343.0) / 2) * d2r;
740 glTranslatef (r1b * cos(th) * dc->gasket_size,
741 r1b * sin(th) * dc->gasket_size,
745 for (i = 0; i < nsteps; i++)
747 th = 2 * M_PI * i / nsteps;
748 cth = cos (th) * dc->gasket_size;
749 sth = sin (th) * dc->gasket_size;
750 pointsx0[npoints] = r0 * cth;
751 pointsy0[npoints] = r0 * sth;
752 pointsx1[npoints] = r1 * cth;
753 pointsy1[npoints] = r1 * sth;
758 pointsx0[npoints] = pointsx0[0];
759 pointsy0[npoints] = pointsy0[0];
760 pointsx1[npoints] = pointsx1[0];
761 pointsy1[npoints] = pointsy1[0];
766 glBegin (GL_LINE_LOOP);
767 for (i = 0; i < npoints; i++)
768 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
771 glBegin (GL_LINE_LOOP);
772 for (i = 0; i < npoints; i++)
773 glVertex3f (pointsx0[i], pointsy0[i], thick2);
777 glBegin (GL_LINE_LOOP);
778 for (i = 0; i < npoints; i++)
779 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
782 glBegin (GL_LINE_LOOP);
783 for (i = 0; i < npoints; i++)
784 glVertex3f (pointsx1[i], pointsy1[i], thick2);
793 glNormal3f(0, 0, -1);
794 glBegin (GL_QUAD_STRIP);
795 for (i = 0; i < npoints; i++)
797 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
798 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
806 glBegin (GL_QUAD_STRIP);
807 for (i = 0; i < npoints; i++)
809 glVertex3f (pointsx0[i], pointsy0[i], thick2);
810 glVertex3f (pointsx1[i], pointsy1[i], thick2);
818 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
819 for (i = 0; i < npoints; i++)
821 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
822 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
823 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
833 /* Attach the bottom-right dingus...
840 glRotatef (49.5, 0, 0, 1);
841 glScalef (dc->gasket_size, dc->gasket_size, 1);
842 glTranslatef (0, (r0+r1)/2, 0);
848 glBegin (wire ? GL_LINE_STRIP : GL_QUADS);
849 glNormal3f (0, 0, -1);
850 glVertex3f (-w/2, -h/2, -thick2); glVertex3f (-w/2, h/2, -thick2);
851 glVertex3f ( w/2, h/2, -thick2); glVertex3f ( w/2, -h/2, -thick2);
852 glNormal3f (1, 0, 0);
853 glVertex3f ( w/2, -h/2, -thick2); glVertex3f ( w/2, h/2, -thick2);
854 glVertex3f ( w/2, h/2, thick2); glVertex3f ( w/2, -h/2, thick2);
855 glNormal3f (0, 0, 1);
856 glVertex3f ( w/2, -h/2, thick2); glVertex3f ( w/2, h/2, thick2);
857 glVertex3f (-w/2, h/2, thick2); glVertex3f (-w/2, -h/2, thick2);
858 glNormal3f (-1, 0, 0);
859 glVertex3f (-w/2, -h/2, thick2); glVertex3f (-w/2, h/2, thick2);
860 glVertex3f (-w/2, h/2, -thick2); glVertex3f (-w/2, -h/2, -thick2);
866 for (th = 0; th < M_PI; th += (M_PI / 6))
868 pointsx0[npoints] = w/2 * cos(th);
869 pointsy0[npoints] = w/2 * sin(th);
874 /* front inside curve */
875 glNormal3f (0, 0, -1);
877 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
878 if (! wire) glVertex3f (0, h/2, -thick2);
879 for (i = 0; i < npoints; i++)
880 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
884 /* front outside curve */
886 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
887 if (! wire) glVertex3f (0, -h/2, -thick2);
888 for (i = 0; i < npoints; i++)
889 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
893 /* back inside curve */
894 glNormal3f (0, 0, 1);
896 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
897 if (! wire) glVertex3f (0, h/2, thick2);
898 for (i = 0; i < npoints; i++)
899 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
903 /* back outside curve */
905 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
906 if (! wire) glVertex3f (0, -h/2, thick2);
907 for (i = 0; i < npoints; i++)
908 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
914 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
915 for (i = 0; i < npoints; i++)
917 glNormal3f (pointsx0[i], pointsy0[i], 0);
918 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
919 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
926 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
927 for (i = 0; i < npoints; i++)
929 glNormal3f (pointsx0[i], -pointsy0[i], 0);
930 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
931 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
948 make_frame (logo_configuration *dc, int wire)
952 GLfloat x[20], y[20];
953 GLfloat corner_cut = 0.5;
956 glRotatef (90, 0, 1, 0);
957 glScalef (4 * dc->frame_size,
961 x[0] = -dc->frame_thickness;
962 x[1] = -dc->frame_thickness * corner_cut;
964 x[3] = 0.5 - dc->triangle_size;
966 x[5] = 0.5 + dc->triangle_size;
968 x[7] = 1 + dc->frame_thickness * corner_cut;
969 x[8] = 1 + dc->frame_thickness;
971 y[0] = -dc->frame_thickness;
972 y[1] = -dc->frame_thickness * corner_cut;
974 y[3] = dc->triangle_size;
978 glTranslatef (-0.5, -0.5, dc->frame_depth / 4);
980 for (j = 0; j <= 1; j++)
982 if (j) glTranslatef (0, 0, -dc->frame_depth / 2);
983 glFrontFace (j ? GL_CCW : GL_CW);
984 for (i = 0; i < 4; i++)
986 glNormal3f (0, 0, (j ? -1 : 1));
987 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
988 glVertex3f (x[0], y[1], 0); glVertex3f (x[0], y[2], 0);
989 glVertex3f (x[1], y[0], 0); glVertex3f (x[1], y[2], 0);
990 glVertex3f (x[3], y[0], 0); glVertex3f (x[3], y[2], 0);
991 glVertex3f (x[4], y[0], 0); glVertex3f (x[4], y[3], 0);
992 glVertex3f (x[5], y[0], 0); glVertex3f (x[5], y[2], 0);
993 glVertex3f (x[7], y[0], 0); glVertex3f (x[7], y[2], 0);
994 glVertex3f (x[8], y[1], 0); glVertex3f (x[8], y[2], 0);
997 glTranslatef (0.5, 0.5, 0);
998 glRotatef (90, 0, 0, 1);
999 glTranslatef (-0.5, -0.5, 0);
1005 glFrontFace (GL_CCW);
1006 for (i = 0; i < 4; i++)
1008 glNormal3f (0, 1, 0);
1009 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1010 glVertex3f (x[2], y[2], 0); glVertex3f (x[2], y[2], dc->frame_depth/2);
1011 glVertex3f (x[3], y[2], 0); glVertex3f (x[3], y[2], dc->frame_depth/2);
1012 glVertex3f (x[4], y[3], 0); glVertex3f (x[4], y[3], dc->frame_depth/2);
1013 glVertex3f (x[5], y[2], 0); glVertex3f (x[5], y[2], dc->frame_depth/2);
1014 glVertex3f (x[6], y[2], 0); glVertex3f (x[6], y[2], dc->frame_depth/2);
1018 glNormal3f (0, -1, 0);
1019 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1020 glVertex3f (x[7], y[0], 0);
1021 glVertex3f (x[7], y[0], dc->frame_depth/2);
1022 glVertex3f (x[1], y[0], dc->frame_depth/2);
1023 glVertex3f (x[1], y[0], 0);
1027 glNormal3f (1, -1, 0);
1028 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1029 glVertex3f (x[8], y[1], 0);
1030 glVertex3f (x[8], y[1], dc->frame_depth/2);
1031 glVertex3f (x[7], y[0], dc->frame_depth/2);
1032 glVertex3f (x[7], y[0], 0);
1038 glNormal3f (0, 1, 0);
1039 for (j = 0; j <= 1; j++)
1041 glBegin (GL_LINE_STRIP);
1042 glVertex3f (x[2], y[2], j*dc->frame_depth/2);
1043 glVertex3f (x[3], y[2], j*dc->frame_depth/2);
1044 glVertex3f (x[4], y[3], j*dc->frame_depth/2);
1045 glVertex3f (x[5], y[2], j*dc->frame_depth/2);
1046 glVertex3f (x[6], y[2], j*dc->frame_depth/2);
1052 glTranslatef (0.5, 0.5, 0);
1053 glRotatef (90, 0, 0, 1);
1054 glTranslatef (-0.5, -0.5, 0);
1063 /* Window management, etc
1066 reshape_logo (ModeInfo *mi, int width, int height)
1068 GLfloat h = (GLfloat) height / (GLfloat) width;
1070 glViewport (0, 0, (GLint) width, (GLint) height);
1072 glMatrixMode(GL_PROJECTION);
1074 gluPerspective (30.0, 1/h, 1.0, 100.0);
1076 glMatrixMode(GL_MODELVIEW);
1078 gluLookAt( 0.0, 0.0, 30.0,
1082 glClear(GL_COLOR_BUFFER_BIT);
1087 gl_init (ModeInfo *mi)
1089 /* logo_configuration *dc = &dcs[MI_SCREEN(mi)]; */
1090 int wire = MI_IS_WIREFRAME(mi);
1092 GLfloat position[] = {0, 0, 0, 0};
1093 GLfloat direction[] = {3, -1, -3};
1095 position[0] = -direction[0];
1096 position[1] = -direction[1];
1097 position[2] = -direction[2];
1101 glLightfv(GL_LIGHT0, GL_POSITION, position);
1102 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction);
1103 glShadeModel(GL_SMOOTH);
1104 glEnable(GL_NORMALIZE);
1105 glEnable(GL_CULL_FACE);
1106 glEnable(GL_LIGHTING);
1107 glEnable(GL_LIGHT0);
1108 glEnable(GL_DEPTH_TEST);
1114 init_logo (ModeInfo *mi)
1116 logo_configuration *dc;
1117 int do_gasket = get_boolean_resource(mi->dpy, "doGasket", "Boolean");
1118 int do_helix = get_boolean_resource(mi->dpy, "doHelix", "Boolean");
1119 int do_ladder = (do_helix &&
1120 get_boolean_resource(mi->dpy, "doLadder", "Boolean"));
1121 int do_frame = get_boolean_resource(mi->dpy, "doFrame", "Boolean");
1122 GLfloat helix_rot = 147.0;
1124 if (!do_gasket && !do_helix)
1126 fprintf (stderr, "%s: no helix or gasket?\n", progname);
1131 dcs = (logo_configuration *)
1132 calloc (MI_NUM_SCREENS(mi), sizeof (logo_configuration));
1134 fprintf(stderr, "%s: out of memory\n", progname);
1139 dc = &dcs[MI_SCREEN(mi)];
1141 if ((dc->glx_context = init_GL(mi)) != NULL) {
1143 reshape_logo (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1146 dc->wall_facets = get_integer_resource(mi->dpy, "wallFacets", "Integer");
1147 dc->bar_facets = get_integer_resource(mi->dpy, "barFacets", "Integer");
1148 dc->clockwise = get_boolean_resource(mi->dpy, "clockwise", "Boolean");
1149 dc->turns = get_float_resource(mi->dpy, "turns", "Float");
1150 dc->turn_spacing = get_float_resource(mi->dpy, "turnSpacing", "Float");
1151 dc->bar_spacing = get_float_resource(mi->dpy, "barSpacing", "Float");
1152 dc->wall_height = get_float_resource(mi->dpy, "wallHeight", "Float");
1153 dc->wall_thickness = get_float_resource(mi->dpy, "wallThickness", "Float");
1154 dc->bar_thickness = get_float_resource(mi->dpy, "barThickness", "Float");
1155 dc->wall_taper = get_float_resource(mi->dpy, "wallTaper", "Float");
1157 dc->gasket_size = get_float_resource(mi->dpy,"gasketSize", "Float");
1158 dc->gasket_depth = get_float_resource(mi->dpy,"gasketDepth", "Float");
1159 dc->gasket_thickness = get_float_resource(mi->dpy,"gasketThickness","Float");
1161 dc->frame_size = get_float_resource(mi->dpy, "frameSize", "Float");
1162 dc->frame_depth = get_float_resource(mi->dpy, "frameDepth", "Float");
1163 dc->frame_thickness = get_float_resource(mi->dpy, "frameThickness", "Float");
1164 dc->triangle_size = get_float_resource(mi->dpy, "triangleSize", "Float");
1166 dc->speed = get_float_resource(mi->dpy, "speed", "Float");
1171 char *color_name = get_string_resource (mi->dpy, "foreground", "Foreground");
1173 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
1174 if (*s2 == ' ' || *s2 == '\t')
1179 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
1181 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
1185 dc->color[0] = xcolor.red / 65535.0;
1186 dc->color[1] = xcolor.green / 65535.0;
1187 dc->color[2] = xcolor.blue / 65535.0;
1191 dc->trackball = gltrackball_init ();
1193 dc->gasket_spinnery.probability = 0.1;
1194 dc->gasket_spinnerx.probability = 0.1;
1195 dc->gasket_spinnerz.probability = 1.0;
1196 dc->helix_spinnerz.probability = 0.6;
1197 dc->scene_spinnerx.probability = 0.1;
1198 dc->scene_spinnery.probability = 0.0;
1199 dc->frame_spinner.probability = 5.0;
1201 /* start the frame off-screen */
1202 dc->frame_spinner.spinning_p = True;
1203 dc->frame_spinner.position = 0.3;
1204 dc->frame_spinner.speed = 0.001;
1206 if (dc->speed > 0) /* start off with the gasket in motion */
1208 dc->gasket_spinnerz.spinning_p = True;
1209 dc->gasket_spinnerz.speed = (0.002
1210 * ((random() & 1) ? 1 : -1)
1215 dc->helix_list = glGenLists (1);
1216 glNewList (dc->helix_list, GL_COMPILE);
1217 glRotatef(helix_rot, 0, 0, 1);
1218 if (do_ladder) dc->polys[0] += make_ladder (dc, 0, 0);
1219 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
1220 glRotatef(180, 0, 0, 1);
1221 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
1226 dc->helix_list_wire = glGenLists (1);
1227 glNewList (dc->helix_list_wire, GL_COMPILE);
1228 /* glRotatef(helix_rot, 0, 0, 1); wtf? */
1229 if (do_ladder) dc->polys[1] += make_ladder (dc, 1, 1);
1230 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
1231 glRotatef(180, 0, 0, 1);
1232 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
1237 dc->helix_list_facetted = glGenLists (1);
1238 glNewList (dc->helix_list_facetted, GL_COMPILE);
1239 glRotatef(helix_rot, 0, 0, 1);
1240 if (do_ladder) dc->polys[2] += make_ladder (dc, 1, 0);
1241 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
1242 glRotatef(180, 0, 0, 1);
1243 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
1247 dc->gasket_list = glGenLists (1);
1248 glNewList (dc->gasket_list, GL_COMPILE);
1249 if (do_gasket) dc->polys[3] += make_gasket (dc, 0);
1252 dc->gasket_list_wire = glGenLists (1);
1253 glNewList (dc->gasket_list_wire, GL_COMPILE);
1254 if (do_gasket) dc->polys[4] += make_gasket (dc, 1);
1257 dc->frame_list = glGenLists (1);
1258 glNewList (dc->frame_list, GL_COMPILE);
1259 if (do_frame) dc->polys[5] += make_frame (dc, 0);
1262 dc->frame_list_wire = glGenLists (1);
1263 glNewList (dc->frame_list_wire, GL_COMPILE);
1264 if (do_frame) dc->polys[6] += make_frame (dc, 1);
1267 /* When drawing both solid and wireframe objects,
1268 make sure the wireframe actually shows up! */
1269 glEnable (GL_POLYGON_OFFSET_FILL);
1270 glPolygonOffset (1.0, 1.0);
1275 logo_handle_event (ModeInfo *mi, XEvent *event)
1277 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
1279 if (event->xany.type == ButtonPress &&
1280 event->xbutton.button == Button1)
1282 dc->button_down_p = True;
1283 gltrackball_start (dc->trackball,
1284 event->xbutton.x, event->xbutton.y,
1285 MI_WIDTH (mi), MI_HEIGHT (mi));
1288 else if (event->xany.type == ButtonRelease &&
1289 event->xbutton.button == Button1)
1291 dc->button_down_p = False;
1294 else if (event->xany.type == ButtonPress &&
1295 (event->xbutton.button == Button4 ||
1296 event->xbutton.button == Button5 ||
1297 event->xbutton.button == Button6 ||
1298 event->xbutton.button == Button7))
1300 gltrackball_mousewheel (dc->trackball, event->xbutton.button, 10,
1301 !!event->xbutton.state);
1304 else if (event->xany.type == MotionNotify &&
1307 gltrackball_track (dc->trackball,
1308 event->xmotion.x, event->xmotion.y,
1309 MI_WIDTH (mi), MI_HEIGHT (mi));
1318 tick_spinner (ModeInfo *mi, spinner *s)
1320 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
1322 if (dc->speed == 0) return;
1323 if (dc->button_down_p) return;
1327 s->position += s->speed;
1328 if (s->position >= 1.0 || s->position <= -1.0)
1332 s->spinning_p = False;
1335 else if (s->probability &&
1336 (random() % (int) (PROBABILITY_SCALE / s->probability)) == 0)
1339 s->spinning_p = True;
1342 s->speed = dc->speed * (frand(ss/3) + frand(ss/3) + frand(ss/3));
1343 } while (s->speed <= 0);
1345 s->speed = -s->speed;
1351 link_spinners (ModeInfo *mi, spinner *s0, spinner *s1)
1353 if (s0->spinning_p && !s1->spinning_p)
1355 GLfloat op = s1->probability;
1356 s1->probability = PROBABILITY_SCALE;
1357 tick_spinner (mi, s1);
1358 s1->probability = op;
1364 draw_logo (ModeInfo *mi)
1366 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
1367 Display *dpy = MI_DISPLAY(mi);
1368 Window window = MI_WINDOW(mi);
1369 int wire = MI_IS_WIREFRAME(mi);
1371 GLfloat specular[] = {0.8, 0.8, 0.8, 1.0};
1372 GLfloat shininess = 50.0;
1374 if (!dc->glx_context)
1377 mi->polygon_count = 0;
1378 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(dc->glx_context));
1380 if (dc->wire_overlay == 0 &&
1381 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
1382 dc->wire_overlay = ((random() % 200) +
1386 tick_spinner (mi, &dc->gasket_spinnerx);
1387 tick_spinner (mi, &dc->gasket_spinnery);
1388 tick_spinner (mi, &dc->gasket_spinnerz);
1389 tick_spinner (mi, &dc->helix_spinnerz);
1390 tick_spinner (mi, &dc->scene_spinnerx);
1391 tick_spinner (mi, &dc->scene_spinnery);
1392 tick_spinner (mi, &dc->frame_spinner);
1393 link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery);
1395 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1401 glColor3f(dc->color[0], dc->color[1], dc->color[2]);
1403 /* Draw frame before trackball rotation */
1405 GLfloat p = (dc->frame_spinner.position >= 0
1406 ? dc->frame_spinner.position
1407 : -dc->frame_spinner.position);
1408 GLfloat size = (p > 0.5 ? 1-p : p);
1409 GLfloat scale = 1 + (size * 10);
1411 /* gltrackball_rotate (dc->trackball); */
1412 glRotatef(90, 1, 0, 0);
1413 glRotatef(90, 0, 0, 1);
1415 glScalef (1, scale, scale);
1418 glCallList (dc->frame_list_wire);
1419 mi->polygon_count += dc->polys[6];
1421 else if (dc->wire_overlay != 0)
1423 glCallList (dc->frame_list);
1424 glDisable (GL_LIGHTING);
1425 glCallList (dc->frame_list_wire);
1426 mi->polygon_count += dc->polys[6];
1427 if (!wire) glEnable (GL_LIGHTING);
1431 glCallList (dc->frame_list);
1432 mi->polygon_count += dc->polys[5];
1437 gltrackball_rotate (dc->trackball);
1439 glRotatef(90, 1, 0, 0);
1440 glRotatef(90, 0, 0, 1);
1442 glRotatef (360 * sin (M_PI/2 * dc->scene_spinnerx.position), 0, 1, 0);
1443 glRotatef (360 * sin (M_PI/2 * dc->scene_spinnery.position), 0, 0, 1);
1447 glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnerx.position), 0, 1, 0);
1448 glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnery.position), 0, 0, 1);
1449 glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnerz.position), 1, 0, 0);
1451 memcpy (gcolor, dc->color, sizeof (dc->color));
1452 if (dc->wire_overlay != 0)
1454 gcolor[0] = gcolor[1] = gcolor[2] = 0;
1455 specular[0] = specular[1] = specular[2] = 0;
1458 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
1459 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
1460 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shininess);
1464 glCallList (dc->gasket_list_wire);
1465 mi->polygon_count += dc->polys[4];
1467 else if (dc->wire_overlay != 0)
1469 glCallList (dc->gasket_list);
1470 glDisable (GL_LIGHTING);
1471 glCallList (dc->gasket_list_wire);
1472 mi->polygon_count += dc->polys[4];
1473 if (!wire) glEnable (GL_LIGHTING);
1477 glCallList (dc->gasket_list);
1478 mi->polygon_count += dc->polys[3];
1483 glRotatef (360 * sin (M_PI/2 * dc->helix_spinnerz.position), 0, 0, 1);
1487 glCallList (dc->helix_list_wire);
1488 mi->polygon_count += dc->polys[1];
1490 else if (dc->wire_overlay != 0)
1492 glCallList (dc->helix_list_facetted);
1493 glDisable (GL_LIGHTING);
1494 glCallList (dc->helix_list_wire);
1495 mi->polygon_count += dc->polys[2];
1496 if (!wire) glEnable (GL_LIGHTING);
1500 glCallList (dc->helix_list);
1501 mi->polygon_count += dc->polys[0];
1506 if (dc->wire_overlay > 0)
1509 if (mi->fps_p) do_fps (mi);
1512 glXSwapBuffers(dpy, window);
1515 XSCREENSAVER_MODULE_2 ("DNAlogo", dnalogo, logo)