Compile GL screensaver
[kdeartwork.git] / kscreensaver / kdesavers / gravity.cpp
blobe5a64ee7c73fd4c3ac6a92b67ab15bd961969750
1 //-----------------------------------------------------------------------------
2 //
3 // kgravity - Partical Gravity Screen Saver for KDE 2
4 //
5 // Copyright (c) Ian Reinhart Geiser 2001
6 //
7 // KConfig code and KScreenSaver "Setup..." improvements by
8 // Nick Betcher <nbetcher@usinternet.com> 2001
9 //
10 #include <stdlib.h>
11 #include <qlabel.h>
12 #include <qlayout.h>
13 #include <kapplication.h>
14 #include <klocale.h>
15 #include <kconfig.h>
16 #include <kcolordialog.h>
17 #include <kbuttonbox.h>
18 #include <kcolorbutton.h>
19 #include "gravity.h"
20 #include "gravity.moc"
21 #ifdef Q_WS_MACX
22 #include <OpenGL/glu.h>
23 #include <OpenGL/gl.h>
24 #else
25 #include <GL/glu.h>
26 #include <GL/gl.h>
27 #endif
28 #include <qimage.h>
29 #include <kdebug.h>
30 #include <qpainter.h>
31 #include <qradiobutton.h>
32 #include <qspinbox.h>
33 #include <kstandarddirs.h>
34 #include <math.h>
35 #include <kmessagebox.h>
36 #include <krandom.h>
37 // libkscreensaver interface
38 class KGravitySaverInterface : public KScreenSaverInterface
42 public:
43 virtual KAboutData* aboutData() {
44 return new KAboutData( "kgravity.kss", I18N_NOOP( "Particle Gravity Screen Saver" ), "2.2.0", I18N_NOOP( "Particle Gravity Screen Saver" ) );
48 virtual KScreenSaver* create( WId id )
50 return new KGravitySaver( id );
53 virtual QDialog* setup()
55 return new KGravitySetup();
59 int main( int argc, char *argv[] )
61 KGravitySaverInterface kss;
62 return kScreenSaverMain( argc, argv, kss );
65 //-----------------------------------------------------------------------------
66 // dialog to setup screen saver parameters
68 KGravitySetup::KGravitySetup( QWidget *parent, const char *name )
69 : SetupUi( parent, name, TRUE )
71 readSettings();
73 preview->setFixedSize( 220, 170 );
74 preview->setBackgroundColor( Qt::black );
75 #ifdef Q_WS_X11
76 preview->show(); // otherwise saver does not get correct size
77 #endif
78 saver = new KGravitySaver( preview->winId() );
80 connect( PushButton1, SIGNAL( clicked() ), SLOT( slotOkPressed() ) );
81 connect( PushButton2, SIGNAL( clicked() ), SLOT( reject() ) );
82 connect( PushButton3, SIGNAL( clicked() ), SLOT( aboutPressed() ) );
83 connect( SpinBox1, SIGNAL( valueChanged(int)), saver, SLOT( updateSize(int)));
84 connect( RadioButton1, SIGNAL( toggled(bool)), saver, SLOT( doStars(bool)));
88 KGravitySetup::~KGravitySetup()
90 delete saver;
93 // read settings from config file
94 void KGravitySetup::readSettings()
96 KConfig config("kssgravityrc", false, false);
98 config.setGroup( "Settings" );
99 QString boolval = config.readEntry( "Stars", "false" );
100 if (boolval == "true") {
101 RadioButton1->setDown(true);
102 RadioButton1_2->setDown(false);
103 } else {
104 if (boolval == "false")
106 RadioButton1->setDown(false);
107 RadioButton1_2->setDown(true);
111 QString starammount = config.readEntry("StarSize", "75");
112 SpinBox1->setValue(starammount.toInt());
116 // Ok pressed - save settings and exit
117 void KGravitySetup::slotOkPressed()
119 KConfig config("kssgravityrc", false, false);
120 config.setGroup( "Settings" );
122 if (RadioButton1->isOn() == true)
124 config.writeEntry( "Stars", "true" );
125 } else {
126 if (RadioButton1_2->isOn() == true)
128 config.writeEntry( "Stars", "false" );
131 config.writeEntry( "StarSize", QString::number(SpinBox1->value()) );
133 config.sync();
135 accept();
138 void KGravitySetup::aboutPressed()
140 KMessageBox::about(this,
141 i18n("<h3>Gravity</h3>\n<p>Particle Gravity Screen Saver for KDE</p>\nCopyright (c) Ian Reinhart Geiser 2001<br>\n\n<p>KConfig code and KScreenSaver \"Setup...\" improvements by Nick Betcher <nbetcher@usinternet.com> 2001</p>"));
143 //-----------------------------------------------------------------------------
146 KGravitySaver::KGravitySaver( WId id ) : KScreenSaver( id )
149 kDebug() << "Blank" << endl;
151 timer = new QTimer( this );
152 timer->start( 25, TRUE );
153 setBackgroundColor( Qt::black );
154 erase();
155 gravity = new Gravity();
156 embed(gravity);
157 #ifdef Q_WS_X11
158 gravity->show();
159 #endif
160 connect( timer, SIGNAL(timeout()), this, SLOT(blank()) );
163 KGravitySaver::~KGravitySaver()
168 // read configuration settings from config file
169 void KGravitySaver::readSettings()
171 // Please remove me
175 void KGravitySaver::blank()
177 // Play gravity
179 gravity->updateGL();
180 timer->start( 25, TRUE );
183 Gravity::Gravity( QWidget * parent, const char * name) : QGLWidget (parent,name)
185 rainbow=true;
186 slowdown=2.0f;
187 zoom=-50.0f;
188 index=0;
189 size = 3.95f;
190 // obj = gluNewQuadric();
192 // This has to be here because you can't update the gravity until 'gravity' is created!
193 KConfig config("kssgravityrc", false, false);
194 config.setGroup( "Settings" );
195 QString boolval = config.readEntry( "Stars", "false" );
196 if (boolval == "true") {
197 setStars(true);
198 } else {
199 if (boolval == "false")
201 setStars(false);
205 QString starammount = config.readEntry("StarSize", "75");
206 float passvalue = (starammount.toInt() / 100.0);
207 setSize(passvalue);
211 Gravity::~Gravity()
213 glDeleteTextures( 1, &texture[0] );
214 gluDeleteQuadric(obj);
217 /** load the particle file */
218 bool Gravity::loadParticle()
220 /* Status indicator */
221 bool Status = TRUE;
222 QImage buf;
224 kDebug() << "Loading: " << KStandardDirs::locate("data", "kscreensaver/particle.png") << endl;
225 if (buf.load( KStandardDirs::locate("data", "kscreensaver/particle.png") ) )
228 tex = convertToGLFormat(buf); // flipped 32bit RGBA
229 kDebug() << "Texture loaded: " << tex.numBytes () << endl;
231 else
233 QImage dummy( 32, 32, 32 );
234 dummy.fill( Qt::white );
235 buf = dummy;
236 tex = convertToGLFormat( buf );
239 /* Set the status to true */
240 //Status = TRUE;
241 glGenTextures(1, &texture[0]); /* create three textures */
242 glBindTexture(GL_TEXTURE_2D, texture[0]);
243 /* use linear filtering */
244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
245 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
246 /* actually generate the texture */
247 glTexImage2D(GL_TEXTURE_2D, 0, 4, tex.width(), tex.height(), 0,
248 GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
252 return Status;
254 /** setup the GL enviroment */
255 void Gravity::initializeGL ()
258 kDebug() << "InitGL" << endl;
260 if (loadParticle()) // Jump To Texture Loading Routine
262 /* Enable smooth shading */
263 glShadeModel( GL_SMOOTH );
265 /* Set the background black */
266 glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
268 /* Depth buffer setup */
269 glClearDepth( 1.0f );
271 /* Enables Depth Testing */
272 glDisable( GL_DEPTH_TEST );
274 /* Enable Blending */
275 glEnable( GL_BLEND );
276 /* Type Of Blending To Perform */
277 glBlendFunc( GL_SRC_ALPHA, GL_ONE );
280 /* Really Nice Perspective Calculations */
281 glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
282 /* Really Nice Point Smoothing */
283 glHint( GL_POINT_SMOOTH_HINT, GL_NICEST );
285 /* Enable Texture Mapping */
286 glEnable( GL_TEXTURE_2D );
287 /* Select Our Texture */
288 glBindTexture( GL_TEXTURE_2D, texture[0] );
290 for (loop=0;loop<MAX_PARTICLES;loop++) // Initials All The Textures
292 buildParticle(loop);
295 else
296 exit(0);
298 /** resize the gl view */
299 void Gravity::resizeGL ( int width, int height )
301 kDebug() << "ResizeGL " << width << "," <<height<< endl;
302 if (height==0) // Prevent A Divide By Zero By
304 height=1; // Making Height Equal One
307 glViewport(0,0,width,height); // Reset The Current Viewport
309 glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
310 glLoadIdentity(); // Reset The Projection Matrix
312 // Calculate The Aspect Ratio Of The Window
313 gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
315 glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
316 glLoadIdentity();
318 /** paint the GL view */
319 void Gravity::paintGL ()
321 //kDebug() << "PaintGL" << endl;
322 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
323 glLoadIdentity();
324 // Reset The ModelView Matrix
325 transIndex++;
326 //glRotatef(transIndex, 1,0,0);
327 //glRotatef(transIndex, 0,1,0);
328 //glRotatef(transIndex, 0,0,1);
329 float xmax = 5.0;
330 float ymax = 5.0;
331 glTranslatef( GLfloat(xmax*sin(3.14*transIndex/360)-xmax),
332 GLfloat(ymax*cos(3.14*transIndex/360)-ymax),
333 0.0 );
334 //glRotatef(transIndex, 0,GLfloat(zmax*cos(3.14*transIndex/360000)), GLfloat(zmax*cos(3.14*transIndex/360000)));
336 for (loop=0;loop<MAX_PARTICLES;loop++) // Loop Through All The Particles
338 if (particle[loop].active) // If The Particle Is Active
340 float x=particle[loop].x; // Grab Our Particle X Position
341 float y=particle[loop].y; // Grab Our Particle Y Position
342 float z=particle[loop].z+zoom; // Particle Z Pos + Zoom
343 /* Select Our Texture */
345 /* Draw The Particle Using Our RGB Values,
346 * Fade The Particle Based On It's Life
348 particle[loop].life=(particle[loop].index/particle[loop].indexo)*2.0f;
349 glColor4f( particle[loop].r,
350 particle[loop].g,
351 particle[loop].b,
352 particle[loop].life );
354 /* Build Quad From A Triangle Strip */
355 if( !stars )
356 glBegin( GL_TRIANGLE_STRIP );
357 else
358 glBegin( GL_TRIANGLE_FAN );
359 /* Top Right */
360 glTexCoord2d( 1, 1 );
361 glVertex3f( x + particle[loop].size, y + particle[loop].size, z );
362 /* Top Left */
363 glTexCoord2d( 0, 1 );
364 glVertex3f( x - particle[loop].size, y + particle[loop].size, z );
365 /* Bottom Right */
366 glTexCoord2d( 1, 0 );
367 glVertex3f( x + particle[loop].size, y - particle[loop].size, z );
368 /* Bottom Left */
369 glTexCoord2d( 0, 0 );
370 glVertex3f( x - particle[loop].size, y - particle[loop].size, z );
371 glEnd( );
372 particle[loop].x=(particle[loop].xo*sin(particle[loop].index))*pow((double) particle[loop].index/particle[loop].indexo,(double) 8.0);
373 particle[loop].y=(particle[loop].yo*sin(particle[loop].index))*pow((double) particle[loop].index/particle[loop].indexo,(double) 8.0);
374 particle[loop].z=(particle[loop].zo*sin(particle[loop].index))*pow((double) particle[loop].index/particle[loop].indexo,(double) 8.0);
375 particle[loop].index-=0.05;
376 if (particle[loop].index<0.0f ) // If Particle Is Burned Out
378 buildParticle(loop);
380 // Lets stir some things up
384 glFlush();
386 void Gravity::setSize( float newSize )
388 size = newSize;
390 void Gravity::setStars( bool doStars )
392 stars = doStars;
395 void KGravitySaver::updateSize(int newSize)
397 gravity->setSize(newSize/100);
399 void KGravitySaver::doStars(bool starState)
401 gravity->setStars(starState);
404 void Gravity::buildParticle(int loop)
406 GLfloat colors[12][3]=
407 {{1.0f,0.5f,0.5f},{1.0f,0.75f,0.5f},{1.0f,1.0f,0.5f},{0.75f,1.0f,0.5f},
408 {0.5f,1.0f,0.5f},{0.5f,1.0f,0.75f},{0.5f,1.0f,1.0f},{0.5f,0.75f,1.0f},
409 {0.5f,0.5f,1.0f},{0.75f,0.5f,1.0f},{1.0f,0.5f,1.0f},{1.0f,0.5f,0.75f}};
410 col = ( ++col ) % 12;
411 particle[loop].active=true;
412 particle[loop].index=KRandom::random()%100;
413 particle[loop].indexo=particle[loop].index;
414 particle[loop].fade=float(KRandom::random()%100)/1000.0f+0.003f; // Random Fade Value
415 particle[loop].r=colors[col][0]; // Select Red From Color Table
416 particle[loop].g=colors[col][1]; // Select Green From Color Table
417 particle[loop].b=colors[col][2]; // Select Blue From Color Table
418 particle[loop].size=size;
419 particle[loop].x = float(KRandom::random()%100-50)*4.0;
420 particle[loop].y = float(KRandom::random()%20-10)*4.0;
421 particle[loop].z = float(KRandom::random()%100-50)*4.0;
422 particle[loop].xo = particle[loop].x;
423 if ((1+(KRandom::random() % 10) > 5))
424 particle[loop].yo = particle[loop].y;
425 else
426 particle[loop].yo = 0.0;
427 particle[loop].zo = particle[loop].z;