1 /*
2  * Copyright (C) 2002  <hk@dgmr.nl>
3  * Ported to Linux by Tugrul Galatali <tugrul@galatali.com>
4  *
5  * BioF is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * BioF is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 
19 // BioF screen saver
20 
21 #include <math.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <GL/gl.h>
25 #include <GL/glu.h>
26 
27 #include "driver.h"
28 #include "rsRand.h"
29 
30 const char *hack_name = "BioF";
31 
32 #define TRIANGLES 1
33 #define SPHERES 2
34 #define BIGSPHERES 3
35 #define POINTS 4
36 #define LIGHTMAP 5
37 
38 int NRPOINTS, NRLINES;
39 int dGeometry;
40 int dOffAngle;
41 
42 GLUquadricObj *shapes;
43 
Horn(int ribs,double bend,double stack,double twist,double twisttrans,double grow)44 void Horn (int ribs, double bend, double stack, double twist, double twisttrans, double grow)
45 {
46 	int i;
47 
48 	for (i = 0; i < ribs; i++) {
49 		glPushMatrix ();
50 		glRotated (i * bend / ribs, 1, 0, 0);
51 		glTranslated (0, 0, i * stack / ribs);
52 		glTranslated (twisttrans, 0, 0);
53 		glRotated (i * twist / ribs, 0, 0, 1);
54 		glTranslated (-twisttrans, 0, 0);
55 
56 		switch (dGeometry) {
57 		case TRIANGLES:
58 			glBegin (GL_TRIANGLES);
59 			glColor4d (0.9, 0.8, 0.5, 1);
60 			glVertex3d (2, 2, 0);
61 			glColor4d (0.9, 0.8, 0.5, 0.0);
62 			glVertex3d (0, 2, 0);
63 			glVertex3d (2, 0, 0);
64 			glEnd ();
65 
66 			break;
67 
68 		case BIGSPHERES:
69 			gluQuadricDrawStyle (shapes, GLU_FILL);
70 			gluQuadricNormals (shapes, GLU_SMOOTH);
71 			gluSphere (shapes, 7 * exp (i / ribs * log (grow)), 20, 10);
72 
73 			break;
74 
75 		case SPHERES:
76 			gluQuadricDrawStyle (shapes, GLU_FILL);
77 			gluQuadricNormals (shapes, GLU_SMOOTH);
78 			//gluSphere(shapes, power(grow,i/ribs), 5, 5);
79 			gluSphere (shapes, exp (i / ribs * log (grow)), 6, 4);
80 
81 			break;
82 
83 		case LIGHTMAP:
84 		case POINTS:
85 			glBegin (GL_POINTS);
86 			glVertex3d (0, 0, 0);
87 			glEnd ();
88 
89 			break;
90 		}
91 
92 		glPopMatrix ();
93 	}
94 }
95 
hack_reshape(xstuff_t * XStuff)96 void hack_reshape (xstuff_t * XStuff)
97 {
98 	glViewport (0, 0, (GLsizei) XStuff->windowWidth, (GLsizei) XStuff->windowHeight);
99 	glMatrixMode (GL_PROJECTION);
100 	glLoadIdentity ();
101 	gluPerspective (30, (float)XStuff->windowWidth / (float)XStuff->windowHeight, 100, 300);
102 }
103 
hack_init(xstuff_t * XStuff)104 void hack_init (xstuff_t * XStuff)	// Called right after the window is created, and OpenGL is initialized.
105 {
106 	float glfLightPosition[4] = { 100.0, 100.0, 100.0, 0.0 };
107 	float glfFog[4] = { 0.0, 0.0, 0.3, 1.0 };
108 	float DiffuseLightColor[4] = { 1, 0.8, 0.4, 1.0 };
109 	int i, j;
110 	double x, y, r, d;
111 	unsigned char texbuf[64][64];
112 
113 	glEnable (GL_DEPTH_TEST);
114 
115 	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
116 	glEnable (GL_BLEND);
117 
118 	if ((dGeometry == SPHERES) || (dGeometry == BIGSPHERES)) {
119 		glEnable (GL_CULL_FACE);
120 		glCullFace (GL_BACK);
121 
122 		glLightfv (GL_LIGHT0, GL_POSITION, glfLightPosition);
123 		glEnable (GL_LIGHTING);
124 		glEnable (GL_LIGHT0);
125 
126 		glLightfv (GL_LIGHT0, GL_DIFFUSE, DiffuseLightColor);
127 
128 		shapes = gluNewQuadric ();
129 	} else if (dGeometry == POINTS) {
130 		glHint (GL_POINT_SMOOTH_HINT, GL_NICEST);
131 		glPointSize (3);
132 		glEnable (GL_POINT_SMOOTH);
133 
134 		glFogi (GL_FOG_MODE, GL_LINEAR);
135 		glHint (GL_FOG_HINT, GL_NICEST);
136 		glFogfv (GL_FOG_COLOR, glfFog);
137 		glFogf (GL_FOG_START, 150);
138 		glFogf (GL_FOG_END, 250);
139 		glEnable (GL_FOG);
140 	} else if (dGeometry == LIGHTMAP) {
141 		r = 32;
142 
143 		memset ((void *)&texbuf, 0, 4096);
144 
145 		for (i = 0; i < 64; i++) {
146 			for (j = 0; j < 64; j++) {
147 				x = abs (i - 32);
148 				y = abs (j - 32);
149 				d = sqrt (x * x + y * y);
150 
151 				if (d < r) {
152 					d = 1 - (d / r);
153 					texbuf[i][j] = (char)(255.0f * d * d);
154 				}
155 			}
156 		}
157 
158 		gluBuild2DMipmaps (GL_TEXTURE_2D, 1, 64, 64, GL_LUMINANCE, GL_UNSIGNED_BYTE, texbuf);
159 
160 		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
161 		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
162 	}
163 
164 	hack_reshape (XStuff);
165 }
166 
hack_cleanup(xstuff_t * XStuff)167 void hack_cleanup (xstuff_t * XStuff)
168 {
169 	if ((dGeometry == SPHERES) || (dGeometry == BIGSPHERES))
170 		gluDeleteQuadric(shapes);
171 }
172 
hack_draw(xstuff_t * XStuff,double currentTime,float lastFrameDuration)173 void hack_draw (xstuff_t * XStuff, double currentTime, float lastFrameDuration)
174 {
175 	if (dGeometry == LIGHTMAP) {
176 		int i, j, offset;
177 		float fb_buffer[NRPOINTS * NRLINES * 3];
178 		double x, y, w;
179 
180 		glDisable (GL_DEPTH_TEST);
181 		glFeedbackBuffer (NRPOINTS * NRLINES * 3, GL_2D, fb_buffer);
182 		glRenderMode (GL_FEEDBACK);
183 
184 		glMatrixMode (GL_MODELVIEW);
185 		glPushMatrix ();
186 		glLoadIdentity ();
187 
188 		gluLookAt (200, 0, 0, 0, 0, 0, 0, 0, 1);
189 
190 		glRotated (90, 0, 1, 0);
191 		glRotated (10 * currentTime, 0, 0, 1);
192 
193 		glNewList (1, GL_COMPILE);
194 		Horn (NRPOINTS, 315 * sin (currentTime * 0.237), 45 /* + 20 * sin(currentTime * 0.133) */ , 1500 * sin (currentTime * 0.213), 7.5 + 2.5 * sin (currentTime * 0.173), 1);
195 		glEndList ();
196 
197 		if (dOffAngle)
198 			glRotated (45, 1, 1, 0);
199 
200 		for (i = 0; i < NRLINES; i++) {
201 			glPushMatrix ();
202 
203 			glRotated (360 * i / NRLINES, 0, 0, 1);
204 			glRotated (45, 1, 0, 0);
205 			glTranslated (0, 0, 2);
206 
207 			glCallList (1);
208 
209 			glPopMatrix ();
210 		}
211 
212 		glPopMatrix ();
213 
214 		glRenderMode (GL_RENDER);
215 
216 		glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
217 
218 		glMatrixMode (GL_PROJECTION);
219 		glPushMatrix ();
220 		glLoadIdentity ();
221 
222 		glMatrixMode (GL_MODELVIEW);
223 		glPushMatrix ();
224 		glLoadIdentity ();
225 
226 		glScalef (2.0 / XStuff->windowWidth, 2.0 / XStuff->windowHeight, 1.0);
227 		glTranslatef (-0.5 * XStuff->windowWidth, -0.5 * XStuff->windowHeight, 0.0);
228 
229 		glClear (GL_COLOR_BUFFER_BIT);
230 
231 		glEnable (GL_TEXTURE_2D);
232 		glBlendFunc (GL_ONE, GL_ONE);
233 		glEnable (GL_BLEND);
234 
235 		glBegin (GL_QUADS);
236 
237 		w = XStuff->windowWidth >> 7;
238 
239 		for (j = 0; j < NRPOINTS; j++) {
240 			glColor3f (0.25 - 0.15 * j / NRPOINTS, 0.15 + 0.10 * j / NRPOINTS, 0.06 + 0.14 * j / NRPOINTS);
241 			for (i = 0; i < NRLINES; i++) {
242 				offset = 3 * (i * NRPOINTS + j);
243 				x = fb_buffer[offset + 1];
244 				y = fb_buffer[offset + 2];
245 
246 				glTexCoord2f (0.0, 0.0);
247 				glVertex2f (x - w, y - w);
248 
249 				glTexCoord2f (1.0, 0.0);
250 				glVertex2f (x + w, y - w);
251 
252 				glTexCoord2f (1.0, 1.0);
253 				glVertex2f (x + w, y + w);
254 
255 				glTexCoord2f (0.0, 1.0);
256 				glVertex2f (x - w, y + w);
257 			}
258 		}
259 
260 		glEnd ();
261 
262 		glMatrixMode (GL_MODELVIEW);
263 		glPopMatrix ();
264 		glMatrixMode (GL_PROJECTION);
265 		glPopMatrix ();
266 	} else {
267 		int i;
268 
269 		glClear (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
270 
271 		glMatrixMode (GL_MODELVIEW);
272 		glLoadIdentity ();
273 		gluLookAt (200, 0, 0, 0, 0, 0, 0, 0, 1);
274 
275 		glPushMatrix ();
276 		glRotated (90, 0, 1, 0);
277 		glRotated (10 * currentTime, 0, 0, 1);
278 
279 		glColor3d (0.9, 0.7, 0.5);
280 
281 		glNewList (1, GL_COMPILE);
282 		Horn (NRPOINTS, 315 * sin (currentTime * 0.237), 50 + 20 * sin (currentTime * 0.133), 1500 * sin (currentTime * 0.213), 7.5 + 2.5 * sin (currentTime * 0.173), 0.6 + 0.1 * sin (currentTime * 0.317));
283 		glEndList ();
284 
285 		if (dOffAngle)
286 			glRotated (45, 1, 1, 0);
287 
288 		for (i = 0; i < NRLINES; i++) {
289 			glPushMatrix ();
290 			glRotated (360 * i / NRLINES, 0, 0, 1);
291 			glRotated (45, 1, 0, 0);
292 			glTranslated (0, 0, 2);
293 			glCallList (1);
294 			glPopMatrix ();
295 		}
296 
297 		glPopMatrix ();
298 	}
299 }
300 
setDefaults(int preset)301 void setDefaults (int preset)
302 {
303 	dGeometry = preset;
304 
305 	switch (preset) {
306 	case TRIANGLES:
307 		NRPOINTS = 80;
308 		NRLINES = 32;
309 
310 		break;
311 	case SPHERES:
312 		NRPOINTS = 80;
313 		NRLINES = 30;
314 
315 		break;
316 	case BIGSPHERES:
317 		NRPOINTS = 20;
318 		NRLINES = 5;
319 
320 		break;
321 	case POINTS:
322 		NRPOINTS = 250;
323 		NRLINES = 30;
324 
325 		break;
326 	case LIGHTMAP:
327 		NRPOINTS = 150;
328 		NRLINES = 20;
329 
330 		break;
331 	}
332 }
333 
hack_handle_opts(int argc,char ** argv)334 void hack_handle_opts (int argc, char **argv)
335 {
336 	int change_flag = 0;
337 
338 	setDefaults(LIGHTMAP);
339 	dOffAngle = 0;
340 
341 	while (1) {
342 		int c;
343 
344 #ifdef HAVE_GETOPT_H
345 		static struct option long_options[] = {
346 			{"help", 0, 0, 'h'},
347 			DRIVER_OPTIONS_LONG {"preset", 1, 0, 'P'},
348 			{"triangles", 0, 0, 0},
349 			{"spheres", 0, 0, 1},
350 			{"bigspheres", 0, 0, 2},
351 			{"points", 0, 0, 3},
352 			{"lightmap", 0, 0, 4},
353 			{"lines", 1, 0, 'l'},
354 			{"points", 1, 0, 'p'},
355 			{"offangle", 0, 0, 'o'},
356 			{0, 0, 0, 0}
357 		};
358 
359 		c = getopt_long (argc, argv, DRIVER_OPTIONS_SHORT "hP:l:p:o", long_options, NULL);
360 #else
361 		c = getopt (argc, argv, DRIVER_OPTIONS_SHORT "hP:l:p:o");
362 #endif
363 		if (c == -1)
364 			break;
365 
366 		switch (c) {
367 			DRIVER_OPTIONS_CASES case 'h':printf ("%s:"
368 #ifndef HAVE_GETOPT_H
369 							      " Not built with GNU getopt.h, long options *NOT* enabled."
370 #endif
371 							      "\n" DRIVER_OPTIONS_HELP "\t--preset/-P <arg>\n" "\t--triangles\n"
372 							      "\t--spheres\n" "\t--bigspheres\n" "\t--points\n" "\t--lightmap\n"
373 							      "\t--lines/-l <arg>\n" "\t--points/-p <arg>\n" "\t--offangle\n", argv[0]);
374 			exit (1);
375 		case 'P':
376 			change_flag = 1;
377 			setDefaults (strtol_minmaxdef (optarg, 10, 1, 5, 0, 1, "--preset: "));
378 			break;
379 		case 0:
380 		case 1:
381 		case 2:
382 		case 3:
383 		case 4:
384 			change_flag = 1;
385 			setDefaults (c + 1);
386 			break;
387 		case 'l':
388 			change_flag = 1;
389 			NRLINES = strtol_minmaxdef (optarg, 10, 1, 1024, 0, 1, "--lines: ");
390 			break;
391 		case 'p':
392 			change_flag = 1;
393 			NRPOINTS = strtol_minmaxdef (optarg, 10, 1, 4096, 0, 1, "--points: ");
394 			break;
395 		case 'o':
396 			change_flag = 1;
397 			dOffAngle = 1;
398 		}
399 	}
400 
401 	if (!change_flag) {
402 		dGeometry = rsRandi (5) + 1;
403 		dOffAngle = rsRandi (2);
404 
405 		switch (dGeometry) {
406 		case TRIANGLES:
407 		case SPHERES:
408 			NRLINES = rsRandi (7) + 2;
409 			NRPOINTS = rsRandi (96) + 32;
410 			break;
411 
412 		case BIGSPHERES:
413 			NRLINES = rsRandi (7) + 4;
414 			NRPOINTS = rsRandi (32) + 4;
415 			break;
416 
417 		case POINTS:
418 		case LIGHTMAP:
419 			NRLINES = rsRandi (32) + 4;
420 			NRPOINTS = rsRandi (64) + 64;
421 		}
422 	}
423 }
424 
425