/* * * kStart OpenGL screensave for KDE * * $Id$ * * Copyright (C) 1998 Bernd Johannes Wuebben * wuebben@math.cornell.edu * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Based on star.c: * * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the name of * Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF * ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #define LONG64 //#define TQT_CLEAN_NAMESPACE #include #include #include #include #include #include #include "xlock.h" #include "helpers.h" #ifdef HAVE_CONFIG_H #include "../../config.h" #endif #ifdef HAVE_GL #include #undef index #include "space.h" #include #include #ifdef HAVE_GL_XMESA_H #include #endif #include #include #ifdef HAVE_GL_GLUT_H // We don't need GLUT, but some BROKEN GLU implemenations, such as the one // used in SuSE Linux 6.3, do. :( #include #endif #include #ifndef PI #ifdef M_PI #define PI M_PI #else #define PI 3.141592657 #endif #endif enum { NORMAL = 0, WEIRD = 1 } flag = NORMAL; enum { STREAK = 0, CIRCLE = 1 }; #define MAXSTARS 400 #define MAXPOS 10000 #define MAXWARP1 10 #define MAXANGLES 6000 typedef struct _starRec { GLint type; float x[2], y[2], z[2]; float offsetX, offsetY, offsetR, rotation; } starRec; GLenum doubleBuffer, directRender; GLint windW, windH; GLint starCount = MAXSTARS / 2; float speed = 1.0; float warpinterval = 30000.0; GLint nitro = 0; starRec stars[MAXSTARS]; float sinTable[MAXANGLES]; static GLXContext glx_context; static KRandomSequence *rnd = 0; float Sin(float angle) { return (sinTable[(GLint)angle]); } float Cos(float angle) { return (sinTable[((GLint)angle+(MAXANGLES/4))%MAXANGLES]); } void NewStar(GLint n, GLint d) { if (rnd->getLong(4) == 0) { stars[n].type = CIRCLE; } else { stars[n].type = STREAK; } stars[n].x[0] = rnd->getDouble() * MAXPOS - MAXPOS / 2; stars[n].y[0] = rnd->getDouble() * MAXPOS - MAXPOS / 2; stars[n].z[0] = rnd->getDouble() * MAXPOS + d; if (rnd->getLong(4) == 0 && flag == WEIRD) { stars[n].offsetX = rnd->getDouble()* 100 - 100 / 2; stars[n].offsetY = rnd->getDouble()* 100 - 100 / 2; stars[n].offsetR = rnd->getDouble()* 25 - 25 / 2; } else { stars[n].offsetX = 0.0; stars[n].offsetY = 0.0; stars[n].offsetR = 0.0; } } void RotatePoint(float *x, float *y, float rotation) { float tmpX, tmpY; tmpX = *x * Cos(rotation) - *y * Sin(rotation); tmpY = *y * Cos(rotation) + *x * Sin(rotation); *x = tmpX; *y = tmpY; } void MoveStars(void) { float offset; GLint n; offset = speed * 60.0; for (n = 0; n < starCount; n++) { stars[n].x[1] = stars[n].x[0]; stars[n].y[1] = stars[n].y[0]; stars[n].z[1] = stars[n].z[0]; stars[n].x[0] += stars[n].offsetX; stars[n].y[0] += stars[n].offsetY; stars[n].z[0] -= offset; stars[n].rotation += stars[n].offsetR; if (stars[n].rotation > MAXANGLES) { stars[n].rotation = 0.0; } } } GLenum StarPoint(GLint n) { float x0, y0, x1, y1, width; GLint i; x0 = stars[n].x[0] * windW / stars[n].z[0]; y0 = stars[n].y[0] * windH / stars[n].z[0]; RotatePoint(&x0, &y0, stars[n].rotation); x0 += windW / 2.0; y0 += windH / 2.0; if (x0 >= 0.0 && x0 < windW && y0 >= 0.0 && y0 < windH) { if (stars[n].type == STREAK) { x1 = stars[n].x[1] * windW / stars[n].z[1]; y1 = stars[n].y[1] * windH / stars[n].z[1]; RotatePoint(&x1, &y1, stars[n].rotation); x1 += windW / 2.0; y1 += windH / 2.0; glLineWidth(MAXPOS/100.0/stars[n].z[0]+1.0); glColor3f((MAXWARP1-speed)/MAXWARP1, (MAXWARP1-speed)/MAXWARP1, .9); if (fabs(x0-x1) < 1.0 && fabs(y0-y1) < 1.0) { glBegin(GL_POINTS); glVertex2f(x0, y0); glEnd(); } else { glBegin(GL_LINES); glVertex2f(x0, y0); glVertex2f(x1, y1); glEnd(); } } else { width = MAXPOS / 10.0 / stars[n].z[0] + 1.0; glColor3f(1.0, 0.0, 0.0); glBegin(GL_POLYGON); for (i = 0; i < 8; i++) { float x = x0 + width * Cos((float)i*MAXANGLES/8.0); float y = y0 + width * Sin((float)i*MAXANGLES/8.0); glVertex2f(x, y); }; glEnd(); } return GL_TRUE; } else { return GL_FALSE; } } void ShowStars(void) { GLint n; glClear(GL_COLOR_BUFFER_BIT); for (n = 0; n < starCount; n++) { if (stars[n].z[0] > speed || (stars[n].z[0] > 0.0 && speed < MAXWARP1)) { if (StarPoint(n) == GL_FALSE) { NewStar(n, MAXPOS); } } else { NewStar(n, MAXPOS); } } } static void Init(void) { float angle; GLint n; for (n = 0; n < MAXSTARS; n++) { NewStar(n, 100); } angle = 0.0; for (n = 0; n < MAXANGLES ; n++) { sinTable[n] = sin(angle); angle += PI / (MAXANGLES / 2.0); } glClearColor(0.0, 0.0, 0.0, 0.0); glDisable(GL_DITHER); } void reshape(int width, int height) { windW = (GLint)width; windH = (GLint)height; glViewport(0, 0, windW, windH); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-0.5, windW+0.5, -0.5, windH+0.5); glMatrixMode(GL_MODELVIEW); } void Idle(void) { MoveStars(); ShowStars(); if (nitro > 0) { speed = (float)(nitro / 10) + 1.0; if (speed > MAXWARP1) { speed = MAXWARP1; } if (++nitro > MAXWARP1*10) { nitro = -nitro; } } else if (nitro < 0) { nitro++; speed = (float)(-nitro / 10) + 1.0; if (speed > MAXWARP1) { speed = MAXWARP1; } } glFlush(); /* if (doubleBuffer) { tkSwapBuffers(); }*/ } void drawSpace(Window /*window*/) { /* Display *display = dsp; //glXMakeCurrent(display, window, mp->glx_context); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glFlush(); glXSwapBuffers(display, window); */ Idle(); } void release_Space(){ glXDestroyContext(dsp, glx_context); } static XVisualInfo *glVis[MAXSCREENS]; int getVisual(XVisualInfo * wantVis, int visual_count) { Display *display = dsp; static int first; int i; if (first) { for (screen = 0; screen < MAXSCREENS; screen++) glVis[screen] = NULL; } if (!glVis[screen]) { if (mono) { /* Monochrome display - use color index mode */ int attribList[] = {GLX_DOUBLEBUFFER, None}; glVis[screen] = glXChooseVisual(display, screen, attribList); } else { int attribList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 1, None}; glVis[screen] = glXChooseVisual(display, screen, attribList); } } // Make sure we have a visual if (!glVis[screen]) { return (0); } /* check if GL can render into root window. */ for(i=0;ivisual == (wantVis+i)->visual) ) return (1); // success // The visual we received did not match one we asked for return (0); } void initSpace(Window window) { Display *display = dsp; XWindowAttributes xwa; (void) XGetWindowAttributes(dsp, window, &xwa); int n; XVisualInfo *wantVis, vTemplate; int VisualClassWanted=-1; vTemplate.screen = screen; vTemplate.depth = xwa.depth; if (VisualClassWanted == -1) { vTemplate.c_class = DefaultVisual(display, screen)->c_class; } else { vTemplate.c_class = VisualClassWanted; } wantVis = XGetVisualInfo(display, VisualScreenMask | VisualDepthMask | VisualClassMask, &vTemplate, &n); if (VisualClassWanted != -1 && n == 0) { /* Wanted visual not found so use default */ vTemplate.c_class = DefaultVisual(display, screen)->c_class; wantVis = XGetVisualInfo(display, VisualScreenMask | VisualDepthMask | VisualClassMask, &vTemplate, &n); } /* if User asked for color, try that first, then try mono */ /* if User asked for mono. Might fail on 16/24 bit displays, so fall back on color, but keep the mono "look & feel". */ if (!getVisual(wantVis, n)) { if (!getVisual(wantVis, n)) { kdError() << i18n("GL can not render with root visual\n") << endl; return; } } /* PURIFY 3.0a on SunOS4 reports a 104 byte memory leak on the next line each * time that morph3d mode is run in random mode. */ glx_context = glXCreateContext(display, wantVis, 0, True); XFree((char *) wantVis); glXMakeCurrent(display, window, glx_context); glDrawBuffer(GL_FRONT); if (mono) { glIndexi(WhitePixel(display, screen)); glClearIndex(BlackPixel(display, screen)); } reshape(xwa.width, xwa.height); Init(); } #endif #define MINSPEED 1 #define MAXSPEED 100 #define DEFSPEED 50 #define MINWARP 1 #define MAXWARP 30 #define DEFWARP 2 #define WARPFACTOR 100 //----------------------------------------------------------------------------- #include #include #include #include #include #include "space.moc" #undef Below static kSpaceSaver *saver = NULL; void startScreenSaver( Drawable d ) { if ( saver ) return; saver = new kSpaceSaver( d ); } void stopScreenSaver() { if ( saver ) delete saver; saver = NULL; } int setupScreenSaver() { kSpaceSetup dlg; return dlg.exec(); } //----------------------------------------------------------------------------- kSpaceSaver::kSpaceSaver( Drawable drawable ) : kScreenSaver( drawable ) { rnd = new KRandomSequence(); readSettings(); counter = (int)warpinterval *WARPFACTOR; colorContext = TQColor::enterAllocContext(); initXLock( mGc ); initSpace( mDrawable ); timer.start( speed ); connect( &timer, TQT_SIGNAL( timeout() ), TQT_SLOT( slotTimeout() ) ); } kSpaceSaver::~kSpaceSaver() { timer.stop(); release_Space(); TQColor::leaveAllocContext(); TQColor::destroyAllocContext( colorContext ); delete rnd; rnd = 0; } void kSpaceSaver::setSpeed( int spd ) { timer.stop(); speed = MAXSPEED - spd ; // printf("speed %d\n",speed); timer.stop(); timer.start( speed ); } void kSpaceSaver::setWarp( int w ) { warpinterval = w; counter = (int)warpinterval; initSpace( mDrawable ); } void kSpaceSaver::readSettings() { TDEConfig *config = klock_config(); config->setGroup( "Settings" ); TQString str; str = config->readEntry( "Speed" ); if ( !str.isNull() ) speed = MAXSPEED - str.toInt(); else speed = DEFSPEED; warpinterval = config->readNumEntry( "WarpInterval", 15 ); delete config; } void kSpaceSaver::slotTimeout() { //printf("%d %d \n",(int)warpinterval, MAXWARP); if(warpinterval != MAXWARP){ if(nitro == 0) counter -= speed +1; if(counter <= 0){ nitro = 1; counter = (int) warpinterval *WARPFACTOR; } } else nitro = 0; drawSpace( mDrawable ); } //----------------------------------------------------------------------------- kSpaceSetup::kSpaceSetup( TQWidget *parent, const char *name ) : KDialogBase( parent, name, true, i18n("Setup Space Screen Saver"), Ok|Cancel|Help, Ok, true ) { setButtonText( Help, i18n( "A&bout" ) ); readSettings(); TQWidget *page = new TQWidget( this ); setMainWidget( page ); TQHBoxLayout *hb = new TQHBoxLayout( page, 0, spacingHint() ); TQVBoxLayout *vb = new TQVBoxLayout( hb, spacingHint() ); TQLabel *label; TQSlider *slider; label = new TQLabel( i18n("Speed:"), page ); vb->addWidget( label ); slider = new TQSlider(MINSPEED, MAXSPEED, 10, speed, Qt::Horizontal, page ); vb->addWidget( slider ); slider->setTickmarks(TQSlider::Below); slider->setTickInterval(10); connect( slider, TQT_SIGNAL( valueChanged( int ) ), TQT_SLOT( slotSpeed( int ) ) ); label = new TQLabel( i18n("Warp interval:"), page ); vb->addWidget( label ); slider = new TQSlider(MINWARP, MAXWARP, 3, warpinterval,Qt::Horizontal, page ); vb->addWidget( slider ); slider->setTickmarks(TQSlider::Below); slider->setTickInterval(3); connect( slider, TQT_SIGNAL( valueChanged( int ) ), TQT_SLOT( slotWarp( int ) ) ); vb->addStrut( 150 ); vb->addStretch(); preview = new TQWidget( page ); hb->addWidget( preview ); preview->setFixedSize( 220, 170 ); preview->setBackgroundColor( black ); preview->show(); // otherwise saver does not get correct size saver = new kSpaceSaver( preview->winId() ); } void kSpaceSetup::readSettings() { TDEConfig *config = klock_config(); config->setGroup( "Settings" ); speed = config->readNumEntry( "Speed", speed ); if ( speed > MAXSPEED ) speed = MAXSPEED; else if ( speed < MINSPEED ) speed = MINSPEED; warpinterval = config->readNumEntry( "WarpInterval", 15 ); delete config; } void kSpaceSetup::slotSpeed( int num ) { speed = num ; if ( saver ) saver->setSpeed( speed ); } void kSpaceSetup::slotWarp( int num ) { warpinterval = num; if ( saver ) saver->setWarp( warpinterval ); } void kSpaceSetup::slotOk() { TDEConfig *config = klock_config(); config->setGroup( "Settings" ); TQString sspeed; sspeed.setNum( speed ); config->writeEntry( "Speed", sspeed ); TQString interval; interval.setNum( (int)warpinterval ); config->writeEntry( "WarpInterval", interval ); config->sync(); delete config; accept(); } void kSpaceSetup::slotHelp() { KMessageBox::about(this, i18n("KSpace\nCopyright (c) 1998\n" "Bernd Johannes Wuebben ")); } /* static GLenum Args(int argc, char **argv) { GLint i; doubleBuffer = GL_FALSE; directRender = GL_TRUE; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-sb") == 0) { doubleBuffer = GL_FALSE; } else if (strcmp(argv[i], "-db") == 0) { doubleBuffer = GL_TRUE; } else if (strcmp(argv[i], "-dr") == 0) { directRender = GL_TRUE; } else if (strcmp(argv[i], "-ir") == 0) { directRender = GL_FALSE; } } return GL_TRUE; } void main(int argc, char **argv) { GLenum type; if (Args(argc, argv) == GL_FALSE) { tkQuit(); } windW = 300; windH = 300; tkInitPosition(0, 0, 300, 300); type = TK_RGB; type |= (doubleBuffer) ? TK_DOUBLE : TK_SINGLE; type |= (directRender) ? TK_DIRECT : TK_INDIRECT; tkInitDisplayMode(type); if (tkInitWindow("Stars") == GL_FALSE) { tkQuit(); } Init(); tkExposeFunc(Reshape); tkReshapeFunc(Reshape); tkKeyDownFunc(Key); tkIdleFunc(Idle); tkExec(); } */