1 /*
2 * Copyright (C) 2002 Terence M. Welsh
3 * Ported to Linux by Tugrul Galatali <tugrul@galatali.com>
4 *
5 * Plasma 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 * Plasma 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 // Plasma screen saver
20
21 #include <math.h>
22 #include <stdio.h>
23 #include <GL/gl.h>
24 #include <GL/glu.h>
25
26 #include "driver.h"
27 #include "rsDefines.h"
28 #include "rsRand.h"
29
30 const char *hack_name = "plasma";
31
32 #define NUMCONSTS 18
33 #define MAXTEXSIZE 1024
34
35 // Globals
36 float aspectRatio;
37 float wide;
38 float high;
39 float c[NUMCONSTS]; // constant
40 float ct[NUMCONSTS]; // temporary value of constant
41 float cv[NUMCONSTS]; // velocity of constant
42 float ***position;
43 float ***plasma;
44 unsigned int tex;
45 int texsize = 256;
46 int plasmaWidth, plasmaHeight;
47 float texright, textop;
48 float *plasmamap;
49
50 // Parameters edited in the dialog box
51 int dZoom;
52 int dFocus;
53 int dSpeed;
54 int dResolution;
55
56 // Find absolute value and truncate to 1.0
57 #define fabstrunc(f) (f >= 0.0f ? (f <= 1.0f ? f : 1.0f) : (f >= -1.0f ? -f : 1.0f))
58
59 /*
60 float fabstrunc (float f)
61 {
62 if (f >= 0.0f) {
63 return (f <= 1.0f ? f : 1.0f);
64 } else {
65 return (f >= -1.0f ? -f : 1.0f);
66 }
67 }
68 */
69
hack_draw(xstuff_t * XStuff,double currentTime,float frameTime)70 void hack_draw (xstuff_t * XStuff, double currentTime, float frameTime)
71 {
72 int i, j;
73 float rgb[3];
74 float temp;
75 static float focus = float (dFocus) / 50.0f + 0.3f;
76 static float maxdiff = 0.004f * float (dSpeed);
77 static int index;
78
79 // Update constants
80 for (i = 0; i < NUMCONSTS; i++) {
81 ct[i] += cv[i];
82 if (ct[i] > PIx2)
83 ct[i] -= PIx2;
84 c[i] = sin (ct[i]) * focus;
85 }
86
87 // Update colors
88 for (i = 0; i < plasmaHeight; i++) {
89 for (j = 0; j < plasmaWidth; j++) {
90 // Calculate vertex colors
91 rgb[0] = plasma[i][j][0];
92 rgb[1] = plasma[i][j][1];
93 rgb[2] = plasma[i][j][2];
94 plasma[i][j][0] = 0.7f * (c[0] * position[i][j][0] + c[1] * position[i][j][1]
95 + c[2] * (position[i][j][0] * position[i][j][0] + 1.0f)
96 + c[3] * position[i][j][0] * position[i][j][1]
97 + c[4] * rgb[1] + c[5] * rgb[2]);
98 plasma[i][j][1] = 0.7f * (c[6] * position[i][j][0] + c[7] * position[i][j][1]
99 + c[8] * position[i][j][0] * position[i][j][0]
100 + c[9] * (position[i][j][1] * position[i][j][1] - 1.0f)
101 + c[10] * rgb[0] + c[11] * rgb[2]);
102 plasma[i][j][2] = 0.7f * (c[12] * position[i][j][0] + c[13] * position[i][j][1]
103 + c[14] * (1.0f - position[i][j][0] * position[i][j][1])
104 + c[15] * position[i][j][1] * position[i][j][1]
105 + c[16] * rgb[0] + c[17] * rgb[1]);
106
107 // Don't let the colors change too much
108 temp = plasma[i][j][0] - rgb[0];
109 if (temp > maxdiff)
110 plasma[i][j][0] = rgb[0] + maxdiff;
111 if (temp < -maxdiff)
112 plasma[i][j][0] = rgb[0] - maxdiff;
113 temp = plasma[i][j][1] - rgb[1];
114 if (temp > maxdiff)
115 plasma[i][j][1] = rgb[1] + maxdiff;
116 if (temp < -maxdiff)
117 plasma[i][j][1] = rgb[1] - maxdiff;
118 temp = plasma[i][j][2] - rgb[2];
119 if (temp > maxdiff)
120 plasma[i][j][2] = rgb[2] + maxdiff;
121 if (temp < -maxdiff)
122 plasma[i][j][2] = rgb[2] - maxdiff;
123
124 // Put colors into texture
125 index = (i * texsize + j) * 3;
126 plasmamap[index] = fabstrunc (plasma[i][j][0]);
127 plasmamap[index + 1] = fabstrunc (plasma[i][j][1]);
128 plasmamap[index + 2] = fabstrunc (plasma[i][j][2]);
129 }
130 }
131
132 // Update texture
133 glPixelStorei(GL_UNPACK_ROW_LENGTH, texsize);
134 glBindTexture(GL_TEXTURE_2D, tex);
135 glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, plasmaWidth, plasmaHeight, GL_RGB, GL_FLOAT, plasmamap);
136
137 // Draw it
138 glBegin (GL_TRIANGLE_STRIP);
139 glTexCoord2f (0.0f, 0.0f);
140 glVertex2f (0.0f, 0.0f);
141 glTexCoord2f (0.0f, texright);
142 glVertex2f (1.0f, 0.0f);
143 glTexCoord2f (textop, 0.0f);
144 glVertex2f (0.0f, 1.0f);
145 glTexCoord2f (textop, texright);
146 glVertex2f (1.0f, 1.0f);
147 glEnd ();
148 }
149
hack_reshape(xstuff_t * XStuff)150 void hack_reshape (xstuff_t * XStuff)
151 {
152 // Window initialization
153 glViewport (0, 0, XStuff->windowWidth, XStuff->windowHeight);
154
155 glMatrixMode (GL_PROJECTION);
156 glLoadIdentity ();
157 gluOrtho2D (0.0f, 1.0f, 0.0f, 1.0f);
158 glMatrixMode (GL_MODELVIEW);
159 glLoadIdentity ();
160 }
161
hack_init(xstuff_t * XStuff)162 void hack_init (xstuff_t * XStuff)
163 {
164 int i, j;
165
166 hack_reshape (XStuff);
167
168 aspectRatio = float (XStuff->windowWidth) / float (XStuff->windowHeight);
169
170 if (aspectRatio >= 1.0f) {
171 wide = 30.0f / float (dZoom);
172
173 high = wide / aspectRatio;
174 } else {
175 high = 30.0f / float (dZoom);
176
177 wide = high * aspectRatio;
178 }
179
180 // Set resolution of plasma
181 if (aspectRatio >= 1.0f)
182 plasmaHeight = (dResolution * MAXTEXSIZE) / 100;
183 else
184 plasmaHeight = int (float (dResolution * MAXTEXSIZE) * aspectRatio * 0.01f);
185
186 plasmaWidth = int (float (plasmaHeight) / aspectRatio);
187
188 // Set resolution of texture
189 texsize = 16;
190 if (aspectRatio >= 1.0f)
191 while (plasmaHeight > texsize)
192 texsize *= 2;
193 else
194 while (plasmaWidth > texsize)
195 texsize *= 2;
196
197 // The "- 1" cuts off right and top edges to get rid of blending to black
198 texright = float (plasmaHeight - 1) / float (texsize);
199 textop = texright / aspectRatio;
200
201 // Initialize memory and positions
202 plasmamap = new float[texsize * texsize * 3];
203
204 for (i = 0; i < texsize * texsize * 3; i++)
205 plasmamap[i] = 0.0f;
206 plasma = new float **[plasmaHeight];
207 position = new float **[plasmaHeight];
208
209 for (i = 0; i < plasmaHeight; i++) {
210 plasma[i] = new float *[plasmaWidth];
211 position[i] = new float *[plasmaWidth];
212
213 for (j = 0; j < plasmaWidth; j++) {
214 plasma[i][j] = new float[3];
215 position[i][j] = new float[2];
216
217 plasma[i][j][0] = 0.0f;
218 plasma[i][j][1] = 0.0f;
219 plasma[i][j][2] = 0.0f;
220 position[i][j][0] = float (i * wide) / float (plasmaHeight - 1) - (wide * 0.5f);
221 position[i][j][1] = float (j * high) / (float(plasmaHeight) / aspectRatio - 1.0f) - (high * 0.5f);
222 }
223 }
224 // Initialize constants
225 for (i = 0; i < NUMCONSTS; i++) {
226 ct[i] = rsRandf (PIx2);
227 cv[i] = rsRandf (0.005f * dSpeed) + 0.0001f;
228 }
229
230 // Make texture
231 glGenTextures(1, &tex);
232 glBindTexture(GL_TEXTURE_2D, tex);
233 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
234 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
235 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
236 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
237 glTexImage2D (GL_TEXTURE_2D, 0, 3, texsize, texsize, 0, GL_RGB, GL_FLOAT, plasmamap);
238 glEnable (GL_TEXTURE_2D);
239 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
240 }
241
hack_cleanup(xstuff_t * XStuff)242 void hack_cleanup (xstuff_t * XStuff)
243 {
244 }
245
hack_handle_opts(int argc,char ** argv)246 void hack_handle_opts (int argc, char **argv)
247 {
248 dZoom = 10;
249 dFocus = 30;
250 dSpeed = 20;
251 dResolution = 25;
252
253 while (1) {
254 int c;
255
256 #ifdef HAVE_GETOPT_H
257 static struct option long_options[] = {
258 {"help", 0, 0, 'h'},
259 DRIVER_OPTIONS_LONG
260 {"zoom", 1, 0, 'z'},
261 {"focus", 1, 0, 'f'},
262 {"speed", 1, 0, 's'},
263 {"resolution", 1, 0, 'R'},
264 {0, 0, 0, 0}
265 };
266
267 c = getopt_long (argc, argv, DRIVER_OPTIONS_SHORT "hz:f:s:R:", long_options, NULL);
268 #else
269 c = getopt (argc, argv, DRIVER_OPTIONS_SHORT "hz:f:s:R:");
270 #endif
271 if (c == -1)
272 break;
273
274 switch (c) {
275 DRIVER_OPTIONS_CASES case 'h':printf ("%s:"
276 #ifndef HAVE_GETOPT_H
277 " Not built with GNU getopt.h, long options *NOT* enabled."
278 #endif
279 "\n" DRIVER_OPTIONS_HELP "\t--zoom/-z <arg>\n" "\t--focus/-f <arg>\n" "\t--speed/-s <arg>\n"
280 "\t--resolution/-R <arg>\n", argv[0]);
281 exit (1);
282 case 'z':
283 dZoom = strtol_minmaxdef (optarg, 10, 1, 100, 1, 10, "--zoom: ");
284 break;
285 case 'f':
286 dFocus = strtol_minmaxdef (optarg, 10, 1, 100, 1, 30, "--focus: ");
287 break;
288 case 's':
289 dSpeed = strtol_minmaxdef (optarg, 10, 1, 100, 1, 20, "--speed: ");
290 break;
291 case 'R':
292 dResolution = strtol_minmaxdef (optarg, 10, 1, 100, 1, 25, "--resolution: ");
293 break;
294 }
295 }
296 }
297