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)))
59 #undef DXF_OUTPUT_HACK
61 #ifdef DXF_OUTPUT_HACK /* When this is defined, instead of rendering
62 to the screen, we write a DXF CAD file to stdout.
63 This is a kludge of shocking magnitude...
64 Maybe there's some other way to intercept all
65 glVertex3f calls than with a #define? */
66 # define unit_tube dxf_unit_tube
67 # define unit_cone dxf_unit_cone
68 # define tube_1 dxf_tube_1
69 # define tube dxf_tube
70 # define cone dxf_cone
71 #endif /* DXF_OUTPUT_HACK */
73 #include "xlockmore.h"
77 #include "gltrackball.h"
79 #ifdef USE_GL /* whole file */
82 # include "dnapizza.h"
88 HELIX_IN, HELIX, HELIX_OUT,
89 PIZZA_IN, PIZZA, PIZZA_OUT,
95 GLfloat position; /* 0.0 - 1.0 */
96 GLfloat speed; /* how far along the path (may be negative) */
97 GLfloat probability; /* relative likelyhood to start spinning */
101 GLXContext *glx_context;
103 GLuint helix_list, helix_list_wire, helix_list_facetted;
104 GLuint pizza_list, pizza_list_wire, pizza_list_facetted;
105 GLuint gasket_list, gasket_list_wire;
106 GLuint frame_list, frame_list_wire;
115 GLfloat turn_spacing;
118 GLfloat wall_thickness;
119 GLfloat bar_thickness;
123 GLfloat gasket_depth;
124 GLfloat gasket_thickness;
128 GLfloat frame_thickness;
129 GLfloat triangle_size;
133 glyph_mode anim_state;
136 spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz;
137 spinner scene_spinnerx, scene_spinnery;
138 spinner helix_spinnerz;
139 spinner pizza_spinnery, pizza_spinnerz;
140 spinner frame_spinner;
142 trackball_state *trackball;
145 int wire_overlay; /* frame countdown */
147 } logo_configuration;
149 static logo_configuration *dcs = NULL;
151 static XrmOptionDescRec opts[] = {
152 { "-speed", ".speed", XrmoptionSepArg, 0 },
153 { "-mode", ".mode", XrmoptionSepArg, 0 },
154 { "-pizza", ".mode", XrmoptionNoArg, "pizza" },
155 { "-helix", ".mode", XrmoptionNoArg, "helix" },
156 { "-both", ".mode", XrmoptionNoArg, "both" },
159 ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
161 #define PROBABILITY_SCALE 600
164 #ifdef DXF_OUTPUT_HACK
166 # define glBegin dxf_glBegin
167 # define glVertex3f dxf_glVertex3f
168 # define glVertex3dv dxf_glVertex3dv
169 # define glEnd dxf_glEnd
170 # define glVertexPointer dxf_glVertexPointer
171 # define glDrawArrays dxf_glDrawArrays
173 static int dxf_type, dxf_point, dxf_point_total, dxf_layer, dxf_color;
174 static GLfloat dxf_quads[4*4];
177 dxf_glBegin (int type)
185 dxf_glVertex3f (GLfloat ox, GLfloat oy, GLfloat oz)
191 /* Transform the point into modelview space. */
192 glGetFloatv (GL_MODELVIEW_MATRIX, m);
193 x = ox * m[0] + oy * m[4] + oz * m[8] + m[12];
194 y = ox * m[1] + oy * m[5] + oz * m[9] + m[13];
195 z = ox * m[2] + oy * m[6] + oz * m[10] + m[14];
197 dxf_quads[dxf_point*3+0] = x;
198 dxf_quads[dxf_point*3+1] = y;
199 dxf_quads[dxf_point*3+2] = z;
205 if (dxf_point < 4) return;
207 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
208 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
209 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
210 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
212 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
213 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
214 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
216 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
217 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
218 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
220 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]);
221 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
222 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
227 if (dxf_point < 4) return;
229 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
230 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
231 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
232 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
234 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
235 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
236 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
238 fprintf (stdout, "12\n%.6f\n", dxf_quads[i+3]); /* funky quad strip */
239 fprintf (stdout, "22\n%.6f\n", dxf_quads[i+4]); /* vert order: 1243. */
240 fprintf (stdout, "32\n%.6f\n", dxf_quads[i+5]);
242 fprintf (stdout, "13\n%.6f\n", dxf_quads[i]);
243 fprintf (stdout, "23\n%.6f\n", dxf_quads[i+1]);
244 fprintf (stdout, "33\n%.6f\n", dxf_quads[i+2]);
247 dxf_quads[0] = dxf_quads[6]; /* copy point 3 to pos 1 */
248 dxf_quads[1] = dxf_quads[7];
249 dxf_quads[2] = dxf_quads[8];
250 dxf_quads[3] = dxf_quads[9]; /* copy point 4 to pos 2 */
251 dxf_quads[4] = dxf_quads[10];
252 dxf_quads[5] = dxf_quads[11];
253 dxf_point = 2; /* leave those two points in queue */
257 case GL_TRIANGLE_FAN:
258 if (dxf_point < 3) return;
260 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
261 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
262 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
263 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
265 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
266 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
267 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
269 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
270 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
271 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
274 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
275 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
276 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
279 if (dxf_type == GL_TRIANGLE_FAN)
281 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to point 2 */
282 dxf_quads[4] = dxf_quads[7];
283 dxf_quads[5] = dxf_quads[8];
284 dxf_point = 2; /* leave two points in queue */
288 case GL_TRIANGLE_STRIP:
289 if (dxf_point < 3) return;
291 fprintf (stdout, "0\n3DFACE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
293 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
294 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
295 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
297 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
298 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
299 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
301 fprintf (stdout, "12\n%.6f\n", dxf_quads[i++]);
302 fprintf (stdout, "22\n%.6f\n", dxf_quads[i++]);
303 fprintf (stdout, "32\n%.6f\n", dxf_quads[i++]);
306 fprintf (stdout, "13\n%.6f\n", dxf_quads[i++]); /* dup pt 4 as pt 3. */
307 fprintf (stdout, "23\n%.6f\n", dxf_quads[i++]);
308 fprintf (stdout, "33\n%.6f\n", dxf_quads[i++]);
310 dxf_quads[0] = dxf_quads[3]; /* copy point 2 to pos 1 */
311 dxf_quads[1] = dxf_quads[4];
312 dxf_quads[2] = dxf_quads[5];
313 dxf_quads[3] = dxf_quads[6]; /* copy point 3 to pos 2 */
314 dxf_quads[4] = dxf_quads[7];
315 dxf_quads[5] = dxf_quads[8];
316 dxf_point = 2; /* leave those two points in queue */
323 if (dxf_point_total == 1)
330 if (dxf_point < 2) return;
332 fprintf (stdout, "0\nLINE\n8\n%d\n62\n%d\n", dxf_layer, dxf_color);
334 fprintf (stdout, "10\n%.6f\n", dxf_quads[i++]);
335 fprintf (stdout, "20\n%.6f\n", dxf_quads[i++]);
336 fprintf (stdout, "30\n%.6f\n", dxf_quads[i++]);
338 fprintf (stdout, "11\n%.6f\n", dxf_quads[i++]);
339 fprintf (stdout, "21\n%.6f\n", dxf_quads[i++]);
340 fprintf (stdout, "31\n%.6f\n", dxf_quads[i++]);
343 if (dxf_type != GL_LINES)
345 dxf_quads[0] = dxf_quads[3];
346 dxf_quads[1] = dxf_quads[4];
347 dxf_quads[2] = dxf_quads[5];
360 dxf_glVertex3dv (const GLdouble *v)
362 glVertex3f (v[0], v[1], v[2]);
369 if (dxf_type == GL_LINE_LOOP) /* close loop */
370 glVertex3f (dxf_quads[6], dxf_quads[7], dxf_quads[8]);
380 fprintf (stdout, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n");
381 fprintf (stdout, "0\nSECTION\n2\nENTITIES\n");
387 fprintf (stdout, "0\nENDSEC\n0\nEOF\n");
392 static const GLvoid *dxf_vp;
393 static GLsizei dxf_vp_size;
394 static GLsizei dxf_vp_stride;
397 dxf_glVertexPointer (GLint size, GLenum type, GLsizei stride,
398 const GLvoid *pointer)
400 if (type != GL_FLOAT) abort();
401 if (stride <= 0) abort();
404 dxf_vp_stride = stride;
408 dxf_glDrawArrays (GLenum mode, GLint first, GLsizei count)
411 unsigned char *a = (unsigned char *) dxf_vp;
413 for (i = first; i < first+count; i++)
415 GLfloat *fa = (GLfloat *) a;
416 dxf_glVertex3f (fa[0], fa[1], fa[2]);
423 # define XYZ tube_XYZ /* avoid conflict with normals.h */
424 # include "tube.c" /* Yes, I really am including a C file. */
427 #endif /* DXF_OUTPUT_HACK */
431 /* Calculate the angle (in degrees) between two vectors.
434 vector_angle (double ax, double ay, double az,
435 double bx, double by, double bz)
437 double La = sqrt (ax*ax + ay*ay + az*az);
438 double Lb = sqrt (bx*bx + by*by + bz*bz);
441 if (La == 0 || Lb == 0) return 0;
442 if (ax == bx && ay == by && az == bz) return 0;
444 /* dot product of two vectors is defined as:
445 La * Lb * cos(angle between vectors)
446 and is also defined as:
447 ax*bx + ay*by + az*bz
449 La * Lb * cos(angle) = ax*bx + ay*by + az*bz
450 cos(angle) = (ax*bx + ay*by + az*bz) / (La * Lb)
451 angle = acos ((ax*bx + ay*by + az*bz) / (La * Lb));
453 cc = (ax*bx + ay*by + az*bz) / (La * Lb);
454 if (cc > 1) cc = 1; /* avoid fp rounding error (1.000001 => sqrt error) */
457 return (angle * M_PI / 180);
465 make_helix (logo_configuration *dc, int facetted, int wire)
468 int wall_facets = dc->wall_facets / (facetted ? 10 : 1);
470 GLfloat max_th = M_PI * 2 * dc->turns;
471 GLfloat th_inc = M_PI * 2 / wall_facets;
473 GLfloat x1=0, y1=0, x2=0, y2=0;
474 GLfloat x1b=0, y1b=0, x2b=0, y2b=0;
477 GLfloat h1off=0, h2off=0;
478 GLfloat z_inc = dc->turn_spacing / wall_facets;
483 x1b = 1 - dc->wall_thickness;
486 z1 = -(dc->turn_spacing * dc->turns / 2);
488 h1 = (dc->wall_taper > 0 ? 0 : dc->wall_height / 2);
489 h1off = (dc->wall_taper > 0 ? -dc->wall_height / 2 : 0);
492 z1 = -z1, z_inc = -z_inc, h1off = -h1off;
501 nx = cos (th + M_PI/2);
502 ny = sin (th + M_PI/2);
503 glNormal3f(nx, ny, 0);
504 glVertex3f( x1, y1, z1 - h1 + h1off);
505 glVertex3f( x1, y1, z1 + h1 + h1off);
506 glVertex3f(x1b, y1b, z1 + h1 + h1off);
507 glVertex3f(x1b, y1b, z1 - h1 + h1off);
512 while (th + th_inc <= max_th)
519 x2b = x2 * (1 - dc->wall_thickness);
520 y2b = y2 * (1 - dc->wall_thickness);
525 if (dc->wall_taper > 0)
528 if (th < dc->wall_taper)
530 h2 = dc->wall_height/2 * cos (M_PI / 2
531 * (1 - (th / dc->wall_taper)));
533 h2off = h2 - dc->wall_height/2;
535 h2off = dc->wall_height/2 - h2;
537 else if (th >= max_th - dc->wall_taper)
539 if (th + th_inc > max_th) /* edge case: always come to a point */
542 h2 = dc->wall_height/2 * cos (M_PI / 2
543 * (1 - ((max_th - th)
546 h2off = dc->wall_height/2 - h2;
548 h2off = h2 - dc->wall_height/2;
555 glBegin(wire ? GL_LINES : GL_QUADS);
556 glNormal3f(x1, y1, 0);
557 glVertex3f(x1, y1, z1 - h1 + h1off);
558 glVertex3f(x1, y1, z1 + h1 + h1off);
559 glNormal3f(x2, y2, 0);
560 glVertex3f(x2, y2, z2 + h2 + h2off);
561 glVertex3f(x2, y2, z2 - h2 + h2off);
568 glBegin(wire ? GL_LINES : GL_QUADS);
569 glNormal3f(-x1b, -y1b, 0);
570 glVertex3f( x1b, y1b, z1 - h1 + h1off);
571 glVertex3f( x1b, y1b, z1 + h1 + h1off);
572 glNormal3f(-x2b, -y2b, 0);
573 glVertex3f( x2b, y2b, z2 + h2 + h2off);
574 glVertex3f( x2b, y2b, z2 - h2 + h2off);
581 /* glNormal3f(0, 0, 1);*/
582 do_normal (x2, y2, z2 + h2 + h2off,
583 x2b, y2b, z2 + h2 + h2off,
584 x1b, y1b, z1 + h1 + h1off);
585 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
586 glVertex3f( x2, y2, z2 + h2 + h2off);
587 glVertex3f( x2b, y2b, z2 + h2 + h2off);
588 glVertex3f( x1b, y1b, z1 + h1 + h1off);
589 glVertex3f( x1, y1, z1 + h1 + h1off);
596 do_normal ( x1, y1, z1 - h1 + h1off,
597 x1b, y1b, z1 - h1 + h1off,
598 x2b, y2b, z2 - h2 + h2off);
599 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
600 glNormal3f(0, 0, -1);
601 glVertex3f( x1, y1, z1 - h1 + h1off);
602 glVertex3f( x1b, y1b, z1 - h1 + h1off);
603 glVertex3f( x2b, y2b, z2 - h2 + h2off);
604 glVertex3f( x2, y2, z2 - h2 + h2off);
624 nx = cos (th + M_PI/2);
625 ny = sin (th + M_PI/2);
626 glNormal3f(nx, ny, 0);
627 glVertex3f(x2, y2, z1 - h2 + h2off);
628 glVertex3f(x2, y2, z1 + h2 + h2off);
629 glVertex3f(x2b, y2b, z1 + h2 + h2off);
630 glVertex3f(x2b, y2b, z1 - h2 + h2off);
639 make_ladder (logo_configuration *dc, int facetted, int wire)
643 GLfloat max_th = dc->turns * M_PI * 2;
644 GLfloat max_z = dc->turns * dc->turn_spacing;
645 GLfloat z_inc = dc->bar_spacing;
646 GLfloat th_inc = M_PI * 2 * (dc->bar_spacing / dc->turn_spacing);
649 /* skip forward to center the bars in the helix... */
651 GLfloat usable_th = max_th - dc->wall_taper;
652 GLfloat usable_z = max_z / (max_th / usable_th);
653 int nbars = usable_z / dc->bar_spacing;
654 GLfloat used_z, pad_z, pad_ratio;
656 if (! (nbars & 1)) nbars--; /* always an odd number of bars */
658 used_z = (nbars - 1) * dc->bar_spacing;
659 pad_z = max_z - used_z;
660 pad_ratio = pad_z / max_z;
662 th = (max_th * pad_ratio/2);
663 z = -(max_z / 2) + (max_z * pad_ratio/2);
666 z = -z, z_inc = -z_inc;
669 for (i = 0; i < nbars; i++)
671 int facets = dc->bar_facets / (facetted ? 14 : 1);
672 if (facets <= 3) facets = 3;
673 x = cos (th) * (1 - dc->wall_thickness);
674 y = sin (th) * (1 - dc->wall_thickness);
675 polys += tube ( x, y, z,
677 dc->bar_thickness, 0, facets,
692 make_gasket (logo_configuration *dc, int wire)
700 GLfloat d2r = M_PI / 180;
702 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 2;
704 GLfloat *pointsx0, *pointsy0, *pointsx1, *pointsy1, *normals;
706 GLfloat r0 = 0.750; /* 395 */
707 GLfloat r1a = 0.825; /* bottom of wall below upper left hole */
708 GLfloat r1b = 0.867; /* center of upper left hole */
709 GLfloat r1c = 0.909; /* top of wall above hole */
710 GLfloat r1 = 0.916; /* 471 */
711 GLfloat r2 = 0.963; /* 490 */
712 GLfloat r3 = 0.960; /* 499 */
713 GLfloat r4 = 1.000; /* 507 */
714 GLfloat r5 = 1.080; /* 553 */
716 GLfloat ctrl_r[100], ctrl_th[100];
720 # ifdef DXF_OUTPUT_HACK
721 if (! wire) res *= 8;
724 # define POINT(r,th) \
725 ctrl_r [nctrls] = r, \
726 ctrl_th[nctrls] = (th * d2r), \
729 POINT (0.829, 0); /* top indentation, right half */
737 POINT (r4, 4.0); /* moving clockwise... */
758 POINT (r4, 316.8); /* upper left indentation */
759 POINT (0.990, 316.87);
760 POINT (0.880, 317.21);
761 POINT (0.872, 317.45);
762 POINT (0.869, 317.80);
763 POINT (0.867, 318.10);
765 POINT (0.867, 318.85);
766 POINT (0.869, 319.15);
767 POINT (0.872, 319.50);
768 POINT (0.880, 319.74);
769 POINT (0.990, 320.08);
774 POINT (r1a, 338.0); /* cut-out disc */
780 POINT (0.872, 356.05); /* top indentation, left half */
781 POINT (0.862, 356.19);
782 POINT (0.851, 356.70);
783 POINT (0.841, 357.35);
784 POINT (0.835, 358.19);
785 POINT (0.831, 359.15);
789 points_size = res + (nctrls * 2);
790 pointsx0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
791 pointsy0 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
792 pointsx1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
793 pointsy1 = (GLfloat *) malloc (points_size * sizeof(GLfloat));
794 normals = (GLfloat *) malloc (points_size * sizeof(GLfloat) * 2);
797 for (i = 1; i < nctrls; i++)
799 GLfloat from_r = ctrl_r [i-1];
800 GLfloat from_th = ctrl_th[i-1];
801 GLfloat to_r = ctrl_r [i];
802 GLfloat to_th = ctrl_th[i];
804 GLfloat step = 2*M_PI / res;
805 int nsteps = 1 + ((to_th - from_th) / step);
808 for (j = 0; j < nsteps + (i == nctrls-1); j++)
810 GLfloat r = from_r + (j * (to_r - from_r) / nsteps);
811 GLfloat th = from_th + (j * (to_th - from_th) / nsteps);
813 GLfloat cth = cos(th) * dc->gasket_size;
814 GLfloat sth = sin(th) * dc->gasket_size;
816 pointsx0[npoints] = r0 * cth; /* inner ring */
817 pointsy0[npoints] = r0 * sth;
818 pointsx1[npoints] = r * cth; /* outer ring */
819 pointsy1[npoints] = r * sth;
822 if (npoints >= points_size) abort();
826 /* normals for the outer ring */
827 for (i = 1; i < npoints; i++)
838 n = calc_normal (a, b, c);
839 normals[(i-1)*2 ] = n.x;
840 normals[(i-1)*2+1] = n.y;
843 glRotatef(-90, 0, 1, 0);
844 glRotatef(180, 0, 0, 1);
849 for (z = -thick2; z <= thick2; z += thick2*2)
853 glBegin (GL_LINE_LOOP);
854 for (i = 0; i < npoints; i++)
855 glVertex3f (pointsx0[i], pointsy0[i], z);
860 glBegin (GL_LINE_LOOP);
861 for (i = 0; i < npoints; i++)
862 glVertex3f (pointsx1[i], pointsy1[i], z);
866 for (i = 1; i < npoints; i++)
868 glBegin (GL_LINE_STRIP);
869 glVertex3f (pointsx0[i-1], pointsy0[i-1], z);
870 glVertex3f (pointsx0[i ], pointsy0[i ], z);
871 glVertex3f (pointsx1[i ], pointsy1[i ], z);
872 glVertex3f (pointsx1[i-1], pointsy1[i-1], z);
880 for (i = 0; i < npoints; i++)
883 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
884 glVertex3f (pointsx0[i], pointsy0[i], thick2);
886 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
887 glVertex3f (pointsx1[i], pointsy1[i], thick2);
897 glNormal3f(0, 0, -1);
898 glBegin (GL_QUAD_STRIP);
899 for (i = 0; i < npoints; i++)
901 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
902 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
910 glBegin (GL_QUAD_STRIP);
911 for (i = 0; i < npoints; i++)
913 glVertex3f (pointsx0[i], pointsy0[i], thick2);
914 glVertex3f (pointsx1[i], pointsy1[i], thick2);
921 glBegin (GL_QUAD_STRIP);
922 for (i = 0; i < npoints; i++)
924 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
925 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
926 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
935 for (i = 0; i < npoints-1; i++)
937 int ia = (i == 0 ? npoints-2 : i-1);
938 int iz = (i == npoints-2 ? 0 : i+1);
939 GLfloat x = pointsx1[i];
940 GLfloat y = pointsy1[i];
941 GLfloat xz = pointsx1[iz];
942 GLfloat yz = pointsy1[iz];
944 GLfloat nxa = normals[ia*2]; /* normal of [i-1 - i] face */
945 GLfloat nya = normals[ia*2+1];
946 GLfloat nx = normals[i*2]; /* normal of [i - i+1] face */
947 GLfloat ny = normals[i*2+1];
948 GLfloat nxz = normals[iz*2]; /* normal of [i+1 - i+2] face */
949 GLfloat nyz = normals[iz*2+1];
951 GLfloat anglea = vector_angle (nx, ny, 0, nxa, nya, 0);
952 GLfloat anglez = vector_angle (nx, ny, 0, nxz, nyz, 0);
953 GLfloat pointy = 0.005;
957 glNormal3f (nx, ny, 0);
958 glVertex3f (x, y, thick2);
959 glVertex3f (x, y, -thick2);
963 glNormal3f ((nxa + nx) / 2, (nya + ny) / 2, 0);
964 glVertex3f (x, y, thick2);
965 glVertex3f (x, y, -thick2);
970 glNormal3f (nx, ny, 0);
971 glVertex3f (xz, yz, -thick2);
972 glVertex3f (xz, yz, thick2);
976 glNormal3f ((nx + nxz) / 2, (ny + nyz) / 2, 0);
977 glVertex3f (xz, yz, -thick2);
978 glVertex3f (xz, yz, thick2);
986 /* Fill in the upper left hole...
993 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
994 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
996 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
997 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
1001 pointsx0[npoints] = r1c * cos(th) * dc->gasket_size;
1002 pointsy0[npoints] = r1c * sin(th) * dc->gasket_size;
1004 pointsx0[npoints] = r4 * cos(th) * dc->gasket_size;
1005 pointsy0[npoints] = r4 * sin(th) * dc->gasket_size;
1010 glNormal3f (0, 0, -1);
1012 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1013 glVertex3f (pointsx0[0], pointsy0[0], -thick2);
1014 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1015 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1016 glVertex3f (pointsx0[2], pointsy0[2], -thick2);
1021 glNormal3f (0, 0, 1);
1022 glFrontFace(GL_CCW);
1023 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1024 glVertex3f (pointsx0[0], pointsy0[0], thick2);
1025 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1026 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1027 glVertex3f (pointsx0[2], pointsy0[2], thick2);
1034 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1035 glNormal3f (pointsx0[1], pointsy0[1], 0);
1036 glVertex3f (pointsx0[1], pointsy0[1], thick2);
1037 glNormal3f (pointsx0[3], pointsy0[3], 0);
1038 glVertex3f (pointsx0[3], pointsy0[3], thick2);
1039 glVertex3f (pointsx0[3], pointsy0[3], -thick2);
1040 glNormal3f (pointsx0[1], pointsy0[1], 0);
1041 glVertex3f (pointsx0[1], pointsy0[1], -thick2);
1046 /* Now make a donut.
1049 int nsteps = (wire ? 12 : 64);
1052 GLfloat th, cth, sth;
1056 th = ((339.0 + 343.0) / 2) * d2r;
1058 glTranslatef (r1b * cos(th) * dc->gasket_size,
1059 r1b * sin(th) * dc->gasket_size,
1063 for (i = 0; i < nsteps; i++)
1065 th = 2 * M_PI * i / nsteps;
1066 cth = cos (th) * dc->gasket_size;
1067 sth = sin (th) * dc->gasket_size;
1068 pointsx0[npoints] = r0 * cth;
1069 pointsy0[npoints] = r0 * sth;
1070 pointsx1[npoints] = r1 * cth;
1071 pointsy1[npoints] = r1 * sth;
1076 pointsx0[npoints] = pointsx0[0];
1077 pointsy0[npoints] = pointsy0[0];
1078 pointsx1[npoints] = pointsx1[0];
1079 pointsy1[npoints] = pointsy1[0];
1084 glBegin (GL_LINE_LOOP);
1085 for (i = 0; i < npoints; i++)
1086 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1089 glBegin (GL_LINE_LOOP);
1090 for (i = 0; i < npoints; i++)
1091 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1095 glBegin (GL_LINE_LOOP);
1096 for (i = 0; i < npoints; i++)
1097 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1100 glBegin (GL_LINE_LOOP);
1101 for (i = 0; i < npoints; i++)
1102 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1111 glNormal3f(0, 0, -1);
1112 glBegin (GL_QUAD_STRIP);
1113 for (i = 0; i < npoints; i++)
1115 glVertex3f (pointsx0[i], pointsy0[i], -thick2);
1116 glVertex3f (pointsx1[i], pointsy1[i], -thick2);
1122 glFrontFace(GL_CCW);
1123 glNormal3f(0, 0, 1);
1124 glBegin (GL_QUAD_STRIP);
1125 for (i = 0; i < npoints; i++)
1127 glVertex3f (pointsx0[i], pointsy0[i], thick2);
1128 glVertex3f (pointsx1[i], pointsy1[i], thick2);
1136 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1137 for (i = 0; i < npoints; i++)
1139 glNormal3f (-pointsx0[i], -pointsy0[i], 0);
1140 glVertex3f ( pointsx0[i], pointsy0[i], thick2);
1141 glVertex3f ( pointsx0[i], pointsy0[i], -thick2);
1151 /* Attach the bottom-right dingus...
1158 glRotatef (49.5, 0, 0, 1);
1159 glScalef (dc->gasket_size, dc->gasket_size, 1);
1160 glTranslatef (0, (r0+r1)/2, 0);
1165 glFrontFace(GL_CCW);
1166 glBegin (wire ? GL_LINE_STRIP : GL_QUADS);
1167 glNormal3f (0, 0, -1);
1168 glVertex3f (-w/2, -h/2, -thick2); glVertex3f (-w/2, h/2, -thick2);
1169 glVertex3f ( w/2, h/2, -thick2); glVertex3f ( w/2, -h/2, -thick2);
1170 glNormal3f (1, 0, 0);
1171 glVertex3f ( w/2, -h/2, -thick2); glVertex3f ( w/2, h/2, -thick2);
1172 glVertex3f ( w/2, h/2, thick2); glVertex3f ( w/2, -h/2, thick2);
1173 glNormal3f (0, 0, 1);
1174 glVertex3f ( w/2, -h/2, thick2); glVertex3f ( w/2, h/2, thick2);
1175 glVertex3f (-w/2, h/2, thick2); glVertex3f (-w/2, -h/2, thick2);
1176 glNormal3f (-1, 0, 0);
1177 glVertex3f (-w/2, -h/2, thick2); glVertex3f (-w/2, h/2, thick2);
1178 glVertex3f (-w/2, h/2, -thick2); glVertex3f (-w/2, -h/2, -thick2);
1184 for (th = (wire ? 0 : -0.1);
1186 th += (M_PI / (wire ? 5 : 32)))
1188 pointsx0[npoints] = w/2 * cos(th);
1189 pointsy0[npoints] = w/2 * sin(th);
1194 /* front inside curve */
1195 glNormal3f (0, 0, -1);
1197 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1198 if (! wire) glVertex3f (0, h/2, -thick2);
1199 for (i = 0; i < npoints; i++)
1200 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1204 /* front outside curve */
1205 glFrontFace(GL_CCW);
1206 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1207 if (! wire) glVertex3f (0, -h/2, -thick2);
1208 for (i = 0; i < npoints; i++)
1209 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1213 /* back inside curve */
1214 glNormal3f (0, 0, 1);
1215 glFrontFace(GL_CCW);
1216 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1217 if (! wire) glVertex3f (0, h/2, thick2);
1218 for (i = 0; i < npoints; i++)
1219 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1223 /* back outside curve */
1225 glBegin (wire ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
1226 if (! wire) glVertex3f (0, -h/2, thick2);
1227 for (i = 0; i < npoints; i++)
1228 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1233 glFrontFace(GL_CCW);
1234 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1235 for (i = 0; i < npoints; i++)
1237 glNormal3f (pointsx0[i], pointsy0[i], 0);
1238 glVertex3f (pointsx0[i], h/2 + pointsy0[i], thick2);
1239 glVertex3f (pointsx0[i], h/2 + pointsy0[i], -thick2);
1246 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1247 for (i = 0; i < npoints; i++)
1249 glNormal3f (pointsx0[i], -pointsy0[i], 0);
1250 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], thick2);
1251 glVertex3f (pointsx0[i], -h/2 - pointsy0[i], -thick2);
1268 make_frame (logo_configuration *dc, int wire)
1272 GLfloat x[20], y[20];
1273 GLfloat corner_cut = 0.5;
1276 glRotatef (90, 0, 1, 0);
1277 glScalef (4 * dc->frame_size,
1279 4 * dc->frame_size);
1281 x[0] = -dc->frame_thickness;
1282 x[1] = -dc->frame_thickness * corner_cut;
1284 x[3] = 0.5 - dc->triangle_size;
1286 x[5] = 0.5 + dc->triangle_size;
1288 x[7] = 1 + dc->frame_thickness * corner_cut;
1289 x[8] = 1 + dc->frame_thickness;
1291 y[0] = -dc->frame_thickness;
1292 y[1] = -dc->frame_thickness * corner_cut;
1294 y[3] = dc->triangle_size;
1298 glTranslatef (-0.5, -0.5, dc->frame_depth / 4);
1300 for (j = 0; j <= 1; j++)
1302 if (j) glTranslatef (0, 0, -dc->frame_depth / 2);
1303 glFrontFace (j ? GL_CCW : GL_CW);
1304 for (i = 0; i < 4; i++)
1306 glNormal3f (0, 0, (j ? -1 : 1));
1307 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1308 glVertex3f (x[0], y[1], 0); glVertex3f (x[0], y[2], 0);
1309 glVertex3f (x[1], y[0], 0); glVertex3f (x[1], y[2], 0);
1310 glVertex3f (x[3], y[0], 0); glVertex3f (x[3], y[2], 0);
1311 glVertex3f (x[4], y[0], 0); glVertex3f (x[4], y[3], 0);
1312 glVertex3f (x[5], y[0], 0); glVertex3f (x[5], y[2], 0);
1313 glVertex3f (x[7], y[0], 0); glVertex3f (x[7], y[2], 0);
1314 glVertex3f (x[8], y[1], 0); glVertex3f (x[8], y[2], 0);
1317 glTranslatef (0.5, 0.5, 0);
1318 glRotatef (90, 0, 0, 1);
1319 glTranslatef (-0.5, -0.5, 0);
1325 glFrontFace (GL_CCW);
1326 for (i = 0; i < 4; i++)
1328 glNormal3f (0, 1, 0);
1329 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1330 glVertex3f (x[2], y[2], 0); glVertex3f (x[2], y[2], dc->frame_depth/2);
1331 glVertex3f (x[3], y[2], 0); glVertex3f (x[3], y[2], dc->frame_depth/2);
1332 glVertex3f (x[4], y[3], 0); glVertex3f (x[4], y[3], dc->frame_depth/2);
1333 glVertex3f (x[5], y[2], 0); glVertex3f (x[5], y[2], dc->frame_depth/2);
1334 glVertex3f (x[6], y[2], 0); glVertex3f (x[6], y[2], dc->frame_depth/2);
1338 glNormal3f (0, -1, 0);
1339 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1340 glVertex3f (x[7], y[0], 0);
1341 glVertex3f (x[7], y[0], dc->frame_depth/2);
1342 glVertex3f (x[1], y[0], dc->frame_depth/2);
1343 glVertex3f (x[1], y[0], 0);
1347 glNormal3f (1, -1, 0);
1348 glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
1349 glVertex3f (x[8], y[1], 0);
1350 glVertex3f (x[8], y[1], dc->frame_depth/2);
1351 glVertex3f (x[7], y[0], dc->frame_depth/2);
1352 glVertex3f (x[7], y[0], 0);
1358 glNormal3f (0, 1, 0);
1359 for (j = 0; j <= 1; j++)
1361 glBegin (GL_LINE_STRIP);
1362 glVertex3f (x[2], y[2], j*dc->frame_depth/2);
1363 glVertex3f (x[3], y[2], j*dc->frame_depth/2);
1364 glVertex3f (x[4], y[3], j*dc->frame_depth/2);
1365 glVertex3f (x[5], y[2], j*dc->frame_depth/2);
1366 glVertex3f (x[6], y[2], j*dc->frame_depth/2);
1372 glTranslatef (0.5, 0.5, 0);
1373 glRotatef (90, 0, 0, 1);
1374 glTranslatef (-0.5, -0.5, 0);
1394 tess_error_cb (GLenum errorCode)
1396 fprintf (stderr, "%s: tesselation error: %s\n",
1397 progname, gluErrorString(errorCode));
1402 tess_combine_cb (GLdouble coords[3], GLdouble *d[4], GLfloat w[4],
1403 GLdouble **data_out)
1405 GLdouble *new = (GLdouble *) malloc (3 * sizeof(*new));
1415 tess_vertex_cb (void *vertex_data, void *closure)
1417 tess_out *to = (tess_out *) closure;
1418 GLdouble *v = (GLdouble *) vertex_data;
1419 to->points[to->i++] = v[0];
1420 to->points[to->i++] = v[1];
1421 to->points[to->i++] = v[2];
1426 tess_begin_cb (GLenum which)
1437 #endif /* HAVE_TESS */
1441 make_pizza (logo_configuration *dc, int facetted, int wire)
1444 int topfaces = (facetted ? 48 : 120);
1445 int discfaces = (facetted ? 12 : 120);
1446 int npoints = topfaces * 2 + 100;
1447 GLdouble *points = (GLdouble *) calloc (npoints * 3, sizeof(GLdouble));
1449 GLdouble *holes = (GLdouble *) calloc (topfaces*nholes*3, sizeof(GLdouble));
1451 GLfloat step = M_PI * 2 / 6 / topfaces;
1452 GLfloat thick2 = (dc->gasket_thickness / dc->gasket_size) / 4;
1453 GLfloat th, x, y, s;
1459 tess_out TO, *to = &TO;
1460 GLUtesselator *tess = gluNewTess();
1462 to->points = (GLdouble *) calloc (topfaces * 20, sizeof(GLdouble));
1465 # ifndef _GLUfuncptr
1466 # define _GLUfuncptr void(*)(void)
1469 gluTessCallback(tess,GLU_TESS_BEGIN, (_GLUfuncptr)tess_begin_cb);
1470 gluTessCallback(tess,GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv);
1471 gluTessCallback(tess,GLU_TESS_END, (_GLUfuncptr)tess_end_cb);
1472 gluTessCallback(tess,GLU_TESS_COMBINE, (_GLUfuncptr)tess_combine_cb);
1473 gluTessCallback(tess,GLU_TESS_ERROR, (_GLUfuncptr)tess_error_cb);
1475 gluTessProperty (tess, GLU_TESS_BOUNDARY_ONLY, wire);
1476 gluTessProperty (tess,GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
1478 # endif /* HAVE_TESS */
1483 glRotatef (180, 0, 0, 1);
1485 glRotatef (90, 0, 1, 0);
1486 glTranslatef (-0.53, 0, 0);
1487 glRotatef (-30, 0, 0, 1);
1489 /* Compute the wedge */
1502 for (i = 0; i < countof(edge)/2; i++)
1504 points[j++] = edge[i*2+1];
1505 points[j++] = edge[i*2];
1511 s = 0.798; /* radius of end of slice, before crust gap */
1512 for (i = 0; i < topfaces; i++)
1514 points[j++] = cos(th) * s;
1515 points[j++] = sin(th) * s;
1532 for (i = 0; i < countof(edge)/2; i++)
1534 points[j++] = edge[i*2+1];
1535 points[j++] = edge[i*2];
1542 /* Draw the rim of the slice */
1543 glBegin (wire ? GL_LINES : GL_QUADS);
1546 for (i = (wire ? 0 : 1); i < endpoints; i++)
1548 GLdouble *p = points + (i*3);
1550 do_normal (p[0], p[1], -thick2,
1555 glVertex3f (x, y, -thick2);
1556 glVertex3f (x, y, thick2);
1558 glVertex3f (p[0], p[1], thick2);
1559 glVertex3f (p[0], p[1], -thick2);
1565 do_normal (points[0], points[1], -thick2,
1566 points[0], points[1], thick2,
1568 glVertex3f (x, y, -thick2);
1569 glVertex3f (x, y, thick2);
1570 glVertex3f (points[0], points[1], thick2);
1571 glVertex3f (points[0], points[1], -thick2);
1578 /* Outline of slice */
1579 glBegin (GL_LINE_LOOP);
1580 for (i = 0; i < endpoints; i++)
1581 glVertex3f (points[i*3], points[i*3+1], -thick2);
1583 glBegin (GL_LINE_LOOP);
1584 for (i = 0; i < endpoints; i++)
1585 glVertex3f (points[i*3], points[i*3+1], thick2);
1588 # endif /* HAVE_TESS */
1590 /* Compute the holes */
1591 step = M_PI * 2 / discfaces;
1592 for (k = 0; k < nholes; k++)
1594 GLdouble *p = holes + (discfaces * 3 * k);
1598 case 0: x = 0.34; y = 0.17; s = 0.05; break;
1599 case 1: x = 0.54; y = 0.17; s = 0.06; break;
1600 case 2: x = 0.55; y = 0.36; s = 0.06; break;
1601 default: abort(); break;
1603 for (i = 0; i < discfaces; i++)
1605 p[j++] = x + cos(M_PI*2 - th) * s;
1606 p[j++] = y + sin(M_PI*2 - th) * s;
1613 /* Draw the inside rim of the holes */
1614 for (k = 0; k < nholes; k++)
1616 GLdouble *p = holes + (discfaces * 3 * k);
1618 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1619 for (i = 0; i < discfaces; i++)
1621 GLdouble *p2 = p + (i*3);
1623 do_normal (p2[0], p2[1], -thick2,
1624 p2[0], p2[1], thick2,
1625 p2[-3], p2[-2], thick2);
1626 glVertex3f (p2[0], p2[1], -thick2);
1627 glVertex3f (p2[0], p2[1], thick2);
1630 glVertex3f (p[0], p[1], -thick2);
1631 glVertex3f (p[0], p[1], thick2);
1637 /* Outline of holes */
1638 glBegin (GL_LINE_LOOP);
1639 for (i = 0; i < discfaces; i++)
1640 glVertex3f (p[i*3], p[i*3+1], -thick2);
1642 glBegin (GL_LINE_LOOP);
1643 for (i = 0; i < discfaces; i++)
1644 glVertex3f (p[i*3], p[i*3+1], thick2);
1647 # endif /* !HAVE_TESS */
1651 glTranslatef (0, 0, -thick2);
1652 for (y = 0; y <= 1; y++)
1654 if (y) glTranslatef (0, 0, thick2*2);
1656 /* A non-convex polygon */
1657 gluTessBeginPolygon (tess, to);
1659 glNormal3f (0, 0, (y > 0 ? 1 : -1));
1660 gluTessNormal (tess, 0, 0, (y > 0 ? 1 : -1));
1661 glFrontFace (GL_CCW);
1663 /* Tess the wedge */
1664 gluTessBeginContour (tess);
1665 for (i = 0; i < endpoints; i++)
1667 GLdouble *p = points + (i*3);
1668 gluTessVertex (tess, p, p);
1671 gluTessVertex (tess, points, points);
1672 gluTessEndContour (tess);
1674 /* Tess the holes */
1675 for (k = 0; k < nholes; k++)
1677 GLdouble *p = holes + (discfaces * 3 * k);
1678 gluTessBeginContour (tess);
1679 for (i = 0; i < discfaces; i++)
1681 GLdouble *p2 = p + (i*3);
1682 gluTessVertex (tess, p2, p2);
1685 gluTessEndContour (tess);
1688 gluTessEndPolygon (tess);
1691 glTranslatef (0, 0, -thick2);
1693 # else /* !HAVE_TESS */
1696 glDisableClientState (GL_COLOR_ARRAY);
1697 glDisableClientState (GL_NORMAL_ARRAY);
1698 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1699 glEnableClientState (GL_VERTEX_ARRAY);
1700 glVertexPointer (3, GL_FLOAT, 0, dnapizza_triangles);
1702 glTranslatef(0, 0, thick2);
1703 glNormal3f (0, 0, 1);
1704 glFrontFace (GL_CW);
1705 glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
1707 glTranslatef(0, 0, -thick2*2);
1708 glNormal3f (0, 0, -1);
1709 glFrontFace (GL_CCW);
1710 glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
1712 glTranslatef(0, 0, thick2);
1714 # endif /* !HAVE_TESS */
1717 /* Compute the crust */
1719 s = 0.861; /* radius of inside of crust */
1720 step = M_PI * 2 / 6 / topfaces;
1723 for (i = 0; i < topfaces; i++)
1725 points[j++] = cos(th) * s;
1726 points[j++] = sin(th) * s;
1732 for (i = 0; i < topfaces; i++)
1734 points[j++] = cos(th) * s;
1735 points[j++] = sin(th) * s;
1740 /* Draw the rim of the crust */
1741 glFrontFace (GL_CCW);
1742 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1743 for (i = 0; i < topfaces * 2; i++)
1745 GLdouble *p = points + (i*3);
1746 if (i == 0 || i == (topfaces*2)-1)
1747 glNormal3f (0, -1, 0);
1748 else if (i == topfaces-1 || i == topfaces)
1749 glNormal3f (0, 1, 0);
1751 do_normal (p[-3], p[-2], thick2,
1753 p[0], p[1], -thick2);
1754 glVertex3f (p[0], p[1], -thick2);
1755 glVertex3f (p[0], p[1], thick2);
1758 glVertex3f (points[0], points[1], -thick2);
1759 glVertex3f (points[0], points[1], thick2);
1765 glBegin (GL_LINE_STRIP);
1766 for (i = 0; i < topfaces * 2; i++)
1768 GLdouble *p = points + (i*3);
1769 glVertex3f (p[0], p[1], -thick2);
1772 glVertex3f (points[0], points[1], -thick2);
1775 glBegin (GL_LINE_STRIP);
1776 for (i = 0; i < topfaces * 2; i++)
1778 GLdouble *p = points + (i*3);
1779 glVertex3f (p[0], p[1], thick2);
1782 glVertex3f (points[0], points[1], thick2);
1786 /* Draw the top of the crust */
1789 glFrontFace (GL_CW);
1790 glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP);
1791 glNormal3f (0, 0, -1);
1793 for (i = 0; i < topfaces; i++)
1795 int ii = topfaces + (topfaces - i - 1);
1796 GLdouble *p1 = points + (i*3);
1797 GLdouble *p2 = points + (ii*3);
1798 glVertex3f (p1[0], p1[1], -thick2);
1799 glVertex3f (p2[0], p2[1], -thick2);
1805 /* Draw the bottom of the crust */
1806 glFrontFace (GL_CCW);
1807 glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
1808 glNormal3f (0, 0, 1);
1809 for (i = 0; i < topfaces; i++)
1811 int ii = topfaces + (topfaces - i - 1);
1812 GLdouble *p1 = points + (i*3);
1813 GLdouble *p2 = points + (ii*3);
1814 glVertex3f (p1[0], p1[1], thick2);
1815 glVertex3f (p2[0], p2[1], thick2);
1823 gluDeleteTess (tess);
1825 # endif /* HAVE_TESS */
1838 /* Window management, etc
1841 reshape_logo (ModeInfo *mi, int width, int height)
1843 GLfloat h = (GLfloat) height / (GLfloat) width;
1845 glViewport (0, 0, (GLint) width, (GLint) height);
1847 glMatrixMode(GL_PROJECTION);
1849 gluPerspective (30.0, 1/h, 1.0, 100.0);
1851 glMatrixMode(GL_MODELVIEW);
1853 gluLookAt( 0.0, 0.0, 30.0,
1857 glClear(GL_COLOR_BUFFER_BIT);
1862 gl_init (ModeInfo *mi)
1864 /* logo_configuration *dc = &dcs[MI_SCREEN(mi)]; */
1865 int wire = MI_IS_WIREFRAME(mi);
1867 GLfloat position[] = {0, 0, 0, 0};
1868 GLfloat direction[] = {3, -1, -3};
1870 position[0] = -direction[0];
1871 position[1] = -direction[1];
1872 position[2] = -direction[2];
1876 glLightfv(GL_LIGHT0, GL_POSITION, position);
1877 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction);
1878 glShadeModel(GL_SMOOTH);
1879 glEnable(GL_NORMALIZE);
1880 glEnable(GL_CULL_FACE);
1881 glEnable(GL_LIGHTING);
1882 glEnable(GL_LIGHT0);
1883 glEnable(GL_DEPTH_TEST);
1889 init_logo (ModeInfo *mi)
1891 logo_configuration *dc;
1892 int do_gasket = get_boolean_resource(mi->dpy, "doGasket", "Boolean");
1893 int do_helix = get_boolean_resource(mi->dpy, "doHelix", "Boolean");
1894 int do_ladder = (do_helix &&
1895 get_boolean_resource(mi->dpy, "doLadder", "Boolean"));
1896 int do_frame = get_boolean_resource(mi->dpy, "doFrame", "Boolean");
1897 GLfloat helix_rot = 147.0;
1899 if (!do_gasket && !do_helix)
1901 fprintf (stderr, "%s: no helix or gasket?\n", progname);
1906 dcs = (logo_configuration *)
1907 calloc (MI_NUM_SCREENS(mi), sizeof (logo_configuration));
1909 fprintf(stderr, "%s: out of memory\n", progname);
1914 dc = &dcs[MI_SCREEN(mi)];
1916 if ((dc->glx_context = init_GL(mi)) != NULL) {
1918 reshape_logo (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1921 dc->wall_facets = get_integer_resource(mi->dpy, "wallFacets", "Integer");
1922 dc->bar_facets = get_integer_resource(mi->dpy, "barFacets", "Integer");
1923 dc->clockwise = get_boolean_resource(mi->dpy, "clockwise", "Boolean");
1924 dc->turns = get_float_resource(mi->dpy, "turns", "Float");
1925 dc->turn_spacing = get_float_resource(mi->dpy, "turnSpacing", "Float");
1926 dc->bar_spacing = get_float_resource(mi->dpy, "barSpacing", "Float");
1927 dc->wall_height = get_float_resource(mi->dpy, "wallHeight", "Float");
1928 dc->wall_thickness = get_float_resource(mi->dpy, "wallThickness", "Float");
1929 dc->bar_thickness = get_float_resource(mi->dpy, "barThickness", "Float");
1930 dc->wall_taper = get_float_resource(mi->dpy, "wallTaper", "Float");
1932 dc->gasket_size = get_float_resource(mi->dpy,"gasketSize", "Float");
1933 dc->gasket_depth = get_float_resource(mi->dpy,"gasketDepth", "Float");
1934 dc->gasket_thickness = get_float_resource(mi->dpy,"gasketThickness","Float");
1936 dc->frame_size = get_float_resource(mi->dpy, "frameSize", "Float");
1937 dc->frame_depth = get_float_resource(mi->dpy, "frameDepth", "Float");
1938 dc->frame_thickness = get_float_resource(mi->dpy, "frameThickness", "Float");
1939 dc->triangle_size = get_float_resource(mi->dpy, "triangleSize", "Float");
1941 dc->speed = get_float_resource(mi->dpy, "speed", "Float");
1944 char *s = get_string_resource (MI_DISPLAY (mi), "mode", "String");
1945 if (!s || !*s || !strcasecmp (s, "helix"))
1947 else if (!strcasecmp (s, "pizza"))
1949 else if (!strcasecmp (s, "both"))
1953 fprintf (stderr, "%s: mode must be helix, pizza or both, not \"%s\"\n",
1959 dc->anim_state = (dc->mode == BOTH
1960 ? ((random() & 1) ? HELIX : PIZZA)
1968 char *color_name = get_string_resource (mi->dpy, "foreground", "Foreground");
1970 for (s2 = color_name + strlen(color_name) - 1; s2 > color_name; s2--)
1971 if (*s2 == ' ' || *s2 == '\t')
1976 if (! XParseColor (MI_DISPLAY(mi), mi->xgwa.colormap, color_name, &xcolor))
1978 fprintf (stderr, "%s: can't parse color %s\n", progname, color_name);
1982 dc->color[0] = xcolor.red / 65535.0;
1983 dc->color[1] = xcolor.green / 65535.0;
1984 dc->color[2] = xcolor.blue / 65535.0;
1988 dc->trackball = gltrackball_init ();
1990 dc->gasket_spinnerx.probability = 0.1;
1991 dc->gasket_spinnery.probability = 0.1;
1992 dc->gasket_spinnerz.probability = 1.0;
1994 dc->helix_spinnerz.probability = 0.6;
1996 dc->pizza_spinnerz.probability = 0.6;
1997 dc->pizza_spinnery.probability = 0.6;
1999 dc->scene_spinnerx.probability = 0.1;
2000 dc->scene_spinnery.probability = 0.0;
2002 dc->frame_spinner.probability = 5.0;
2004 /* start the frame off-screen */
2005 dc->frame_spinner.spinning_p = True;
2006 dc->frame_spinner.position = 0.3;
2007 dc->frame_spinner.speed = 0.001;
2009 if (dc->speed > 0) /* start off with the gasket in motion */
2011 dc->gasket_spinnerz.spinning_p = True;
2012 dc->gasket_spinnerz.speed = (0.002
2013 * ((random() & 1) ? 1 : -1)
2017 # ifdef DXF_OUTPUT_HACK
2019 dc->frame_depth = dc->gasket_depth;
2024 glRotatef(90, 1, 0, 0);
2025 glRotatef(90, 0, 0, 1);
2026 make_pizza (dc, 0, 0);
2029 glRotatef(helix_rot, 0, 0, 1);
2030 make_ladder (dc, 0, 0);
2031 make_helix (dc, 0, 0);
2032 glRotatef (180, 0, 0, 1);
2033 make_helix (dc, 0, 0);
2037 make_gasket (dc, 0);
2046 dc->helix_list = glGenLists (1);
2047 glNewList (dc->helix_list, GL_COMPILE);
2048 glRotatef(helix_rot, 0, 0, 1);
2049 if (do_ladder) dc->polys[0] += make_ladder (dc, 0, 0);
2050 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
2051 glRotatef(180, 0, 0, 1);
2052 if (do_helix) dc->polys[0] += make_helix (dc, 0, 0);
2057 dc->helix_list_wire = glGenLists (1);
2058 glNewList (dc->helix_list_wire, GL_COMPILE);
2059 /* glRotatef(helix_rot, 0, 0, 1); wtf? */
2060 if (do_ladder) dc->polys[1] += make_ladder (dc, 1, 1);
2061 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
2062 glRotatef(180, 0, 0, 1);
2063 if (do_helix) dc->polys[1] += make_helix (dc, 1, 1);
2068 dc->helix_list_facetted = glGenLists (1);
2069 glNewList (dc->helix_list_facetted, GL_COMPILE);
2070 glRotatef(helix_rot, 0, 0, 1);
2071 if (do_ladder) dc->polys[2] += make_ladder (dc, 1, 0);
2072 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
2073 glRotatef(180, 0, 0, 1);
2074 if (do_helix) dc->polys[2] += make_helix (dc, 1, 0);
2078 dc->pizza_list = glGenLists (1);
2079 glNewList (dc->pizza_list, GL_COMPILE);
2080 if (do_frame) dc->polys[5] += make_pizza (dc, 0, 0);
2083 dc->pizza_list_wire = glGenLists (1);
2084 glNewList (dc->pizza_list_wire, GL_COMPILE);
2085 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 1);
2088 dc->pizza_list_facetted = glGenLists (1);
2089 glNewList (dc->pizza_list_facetted, GL_COMPILE);
2090 if (do_frame) dc->polys[6] += make_pizza (dc, 1, 0);
2093 dc->gasket_list = glGenLists (1);
2094 glNewList (dc->gasket_list, GL_COMPILE);
2095 if (do_gasket) dc->polys[3] += make_gasket (dc, 0);
2098 dc->gasket_list_wire = glGenLists (1);
2099 glNewList (dc->gasket_list_wire, GL_COMPILE);
2100 if (do_gasket) dc->polys[4] += make_gasket (dc, 1);
2103 dc->frame_list = glGenLists (1);
2104 glNewList (dc->frame_list, GL_COMPILE);
2105 if (do_frame) dc->polys[5] += make_frame (dc, 0);
2108 dc->frame_list_wire = glGenLists (1);
2109 glNewList (dc->frame_list_wire, GL_COMPILE);
2110 if (do_frame) dc->polys[6] += make_frame (dc, 1);
2113 /* When drawing both solid and wireframe objects,
2114 make sure the wireframe actually shows up! */
2115 glEnable (GL_POLYGON_OFFSET_FILL);
2116 glPolygonOffset (1.0, 1.0);
2121 logo_handle_event (ModeInfo *mi, XEvent *event)
2123 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2125 if (event->xany.type == ButtonPress &&
2126 event->xbutton.button == Button1)
2128 dc->button_down_p = True;
2129 gltrackball_start (dc->trackball,
2130 event->xbutton.x, event->xbutton.y,
2131 MI_WIDTH (mi), MI_HEIGHT (mi));
2134 else if (event->xany.type == ButtonRelease &&
2135 event->xbutton.button == Button1)
2137 dc->button_down_p = False;
2140 else if (event->xany.type == ButtonPress &&
2141 (event->xbutton.button == Button4 ||
2142 event->xbutton.button == Button5 ||
2143 event->xbutton.button == Button6 ||
2144 event->xbutton.button == Button7))
2146 gltrackball_mousewheel (dc->trackball, event->xbutton.button, 10,
2147 !!event->xbutton.state);
2150 else if (event->xany.type == MotionNotify &&
2153 gltrackball_track (dc->trackball,
2154 event->xmotion.x, event->xmotion.y,
2155 MI_WIDTH (mi), MI_HEIGHT (mi));
2164 tick_spinner (ModeInfo *mi, spinner *s)
2166 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2168 if (dc->speed == 0) return;
2169 if (dc->button_down_p) return;
2173 s->position += s->speed;
2174 if (s->position >= 1.0 || s->position <= -1.0)
2178 s->spinning_p = False;
2181 else if (s->probability &&
2182 (random() % (int) (PROBABILITY_SCALE / s->probability)) == 0)
2185 s->spinning_p = True;
2188 s->speed = dc->speed * (frand(ss/3) + frand(ss/3) + frand(ss/3));
2189 } while (s->speed <= 0);
2191 s->speed = -s->speed;
2197 link_spinners (ModeInfo *mi, spinner *s0, spinner *s1)
2199 if (s0->spinning_p && !s1->spinning_p)
2201 GLfloat op = s1->probability;
2202 s1->probability = PROBABILITY_SCALE;
2203 tick_spinner (mi, s1);
2204 s1->probability = op;
2210 draw_logo (ModeInfo *mi)
2212 logo_configuration *dc = &dcs[MI_SCREEN(mi)];
2213 Display *dpy = MI_DISPLAY(mi);
2214 Window window = MI_WINDOW(mi);
2215 int wire = MI_IS_WIREFRAME(mi);
2217 GLfloat specular[] = {0.8, 0.8, 0.8, 1.0};
2218 GLfloat shininess = 50.0;
2221 if (!dc->glx_context)
2224 mi->polygon_count = 0;
2225 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(dc->glx_context));
2228 dc->wire_overlay == 0 &&
2229 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
2230 dc->wire_overlay = ((random() % 200) +
2234 tick_spinner (mi, &dc->gasket_spinnerx);
2235 tick_spinner (mi, &dc->gasket_spinnery);
2236 tick_spinner (mi, &dc->gasket_spinnerz);
2237 tick_spinner (mi, &dc->helix_spinnerz);
2238 tick_spinner (mi, &dc->pizza_spinnery);
2239 tick_spinner (mi, &dc->pizza_spinnerz);
2240 tick_spinner (mi, &dc->scene_spinnerx);
2241 tick_spinner (mi, &dc->scene_spinnery);
2242 tick_spinner (mi, &dc->frame_spinner);
2243 link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery);
2247 static double i = 0.0;
2248 dc->anim_state = HELIX;
2249 dc->wire_overlay = 0;
2250 dc->gasket_spinnerx.spinning_p = 0;
2251 dc->gasket_spinnery.spinning_p = 0;
2252 dc->gasket_spinnerz.spinning_p = 0;
2253 dc->helix_spinnerz.spinning_p = 0;
2254 dc->pizza_spinnery.spinning_p = 0;
2255 dc->pizza_spinnerz.spinning_p = 0;
2256 dc->scene_spinnerx.spinning_p = 0;
2257 dc->scene_spinnery.spinning_p = 0;
2258 dc->frame_spinner.spinning_p = 0;
2259 dc->frame_spinner.position = 0.3;
2260 dc->gasket_spinnerz.position = i;
2261 dc->helix_spinnerz.position = i;
2265 # endif /* LINEAR */
2267 switch (dc->anim_state)
2270 if (dc->mode == BOTH &&
2271 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
2272 dc->anim_state = HELIX_OUT;
2276 dc->anim_ratio += 0.1 * dc->speed;
2277 if (dc->anim_ratio >= 1.0)
2279 dc->anim_ratio = 0.0;
2280 dc->anim_state = PIZZA_IN;
2285 dc->anim_ratio += 0.1 * dc->speed;
2286 if (dc->anim_ratio >= 1.0)
2288 dc->anim_ratio = 0.0;
2289 dc->anim_state = PIZZA;
2294 if (dc->mode == BOTH &&
2295 (random() % (int) (PROBABILITY_SCALE / 0.2)) == 0)
2296 dc->anim_state = PIZZA_OUT;
2300 dc->anim_ratio += 0.1 * dc->speed;
2301 if (dc->anim_ratio >= 1.0)
2303 dc->anim_ratio = 0.0;
2304 dc->anim_state = HELIX_IN;
2309 dc->anim_ratio += 0.1 * dc->speed;
2310 if (dc->anim_ratio >= 1.0)
2312 dc->anim_ratio = 0.0;
2313 dc->anim_state = HELIX;
2322 pizza_p = (dc->anim_state == PIZZA ||
2323 dc->anim_state == PIZZA_IN ||
2324 dc->anim_state == PIZZA_OUT);
2326 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2329 glRotatef(current_device_rotation(), 0, 0, 1);
2331 GLfloat scale = 1.8;
2335 glScalef(scale, scale, scale);
2337 glColor3f(dc->color[0], dc->color[1], dc->color[2]);
2339 /* Draw frame before trackball rotation */
2341 GLfloat p = (dc->frame_spinner.position >= 0
2342 ? dc->frame_spinner.position
2343 : -dc->frame_spinner.position);
2344 GLfloat size = (p > 0.5 ? 1-p : p);
2345 scale = 1 + (size * 10);
2347 /* gltrackball_rotate (dc->trackball); */
2348 glRotatef(90, 1, 0, 0);
2349 glRotatef(90, 0, 0, 1);
2351 glScalef (1, scale, scale);
2354 glDisable (GL_LIGHTING);
2355 glCallList (dc->frame_list_wire);
2356 mi->polygon_count += dc->polys[6];
2358 else if (dc->wire_overlay != 0)
2360 glCallList (dc->frame_list);
2361 glDisable (GL_LIGHTING);
2362 glColor3fv (dc->color);
2363 glCallList (dc->frame_list_wire);
2364 mi->polygon_count += dc->polys[6];
2365 if (!wire) glEnable (GL_LIGHTING);
2369 glCallList (dc->frame_list);
2370 mi->polygon_count += dc->polys[5];
2375 gltrackball_rotate (dc->trackball);
2377 glRotatef(90, 1, 0, 0);
2378 glRotatef(90, 0, 0, 1);
2381 # define SINIFY(I) (I)
2383 # define SINIFY(I) sin (M_PI/2 * (I))
2386 glRotatef (360 * SINIFY (dc->scene_spinnerx.position), 0, 1, 0);
2387 glRotatef (360 * SINIFY (dc->scene_spinnery.position), 0, 0, 1);
2391 glRotatef (360 * SINIFY (dc->gasket_spinnerx.position), 0, 1, 0);
2392 glRotatef (360 * SINIFY (dc->gasket_spinnery.position), 0, 0, 1);
2393 glRotatef (360 * SINIFY (dc->gasket_spinnerz.position), 1, 0, 0);
2395 memcpy (gcolor, dc->color, sizeof (dc->color));
2396 if (dc->wire_overlay != 0)
2398 gcolor[0] = gcolor[1] = gcolor[2] = 0;
2399 specular[0] = specular[1] = specular[2] = 0;
2402 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
2403 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
2404 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shininess);
2408 glDisable (GL_LIGHTING);
2409 glCallList (dc->gasket_list_wire);
2410 mi->polygon_count += dc->polys[4];
2412 else if (dc->wire_overlay != 0)
2414 glCallList (dc->gasket_list);
2415 glDisable (GL_LIGHTING);
2416 glColor3fv (dc->color);
2417 glCallList (dc->gasket_list_wire);
2418 mi->polygon_count += dc->polys[4];
2419 if (!wire) glEnable (GL_LIGHTING);
2420 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gcolor);
2424 glCallList (dc->gasket_list);
2425 mi->polygon_count += dc->polys[3];
2432 glRotatef (360 * SINIFY (dc->pizza_spinnery.position), 1, 0, 0);
2433 glRotatef (360 * SINIFY (dc->pizza_spinnerz.position), 0, 0, 1);
2437 glRotatef (360 * SINIFY (dc->helix_spinnerz.position), 0, 0, 1);
2440 scale = ((dc->anim_state == PIZZA_IN || dc->anim_state == HELIX_IN)
2442 : ((dc->anim_state == PIZZA_OUT || dc->anim_state == HELIX_OUT)
2443 ? 1.0 - dc->anim_ratio
2445 if (scale <= 0) scale = 0.001;
2446 glScalef (scale, scale, scale);
2450 glDisable (GL_LIGHTING);
2452 glCallList (dc->pizza_list_wire);
2454 glCallList (dc->helix_list_wire);
2455 mi->polygon_count += dc->polys[1];
2457 else if (dc->wire_overlay != 0)
2460 glCallList (dc->pizza_list_facetted);
2462 glCallList (dc->helix_list_facetted);
2464 glDisable (GL_LIGHTING);
2465 glColor3fv (dc->color);
2468 glCallList (dc->pizza_list_wire);
2470 glCallList (dc->helix_list_wire);
2472 mi->polygon_count += dc->polys[2];
2473 if (!wire) glEnable (GL_LIGHTING);
2478 glCallList (dc->pizza_list);
2480 glCallList (dc->helix_list);
2481 mi->polygon_count += dc->polys[0];
2486 if (dc->wire_overlay > 0)
2489 if (mi->fps_p) do_fps (mi);
2492 glXSwapBuffers(dpy, window);
2495 XSCREENSAVER_MODULE_2 ("DNALogo", dnalogo, logo)