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