1 /* biof --- 3D Bioform */
2
3 #if 0
4 static const char sccsid[] = "@(#)biof.c 5.15 2005/02/15 xlockmore";
5 #endif
6
7 /* Copyright (c) E. Lassauge, 2005. */
8
9 /*
10 * Permission to use, copy, modify, and distribute this software and its
11 * documentation for any purpose and without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and that
13 * both that copyright notice and this permission notice appear in
14 * supporting documentation.
15 *
16 * This file is provided AS IS with no warranties of any kind. The author
17 * shall have no liability with respect to the infringement of copyrights,
18 * trade secrets or any patents by this file or any part thereof. In no
19 * event will the author be liable for any lost revenue or profits or
20 * other special, indirect and consequential damages.
21 *
22 * The original code is from the really slick screensaver series
23 * (see below the original header)
24 *
25 * Eric Lassauge (Feb-15-2005) <lassauge AT users.sourceforge.net>
26 *
27 * REVISION HISTORY:
28 *
29 * - Eric Lassauge (Feb-15-2005) <lassauge AT users.sourceforge.net>
30 * Ported the rss_glx version to xlockmore (added random color + wireframe + fps)
31 */
32
33 /*
34 * Copyright (C) 2002 <hk@dgmr.nl>
35 * Ported to Linux by Tugrul Galatali <tugrul@galatali.com>
36 *
37 * BioF is free software; you can redistribute it and/or modify
38 * it under the terms of the GNU General Public License version 2 as
39 * published by the Free Software Foundation.
40 *
41 * BioF is distributed in the hope that it will be useful,
42 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 * GNU General Public License for more details.
45 *
46 * You should have received a copy of the GNU General Public License
47 * along with this program; if not, write to the Free Software
48 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
49 */
50
51 #ifdef STANDALONE
52 # define MODE_biof
53 # define DEFAULTS "*delay: 25000 \n" \
54 "*count: 4 \n" \
55 "*showFPS: False \n" \
56 "*cycles: 100 \n" \
57 "*size: 6000 \n" \
58
59 /* "*preset: 5 \n" */
60 #define free_biof 0
61 #define biof_handle_event 0
62 # include "xlockmore.h" /* from the xscreensaver distribution */
63 # include <stdio.h>
64 # include <stdlib.h>
65 # include <math.h>
66 #else /* !STANDALONE */
67 # include "xlock.h" /* from the xlockmore distribution */
68 # include "visgl.h"
69 #endif /* !STANDALONE */
70
71 #ifdef MODE_biof
72 /* BioF screen saver */
73
74 #include <stdlib.h>
75 #include <GL/gl.h>
76 #include <GL/glu.h>
77
78 #define TRIANGLES 1
79 #define SPHERES 2
80 #define BIGSPHERES 3
81 #define POINTS 4
82 #define LIGHTMAP 5
83
84 /*#define COLOR 0.9, 0.75, 0.5 */
85 /*#define COLOR_RAND(i) ((float) (NRAND(i)) / 100.0) */
86 /* Try to keep the same 'weight' on the components: */
87 #define COLOR_RAND(i) ((float) ( (2*i - 100) + NRAND(100 - i) ) / 100.0)
88 static float C_RED;
89 static float C_GREEN;
90 static float C_BLUE;
91 #define COLOR C_RED, C_GREEN, C_BLUE
92
93 static void handle_opts (ModeInfo * mi);
94
95 static XrmOptionDescRec opts[] =
96 {
97 {(char *) "-preset", (char *) ".biof.preset", XrmoptionSepArg, (caddr_t)NULL},
98 {(char *) "-triangles", (char *) ".biof.preset", XrmoptionNoArg, (caddr_t)"1"},
99 {(char *) "-spheres", (char *) ".biof.preset", XrmoptionNoArg, (caddr_t)"2"},
100 {(char *) "-bigspheres", (char *) ".biof.preset", XrmoptionNoArg, (caddr_t)"3"},
101 {(char *) "-lightmap", (char *) ".biof.preset", XrmoptionNoArg, (caddr_t)"5"},
102 {(char *) "-lines", (char *) ".biof.lines", XrmoptionSepArg, (caddr_t)NULL},
103 {(char *) "-points", (char *) ".biof.points", XrmoptionSepArg, (caddr_t)NULL},
104 {(char *) "-offangle", (char *) ".biof.offangle", XrmoptionNoArg, (caddr_t)"True"},
105 {(char *) "+offangle", (char *) ".biof.offangle", XrmoptionNoArg, (caddr_t)"False"},
106 };
107
108 static int var_preset;
109 static int var_offangle;
110 static int var_lines;
111 static int var_points;
112
113 static argtype vars[] =
114 {
115 {(void *) & var_preset, (char *) "preset", (char *) "Preset", (char *) "0", t_Int},
116 {(void *) & var_lines, (char *) "lines", (char *) "Lines", (char *) "0", t_Int},
117 {(void *) & var_points, (char *) "points", (char *) "Points", (char *) "0", t_Int},
118 {(void *) & var_offangle, (char *) "offangle", (char *) "OffAngle", (char *) "False", t_Bool},
119 };
120
121 static OptionStruct desc[] =
122 {
123 {(char *) "-preset num", (char *) "preset to use [1-5]"},
124 {(char *) "-triangles", (char *) "preset 1"},
125 {(char *) "-spheres", (char *) "preset 2"},
126 {(char *) "-bigspheres", (char *) "preset 3"},
127 {(char *) "-lightmap", (char *) "preset 5"},
128 {(char *) "-lines num", (char *) "use num lines"},
129 {(char *) "-points num", (char *) "use num points"},
130 {(char *) "+/-offangle", (char *) "whether to use OffAngle"},
131 };
132
133 ENTRYPOINT ModeSpecOpt biof_opts =
134 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
135
136 #ifdef USE_MODULES
137 ModStruct biof_description =
138 {"biof", "init_biof", "draw_biof", "release_biof",
139 "draw_biof", "init_biof", (char *) NULL, &cage_opts,
140 10000, 800, 1, 0, 1.0, "",
141 "Shows BioF", 0, NULL};
142
143 #endif
144
145 typedef struct {
146 #ifdef WIN32
147 HGLRC glx_context;
148 #else
149 GLXContext *glx_context;
150 #endif
151 GLint WinH, WinW;
152 int wire;
153
154 int NRPOINTS, NRLINES;
155 int dGeometry;
156 int dOffAngle;
157 double time;
158
159 GLUquadricObj *shapes;
160 } biofstruct;
161
162 static biofstruct *biof = (biofstruct *) NULL;
163
Horn(ModeInfo * mi,int ribs,double bend,double stack,double twist,double twisttrans,double grow)164 static void Horn (ModeInfo * mi, int ribs, double bend, double stack, double twist, double twisttrans, double grow)
165 {
166 biofstruct *bp = &biof[MI_SCREEN(mi)];
167 int i;
168
169 for (i = 0; i < ribs; i++) {
170 glPushMatrix ();
171 glRotated (i * bend / ribs, 1, 0, 0);
172 glTranslated (0, 0, i * stack / ribs);
173 glTranslated (twisttrans, 0, 0);
174 glRotated (i * twist / ribs, 0, 0, 1);
175 glTranslated (-twisttrans, 0, 0);
176
177 switch (bp->dGeometry) {
178 case TRIANGLES:
179 glBegin (bp->wire?GL_LINE_LOOP:GL_TRIANGLES);
180 glColor4d (COLOR, 1.0);
181 glVertex3d (2.0, 2.0, 0.0);
182 glColor4d (COLOR, 0.0);
183 glVertex3d (0.0, 2.0, 0.0);
184 glVertex3d (2.0, 0.0, 0.0);
185 glEnd ();
186
187 break;
188
189 case BIGSPHERES:
190 if (!bp->wire)
191 {
192 gluQuadricDrawStyle (bp->shapes, GLU_FILL);
193 gluQuadricNormals (bp->shapes, GLU_SMOOTH);
194 }
195 else
196 {
197 gluQuadricDrawStyle (bp->shapes, GLU_LINE);
198 gluQuadricNormals (bp->shapes, GLU_NONE);
199 }
200 gluSphere (bp->shapes, 7 * exp (i / ribs * log (grow)), 20, 10);
201
202 break;
203
204 case SPHERES:
205 if (!bp->wire)
206 {
207 gluQuadricDrawStyle (bp->shapes, GLU_FILL);
208 gluQuadricNormals (bp->shapes, GLU_SMOOTH);
209 }
210 else
211 {
212 gluQuadricDrawStyle (bp->shapes, GLU_LINE);
213 gluQuadricNormals (bp->shapes, GLU_NONE);
214 }
215 /*gluSphere(bp->shapes, power(grow,i/ribs), 5, 5);*/
216 gluSphere (bp->shapes, exp (i / ribs * log (grow)), 6, 4);
217
218 break;
219
220 case LIGHTMAP:
221 case POINTS:
222 glBegin (GL_POINTS);
223 glVertex3d (0, 0, 0);
224 glEnd ();
225
226 break;
227 }
228
229 glPopMatrix ();
230 }
231 }
232
233 ENTRYPOINT void
reshape_biof(ModeInfo * mi,int width,int height)234 reshape_biof (ModeInfo * mi, int width, int height)
235 {
236 biofstruct *bp = &biof[MI_SCREEN(mi)];
237
238 glViewport (0, 0, bp->WinW = (GLint) width, bp->WinH = (GLint) height);
239 glMatrixMode (GL_PROJECTION);
240 glLoadIdentity ();
241 gluPerspective (30, (GLdouble) width / (GLdouble) height, 100, 300);
242 }
243
244 ENTRYPOINT void
init_biof(ModeInfo * mi)245 init_biof (ModeInfo * mi)
246 {
247 float glfLightPosition[4] = { 100.0, 100.0, 100.0, 0.0 };
248 float glfFog[4] = { 0.0, 0.0, 0.3, 1.0 };
249 /*float DiffuseLightColor[4] = { 1, 0.8, 0.4, 1.0 };*/
250 float DiffuseLightColor[4] = { 1.0, 1.0, 1.0, 1.0 };
251 int i, j;
252 double x, y, r, d;
253 unsigned char texbuf[64][64];
254 int screen = MI_SCREEN(mi);
255 biofstruct *bp;
256
257 MI_INIT(mi, biof);
258 bp = &biof[screen];
259 bp->wire = MI_IS_WIREFRAME(mi);
260 C_RED = COLOR_RAND(90);
261 C_GREEN = COLOR_RAND(75);
262 C_BLUE = COLOR_RAND(50);
263 DiffuseLightColor[1] = COLOR_RAND(80);
264 DiffuseLightColor[2] = COLOR_RAND(40);
265
266 handle_opts(mi);
267 if (MI_IS_DEBUG(mi)) {
268 (void) fprintf(stderr,
269 "%s:\n\tpreset=%d\n\toffangle=%d\n\tlines=%d\n\tpoints=%d\n\twireframe=%s\n",
270 MI_NAME(mi),
271 bp->dGeometry,
272 bp->dOffAngle,
273 bp->NRLINES,
274 bp->NRPOINTS,
275 bp->wire ? "yes" : "no"
276 );
277 }
278
279 if ((bp->glx_context = init_GL(mi)) != NULL) {
280
281 glEnable (GL_DEPTH_TEST);
282
283 if (bp->wire)
284 {
285 glDisable (GL_BLEND);
286 }
287 else
288 {
289 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
290 glEnable (GL_BLEND);
291 }
292
293 if ((bp->dGeometry == SPHERES) || (bp->dGeometry == BIGSPHERES)) {
294 if (bp->wire)
295 {
296 glDisable (GL_CULL_FACE);
297 glDisable (GL_LIGHTING);
298 glDisable (GL_LIGHT0);
299 }
300 else
301 {
302 glEnable (GL_CULL_FACE);
303 glCullFace (GL_BACK);
304
305 glLightfv (GL_LIGHT0, GL_POSITION, glfLightPosition);
306 glEnable (GL_LIGHTING);
307 glEnable (GL_LIGHT0);
308
309 glLightfv (GL_LIGHT0, GL_DIFFUSE, DiffuseLightColor);
310 }
311
312 bp->shapes = gluNewQuadric ();
313 } else if (bp->dGeometry == POINTS) {
314 if (bp->wire)
315 {
316 glDisable (GL_POINT_SMOOTH);
317 glPointSize (3.0);
318 }
319 else
320 {
321 glHint (GL_POINT_SMOOTH_HINT, GL_NICEST);
322 glPointSize (3.0);
323 glEnable (GL_POINT_SMOOTH);
324
325 glFogi (GL_FOG_MODE, GL_LINEAR);
326 glHint (GL_FOG_HINT, GL_NICEST);
327 glFogfv (GL_FOG_COLOR, glfFog);
328 glFogf (GL_FOG_START, 150);
329 glFogf (GL_FOG_END, 250);
330 glEnable (GL_FOG);
331 }
332 } else if (bp->dGeometry == LIGHTMAP) { /* Can't be wired ! */
333 r = 32;
334
335 memset ((void *)&texbuf, 0, 4096);
336
337 for (i = 0; i < 64; i++) {
338 for (j = 0; j < 64; j++) {
339 x = abs (i - 32);
340 y = abs (j - 32);
341 d = sqrt (x * x + y * y);
342
343 if (d < r) {
344 d = 1 - (d / r);
345 texbuf[i][j] = (char)(255.0f * d * d);
346 }
347 }
348 }
349
350 gluBuild2DMipmaps (GL_TEXTURE_2D, 1, 64, 64, GL_LUMINANCE, GL_UNSIGNED_BYTE, texbuf);
351
352 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
353 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
354 }
355
356 reshape_biof (mi,MI_WIDTH(mi), MI_HEIGHT(mi));
357 } else {
358 MI_CLEARWINDOW(mi);
359 }
360
361 }
362
363 ENTRYPOINT void
release_biof(ModeInfo * mi)364 release_biof (ModeInfo * mi)
365 {
366 int screen;
367
368 if (biof != NULL) {
369 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
370 biofstruct *bp = &biof[screen];
371 if ((bp->dGeometry == SPHERES) || (bp->dGeometry == BIGSPHERES))
372 gluDeleteQuadric(bp->shapes);
373 }
374 (void)free((void *)biof);
375 biof = (biofstruct *) NULL;
376 }
377 FreeAllGL(mi);
378 }
379
380 ENTRYPOINT void
draw_biof(ModeInfo * mi)381 draw_biof (ModeInfo * mi)
382 {
383 #ifndef WIN32
384 struct timeval now;
385 #endif
386 double dt = 0;
387 biofstruct *bp = &biof[MI_SCREEN(mi)];
388 Display *display = MI_DISPLAY(mi);
389 Window window = MI_WINDOW(mi);
390
391 MI_IS_DRAWN(mi) = True;
392
393 if (!bp->glx_context)
394 return;
395 #ifdef WIN32
396 wglMakeCurrent(hdc, bp->glx_context);
397 #else
398 glXMakeCurrent(display, window, *(bp->glx_context));
399 #endif
400 #ifdef WIN32
401 bp->time += MI_DELAY(mi) / 100000.0;
402 dt = bp->time;
403 #else
404 GETTIMEOFDAY (&now);
405 dt = (now.tv_sec * 1000000 + now.tv_usec) * 0.000001;
406 #endif
407 if (bp->dGeometry == LIGHTMAP) {
408 int i, j, offset;
409 float *fb_buffer;
410 double x, y, w;
411
412 if ((fb_buffer = (float *) malloc(bp->NRPOINTS *
413 bp->NRLINES * 3 * sizeof (float))) == NULL) {
414 return;
415 }
416 glDisable (GL_DEPTH_TEST);
417 glFeedbackBuffer (bp->NRPOINTS * bp->NRLINES * 3, GL_2D, fb_buffer);
418 glRenderMode (GL_FEEDBACK);
419
420 glMatrixMode (GL_MODELVIEW);
421 glPushMatrix ();
422 glLoadIdentity ();
423
424 gluLookAt (200, 0, 0, 0, 0, 0, 0, 0, 1);
425
426 glRotated (90, 0, 1, 0);
427 glRotated (10 * dt, 0, 0, 1);
428
429 glNewList (1, GL_COMPILE);
430 Horn (mi, bp->NRPOINTS, 315 * sin (dt * 0.237), 45 /* + 20 * sin(dt * 0.133) */ , 1500 * sin (dt * 0.213), 7.5 + 2.5 * sin (dt * 0.173), 1);
431 glEndList ();
432
433 if (bp->dOffAngle)
434 glRotated (45, 1, 1, 0);
435
436 for (i = 0; i < bp->NRLINES; i++) {
437 glPushMatrix ();
438
439 glRotated (360 * i / bp->NRLINES, 0, 0, 1);
440 glRotated (45, 1, 0, 0);
441 glTranslated (0, 0, 2);
442
443 glCallList (1);
444
445 glPopMatrix ();
446 }
447
448 glPopMatrix ();
449
450 glRenderMode (GL_RENDER);
451
452 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
453
454 glMatrixMode (GL_PROJECTION);
455 glPushMatrix ();
456 glLoadIdentity ();
457
458 glMatrixMode (GL_MODELVIEW);
459 glPushMatrix ();
460 glLoadIdentity ();
461
462 glScalef (2.0 / bp->WinW, 2.0 / bp->WinH, 1.0);
463 glTranslatef (-0.5 * bp->WinW, -0.5 * bp->WinH, 0.0);
464
465 glClear (GL_COLOR_BUFFER_BIT);
466
467 glEnable (GL_TEXTURE_2D);
468 glBlendFunc (GL_ONE, GL_ONE);
469 glEnable (GL_BLEND);
470
471 glBegin (GL_QUADS);
472
473 w = bp->WinW >> 7;
474
475 for (j = 0; j < bp->NRPOINTS; j++) {
476 glColor3f (0.25 - 0.15 * j / bp->NRPOINTS, 0.15 + 0.10 * j / bp->NRPOINTS, 0.06 + 0.14 * j / bp->NRPOINTS);
477 for (i = 0; i < bp->NRLINES; i++) {
478 offset = 3 * (i * bp->NRPOINTS + j);
479 x = fb_buffer[offset + 1];
480 y = fb_buffer[offset + 2];
481
482 glTexCoord2f (0.0, 0.0);
483 glVertex2f (x - w, y - w);
484
485 glTexCoord2f (1.0, 0.0);
486 glVertex2f (x + w, y - w);
487
488 glTexCoord2f (1.0, 1.0);
489 glVertex2f (x + w, y + w);
490
491 glTexCoord2f (0.0, 1.0);
492 glVertex2f (x - w, y + w);
493 }
494 }
495 if (fb_buffer != NULL)
496 free(fb_buffer);
497 glEnd ();
498
499 glMatrixMode (GL_MODELVIEW);
500 glPopMatrix ();
501 glMatrixMode (GL_PROJECTION);
502 glPopMatrix ();
503 } else {
504 int i;
505
506 glClear (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
507
508 glMatrixMode (GL_MODELVIEW);
509 glLoadIdentity ();
510 gluLookAt (200, 0, 0, 0, 0, 0, 0, 0, 1);
511
512 glPushMatrix ();
513 glRotated (90, 0, 1, 0);
514 glRotated (10 * dt, 0, 0, 1);
515
516 glColor3d (COLOR);
517
518 glNewList (1, GL_COMPILE);
519 Horn (mi, bp->NRPOINTS, 315 * sin (dt * 0.237), 50 + 20 * sin (dt * 0.133), 1500 * sin (dt * 0.213), 7.5 + 2.5 * sin (dt * 0.173), 0.6 + 0.1 * sin (dt * 0.317));
520 glEndList ();
521
522 if (bp->dOffAngle)
523 glRotated (45, 1, 1, 0);
524
525 for (i = 0; i < bp->NRLINES; i++) {
526 glPushMatrix ();
527 glRotated (360 * i / bp->NRLINES, 0, 0, 1);
528 glRotated (45, 1, 0, 0);
529 glTranslated (0, 0, 2);
530 glCallList (1);
531 glPopMatrix ();
532 }
533
534 glPopMatrix ();
535 }
536
537 if (MI_IS_FPS(mi)) do_fps (mi);
538 glXSwapBuffers(display, window);
539 }
540
setDefaults(ModeInfo * mi,int use_preset)541 static void setDefaults (ModeInfo *mi, int use_preset)
542 {
543 biofstruct *bp = &biof[MI_SCREEN(mi)];
544 bp->dGeometry = use_preset;
545
546 switch (use_preset) {
547 case TRIANGLES:
548 bp->NRPOINTS = 80;
549 bp->NRLINES = 32;
550
551 break;
552 case SPHERES:
553 bp->NRPOINTS = 80;
554 bp->NRLINES = 30;
555
556 break;
557 case BIGSPHERES:
558 bp->NRPOINTS = 20;
559 bp->NRLINES = 5;
560
561 break;
562 case POINTS:
563 bp->NRPOINTS = 250;
564 bp->NRLINES = 30;
565
566 break;
567 case LIGHTMAP:
568 bp->NRPOINTS = 150;
569 bp->NRLINES = 20;
570
571 break;
572 }
573 }
574
handle_opts(ModeInfo * mi)575 static void handle_opts (ModeInfo * mi)
576 {
577 biofstruct *bp = &biof[MI_SCREEN(mi)];
578 int change_flag = 0;
579
580 setDefaults(mi,LIGHTMAP);
581 bp->dOffAngle = 0;
582
583 if ( (var_preset > 0) && (var_preset < 6))
584 {
585 change_flag = 1;
586 setDefaults (mi, var_preset);
587 }
588 if (var_lines > 0)
589 {
590 change_flag = 1;
591 bp->NRLINES = var_lines;
592 }
593 if (var_points > 0)
594 {
595 change_flag = 1;
596 bp->NRPOINTS = var_points;
597 }
598 if (var_offangle)
599 {
600 change_flag = 1;
601 bp->dOffAngle = 1;
602 }
603
604 if (!change_flag) {
605 bp->dGeometry = NRAND (5) + 1;
606 bp->dOffAngle = NRAND (2);
607
608 switch (bp->dGeometry) {
609 case TRIANGLES:
610 case SPHERES:
611 bp->NRLINES = NRAND (7) + 2;
612 bp->NRPOINTS = NRAND (96) + 32;
613 break;
614
615 case BIGSPHERES:
616 bp->NRLINES = NRAND (7) + 4;
617 bp->NRPOINTS = NRAND (32) + 4;
618 break;
619
620 case POINTS:
621 case LIGHTMAP:
622 bp->NRLINES = NRAND (32) + 4;
623 bp->NRPOINTS = NRAND (64) + 64;
624 }
625 }
626 }
627
628 XSCREENSAVER_MODULE ("Biof", biof)
629
630 #endif /* MODE_biof */
631