File indexing completed on 2025-01-05 04:25:24

0001 /****************************************************************************************
0002  * Copyright (c) 2007 Mark Kretschmann <kretschmann@kde.org>                            *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #define DEBUG_PREFIX "CoverBling"
0018 
0019 #include "CoverBling.h"
0020 
0021 #include "core/support/Debug.h"
0022 #include "core-impl/collections/support/CollectionManager.h"
0023 #include "core/meta/Meta.h"
0024 
0025 #include <math.h>
0026 #ifdef Q_WS_MAC
0027 #include <OpenGL/glext.h>
0028 #else
0029 #include <GL/glext.h>
0030 #endif
0031 #include <QGLFormat>
0032 #include <QGLWidget>
0033 #include <QTimer>
0034 
0035 #include <climits>
0036 
0037 #define TEXTURE_SIZE QSize( 256, 256 )
0038 
0039 
0040 CoverBling::CoverBling( QWidget* parent )
0041         : QGLWidget( QGLFormat(QGL::DepthBuffer|QGL::SampleBuffers|QGL::AlphaChannel|QGL::DoubleBuffer), parent )
0042         , m_xOffset( 0.0 )
0043         , m_zOffset( M_PI / 2 )
0044 {
0045     DEBUG_BLOCK
0046 
0047     setFixedHeight( 200 );
0048 
0049     Collections::Collection *coll = CollectionManager::instance()->primaryCollection();
0050     QueryMaker *qm = coll->queryMaker();
0051     qm->setQueryType( QueryMaker::Album );
0052     qm->limitMaxResultSize( 10 );
0053 
0054     connect( qm, SIGNAL(newResultReady(Meta::AlbumList)), this, SLOT(queryResult(Meta::AlbumList)) );
0055 
0056     qm->run();
0057 }
0058 
0059 void
0060 CoverBling::queryResult( Meta::AlbumList albums )
0061 {
0062     foreach( Meta::AlbumPtr album, albums )
0063         m_covers << album->image();
0064 
0065     QTimer* timer = new QTimer( this );
0066     connect( timer, SIGNAL(timeout()), this, SLOT(updateGL()) );
0067     timer->start( 20 ); //50fps
0068 }
0069 
0070 void
0071 CoverBling::initializeGL() //reimplemented
0072 {
0073     DEBUG_BLOCK
0074 
0075     //generate all textures
0076     foreach( const QPixmap &p, m_covers ) {
0077         QImage image = p.toImage();
0078         image = image.scaled( TEXTURE_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
0079         m_textureIds << bindTexture( image );
0080     }
0081 
0082     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
0083     glShadeModel(GL_SMOOTH); 
0084     qglClearColor( Qt::black );
0085     glEnable( GL_MULTISAMPLE ); //enable anti aliasing
0086     glEnable( GL_DEPTH_TEST );
0087     glDepthMask( true );
0088  
0089     //Display list for drawing a textured rectangle
0090     m_texturedRectList = glGenLists( 1 );
0091     glNewList( m_texturedRectList, GL_COMPILE );
0092         glBegin (GL_QUADS);
0093             glTexCoord2f (0.0, 0.0);
0094             glColor3f( 1.0, 1.0, 1.0 );
0095             glVertex3f (-1.0, -1.0, -1.0);
0096             glTexCoord2f (1.0, 0.0);
0097             glColor3f( 0.1, 0.1, 0.1 );
0098             glVertex3f (1.0, -1.0, -1.0);
0099             glTexCoord2f (1.0, 1.0);
0100             glColor3f( 0.1, 0.1, 0.1 );
0101             glVertex3f (1.0, 1.0, -1.0);
0102             glTexCoord2f (0.0, 1.0);
0103             glColor3f( 1.0, 1.0, 1.0 );
0104             glVertex3f (-1.0, 1.0, -1.0);
0105         glEnd ();
0106         //glDisable( GL_DEPTH_TEST );
0107     glEndList();
0108 
0109     //Display list for drawing reflection of the textured rectangle
0110     m_texturedRectReflectedList = glGenLists( 1 );
0111     glNewList( m_texturedRectReflectedList, GL_COMPILE );
0112         glTranslatef( 0.0, -2.0, 0.0 );
0113         glScalef( 1.0, -1.0, 1.0 );
0114 
0115         glEnable( GL_BLEND );
0116         //glBlendFunc( GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR );
0117         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
0118 
0119         glBegin (GL_QUADS);
0120             glTexCoord2f (0.0, 0.0);
0121             glColor4f( 1.0, 1.0, 1.0, 0.3 );
0122             glVertex3f (-1.0, -1.0, -1.0);
0123             glColor4f( 1.0, 1.0, 1.0, 0.3 - 0.15 );
0124             glTexCoord2f (1.0, 0.0);
0125             glVertex3f (1.0, -1.0, -1.0);
0126             glColor4f( 1.0, 1.0, 1.0, 0.02 - 0.15 );
0127             glTexCoord2f (1.0, 1.0);
0128             glVertex3f (1.0, 1.0, -1.0);
0129             glColor4f( 1.0, 1.0, 1.0, 0.02 );
0130             glTexCoord2f (0.0, 1.0);
0131             glVertex3f (-1.0, 1.0, -1.0);
0132         glEnd ();
0133 
0134         glDisable( GL_BLEND );
0135     glEndList();
0136 }
0137 
0138 void
0139 CoverBling::resizeGL( int width, int height ) //reimplemented
0140 {
0141     DEBUG_BLOCK
0142 
0143     glViewport( 0, 0, (GLint)width, (GLint)height );
0144     glMatrixMode(GL_PROJECTION);
0145     glLoadIdentity();
0146     //glFrustum( -0.5f, 0.5f, -0.5f, 0.5f, 0.3f, 4.5f );
0147     setPerspective();
0148     glMatrixMode(GL_MODELVIEW);
0149 }
0150 
0151 void
0152 CoverBling::setPerspective()
0153 {
0154     gluPerspective( 30, (double)width() / height(), 1.0, 20.0 );
0155 }
0156 
0157 void
0158 CoverBling::paintGL() //reimplemented
0159 {
0160     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
0161 
0162     const QPoint mousePos = mapFromGlobal( QCursor::pos() );
0163     draw( objectAtPosition( mousePos ) );
0164 }
0165 
0166 void
0167 CoverBling::draw( GLuint selected )
0168 {
0169     GLuint objectName = 1;
0170 
0171     glMatrixMode( GL_MODELVIEW );
0172     glLoadIdentity();
0173     glRotatef( 10, 1.0, 0.0, 0.0 ); //Rotate whole scene around X axis; simulates camera tilt
0174     glScalef( 1.0, 1.0, 6.0 );
0175 
0176     //draw the ground
0177     //glBegin( GL_POLYGON );
0178     //    glColor3f( 0.0, 0.0, 0.5 );
0179     //    glVertex3f (-3.0, -1.0, -2.0);
0180     //    glColor3f( 1.0, 0.0, 0.5 );
0181     //    glVertex3f (3.0, -1.0, -2.0);
0182     //    glColor3f( 0.0, 1.0, 0.5 );
0183     //    glVertex3f (3.0, -1.0, 2.0);
0184     //    glColor3f( 0.0, 0.0, 1.5 );
0185     //    glVertex3f (-3.0, -1.0, 2.0);
0186     //glEnd();
0187 
0188     glColor3f( 1.0, 1.0, 1.0 ); //reset color
0189     glEnable( GL_TEXTURE_2D);
0190 
0191     float xoffset = -5.5;
0192     float yoffset = -0.6;
0193     float zoffset = -1.1;
0194 
0195     foreach( GLuint id, m_textureIds ) { // krazy:exclude=foreach
0196         glBindTexture( GL_TEXTURE_2D, id );
0197         glPushMatrix();
0198             //const float xsin = sin( xoffset );
0199             //const float zsin = sin( zoffset );
0200             xoffset += 1.0;
0201             zoffset += 0.1;
0202             glTranslatef( xoffset, yoffset, zoffset );
0203             glRotatef( 8, 0.0, 1.0, 0.0 );
0204 
0205             //draw the cover
0206             if( objectName == selected )
0207                 glColor3f( 1.0, 0.0, 0.0 );
0208             glLoadName( objectName++ );
0209             glCallList( m_texturedRectList );
0210             glColor4f( 1.0, 1.0, 1.0, 1.0 );
0211 
0212             //draw reflection on the ground
0213             glLoadName( 0 );
0214             glPushMatrix();
0215                 glCallList( m_texturedRectReflectedList );
0216             glPopMatrix();
0217         glPopMatrix();
0218         glColor4f( 1.0, 1.0, 1.0, 1.0 );
0219     }
0220 
0221     glDisable( GL_TEXTURE_2D);
0222 }
0223 
0224 GLuint
0225 CoverBling::objectAtPosition( const QPoint& pos )
0226 {
0227     // this is the same as in every OpenGL picking example
0228     const int MaxSize = 512; // see below for an explanation on the buffer content
0229     GLuint buffer[MaxSize];
0230     GLint viewport[4];
0231 
0232     glGetIntegerv(GL_VIEWPORT, viewport);
0233     glSelectBuffer(MaxSize, buffer);
0234     // enter select mode
0235     glRenderMode(GL_SELECT);
0236 
0237     glInitNames();
0238     glPushName(0);
0239 
0240     glMatrixMode(GL_PROJECTION);
0241     glPushMatrix();
0242         glLoadIdentity();
0243         gluPickMatrix((GLdouble)pos.x(), (GLdouble)(viewport[3] - pos.y()), 5.0, 5.0, viewport);
0244         setPerspective();
0245         draw();
0246         glMatrixMode(GL_PROJECTION);
0247     glPopMatrix();
0248 
0249     const int hits = glRenderMode( GL_RENDER );
0250     if ( !hits )
0251         return 0;
0252 
0253     //determine object with the lowest Z value
0254     uint hitZValue = UINT_MAX;
0255     uint hit       = UINT_MAX;
0256     for( int i = 0; i < hits; i++ ) { 
0257         if( buffer[(i*4)+1] < hitZValue ) { 
0258             hit       = buffer[(i*4)+3];
0259             hitZValue = buffer[(i*4)+1];
0260         }
0261     }
0262     
0263     // return the name of the clicked surface
0264     return hit;
0265 }
0266 
0267 
0268