kwin/effects/_test/gears.cpp
Martin Gräßlin 1ae6878e76 Providing a way to render something inside the cube. Added as an example the glxgears to the test effects.
svn path=/trunk/KDE/kdebase/workspace/; revision=1038868
2009-10-22 07:06:44 +00:00

354 lines
10 KiB
C++

/********************************************************************
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