Back to index

kdeartwork  4.3.2
gravity.cpp
Go to the documentation of this file.
00001 //-----------------------------------------------------------------------------
00002 //
00003 // kgravity - Partical Gravity Screen Saver for KDE 2
00004 //
00005 // Copyright (c)  Ian Reinhart Geiser 2001
00006 //
00007 // KConfig code and KScreenSaver "Setup..." improvements by
00008 // Nick Betcher <nbetcher@usinternet.com> 2001
00009 //
00010 #include <stdlib.h>
00011 #include <qlabel.h>
00012 #include <qlayout.h>
00013 #include <kapplication.h>
00014 #include <klocale.h>
00015 #include <kconfig.h>
00016 #include <kcolordialog.h>
00017 #include <kcolorbutton.h>
00018 #include "gravity.h"
00019 #include "gravity.moc"
00020 #ifdef Q_WS_MACX
00021 #include <OpenGL/glu.h>
00022 #include <OpenGL/gl.h>
00023 #else
00024 #include <GL/glu.h>
00025 #include <GL/gl.h>
00026 #endif
00027 #include <qimage.h>
00028 #include <kdebug.h>
00029 #include <qpainter.h>
00030 #include <qradiobutton.h>
00031 #include <qspinbox.h>
00032 #include <kstandarddirs.h>
00033 #include <math.h>
00034 #include <kmessagebox.h>
00035 #include <krandom.h>
00036 // libkscreensaver interface
00037 class KGravitySaverInterface : public KScreenSaverInterface
00038 {
00039 
00040 
00041 public:
00042     virtual KAboutData* aboutData() {
00043         return new KAboutData( "kgravity.kss", "klock", ki18n( "Particle Gravity Screen Saver" ), "2.2.0", ki18n( "Particle Gravity Screen Saver" ) );
00044     }
00045 
00046 
00047        virtual KScreenSaver* create( WId id )
00048        {
00049               return new KGravitySaver( id );
00050        }
00051 
00052        virtual QDialog* setup()
00053        {
00054               return new KGravitySetup();
00055        }
00056 };
00057 
00058 int main( int argc, char *argv[] )
00059 {
00060     KGravitySaverInterface kss;
00061     return kScreenSaverMain( argc, argv, kss );
00062 }
00063 
00064 //-----------------------------------------------------------------------------
00065 // dialog to setup screen saver parameters
00066 //
00067 KGravitySetup::KGravitySetup( QWidget *parent )
00068         : QDialog(parent)
00069 {
00070        setupUi(this);
00071        readSettings();
00072 
00073        preview->setFixedSize( 220, 170 );
00074         {
00075             QPalette palette;
00076             palette.setColor( preview->backgroundRole(), Qt::black );
00077             preview->setPalette( palette );
00078            preview->setAutoFillBackground(true);
00079         }
00080 #ifdef Q_WS_X11
00081        preview->show();    // otherwise saver does not get correct size
00082 #endif
00083        saver = new KGravitySaver( preview->winId() );
00084 ;
00085        connect( PushButton1, SIGNAL( clicked() ), SLOT( slotOkPressed() ) );
00086        connect( PushButton2, SIGNAL( clicked() ), SLOT( reject() ) );
00087        connect( PushButton3, SIGNAL( clicked() ), SLOT( aboutPressed() ) );
00088        connect(  SpinBox1, SIGNAL( valueChanged(int)), saver, SLOT( updateSize(int)));
00089        connect( RadioButton1, SIGNAL( toggled(bool)), saver, SLOT( doStars(bool)));
00090 
00091 }
00092 
00093 KGravitySetup::~KGravitySetup()
00094 {
00095     delete saver;
00096 }
00097 
00098 // read settings from config file
00099 void KGravitySetup::readSettings()
00100 {
00101        KConfig config("kssgravityrc", KConfig::NoGlobals);
00102         KConfigGroup grp = config.group( "Settings" );
00103 
00104        bool boolval = grp.readEntry( "Stars", false );
00105        if (boolval) {
00106               RadioButton1->setChecked(true);
00107        } else {
00108               if (!boolval)
00109               {
00110                      RadioButton1_2->setChecked(true);
00111               }
00112        }
00113 
00114        int starammount = grp.readEntry("StarSize", 75);
00115        SpinBox1->setValue(starammount);
00116 
00117 }
00118 
00119 // Ok pressed - save settings and exit
00120 void KGravitySetup::slotOkPressed()
00121 {
00122        KConfig _config("kssgravityrc", KConfig::NoGlobals);
00123        KConfigGroup config(&_config, "Settings" );
00124 
00125        if (RadioButton1->isChecked() == true)
00126        {
00127               config.writeEntry( "Stars", true );
00128        } else {
00129               if (RadioButton1_2->isChecked() == true)
00130               {
00131                      config.writeEntry( "Stars", false );
00132               }
00133        }
00134        config.writeEntry( "StarSize", SpinBox1->value() );
00135 
00136        config.sync();
00137 
00138        accept();
00139 }
00140 
00141 void KGravitySetup::aboutPressed()
00142 {
00143     KMessageBox::about(this,
00144         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>"));
00145 }
00146 //-----------------------------------------------------------------------------
00147 
00148 
00149 KGravitySaver::KGravitySaver( WId id ) : KScreenSaver( id )
00150 {
00151 
00152     kDebug() << "Blank";
00153 
00154     timer = new QTimer( this );
00155     timer->setSingleShot(true);
00156     timer->start( 25);
00157     {
00158         QPalette palette;
00159         palette.setColor( backgroundRole(), Qt::black );
00160         setPalette( palette );
00161     }
00162     update();
00163     gravity = new Gravity();
00164     embed(gravity);
00165 #ifdef Q_WS_X11
00166     gravity->show();
00167 #endif
00168     connect( timer, SIGNAL(timeout()), this, SLOT(blank()) );
00169 }
00170 
00171 KGravitySaver::~KGravitySaver()
00172 {
00173 
00174 }
00175 
00176 // read configuration settings from config file
00177 void KGravitySaver::readSettings()
00178 {
00179 // Please remove me
00180 
00181 }
00182 
00183 void KGravitySaver::blank()
00184 {
00185        // Play gravity
00186 
00187        gravity->updateGL();
00188     timer->setSingleShot(true);
00189        timer->start( 25);
00190 
00191 }
00192 Gravity::Gravity( QWidget * parent ) : QGLWidget (parent)
00193 {
00194        rainbow=true;
00195        slowdown=2.0f;
00196        zoom=-50.0f;
00197        index=0;
00198        size = 3.95f;
00199 //     obj = gluNewQuadric();
00200 
00201 // This has to be here because you can't update the gravity until 'gravity' is created!
00202        KConfig _config("kssgravityrc", KConfig::NoGlobals);
00203        KConfigGroup config(&_config, "Settings" );
00204        bool boolval = config.readEntry( "Stars", false );
00205         setStars(boolval);
00206        int starammount = config.readEntry("StarSize", 75);
00207        float passvalue = (starammount / 100.0);
00208        setSize(passvalue);
00209 
00210 }
00211 
00212 Gravity::~Gravity()
00213 {
00214        glDeleteTextures( 1, &texture[0] );
00215        gluDeleteQuadric(obj);
00216 }
00217 
00219 bool Gravity::loadParticle()
00220 {
00221     /* Status indicator */
00222     bool Status = true;
00223     QImage buf;
00224 
00225     kDebug() << "Loading: " << KStandardDirs::locate("data", "kscreensaver/particle.png");
00226  if (buf.load( KStandardDirs::locate("data", "kscreensaver/particle.png") ) )
00227 
00228         {
00229               tex = convertToGLFormat(buf);  // flipped 32bit RGBA
00230               kDebug() << "Texture loaded: " << tex.numBytes ();
00231        }
00232        else
00233        {
00234               QImage dummy( 32, 32, QImage::Format_RGB32 );
00235               dummy.fill( Qt::white );
00236               buf = dummy;
00237               tex = convertToGLFormat( buf );
00238        }
00239 
00240             /* Set the status to true */
00241             //Status = true;
00242        glGenTextures(1, &texture[0]);   /* create three textures */
00243        glBindTexture(GL_TEXTURE_2D, texture[0]);
00244        /* use linear filtering */
00245        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00246        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00247        /* actually generate the texture */
00248        glTexImage2D(GL_TEXTURE_2D, 0, 4, tex.width(), tex.height(), 0,
00249        GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
00250 
00251 
00252 
00253     return Status;
00254 }
00256 void Gravity::initializeGL ()
00257 {
00258 
00259        kDebug() << "InitGL";
00260 
00261        if (loadParticle())                                     // Jump To Texture Loading Routine
00262        {
00263     /* Enable smooth shading */
00264     glShadeModel( GL_SMOOTH );
00265 
00266     /* Set the background black */
00267     glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
00268 
00269     /* Depth buffer setup */
00270     glClearDepth( 1.0f );
00271 
00272     /* Enables Depth Testing */
00273     glDisable( GL_DEPTH_TEST );
00274 
00275     /* Enable Blending */
00276     glEnable( GL_BLEND );
00277     /* Type Of Blending To Perform */
00278     glBlendFunc( GL_SRC_ALPHA, GL_ONE );
00279 
00280 
00281     /* Really Nice Perspective Calculations */
00282     glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
00283     /* Really Nice Point Smoothing */
00284     glHint( GL_POINT_SMOOTH_HINT, GL_NICEST );
00285 
00286     /* Enable Texture Mapping */
00287     glEnable( GL_TEXTURE_2D );
00288     /* Select Our Texture */
00289     glBindTexture( GL_TEXTURE_2D, texture[0] );
00290 
00291               for (loop=0;loop<MAX_PARTICLES;loop++)                         // Initials All The Textures
00292                {
00293                      buildParticle(loop);
00294               }
00295        }
00296        else
00297               exit(0);
00298 }
00300 void Gravity::resizeGL ( int width, int height )
00301 {
00302        kDebug() << "ResizeGL " << width << "," <<height;
00303        if (height==0)                                                 // Prevent A Divide By Zero By
00304        {
00305               height=1;                                        // Making Height Equal One
00306        }
00307 
00308        glViewport(0,0,width,height);                                  // Reset The Current Viewport
00309 
00310        glMatrixMode(GL_PROJECTION);                                   // Select The Projection Matrix
00311        glLoadIdentity();                                       // Reset The Projection Matrix
00312 
00313        // Calculate The Aspect Ratio Of The Window
00314        gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
00315 
00316        glMatrixMode(GL_MODELVIEW);                             // Select The Modelview Matrix
00317        glLoadIdentity();
00318 }
00320 void Gravity::paintGL ()
00321 {
00322        //kDebug() << "PaintGL";
00323        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);            // Clear Screen And Depth Buffer
00324        glLoadIdentity();
00325                                           // Reset The ModelView Matrix
00326        transIndex++;
00327        //glRotatef(transIndex, 1,0,0);
00328        //glRotatef(transIndex, 0,1,0);
00329        //glRotatef(transIndex, 0,0,1);
00330        float xmax = 5.0;
00331        float ymax = 5.0;
00332        glTranslatef( GLfloat(xmax*sin(3.14*transIndex/360)-xmax),
00333                      GLfloat(ymax*cos(3.14*transIndex/360)-ymax),
00334                      0.0 );
00335        //glRotatef(transIndex, 0,GLfloat(zmax*cos(3.14*transIndex/360000)), GLfloat(zmax*cos(3.14*transIndex/360000)));
00336 
00337        for (loop=0;loop<MAX_PARTICLES;loop++)                         // Loop Through All The Particles
00338        {
00339               if (particle[loop].active)                       // If The Particle Is Active
00340               {
00341                      float x=particle[loop].x;                 // Grab Our Particle X Position
00342                      float y=particle[loop].y;                 // Grab Our Particle Y Position
00343                      float z=particle[loop].z+zoom;                   // Particle Z Pos + Zoom
00344     /* Select Our Texture */
00345 
00346                     /* Draw The Particle Using Our RGB Values,
00347                      * Fade The Particle Based On It's Life
00348                      */
00349                      particle[loop].life=(particle[loop].index/particle[loop].indexo)*2.0f;
00350                     glColor4f( particle[loop].r,
00351                                particle[loop].g,
00352                                particle[loop].b,
00353                                particle[loop].life );
00354 
00355                     /* Build Quad From A Triangle Strip */
00356                 if( !stars )
00357                   glBegin( GL_TRIANGLE_STRIP );
00358                 else
00359               glBegin( GL_TRIANGLE_FAN );
00360                      /* Top Right */
00361                      glTexCoord2d( 1, 1 );
00362                      glVertex3f( x + particle[loop].size, y + particle[loop].size, z );
00363                      /* Top Left */
00364                      glTexCoord2d( 0, 1 );
00365                      glVertex3f( x - particle[loop].size, y + particle[loop].size, z );
00366                      /* Bottom Right */
00367                      glTexCoord2d( 1, 0 );
00368                      glVertex3f( x + particle[loop].size, y - particle[loop].size, z );
00369                      /* Bottom Left */
00370                      glTexCoord2d( 0, 0 );
00371                      glVertex3f( x - particle[loop].size, y - particle[loop].size, z );
00372               glEnd( );
00373                      particle[loop].x=(particle[loop].xo*sin(particle[loop].index))*pow((double) particle[loop].index/particle[loop].indexo,(double) 8.0);
00374                      particle[loop].y=(particle[loop].yo*sin(particle[loop].index))*pow((double) particle[loop].index/particle[loop].indexo,(double) 8.0);
00375                      particle[loop].z=(particle[loop].zo*sin(particle[loop].index))*pow((double) particle[loop].index/particle[loop].indexo,(double) 8.0);
00376                      particle[loop].index-=0.05;
00377                      if (particle[loop].index<0.0f )                  // If Particle Is Burned Out
00378                      {
00379                             buildParticle(loop);
00380                      }
00381                      // Lets stir some things up
00382               }
00383        }
00384 
00385        glFlush();
00386 }
00387 void Gravity::setSize( float newSize )
00388 {
00389        size = newSize;
00390 }
00391 void Gravity::setStars( bool doStars )
00392 {
00393        stars = doStars;
00394 }
00395 
00396 void KGravitySaver::updateSize(int newSize)
00397 {
00398        gravity->setSize(newSize/100);
00399 }
00400 void KGravitySaver::doStars(bool starState)
00401 {
00402        gravity->setStars(starState);
00403 }
00404 
00405 void Gravity::buildParticle(int loop)
00406 {
00407        GLfloat colors[12][3]=
00408        {{1.0f,0.5f,0.5f},{1.0f,0.75f,0.5f},{1.0f,1.0f,0.5f},{0.75f,1.0f,0.5f},
00409        {0.5f,1.0f,0.5f},{0.5f,1.0f,0.75f},{0.5f,1.0f,1.0f},{0.5f,0.75f,1.0f},
00410        {0.5f,0.5f,1.0f},{0.75f,0.5f,1.0f},{1.0f,0.5f,1.0f},{1.0f,0.5f,0.75f}};
00411        col = ( ++col ) % 12;
00412        particle[loop].active=true;
00413        particle[loop].index=KRandom::random()%100;
00414        particle[loop].indexo=particle[loop].index;
00415        particle[loop].fade=float(KRandom::random()%100)/1000.0f+0.003f;      // Random Fade Value
00416        particle[loop].r=colors[col][0];                 // Select Red From Color Table
00417        particle[loop].g=colors[col][1];                 // Select Green From Color Table
00418        particle[loop].b=colors[col][2];                 // Select Blue From Color Table
00419        particle[loop].size=size;
00420        particle[loop].x = float(KRandom::random()%100-50)*4.0;
00421        particle[loop].y = float(KRandom::random()%20-10)*4.0;
00422        particle[loop].z = float(KRandom::random()%100-50)*4.0;
00423        particle[loop].xo = particle[loop].x;
00424        if ((1+(KRandom::random() % 10) > 5))
00425               particle[loop].yo = particle[loop].y;
00426        else
00427               particle[loop].yo = 0.0;
00428        particle[loop].zo = particle[loop].z;
00429 
00430 }
00431