1 /* DNA Logo, Copyright (c) 2001-2011 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" \
50 ".foreground: #00AA00 \n" \
51 "*geometry: =640x640\n" \
53 # define refresh_logo 0
54 # define release_logo 0
56 #define countof(x) (sizeof((x))/sizeof((*x)))
58 #ifdef DXF_OUTPUT_HACK /* When this is defined, instead of rendering
59 to the screen, we write a DXF CAD file to stdout.
60 This is a kludge of shocking magnitude...
61 Maybe there's some other way to intercept all
62 glVertex3f calls than with a #define? */
63 # define unit_tube dxf_unit_tube
64 # define unit_cone dxf_unit_cone
65 # define tube_1 dxf_tube_1
66 # define tube dxf_tube
67 # define cone dxf_cone
68 #endif /* DXF_OUTPUT_HACK */
70 #include "xlockmore.h"
74 #include "gltrackball.h"
76 #ifdef USE_GL /* whole file */
80 GLfloat position; /* 0.0 - 1.0 */
81 GLfloat speed; /* how far along the path (may be negative) */
82 GLfloat probability; /* relative likelyhood to start spinning */
86 GLXContext *glx_context;
88 GLuint helix_list, helix_list_wire, helix_list_facetted;
89 GLuint pizza_list, pizza_list_wire, pizza_list_facetted;
90 GLuint gasket_list, gasket_list_wire;
91 GLuint frame_list, frame_list_wire;
100 GLfloat turn_spacing;
103 GLfloat wall_thickness;
104 GLfloat bar_thickness;
108 GLfloat gasket_depth;
109 GLfloat gasket_thickness;
113 GLfloat frame_thickness;
114 GLfloat triangle_size;
119 spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz;
120 spinner scene_spinnerx, scene_spinnery;
121 spinner helix_spinnery, helix_spinnerz;
122 spinner frame_spinner;
124 trackball_state *trackball;
127 int wire_overlay; /* frame countdown */
129 } logo_configuration;
131 static logo_configuration *dcs = NULL;
133 static XrmOptionDescRec opts[] = {
134 { "-speed", ".speed", XrmoptionSepArg, 0 },
135 { "-pizza", ".pizza", XrmoptionNoArg, "True" },
138 ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
140 #define PROBABILITY_SCALE 600
143 #ifdef DXF_OUTPUT_HACK
145 # define glBegin dxf_glBegin
146 # define glVertex3f dxf_glVertex3f
147 # define glVertex3dv dxf_glVertex3dv
148 # define glEnd dxf_glEnd
149 # define glVertexPointer dxf_glVertexPointer
150 # define glDrawArrays dxf_glDrawArrays
152 static int dxf_type, dxf_point, dxf_point_total, dxf_layer, dxf_color;
153 static GLfloat dxf_quads[4*4];
156 dxf_glBegin (int type)
164 dxf_glVertex3f (GLfloat ox, GLfloat oy, GLfloat oz)
170 /* Transform the point into modelview space. */
171 glGetFloatv (GL_MODELVIEW_MATRIX, m);
172 x = ox * m[0] + oy * m[4] + oz * m[8] + m[12];
173 y = ox * m[1] + oy * m[5] + oz * m[9] + m[13];
174 z = ox * m[2] + oy * m[6] + oz * m[10] + m[14];
176 dxf_quads[dxf_point*3+0] = x;
177 dxf_quads[dxf_point*3+1] = y;
178 dxf_quads[dxf_point*3+2] = z;
184 if (dxf_point < 4) return;
186 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
187 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
188 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
189 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
191 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
192 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
193 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
195 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
196 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
197 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
199 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]);
200 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
201 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
206 if (dxf_point < 4) return;
208 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
209 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
210 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
211 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
213 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
214 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
215 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
217 fprintf (stdout, "12\n%.6f\n", dxf_quads[i+3]); /* funky quad strip */
218 fprintf (stdout, "22\n%.6f\n", dxf_quads[i+4]); /* vert order: 1243. */
219 fprintf (stdout, "32\n%.6f\n", dxf_quads[i+5]);
221 fprintf (stdout, "13\n%.6f\n", dxf_quads[i]);
222 fprintf (stdout, "23\n%.6f\n", dxf_quads[i+1]);
223 fprintf (stdout, "33\n%.6f\n", dxf_quads[i+2]);
226 dxf_quads[0] = dxf_quads[6]; /* copy point 3 to pos 1 */
227 dxf_quads[1] = dxf_quads[7];
228 dxf_quads[2] = dxf_quads[8];
229 dxf_quads[3] = dxf_quads[9]; /* copy point 4 to pos 2 */
230 dxf_quads[4] = dxf_quads[10];
231 dxf_quads[5] = dxf_quads[11];
232 dxf_point = 2; /* leave those two points in queue */
236 case GL_TRIANGLE_FAN:
237 if (dxf_point < 3) return;
239 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
240 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
241 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
242 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
244 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
245 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
246 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
248 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
249 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
250 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
253 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
254 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
255 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
258 if (dxf_type == GL_TRIANGLE_FAN)
260 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to point 2 */
261 dxf_quads[4] = dxf_quads[7];
262 dxf_quads[5] = dxf_quads[8];
263 dxf_point = 2; /* leave two points in queue */
267 case GL_TRIANGLE_STRIP:
268 if (dxf_point < 3) return;
270 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
272 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
273 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
274 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
276 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
277 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
278 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
280 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
281 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
282 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
285 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
286 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
287 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
289 dxf_quads[0] = dxf_quads[3]; /* copy point 2 to pos 1 */
290 dxf_quads[1] = dxf_quads[4];
291 dxf_quads[2] = dxf_quads[5];
292 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to pos 2 */
293 dxf_quads[4] = dxf_quads[7];
294 dxf_quads[5] = dxf_quads[8];
295 dxf_point = 2; /* leave those two points in queue */
302 if (dxf_point_total == 1)
309 if (dxf_point < 2) return;
311 fprintf (stdout, "0\nLINE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
313 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
314 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
315 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
317 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
318 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
319 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
322 if (dxf_type != GL_LINES)
324 dxf_quads[0] = dxf_quads[3];
325 dxf_quads[1] = dxf_quads[4];
326 dxf_quads[2] = dxf_quads[5];
339 dxf_glVertex3dv (const GLdouble *v)
341 glVertex3f (v[0], v[1], v[2]);
348 if (dxf_type == GL_LINE_LOOP) /* close loop */
349 glVertex3f (dxf_quads[6], dxf_quads[7], dxf_quads[8]);
359 fprintf (stdout, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n");
360 fprintf (stdout, "0\nSECTION\n2\nENTITIES\n");
366 fprintf (stdout, "0\nENDSEC\n0\nEOF\n");
371 static const GLvoid *dxf_vp;
372 static GLsizei dxf_vp_size;
373 static GLsizei dxf_vp_stride;
376 dxf_glVertexPointer (GLint size, GLenum type, GLsizei stride,
377 const GLvoid *pointer)
379 if (type != GL_FLOAT) abort();
380 if (stride <= 0) abort();
383 dxf_vp_stride = stride;
387 dxf_glDrawArrays (GLenum mode, GLint first, GLsizei count)
390 unsigned char *a = (unsigned char *) dxf_vp;
392 for (i = first; i < first+count; i++)
394 GLfloat *fa = (GLfloat *) a;
395 dxf_glVertex3f (fa[0], fa[1], fa[2]);
402 # define XYZ tube_XYZ /* avoid conflict with normals.h */
403 # include "tube.c" /* Yes, I really am including a C file. */
406 #endif /* DXF_OUTPUT_HACK */
410 /* Calculate the angle (in degrees) between two vectors.
413 vector_angle (double ax, double ay, double az,
414 double bx, double by, double bz)
416 double La = sqrt (ax*ax + ay*ay + az*az);
417 double Lb = sqrt (bx*bx + by*by + bz*bz);
420 if (La == 0 || Lb == 0) return 0;
421 if (ax == bx && ay == by && az == bz) return 0;
423 /* dot product of two vectors is defined as:
424 La * Lb * cos(angle between vectors)
425 and is also defined as:
426 ax*bx + ay*by + az*bz
428 La * Lb * cos(angle) = ax*bx + ay*by + az*bz
429 cos(angle) = (ax*bx + ay*by + az*bz) / (La * Lb)
430 angle = acos ((ax*bx + ay*by + az*bz) / (La * Lb));
432 cc = (ax*bx + ay*by + az*bz) / (La * Lb);
433 if (cc > 1) cc = 1; /* avoid fp rounding error (1.000001 => sqrt error) */
436 return (angle * M_PI / 180);
444 make_helix (logo_configuration *dc, int facetted, int wire)
447 int wall_facets = dc->wall_facets / (facetted ? 10 : 1);
449 GLfloat max_th = M_PI * 2 * dc->turns;
450 GLfloat th_inc = M_PI * 2 / wall_facets;
452 GLfloat x1=0, y1=0, x2=0, y2=0;
453 GLfloat x1b=0, y1b=0, x2b=0, y2b=0;
456 GLfloat h1off=0, h2off=0;
457 GLfloat z_inc = dc->turn_spacing / wall_facets;
462 x1b = 1 - dc->wall_thickness;
465 z1 = -(dc->turn_spacing * dc->turns / 2);
467 h1 = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2);
468 h1off = (dc->wall_taper > 0 ? -dc->wall_height / 2 : 0);
471 z1 = -z1, z_inc = -z_inc, h1off = -h1off;
480 nx = cos (th + M_PI/2);
481 ny = sin (th + M_PI/2);
482 glNormal3f(nx, ny, 0);
483 glVertex3f( x1, y1, z1 - h1 + h1off);
484 glVertex3f( x1, y1, z1 + h1 + h1off);
485 glVertex3f(x1b, y1b, z1 + h1 + h1off);
486 glVertex3f(x1b, y1b, z1 - h1 + h1off);
491 while (th + th_inc <= max_th)
498 x2b = x2 * (1 - dc->wall_thickness);
499 y2b = y2 * (1 - dc->wall_thickness);
504 if (dc->wall_taper > 0)
507 if (th < dc->wall_taper)
509 h2 = dc->wall_height/2 * cos (M_PI / 2
510 * (1 - (th / dc->wall_taper)));
512 h2off = h2 - dc->wall_height/2;
514 h2off = dc->wall_height/2 - h2;
516 else if (th >= max_th - dc->wall_taper)
518 if (th + th_inc > max_th) /* edge case: always come to a point */
521 h2 = dc->wall_height/2 * cos (M_PI / 2
522 * (1 - ((max_th - th)
525 h2off = dc->wall_height/2 - h2;
527 h2off = h2 - dc->wall_height/2;
534 glBegin(wire ? GL_LINES : GL_QUADS);
535 glNormal3f(x1, y1, 0);
536 glVertex3f(x1, y1, z1 - h1 + h1off);
537 glVertex3f(x1, y1, z1 + h1 + h1off);
538 glNormal3f(x2, y2, 0);
539 glVertex3f(x2, y2, z2 + h2 + h2off);
540 glVertex3f(x2, y2, z2 - h2 + h2off);
547 glBegin(wire ? GL_LINES : GL_QUADS);
548 glNormal3f(-x1b, -y1b, 0);
549 glVertex3f( x1b, y1b, z1 - h1 + h1off);
550 glVertex3f( x1b, y1b, z1 + h1 + h1off);
551 glNormal3f(-x2b, -y2b, 0);
552 glVertex3f( x2b, y2b, z2 + h2 + h2off);
553 glVertex3f( x2b, y2b, z2 - h2 + h2off);
560 /* glNormal3f(0, 0, 1);*/
561 do_normal (x2, y2, z2 + h2 + h2off,
562 x2b, y2b, z2 + h2 + h2off,
563 x1b, y1b, z1 + h1 + h1off);
564 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
565 glVertex3f( x2, y2, z2 + h2 + h2off);
566 glVertex3f( x2b, y2b, z2 + h2 + h2off);
567 glVertex3f( x1b, y1b, z1 + h1 + h1off);
568 glVertex3f( x1, y1, z1 + h1 + h1off);
575 do_normal ( x1, y1, z1 - h1 + h1off,
576 x1b, y1b, z1 - h1 + h1off,
577 x2b, y2b, z2 - h2 + h2off);
578 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
579 glNormal3f(0, 0, -1);
580 glVertex3f( x1, y1, z1 - h1 + h1off);
581 glVertex3f( x1b, y1b, z1 - h1 + h1off);
582 glVertex3f( x2b, y2b, z2 - h2 + h2off);
583 glVertex3f( x2, y2, z2 - h2 + h2off);
603 nx = cos (th + M_PI/2);
604 ny = sin (th + M_PI/2);
605 glNormal3f(nx, ny, 0);
606 glVertex3f(x2, y2, z1 - h2 + h2off);
607 glVertex3f(x2, y2, z1 + h2 + h2off);
608 glVertex3f(x2b, y2b, z1 + h2 + h2off);
609 glVertex3f(x2b, y2b, z1 - h2 + h2off);
618 make_ladder (logo_configuration *dc, int facetted, int wire)
622 GLfloat max_th = dc->turns * M_PI * 2;
623 GLfloat max_z = dc->turns * dc->turn_spacing;
624 GLfloat z_inc = dc->bar_spacing;
625 GLfloat th_inc = M_PI * 2 * (dc->bar_spacing / dc->turn_spacing);
628 /* skip forward to center the bars in the helix... */
630 GLfloat usable_th = max_th - dc->wall_taper;
631 GLfloat usable_z = max_z / (max_th / usable_th);
632 int nbars = usable_z / dc->bar_spacing;
633 GLfloat used_z, pad_z, pad_ratio;
635 if (! (nbars & 1)) nbars--; /* always an odd number of bars */
637 used_z = (nbars - 1) * dc->bar_spacing;
638 pad_z = max_z - used_z;
639 pad_ratio = pad_z / max_z;
641 th = (max_th * pad_ratio/2);
642 z = -(max_z / 2) + (max_z * pad_ratio/2);
645 z = -z, z_inc = -z_inc;
648 for (i = 0; i < nbars; i++)
650 int facets = dc->bar_facets / (facetted ? 14 : 1);
651 if (facets <= 3) facets = 3;
652 x = cos (th) * (1 - dc->wall_thickness);
653 y = sin (th) * (1 - dc->wall_thickness);
654 polys += tube ( x, y, z,
656 dc->bar_thickness, 0, facets,
671 make_gasket (logo_configuration *dc, int wire)
679 GLfloat d2r = M_PI / 180;
681 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 2;
683 GLfloat *pointsx0, *pointsy0, *pointsx1, *pointsy1, *normals;
685 GLfloat r0 = 0.750; /* 395 */
686 GLfloat r1a = 0.825; /* bottom of wall below upper left hole */
687 GLfloat r1b = 0.867; /* center of upper left hole */
688 GLfloat r1c = 0.909; /* top of wall above hole */
689 GLfloat r1 = 0.916; /* 471 */
690 GLfloat r2 = 0.963; /* 490 */
691 GLfloat r3 = 0.960; /* 499 */
692 GLfloat r4 = 1.000; /* 507 */
693 GLfloat r5 = 1.080; /* 553 */
695 GLfloat ctrl_r[100], ctrl_th[100];
699 # ifdef DXF_OUTPUT_HACK
700 if (! wire) res *= 8;
703 # define POINT(r,th) \
704 ctrl_r [nctrls] = r, \
705 ctrl_th[nctrls] = (th * d2r), \
708 POINT (0.829, 0); /* top indentation, right half */
716 POINT (r4, 4.0); /* moving clockwise... */
737 POINT (r4, 316.8); /* upper left indentation */
738 POINT (0.990, 316.87);
739 POINT (0.880, 317.21);
740 POINT (0.872, 317.45);
741 POINT (0.869, 317.80);
742 POINT (0.867, 318.10);
744 POINT (0.867, 318.85);
745 POINT (0.869, 319.15);
746 POINT (0.872, 319.50);
747 POINT (0.880, 319.74);
748 POINT (0.990, 320.08);
753 POINT (r1a, 338.0); /* cut-out disc */
759 POINT (0.872, 356.05); /* top indentation, left half */
760 POINT (0.862, 356.19);
761 POINT (0.851, 356.70);
762 POINT (0.841, 357.35);
763 POINT (0.835, 358.19);
764 POINT (0.831, 359.15);
768 points_size = res + (nctrls * 2);
769 pointsx0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
770 pointsy0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
771 pointsx1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
772 pointsy1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
773 normals = (GLfloat *) malloc (points_size * sizeof(GLfloat) * 2);
776 for (i = 1; i < nctrls; i++)
778 GLfloat from_r = ctrl_r [i-1];
779 GLfloat from_th = ctrl_th[i-1];
780 GLfloat to_r = ctrl_r [i];
781 GLfloat to_th = ctrl_th[i];
783 GLfloat step = 2*M_PI / res;
784 int nsteps = 1 + ((to_th - from_th) / step);
787 for (j = 0; j < nsteps + (i == nctrls-1); j++)
789 GLfloat r = from_r + (j * (to_r - from_r) / nsteps);
790 GLfloat th = from_th + (j * (to_th - from_th) / nsteps);
792 GLfloat cth = cos(th) * dc->gasket_size;
793 GLfloat sth = sin(th) * dc->gasket_size;
795 pointsx0[npoints] = r0 * cth; /* inner ring */
796 pointsy0[npoints] = r0 * sth;
797 pointsx1[npoints] = r * cth; /* outer ring */
798 pointsy1[npoints] = r * sth;
801 if (npoints >= points_size) abort();
805 /* normals for the outer ring */
806 for (i = 1; i < npoints; i++)
817 n = calc_normal (a, b, c);
818 normals[(i-1)*2 ] = n.x;
819 normals[(i-1)*2+1] = n.y;
822 glRotatef(-90, 0, 1, 0);
823 glRotatef(180, 0, 0, 1);
828 for (z = -thick2; z <= thick2; z += thick2*2)
832 glBegin (GL_LINE_LOOP);
833 for (i = 0; i < npoints; i++)
834 glVertex3f (pointsx0[i], pointsy0[i], z);
839 glBegin (GL_LINE_LOOP);
840 for (i = 0; i < npoints; i++)
841 glVertex3f (pointsx1[i], pointsy1[i], z);
845 for (i = 1; i < npoints; i++)
847 glBegin (GL_LINE_STRIP);
848 glVertex3f (pointsx0[i-1], pointsy0[i-1], z);
849 glVertex3f (pointsx0[i ], pointsy0[i ], z);
850 glVertex3f (pointsx1[i ], pointsy1[i ], z);
851 glVertex3f (pointsx1[i-1], pointsy1[i-1], z);
859 for (i = 0; i < npoints; i++)
862 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
863 glVertex3f (pointsx0[i], pointsy0[i], thick2);
865 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
866 glVertex3f (pointsx1[i], pointsy1[i], thick2);
876 glNormal3f(0, 0, -1);
877 glBegin (GL_QUAD_STRIP);
878 for (i = 0; i < npoints; i++)
880 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
881 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
889 glBegin (GL_QUAD_STRIP);
890 for (i = 0; i < npoints; i++)
892 glVertex3f (pointsx0[i], pointsy0[i], thick2);
893 glVertex3f (pointsx1[i], pointsy1[i], thick2);
900 glBegin (GL_QUAD_STRIP);
901 for (i = 0; i < npoints; i++)
903 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
904 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
905 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
914 for (i = 0; i < npoints-1; i++)
916 int ia = (i == 0 ? npoints-2 : i-1);
917 int iz = (i == npoints-2 ? 0 : i+1);
918 GLfloat x = pointsx1[i];
919 GLfloat y = pointsy1[i];
920 GLfloat xz = pointsx1[iz];
921 GLfloat yz = pointsy1[iz];
923 GLfloat nxa = normals[ia*2]; /* normal of [i-1 - i] face */
924 GLfloat nya = normals[ia*2+1];
925 GLfloat nx = normals[i*2]; /* normal of [i - i+1] face */
926 GLfloat ny = normals[i*2+1];
927 GLfloat nxz = normals[iz*2]; /* normal of [i+1 - i+2] face */
928 GLfloat nyz = normals[iz*2+1];
930 GLfloat anglea = vector_angle (nx, ny, 0, nxa, nya, 0);
931 GLfloat anglez = vector_angle (nx, ny, 0, nxz, nyz, 0);
932 GLfloat pointy = 0.005;
936 glNormal3f (nx, ny, 0);
937 glVertex3f (x, y, thick2);
938 glVertex3f (x, y, -thick2);
942 glNormal3f ((nxa + nx) / 2, (nya + ny) / 2, 0);
943 glVertex3f (x, y, thick2);
944 glVertex3f (x, y, -thick2);
949 glNormal3f (nx, ny, 0);
950 glVertex3f (xz, yz, -thick2);
951 glVertex3f (xz, yz, thick2);
955 glNormal3f ((nx + nxz) / 2, (ny + nyz) / 2, 0);
956 glVertex3f (xz, yz, -thick2);
957 glVertex3f (xz, yz, thick2);
965 /* Fill in the upper left hole...
972 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
973 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
975 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
976 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
980 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
981 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
983 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
984 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
989 glNormal3f (0, 0, -1);
991 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
992 glVertex3f (pointsx0[0], pointsy0[0], -thick2);
993 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
994 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
995 glVertex3f (pointsx0[2], pointsy0[2], -thick2);
1000 glNormal3f (0, 0, 1);
1001 glFrontFace(GL_CCW);
1002 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1003 glVertex3f (pointsx0[0], pointsy0[0], thick2);
1004 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1005 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1006 glVertex3f (pointsx0[2], pointsy0[2], thick2);
1013 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1014 glNormal3f (pointsx0[1], pointsy0[1], 0);
1015 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1016 glNormal3f (pointsx0[3], pointsy0[3], 0);
1017 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1018 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1019 glNormal3f (pointsx0[1], pointsy0[1], 0);
1020 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1025 /* Now make a donut.
1028 int nsteps = (wire ? 12 : 64);
1031 GLfloat th, cth, sth;
1035 th = ((339.0 + 343.0) / 2) * d2r;
1037 glTranslatef (r1b * cos(th) * dc->gasket_size,
1038 r1b * sin(th) * dc->gasket_size,
1042 for (i = 0; i < nsteps; i++)
1044 th = 2 * M_PI * i / nsteps;
1045 cth = cos (th) * dc->gasket_size;
1046 sth = sin (th) * dc->gasket_size;
1047 pointsx0[npoints] = r0 * cth;
1048 pointsy0[npoints] = r0 * sth;
1049 pointsx1[npoints] = r1 * cth;
1050 pointsy1[npoints] = r1 * sth;
1055 pointsx0[npoints] = pointsx0[0];
1056 pointsy0[npoints] = pointsy0[0];
1057 pointsx1[npoints] = pointsx1[0];
1058 pointsy1[npoints] = pointsy1[0];
1063 glBegin (GL_LINE_LOOP);
1064 for (i = 0; i < npoints; i++)
1065 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1068 glBegin (GL_LINE_LOOP);
1069 for (i = 0; i < npoints; i++)
1070 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1074 glBegin (GL_LINE_LOOP);
1075 for (i = 0; i < npoints; i++)
1076 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1079 glBegin (GL_LINE_LOOP);
1080 for (i = 0; i < npoints; i++)
1081 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1090 glNormal3f(0, 0, -1);
1091 glBegin (GL_QUAD_STRIP);
1092 for (i = 0; i < npoints; i++)
1094 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1095 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1101 glFrontFace(GL_CCW);
1102 glNormal3f(0, 0, 1);
1103 glBegin (GL_QUAD_STRIP);
1104 for (i = 0; i < npoints; i++)
1106 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1107 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1115 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1116 for (i = 0; i < npoints; i++)
1118 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
1119 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
1120 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
1130 /* Attach the bottom-right dingus...
1137 glRotatef (49.5, 0, 0, 1);
1138 glScalef (dc->gasket_size, dc->gasket_size, 1);
1139 glTranslatef (0, (r0+r1)/2, 0);
1144 glFrontFace(GL_CCW);
1145 glBegin (wire ? GL_LINE_STRIP : GL_QUADS);
1146 glNormal3f (0, 0, -1);
1147 glVertex3f (-w/2, -h/2, -thick2); glVertex3f (-w/2, h/2, -thick2);
1148 glVertex3f ( w/2, h/2, -thick2); glVertex3f ( w/2, -h/2, -thick2);
1149 glNormal3f (1, 0, 0);
1150 glVertex3f ( w/2, -h/2, -thick2); glVertex3f ( w/2, h/2, -thick2);
1151 glVertex3f ( w/2, h/2, thick2); glVertex3f ( w/2, -h/2, thick2);
1152 glNormal3f (0, 0, 1);
1153 glVertex3f ( w/2, -h/2, thick2); glVertex3f ( w/2, h/2, thick2);
1154 glVertex3f (-w/2, h/2, thick2); glVertex3f (-w/2, -h/2, thick2);
1155 glNormal3f (-1, 0, 0);
1156 glVertex3f (-w/2, -h/2, thick2); glVertex3f (-w/2, h/2, thick2);
1157 glVertex3f (-w/2, h/2, -thick2); glVertex3f (-w/2, -h/2, -thick2);
1163 for (th = (wire ? 0 : -0.1);
1165 th += (M_PI / (wire ? 5 : 32)))
1167 pointsx0[npoints] = w/2 * cos(th);
1168 pointsy0[npoints] = w/2 * sin(th);
1173 /* front inside curve */
1174 glNormal3f (0, 0, -1);
1176 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1177 if (! wire) glVertex3f (0, h/2, -thick2);
1178 for (i = 0; i < npoints; i++)
1179 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1183 /* front outside curve */
1184 glFrontFace(GL_CCW);
1185 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1186 if (! wire) glVertex3f (0, -h/2, -thick2);
1187 for (i = 0; i < npoints; i++)
1188 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1192 /* back inside curve */
1193 glNormal3f (0, 0, 1);
1194 glFrontFace(GL_CCW);
1195 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1196 if (! wire) glVertex3f (0, h/2, thick2);
1197 for (i = 0; i < npoints; i++)
1198 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1202 /* back outside curve */
1204 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1205 if (! wire) glVertex3f (0, -h/2, thick2);
1206 for (i = 0; i < npoints; i++)
1207 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1212 glFrontFace(GL_CCW);
1213 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1214 for (i = 0; i < npoints; i++)
1216 glNormal3f (pointsx0[i], pointsy0[i], 0);
1217 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1218 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1225 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1226 for (i = 0; i < npoints; i++)
1228 glNormal3f (pointsx0[i], -pointsy0[i], 0);
1229 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1230 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1247 make_frame (logo_configuration *dc, int wire)
1251 GLfloat x[20], y[20];
1252 GLfloat corner_cut = 0.5;
1255 glRotatef (90, 0, 1, 0);
1256 glScalef (4 * dc->frame_size,
1258 4 * dc->frame_size);
1260 x[0] = -dc->frame_thickness;
1261 x[1] = -dc->frame_thickness * corner_cut;
1263 x[3] = 0.5 - dc->triangle_size;
1265 x[5] = 0.5 + dc->triangle_size;
1267 x[7] = 1 + dc->frame_thickness * corner_cut;
1268 x[8] = 1 + dc->frame_thickness;
1270 y[0] = -dc->frame_thickness;
1271 y[1] = -dc->frame_thickness * corner_cut;
1273 y[3] = dc->triangle_size;
1277 glTranslatef (-0.5, -0.5, dc->frame_depth / 4);
1279 for (j = 0; j <= 1; j++)
1281 if (j) glTranslatef (0, 0, -dc->frame_depth / 2);
1282 glFrontFace (j ? GL_CCW : GL_CW);
1283 for (i = 0; i < 4; i++)
1285 glNormal3f (0, 0, (j ? -1 : 1));
1286 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1287 glVertex3f (x[0], y[1], 0); glVertex3f (x[0], y[2], 0);
1288 glVertex3f (x[1], y[0], 0); glVertex3f (x[1], y[2], 0);
1289 glVertex3f (x[3], y[0], 0); glVertex3f (x[3], y[2], 0);
1290 glVertex3f (x[4], y[0], 0); glVertex3f (x[4], y[3], 0);
1291 glVertex3f (x[5], y[0], 0); glVertex3f (x[5], y[2], 0);
1292 glVertex3f (x[7], y[0], 0); glVertex3f (x[7], y[2], 0);
1293 glVertex3f (x[8], y[1], 0); glVertex3f (x[8], y[2], 0);
1296 glTranslatef (0.5, 0.5, 0);
1297 glRotatef (90, 0, 0, 1);
1298 glTranslatef (-0.5, -0.5, 0);
1304 glFrontFace (GL_CCW);
1305 for (i = 0; i < 4; i++)
1307 glNormal3f (0, 1, 0);
1308 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1309 glVertex3f (x[2], y[2], 0); glVertex3f (x[2], y[2], dc->frame_depth/2);
1310 glVertex3f (x[3], y[2], 0); glVertex3f (x[3], y[2], dc->frame_depth/2);
1311 glVertex3f (x[4], y[3], 0); glVertex3f (x[4], y[3], dc->frame_depth/2);
1312 glVertex3f (x[5], y[2], 0); glVertex3f (x[5], y[2], dc->frame_depth/2);
1313 glVertex3f (x[6], y[2], 0); glVertex3f (x[6], y[2], dc->frame_depth/2);
1317 glNormal3f (0, -1, 0);
1318 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1319 glVertex3f (x[7], y[0], 0);
1320 glVertex3f (x[7], y[0], dc->frame_depth/2);
1321 glVertex3f (x[1], y[0], dc->frame_depth/2);
1322 glVertex3f (x[1], y[0], 0);
1326 glNormal3f (1, -1, 0);
1327 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1328 glVertex3f (x[8], y[1], 0);
1329 glVertex3f (x[8], y[1], dc->frame_depth/2);
1330 glVertex3f (x[7], y[0], dc->frame_depth/2);
1331 glVertex3f (x[7], y[0], 0);
1337 glNormal3f (0, 1, 0);
1338 for (j = 0; j <= 1; j++)
1340 glBegin (GL_LINE_STRIP);
1341 glVertex3f (x[2], y[2], j*dc->frame_depth/2);
1342 glVertex3f (x[3], y[2], j*dc->frame_depth/2);
1343 glVertex3f (x[4], y[3], j*dc->frame_depth/2);
1344 glVertex3f (x[5], y[2], j*dc->frame_depth/2);
1345 glVertex3f (x[6], y[2], j*dc->frame_depth/2);
1351 glTranslatef (0.5, 0.5, 0);
1352 glRotatef (90, 0, 0, 1);
1353 glTranslatef (-0.5, -0.5, 0);
1371 tess_error_cb (GLenum errorCode)
1373 fprintf (stderr, "%s: tesselation error: %s\n",
1374 progname, gluErrorString(errorCode));
1379 tess_combine_cb (GLdouble coords[3], GLdouble *d[4], GLfloat w[4],
1380 GLdouble **data_out)
1382 GLdouble *new = (GLdouble *) malloc (3 * sizeof(*new));
1391 tess_vertex_cb (void *vertex_data, void *closure)
1393 tess_out *to = (tess_out *) closure;
1394 GLdouble *v = (GLdouble *) vertex_data;
1395 to->points[to->i++] = v[0];
1396 to->points[to->i++] = v[1];
1397 to->points[to->i++] = v[2];
1401 tess_begin_cb (GLenum which)
1414 make_pizza (logo_configuration *dc, int facetted, int wire)
1418 int topfaces = (facetted ? 48 : 120);
1419 int discfaces = (facetted ? 12 : 120);
1420 int npoints = topfaces * 2 + 100;
1421 GLdouble *points = (GLdouble *) calloc (npoints * 3, sizeof(GLdouble));
1423 GLdouble *holes = (GLdouble *) calloc (topfaces*nholes*3, sizeof(GLdouble));
1425 GLfloat step = M_PI * 2 / 6 / topfaces;
1426 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 4;
1427 GLfloat th, x, y, s;
1429 tess_out TO, *to = &TO;
1430 GLUtesselator *tess = gluNewTess();
1434 to->points = (GLdouble *) calloc (topfaces * 20, sizeof(GLdouble));
1438 # ifndef _GLUfuncptr
1439 # define _GLUfuncptr void(*)(void)
1442 gluTessCallback(tess,GLU_TESS_BEGIN, (_GLUfuncptr)tess_begin_cb);
1443 gluTessCallback(tess,GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv);
1444 gluTessCallback(tess,GLU_TESS_END, (_GLUfuncptr)tess_end_cb);
1445 gluTessCallback(tess,GLU_TESS_COMBINE, (_GLUfuncptr)tess_combine_cb);
1446 gluTessCallback(tess,GLU_TESS_ERROR, (_GLUfuncptr)tess_error_cb);
1448 gluTessProperty (tess, GLU_TESS_BOUNDARY_ONLY, wire);
1449 gluTessProperty (tess,GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
1454 glRotatef (180, 0, 0, 1);
1456 glRotatef (90, 0, 1, 0);
1457 glTranslatef (-0.53, 0, 0);
1458 glRotatef (-30, 0, 0, 1);
1460 /* Compute the wedge */
1473 for (i = 0; i < countof(edge)/2; i++)
1475 points[j++] = edge[i*2+1];
1476 points[j++] = edge[i*2];
1482 s = 0.798; /* radius of end of slice, before crust gap */
1483 for (i = 0; i < topfaces; i++)
1485 points[j++] = cos(th) * s;
1486 points[j++] = sin(th) * s;
1503 for (i = 0; i < countof(edge)/2; i++)
1505 points[j++] = edge[i*2+1];
1506 points[j++] = edge[i*2];
1513 /* Draw the rim of the slice */
1514 glBegin (wire ? GL_LINES : GL_QUADS);
1517 for (i = (wire ? 0 : 1); i < endpoints; i++)
1519 GLdouble *p = points + (i*3);
1521 do_normal (p[0], p[1], -thick2,
1526 glVertex3f (x, y, -thick2);
1527 glVertex3f (x, y, thick2);
1529 glVertex3f (p[0], p[1], thick2);
1530 glVertex3f (p[0], p[1], -thick2);
1535 do_normal (points[0], points[1], -thick2,
1536 points[0], points[1], thick2,
1538 glVertex3f (x, y, -thick2);
1539 glVertex3f (x, y, thick2);
1540 glVertex3f (points[0], points[1], thick2);
1541 glVertex3f (points[0], points[1], -thick2);
1545 /* Compute the holes */
1546 step = M_PI * 2 / discfaces;
1547 for (k = 0; k < nholes; k++)
1549 GLdouble *p = holes + (discfaces * 3 * k);
1553 case 0: x = 0.34; y = 0.17; s = 0.05; break;
1554 case 1: x = 0.54; y = 0.17; s = 0.06; break;
1555 case 2: x = 0.55; y = 0.36; s = 0.06; break;
1556 default: abort(); break;
1558 for (i = 0; i < discfaces; i++)
1560 p[j++] = x + cos(M_PI*2 - th) * s;
1561 p[j++] = y + sin(M_PI*2 - th) * s;
1568 /* Draw the inside rim of the holes */
1569 for (k = 0; k < nholes; k++)
1571 GLdouble *p = holes + (discfaces * 3 * k);
1572 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1573 for (i = 0; i < discfaces; i++)
1575 GLdouble *p2 = p + (i*3);
1577 do_normal (p2[0], p2[1], -thick2,
1578 p2[0], p2[1], thick2,
1579 p2[-3], p2[-2], thick2);
1580 glVertex3f (p2[0], p2[1], -thick2);
1581 glVertex3f (p2[0], p2[1], thick2);
1584 glVertex3f (p[0], p[1], -thick2);
1585 glVertex3f (p[0], p[1], thick2);
1590 glTranslatef (0, 0, -thick2);
1591 for (y = 0; y <= 1; y++)
1593 if (y) glTranslatef (0, 0, thick2*2);
1595 /* A non-convex polygon */
1596 gluTessBeginPolygon (tess, to);
1598 glNormal3f (0, 0, (y > 0 ? 1 : -1));
1599 gluTessNormal (tess, 0, 0, (y > 0 ? 1 : -1));
1600 glFrontFace (GL_CCW);
1602 /* Tess the wedge */
1603 gluTessBeginContour (tess);
1604 for (i = 0; i < endpoints; i++)
1606 GLdouble *p = points + (i*3);
1607 gluTessVertex (tess, p, p);
1610 gluTessVertex (tess, points, points);
1611 gluTessEndContour (tess);
1613 /* Tess the holes */
1614 for (k = 0; k < nholes; k++)
1616 GLdouble *p = holes + (discfaces * 3 * k);
1617 gluTessBeginContour (tess);
1618 for (i = 0; i < discfaces; i++)
1620 GLdouble *p2 = p + (i*3);
1621 gluTessVertex (tess, p2, p2);
1624 gluTessEndContour (tess);
1627 gluTessEndPolygon (tess);
1629 glTranslatef (0, 0, -thick2);
1632 /* Compute the crust */
1634 s = 0.861; /* radius of inside of crust */
1635 step = M_PI * 2 / 6 / topfaces;
1638 for (i = 0; i < topfaces; i++)
1640 points[j++] = cos(th) * s;
1641 points[j++] = sin(th) * s;
1647 for (i = 0; i < topfaces; i++)
1649 points[j++] = cos(th) * s;
1650 points[j++] = sin(th) * s;
1655 /* Draw the rim of the crust */
1656 glFrontFace (GL_CCW);
1657 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1658 for (i = 0; i < topfaces * 2; i++)
1660 GLdouble *p = points + (i*3);
1661 if (i == 0 || i == (topfaces*2)-1)
1662 glNormal3f (0, -1, 0);
1663 else if (i == topfaces-1 || i == topfaces)
1664 glNormal3f (0, 1, 0);
1666 do_normal (p[-3], p[-2], thick2,
1668 p[0], p[1], -thick2);
1669 glVertex3f (p[0], p[1], -thick2);
1670 glVertex3f (p[0], p[1], thick2);
1673 glVertex3f (points[0], points[1], -thick2);
1674 glVertex3f (points[0], points[1], thick2);
1680 glBegin (GL_LINE_STRIP);
1681 for (i = 0; i < topfaces * 2; i++)
1683 GLdouble *p = points + (i*3);
1684 glVertex3f (p[0], p[1], -thick2);
1687 glVertex3f (points[0], points[1], -thick2);
1690 glBegin (GL_LINE_STRIP);
1691 for (i = 0; i < topfaces * 2; i++)
1693 GLdouble *p = points + (i*3);
1694 glVertex3f (p[0], p[1], thick2);
1697 glVertex3f (points[0], points[1], thick2);
1701 /* Draw the top of the crust */
1704 glFrontFace (GL_CW);
1705 glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP);
1706 glNormal3f (0, 0, -1);
1708 for (i = 0; i < topfaces; i++)
1710 int ii = topfaces + (topfaces - i - 1);
1711 GLdouble *p1 = points + (i*3);
1712 GLdouble *p2 = points + (ii*3);
1713 glVertex3f (p1[0], p1[1], -thick2);
1714 glVertex3f (p2[0], p2[1], -thick2);
1720 /* Draw the bottom of the crust */
1721 glFrontFace (GL_CCW);
1722 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1723 glNormal3f (0, 0, 1);
1724 for (i = 0; i < topfaces; i++)
1726 int ii = topfaces + (topfaces - i - 1);
1727 GLdouble *p1 = points + (i*3);
1728 GLdouble *p2 = points + (ii*3);
1729 glVertex3f (p1[0], p1[1], thick2);
1730 glVertex3f (p2[0], p2[1], thick2);
1737 gluDeleteTess (tess);
1750 /* Window management, etc
1753 reshape_logo (ModeInfo *mi, int width, int height)
1755 GLfloat h = (GLfloat) height / (GLfloat) width;
1757 glViewport (0, 0, (GLint) width, (GLint) height);
1759 glMatrixMode(GL_PROJECTION);
1761 gluPerspective (30.0, 1/h, 1.0, 100.0);
1763 glMatrixMode(GL_MODELVIEW);
1765 gluLookAt( 0.0, 0.0, 30.0,
1769 glClear(GL_COLOR_BUFFER_BIT);
1774 gl_init (ModeInfo *mi)
1776 /* logo_configuration *dc = &dcs[MI_SCREEN(mi)]; */
1777 int wire = MI_IS_WIREFRAME(mi);
1779 GLfloat position[] = {0, 0, 0, 0};
1780 GLfloat direction[] = {3, -1, -3};
1782 position[0] = -direction[0];
1783 position[1] = -direction[1];
1784 position[2] = -direction[2];
1788 glLightfv(GL_LIGHT0, GL_POSITION, position);
1789 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction);
1790 glShadeModel(GL_SMOOTH);
1791 glEnable(GL_NORMALIZE);
1792 glEnable(GL_CULL_FACE);
1793 glEnable(GL_LIGHTING);
1794 glEnable(GL_LIGHT0);
1795 glEnable(GL_DEPTH_TEST);
1801 init_logo (ModeInfo *mi)
1803 logo_configuration *dc;
1804 int do_gasket = get_boolean_resource(mi->dpy, "doGasket", "Boolean");
1805 int do_helix = get_boolean_resource(mi->dpy, "doHelix", "Boolean");
1806 int do_ladder = (do_helix &&
1807 get_boolean_resource(mi->dpy, "doLadder", "Boolean"));
1808 int do_frame = get_boolean_resource(mi->dpy, "doFrame", "Boolean");
1809 GLfloat helix_rot = 147.0;
1811 if (!do_gasket && !do_helix)
1813 fprintf (stderr, "%s: no helix or gasket?\n", progname);
1818 dcs = (logo_configuration *)
1819 calloc (MI_NUM_SCREENS(mi), sizeof (logo_configuration));
1821 fprintf(stderr, "%s: out of memory\n", progname);
1826 dc = &dcs[MI_SCREEN(mi)];
1828 if ((dc->glx_context = init_GL(mi)) != NULL) {
1830 reshape_logo (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1833 dc->wall_facets = get_integer_resource(mi->dpy, "wallFacets", "Integer");
1834 dc->bar_facets = get_integer_resource(mi->dpy, "barFacets", "Integer");
1835 dc->clockwise = get_boolean_resource(mi->dpy, "clockwise", "Boolean");
1836 dc->turns = get_float_resource(mi->dpy, "turns", "Float");
1837 dc->turn_spacing = get_float_resource(mi->dpy, "turnSpacing", "Float");
1838 dc->bar_spacing = get_float_resource(mi->dpy, "barSpacing", "Float");
1839 dc->wall_height = get_float_resource(mi->dpy, "wallHeight", "Float");
1840 dc->wall_thickness = get_float_resource(mi->dpy, "wallThickness", "Float");
1841 dc->bar_thickness = get_float_resource(mi->dpy, "barThickness", "Float");
1842 dc->wall_taper = get_float_resource(mi->dpy, "wallTaper", "Float");
1844 dc->gasket_size = get_float_resource(mi->dpy,"gasketSize", "Float");
1845 dc->gasket_depth = get_float_resource(mi->dpy,"gasketDepth", "Float");
1846 dc->gasket_thickness = get_float_resource(mi->dpy,"gasketThickness","Float");
1848 dc->frame_size = get_float_resource(mi->dpy, "frameSize", "Float");
1849 dc->frame_depth = get_float_resource(mi->dpy, "frameDepth", "Float");
1850 dc->frame_thickness = get_float_resource(mi->dpy, "frameThickness", "Float");
1851 dc->triangle_size = get_float_resource(mi->dpy, "triangleSize", "Float");
1853 dc->speed = get_float_resource(mi->dpy, "speed", "Float");
1854 dc->pizza_p = get_boolean_resource(mi->dpy, "pizza", "Boolean");
1859 char *color_name = get_string_resource (mi->dpy, "foreground", "Foreground");
1861 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
1862 if (*s2 == ' ' || *s2 == '\t')
1867 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
1869 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
1873 dc->color[0] = xcolor.red / 65535.0;
1874 dc->color[1] = xcolor.green / 65535.0;
1875 dc->color[2] = xcolor.blue / 65535.0;
1879 dc->trackball = gltrackball_init ();
1881 dc->gasket_spinnery.probability = 0.1;
1882 dc->gasket_spinnerx.probability = 0.1;
1883 dc->gasket_spinnerz.probability = 1.0;
1884 dc->helix_spinnerz.probability = 0.6;
1885 dc->helix_spinnery.probability = (dc->pizza_p ? 0.6 : 0);
1886 dc->scene_spinnerx.probability = 0.1;
1887 dc->scene_spinnery.probability = 0.0;
1888 dc->frame_spinner.probability = 5.0;
1890 /* start the frame off-screen */
1891 dc->frame_spinner.spinning_p = True;
1892 dc->frame_spinner.position = 0.3;
1893 dc->frame_spinner.speed = 0.001;
1895 if (dc->speed > 0) /* start off with the gasket in motion */
1897 dc->gasket_spinnerz.spinning_p = True;
1898 dc->gasket_spinnerz.speed = (0.002
1899 * ((random() & 1) ? 1 : -1)
1903 # ifdef DXF_OUTPUT_HACK
1905 dc->frame_depth = dc->gasket_depth;
1910 glRotatef(90, 1, 0, 0);
1911 glRotatef(90, 0, 0, 1);
1913 make_pizza (dc, 0, 0);
1917 glRotatef(helix_rot, 0, 0, 1);
1918 make_ladder (dc, 0, 0);
1919 make_helix (dc, 0, 0);
1920 glRotatef (180, 0, 0, 1);
1921 make_helix (dc, 0, 0);
1925 make_gasket (dc, 0);
1934 dc->helix_list = glGenLists (1);
1935 glNewList (dc->helix_list, GL_COMPILE);
1936 glRotatef(helix_rot, 0, 0, 1);
1937 if (do_ladder) dc->polys[0] += make_ladder (dc, 0, 0);
1938 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
1939 glRotatef(180, 0, 0, 1);
1940 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
1945 dc->helix_list_wire = glGenLists (1);
1946 glNewList (dc->helix_list_wire, GL_COMPILE);
1947 /* glRotatef(helix_rot, 0, 0, 1); wtf? */
1948 if (do_ladder) dc->polys[1] += make_ladder (dc, 1, 1);
1949 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
1950 glRotatef(180, 0, 0, 1);
1951 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
1956 dc->helix_list_facetted = glGenLists (1);
1957 glNewList (dc->helix_list_facetted, GL_COMPILE);
1958 glRotatef(helix_rot, 0, 0, 1);
1959 if (do_ladder) dc->polys[2] += make_ladder (dc, 1, 0);
1960 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
1961 glRotatef(180, 0, 0, 1);
1962 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
1966 dc->pizza_list = glGenLists (1);
1967 glNewList (dc->pizza_list, GL_COMPILE);
1968 if (do_frame) dc->polys[5] += make_pizza (dc, 0, 0);
1971 dc->pizza_list_wire = glGenLists (1);
1972 glNewList (dc->pizza_list_wire, GL_COMPILE);
1973 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 1);
1976 dc->pizza_list_facetted = glGenLists (1);
1977 glNewList (dc->pizza_list_facetted, GL_COMPILE);
1978 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 0);
1981 dc->gasket_list = glGenLists (1);
1982 glNewList (dc->gasket_list, GL_COMPILE);
1983 if (do_gasket) dc->polys[3] += make_gasket (dc, 0);
1986 dc->gasket_list_wire = glGenLists (1);
1987 glNewList (dc->gasket_list_wire, GL_COMPILE);
1988 if (do_gasket) dc->polys[4] += make_gasket (dc, 1);
1991 dc->frame_list = glGenLists (1);
1992 glNewList (dc->frame_list, GL_COMPILE);
1993 if (do_frame) dc->polys[5] += make_frame (dc, 0);
1996 dc->frame_list_wire = glGenLists (1);
1997 glNewList (dc->frame_list_wire, GL_COMPILE);
1998 if (do_frame) dc->polys[6] += make_frame (dc, 1);
2001 /* When drawing both solid and wireframe objects,
2002 make sure the wireframe actually shows up! */
2003 glEnable (GL_POLYGON_OFFSET_FILL);
2004 glPolygonOffset (1.0, 1.0);
2009 logo_handle_event (ModeInfo *mi, XEvent *event)
2011 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2013 if (event->xany.type == ButtonPress &&
2014 event->xbutton.button == Button1)
2016 dc->button_down_p = True;
2017 gltrackball_start (dc->trackball,
2018 event->xbutton.x, event->xbutton.y,
2019 MI_WIDTH (mi), MI_HEIGHT (mi));
2022 else if (event->xany.type == ButtonRelease &&
2023 event->xbutton.button == Button1)
2025 dc->button_down_p = False;
2028 else if (event->xany.type == ButtonPress &&
2029 (event->xbutton.button == Button4 ||
2030 event->xbutton.button == Button5 ||
2031 event->xbutton.button == Button6 ||
2032 event->xbutton.button == Button7))
2034 gltrackball_mousewheel (dc->trackball, event->xbutton.button, 10,
2035 !!event->xbutton.state);
2038 else if (event->xany.type == MotionNotify &&
2041 gltrackball_track (dc->trackball,
2042 event->xmotion.x, event->xmotion.y,
2043 MI_WIDTH (mi), MI_HEIGHT (mi));
2052 tick_spinner (ModeInfo *mi, spinner *s)
2054 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2056 if (dc->speed == 0) return;
2057 if (dc->button_down_p) return;
2061 s->position += s->speed;
2062 if (s->position >= 1.0 || s->position <= -1.0)
2066 s->spinning_p = False;
2069 else if (s->probability &&
2070 (random() % (int) (PROBABILITY_SCALE / s->probability)) == 0)
2073 s->spinning_p = True;
2076 s->speed = dc->speed * (frand(ss/3) + frand(ss/3) + frand(ss/3));
2077 } while (s->speed <= 0);
2079 s->speed = -s->speed;
2085 link_spinners (ModeInfo *mi, spinner *s0, spinner *s1)
2087 if (s0->spinning_p && !s1->spinning_p)
2089 GLfloat op = s1->probability;
2090 s1->probability = PROBABILITY_SCALE;
2091 tick_spinner (mi, s1);
2092 s1->probability = op;
2098 draw_logo (ModeInfo *mi)
2100 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2101 Display *dpy = MI_DISPLAY(mi);
2102 Window window = MI_WINDOW(mi);
2103 int wire = MI_IS_WIREFRAME(mi);
2105 GLfloat specular[] = {0.8, 0.8, 0.8, 1.0};
2106 GLfloat shininess = 50.0;
2108 if (!dc->glx_context)
2111 mi->polygon_count = 0;
2112 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(dc->glx_context));
2114 if (dc->wire_overlay == 0 &&
2115 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
2116 dc->wire_overlay = ((random() % 200) +
2120 tick_spinner (mi, &dc->gasket_spinnerx);
2121 tick_spinner (mi, &dc->gasket_spinnery);
2122 tick_spinner (mi, &dc->gasket_spinnerz);
2123 tick_spinner (mi, &dc->helix_spinnery);
2124 tick_spinner (mi, &dc->helix_spinnerz);
2125 tick_spinner (mi, &dc->scene_spinnerx);
2126 tick_spinner (mi, &dc->scene_spinnery);
2127 tick_spinner (mi, &dc->frame_spinner);
2128 link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery);
2130 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2136 glColor3f(dc->color[0], dc->color[1], dc->color[2]);
2138 /* Draw frame before trackball rotation */
2140 GLfloat p = (dc->frame_spinner.position >= 0
2141 ? dc->frame_spinner.position
2142 : -dc->frame_spinner.position);
2143 GLfloat size = (p > 0.5 ? 1-p : p);
2144 GLfloat scale = 1 + (size * 10);
2146 /* gltrackball_rotate (dc->trackball); */
2147 glRotatef(90, 1, 0, 0);
2148 glRotatef(90, 0, 0, 1);
2150 glScalef (1, scale, scale);
2153 glCallList (dc->frame_list_wire);
2154 mi->polygon_count += dc->polys[6];
2156 else if (dc->wire_overlay != 0)
2158 glCallList (dc->frame_list);
2159 glDisable (GL_LIGHTING);
2160 glCallList (dc->frame_list_wire);
2161 mi->polygon_count += dc->polys[6];
2162 if (!wire) glEnable (GL_LIGHTING);
2166 glCallList (dc->frame_list);
2167 mi->polygon_count += dc->polys[5];
2172 gltrackball_rotate (dc->trackball);
2174 glRotatef(90, 1, 0, 0);
2175 glRotatef(90, 0, 0, 1);
2177 glRotatef (360 * sin (M_PI/2 * dc->scene_spinnerx.position), 0, 1, 0);
2178 glRotatef (360 * sin (M_PI/2 * dc->scene_spinnery.position), 0, 0, 1);
2182 glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnerx.position), 0, 1, 0);
2183 glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnery.position), 0, 0, 1);
2184 glRotatef (360 * sin (M_PI/2 * dc->gasket_spinnerz.position), 1, 0, 0);
2186 memcpy (gcolor, dc->color, sizeof (dc->color));
2187 if (dc->wire_overlay != 0)
2189 gcolor[0] = gcolor[1] = gcolor[2] = 0;
2190 specular[0] = specular[1] = specular[2] = 0;
2193 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
2194 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
2195 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shininess);
2199 glCallList (dc->gasket_list_wire);
2200 mi->polygon_count += dc->polys[4];
2202 else if (dc->wire_overlay != 0)
2204 glCallList (dc->gasket_list);
2205 glDisable (GL_LIGHTING);
2206 glCallList (dc->gasket_list_wire);
2207 mi->polygon_count += dc->polys[4];
2208 if (!wire) glEnable (GL_LIGHTING);
2212 glCallList (dc->gasket_list);
2213 mi->polygon_count += dc->polys[3];
2218 glRotatef (360 * sin (M_PI/2 * dc->helix_spinnery.position), 1, 0, 0);
2219 glRotatef (360 * sin (M_PI/2 * dc->helix_spinnerz.position), 0, 0, 1);
2224 glCallList (dc->pizza_list_wire);
2226 glCallList (dc->helix_list_wire);
2227 mi->polygon_count += dc->polys[1];
2229 else if (dc->wire_overlay != 0)
2232 glCallList (dc->pizza_list_facetted);
2234 glCallList (dc->helix_list_facetted);
2236 glDisable (GL_LIGHTING);
2239 glCallList (dc->pizza_list_wire);
2241 glCallList (dc->helix_list_wire);
2243 mi->polygon_count += dc->polys[2];
2244 if (!wire) glEnable (GL_LIGHTING);
2249 glCallList (dc->pizza_list);
2251 glCallList (dc->helix_list);
2252 mi->polygon_count += dc->polys[0];
2257 if (dc->wire_overlay > 0)
2260 if (mi->fps_p) do_fps (mi);
2263 glXSwapBuffers(dpy, window);
2266 XSCREENSAVER_MODULE_2 ("DNAlogo", dnalogo, logo)