//============================================================================
//
// Terence Welsh Screensaver - Euphoria
// http://www.reallyslick.com/
//
// Ported to KDE by Karl Robillard
//
/*
* Copyright ( C ) 2002 Terence M . Welsh
*
* Euphoria is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* Euphoria 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 General Public License for more details .
*
* You should have received a copy of the GNU 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
*/
//============================================================================
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
# include <time.h>
# include <tqtimer.h>
# include "Euphoria.h"
# include "Euphoria.moc"
# include "EuphoriaTexture.h"
# define NUMCONSTS 9
# define PIx2 6.28318530718f
//----------------------------------------------------------------------------
# include <sys/time.h>
# include <unistd.h>
// Returns the system time, in seconds.
double timeGetTime ( )
{
struct timeval tp ;
gettimeofday ( & tp , 0 ) ;
return ( double ) tp . tv_sec + ( double ) tp . tv_usec / 1000000 ;
}
//----------------------------------------------------------------------------
class rsVec
{
public :
float v [ 3 ] ;
rsVec ( ) { }
rsVec ( float xx , float yy , float zz ) ;
void set ( float xx , float yy , float zz ) ;
float normalize ( ) ;
float dot ( rsVec ) ;
void cross ( rsVec , rsVec ) ;
float & operator [ ] ( int i ) { return v [ i ] ; }
const float & operator [ ] ( int i ) const { return v [ i ] ; }
rsVec & operator = ( const rsVec & vec )
{ v [ 0 ] = vec [ 0 ] ; v [ 1 ] = vec [ 1 ] ; v [ 2 ] = vec [ 2 ] ; return * this ; } ;
rsVec operator + ( const rsVec & vec )
{ return ( rsVec ( v [ 0 ] + vec [ 0 ] , v [ 1 ] + vec [ 1 ] , v [ 2 ] + vec [ 2 ] ) ) ; } ;
rsVec operator - ( const rsVec & vec )
{ return ( rsVec ( v [ 0 ] - vec [ 0 ] , v [ 1 ] - vec [ 1 ] , v [ 2 ] - vec [ 2 ] ) ) ; } ;
rsVec operator * ( const float & mul )
{ return ( rsVec ( v [ 0 ] * mul , v [ 1 ] * mul , v [ 2 ] * mul ) ) ; } ;
rsVec operator / ( const float & div )
{ float rec = 1.0f / div ; return ( rsVec ( v [ 0 ] * rec , v [ 1 ] * rec , v [ 2 ] * rec ) ) ; } ;
rsVec & operator + = ( const rsVec & vec )
{ v [ 0 ] + = vec [ 0 ] ; v [ 1 ] + = vec [ 1 ] ; v [ 2 ] + = vec [ 2 ] ; return * this ; } ;
rsVec & operator - = ( const rsVec & vec )
{ v [ 0 ] - = vec [ 0 ] ; v [ 1 ] - = vec [ 1 ] ; v [ 2 ] - = vec [ 2 ] ; return * this ; } ;
rsVec & operator * = ( const rsVec & vec )
{ v [ 0 ] * = vec [ 0 ] ; v [ 1 ] * = vec [ 1 ] ; v [ 2 ] * = vec [ 2 ] ; return * this ; } ;
rsVec & operator * = ( const float & mul )
{ v [ 0 ] * = mul ; v [ 1 ] * = mul ; v [ 2 ] * = mul ; return * this ; } ;
} ;
rsVec : : rsVec ( float xx , float yy , float zz ) {
v [ 0 ] = xx ;
v [ 1 ] = yy ;
v [ 2 ] = zz ;
}
void rsVec : : set ( float xx , float yy , float zz ) {
v [ 0 ] = xx ;
v [ 1 ] = yy ;
v [ 2 ] = zz ;
}
float rsVec : : normalize ( ) {
float length = float ( sqrt ( v [ 0 ] * v [ 0 ] + v [ 1 ] * v [ 1 ] + v [ 2 ] * v [ 2 ] ) ) ;
if ( length = = 0.0f ) {
v [ 1 ] = 1.0f ;
return ( 0.0f ) ;
}
float reciprocal = 1.0f / length ;
v [ 0 ] * = reciprocal ;
v [ 1 ] * = reciprocal ;
v [ 2 ] * = reciprocal ;
// Really freakin' stupid compiler bug fix for VC++ 5.0
/*v[0] /= length;
v [ 1 ] / = length ;
v [ 2 ] / = length ; */
return ( length ) ;
}
float rsVec : : dot ( rsVec vec1 ) {
return ( v [ 0 ] * vec1 [ 0 ] + v [ 1 ] * vec1 [ 1 ] + v [ 2 ] * vec1 [ 2 ] ) ;
}
void rsVec : : cross ( rsVec vec1 , rsVec vec2 ) {
v [ 0 ] = vec1 [ 1 ] * vec2 [ 2 ] - vec2 [ 1 ] * vec1 [ 2 ] ;
v [ 1 ] = vec1 [ 2 ] * vec2 [ 0 ] - vec2 [ 2 ] * vec1 [ 0 ] ;
v [ 2 ] = vec1 [ 0 ] * vec2 [ 1 ] - vec2 [ 0 ] * vec1 [ 1 ] ;
}
//----------------------------------------------------------------------------
void hsl2rgb ( float h , float s , float l , float & r , float & g , float & b )
{
// hue influence
if ( h < 0.166667 ) { // full red, some green
r = 1.0 ;
g = h * 6.0f ;
b = 0.0 ;
}
else {
if ( h < 0.5 ) { // full green
g = 1.0 ;
if ( h < 0.333333 ) { // some red
r = 1.0f - ( ( h - 0.166667f ) * 6.0f ) ;
b = 0.0 ;
}
else { // some blue
b = ( h - 0.333333f ) * 6.0f ;
r = 0.0 ;
}
}
else {
if ( h < 0.833333 ) { // full blue
b = 1.0 ;
if ( h < 0.666667 ) { // some green
g = 1.0f - ( ( h - 0.5f ) * 6.0f ) ;
r = 0.0 ;
}
else { // some red
r = ( h - 0.666667f ) * 6.0f ;
g = 0.0 ;
}
}
else { // full red, some blue
r = 1.0 ;
b = 1.0f - ( ( h - 0.833333f ) * 6.0f ) ;
g = 0.0 ;
}
}
}
// saturation influence
r = 1.0f - ( s * ( 1.0f - r ) ) ;
g = 1.0f - ( s * ( 1.0f - g ) ) ;
b = 1.0f - ( s * ( 1.0f - b ) ) ;
// luminosity influence
r * = l ;
g * = l ;
b * = l ;
}
// Useful random number macros
// Don't forget to initialize with srand()
inline int myRandi ( int x ) {
return ( ( rand ( ) * x ) / RAND_MAX ) ;
}
inline float myRandf ( float x ) {
return ( float ( rand ( ) * x ) / float ( RAND_MAX ) ) ;
}
//----------------------------------------------------------------------------
// Context pointer to allow many instances.
static EuphoriaWidget * _ec = 0 ;
class wisp
{
public :
wisp ( ) ;
~ wisp ( ) ;
void update ( ) ;
void draw ( ) ;
void drawAsBackground ( ) ;
int density ;
float * * * vertices ;
float c [ NUMCONSTS ] ; // constants
float cr [ NUMCONSTS ] ; // constants' radial position
float cv [ NUMCONSTS ] ; // constants' change velocities
float hsl [ 3 ] ;
float rgb [ 3 ] ;
float hueSpeed ;
float saturationSpeed ;
} ;
wisp : : wisp ( )
{
int i , j ;
float recHalfDens = 1.0f / ( float ( _ec - > dDensity ) * 0.5f ) ;
density = _ec - > dDensity ;
vertices = new float * * [ density + 1 ] ;
for ( i = 0 ; i < = density ; i + + )
{
vertices [ i ] = new float * [ density + 1 ] ;
for ( j = 0 ; j < = density ; j + + )
{
vertices [ i ] [ j ] = new float [ 7 ] ;
vertices [ i ] [ j ] [ 3 ] = float ( i ) * recHalfDens - 1.0f ; // x position on grid
vertices [ i ] [ j ] [ 4 ] = float ( j ) * recHalfDens - 1.0f ; // y position on grid
// distance squared from the center
vertices [ i ] [ j ] [ 5 ] = vertices [ i ] [ j ] [ 3 ] * vertices [ i ] [ j ] [ 3 ]
+ vertices [ i ] [ j ] [ 4 ] * vertices [ i ] [ j ] [ 4 ] ;
vertices [ i ] [ j ] [ 6 ] = 0.0f ; // intensity
}
}
// initialize constants
for ( i = 0 ; i < NUMCONSTS ; i + + )
{
c [ i ] = myRandf ( 2.0f ) - 1.0f ;
cr [ i ] = myRandf ( PIx2 ) ;
cv [ i ] = myRandf ( _ec - > dSpeed * 0.03f ) + ( _ec - > dSpeed * 0.001f ) ;
}
// pick color
hsl [ 0 ] = myRandf ( 1.0f ) ;
hsl [ 1 ] = 0.1f + myRandf ( 0.9f ) ;
hsl [ 2 ] = 1.0f ;
hueSpeed = myRandf ( 0.1f ) - 0.05f ;
saturationSpeed = myRandf ( 0.04f ) + 0.001f ;
}
wisp : : ~ wisp ( )
{
int i , j ;
for ( i = 0 ; i < = density ; i + + )
{
for ( j = 0 ; j < = density ; j + + )
{
delete [ ] vertices [ i ] [ j ] ;
}
delete [ ] vertices [ i ] ;
}
delete [ ] vertices ;
}
void wisp : : update ( )
{
int i , j ;
rsVec up , right , crossvec ;
// visibility constants
static float viscon1 = float ( _ec - > dVisibility ) * 0.01f ;
static float viscon2 = 1.0f / viscon1 ;
// update constants
for ( i = 0 ; i < NUMCONSTS ; i + + ) {
cr [ i ] + = cv [ i ] * _ec - > elapsedTime ;
if ( cr [ i ] > PIx2 )
cr [ i ] - = PIx2 ;
c [ i ] = cos ( cr [ i ] ) ;
}
// update vertex positions
for ( i = 0 ; i < = density ; i + + ) {
for ( j = 0 ; j < = density ; j + + ) {
vertices [ i ] [ j ] [ 0 ] = vertices [ i ] [ j ] [ 3 ] * vertices [ i ] [ j ] [ 3 ] * vertices [ i ] [ j ] [ 4 ] * c [ 0 ]
+ vertices [ i ] [ j ] [ 5 ] * c [ 1 ] + 0.5f * c [ 2 ] ;
vertices [ i ] [ j ] [ 1 ] = vertices [ i ] [ j ] [ 4 ] * vertices [ i ] [ j ] [ 4 ] * vertices [ i ] [ j ] [ 5 ] * c [ 3 ]
+ vertices [ i ] [ j ] [ 3 ] * c [ 4 ] + 0.5f * c [ 5 ] ;
vertices [ i ] [ j ] [ 2 ] = vertices [ i ] [ j ] [ 5 ] * vertices [ i ] [ j ] [ 5 ] * vertices [ i ] [ j ] [ 3 ] * c [ 6 ]
+ vertices [ i ] [ j ] [ 4 ] * c [ 7 ] + c [ 8 ] ;
}
}
// update vertex normals for most of mesh
for ( i = 1 ; i < density ; i + + ) {
for ( j = 1 ; j < density ; j + + ) {
up . set ( vertices [ i ] [ j + 1 ] [ 0 ] - vertices [ i ] [ j - 1 ] [ 0 ] ,
vertices [ i ] [ j + 1 ] [ 1 ] - vertices [ i ] [ j - 1 ] [ 1 ] ,
vertices [ i ] [ j + 1 ] [ 2 ] - vertices [ i ] [ j - 1 ] [ 2 ] ) ;
right . set ( vertices [ i + 1 ] [ j ] [ 0 ] - vertices [ i - 1 ] [ j ] [ 0 ] ,
vertices [ i + 1 ] [ j ] [ 1 ] - vertices [ i - 1 ] [ j ] [ 1 ] ,
vertices [ i + 1 ] [ j ] [ 2 ] - vertices [ i - 1 ] [ j ] [ 2 ] ) ;
up . normalize ( ) ;
right . normalize ( ) ;
crossvec . cross ( right , up ) ;
// Use depth component of normal to compute intensity
// This way only edges of wisp are bright
if ( crossvec [ 2 ] < 0.0f )
crossvec [ 2 ] * = - 1.0f ;
vertices [ i ] [ j ] [ 6 ] = viscon2 * ( viscon1 - crossvec [ 2 ] ) ;
if ( vertices [ i ] [ j ] [ 6 ] > 1.0f )
vertices [ i ] [ j ] [ 6 ] = 1.0f ;
if ( vertices [ i ] [ j ] [ 6 ] < 0.0f )
vertices [ i ] [ j ] [ 6 ] = 0.0f ;
}
}
// update color
hsl [ 0 ] + = hueSpeed * _ec - > elapsedTime ;
if ( hsl [ 0 ] < 0.0f )
hsl [ 0 ] + = 1.0f ;
if ( hsl [ 0 ] > 1.0f )
hsl [ 0 ] - = 1.0f ;
hsl [ 1 ] + = saturationSpeed * _ec - > elapsedTime ;
if ( hsl [ 1 ] < = 0.1f ) {
hsl [ 1 ] = 0.1f ;
saturationSpeed = - saturationSpeed ;
}
if ( hsl [ 1 ] > = 1.0f ) {
hsl [ 1 ] = 1.0f ;
saturationSpeed = - saturationSpeed ;
}
hsl2rgb ( hsl [ 0 ] , hsl [ 1 ] , hsl [ 2 ] , rgb [ 0 ] , rgb [ 1 ] , rgb [ 2 ] ) ;
}
void wisp : : draw ( )
{
int i , j ;
glPushMatrix ( ) ;
if ( _ec - > dWireframe )
{
for ( i = 1 ; i < density ; i + + ) {
glBegin ( GL_LINE_STRIP ) ;
for ( j = 0 ; j < = density ; j + + ) {
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 ) ;
glTexCoord2d ( vertices [ i ] [ j ] [ 3 ] - vertices [ i ] [ j ] [ 0 ] , vertices [ i ] [ j ] [ 4 ] - vertices [ i ] [ j ] [ 1 ] ) ;
glVertex3fv ( vertices [ i ] [ j ] ) ;
}
glEnd ( ) ;
}
for ( j = 1 ; j < density ; j + + ) {
glBegin ( GL_LINE_STRIP ) ;
for ( i = 0 ; i < = density ; i + + ) {
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 ) ;
glTexCoord2d ( vertices [ i ] [ j ] [ 3 ] - vertices [ i ] [ j ] [ 0 ] , vertices [ i ] [ j ] [ 4 ] - vertices [ i ] [ j ] [ 1 ] ) ;
glVertex3fv ( vertices [ i ] [ j ] ) ;
}
glEnd ( ) ;
}
}
else
{
for ( i = 0 ; i < density ; i + + ) {
glBegin ( GL_TRIANGLE_STRIP ) ;
for ( j = 0 ; j < = density ; j + + ) {
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 ) ;
glTexCoord2d ( vertices [ i + 1 ] [ j ] [ 3 ] - vertices [ i + 1 ] [ j ] [ 0 ] , vertices [ i + 1 ] [ j ] [ 4 ] - vertices [ i + 1 ] [ j ] [ 1 ] ) ;
glVertex3fv ( vertices [ i + 1 ] [ j ] ) ;
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 ) ;
glTexCoord2d ( vertices [ i ] [ j ] [ 3 ] - vertices [ i ] [ j ] [ 0 ] , vertices [ i ] [ j ] [ 4 ] - vertices [ i ] [ j ] [ 1 ] ) ;
glVertex3fv ( vertices [ i ] [ j ] ) ;
}
glEnd ( ) ;
}
}
glPopMatrix ( ) ;
}
void wisp : : drawAsBackground ( )
{
int i , j ;
glPushMatrix ( ) ;
glTranslatef ( c [ 0 ] * 0.2f , c [ 1 ] * 0.2f , 1.6f ) ;
if ( _ec - > dWireframe )
{
for ( i = 1 ; i < density ; i + + ) {
glBegin ( GL_LINE_STRIP ) ;
for ( j = 0 ; j < = density ; j + + ) {
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 ) ;
glTexCoord2d ( vertices [ i ] [ j ] [ 3 ] - vertices [ i ] [ j ] [ 0 ] , vertices [ i ] [ j ] [ 4 ] - vertices [ i ] [ j ] [ 1 ] ) ;
glVertex3f ( vertices [ i ] [ j ] [ 3 ] , vertices [ i ] [ j ] [ 4 ] , vertices [ i ] [ j ] [ 6 ] ) ;
}
glEnd ( ) ;
}
for ( j = 1 ; j < density ; j + + ) {
glBegin ( GL_LINE_STRIP ) ;
for ( i = 0 ; i < = density ; i + + ) {
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 ) ;
glTexCoord2d ( vertices [ i ] [ j ] [ 3 ] - vertices [ i ] [ j ] [ 0 ] , vertices [ i ] [ j ] [ 4 ] - vertices [ i ] [ j ] [ 1 ] ) ;
glVertex3f ( vertices [ i ] [ j ] [ 3 ] , vertices [ i ] [ j ] [ 4 ] , vertices [ i ] [ j ] [ 6 ] ) ;
}
glEnd ( ) ;
}
}
else
{
for ( i = 0 ; i < density ; i + + ) {
glBegin ( GL_TRIANGLE_STRIP ) ;
for ( j = 0 ; j < = density ; j + + ) {
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 ) ;
glTexCoord2d ( vertices [ i + 1 ] [ j ] [ 3 ] - vertices [ i + 1 ] [ j ] [ 0 ] , vertices [ i + 1 ] [ j ] [ 4 ] - vertices [ i + 1 ] [ j ] [ 1 ] ) ;
glVertex3f ( vertices [ i + 1 ] [ j ] [ 3 ] , vertices [ i + 1 ] [ j ] [ 4 ] , vertices [ i + 1 ] [ j ] [ 6 ] ) ;
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 ) ;
glTexCoord2d ( vertices [ i ] [ j ] [ 3 ] - vertices [ i ] [ j ] [ 0 ] , vertices [ i ] [ j ] [ 4 ] - vertices [ i ] [ j ] [ 1 ] ) ;
glVertex3f ( vertices [ i ] [ j ] [ 3 ] , vertices [ i ] [ j ] [ 4 ] , vertices [ i ] [ j ] [ 6 ] ) ;
}
glEnd ( ) ;
}
}
glPopMatrix ( ) ;
}
//----------------------------------------------------------------------------
EuphoriaWidget : : EuphoriaWidget ( TQWidget * parent , const char * name )
: TQGLWidget ( parent , name ) , texName ( 0 ) , _wisps ( 0 ) , _backwisps ( 0 ) ,
feedbackmap ( 0 ) , feedbacktex ( 0 )
{
setDefaults ( Regular ) ;
_frameTime = 1000 / 60 ;
_timer = new TQTimer ( this ) ;
connect ( _timer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( nextFrame ( ) ) ) ;
}
EuphoriaWidget : : ~ EuphoriaWidget ( )
{
// Free memory
if ( texName )
glDeleteTextures ( 1 , & texName ) ;
if ( feedbacktex )
glDeleteTextures ( 1 , & feedbacktex ) ;
delete [ ] _wisps ;
delete [ ] _backwisps ;
}
void EuphoriaWidget : : paintGL ( )
{
int i ;
static double lastTime = timeGetTime ( ) ;
// update time
elapsedTime = timeGetTime ( ) - lastTime ;
lastTime + = elapsedTime ;
_ec = this ;
// Update wisps
for ( i = 0 ; i < dWisps ; i + + )
_wisps [ i ] . update ( ) ;
for ( i = 0 ; i < dBackground ; i + + )
_backwisps [ i ] . update ( ) ;
if ( dFeedback )
{
float feedbackIntensity = float ( dFeedback ) / 101.0f ;
// update feedback variables
for ( i = 0 ; i < 4 ; i + + )
{
fr [ i ] + = elapsedTime * fv [ i ] ;
if ( fr [ i ] > PIx2 )
fr [ i ] - = PIx2 ;
}
f [ 0 ] = 30.0f * cos ( fr [ 0 ] ) ;
f [ 1 ] = 0.2f * cos ( fr [ 1 ] ) ;
f [ 2 ] = 0.2f * cos ( fr [ 2 ] ) ;
f [ 3 ] = 0.8f * cos ( fr [ 3 ] ) ;
for ( i = 0 ; i < 3 ; i + + )
{
lr [ i ] + = elapsedTime * lv [ i ] ;
if ( lr [ i ] > PIx2 )
lr [ i ] - = PIx2 ;
l [ i ] = cos ( lr [ i ] ) ;
l [ i ] = l [ i ] * l [ i ] ;
}
// Create drawing area for feedback texture
glViewport ( 0 , 0 , feedbacktexsize , feedbacktexsize ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
gluPerspective ( 30.0 , aspectRatio , 0.01f , 20.0f ) ;
glMatrixMode ( GL_MODELVIEW ) ;
// Draw
glClear ( GL_COLOR_BUFFER_BIT ) ;
glColor3f ( feedbackIntensity , feedbackIntensity , feedbackIntensity ) ;
glBindTexture ( GL_TEXTURE_2D , feedbacktex ) ;
glPushMatrix ( ) ;
glTranslatef ( f [ 1 ] * l [ 1 ] , f [ 2 ] * l [ 1 ] , f [ 3 ] * l [ 2 ] ) ;
glRotatef ( f [ 0 ] * l [ 0 ] , 0 , 0 , 1 ) ;
glBegin ( GL_TRIANGLE_STRIP ) ;
glTexCoord2f ( - 0.5f , - 0.5f ) ;
glVertex3f ( - aspectRatio * 2.0f , - 2.0f , 1.25f ) ;
glTexCoord2f ( 1.5f , - 0.5f ) ;
glVertex3f ( aspectRatio * 2.0f , - 2.0f , 1.25f ) ;
glTexCoord2f ( - 0.5f , 1.5f ) ;
glVertex3f ( - aspectRatio * 2.0f , 2.0f , 1.25f ) ;
glTexCoord2f ( 1.5f , 1.5f ) ;
glVertex3f ( aspectRatio * 2.0f , 2.0f , 1.25f ) ;
glEnd ( ) ;
glPopMatrix ( ) ;
glBindTexture ( GL_TEXTURE_2D , texName ) ;
for ( i = 0 ; i < dBackground ; i + + )
_backwisps [ i ] . drawAsBackground ( ) ;
for ( i = 0 ; i < dWisps ; i + + )
_wisps [ i ] . draw ( ) ;
// readback feedback texture
glReadBuffer ( GL_BACK ) ;
glPixelStorei ( GL_UNPACK_ROW_LENGTH , feedbacktexsize ) ;
glBindTexture ( GL_TEXTURE_2D , feedbacktex ) ;
glReadPixels ( 0 , 0 , feedbacktexsize , feedbacktexsize , GL_RGB , GL_UNSIGNED_BYTE , feedbackmap ) ;
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , 0 , feedbacktexsize , feedbacktexsize , GL_RGB , GL_UNSIGNED_BYTE , feedbackmap ) ;
// create regular drawing area
glViewport ( viewport [ 0 ] , viewport [ 1 ] , viewport [ 2 ] , viewport [ 3 ] ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
gluPerspective ( 20.0 , aspectRatio , 0.01f , 20.0f ) ;
glMatrixMode ( GL_MODELVIEW ) ;
// Draw again
glClear ( GL_COLOR_BUFFER_BIT ) ;
glColor3f ( feedbackIntensity , feedbackIntensity , feedbackIntensity ) ;
glPushMatrix ( ) ;
glTranslatef ( f [ 1 ] * l [ 1 ] , f [ 2 ] * l [ 1 ] , f [ 3 ] * l [ 2 ] ) ;
glRotatef ( f [ 0 ] * l [ 0 ] , 0 , 0 , 1 ) ;
glBegin ( GL_TRIANGLE_STRIP ) ;
glTexCoord2f ( - 0.5f , - 0.5f ) ;
glVertex3f ( - aspectRatio * 2.0f , - 2.0f , 1.25f ) ;
glTexCoord2f ( 1.5f , - 0.5f ) ;
glVertex3f ( aspectRatio * 2.0f , - 2.0f , 1.25f ) ;
glTexCoord2f ( - 0.5f , 1.5f ) ;
glVertex3f ( - aspectRatio * 2.0f , 2.0f , 1.25f ) ;
glTexCoord2f ( 1.5f , 1.5f ) ;
glVertex3f ( aspectRatio * 2.0f , 2.0f , 1.25f ) ;
glEnd ( ) ;
glPopMatrix ( ) ;
glBindTexture ( GL_TEXTURE_2D , texName ) ;
}
else
glClear ( GL_COLOR_BUFFER_BIT ) ;
//
for ( i = 0 ; i < dBackground ; i + + )
_backwisps [ i ] . drawAsBackground ( ) ;
for ( i = 0 ; i < dWisps ; i + + )
_wisps [ i ] . draw ( ) ;
glFlush ( ) ;
}
void EuphoriaWidget : : resizeGL ( int w , int h )
{
glViewport ( 0 , 0 , w , h ) ;
viewport [ 0 ] = 0 ;
viewport [ 1 ] = 0 ;
viewport [ 2 ] = w ;
viewport [ 3 ] = h ;
aspectRatio = ( float ) w / ( float ) h ;
// setup regular drawing area just in case feedback isn't used
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
gluPerspective ( 20.0 , aspectRatio , 0.01 , 20 ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
glTranslatef ( 0.0 , 0.0 , - 5.0 ) ;
}
// Window initialization
void EuphoriaWidget : : initializeGL ( )
{
// Need to call this to setup viewport[] parameters used in
// the next updateParameters() call
resizeGL ( width ( ) , height ( ) ) ;
updateParameters ( ) ;
_timer - > start ( _frameTime , true ) ;
}
# ifdef UNIT_TEST
void EuphoriaWidget : : keyPressEvent ( TQKeyEvent * e )
{
if ( e - > key ( ) = = TQt : : Key_0 ) { setDefaults ( 0 ) ; updateParameters ( ) ; }
if ( e - > key ( ) = = TQt : : Key_1 ) { setDefaults ( 1 ) ; updateParameters ( ) ; }
if ( e - > key ( ) = = TQt : : Key_2 ) { setDefaults ( 2 ) ; updateParameters ( ) ; }
if ( e - > key ( ) = = TQt : : Key_3 ) { setDefaults ( 3 ) ; updateParameters ( ) ; }
if ( e - > key ( ) = = TQt : : Key_4 ) { setDefaults ( 4 ) ; updateParameters ( ) ; }
if ( e - > key ( ) = = TQt : : Key_5 ) { setDefaults ( 5 ) ; updateParameters ( ) ; }
if ( e - > key ( ) = = TQt : : Key_6 ) { setDefaults ( 6 ) ; updateParameters ( ) ; }
if ( e - > key ( ) = = TQt : : Key_7 ) { setDefaults ( 7 ) ; updateParameters ( ) ; }
if ( e - > key ( ) = = TQt : : Key_8 ) { setDefaults ( 8 ) ; updateParameters ( ) ; }
}
# endif
void EuphoriaWidget : : nextFrame ( )
{
updateGL ( ) ;
_timer - > start ( _frameTime , true ) ;
}
void EuphoriaWidget : : updateParameters ( )
{
srand ( ( unsigned ) time ( NULL ) ) ;
rand ( ) ; rand ( ) ; rand ( ) ; rand ( ) ; rand ( ) ;
elapsedTime = 0.0f ;
fr [ 0 ] = 0.0f ;
fr [ 1 ] = 0.0f ;
fr [ 2 ] = 0.0f ;
fr [ 3 ] = 0.0f ;
lr [ 0 ] = 0.0f ;
lr [ 1 ] = 0.0f ;
lr [ 2 ] = 0.0f ;
glClearColor ( 0.0f , 0.0f , 0.0f , 1.0f ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_ONE , GL_ONE ) ;
glLineWidth ( 2.0f ) ;
// Commented out because smooth lines and textures don't mix on my TNT.
// It's like it rendering in software mode
glEnable ( GL_LINE_SMOOTH ) ;
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
if ( dTexture )
{
int whichtex = dTexture ;
if ( whichtex = = 4 ) // random texture
whichtex = myRandi ( 3 ) + 1 ;
glEnable ( GL_TEXTURE_2D ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
// Initialize texture
glGenTextures ( 1 , & texName ) ;
glBindTexture ( GL_TEXTURE_2D , texName ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_REPEAT ) ;
switch ( whichtex ) {
case 1 :
gluBuild2DMipmaps ( GL_TEXTURE_2D , 1 , TEXSIZE , TEXSIZE , GL_LUMINANCE , GL_UNSIGNED_BYTE , plasmamap ) ;
break ;
case 2 :
gluBuild2DMipmaps ( GL_TEXTURE_2D , 1 , TEXSIZE , TEXSIZE , GL_LUMINANCE , GL_UNSIGNED_BYTE , stringymap ) ;
break ;
case 3 :
gluBuild2DMipmaps ( GL_TEXTURE_2D , 1 , TEXSIZE , TEXSIZE , GL_LUMINANCE , GL_UNSIGNED_BYTE , linesmap ) ;
}
} else if ( texName ) {
glDeleteTextures ( 1 , & texName ) ;
texName = 0 ;
}
if ( dFeedback )
{
feedbacktexsize = int ( pow ( 2.0 , dFeedbacksize ) ) ;
while ( feedbacktexsize > viewport [ 2 ] | | feedbacktexsize > viewport [ 3 ] ) {
dFeedbacksize - = 1 ;
feedbacktexsize = int ( pow ( 2.0 , dFeedbacksize ) ) ;
}
// feedback texture setup
glEnable ( GL_TEXTURE_2D ) ;
delete [ ] feedbackmap ;
feedbackmap = new unsigned char [ feedbacktexsize * feedbacktexsize * 3 ] ;
glGenTextures ( 1 , & feedbacktex ) ;
glBindTexture ( GL_TEXTURE_2D , feedbacktex ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , 3 , feedbacktexsize , feedbacktexsize , 0 , GL_RGB , GL_UNSIGNED_BYTE , feedbackmap ) ;
// feedback velocity variable setup
fv [ 0 ] = float ( dFeedbackspeed ) * ( myRandf ( 0.025f ) + 0.025f ) ;
fv [ 1 ] = float ( dFeedbackspeed ) * ( myRandf ( 0.05f ) + 0.05f ) ;
fv [ 2 ] = float ( dFeedbackspeed ) * ( myRandf ( 0.05f ) + 0.05f ) ;
fv [ 3 ] = float ( dFeedbackspeed ) * ( myRandf ( 0.1f ) + 0.1f ) ;
lv [ 0 ] = float ( dFeedbackspeed ) * ( myRandf ( 0.0025f ) + 0.0025f ) ;
lv [ 1 ] = float ( dFeedbackspeed ) * ( myRandf ( 0.0025f ) + 0.0025f ) ;
lv [ 2 ] = float ( dFeedbackspeed ) * ( myRandf ( 0.0025f ) + 0.0025f ) ;
} else if ( feedbacktex ) {
glDeleteTextures ( 1 , & feedbacktex ) ;
feedbacktex = 0 ;
}
// Initialize wisps
_ec = this ;
delete [ ] _wisps ;
delete [ ] _backwisps ;
_wisps = new wisp [ dWisps ] ;
_backwisps = new wisp [ dBackground ] ;
}
/**
May be called at any time - makes no OpenGL calls .
*/
void EuphoriaWidget : : setDefaults ( int which )
{
switch ( which )
{
case Grid :
dWisps = 4 ;
dBackground = 1 ;
dDensity = 25 ;
dVisibility = 70 ;
dSpeed = 15 ;
dFeedback = 0 ;
dFeedbackspeed = 1 ;
dFeedbacksize = 8 ;
dWireframe = 1 ;
dTexture = 0 ;
break ;
case Cubism :
dWisps = 15 ;
dBackground = 0 ;
dDensity = 4 ;
dVisibility = 15 ;
dSpeed = 10 ;
dFeedback = 0 ;
dFeedbackspeed = 1 ;
dFeedbacksize = 8 ;
dWireframe = 0 ;
dTexture = 0 ;
break ;
case BadMath :
dWisps = 2 ;
dBackground = 2 ;
dDensity = 20 ;
dVisibility = 40 ;
dSpeed = 30 ;
dFeedback = 40 ;
dFeedbackspeed = 5 ;
dFeedbacksize = 8 ;
dWireframe = 1 ;
dTexture = 2 ;
break ;
case MTheory :
dWisps = 3 ;
dBackground = 0 ;
dDensity = 25 ;
dVisibility = 15 ;
dSpeed = 20 ;
dFeedback = 40 ;
dFeedbackspeed = 20 ;
dFeedbacksize = 8 ;
dWireframe = 0 ;
dTexture = 0 ;
break ;
case UHFTEM :
dWisps = 0 ;
dBackground = 3 ;
dDensity = 35 ;
dVisibility = 5 ;
dSpeed = 50 ;
dFeedback = 0 ;
dFeedbackspeed = 1 ;
dFeedbacksize = 8 ;
dWireframe = 0 ;
dTexture = 0 ;
break ;
case Nowhere :
dWisps = 0 ;
dBackground = 3 ;
dDensity = 30 ;
dVisibility = 40 ;
dSpeed = 20 ;
dFeedback = 80 ;
dFeedbackspeed = 10 ;
dFeedbacksize = 8 ;
dWireframe = 1 ;
dTexture = 3 ;
break ;
case Echo :
dWisps = 3 ;
dBackground = 0 ;
dDensity = 25 ;
dVisibility = 30 ;
dSpeed = 20 ;
dFeedback = 85 ;
dFeedbackspeed = 30 ;
dFeedbacksize = 8 ;
dWireframe = 0 ;
dTexture = 1 ;
break ;
case Kaleidoscope :
dWisps = 3 ;
dBackground = 0 ;
dDensity = 25 ;
dVisibility = 40 ;
dSpeed = 15 ;
dFeedback = 90 ;
dFeedbackspeed = 3 ;
dFeedbacksize = 8 ;
dWireframe = 0 ;
dTexture = 0 ;
break ;
case Regular :
default :
dWisps = 5 ;
dBackground = 0 ;
dDensity = 25 ;
dVisibility = 35 ;
dSpeed = 15 ;
dFeedback = 0 ;
dFeedbackspeed = 1 ;
dFeedbacksize = 8 ;
dWireframe = 0 ;
dTexture = 2 ;
break ;
}
}
//----------------------------------------------------------------------------
# ifndef UNIT_TEST
# include <klocale.h>
# include <kglobal.h>
# include <kconfig.h>
// libkscreensaver interface
extern " C "
{
KDE_EXPORT const char * kss_applicationName = " keuphoria.kss " ;
KDE_EXPORT const char * kss_description = I18N_NOOP ( " Euphoria " ) ;
KDE_EXPORT const char * kss_version = " 1.0 " ;
KDE_EXPORT KScreenSaver * kss_create ( WId id )
{
return new KEuphoriaScreenSaver ( id ) ;
}
KDE_EXPORT TQDialog * kss_setup ( )
{
return new KEuphoriaSetup ;
}
}
//----------------------------------------------------------------------------
KEuphoriaScreenSaver : : KEuphoriaScreenSaver ( WId id ) : KScreenSaver ( id )
{
_effect = new EuphoriaWidget ;
readSettings ( ) ;
embed ( _effect ) ;
_effect - > show ( ) ;
}
KEuphoriaScreenSaver : : ~ KEuphoriaScreenSaver ( )
{
}
static int filterRandom ( int n )
{
if ( ( n < 0 ) | | ( n > = EuphoriaWidget : : DefaultModes ) )
{
srand ( ( unsigned ) time ( NULL ) ) ;
n = rand ( ) % EuphoriaWidget : : DefaultModes ;
}
return n ;
}
void KEuphoriaScreenSaver : : readSettings ( )
{
KConfig * config = KGlobal : : config ( ) ;
config - > setGroup ( " Settings " ) ;
_mode = config - > readNumEntry ( " Mode " , EuphoriaWidget : : Regular ) ;
_effect - > setDefaults ( filterRandom ( _mode ) ) ;
}
/**
Any invalid mode will select one at random .
*/
void KEuphoriaScreenSaver : : setMode ( int id )
{
_mode = id ;
_effect - > setDefaults ( filterRandom ( id ) ) ;
_effect - > updateParameters ( ) ;
}
//----------------------------------------------------------------------------
# include <tqlayout.h>
# include <tqlabel.h>
# include <tqcombobox.h>
# include <kmessagebox.h>
static const char * defaultText [ ] =
{
I18N_NOOP ( " Regular " ) ,
I18N_NOOP ( " Grid " ) ,
I18N_NOOP ( " Cubism " ) ,
I18N_NOOP ( " Bad Math " ) ,
I18N_NOOP ( " M-Theory " ) ,
I18N_NOOP ( " UHFTEM " ) , //"ultra high frequency tunneling electron microscope",
I18N_NOOP ( " Nowhere " ) ,
I18N_NOOP ( " Echo " ) ,
I18N_NOOP ( " Kaleidoscope " ) ,
I18N_NOOP ( " (Random) " ) ,
0
} ;
KEuphoriaSetup : : KEuphoriaSetup ( TQWidget * parent , const char * name )
: KDialogBase ( parent , name , true , i18n ( " Setup Euphoria Screen Saver " ) ,
Ok | Cancel | Help , Ok , true )
{
setButtonText ( Help , i18n ( " A&bout " ) ) ;
TQWidget * main = makeMainWidget ( ) ;
TQHBoxLayout * top = new TQHBoxLayout ( main , 0 , spacingHint ( ) ) ;
TQVBoxLayout * leftCol = new TQVBoxLayout ;
top - > addLayout ( leftCol ) ;
TQLabel * label = new TQLabel ( i18n ( " Mode: " ) , main ) ;
leftCol - > addWidget ( label ) ;
modeW = new TQComboBox ( main ) ;
int i = 0 ;
while ( defaultText [ i ] )
modeW - > insertItem ( i18n ( defaultText [ i + + ] ) ) ;
leftCol - > addWidget ( modeW ) ;
leftCol - > addStretch ( ) ;
// Preview
TQWidget * preview ;
preview = new TQWidget ( main ) ;
preview - > setFixedSize ( 220 , 170 ) ;
preview - > setBackgroundColor ( black ) ;
preview - > show ( ) ; // otherwise saver does not get correct size
_saver = new KEuphoriaScreenSaver ( preview - > winId ( ) ) ;
top - > addWidget ( preview ) ;
// Now that we have _saver...
modeW - > setCurrentItem ( _saver - > mode ( ) ) ; // set before we connect
connect ( modeW , TQT_SIGNAL ( activated ( int ) ) , _saver , TQT_SLOT ( setMode ( int ) ) ) ;
setMinimumSize ( sizeHint ( ) ) ;
}
KEuphoriaSetup : : ~ KEuphoriaSetup ( )
{
delete _saver ;
}
void KEuphoriaSetup : : slotHelp ( )
{
KMessageBox : : about ( this ,
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> " ) ,
TQString ( ) , KMessageBox : : AllowLink ) ;
}
/**
Ok pressed - save settings and exit
*/
void KEuphoriaSetup : : slotOk ( )
{
KConfig * config = KGlobal : : config ( ) ;
config - > setGroup ( " Settings " ) ;
TQString val ;
val . setNum ( modeW - > currentItem ( ) ) ;
config - > writeEntry ( " Mode " , val ) ;
config - > sync ( ) ;
accept ( ) ;
}
# endif
//----------------------------------------------------------------------------
# ifdef UNIT_TEST
// moc Euphoria.h -o Euphoria.moc
// g++ -g -DUNIT_TEST Euphoria.cpp -I/usr/lib/qt3/include -lqt -L/usr/lib/qt3/lib -lGLU -lGL
# include <tqapplication.h>
int main ( int argc , char * * argv )
{
TQApplication app ( argc , argv ) ;
EuphoriaWidget w ;
w . setDefaults ( EuphoriaWidget : : UHFTEM ) ;
app . setMainWidget ( & w ) ;
w . show ( ) ;
return app . exec ( ) ;
}
# endif
//EOF