1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* pipes --- 3D selfbuiding pipe system */
5 static const char sccsid[] = "@(#)pipes.c 4.07 97/11/24 xlockmore";
9 * Permission to use, copy, modify, and distribute this software and its
10 * documentation for any purpose and without fee is hereby granted,
11 * provided that the above copyright notice appear in all copies and that
12 * both that copyright notice and this permission notice appear in
13 * supporting documentation.
15 * This file is provided AS IS with no warranties of any kind. The author
16 * shall have no liability with respect to the infringement of copyrights,
17 * trade secrets or any patents by this file or any part thereof. In no
18 * event will the author be liable for any lost revenue or profits or
19 * other special, indirect and consequential damages.
21 * This program was inspired on a WindowsNT(R)'s screen saver. It was written
22 * from scratch and it was not based on any other source code.
24 * ==========================================================================
25 * The routine myElbow is derivated from the doughnut routine from the MesaGL
26 * library (more especifically the Mesaaux library) written by Brian Paul.
27 * ==========================================================================
29 * Thanks goes to Brian Paul for making it possible and inexpensive to use
32 * Since I'm not a native English speaker, my apologies for any grammatical
35 * My e-mail address is
37 * Marcelo F. Vianna (Apr-09-1997)
40 * 24-Jun-12: Eliminate single-buffer dependency.
41 * 29-Apr-97: Factory equipment by Ed Mackey. Productive day today, eh?
42 * 29-Apr-97: Less tight turns Jeff Epler <jepler@inetnebr.com>
43 * 29-Apr-97: Efficiency speed-ups by Marcelo F. Vianna
46 /* This program was originally written to be single-buffered: it kept
47 building up new objects in the front buffer by never clearing the
48 depth or color buffers at the end of each frame. In that way, it
49 was drawing a very small number of polygons per frame. However,
50 modern systems make it difficult to live in a single-buffered world
51 like that. So I changed it to re-generate the scene at every
52 frame, which makes it vastly less efficient, but also, makes it
53 work right on modern hardware. It generates the entire system up
54 front, putting each "frame" of the animation into its own display
55 list; then it draws successively more of those display lists each
56 time the redisplay method is called. When it reaches the end,
57 it regenerates a new system and re-populates the existing display
62 # define DEFAULTS "*delay: 10000 \n" \
66 "*showFPS: False \n" \
67 "*fpsSolid: True \n" \
68 "*wireframe: False \n" \
69 "*suppressRotationAnimation: True\n" \
71 # define refresh_pipes 0
72 # define release_pipes 0
73 # include "xlockmore.h" /* from the xscreensaver distribution */
74 #else /* !STANDALONE */
75 # include "xlock.h" /* from the xlockmore distribution */
76 #endif /* !STANDALONE */
83 # include <X11/Xlib.h>
90 #endif /* HAVE_JWZGLES */
95 #include "gltrackball.h"
97 #define DEF_FACTORY "2"
98 #define DEF_FISHEYE "True"
99 #define DEF_TIGHTTURNS "False"
100 #define DEF_ROTATEPIPES "True"
101 #define NofSysTypes 3
104 static Bool fisheye, tightturns, rotatepipes;
106 static XrmOptionDescRec opts[] =
108 {"-factory", ".pipes.factory", XrmoptionSepArg, 0},
109 {"-fisheye", ".pipes.fisheye", XrmoptionNoArg, "on"},
110 {"+fisheye", ".pipes.fisheye", XrmoptionNoArg, "off"},
111 {"-tightturns", ".pipes.tightturns", XrmoptionNoArg, "on"},
112 {"+tightturns", ".pipes.tightturns", XrmoptionNoArg, "off"},
113 {"-rotatepipes", ".pipes.rotatepipes", XrmoptionNoArg, "on"},
114 {"+rotatepipes", ".pipes.rotatepipes", XrmoptionNoArg, "off"},
116 static argtype vars[] =
118 {&factory, "factory", "Factory", DEF_FACTORY, t_Int},
119 {&fisheye, "fisheye", "Fisheye", DEF_FISHEYE, t_Bool},
120 {&tightturns, "tightturns", "Tightturns", DEF_TIGHTTURNS, t_Bool},
121 {&rotatepipes, "rotatepipes", "Rotatepipes", DEF_ROTATEPIPES, t_Bool},
123 static OptionStruct desc[] =
125 {"-factory num", "how much extra equipment in pipes (0 for none)"},
126 {"-/+fisheye", "turn on/off zoomed-in view of pipes"},
127 {"-/+tightturns", "turn on/off tight turns"},
128 {"-/+rotatepipes", "turn on/off pipe system rotation per screenful"},
131 ENTRYPOINT ModeSpecOpt pipes_opts =
132 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
135 ModStruct pipes_description =
136 {"pipes", "init_pipes", "draw_pipes", NULL,
138 "change_pipes", NULL, &pipes_opts,
139 1000, 2, 5, 500, 4, 1.0, "",
140 "Shows a selfbuilding pipe system", 0, NULL};
144 #define Scale4Window 0.1
146 #define one_third 0.3333333333333333333
158 #define DEFINEDCOLORS 7
159 #define elbowradius 0.5
161 /*************************************************************************/
166 int Cells[HCELLS][VCELLS][HCELLS];
167 int usedcolors[DEFINEDCOLORS];
174 int number_of_systems;
179 const float *system_color;
180 GLfloat initial_rotation;
181 GLuint valve, bolts, betweenbolts, elbowbolts, elbowcoins;
182 GLuint guagehead, guageface, guagedial, guageconnector, teapot;
184 GLXContext *glx_context;
187 trackball_state *trackball;
188 GLuint *dlists, *poly_counts;
189 int dlist_count, dlist_size;
190 int system_index, system_size;
196 extern struct lwo LWO_BigValve, LWO_PipeBetweenBolts, LWO_Bolts3D;
197 extern struct lwo LWO_GuageHead, LWO_GuageFace, LWO_GuageDial, LWO_GuageConnector;
198 extern struct lwo LWO_ElbowBolts, LWO_ElbowCoins;
200 static const float front_shininess[] = {60.0};
201 static const float front_specular[] = {0.7, 0.7, 0.7, 1.0};
202 static const float ambient0[] = {0.4, 0.4, 0.4, 1.0};
203 static const float diffuse0[] = {1.0, 1.0, 1.0, 1.0};
204 static const float ambient1[] = {0.2, 0.2, 0.2, 1.0};
205 static const float diffuse1[] = {0.5, 0.5, 0.5, 1.0};
206 static const float position0[] = {1.0, 1.0, 1.0, 0.0};
207 static const float position1[] = {-1.0, -1.0, 1.0, 0.0};
208 static const float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};
209 static const float lmodel_twoside[] = {GL_TRUE};
211 static const float MaterialRed[] = {0.7, 0.0, 0.0, 1.0};
212 static const float MaterialGreen[] = {0.1, 0.5, 0.2, 1.0};
213 static const float MaterialBlue[] = {0.0, 0.0, 0.7, 1.0};
214 static const float MaterialCyan[] = {0.2, 0.5, 0.7, 1.0};
215 static const float MaterialYellow[] = {0.7, 0.7, 0.0, 1.0};
216 static const float MaterialMagenta[] = {0.6, 0.2, 0.5, 1.0};
217 static const float MaterialWhite[] = {0.7, 0.7, 0.7, 1.0};
218 static const float MaterialGray[] = {0.2, 0.2, 0.2, 1.0};
220 static pipesstruct *pipes = NULL;
224 MakeTube(ModeInfo *mi, int direction)
226 Bool wire = MI_IS_WIREFRAME(mi);
228 float SINan_3, COSan_3;
229 int facets = (wire ? 5 : 24);
231 /*dirUP = 00000000 */
232 /*dirDOWN = 00000001 */
233 /*dirLEFT = 00000010 */
234 /*dirRIGHT = 00000011 */
235 /*dirNEAR = 00000100 */
236 /*dirFAR = 00000101 */
238 if (!(direction & 4)) {
239 glRotatef(90.0, (direction & 2) ? 0.0 : 1.0,
240 (direction & 2) ? 1.0 : 0.0, 0.0);
242 glBegin(wire ? GL_LINE_STRIP : GL_QUAD_STRIP);
243 for (an = 0.0; an <= 2.0 * M_PI; an += M_PI * 2 / facets) {
244 glNormal3f((COSan_3 = cos(an) / 3.0), (SINan_3 = sin(an) / 3.0), 0.0);
245 glVertex3f(COSan_3, SINan_3, one_third);
246 glVertex3f(COSan_3, SINan_3, -one_third);
253 mySphere(float radius, Bool wire)
256 GLUquadricObj *quadObj;
258 quadObj = gluNewQuadric();
259 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
260 gluSphere(quadObj, radius, 16, 16);
261 gluDeleteQuadric(quadObj);
264 glScalef (radius, radius, radius);
265 glRotatef (90, 1, 0, 0);
266 unit_sphere (16, 16, wire);
272 myElbow(ModeInfo * mi, int bolted)
274 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
275 Bool wire = MI_IS_WIREFRAME(mi);
277 int nsides = (wire ? 6 : 25);
283 GLfloat p0[3], p1[3], p2[3], p3[3];
284 GLfloat n0[3], n1[3], n2[3], n3[3];
285 GLfloat COSphi, COSphi1, COStheta, COStheta1;
286 GLfloat _SINtheta, _SINtheta1;
288 for (i = 0; i <= rings / 4; i++) {
289 GLfloat theta, theta1;
291 theta = (GLfloat) i *2.0 * M_PI / rings;
293 theta1 = (GLfloat) (i + 1) * 2.0 * M_PI / rings;
294 for (j = 0; j < nsides; j++) {
297 phi = (GLfloat) j *2.0 * M_PI / nsides;
299 phi1 = (GLfloat) (j + 1) * 2.0 * M_PI / nsides;
301 p0[0] = (COStheta = cos(theta)) * (R + r * (COSphi = cos(phi)));
302 p0[1] = (_SINtheta = -sin(theta)) * (R + r * COSphi);
304 p1[0] = (COStheta1 = cos(theta1)) * (R + r * COSphi);
305 p1[1] = (_SINtheta1 = -sin(theta1)) * (R + r * COSphi);
307 p2[0] = COStheta1 * (R + r * (COSphi1 = cos(phi1)));
308 p2[1] = _SINtheta1 * (R + r * COSphi1);
310 p3[0] = COStheta * (R + r * COSphi1);
311 p3[1] = _SINtheta * (R + r * COSphi1);
313 n0[0] = COStheta * COSphi;
314 n0[1] = _SINtheta * COSphi;
316 n1[0] = COStheta1 * COSphi;
317 n1[1] = _SINtheta1 * COSphi;
319 n2[0] = COStheta1 * COSphi1;
320 n2[1] = _SINtheta1 * COSphi1;
322 n3[0] = COStheta * COSphi1;
323 n3[1] = _SINtheta * COSphi1;
325 p0[2] = p1[2] = r * (n0[2] = n1[2] = sin(phi));
326 p2[2] = p3[2] = r * (n2[2] = n3[2] = sin(phi1));
328 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
342 if (factory > 0 && bolted) {
343 /* Bolt the elbow onto the pipe system */
346 glRotatef(90.0, 0.0, 0.0, -1.0);
347 glRotatef(90.0, 0.0, 1.0, 0.0);
348 glTranslatef(0.0, one_third, one_third);
349 glCallList(pp->elbowcoins);
350 mi->polygon_count += LWO_ElbowCoins.num_pnts/3;
351 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
352 glCallList(pp->elbowbolts);
353 mi->polygon_count += LWO_ElbowBolts.num_pnts/3;
354 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color);
365 FindNeighbors(ModeInfo * mi)
367 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
370 pp->directions[dirUP] = (!pp->Cells[pp->PX][pp->PY + 1][pp->PZ]) ? 1 : 0;
371 pp->ndirections += pp->directions[dirUP];
372 pp->directions[dirDOWN] = (!pp->Cells[pp->PX][pp->PY - 1][pp->PZ]) ? 1 : 0;
373 pp->ndirections += pp->directions[dirDOWN];
374 pp->directions[dirLEFT] = (!pp->Cells[pp->PX - 1][pp->PY][pp->PZ]) ? 1 : 0;
375 pp->ndirections += pp->directions[dirLEFT];
376 pp->directions[dirRIGHT] = (!pp->Cells[pp->PX + 1][pp->PY][pp->PZ]) ? 1 : 0;
377 pp->ndirections += pp->directions[dirRIGHT];
378 pp->directions[dirFAR] = (!pp->Cells[pp->PX][pp->PY][pp->PZ - 1]) ? 1 : 0;
379 pp->ndirections += pp->directions[dirFAR];
380 pp->directions[dirNEAR] = (!pp->Cells[pp->PX][pp->PY][pp->PZ + 1]) ? 1 : 0;
381 pp->ndirections += pp->directions[dirNEAR];
385 SelectNeighbor(ModeInfo * mi)
387 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
391 for (i = 0, j = 0; i < 6; i++) {
392 if (pp->directions[i]) {
398 return dirlist[NRAND(pp->ndirections)];
402 MakeValve(ModeInfo * mi, int newdir)
404 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
406 /* There is a glPopMatrix() right after this subroutine returns. */
410 glRotatef(90.0, 1.0, 0.0, 0.0);
411 glRotatef(NRAND(3) * 90.0, 0.0, 0.0, 1.0);
415 glRotatef(90.0, 0.0, -1.0, 0.0);
416 glRotatef((NRAND(3) * 90.0) - 90.0, 0.0, 0.0, 1.0);
420 glRotatef(NRAND(4) * 90.0, 0.0, 0.0, 1.0);
424 glCallList(pp->betweenbolts);
425 mi->polygon_count += LWO_PipeBetweenBolts.num_pnts/3;
426 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
427 glCallList(pp->bolts);
428 mi->polygon_count += LWO_Bolts3D.num_pnts/3;
429 if (!MI_IS_MONO(mi)) {
430 if (pp->system_color == MaterialRed) {
431 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, NRAND(2) ? MaterialYellow : MaterialBlue);
432 } else if (pp->system_color == MaterialBlue) {
433 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, NRAND(2) ? MaterialRed : MaterialYellow);
434 } else if (pp->system_color == MaterialYellow) {
435 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, NRAND(2) ? MaterialBlue : MaterialRed);
437 switch ((NRAND(3))) {
439 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
442 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlue);
445 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialYellow);
449 glRotatef((GLfloat) (NRAND(90)), 1.0, 0.0, 0.0);
450 glCallList(pp->valve);
451 mi->polygon_count += LWO_BigValve.num_pnts/3;
452 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color);
457 MakeGuage(ModeInfo * mi, int newdir)
459 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
461 /* Can't have a guage on a vertical pipe. */
462 if ((newdir == dirUP) || (newdir == dirDOWN))
465 /* Is there space above this pipe for a guage? */
466 if (!pp->directions[dirUP])
469 /* Yes! Mark the space as used. */
470 pp->Cells[pp->PX][pp->PY + 1][pp->PZ] = 1;
474 if ((newdir == dirLEFT) || (newdir == dirRIGHT))
475 glRotatef(90.0, 0.0, 1.0, 0.0);
476 glCallList(pp->betweenbolts);
477 mi->polygon_count += LWO_PipeBetweenBolts.num_pnts/3;
478 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
479 glCallList(pp->bolts);
480 mi->polygon_count += LWO_Bolts3D.num_pnts/3;
483 glCallList(pp->guageconnector);
484 mi->polygon_count += LWO_GuageConnector.num_pnts/3;
486 glTranslatef(0.0, 1.33333, 0.0);
487 /* Do not change the above to 1 + ONE_THIRD, because */
488 /* the object really is centered on 1.3333300000. */
489 glRotatef(NRAND(270) + 45.0, 0.0, 0.0, -1.0);
490 /* Random rotation for the dial. I love it. */
491 glCallList(pp->guagedial);
492 mi->polygon_count += LWO_GuageDial.num_pnts/3;
495 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color);
496 glCallList(pp->guagehead);
497 mi->polygon_count += LWO_GuageHead.num_pnts/3;
499 /* GuageFace is drawn last, in case of low-res depth buffers. */
500 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
501 glCallList(pp->guageface);
502 mi->polygon_count += LWO_GuageFace.num_pnts/3;
504 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color);
512 build_teapot(ModeInfo *mi)
514 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
515 GLuint list = glGenLists(1);
517 glNewList(list, GL_COMPILE);
518 pp->teapot_polys = unit_teapot (12, MI_IS_WIREFRAME(mi));
525 MakeTeapot(ModeInfo * mi, int newdir)
527 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
532 glRotatef(90.0, 1.0, 0.0, 0.0);
533 glRotatef(NRAND(3) * 90.0, 0.0, 0.0, 1.0);
537 glRotatef(90.0, 0.0, -1.0, 0.0);
538 glRotatef((NRAND(3) * 90.0) - 90.0, 0.0, 0.0, 1.0);
542 glRotatef(NRAND(4) * 90.0, 0.0, 0.0, 1.0);
546 glCallList(pp->teapot);
547 mi->polygon_count += pp->teapot_polys;
553 MakeShape(ModeInfo * mi, int newdir)
557 if (!MakeGuage(mi, newdir))
558 MakeTube(mi, newdir);
560 MakeValve(mi, newdir);
562 MakeTeapot(mi,newdir);
567 pinit(ModeInfo * mi, int zera)
569 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
573 pp->system_number = 1;
574 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
575 (void) memset(pp->Cells, 0, sizeof (pp->Cells));
576 for (X = 0; X < HCELLS; X++) {
577 for (Y = 0; Y < VCELLS; Y++) {
578 pp->Cells[X][Y][0] = 1;
579 pp->Cells[X][Y][HCELLS - 1] = 1;
580 pp->Cells[0][Y][X] = 1;
581 pp->Cells[HCELLS - 1][Y][X] = 1;
584 for (X = 0; X < HCELLS; X++) {
585 for (Z = 0; Z < HCELLS; Z++) {
586 pp->Cells[X][0][Z] = 1;
587 pp->Cells[X][VCELLS - 1][Z] = 1;
590 (void) memset(pp->usedcolors, 0, sizeof (pp->usedcolors));
595 if (!MI_IS_MONO(mi)) {
596 int collist[DEFINEDCOLORS];
597 int i, j, lower = 1000;
599 /* Avoid repeating colors on the same screen unless necessary */
600 for (i = 0; i < DEFINEDCOLORS; i++) {
601 if (lower > pp->usedcolors[i])
602 lower = pp->usedcolors[i];
604 for (i = 0, j = 0; i < DEFINEDCOLORS; i++) {
605 if (pp->usedcolors[i] == lower) {
610 i = collist[NRAND(j)];
614 pp->system_color = MaterialRed;
617 pp->system_color = MaterialGreen;
620 pp->system_color = MaterialBlue;
623 pp->system_color = MaterialCyan;
626 pp->system_color = MaterialYellow;
629 pp->system_color = MaterialMagenta;
632 pp->system_color = MaterialWhite;
636 pp->system_color = MaterialGray;
640 pp->PX = NRAND((HCELLS - 1)) + 1;
641 pp->PY = NRAND((VCELLS - 1)) + 1;
642 pp->PZ = NRAND((HCELLS - 1)) + 1;
643 } while (pp->Cells[pp->PX][pp->PY][pp->PZ] ||
644 (pp->Cells[pp->PX + 1][pp->PY][pp->PZ] && pp->Cells[pp->PX - 1][pp->PY][pp->PZ] &&
645 pp->Cells[pp->PX][pp->PY + 1][pp->PZ] && pp->Cells[pp->PX][pp->PY - 1][pp->PZ] &&
646 pp->Cells[pp->PX][pp->PY][pp->PZ + 1] && pp->Cells[pp->PX][pp->PY][pp->PZ - 1]));
647 pp->Cells[pp->PX][pp->PY][pp->PZ] = 1;
648 pp->olddir = dirNone;
652 pp->nowdir = SelectNeighbor(mi);
657 reshape_pipes(ModeInfo * mi, int width, int height)
659 glViewport(0, 0, width, (GLint) height);
660 glMatrixMode(GL_PROJECTION);
662 /*glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0); */
663 gluPerspective(65.0, (GLfloat) width / (GLfloat) height, 0.1, 20.0);
664 glMatrixMode(GL_MODELVIEW);
666 glClear(GL_COLOR_BUFFER_BIT);
670 pipes_handle_event (ModeInfo *mi, XEvent *event)
672 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
674 if (gltrackball_event_handler (event, pp->trackball,
675 MI_WIDTH (mi), MI_HEIGHT (mi),
678 else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
689 static void generate_system (ModeInfo *);
692 static void free_pipes (ModeInfo *);
695 init_pipes (ModeInfo * mi)
697 int screen = MI_SCREEN(mi);
700 MI_INIT (mi, pipes, free_pipes);
703 pp->window = MI_WINDOW(mi);
704 if ((pp->glx_context = init_GL(mi)) != NULL) {
706 reshape_pipes(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
708 pp->initial_rotation = NRAND(180); /* jwz */
710 pp->initial_rotation = -10.0;
714 pp->valve = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_BigValve);
715 pp->bolts = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_Bolts3D);
716 pp->betweenbolts = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_PipeBetweenBolts);
718 pp->elbowbolts = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_ElbowBolts);
719 pp->elbowcoins = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_ElbowCoins);
721 pp->guagehead = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_GuageHead);
722 pp->guageface = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_GuageFace);
723 pp->guagedial = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_GuageDial);
724 pp->guageconnector = BuildLWO(MI_IS_WIREFRAME(mi), &LWO_GuageConnector);
725 pp->teapot = build_teapot(mi);
727 /* else they are all 0, thanks to calloc(). */
729 if (MI_COUNT(mi) < 1 || MI_COUNT(mi) > NofSysTypes + 1) {
730 pp->system_type = NRAND(NofSysTypes) + 1;
732 pp->system_type = MI_COUNT(mi);
735 if (MI_CYCLES(mi) > 0 && MI_CYCLES(mi) < 11) {
736 pp->number_of_systems = MI_CYCLES(mi);
738 pp->number_of_systems = 5;
741 if (MI_SIZE(mi) < 10) {
742 pp->system_length = 10;
743 } else if (MI_SIZE(mi) > 1000) {
744 pp->system_length = 1000;
746 pp->system_length = MI_SIZE(mi);
752 pp->trackball = gltrackball_init (True);
753 generate_system (mi);
758 get_dlist (ModeInfo *mi, int i)
760 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
761 if (i >= pp->dlist_count)
764 if (pp->dlist_count >= pp->dlist_size)
766 int s2 = (pp->dlist_size + 100) * 1.2;
767 pp->dlists = (GLuint *)
768 realloc (pp->dlists, s2 * sizeof(*pp->dlists));
769 if (! pp->dlists) abort();
770 pp->poly_counts = (GLuint *)
771 realloc (pp->poly_counts, s2 * sizeof(*pp->poly_counts));
772 if (! pp->poly_counts) abort();
775 pp->dlists [i] = glGenLists (1);
776 pp->poly_counts [i] = 0;
778 return pp->dlists[i];
784 generate_system (ModeInfo * mi)
786 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
787 Bool wire = MI_IS_WIREFRAME(mi);
792 Bool reset_p = False;
794 pp->system_index = 0;
799 glNewList (get_dlist (mi, pp->system_size++), GL_COMPILE);
800 mi->polygon_count = 0;
807 glColor4fv (pp->system_color);
809 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color);
811 /* If it's the begining of a system, draw a sphere */
812 if (pp->olddir == dirNone) {
814 glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0);
818 /* Check for stop conditions */
819 if (pp->ndirections == 0 || pp->counter > pp->system_length) {
821 glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0);
822 /* Finish the system with another sphere */
827 /* If the maximum number of system was drawn, restart (clearing the screen), */
828 /* else start a new system. */
829 if (++pp->system_number > pp->number_of_systems) {
840 /* Do will the direction change? if so, determine the new one */
842 if (!pp->directions[newdir]) { /* cannot proceed in the current direction */
843 newdir = SelectNeighbor(mi);
846 /* random change (20% chance) */
847 if ((pp->counter > 1) && (NRAND(100) < 20)) {
848 newdir = SelectNeighbor(mi);
851 /* Chance to turn increases after each length of pipe drawn */
852 if ((pp->counter > 1) && NRAND(50) < NRAND(pp->turncounter + 1)) {
853 newdir = SelectNeighbor(mi);
859 /* Has the direction changed? */
860 if (newdir == pp->nowdir) {
861 /* If not, draw the cell's center pipe */
863 glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0);
864 /* Chance of factory shape here, if enabled. */
865 if ((pp->counter > 1) && (NRAND(100) < factory)) {
866 MakeShape(mi, newdir);
868 MakeTube(mi, newdir);
872 /* If so, draw the cell's center elbow/sphere */
873 int sysT = pp->system_type;
875 if (sysT == NofSysTypes + 1) {
876 sysT = ((pp->system_number - 1) % NofSysTypes) + 1;
882 glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0);
883 mySphere(elbowradius, wire);
887 switch (pp->nowdir) {
891 glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0);
892 glRotatef(180.0, 1.0, 0.0, 0.0);
895 glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0);
896 glRotatef(180.0, 1.0, 0.0, 0.0);
897 glRotatef(180.0, 0.0, 1.0, 0.0);
900 glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0 - (one_third));
901 glRotatef(90.0, 0.0, 1.0, 0.0);
902 glRotatef(180.0, 0.0, 0.0, 1.0);
905 glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0 + (one_third));
906 glRotatef(90.0, 0.0, 1.0, 0.0);
907 glRotatef(180.0, 1.0, 0.0, 0.0);
914 glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0);
917 glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0);
918 glRotatef(180.0, 0.0, 1.0, 0.0);
921 glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0 - (one_third));
922 glRotatef(270.0, 0.0, 1.0, 0.0);
925 glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0 + (one_third));
926 glRotatef(90.0, 0.0, 1.0, 0.0);
933 glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0);
934 glRotatef(180.0, 0.0, 1.0, 0.0);
937 glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0);
938 glRotatef(180.0, 1.0, 0.0, 0.0);
939 glRotatef(180.0, 0.0, 1.0, 0.0);
942 glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 - (one_third));
943 glRotatef(270.0, 1.0, 0.0, 0.0);
944 glRotatef(180.0, 0.0, 1.0, 0.0);
947 glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 + (one_third));
948 glRotatef(270.0, 1.0, 0.0, 0.0);
949 glRotatef(180.0, 0.0, 0.0, 1.0);
956 glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0);
959 glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0);
960 glRotatef(180.0, 1.0, 0.0, 0.0);
963 glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 - (one_third));
964 glRotatef(270.0, 1.0, 0.0, 0.0);
967 glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 + (one_third));
968 glRotatef(90.0, 1.0, 0.0, 0.0);
975 glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 - (one_third));
976 glRotatef(270.0, 1.0, 0.0, 0.0);
979 glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 - (one_third));
980 glRotatef(270.0, 1.0, 0.0, 0.0);
981 glRotatef(180.0, 0.0, 1.0, 0.0);
984 glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0 - (one_third));
985 glRotatef(270.0, 0.0, 1.0, 0.0);
988 glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0 - (one_third));
989 glRotatef(90.0, 0.0, 1.0, 0.0);
990 glRotatef(180.0, 0.0, 0.0, 1.0);
997 glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 + (one_third), (pp->PZ - 16) / 3.0 * 4.0 + (one_third));
998 glRotatef(90.0, 0.0, 1.0, 0.0);
1001 glTranslatef((pp->PX - 16) / 3.0 * 4.0, (pp->PY - 12) / 3.0 * 4.0 - (one_third), (pp->PZ - 16) / 3.0 * 4.0 + (one_third));
1002 glRotatef(90.0, 0.0, 1.0, 0.0);
1003 glRotatef(180.0, 1.0, 0.0, 0.0);
1006 glTranslatef((pp->PX - 16) / 3.0 * 4.0 - (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 + (one_third));
1007 glRotatef(90.0, 1.0, 0.0, 0.0);
1010 glTranslatef((pp->PX - 16) / 3.0 * 4.0 + (one_third), (pp->PY - 12) / 3.0 * 4.0, (pp->PZ - 16) / 3.0 * 4.0 + (one_third));
1011 glRotatef(270.0, 1.0, 0.0, 0.0);
1012 glRotatef(180.0, 0.0, 0.0, 1.0);
1017 myElbow(mi, (sysT == 2));
1026 pp->olddir = pp->nowdir;
1027 pp->nowdir = newdir;
1028 switch (pp->nowdir) {
1048 pp->Cells[pp->PX][pp->PY][pp->PZ] = 1;
1050 /* Cells'face pipe */
1051 glTranslatef(((pp->PX + OPX) / 2.0 - 16) / 3.0 * 4.0, ((pp->PY + OPY) / 2.0 - 12) / 3.0 * 4.0, ((pp->PZ + OPZ) / 2.0 - 16) / 3.0 * 4.0);
1052 MakeTube(mi, newdir);
1057 pp->poly_counts [pp->system_size-1] = mi->polygon_count;
1066 draw_pipes (ModeInfo * mi)
1068 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
1069 Display *display = MI_DISPLAY(mi);
1070 Window window = MI_WINDOW(mi);
1071 Bool wire = MI_IS_WIREFRAME(mi);
1074 if (!pp->glx_context)
1077 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(pp->glx_context));
1078 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1080 glColor3f(1.0, 1.0, 1.0);
1082 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0);
1083 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0);
1084 glLightfv(GL_LIGHT0, GL_POSITION, position0);
1085 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient1);
1086 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse1);
1087 glLightfv(GL_LIGHT1, GL_POSITION, position1);
1088 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
1089 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
1092 glDisable(GL_LIGHTING);
1095 glEnable(GL_LIGHTING);
1096 glEnable(GL_LIGHT0);
1097 /* This looks crappy. */
1098 /* glEnable(GL_LIGHT1); */
1099 glEnable(GL_DEPTH_TEST);
1100 glEnable(GL_NORMALIZE);
1101 glEnable(GL_CULL_FACE);
1104 glShadeModel(GL_SMOOTH);
1105 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
1106 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
1110 pp->initial_rotation += 0.02;
1112 glTranslatef(0.0, 0.0, fisheye ? -3.8 : -4.8);
1114 gltrackball_rotate (pp->trackball);
1117 glRotatef(pp->initial_rotation, 0.0, 1.0, 0.0);
1119 glScalef(Scale4Window, Scale4Window, Scale4Window);
1121 mi->polygon_count = 0;
1125 GLfloat s = (pp->fadeout * pp->fadeout) / 10000.0;
1127 glRotatef (90 * (1 - (pp->fadeout/100.0)), 1, 0, 0.1);
1129 if (pp->fadeout <= 0)
1132 generate_system (mi);
1135 else if (pp->system_index < pp->system_size)
1140 for (i = 0; i < pp->system_index; i++)
1142 glCallList (pp->dlists[i]);
1143 mi->polygon_count += pp->poly_counts[i];
1148 if (mi->fps_p) do_fps (mi);
1151 glXSwapBuffers(display, window);
1157 change_pipes (ModeInfo * mi)
1159 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
1161 if (!pp->glx_context)
1164 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(pp->glx_context));
1167 #endif /* !STANDALONE */
1171 free_pipes (ModeInfo * mi)
1173 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
1175 if (pp->glx_context) {
1177 /* Display lists MUST be freed while their glXContext is current. */
1178 glXMakeCurrent(MI_DISPLAY(mi), pp->window, *(pp->glx_context));
1181 glDeleteLists(pp->valve, 1);
1183 glDeleteLists(pp->bolts, 1);
1184 if (pp->betweenbolts)
1185 glDeleteLists(pp->betweenbolts, 1);
1188 glDeleteLists(pp->elbowbolts, 1);
1190 glDeleteLists(pp->elbowcoins, 1);
1193 glDeleteLists(pp->guagehead, 1);
1195 glDeleteLists(pp->guageface, 1);
1197 glDeleteLists(pp->guagedial, 1);
1198 if (pp->guageconnector)
1199 glDeleteLists(pp->guageconnector, 1);
1201 glDeleteLists(pp->teapot, 1);
1205 for (i = 0; i < pp->dlist_count; i++)
1206 glDeleteLists (pp->dlists[i], 1);
1208 free (pp->poly_counts);
1213 XSCREENSAVER_MODULE ("Pipes", pipes)