2
* Copyright (C) 2009 Tugrul Galatali <tugrul@galatali.com
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program 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.
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
19
// feedback screensaver
21
const char *hack_name = "feedback";
33
#include <rsMath/rsVec.h>
38
unsigned int width = 256, height = 256;
39
unsigned int cwidth = 8, cheight = 8;
40
rsVec *displacements, *velocities, *accelerations;
44
float dSaturation = 1.0;
45
float dLightness = 1.0;
51
void hack_draw (xstuff_t * XStuff, double currentTime, float frameTime)
53
// ################################################################################
54
// Frame texture with a rotating color
56
glViewport (0, 0, width, height);
58
glMatrixMode (GL_PROJECTION);
60
gluOrtho2D (-0.125f, 1.125f, -0.125f, 1.125f);
61
glMatrixMode (GL_MODELVIEW);
69
l = currentTime / dPeriod - trunc(currentTime / dPeriod);
77
h = currentTime / dPeriod - trunc(currentTime / dPeriod);
84
hsl2rgb(h, s, l, r, g, b);
86
glClearColor (r, g, b, 1.0);
89
glClear (GL_COLOR_BUFFER_BIT);
91
glColor3f (1.0f, 1.0f, 1.0f);
94
glTexCoord2f (0.0, 1.0); glVertex2d (0.0, 1.0);
95
glTexCoord2f (1.0, 1.0); glVertex2d (1.0, 1.0);
96
glTexCoord2f (1.0, 0.0); glVertex2d (1.0, 0.0);
97
glTexCoord2f (0.0, 0.0); glVertex2d (0.0, 0.0);
100
glCopyTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, 0, 0, width, height, 0);
102
// ################################################################################
103
// Warp framed texture
105
glViewport (0, 0, width, height);
107
glMatrixMode (GL_PROJECTION);
109
gluOrtho2D (0.0f, 1.0f, 0.0f, 1.0f);
110
glMatrixMode (GL_MODELVIEW);
113
glColor3f (1.0, 1.0, 1.0);
115
for (unsigned int dh = 0; dh < cheight; ++dh) {
116
for (unsigned int dw = 0; dw < cwidth; ++dw) {
117
const rsVec da = rsVec(dw / float(cwidth), dh / float(cheight), 0.0);
118
const rsVec db = rsVec(dw / float(cwidth), (dh + 1) / float(cheight), 0.0);
119
const rsVec dc = rsVec((dw + 1) / float(cwidth), (dh + 1) / float(cheight), 0.0);
120
const rsVec dd = rsVec((dw + 1) / float(cwidth), dh / float(cheight), 0.0);
122
const unsigned nh = (dh + 1) & (cheight - 1);
123
const unsigned nw = (dw + 1) & (cwidth - 1);
124
const rsVec sa = displacements[dh * cwidth + dw] + rsVec(dw, dh, 0.0);
125
const rsVec sb = displacements[nh * cwidth + dw] + rsVec(dw, dh + 1, 0.0);
126
const rsVec sc = displacements[nh * cwidth + nw] + rsVec(dw + 1, dh + 1, 0.0);
127
const rsVec sd = displacements[dh * cwidth + nw] + rsVec(dw + 1, dh, 0.0);
129
glTexCoord2f (sa[0] / cwidth * 0.8 + 0.1, sa[1] / cheight * 0.8 + 0.1);
130
glVertex2f (da[0], da[1]);
131
glTexCoord2f (sb[0] / cwidth * 0.8 + 0.1, sb[1] / cheight * 0.8 + 0.1);
132
glVertex2f (db[0], db[1]);
133
glTexCoord2f (sc[0] / cwidth * 0.8 + 0.1, sc[1] / cheight * 0.8 + 0.1);
134
glVertex2f (dc[0], dc[1]);
135
glTexCoord2f (sd[0] / cwidth * 0.8 + 0.1, sd[1] / cheight * 0.8 + 0.1);
136
glVertex2f (dd[0], dd[1]);
141
glCopyTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, 0, 0, width, height, 0);
143
// ################################################################################
144
// Render warped texture to screen
146
glViewport (0, 0, XStuff->windowWidth, XStuff->windowHeight);
148
glClearColor (0.0, 0.0, 0.0, 1.0);
149
glClear (GL_COLOR_BUFFER_BIT);
151
glColor3f (1.0, 1.0, 1.0);
154
glTexCoord2f (0.0, 1.0); glVertex2d (0.0, 1.0);
155
glTexCoord2f (1.0, 1.0); glVertex2d (1.0, 1.0);
156
glTexCoord2f (1.0, 0.0); glVertex2d (1.0, 0.0);
157
glTexCoord2f (0.0, 0.0); glVertex2d (0.0, 0.0);
160
// ################################################################################
161
// Optionally display warping grid
164
glDisable (GL_TEXTURE_2D);
167
for (unsigned int dh = 0; dh < cheight; ++dh) {
168
for (unsigned int dw = 0; dw < cwidth; ++dw) {
169
const unsigned nh = (dh + 1) & (cheight - 1);
170
const unsigned nw = (dw + 1) & (cwidth - 1);
171
const rsVec a = displacements[dh * cwidth + dw] + rsVec(dw, dh, 0.0);
172
const rsVec b = displacements[nh * cwidth + dw] + rsVec(dw, dh + 1, 0.0);
173
const rsVec c = displacements[nh * cwidth + nw] + rsVec(dw + 1, dh + 1, 0.0);
174
const rsVec d = displacements[dh * cwidth + nw] + rsVec(dw + 1, dh, 0.0);
176
glColor3f (0.0, 1.0, 0.0);
178
glVertex2f (float(dw) / cwidth, float(dh) / cheight);
179
glVertex2f (a[0] / cwidth, a[1] / cheight);
181
glColor3f (1.0, 0.0, 0.0);
183
glVertex2f (a[0] / cwidth, a[1] / cheight);
184
glVertex2f (b[0] / cwidth, b[1] / cheight);
186
glVertex2f (b[0] / cwidth, b[1] / cheight);
187
glVertex2f (c[0] / cwidth, c[1] / cheight);
189
glVertex2f (c[0] / cwidth, c[1] / cheight);
190
glVertex2f (d[0] / cwidth, d[1] / cheight);
192
glVertex2f (d[0] / cwidth, d[1] / cheight);
193
glVertex2f (a[0] / cwidth, a[1] / cheight);
198
glEnable (GL_TEXTURE_2D);
201
// ################################################################################
204
// Only compute forces along leading edge to save duplication since the grid wraps...
208
for (unsigned int dh = 0, ii = 0; dh < cheight; ++dh) {
209
for (unsigned int dw = 0; dw < cwidth; ++dw) {
210
const int offsets[4][2] = { { 1, 0 }, { -1, 1 }, { 0, 1 }, { 1, 1 } };
212
accelerations[ii] += displacements[ii] * -displacements[ii].length();
214
for (int jj = 0; jj < 4; ++jj) {
215
const int nh = (int)dh + offsets[jj][0];
216
const int nw = (int)dw + offsets[jj][1];
217
const int nii = (nh & (cheight - 1)) * cwidth + (nw & (cwidth - 1));
219
const rsVec nn = displacements[nii] - displacements[ii] + rsVec(nh - (int)dh, nw - (int)dw, 0.0);
221
const float nominalDisplacements[3] = { 0.0f, 1.0f, M_SQRT2 };
222
const float nominalDisplacement = nominalDisplacements[abs(offsets[jj][0]) + abs(offsets[jj][1])];
224
const rsVec ff = nn * (nn.length() - nominalDisplacement);
225
accelerations[ii] += ff;
226
accelerations[nii] -= ff;
233
rsVec newTotalV(0, 0, 0);
234
const float totalVScalar = totalV.length();
235
const float stepSize = min(frameTime, 0.05f);
236
for (unsigned int dh = 0, ii = 0; dh < cheight; ++dh) {
237
for (unsigned int dw = 0; dw < cwidth; ++dw) {
238
velocities[ii] += accelerations[ii] * stepSize;
239
accelerations[ii] = rsVec(0.0f, 0.0f, 0.0f);
241
// Don't let things get too fast
242
if (totalVScalar > 20.0f) {
243
velocities[ii] -= velocities[ii] / exp(totalVScalar - 20.0);
246
newTotalV += rsVec(abs(velocities[ii][0]), abs(velocities[ii][1]), 0);
248
displacements[ii] += velocities[ii] * stepSize * dSpeed;
250
// or displacements too large
251
if (displacements[ii].length() > 1.0) {
252
displacements[ii] = displacements[ii] / displacements[ii].length();
261
void hack_reshape (xstuff_t * XStuff)
263
// Window initialization
264
glViewport (0, 0, XStuff->windowWidth, XStuff->windowHeight);
266
glMatrixMode (GL_PROJECTION);
268
gluOrtho2D (0.0f, 1.0f, 0.0f, 1.0f);
269
glMatrixMode (GL_MODELVIEW);
273
void hack_init (xstuff_t * XStuff)
276
width = height = 1 << dTexSize;
277
int newTexSize = dTexSize;
278
while ((width > XStuff->windowWidth) || (height > XStuff->windowHeight)) {
281
height = height >> 1;
284
if (newTexSize != dTexSize) {
285
printf("--texsize reduced to %d from %d to fit display\n", newTexSize, dTexSize);
286
dTexSize = newTexSize;
289
unsigned char *pixels = new unsigned char[width * height * 3];
290
for (unsigned int hh = 0, ii = 0; hh < height; ++hh) {
291
for (unsigned int ww = 0; ww < width; ++ww) {
295
hsl2rgb(0.0, 0.0, hh * ww / float(height * width), r, g, b);
297
hsl2rgb(hh / float(height), dSaturation, dLightness, r, g, b);
300
pixels[ii++] = r * 255;
301
pixels[ii++] = g * 255;
302
pixels[ii++] = b * 255;
306
glGenTextures (1, &tex);
308
glBindTexture (GL_TEXTURE_2D, tex);
310
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
311
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
312
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
313
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
315
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
320
displacements = new rsVec[cwidth * cheight];
321
velocities = new rsVec[cwidth * cheight];
322
accelerations = new rsVec[cwidth * cheight];
324
for (unsigned int hh = 0, ii = 0; hh < cheight; ++hh) {
325
for (unsigned int ww = 0; ww < cwidth; ++ww) {
326
displacements[ii][0] = rsRandf(0.5) - 0.25;
327
displacements[ii][1] = rsRandf(0.5) - 0.25;
328
displacements[ii][2] = 0.0;
329
velocities[ii] = rsVec(0.0f, 0.0f, 0.0f);
330
accelerations[ii] = rsVec(0.0f, 0.0f, 0.0f);
335
glEnable (GL_TEXTURE_2D);
337
hack_reshape(XStuff);
340
void hack_cleanup (xstuff_t * XStuff)
342
delete [] displacements;
343
delete [] velocities;
344
delete [] accelerations;
347
void hack_handle_opts (int argc, char **argv)
350
printf("handle_hack_opts\n");
356
static struct option long_options[] = {
359
{"saturation", 0, 0, 'S'},
360
{"lightness", 0, 0, 'L'},
361
{"period", 1, 0, 'p'},
362
{"speed", 1, 0, 's'},
363
{"cells", 1, 0, 'c'},
364
{"texsize", 1, 0, 't'},
369
c = getopt_long (argc, argv, DRIVER_OPTIONS_SHORT "hgS:L:p:s:c:t:i", long_options, NULL);
371
c = getopt (argc, argv, DRIVER_OPTIONS_SHORT "hgS:L:p:s:c:t:i");
380
#ifndef HAVE_GETOPT_H
381
" Not built with GNU getopt.h, long options *NOT* enabled."
383
"\n" DRIVER_OPTIONS_HELP
385
"\t--saturation/-S <arg>\n"
386
"\t--lightness/-L <arg>\n"
387
"\t--period/-p <arg>\n"
388
"\t--speed/-s <arg>\n"
389
"\t--cells/-c <arg>\n"
390
"\t--texsize/-t <arg>\n"
391
"\t--grid/-i\n", argv[0]);
397
dSaturation = strtol_minmaxdef (optarg, 10, 1, 255, 1, 255, "--saturation: ") / 255.0;
400
dLightness = strtol_minmaxdef (optarg, 10, 1, 255, 1, 255, "--lightness: ") / 255.0;
403
dPeriod = strtol_minmaxdef (optarg, 10, 1, 100, 1, 5, "--period: ");
406
dSpeed = strtol_minmaxdef (optarg, 10, 1, 100, 1, 10, "--speed: ") / 10.0;
409
cwidth = cheight = 1 << strtol_minmaxdef (optarg, 10, 0, 6, 1, 3, "--cells: ");
412
dTexSize = strtol_minmaxdef (optarg, 10, 6, 12, 1, 8, "--texsize: ");