You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
354 lines
10 KiB
354 lines
10 KiB
/******************************************************************** |
|
KWin - the KDE window manager |
|
This file is part of the KDE project. |
|
|
|
Copyright (C) 2009 Martin Gräßlin <kde@martin-graesslin.com> |
|
|
|
This program is free software; you can redistribute it and/or modify |
|
it under the terms of the GNU 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 General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
Based on Compiz Fusion cube gear plugin by Dennis Kasprzyk: |
|
http://gitweb.compiz-fusion.org/?p=fusion/plugins/gears;a=blob;f=gears.c;hb=HEAD |
|
Which is based on glxgears.c by Brian Paul: |
|
http://cvsweb.xfree86.org/cvsweb/xc/programs/glxgears/glxgears.c |
|
*********************************************************************/ |
|
|
|
#include "gears.h" |
|
#include "../cube/cube_proxy.h" |
|
|
|
#include <math.h> |
|
|
|
#include <GL/gl.h> |
|
|
|
namespace KWin |
|
{ |
|
|
|
KWIN_EFFECT( gears, GearsEffect ) |
|
KWIN_EFFECT_SUPPORTED( gears, GearsEffect::supported() ) |
|
|
|
GearsEffect::GearsEffect() |
|
: CubeInsideEffect() |
|
, m_active( false ) |
|
, m_contentRotation( 0.0f ) |
|
, m_angle( 0.0f ) |
|
{ |
|
CubeEffectProxy* proxy = |
|
static_cast<CubeEffectProxy*>( effects->getProxy( "cube" ) ); |
|
if( proxy ) |
|
proxy->registerCubeInsideEffect( this ); |
|
} |
|
|
|
GearsEffect::~GearsEffect() |
|
{ |
|
CubeEffectProxy* proxy = |
|
static_cast<CubeEffectProxy*>( effects->getProxy( "cube" ) ); |
|
if( proxy ) |
|
proxy->unregisterCubeInsideEffect( this ); |
|
} |
|
|
|
bool GearsEffect::supported() |
|
{ |
|
return effects->compositingType() == OpenGLCompositing; |
|
} |
|
|
|
void GearsEffect::prePaintScreen( ScreenPrePaintData& data, int time ) |
|
{ |
|
if( m_active ) |
|
{ |
|
m_contentRotation += time * 360.0f / 20000.0f; |
|
if( m_contentRotation > 360.0f ) |
|
m_contentRotation -= 360.0f; |
|
m_angle += time * 360.0f / 8000.0f; |
|
if( m_angle > 360.0f ) |
|
m_angle -= 360.0f; |
|
} |
|
effects->prePaintScreen( data, time ); |
|
} |
|
|
|
void GearsEffect::postPaintScreen() |
|
{ |
|
if( m_active ) |
|
{ |
|
effects->addRepaintFull(); |
|
} |
|
effects->postPaintScreen(); |
|
} |
|
|
|
|
|
void GearsEffect::paint() |
|
{ |
|
if( m_active ) |
|
{ |
|
paintGears(); |
|
} |
|
} |
|
|
|
void GearsEffect::setActive( bool active ) |
|
{ |
|
m_active = active; |
|
if( active ) |
|
initGears(); |
|
else |
|
endGears(); |
|
} |
|
|
|
void GearsEffect::gear( float inner_radius, float outer_radius, float width, int teeth, float tooth_depth ) |
|
{ |
|
GLint i; |
|
GLfloat r0, r1, r2, maxr2, minr2; |
|
GLfloat angle, da; |
|
GLfloat u, v, len; |
|
|
|
r0 = inner_radius; |
|
r1 = outer_radius - tooth_depth / 2.0; |
|
maxr2 = r2 = outer_radius + tooth_depth / 2.0; |
|
minr2 = r2; |
|
|
|
da = 2.0 * M_PI / teeth / 4.0; |
|
|
|
glShadeModel( GL_FLAT ); |
|
|
|
glNormal3f( 0.0, 0.0, 1.0 ); |
|
|
|
/* draw front face */ |
|
glBegin( GL_QUAD_STRIP ); |
|
|
|
for( i = 0; i <= teeth; ++i ) |
|
{ |
|
angle = i * 2.0 * M_PI / teeth; |
|
glVertex3f( r0 * cos( angle ), r0 * sin( angle ), width * 0.5 ); |
|
glVertex3f( r1 * cos( angle ), r1 * sin( angle ), width * 0.5 ); |
|
|
|
if( i < teeth ) |
|
{ |
|
glVertex3f( r0 * cos( angle ), r0 * sin( angle ), width * 0.5 ); |
|
glVertex3f( r1 * cos( angle + 3 * da ), r1 * sin( angle + 3 * da ), width * 0.5 ); |
|
} |
|
} |
|
|
|
glEnd(); |
|
|
|
/* draw front sides of teeth */ |
|
glBegin( GL_QUADS ); |
|
|
|
for( i = 0; i < teeth; ++i ) |
|
{ |
|
angle = i * 2.0 * M_PI / teeth; |
|
|
|
glVertex3f( r1 * cos( angle ), r1 * sin( angle ), width * 0.5 ); |
|
glVertex3f( r2 * cos( angle + da ), r2 * sin( angle + da ), width * 0.5 ); |
|
glVertex3f( r2 * cos( angle + 2 * da ), r2 * sin( angle + 2 * da ), width * 0.5 ); |
|
glVertex3f( r1 * cos( angle + 3 * da ), r1 * sin( angle + 3 * da ), width * 0.5 ); |
|
r2 = minr2; |
|
} |
|
|
|
r2 = maxr2; |
|
|
|
glEnd(); |
|
|
|
glNormal3f( 0.0, 0.0, -1.0 ); |
|
|
|
/* draw back face */ |
|
glBegin( GL_QUAD_STRIP ); |
|
|
|
for( i = 0; i <= teeth; ++i ) |
|
{ |
|
angle = i * 2.0 * M_PI / teeth; |
|
glVertex3f( r1 * cos( angle ), r1 * sin( angle ), -width * 0.5 ); |
|
glVertex3f( r0 * cos( angle ), r0 * sin( angle ), -width * 0.5 ); |
|
|
|
if( i < teeth ) |
|
{ |
|
glVertex3f( r1 * cos( angle + 3 * da ), r1 * sin( angle + 3 * da ), -width * 0.5 ); |
|
glVertex3f( r0 * cos( angle ), r0 * sin( angle ), -width * 0.5 ); |
|
} |
|
} |
|
|
|
glEnd(); |
|
|
|
/* draw back sides of teeth */ |
|
glBegin( GL_QUADS ); |
|
da = 2.0 * M_PI / teeth / 4.0; |
|
|
|
for( i = 0; i < teeth; ++i ) |
|
{ |
|
angle = i * 2.0 * M_PI / teeth; |
|
|
|
glVertex3f( r1 * cos( angle + 3 * da ), r1 * sin( angle + 3 * da ), -width * 0.5 ); |
|
glVertex3f( r2 * cos( angle + 2 * da ), r2 * sin( angle + 2 * da ), -width * 0.5 ); |
|
glVertex3f( r2 * cos (angle + da), r2 * sin (angle + da), -width * 0.5 ); |
|
glVertex3f( r1 * cos (angle), r1 * sin (angle), -width * 0.5 ); |
|
r2 = minr2; |
|
} |
|
|
|
r2 = maxr2; |
|
|
|
glEnd(); |
|
|
|
/* draw outward faces of teeth */ |
|
glBegin( GL_QUAD_STRIP ); |
|
|
|
for( i = 0; i < teeth; ++i ) |
|
{ |
|
angle = i * 2.0 * M_PI / teeth; |
|
|
|
glVertex3f( r1 * cos( angle ), r1 * sin( angle ), width * 0.5 ); |
|
glVertex3f( r1 * cos( angle ), r1 * sin( angle ), -width * 0.5 ); |
|
u = r2 * cos( angle + da ) - r1 * cos( angle ); |
|
v = r2 * sin( angle + da ) - r1 * sin( angle ); |
|
len = sqrt( u * u + v * v ); |
|
u /= len; |
|
v /= len; |
|
glNormal3f( v, -u, 0.0 ); |
|
glVertex3f( r2 * cos( angle + da ), r2 * sin( angle + da ), width * 0.5 ); |
|
glVertex3f( r2 * cos( angle + da ), r2 * sin( angle + da ), -width * 0.5 ); |
|
glNormal3f( cos( angle + 1.5 * da ), sin( angle + 1.5 * da ), 0.0 ); |
|
glVertex3f( r2 * cos( angle + 2 * da ), r2 * sin( angle + 2 * da ), width * 0.5 ); |
|
glVertex3f( r2 * cos( angle + 2 * da ), r2 * sin( angle + 2 * da ), -width * 0.5 ); |
|
u = r1 * cos( angle + 3 * da ) - r2 * cos( angle + 2 * da ); |
|
v = r1 * sin( angle + 3 * da ) - r2 * sin( angle + 2 * da ); |
|
glNormal3f( v, -u, 0.0 ); |
|
glVertex3f( r1 * cos( angle + 3 * da ), r1 * sin( angle + 3 * da ), width * 0.5 ); |
|
glVertex3f( r1 * cos( angle + 3 * da ), r1 * sin( angle + 3 * da ), -width * 0.5 ); |
|
glNormal3f( cos( angle + 3.5 * da ), sin( angle + 3.5 * da ), 0.0 ); |
|
r2 = minr2; |
|
} |
|
|
|
r2 = maxr2; |
|
|
|
glVertex3f( r1 * cos( 0 ), r1 * sin( 0 ), width * 0.5 ); |
|
glVertex3f( r1 * cos( 0 ), r1 * sin( 0 ), -width * 0.5 ); |
|
|
|
glEnd(); |
|
|
|
glShadeModel( GL_SMOOTH ); |
|
|
|
/* draw inside radius cylinder */ |
|
glBegin( GL_QUAD_STRIP ); |
|
|
|
for( i = 0; i <= teeth; ++i ) |
|
{ |
|
angle = i * 2.0 * M_PI / teeth; |
|
glNormal3f( -cos( angle ), -sin( angle ), 0.0 ); |
|
glVertex3f( r0 * cos( angle ), r0 * sin( angle ), -width * 0.5 ); |
|
glVertex3f( r0 * cos( angle ), r0 * sin( angle ), width * 0.5 ); |
|
} |
|
glEnd(); |
|
} |
|
|
|
void GearsEffect::paintGears() |
|
{ |
|
static GLfloat white[4] = { 1.0, 1.0, 1.0, 1.0 }; |
|
QRect rect = effects->clientArea( FullArea, effects->activeScreen(), effects->currentDesktop() ); |
|
|
|
glPushMatrix(); |
|
// invert scale |
|
float fovy = 60.0f; |
|
float zNear = 0.1f; |
|
float ymax = zNear * tan( fovy * M_PI / 360.0f ); |
|
float ymin = -ymax; |
|
float xmin = ymin; |
|
float xmax = ymax; |
|
float scaleFactor = 1.1 * tan( fovy * M_PI / 360.0f )/ymax; |
|
glScalef( 1.0f/((xmax-xmin)*scaleFactor/displayWidth()), 1.0f/(-(ymax-ymin)*scaleFactor/displayHeight()), 1000.0f ); |
|
|
|
glPushAttrib( GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT ); |
|
|
|
glDisable( GL_BLEND ); |
|
|
|
glPushMatrix(); |
|
|
|
// content rotation requires depth test - so disabled |
|
// glRotatef( m_contentRotation, 0.0, 1.0, 0.0 ); |
|
|
|
glScalef( 0.05, 0.05, 0.05 ); |
|
|
|
glEnable( GL_NORMALIZE ); |
|
glEnable( GL_LIGHTING ); |
|
glEnable( GL_LIGHT1 ); |
|
glDisable( GL_COLOR_MATERIAL ); |
|
|
|
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); |
|
|
|
glPushMatrix(); |
|
glTranslatef( -3.0, -2.0, 0.0 ); |
|
glRotatef( m_angle, 0.0, 0.0, 1.0 ); |
|
glCallList( m_gear1 ); |
|
glPopMatrix(); |
|
|
|
glPushMatrix(); |
|
glTranslatef( 3.1, -2.0, 0.0 ); |
|
glRotatef( -2.0 * m_angle - 9.0, 0.0, 0.0, 1.0 ); |
|
glCallList( m_gear2 ); |
|
glPopMatrix(); |
|
|
|
glPushMatrix(); |
|
glTranslatef( -3.1, 4.2, 0.0 ); |
|
glRotatef( -2.0 * m_angle - 25.0, 0.0, 0.0, 1.0 ); |
|
glCallList( m_gear3 ); |
|
glPopMatrix(); |
|
|
|
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white ); |
|
|
|
glPopMatrix(); |
|
|
|
glDisable( GL_LIGHT1 ); |
|
glDisable( GL_NORMALIZE ); |
|
glEnable( GL_COLOR_MATERIAL ); |
|
|
|
glDisable( GL_LIGHTING ); |
|
|
|
glPopMatrix(); |
|
glPopAttrib(); |
|
} |
|
|
|
void GearsEffect::initGears() |
|
{ |
|
static GLfloat pos[4] = { 5.0f, 5.0f, 10.0f, 0.0f }; |
|
static GLfloat red[4] = { 0.8f, 0.1f, 0.0f, 1.0f }; |
|
static GLfloat green[4] = { 0.0f, 0.8f, 0.2f, 1.0f }; |
|
static GLfloat blue[4] = { 0.2f, 0.2f, 1.0f, 1.0f }; |
|
static GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 0.3f }; |
|
static GLfloat diffuseLight[] = { 0.5f, 0.5f, 0.5f, 0.5f }; |
|
|
|
glLightfv( GL_LIGHT1, GL_AMBIENT, ambientLight ); |
|
glLightfv( GL_LIGHT1, GL_DIFFUSE, diffuseLight ); |
|
glLightfv( GL_LIGHT1, GL_POSITION, pos ); |
|
|
|
m_gear1 = glGenLists( 1 ); |
|
glNewList( m_gear1, GL_COMPILE ); |
|
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red ); |
|
gear( 1.0f, 4.0f, 1.0f, 20, 0.7f ); |
|
glEndList(); |
|
|
|
m_gear2 = glGenLists( 1 ); |
|
glNewList( m_gear2, GL_COMPILE ); |
|
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green ); |
|
gear( 0.5f, 2.0f, 2.0f, 10, 0.7f ); |
|
glEndList(); |
|
|
|
m_gear3 = glGenLists( 1 ); |
|
glNewList( m_gear3, GL_COMPILE ); |
|
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue ); |
|
gear( 1.3f, 2.0f, 0.5f, 10, 0.7f ); |
|
glEndList(); |
|
} |
|
|
|
void GearsEffect::endGears() |
|
{ |
|
glDeleteLists( m_gear1, 1 ); |
|
glDeleteLists( m_gear2, 1 ); |
|
glDeleteLists( m_gear3, 1 ); |
|
} |
|
|
|
} // namespace
|
|
|