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"
70 # define refresh_pipes 0
71 # include "xlockmore.h" /* from the xscreensaver distribution */
72 #else /* !STANDALONE */
73 # include "xlock.h" /* from the xlockmore distribution */
74 #endif /* !STANDALONE */
81 # include <X11/Xlib.h>
88 #endif /* HAVE_JWZGLES */
93 #include "gltrackball.h"
95 #define DEF_FACTORY "2"
96 #define DEF_FISHEYE "True"
97 #define DEF_TIGHTTURNS "False"
98 #define DEF_ROTATEPIPES "True"
102 static Bool fisheye, tightturns, rotatepipes;
104 static XrmOptionDescRec opts[] =
106 {"-factory", ".pipes.factory", XrmoptionSepArg, 0},
107 {"-fisheye", ".pipes.fisheye", XrmoptionNoArg, "on"},
108 {"+fisheye", ".pipes.fisheye", XrmoptionNoArg, "off"},
109 {"-tightturns", ".pipes.tightturns", XrmoptionNoArg, "on"},
110 {"+tightturns", ".pipes.tightturns", XrmoptionNoArg, "off"},
111 {"-rotatepipes", ".pipes.rotatepipes", XrmoptionNoArg, "on"},
112 {"+rotatepipes", ".pipes.rotatepipes", XrmoptionNoArg, "off"},
114 static argtype vars[] =
116 {&factory, "factory", "Factory", DEF_FACTORY, t_Int},
117 {&fisheye, "fisheye", "Fisheye", DEF_FISHEYE, t_Bool},
118 {&tightturns, "tightturns", "Tightturns", DEF_TIGHTTURNS, t_Bool},
119 {&rotatepipes, "rotatepipes", "Rotatepipes", DEF_ROTATEPIPES, t_Bool},
121 static OptionStruct desc[] =
123 {"-factory num", "how much extra equipment in pipes (0 for none)"},
124 {"-/+fisheye", "turn on/off zoomed-in view of pipes"},
125 {"-/+tightturns", "turn on/off tight turns"},
126 {"-/+rotatepipes", "turn on/off pipe system rotation per screenful"},
129 ENTRYPOINT ModeSpecOpt pipes_opts =
130 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
133 ModStruct pipes_description =
134 {"pipes", "init_pipes", "draw_pipes", "release_pipes",
136 "change_pipes", NULL, &pipes_opts,
137 1000, 2, 5, 500, 4, 1.0, "",
138 "Shows a selfbuilding pipe system", 0, NULL};
142 #define Scale4Window 0.1
144 #define one_third 0.3333333333333333333
156 #define DEFINEDCOLORS 7
157 #define elbowradius 0.5
159 /*************************************************************************/
164 int Cells[HCELLS][VCELLS][HCELLS];
165 int usedcolors[DEFINEDCOLORS];
172 int number_of_systems;
177 const float *system_color;
178 GLfloat initial_rotation;
179 GLuint valve, bolts, betweenbolts, elbowbolts, elbowcoins;
180 GLuint guagehead, guageface, guagedial, guageconnector, teapot;
182 GLXContext *glx_context;
185 trackball_state *trackball;
186 GLuint *dlists, *poly_counts;
187 int dlist_count, dlist_size;
188 int system_index, system_size;
194 extern struct lwo LWO_BigValve, LWO_PipeBetweenBolts, LWO_Bolts3D;
195 extern struct lwo LWO_GuageHead, LWO_GuageFace, LWO_GuageDial, LWO_GuageConnector;
196 extern struct lwo LWO_ElbowBolts, LWO_ElbowCoins;
198 static const float front_shininess[] = {60.0};
199 static const float front_specular[] = {0.7, 0.7, 0.7, 1.0};
200 static const float ambient0[] = {0.4, 0.4, 0.4, 1.0};
201 static const float diffuse0[] = {1.0, 1.0, 1.0, 1.0};
202 static const float ambient1[] = {0.2, 0.2, 0.2, 1.0};
203 static const float diffuse1[] = {0.5, 0.5, 0.5, 1.0};
204 static const float position0[] = {1.0, 1.0, 1.0, 0.0};
205 static const float position1[] = {-1.0, -1.0, 1.0, 0.0};
206 static const float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};
207 static const float lmodel_twoside[] = {GL_TRUE};
209 static const float MaterialRed[] = {0.7, 0.0, 0.0, 1.0};
210 static const float MaterialGreen[] = {0.1, 0.5, 0.2, 1.0};
211 static const float MaterialBlue[] = {0.0, 0.0, 0.7, 1.0};
212 static const float MaterialCyan[] = {0.2, 0.5, 0.7, 1.0};
213 static const float MaterialYellow[] = {0.7, 0.7, 0.0, 1.0};
214 static const float MaterialMagenta[] = {0.6, 0.2, 0.5, 1.0};
215 static const float MaterialWhite[] = {0.7, 0.7, 0.7, 1.0};
216 static const float MaterialGray[] = {0.2, 0.2, 0.2, 1.0};
218 static pipesstruct *pipes = NULL;
222 MakeTube(ModeInfo *mi, int direction)
224 Bool wire = MI_IS_WIREFRAME(mi);
226 float SINan_3, COSan_3;
227 int facets = (wire ? 5 : 24);
229 /*dirUP = 00000000 */
230 /*dirDOWN = 00000001 */
231 /*dirLEFT = 00000010 */
232 /*dirRIGHT = 00000011 */
233 /*dirNEAR = 00000100 */
234 /*dirFAR = 00000101 */
236 if (!(direction & 4)) {
237 glRotatef(90.0, (direction & 2) ? 0.0 : 1.0,
238 (direction & 2) ? 1.0 : 0.0, 0.0);
240 glBegin(wire ? GL_LINE_STRIP : GL_QUAD_STRIP);
241 for (an = 0.0; an <= 2.0 * M_PI; an += M_PI * 2 / facets) {
242 glNormal3f((COSan_3 = cos(an) / 3.0), (SINan_3 = sin(an) / 3.0), 0.0);
243 glVertex3f(COSan_3, SINan_3, one_third);
244 glVertex3f(COSan_3, SINan_3, -one_third);
251 mySphere(float radius, Bool wire)
254 GLUquadricObj *quadObj;
256 quadObj = gluNewQuadric();
257 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
258 gluSphere(quadObj, radius, 16, 16);
259 gluDeleteQuadric(quadObj);
262 glScalef (radius, radius, radius);
263 glRotatef (90, 1, 0, 0);
264 unit_sphere (16, 16, wire);
270 myElbow(ModeInfo * mi, int bolted)
272 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
273 Bool wire = MI_IS_WIREFRAME(mi);
275 int nsides = (wire ? 6 : 25);
281 GLfloat p0[3], p1[3], p2[3], p3[3];
282 GLfloat n0[3], n1[3], n2[3], n3[3];
283 GLfloat COSphi, COSphi1, COStheta, COStheta1;
284 GLfloat _SINtheta, _SINtheta1;
286 for (i = 0; i <= rings / 4; i++) {
287 GLfloat theta, theta1;
289 theta = (GLfloat) i *2.0 * M_PI / rings;
291 theta1 = (GLfloat) (i + 1) * 2.0 * M_PI / rings;
292 for (j = 0; j < nsides; j++) {
295 phi = (GLfloat) j *2.0 * M_PI / nsides;
297 phi1 = (GLfloat) (j + 1) * 2.0 * M_PI / nsides;
299 p0[0] = (COStheta = cos(theta)) * (R + r * (COSphi = cos(phi)));
300 p0[1] = (_SINtheta = -sin(theta)) * (R + r * COSphi);
302 p1[0] = (COStheta1 = cos(theta1)) * (R + r * COSphi);
303 p1[1] = (_SINtheta1 = -sin(theta1)) * (R + r * COSphi);
305 p2[0] = COStheta1 * (R + r * (COSphi1 = cos(phi1)));
306 p2[1] = _SINtheta1 * (R + r * COSphi1);
308 p3[0] = COStheta * (R + r * COSphi1);
309 p3[1] = _SINtheta * (R + r * COSphi1);
311 n0[0] = COStheta * COSphi;
312 n0[1] = _SINtheta * COSphi;
314 n1[0] = COStheta1 * COSphi;
315 n1[1] = _SINtheta1 * COSphi;
317 n2[0] = COStheta1 * COSphi1;
318 n2[1] = _SINtheta1 * COSphi1;
320 n3[0] = COStheta * COSphi1;
321 n3[1] = _SINtheta * COSphi1;
323 p0[2] = p1[2] = r * (n0[2] = n1[2] = sin(phi));
324 p2[2] = p3[2] = r * (n2[2] = n3[2] = sin(phi1));
326 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
340 if (factory > 0 && bolted) {
341 /* Bolt the elbow onto the pipe system */
344 glRotatef(90.0, 0.0, 0.0, -1.0);
345 glRotatef(90.0, 0.0, 1.0, 0.0);
346 glTranslatef(0.0, one_third, one_third);
347 glCallList(pp->elbowcoins);
348 mi->polygon_count += LWO_ElbowCoins.num_pnts/3;
349 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
350 glCallList(pp->elbowbolts);
351 mi->polygon_count += LWO_ElbowBolts.num_pnts/3;
352 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color);
363 FindNeighbors(ModeInfo * mi)
365 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
368 pp->directions[dirUP] = (!pp->Cells[pp->PX][pp->PY + 1][pp->PZ]) ? 1 : 0;
369 pp->ndirections += pp->directions[dirUP];
370 pp->directions[dirDOWN] = (!pp->Cells[pp->PX][pp->PY - 1][pp->PZ]) ? 1 : 0;
371 pp->ndirections += pp->directions[dirDOWN];
372 pp->directions[dirLEFT] = (!pp->Cells[pp->PX - 1][pp->PY][pp->PZ]) ? 1 : 0;
373 pp->ndirections += pp->directions[dirLEFT];
374 pp->directions[dirRIGHT] = (!pp->Cells[pp->PX + 1][pp->PY][pp->PZ]) ? 1 : 0;
375 pp->ndirections += pp->directions[dirRIGHT];
376 pp->directions[dirFAR] = (!pp->Cells[pp->PX][pp->PY][pp->PZ - 1]) ? 1 : 0;
377 pp->ndirections += pp->directions[dirFAR];
378 pp->directions[dirNEAR] = (!pp->Cells[pp->PX][pp->PY][pp->PZ + 1]) ? 1 : 0;
379 pp->ndirections += pp->directions[dirNEAR];
383 SelectNeighbor(ModeInfo * mi)
385 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
389 for (i = 0, j = 0; i < 6; i++) {
390 if (pp->directions[i]) {
396 return dirlist[NRAND(pp->ndirections)];
400 MakeValve(ModeInfo * mi, int newdir)
402 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
404 /* There is a glPopMatrix() right after this subroutine returns. */
408 glRotatef(90.0, 1.0, 0.0, 0.0);
409 glRotatef(NRAND(3) * 90.0, 0.0, 0.0, 1.0);
413 glRotatef(90.0, 0.0, -1.0, 0.0);
414 glRotatef((NRAND(3) * 90.0) - 90.0, 0.0, 0.0, 1.0);
418 glRotatef(NRAND(4) * 90.0, 0.0, 0.0, 1.0);
422 glCallList(pp->betweenbolts);
423 mi->polygon_count += LWO_PipeBetweenBolts.num_pnts/3;
424 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
425 glCallList(pp->bolts);
426 mi->polygon_count += LWO_Bolts3D.num_pnts/3;
427 if (!MI_IS_MONO(mi)) {
428 if (pp->system_color == MaterialRed) {
429 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, NRAND(2) ? MaterialYellow : MaterialBlue);
430 } else if (pp->system_color == MaterialBlue) {
431 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, NRAND(2) ? MaterialRed : MaterialYellow);
432 } else if (pp->system_color == MaterialYellow) {
433 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, NRAND(2) ? MaterialBlue : MaterialRed);
435 switch ((NRAND(3))) {
437 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
440 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlue);
443 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialYellow);
447 glRotatef((GLfloat) (NRAND(90)), 1.0, 0.0, 0.0);
448 glCallList(pp->valve);
449 mi->polygon_count += LWO_BigValve.num_pnts/3;
450 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color);
455 MakeGuage(ModeInfo * mi, int newdir)
457 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
459 /* Can't have a guage on a vertical pipe. */
460 if ((newdir == dirUP) || (newdir == dirDOWN))
463 /* Is there space above this pipe for a guage? */
464 if (!pp->directions[dirUP])
467 /* Yes! Mark the space as used. */
468 pp->Cells[pp->PX][pp->PY + 1][pp->PZ] = 1;
472 if ((newdir == dirLEFT) || (newdir == dirRIGHT))
473 glRotatef(90.0, 0.0, 1.0, 0.0);
474 glCallList(pp->betweenbolts);
475 mi->polygon_count += LWO_PipeBetweenBolts.num_pnts/3;
476 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
477 glCallList(pp->bolts);
478 mi->polygon_count += LWO_Bolts3D.num_pnts/3;
481 glCallList(pp->guageconnector);
482 mi->polygon_count += LWO_GuageConnector.num_pnts/3;
484 glTranslatef(0.0, 1.33333, 0.0);
485 /* Do not change the above to 1 + ONE_THIRD, because */
486 /* the object really is centered on 1.3333300000. */
487 glRotatef(NRAND(270) + 45.0, 0.0, 0.0, -1.0);
488 /* Random rotation for the dial. I love it. */
489 glCallList(pp->guagedial);
490 mi->polygon_count += LWO_GuageDial.num_pnts/3;
493 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color);
494 glCallList(pp->guagehead);
495 mi->polygon_count += LWO_GuageHead.num_pnts/3;
497 /* GuageFace is drawn last, in case of low-res depth buffers. */
498 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
499 glCallList(pp->guageface);
500 mi->polygon_count += LWO_GuageFace.num_pnts/3;
502 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pp->system_color);
510 build_teapot(ModeInfo *mi)
512 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
513 GLuint list = glGenLists(1);
515 glNewList(list, GL_COMPILE);
516 pp->teapot_polys = unit_teapot (12, MI_IS_WIREFRAME(mi));
523 MakeTeapot(ModeInfo * mi, int newdir)
525 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
530 glRotatef(90.0, 1.0, 0.0, 0.0);
531 glRotatef(NRAND(3) * 90.0, 0.0, 0.0, 1.0);
535 glRotatef(90.0, 0.0, -1.0, 0.0);
536 glRotatef((NRAND(3) * 90.0) - 90.0, 0.0, 0.0, 1.0);
540 glRotatef(NRAND(4) * 90.0, 0.0, 0.0, 1.0);
544 glCallList(pp->teapot);
545 mi->polygon_count += pp->teapot_polys;
551 MakeShape(ModeInfo * mi, int newdir)
555 if (!MakeGuage(mi, newdir))
556 MakeTube(mi, newdir);
558 MakeValve(mi, newdir);
560 MakeTeapot(mi,newdir);
565 pinit(ModeInfo * mi, int zera)
567 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
571 pp->system_number = 1;
572 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
573 (void) memset(pp->Cells, 0, sizeof (pp->Cells));
574 for (X = 0; X < HCELLS; X++) {
575 for (Y = 0; Y < VCELLS; Y++) {
576 pp->Cells[X][Y][0] = 1;
577 pp->Cells[X][Y][HCELLS - 1] = 1;
578 pp->Cells[0][Y][X] = 1;
579 pp->Cells[HCELLS - 1][Y][X] = 1;
582 for (X = 0; X < HCELLS; X++) {
583 for (Z = 0; Z < HCELLS; Z++) {
584 pp->Cells[X][0][Z] = 1;
585 pp->Cells[X][VCELLS - 1][Z] = 1;
588 (void) memset(pp->usedcolors, 0, sizeof (pp->usedcolors));
593 if (!MI_IS_MONO(mi)) {
594 int collist[DEFINEDCOLORS];
595 int i, j, lower = 1000;
597 /* Avoid repeating colors on the same screen unless necessary */
598 for (i = 0; i < DEFINEDCOLORS; i++) {
599 if (lower > pp->usedcolors[i])
600 lower = pp->usedcolors[i];
602 for (i = 0, j = 0; i < DEFINEDCOLORS; i++) {
603 if (pp->usedcolors[i] == lower) {
608 i = collist[NRAND(j)];
612 pp->system_color = MaterialRed;
615 pp->system_color = MaterialGreen;
618 pp->system_color = MaterialBlue;
621 pp->system_color = MaterialCyan;
624 pp->system_color = MaterialYellow;
627 pp->system_color = MaterialMagenta;
630 pp->system_color = MaterialWhite;
634 pp->system_color = MaterialGray;
638 pp->PX = NRAND((HCELLS - 1)) + 1;
639 pp->PY = NRAND((VCELLS - 1)) + 1;
640 pp->PZ = NRAND((HCELLS - 1)) + 1;
641 } while (pp->Cells[pp->PX][pp->PY][pp->PZ] ||
642 (pp->Cells[pp->PX + 1][pp->PY][pp->PZ] && pp->Cells[pp->PX - 1][pp->PY][pp->PZ] &&
643 pp->Cells[pp->PX][pp->PY + 1][pp->PZ] && pp->Cells[pp->PX][pp->PY - 1][pp->PZ] &&
644 pp->Cells[pp->PX][pp->PY][pp->PZ + 1] && pp->Cells[pp->PX][pp->PY][pp->PZ - 1]));
645 pp->Cells[pp->PX][pp->PY][pp->PZ] = 1;
646 pp->olddir = dirNone;
650 pp->nowdir = SelectNeighbor(mi);
655 reshape_pipes(ModeInfo * mi, int width, int height)
657 glViewport(0, 0, width, (GLint) height);
658 glMatrixMode(GL_PROJECTION);
660 /*glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0); */
661 gluPerspective(65.0, (GLfloat) width / (GLfloat) height, 0.1, 20.0);
662 glMatrixMode(GL_MODELVIEW);
664 glClear(GL_COLOR_BUFFER_BIT);
668 pipes_handle_event (ModeInfo *mi, XEvent *event)
670 pipesstruct *pp = &pipes[MI_SCREEN(mi)];
672 if (gltrackball_event_handler (event, pp->trackball,
673 MI_WIDTH (mi), MI_HEIGHT (mi),
676 else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
687 static void generate_system (ModeInfo *);
691 init_pipes (ModeInfo * mi)
693 int screen = MI_SCREEN(mi);
697 if ((pipes = (pipesstruct *) calloc(MI_NUM_SCREENS(mi),
698 sizeof (pipesstruct))) == NULL)
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 release_pipes (ModeInfo * mi)
1173 if (pipes != NULL) {
1176 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
1177 pipesstruct *pp = &pipes[screen];
1179 if (pp->glx_context) {
1181 /* Display lists MUST be freed while their glXContext is current. */
1182 glXMakeCurrent(MI_DISPLAY(mi), pp->window, *(pp->glx_context));
1185 glDeleteLists(pp->valve, 1);
1187 glDeleteLists(pp->bolts, 1);
1188 if (pp->betweenbolts)
1189 glDeleteLists(pp->betweenbolts, 1);
1192 glDeleteLists(pp->elbowbolts, 1);
1194 glDeleteLists(pp->elbowcoins, 1);
1197 glDeleteLists(pp->guagehead, 1);
1199 glDeleteLists(pp->guageface, 1);
1201 glDeleteLists(pp->guagedial, 1);
1202 if (pp->guageconnector)
1203 glDeleteLists(pp->guageconnector, 1);
1205 glDeleteLists(pp->teapot, 1);
1209 for (i = 0; i < pp->dlist_count; i++)
1210 glDeleteLists (pp->dlists[i], 1);
1212 free (pp->poly_counts);
1217 (void) free((void *) pipes);
1223 XSCREENSAVER_MODULE ("Pipes", pipes)