SVN_SILENT made messages (.desktop file)
[kdeartwork.git] / kscreensaver / kdesavers / Euphoria.cpp
blobe098d5926ce354eb5b0e2153a502d5d0ed19a13f
1 /*
2 * Terence Welsh Screensaver - Euphoria
3 * http://www.reallyslick.com/
5 * Ported to KDE by Karl Robillard
6 * Copyright (C) 2002 Terence M. Welsh
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <math.h>
25 #include <time.h>
26 #include <qtimer.h>
28 #include "Euphoria.h"
29 #include "Euphoria.moc"
30 #include "EuphoriaTexture.h"
31 #include <GL/glu.h>
34 #define NUMCONSTS 9
35 #define PIx2 6.28318530718f
38 //----------------------------------------------------------------------------
41 #include <sys/time.h>
42 #include <unistd.h>
45 // Returns the system time, in seconds.
46 double timeGetTime()
48 struct timeval tp;
49 gettimeofday( &tp, 0 );
50 return (double)tp.tv_sec + (double)tp.tv_usec / 1000000;
54 //----------------------------------------------------------------------------
57 class rsVec
59 public:
61 float v[3];
63 rsVec() {}
64 rsVec(float xx, float yy, float zz);
66 void set(float xx, float yy, float zz);
67 float normalize();
68 float dot(rsVec);
69 void cross(rsVec, rsVec);
71 float & operator [] (int i) {return v[i];}
72 const float & operator [] (int i) const {return v[i];}
73 rsVec & operator = (const rsVec &vec)
74 {v[0]=vec[0];v[1]=vec[1];v[2]=vec[2];return *this;}
75 rsVec operator + (const rsVec &vec)
76 {return(rsVec(v[0]+vec[0], v[1]+vec[1], v[2]+vec[2]));}
77 rsVec operator - (const rsVec &vec)
78 {return(rsVec(v[0]-vec[0], v[1]-vec[1], v[2]-vec[2]));}
79 rsVec operator * (const float &mul)
80 {return(rsVec(v[0]*mul, v[1]*mul, v[2]*mul));}
81 rsVec operator / (const float &div)
82 {float rec = 1.0f/div; return(rsVec(v[0]*rec, v[1]*rec, v[2]*rec));}
83 rsVec & operator += (const rsVec &vec)
84 {v[0]+=vec[0];v[1]+=vec[1];v[2]+=vec[2];return *this;}
85 rsVec & operator -= (const rsVec &vec)
86 {v[0]-=vec[0];v[1]-=vec[1];v[2]-=vec[2];return *this;}
87 rsVec & operator *= (const rsVec &vec)
88 {v[0]*=vec[0];v[1]*=vec[1];v[2]*=vec[2];return *this;}
89 rsVec & operator *= (const float &mul)
90 {v[0]*=mul;v[1]*=mul;v[2]*=mul;return *this;}
94 rsVec::rsVec(float xx, float yy, float zz){
95 v[0] = xx;
96 v[1] = yy;
97 v[2] = zz;
101 void rsVec::set(float xx, float yy, float zz){
102 v[0] = xx;
103 v[1] = yy;
104 v[2] = zz;
108 float rsVec::normalize(){
109 float length = float(sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]));
110 if(length == 0.0f){
111 v[1] = 1.0f;
112 return(0.0f);
114 float reciprocal = 1.0f / length;
115 v[0] *= reciprocal;
116 v[1] *= reciprocal;
117 v[2] *= reciprocal;
118 // Really freakin' stupid compiler bug fix for VC++ 5.0
119 /*v[0] /= length;
120 v[1] /= length;
121 v[2] /= length;*/
122 return(length);
126 float rsVec::dot(rsVec vec1){
127 return(v[0] * vec1[0] + v[1] * vec1[1] + v[2] * vec1[2]);
131 void rsVec::cross(rsVec vec1, rsVec vec2){
132 v[0] = vec1[1] * vec2[2] - vec2[1] * vec1[2];
133 v[1] = vec1[2] * vec2[0] - vec2[2] * vec1[0];
134 v[2] = vec1[0] * vec2[1] - vec2[0] * vec1[1];
138 //----------------------------------------------------------------------------
141 void hsl2rgb(float h, float s, float l, float &r, float &g, float &b)
143 // hue influence
144 if(h < 0.166667){ // full red, some green
145 r = 1.0;
146 g = h * 6.0f;
147 b = 0.0;
149 else {
150 if(h < 0.5){ // full green
151 g = 1.0;
152 if(h < 0.333333){ // some red
153 r = 1.0f - ((h - 0.166667f) * 6.0f);
154 b = 0.0;
156 else{ // some blue
157 b = (h - 0.333333f) * 6.0f;
158 r = 0.0;
161 else{
162 if(h < 0.833333){ // full blue
163 b = 1.0;
164 if(h < 0.666667){ // some green
165 g = 1.0f - ((h - 0.5f) * 6.0f);
166 r = 0.0;
168 else{ // some red
169 r = (h - 0.666667f) * 6.0f;
170 g = 0.0;
173 else{ // full red, some blue
174 r = 1.0;
175 b = 1.0f - ((h - 0.833333f) * 6.0f);
176 g = 0.0;
181 // saturation influence
182 r = 1.0f - (s * (1.0f - r));
183 g = 1.0f - (s * (1.0f - g));
184 b = 1.0f - (s * (1.0f - b));
186 // luminosity influence
187 r *= l;
188 g *= l;
189 b *= l;
193 // Useful random number macros
194 // Don't forget to initialize with srand()
195 inline int myRandi(int x){
196 return((rand() * x) / RAND_MAX);
198 inline float myRandf(float x){
199 return(float(rand() * x) / float(RAND_MAX));
203 //----------------------------------------------------------------------------
206 // Context pointer to allow many instances.
207 static EuphoriaWidget* _ec = 0;
210 class wisp
212 public:
214 wisp();
215 ~wisp();
216 void update();
217 void draw();
218 void drawAsBackground();
221 int density;
222 float*** vertices;
223 float c[NUMCONSTS]; // constants
224 float cr[NUMCONSTS]; // constants' radial position
225 float cv[NUMCONSTS]; // constants' change velocities
226 float hsl[3];
227 float rgb[3];
228 float hueSpeed;
229 float saturationSpeed;
233 wisp::wisp()
235 int i, j;
236 float recHalfDens = 1.0f / (float(_ec->dDensity) * 0.5f);
238 density = _ec->dDensity;
239 vertices = new float**[density+1];
240 for(i=0; i<=density; i++)
242 vertices[i] = new float*[density+1];
243 for(j=0; j<=density; j++)
245 vertices[i][j] = new float[7];
246 vertices[i][j][3] = float(i) * recHalfDens - 1.0f; // x position on grid
247 vertices[i][j][4] = float(j) * recHalfDens - 1.0f; // y position on grid
248 // distance squared from the center
249 vertices[i][j][5] = vertices[i][j][3] * vertices[i][j][3]
250 + vertices[i][j][4] * vertices[i][j][4];
251 vertices[i][j][6] = 0.0f; // intensity
255 // initialize constants
256 for(i=0; i<NUMCONSTS; i++)
258 c[i] = myRandf(2.0f) - 1.0f;
259 cr[i] = myRandf(PIx2);
260 cv[i] = myRandf(_ec->dSpeed * 0.03f) + (_ec->dSpeed * 0.001f);
263 // pick color
264 hsl[0] = myRandf(1.0f);
265 hsl[1] = 0.1f + myRandf(0.9f);
266 hsl[2] = 1.0f;
267 hueSpeed = myRandf(0.1f) - 0.05f;
268 saturationSpeed = myRandf(0.04f) + 0.001f;
272 wisp::~wisp()
274 int i, j;
276 for(i=0; i<=density; i++)
278 for(j=0; j<=density; j++)
280 delete[] vertices[i][j];
282 delete[] vertices[i];
284 delete[] vertices;
288 void wisp::update()
290 int i, j;
291 rsVec up, right, crossvec;
292 // visibility constants
293 static float viscon1 = float(_ec->dVisibility) * 0.01f;
294 static float viscon2 = 1.0f / viscon1;
296 // update constants
297 for(i=0; i<NUMCONSTS; i++){
298 cr[i] += cv[i] * _ec->elapsedTime;
299 if(cr[i] > PIx2)
300 cr[i] -= PIx2;
301 c[i] = cos(cr[i]);
304 // update vertex positions
305 for(i=0; i<=density; i++){
306 for(j=0; j<=density; j++){
307 vertices[i][j][0] = vertices[i][j][3] * vertices[i][j][3] * vertices[i][j][4] * c[0]
308 + vertices[i][j][5] * c[1] + 0.5f * c[2];
309 vertices[i][j][1] = vertices[i][j][4] * vertices[i][j][4] * vertices[i][j][5] * c[3]
310 + vertices[i][j][3] * c[4] + 0.5f * c[5];
311 vertices[i][j][2] = vertices[i][j][5] * vertices[i][j][5] * vertices[i][j][3] * c[6]
312 + vertices[i][j][4] * c[7] + c[8];
316 // update vertex normals for most of mesh
317 for(i=1; i<density; i++){
318 for(j=1; j<density; j++){
319 up.set(vertices[i][j+1][0] - vertices[i][j-1][0],
320 vertices[i][j+1][1] - vertices[i][j-1][1],
321 vertices[i][j+1][2] - vertices[i][j-1][2]);
322 right.set(vertices[i+1][j][0] - vertices[i-1][j][0],
323 vertices[i+1][j][1] - vertices[i-1][j][1],
324 vertices[i+1][j][2] - vertices[i-1][j][2]);
325 up.normalize();
326 right.normalize();
327 crossvec.cross(right, up);
328 // Use depth component of normal to compute intensity
329 // This way only edges of wisp are bright
330 if(crossvec[2] < 0.0f)
331 crossvec[2] *= -1.0f;
332 vertices[i][j][6] = viscon2 * (viscon1 - crossvec[2]);
333 if(vertices[i][j][6] > 1.0f)
334 vertices[i][j][6] = 1.0f;
335 if(vertices[i][j][6] < 0.0f)
336 vertices[i][j][6] = 0.0f;
340 // update color
341 hsl[0] += hueSpeed * _ec->elapsedTime;
342 if(hsl[0] < 0.0f)
343 hsl[0] += 1.0f;
344 if(hsl[0] > 1.0f)
345 hsl[0] -= 1.0f;
346 hsl[1] += saturationSpeed * _ec->elapsedTime;
347 if(hsl[1] <= 0.1f){
348 hsl[1] = 0.1f;
349 saturationSpeed = -saturationSpeed;
351 if(hsl[1] >= 1.0f){
352 hsl[1] = 1.0f;
353 saturationSpeed = -saturationSpeed;
355 hsl2rgb(hsl[0], hsl[1], hsl[2], rgb[0], rgb[1], rgb[2]);
359 void wisp::draw()
361 int i, j;
363 glPushMatrix();
365 if(_ec->dWireframe)
367 for(i=1; i<density; i++){
368 glBegin(GL_LINE_STRIP);
369 for(j=0; j<=density; j++){
370 glColor3f(rgb[0] + vertices[i][j][6] - 1.0f, rgb[1] + vertices[i][j][6] - 1.0f, rgb[2] + vertices[i][j][6] - 1.0f);
371 glTexCoord2d(vertices[i][j][3] - vertices[i][j][0], vertices[i][j][4] - vertices[i][j][1]);
372 glVertex3fv(vertices[i][j]);
374 glEnd();
376 for(j=1; j<density; j++){
377 glBegin(GL_LINE_STRIP);
378 for(i=0; i<=density; i++){
379 glColor3f(rgb[0] + vertices[i][j][6] - 1.0f, rgb[1] + vertices[i][j][6] - 1.0f, rgb[2] + vertices[i][j][6] - 1.0f);
380 glTexCoord2d(vertices[i][j][3] - vertices[i][j][0], vertices[i][j][4] - vertices[i][j][1]);
381 glVertex3fv(vertices[i][j]);
383 glEnd();
386 else
388 for(i=0; i<density; i++){
389 glBegin(GL_TRIANGLE_STRIP);
390 for(j=0; j<=density; j++){
391 glColor3f(rgb[0] + vertices[i+1][j][6] - 1.0f, rgb[1] + vertices[i+1][j][6] - 1.0f, rgb[2] + vertices[i+1][j][6] - 1.0f);
392 glTexCoord2d(vertices[i+1][j][3] - vertices[i+1][j][0], vertices[i+1][j][4] - vertices[i+1][j][1]);
393 glVertex3fv(vertices[i+1][j]);
394 glColor3f(rgb[0] + vertices[i][j][6] - 1.0f, rgb[1] + vertices[i][j][6] - 1.0f, rgb[2] + vertices[i][j][6] - 1.0f);
395 glTexCoord2d(vertices[i][j][3] - vertices[i][j][0], vertices[i][j][4] - vertices[i][j][1]);
396 glVertex3fv(vertices[i][j]);
398 glEnd();
402 glPopMatrix();
406 void wisp::drawAsBackground()
408 int i, j;
410 glPushMatrix();
411 glTranslatef(c[0] * 0.2f, c[1] * 0.2f, 1.6f);
413 if(_ec->dWireframe)
415 for(i=1; i<density; i++){
416 glBegin(GL_LINE_STRIP);
417 for(j=0; j<=density; j++){
418 glColor3f(rgb[0] + vertices[i][j][6] - 1.0f, rgb[1] + vertices[i][j][6] - 1.0f, rgb[2] + vertices[i][j][6] - 1.0f);
419 glTexCoord2d(vertices[i][j][3] - vertices[i][j][0], vertices[i][j][4] - vertices[i][j][1]);
420 glVertex3f(vertices[i][j][3], vertices[i][j][4], vertices[i][j][6]);
422 glEnd();
424 for(j=1; j<density; j++){
425 glBegin(GL_LINE_STRIP);
426 for(i=0; i<=density; i++){
427 glColor3f(rgb[0] + vertices[i][j][6] - 1.0f, rgb[1] + vertices[i][j][6] - 1.0f, rgb[2] + vertices[i][j][6] - 1.0f);
428 glTexCoord2d(vertices[i][j][3] - vertices[i][j][0], vertices[i][j][4] - vertices[i][j][1]);
429 glVertex3f(vertices[i][j][3], vertices[i][j][4], vertices[i][j][6]);
431 glEnd();
434 else
436 for(i=0; i<density; i++){
437 glBegin(GL_TRIANGLE_STRIP);
438 for(j=0; j<=density; j++){
439 glColor3f(rgb[0] + vertices[i+1][j][6] - 1.0f, rgb[1] + vertices[i+1][j][6] - 1.0f, rgb[2] + vertices[i+1][j][6] - 1.0f);
440 glTexCoord2d(vertices[i+1][j][3] - vertices[i+1][j][0], vertices[i+1][j][4] - vertices[i+1][j][1]);
441 glVertex3f(vertices[i+1][j][3], vertices[i+1][j][4], vertices[i+1][j][6]);
442 glColor3f(rgb[0] + vertices[i][j][6] - 1.0f, rgb[1] + vertices[i][j][6] - 1.0f, rgb[2] + vertices[i][j][6] - 1.0f);
443 glTexCoord2d(vertices[i][j][3] - vertices[i][j][0], vertices[i][j][4] - vertices[i][j][1]);
444 glVertex3f(vertices[i][j][3], vertices[i][j][4], vertices[i][j][6]);
446 glEnd();
450 glPopMatrix();
454 //----------------------------------------------------------------------------
457 EuphoriaWidget::EuphoriaWidget( QWidget* parent )
458 : QGLWidget(parent), texName(0), _wisps(0), _backwisps(0),
459 feedbackmap(0), feedbacktex(0)
461 setDefaults( Regular );
463 _frameTime = 1000 / 60;
464 _timer = new QTimer( this );
465 _timer->setSingleShot( true );
466 connect( _timer, SIGNAL(timeout()), this, SLOT(nextFrame()) );
470 EuphoriaWidget::~EuphoriaWidget()
472 // Free memory
473 if ( texName )
474 glDeleteTextures( 1, &texName );
475 if ( feedbacktex )
476 glDeleteTextures( 1, &feedbacktex );
477 delete[] _wisps;
478 delete[] _backwisps;
482 void EuphoriaWidget::paintGL()
484 int i;
485 static double lastTime = timeGetTime();
487 // update time
488 elapsedTime = timeGetTime() - lastTime;
489 lastTime += elapsedTime;
491 _ec = this;
493 // Update wisps
494 for(i=0; i<dWisps; i++)
495 _wisps[i].update();
496 for(i=0; i<dBackground; i++)
497 _backwisps[i].update();
500 if(dFeedback)
502 float feedbackIntensity = float(dFeedback) / 101.0f;
504 // update feedback variables
505 for(i=0; i<4; i++)
507 fr[i] += elapsedTime * fv[i];
508 if(fr[i] > PIx2)
509 fr[i] -= PIx2;
511 f[0] = 30.0f * cos(fr[0]);
512 f[1] = 0.2f * cos(fr[1]);
513 f[2] = 0.2f * cos(fr[2]);
514 f[3] = 0.8f * cos(fr[3]);
515 for(i=0; i<3; i++)
517 lr[i] += elapsedTime * lv[i];
518 if(lr[i] > PIx2)
519 lr[i] -= PIx2;
520 l[i] = cos(lr[i]);
521 l[i] = l[i] * l[i];
524 // Create drawing area for feedback texture
525 glViewport(0, 0, feedbacktexsize, feedbacktexsize);
526 glMatrixMode(GL_PROJECTION);
527 glLoadIdentity();
528 gluPerspective(30.0, aspectRatio, 0.01f, 20.0f);
529 glMatrixMode(GL_MODELVIEW);
531 // Draw
532 glClear(GL_COLOR_BUFFER_BIT);
533 glColor3f(feedbackIntensity, feedbackIntensity, feedbackIntensity);
534 glBindTexture(GL_TEXTURE_2D, feedbacktex);
535 glPushMatrix();
536 glTranslatef(f[1] * l[1], f[2] * l[1], f[3] * l[2]);
537 glRotatef(f[0] * l[0], 0, 0, 1);
538 glBegin(GL_TRIANGLE_STRIP);
539 glTexCoord2f(-0.5f, -0.5f);
540 glVertex3f(-aspectRatio*2.0f, -2.0f, 1.25f);
541 glTexCoord2f(1.5f, -0.5f);
542 glVertex3f(aspectRatio*2.0f, -2.0f, 1.25f);
543 glTexCoord2f(-0.5f, 1.5f);
544 glVertex3f(-aspectRatio*2.0f, 2.0f, 1.25f);
545 glTexCoord2f(1.5f, 1.5f);
546 glVertex3f(aspectRatio*2.0f, 2.0f, 1.25f);
547 glEnd();
548 glPopMatrix();
549 glBindTexture(GL_TEXTURE_2D, texName);
550 for(i=0; i<dBackground; i++)
551 _backwisps[i].drawAsBackground();
552 for(i=0; i<dWisps; i++)
553 _wisps[i].draw();
555 // readback feedback texture
556 glReadBuffer(GL_BACK);
557 glPixelStorei(GL_UNPACK_ROW_LENGTH, feedbacktexsize);
558 glBindTexture(GL_TEXTURE_2D, feedbacktex);
559 glReadPixels(0, 0, feedbacktexsize, feedbacktexsize, GL_RGB, GL_UNSIGNED_BYTE, feedbackmap);
560 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, feedbacktexsize, feedbacktexsize, GL_RGB, GL_UNSIGNED_BYTE, feedbackmap);
562 // create regular drawing area
563 glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
564 glMatrixMode(GL_PROJECTION);
565 glLoadIdentity();
566 gluPerspective(20.0, aspectRatio, 0.01f, 20.0f);
567 glMatrixMode(GL_MODELVIEW);
569 // Draw again
570 glClear(GL_COLOR_BUFFER_BIT);
571 glColor3f(feedbackIntensity, feedbackIntensity, feedbackIntensity);
572 glPushMatrix();
573 glTranslatef(f[1] * l[1], f[2] * l[1], f[3] * l[2]);
574 glRotatef(f[0] * l[0], 0, 0, 1);
575 glBegin(GL_TRIANGLE_STRIP);
576 glTexCoord2f(-0.5f, -0.5f);
577 glVertex3f(-aspectRatio*2.0f, -2.0f, 1.25f);
578 glTexCoord2f(1.5f, -0.5f);
579 glVertex3f(aspectRatio*2.0f, -2.0f, 1.25f);
580 glTexCoord2f(-0.5f, 1.5f);
581 glVertex3f(-aspectRatio*2.0f, 2.0f, 1.25f);
582 glTexCoord2f(1.5f, 1.5f);
583 glVertex3f(aspectRatio*2.0f, 2.0f, 1.25f);
584 glEnd();
585 glPopMatrix();
587 glBindTexture(GL_TEXTURE_2D, texName);
589 else
590 glClear(GL_COLOR_BUFFER_BIT);
593 for(i=0; i<dBackground; i++)
594 _backwisps[i].drawAsBackground();
595 for(i=0; i<dWisps; i++)
596 _wisps[i].draw();
598 glFlush();
602 void EuphoriaWidget::resizeGL( int w, int h )
604 glViewport(0, 0, w, h );
606 viewport[0] = 0;
607 viewport[1] = 0;
608 viewport[2] = w;
609 viewport[3] = h;
611 aspectRatio = (float) w / (float) h;
613 // setup regular drawing area just in case feedback isn't used
614 glMatrixMode(GL_PROJECTION);
615 glLoadIdentity();
616 gluPerspective(20.0, aspectRatio, 0.01, 20);
617 glMatrixMode(GL_MODELVIEW);
618 glLoadIdentity();
619 glTranslatef(0.0, 0.0, -5.0);
623 // Window initialization
624 void EuphoriaWidget::initializeGL()
626 // Need to call this to setup viewport[] parameters used in
627 // the next updateParameters() call
628 resizeGL( width(), height() );
630 updateParameters();
632 _timer->start( _frameTime );
636 #ifdef UNIT_TEST
637 void EuphoriaWidget::keyPressEvent( QKeyEvent* e )
639 if( e->key() == Qt::Key_0 ) { setDefaults( 0 ); updateParameters(); }
640 if( e->key() == Qt::Key_1 ) { setDefaults( 1 ); updateParameters(); }
641 if( e->key() == Qt::Key_2 ) { setDefaults( 2 ); updateParameters(); }
642 if( e->key() == Qt::Key_3 ) { setDefaults( 3 ); updateParameters(); }
643 if( e->key() == Qt::Key_4 ) { setDefaults( 4 ); updateParameters(); }
644 if( e->key() == Qt::Key_5 ) { setDefaults( 5 ); updateParameters(); }
645 if( e->key() == Qt::Key_6 ) { setDefaults( 6 ); updateParameters(); }
646 if( e->key() == Qt::Key_7 ) { setDefaults( 7 ); updateParameters(); }
647 if( e->key() == Qt::Key_8 ) { setDefaults( 8 ); updateParameters(); }
649 #endif
652 void EuphoriaWidget::nextFrame()
654 updateGL();
655 _timer->start( _frameTime );
659 void EuphoriaWidget::updateParameters()
661 srand((unsigned)time(NULL));
662 rand(); rand(); rand(); rand(); rand();
664 elapsedTime = 0.0f;
666 fr[0] = 0.0f;
667 fr[1] = 0.0f;
668 fr[2] = 0.0f;
669 fr[3] = 0.0f;
671 lr[0] = 0.0f;
672 lr[1] = 0.0f;
673 lr[2] = 0.0f;
675 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
676 glClear(GL_COLOR_BUFFER_BIT);
677 glEnable(GL_BLEND);
678 glBlendFunc(GL_ONE, GL_ONE);
679 glLineWidth(2.0f);
681 // Commented out because smooth lines and textures don't mix on my TNT.
682 // It's like it rendering in software mode
683 glEnable(GL_LINE_SMOOTH);
684 //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
686 if(dTexture)
688 int whichtex = dTexture;
689 if(whichtex == 4) // random texture
690 whichtex = myRandi(3) + 1;
691 glEnable(GL_TEXTURE_2D);
692 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
693 // Initialize texture
694 glGenTextures(1, &texName);
695 glBindTexture(GL_TEXTURE_2D, texName);
696 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
697 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
698 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
699 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
700 switch(whichtex){
701 case 1:
702 gluBuild2DMipmaps(GL_TEXTURE_2D, 1, TEXSIZE, TEXSIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, plasmamap);
703 break;
704 case 2:
705 gluBuild2DMipmaps(GL_TEXTURE_2D, 1, TEXSIZE, TEXSIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, stringymap);
706 break;
707 case 3:
708 gluBuild2DMipmaps(GL_TEXTURE_2D, 1, TEXSIZE, TEXSIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, linesmap);
710 } else if ( texName ) {
711 glDeleteTextures( 1, &texName );
712 texName = 0;
715 if(dFeedback)
717 feedbacktexsize = int(pow(2.0, dFeedbacksize));
718 while(feedbacktexsize > viewport[2] || feedbacktexsize > viewport[3]){
719 dFeedbacksize -= 1;
720 feedbacktexsize = int(pow(2.0, dFeedbacksize));
723 // feedback texture setup
724 glEnable(GL_TEXTURE_2D);
725 delete [] feedbackmap;
726 feedbackmap = new unsigned char[feedbacktexsize*feedbacktexsize*3];
727 glGenTextures(1, &feedbacktex);
728 glBindTexture(GL_TEXTURE_2D, feedbacktex);
729 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
730 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
731 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
732 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
733 glTexImage2D(GL_TEXTURE_2D, 0, 3, feedbacktexsize, feedbacktexsize, 0, GL_RGB, GL_UNSIGNED_BYTE, feedbackmap);
735 // feedback velocity variable setup
736 fv[0] = float(dFeedbackspeed) * (myRandf(0.025f) + 0.025f);
737 fv[1] = float(dFeedbackspeed) * (myRandf(0.05f) + 0.05f);
738 fv[2] = float(dFeedbackspeed) * (myRandf(0.05f) + 0.05f);
739 fv[3] = float(dFeedbackspeed) * (myRandf(0.1f) + 0.1f);
740 lv[0] = float(dFeedbackspeed) * (myRandf(0.0025f) + 0.0025f);
741 lv[1] = float(dFeedbackspeed) * (myRandf(0.0025f) + 0.0025f);
742 lv[2] = float(dFeedbackspeed) * (myRandf(0.0025f) + 0.0025f);
743 } else if ( feedbacktex ) {
744 glDeleteTextures( 1, &feedbacktex );
745 feedbacktex = 0;
748 // Initialize wisps
749 _ec = this;
750 delete[] _wisps;
751 delete[] _backwisps;
752 _wisps = new wisp[dWisps];
753 _backwisps = new wisp[dBackground];
758 May be called at any time - makes no OpenGL calls.
760 void EuphoriaWidget::setDefaults(int which)
762 switch(which)
764 case Grid:
765 dWisps = 4;
766 dBackground = 1;
767 dDensity = 25;
768 dVisibility = 70;
769 dSpeed = 15;
770 dFeedback = 0;
771 dFeedbackspeed = 1;
772 dFeedbacksize = 8;
773 dWireframe = 1;
774 dTexture = 0;
775 break;
777 case Cubism:
778 dWisps = 15;
779 dBackground = 0;
780 dDensity = 4;
781 dVisibility = 15;
782 dSpeed = 10;
783 dFeedback = 0;
784 dFeedbackspeed = 1;
785 dFeedbacksize = 8;
786 dWireframe = 0;
787 dTexture = 0;
788 break;
790 case BadMath:
791 dWisps = 2;
792 dBackground = 2;
793 dDensity = 20;
794 dVisibility = 40;
795 dSpeed = 30;
796 dFeedback = 40;
797 dFeedbackspeed = 5;
798 dFeedbacksize = 8;
799 dWireframe = 1;
800 dTexture = 2;
801 break;
803 case MTheory:
804 dWisps = 3;
805 dBackground = 0;
806 dDensity = 25;
807 dVisibility = 15;
808 dSpeed = 20;
809 dFeedback = 40;
810 dFeedbackspeed = 20;
811 dFeedbacksize = 8;
812 dWireframe = 0;
813 dTexture = 0;
814 break;
816 case UHFTEM:
817 dWisps = 0;
818 dBackground = 3;
819 dDensity = 35;
820 dVisibility = 5;
821 dSpeed = 50;
822 dFeedback = 0;
823 dFeedbackspeed = 1;
824 dFeedbacksize = 8;
825 dWireframe = 0;
826 dTexture = 0;
827 break;
829 case Nowhere:
830 dWisps = 0;
831 dBackground = 3;
832 dDensity = 30;
833 dVisibility = 40;
834 dSpeed = 20;
835 dFeedback = 80;
836 dFeedbackspeed = 10;
837 dFeedbacksize = 8;
838 dWireframe = 1;
839 dTexture = 3;
840 break;
842 case Echo:
843 dWisps = 3;
844 dBackground = 0;
845 dDensity = 25;
846 dVisibility = 30;
847 dSpeed = 20;
848 dFeedback = 85;
849 dFeedbackspeed = 30;
850 dFeedbacksize = 8;
851 dWireframe = 0;
852 dTexture = 1;
853 break;
855 case Kaleidoscope:
856 dWisps = 3;
857 dBackground = 0;
858 dDensity = 25;
859 dVisibility = 40;
860 dSpeed = 15;
861 dFeedback = 90;
862 dFeedbackspeed = 3;
863 dFeedbacksize = 8;
864 dWireframe = 0;
865 dTexture = 0;
866 break;
868 case Regular:
869 default:
870 dWisps = 5;
871 dBackground = 0;
872 dDensity = 25;
873 dVisibility = 35;
874 dSpeed = 15;
875 dFeedback = 0;
876 dFeedbackspeed = 1;
877 dFeedbacksize = 8;
878 dWireframe = 0;
879 dTexture = 2;
880 break;
885 //----------------------------------------------------------------------------
888 #ifndef UNIT_TEST
889 #include <klocale.h>
890 #include <kglobal.h>
891 #include <kconfig.h>
894 // libkscreensaver interface
895 class KEuphoriaSaverInterface : public KScreenSaverInterface
899 public:
900 virtual KAboutData* aboutData() {
901 return new KAboutData( "keuphoria.kss", 0, ki18n( "Euphoria" ), "1.0", ki18n( "Euphoria" ) );
905 virtual KScreenSaver* create( WId id )
907 return new KEuphoriaScreenSaver( id );
910 virtual QDialog* setup()
912 return new KEuphoriaSetup;
916 int main( int argc, char *argv[] )
918 KEuphoriaSaverInterface kss;
919 return kScreenSaverMain( argc, argv, kss );
923 //----------------------------------------------------------------------------
926 KEuphoriaScreenSaver::KEuphoriaScreenSaver( WId id ) : KScreenSaver( id )
928 _effect = new EuphoriaWidget;
930 readSettings();
932 embed( _effect );
933 _effect->show();
937 KEuphoriaScreenSaver::~KEuphoriaScreenSaver()
942 static int filterRandom( int n )
944 if( (n < 0) || (n >= EuphoriaWidget::DefaultModes) )
946 srand((unsigned)time(NULL));
947 n = rand() % EuphoriaWidget::DefaultModes;
949 return n;
953 void KEuphoriaScreenSaver::readSettings()
955 KConfigGroup config(KGlobal::config(), "Settings");
957 _mode = config.readEntry( "Mode", (int)EuphoriaWidget::Regular );
958 _effect->setDefaults( filterRandom(_mode) );
963 Any invalid mode will select one at random.
965 void KEuphoriaScreenSaver::setMode( int id )
967 _mode = id;
968 _effect->setDefaults( filterRandom(id) );
969 _effect->updateParameters();
973 //----------------------------------------------------------------------------
976 #include <qlayout.h>
977 #include <qlabel.h>
978 #include <qcombobox.h>
979 #include <kmessagebox.h>
982 static const char* defaultText[] =
984 I18N_NOOP( "Regular" ),
985 I18N_NOOP( "Grid" ),
986 I18N_NOOP( "Cubism" ),
987 I18N_NOOP( "Bad Math" ),
988 I18N_NOOP( "M-Theory" ),
989 I18N_NOOP( "UHFTEM" ), //"ultra high frequency tunneling electron microscope",
990 I18N_NOOP( "Nowhere" ),
991 I18N_NOOP( "Echo" ),
992 I18N_NOOP( "Kaleidoscope" ),
993 I18N_NOOP( "(Random)" ),
998 KEuphoriaSetup::KEuphoriaSetup( QWidget* parent )
999 : KDialog( parent)
1001 setCaption(i18n("Setup Euphoria Screen Saver"));
1002 setButtons(Ok|Cancel|Help);
1003 setDefaultButton(Ok);
1004 setModal(true);
1005 showButtonSeparator(true);
1006 setButtonText( Help, i18n( "A&bout" ) );
1008 QWidget *main = new QWidget(this);
1009 setMainWidget(main);
1011 QHBoxLayout* top = new QHBoxLayout( main );
1012 top->setSpacing( spacingHint() );
1013 QVBoxLayout* leftCol = new QVBoxLayout;
1014 top->addLayout( leftCol );
1016 QLabel* label = new QLabel( i18n("Mode:"), main );
1017 leftCol->addWidget( label );
1019 modeW = new QComboBox( main );
1020 int i = 0;
1021 while (defaultText[i])
1022 modeW->addItem( i18n(defaultText[i++]) );
1023 leftCol->addWidget( modeW );
1025 leftCol->addStretch();
1027 // Preview
1028 QWidget* preview;
1029 preview = new QWidget( main );
1030 preview->setFixedSize( 220, 170 );
1032 QPalette palette;
1033 palette.setColor( preview->backgroundRole(), Qt::black );
1034 preview->setPalette( palette );
1036 preview->show(); // otherwise saver does not get correct size
1037 _saver = new KEuphoriaScreenSaver( preview->winId() );
1038 top->addWidget(preview);
1040 // Now that we have _saver...
1041 modeW->setCurrentIndex( _saver->mode() ); // set before we connect
1042 connect( modeW, SIGNAL(activated(int)), _saver, SLOT(setMode(int)) );
1043 connect(this,SIGNAL(okClicked()),SLOT(slotOk()));
1044 connect(this,SIGNAL(helpClicked()),SLOT(slotHelp()));
1046 setMinimumSize( sizeHint() );
1050 KEuphoriaSetup::~KEuphoriaSetup()
1052 delete _saver;
1056 void KEuphoriaSetup::slotHelp()
1058 KMessageBox::about(this,
1059 i18n("<h3>Euphoria 1.0</h3>\n<p>Copyright (c) 2002 Terence M. Welsh<br>\n<a href=\"http://www.reallyslick.com/\">http://www.reallyslick.com/</a></p>\n\n<p>Ported to KDE by Karl Robillard</p>"),
1060 QString(), KMessageBox::AllowLink);
1065 Ok pressed - save settings and exit
1067 void KEuphoriaSetup::slotOk()
1069 KConfigGroup config( KGlobal::config(), "Settings");
1071 config.writeEntry("Mode", QString::number( modeW->currentIndex() ) );
1073 config.sync();
1074 accept();
1076 #endif
1077 //----------------------------------------------------------------------------
1080 #ifdef UNIT_TEST
1081 // moc Euphoria.h -o Euphoria.moc
1082 // g++ -g -DUNIT_TEST Euphoria.cpp -I/usr/lib/qt3/include -lqt -L/usr/lib/qt3/lib -lGLU -lGL
1084 #include <qapplication.h>
1086 int main( int argc, char** argv )
1088 QApplication app( argc, argv );
1090 EuphoriaWidget w;
1091 w.setDefaults( EuphoriaWidget::UHFTEM );
1092 app.setMainWidget( &w );
1093 w.show();
1095 return app.exec();
1097 #endif
1100 //EOF