File indexing completed on 2024-04-28 07:54:41

0001 /*
0002     SPDX-FileCopyrightText: 2008 Ian Wadham <iandw.au@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 // Local includes
0008 #include "gameglview.h"
0009 
0010 // Qt includes
0011 #include <QOpenGLTexture>
0012 #include <QDir>
0013 #include <QImage>
0014 #include <QPainter>
0015 #include <QPoint>
0016 #include <QStandardPaths>
0017 #include <QStringList>
0018 #include <QSvgRenderer>
0019 
0020 #include "kubrick_debug.h"
0021 // C++ includes
0022 #include <iostream>
0023 
0024 GameGLView::GameGLView(Game * g, QWidget * parent)
0025             : QOpenGLWidget(parent),
0026               bgColor (QColor (0, 0, 35))
0027 {
0028     // Save a pointer to the Game object that controls everything.
0029     game = g;
0030 
0031     this->setMinimumSize (450, 300);
0032 
0033     // Set the amount of bevelling on a cubie's edge to its default value.
0034     bevelAmount = 0.125;
0035 
0036     // Set colors to full intensity (no blinking).
0037     blinkIntensity = 1.0;
0038 
0039     // Note: Do not use OpenGL functions here.
0040     //       Initialize OpenGL in initializeGL() instead!
0041 
0042     const GLubyte * v = glGetString(GL_VERSION);
0043     printf ("GL Version %s\n", v);
0044 }
0045 
0046 
0047 void GameGLView::initializeGL()
0048 {
0049     // Look for themes in files "---/share/apps/kubrick/themes/*.desktop".
0050     // IDW - This is temporary code for KDE 4.1. Do themes properly in KDE 4.2.
0051     QStringList themeFilepaths;
0052     const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::AppDataLocation, QStringLiteral("themes"), QStandardPaths::LocateDirectory);
0053     for (const QString& dir : dirs) {
0054         const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.svgz"));  // Find files.
0055         for (const QString& file : fileNames) {
0056             themeFilepaths.append(dir + QLatin1Char('/') + file);
0057         }
0058     }
0059     if (! themeFilepaths.isEmpty()) {
0060     backgroundType = PICTURE;   // Use a picture for the background.
0061     loadBackground (themeFilepaths.first());
0062     }
0063     else {
0064     backgroundType = NO_LOAD;   // Use a 4-way color gradient.
0065     }
0066 
0067     // Make glClear() clear to a deep-blue background.
0068     glClearColor(bgColor.redF(), bgColor.greenF(), bgColor.blueF(), bgColor.alphaF());
0069 
0070     // Disable dithering which is usually not needed.
0071     glDisable(GL_DITHER);
0072 
0073     // Set up fixed lighting.
0074     glMatrixMode(GL_MODELVIEW);
0075     glLoadIdentity();
0076     turnOnLighting();
0077 }
0078 
0079 
0080 // IDW - Key K for switching the background (temporary) - FIX IT FOR KDE 4.2.
0081 void GameGLView::changeBackground()
0082 {
0083     if (backgroundType != NO_LOAD) {
0084     backgroundType = (backgroundType == PICTURE) ? GRADIENT : PICTURE;
0085     }
0086 }
0087 
0088 
0089 void GameGLView::loadBackground (const QString & filepath)
0090 {
0091     // NOTE: Size 1024 gave a significantly sharper picture, compared to 512.
0092     int bgTextureSize = 1024;       // Size of background texture.
0093     QImage tex (bgTextureSize, bgTextureSize, QImage::Format_ARGB32);
0094     tex.fill (bgColor.rgba());
0095 
0096     QString bg (QStringLiteral("background"));
0097     GLdouble bgWidth  = bgTextureSize;
0098     GLdouble bgHeight = bgTextureSize;
0099     bgAspect = 1.0;
0100 
0101     QSvgRenderer svg;
0102     svg.load (filepath);
0103 
0104     if (svg.isValid()) {
0105     QRectF r = svg.boundsOnElement (bg);
0106 
0107     bgAspect = r.width() / r.height();
0108     bool landscape = (bgAspect >= 1.0);
0109 
0110     bgWidth  = landscape ? bgTextureSize : bgTextureSize * bgAspect;
0111     bgHeight = landscape ? bgTextureSize / bgAspect : bgTextureSize;
0112 
0113     // Render the drawing at the bottom left of the texture's QImage.
0114     QRectF bounds (0, bgTextureSize - bgHeight, bgWidth, bgHeight);
0115     QPainter p;
0116     p.begin (&tex);
0117     svg.render (&p, bg, bounds);
0118     p.end();
0119     }
0120     else {
0121     backgroundType = NO_LOAD;   // Use a 4-way color gradient.
0122     }
0123 
0124     bgTexture.reset(new QOpenGLTexture(tex.mirrored()));
0125     txWidth  = bgWidth  / (GLfloat) bgTextureSize;
0126     txHeight = bgHeight / (GLfloat) bgTextureSize;
0127 }
0128 
0129 
0130 void GameGLView::resizeGL(int w, int h)
0131 {
0132     // Make use of the whole view.
0133     glViewport (0, 0, w, h);
0134     glAspect = (GLdouble) w / (GLdouble) h;
0135 
0136     // Set the perspective projection.
0137     glMatrixMode (GL_PROJECTION);
0138     glLoadIdentity();
0139     gluPerspective (viewAngle, glAspect, minZ, maxZ);
0140     glMatrixMode (GL_MODELVIEW);
0141 
0142     // Calculate the depth and size of the background rectangle.
0143     bgRectZ = 2.0 * cubeCentreZ;
0144     bgRectY = -bgRectZ * tan (3.14159 * viewAngle / 360.0);
0145     bgRectX = glAspect * bgRectY;
0146 
0147     if (backgroundType == PICTURE) {
0148     // Make the aspect ratio the same as for the original SVG picture.
0149     if (glAspect > bgAspect) {
0150         // Fit background to full width: OpenGL will trim top and bottom.
0151         bgRectY = bgRectX / bgAspect;   // Stretch the height.
0152     }
0153     else {
0154         // Fit background to full height: OpenGL will trim left and right.
0155         bgRectX = bgRectY * bgAspect;   // Stretch the width.
0156     }
0157     }
0158 
0159     // Re-position the view-labels.
0160     game->setSceneLabels();
0161 }
0162 
0163 
0164 float GameGLView::colors [7] [3] = {
0165     {0.2, 0.2, 0.2},    // Dark grey.
0166     {0.7, 0.0, 0.0},    // Red.
0167     {1.0, 0.5, 0.1},    // Orange.
0168     {0.0, 0.0, 0.8},    // Blue.
0169     {0.0, 0.5, 0.0},    // Green.
0170     {1.0, 1.0, 0.0},    // Yellow.
0171     {0.9, 0.9, 0.8}     // Off-white.
0172     };
0173 
0174 
0175 void GameGLView::paintGL()
0176 {
0177     // Clear the view.
0178     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
0179 
0180     // Reset the modelview matrix.  By doing so we also reset the "camera" that
0181     // is the eye position, so that it is now at (0,0,0), which is also the
0182     // center of the screen.  We are looking down the negative Z axis, towards
0183     // (0,0,-1), with "up" being at (0,1,0).
0184     glLoadIdentity();
0185     glEnable (GL_DEPTH_TEST);
0186 
0187     if (checkGLError()) {
0188     std::cerr << "OpenGL error detected before drawScene()" << std::endl;
0189     }
0190 
0191     // Draw the background.
0192     glDisable (GL_LIGHTING);
0193     switch (backgroundType) {
0194     case PICTURE:
0195     drawPictureBackground();
0196     break;
0197     case GRADIENT:
0198     case NO_LOAD:
0199     draw4WayGradientBackground();
0200     break;
0201     }
0202     glEnable (GL_LIGHTING);
0203 
0204     // Draw the cube(s).
0205     game->drawScene ();
0206 
0207     if (checkGLError()) {
0208     std::cerr << "OpenGL error detected after drawScene()" << std::endl;
0209     }
0210 }
0211 
0212 
0213 void GameGLView::drawPictureBackground()
0214 {
0215     glEnable (GL_TEXTURE_2D);
0216     glBindTexture (GL_TEXTURE_2D, bgTexture->textureId());
0217 
0218     // Draw the background picture behind the cubes, filling the view.
0219     glBegin (GL_QUADS);
0220     glTexCoord2f (0.0,     0.0);
0221     glVertex3f   (-bgRectX, -bgRectY, bgRectZ);
0222 
0223     glTexCoord2f (txWidth, 0.0);
0224     glVertex3f   ( bgRectX, -bgRectY, bgRectZ);
0225 
0226     glTexCoord2f (txWidth, txHeight);
0227     glVertex3f   ( bgRectX,  bgRectY, bgRectZ);
0228 
0229     glTexCoord2f (0.0,     txHeight);
0230     glVertex3f   (-bgRectX,  bgRectY, bgRectZ);
0231     glEnd();
0232 
0233     glDisable (GL_TEXTURE_2D);
0234 }
0235 
0236 
0237 void GameGLView::draw4WayGradientBackground()
0238 {
0239     glShadeModel (GL_SMOOTH);
0240 
0241     // Draw the 4-way color-gradient behind the cubes, filling the view.
0242     glBegin(GL_QUADS);
0243     glColor3f (0.0, 0.0, 0.5);
0244     glVertex3f   (-bgRectX, -bgRectY, bgRectZ);
0245 
0246     glColor3f (0.8, 0.3, 0.6);
0247     glVertex3f   ( bgRectX, -bgRectY, bgRectZ);
0248 
0249     glColor3f (0.5, 0.8, 1.0);
0250     glVertex3f   ( bgRectX,  bgRectY, bgRectZ);
0251 
0252     glColor3f (0.2, 0.2, 0.9);
0253     glVertex3f   (-bgRectX,  bgRectY, bgRectZ);
0254     glEnd();
0255 
0256     glShadeModel (GL_FLAT);
0257 }
0258 
0259 
0260 void GameGLView::dumpExtensions()
0261 {
0262     // OpenGL Extension detection.
0263     QString s = QLatin1String(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)))
0264         + QLatin1Char(' ')
0265         + QLatin1String(reinterpret_cast<const char*>(gluGetString(GLU_EXTENSIONS)));
0266     QStringList extensions = s.split (QLatin1Char(' '), Qt::SkipEmptyParts);
0267     for (int i = 0; i < extensions.count(); i++)
0268     {
0269     std::cout << extensions[i].toLatin1().data() << std::endl;
0270     }
0271 }
0272 
0273 static float ambient[] = {0.0, 0.0, 0.0, 1.0};
0274 static float diffuse[] = {1.0, 1.0, 1.0, 1.0};
0275 
0276 // Directional light, at infinity (parameter 4, w=0.0), shining
0277 // towards -Z.  No attenuation.  Diffuse, no spotlight effect.
0278 static float position0[] = {0.0, 0.0, 1.0, 0.0};
0279 
0280 // With lights off, 100% ambient gives a flat, dull, fairly well-lit picture.
0281 // With lights on, it makes little difference to specular effect, but makes
0282 // the strong colors of stickers look a bit washed out.  So choose 60%.
0283 static float lmodel_ambient[] = {0.6, 0.6, 0.6, 1.0};
0284 
0285 // Controls SPREAD of specular reflections (128.0 = small highlight).
0286 static float material_shininess = 60.0;
0287 
0288 // Controls intensity and color of specular reflections.
0289 static float material_specular[] = {0.5, 0.6, 0.5, 1.0};
0290 
0291 // Trying to light the insides of the cubies is a waste of time.
0292 static float lmodel_twoside[] = {GL_FALSE};
0293 
0294 void GameGLView::turnOnLighting ()
0295 {
0296     // There is just one light.
0297     glLightfv (GL_LIGHT0, GL_AMBIENT, ambient);
0298     glLightfv (GL_LIGHT0, GL_DIFFUSE, diffuse);
0299     glLightfv (GL_LIGHT0, GL_POSITION, position0);
0300 
0301     glLightModelfv (GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
0302     glLightModelfv (GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
0303 
0304     // This gives a rolling-sheen effect to the specularity.
0305     // Not all stickers on a face light up at once.
0306     glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
0307 
0308     glEnable (GL_LIGHTING);
0309     glEnable (GL_LIGHT0);
0310 
0311     glEnable (GL_DEPTH_TEST);
0312     glEnable (GL_NORMALIZE);
0313 
0314     // Do not render the backs (interiors) of cubie and sticker faces. The
0315     // "front" faces are those for which the order of drawing of the vertices
0316     // is anti-clockwise, as seen from the outside looking towards the centre.
0317     glEnable (GL_CULL_FACE);
0318 
0319     glShadeModel (GL_FLAT);
0320     glMaterialf  (GL_FRONT, GL_SHININESS, material_shininess);
0321     glMaterialfv (GL_FRONT, GL_SPECULAR,  material_specular);
0322 
0323     // This tracks color CHANGES and updates the corresponding glMaterial*.
0324     glEnable (GL_COLOR_MATERIAL);
0325     glColorMaterial (GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
0326 }
0327 
0328 
0329 QPoint GameGLView::getMousePosition ()
0330 {
0331     QPoint p;
0332     p = mapFromGlobal (QCursor::pos()); // Convert to window co-ordinates.
0333 
0334     // Convert Y co-ordinate to OpenGL convention (zero at bottom of window).
0335     p.setY (height() - p.y());
0336     return p;
0337 }
0338 
0339 
0340 void GameGLView::pushGLMatrix ()
0341 {
0342     glPushMatrix();
0343 }
0344 
0345 
0346 void GameGLView::moveGLView (float xChange, float yChange, float zChange)
0347 {
0348     glTranslatef (xChange, yChange, zChange);
0349 }
0350 
0351 
0352 void GameGLView::rotateGLView (float degrees, float x, float y, float z)
0353 {
0354     glRotatef (degrees, x, y, z);
0355 }
0356 
0357 
0358 void GameGLView::popGLMatrix ()
0359 {
0360     glPopMatrix();
0361 }
0362 
0363 
0364 void GameGLView::setBevelAmount (int bevelPerCent)
0365 {
0366     bevelAmount = ((float) bevelPerCent)/100.0;
0367 }
0368 
0369 
0370 void GameGLView::drawACubie (float size, float centre[], int axis, int angle)
0371 {
0372     float lenA = 0.5 * size;        // Half of a cubie's outside dimension.
0373     float bevel = bevelAmount * lenA;   // The size of the bevel at the edges.
0374     float lenB = lenA - bevel;      // Half of a face's inside dimension.
0375 
0376     float p[nAxes];         // The point to be drawn currently.
0377     float normal[nAxes];        // The current normal vector (used in lighting).
0378                 // Needs to be of length 1 for best results.
0379     float r2 = 0.7071067;   // (1 / sqrt (2.0)), used for bevel normals.
0380     float r3 = 0.5773502;   // (1 / sqrt (3.0)), used for corner normals.
0381 
0382     // If the cubie is moving, rotate it around the required axis of the cube.
0383     if (angle != 0) {
0384     GLfloat v [nAxes] = {0.0, 0.0, 0.0};
0385     v [axis] = 1.0;
0386     glPushMatrix();
0387     glRotatef ((GLfloat) (-angle), v[0], v[1], v[2]);
0388     }
0389 
0390     glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT);
0391     glPushMatrix();
0392 
0393     glColor3fv (colors [0]);    // The base color of a cubie, without stickers.
0394 
0395     // Bring the centre to the origin during drawing.
0396     glTranslatef ((GLfloat) centre[X],
0397           (GLfloat) centre[Y],
0398           (GLfloat) centre[Z]);
0399 
0400     // Draw three pairs of faces of the cubie and twelve bevelled edges.
0401     glBegin(GL_QUADS);
0402     LOOP (axis, 3) {
0403 
0404     // The coordinate on the axis thru the face does not change, but we must
0405     // work out what the other two coordinates are, in cyclical order: i.e.
0406     //         X-axis (0) --> Y,Z (coordinates 1 and 2 change),
0407     //         Y-axis (1) --> Z,X (coordinates 2 and 0 change),
0408     //         Z-axis (2) --> X,Y (coordinates 0 and 1 change). 
0409     //
0410         int coord1 = 0;
0411         int coord2 = 0;
0412 
0413     // Draw two opposite faces of the cubie and two bevelled edges each.
0414     LOOP (face, 2) {
0415 
0416         // Draw one face of the cubie.
0417         // For (i,j) = (0,0), (0,1), (1,0) and (1,1), we will get values
0418         //     (i,k) = (0,0), (0,1), (1,1) and (1,0) and will be drawing
0419         // vertices going around a square face of the cubie.
0420 
0421         normal[coord1] = 0.0;
0422         normal[coord2] = 0.0;
0423         normal[axis] = (2*face -1) * 1.0;   // -1.0 or +1.0.
0424         glNormal3fv (normal);       // Used by lighting.
0425 
0426         p[axis] = (2*face-1) * lenA;    // Value -lenA or +lenA.
0427         // The axes are chosen so that the vertices go in "GL front face"
0428         // order (ie. anti-clockwise), as viewed from outside the cubie.
0429         if (p[axis] > 0.0) {
0430         coord1 = (axis + 2) % 3;
0431         coord2 = (axis + 1) % 3;
0432         }
0433         else {
0434         coord1 = (axis + 1) % 3;
0435         coord2 = (axis + 2) % 3;
0436         }
0437 
0438         LOOP (i, 2) {
0439         p[coord1] = (2*i-1) * lenB; // Value -lenB or +lenB.
0440         LOOP (j, 2) {
0441             int k = (i + j) % 2;    // Takes values 0 1 1 0.
0442             p[coord2] = (2*k-1) * lenB; // Value -lenB or +lenB.
0443             glVertex3fv (p);        // Draw one of 4 vertices.
0444         }
0445         }
0446 
0447         // Draw two of this face's bevelled edges.
0448         // Eventually, for 6 faces, all 12 edges will have been drawn.
0449         coord1 = (axis + 1) % 3;
0450         coord2 = (axis + 2) % 3;
0451         normal[axis] = (2*face -1) * r2;
0452         LOOP (edge, 2) {
0453         normal[coord1] = (2*edge -1) * r2;
0454         normal[coord2] = 0.0;
0455         glNormal3fv (normal);       // Used by lighting.
0456 
0457         LOOP (i, 2) {
0458             p[axis]   = (2*face-1) * (lenA - ((edge + i)%2) * bevel);
0459             p[coord1] = (2*edge-1) * lenB + (edge - i) * bevel;
0460             LOOP (j, 2) {
0461             int k = (i + j) % 2;    // Takes values 0 1 1 0.
0462             // p[coord2] = -lenB, +lenB, +lenB, -lenB on the + face
0463             //       and = +lenB, -lenB, -lenB, +lenB on the - face,
0464             // thus ensuring anti-clockwise drawing of all 4 bevels
0465             // as you view each face from the outside looking in.
0466             p[coord2] = (2*face -1) * (2*k-1) * lenB;
0467             glVertex3fv (p);    // Draw 1 of 4 vertices.
0468             }
0469         }
0470         } // END (edge, 2)
0471 
0472     } // END (face, 2)
0473 
0474     } // END (axis, 3)
0475 
0476     glEnd();
0477 
0478     // Draw the 8 chiselled corners on the back and front faces of the cubie.
0479     glBegin(GL_TRIANGLES);
0480     LOOP (face, 2) {
0481     float z = ((float) 2*face-1);       // Z direction: +r3 or -r3.
0482     LOOP (i, 2) {
0483         float x = ((float) 2*i-1);      // X direction: +r3 or -r3.
0484         LOOP (j, 2) {
0485         float y = ((float) 2*j-1);  // Y direction: +r3 or -r3.
0486 
0487         glNormal3f (x*r3, y*r3, z*r3);  // Used by lighting.
0488 
0489         // Draw the triangular facet at this corner of the face.
0490         // The vertices must go in "GL front face" order (ie. anti-
0491         // clockwise), as viewed from outside the cubie.
0492 
0493         if ((x * y * z) > 0.0) {
0494             // If 0 or 2 negatives, go round the vertices one way.
0495             glVertex3f (x*lenA, y*lenB, z*lenB);    // A
0496             glVertex3f (x*lenB, y*lenA, z*lenB);    // B
0497             glVertex3f (x*lenB, y*lenB, z*lenA);    // C
0498         }
0499         else {
0500             // If 1 or 3 negatives, go round the vertices the other way.
0501             glVertex3f (x*lenA, y*lenB, z*lenB);    // A
0502             glVertex3f (x*lenB, y*lenB, z*lenA);    // C
0503             glVertex3f (x*lenB, y*lenA, z*lenB);    // B
0504         }
0505         }
0506     }
0507     } // END (face, 2)
0508 
0509     glEnd();
0510 
0511     glPopAttrib();
0512     glPopMatrix();
0513     checkGLError();
0514 }
0515 
0516 
0517 void GameGLView::finishCubie ()
0518 {
0519     // If the cubie just drawn is moving, restore the OpenGL co-ordinate axes.
0520     glPopMatrix();
0521 }
0522 
0523 
0524 void GameGLView::drawASticker (float size, int color, bool blinking,
0525                    int faceNormal[], float faceCentre [])
0526 {
0527     float lenA = 0.5   * size;      // Half of a cubie's outside dimension.
0528     float bevel = bevelAmount * lenA;   // The size of the bevel at the edges.
0529     float lenB = lenA - bevel;      // Half the sticker's dimension.
0530 
0531     float p[nAxes];         // The point to be drawn currently.
0532     float normal[nAxes];        // The normal vector (used in lighting).
0533 
0534     int axis1 = 0, axis2 = 1;       // Two axes in the plane of the sticker.
0535 
0536     float mColor [3];
0537 
0538     glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT);
0539     glPushMatrix();
0540 
0541     // Set the color of this sticker.
0542     if (blinking) {
0543     LOOP (i, 3) {
0544         mColor [i] = blinkIntensity * colors [color] [i];
0545     }
0546     glColor3fv (mColor);        // Dimmed color.
0547     }
0548     else {
0549     glColor3fv (colors [color]);    // Normal color.
0550     }
0551 
0552     // Bring the centre of the sticker to the origin during drawing.
0553     glTranslatef ((GLfloat) faceCentre[X],
0554                   (GLfloat) faceCentre[Y],
0555                   (GLfloat) faceCentre[Z]);
0556 
0557     LOOP (axis, 3) {
0558     normal [axis] = 0.0;
0559     if (faceNormal [axis] != 0) {
0560         // One component of the faceNormal vector is 1: the others are zero.
0561         normal [axis] = (float) faceNormal [axis];
0562 
0563         // The sticker is offset from the cubie's face, along the normal.
0564         p [axis] = 0.01 * size * normal [axis];
0565 
0566         // The coordinate on the normal does not change, but we must work
0567         // out what the other two coordinates are, in cyclical order: i.e.
0568         //         X-axis (0) --> Y,Z (coordinates 1 and 2 change),
0569         //         Y-axis (1) --> Z,X (coordinates 2 and 0 change),
0570         //         Z-axis (2) --> X,Y (coordinates 0 and 1 change). 
0571         //
0572         // Ensure that the outside face of the sticker is drawn in
0573         // anti-clockwise sequence, so GL_CULL_FACE culls the inside one.
0574 
0575         if (faceNormal [axis] > 0) {
0576         axis1 = (axis + 1) % 3;
0577         axis2 = (axis + 2) % 3;
0578         }
0579         else {
0580         axis2 = (axis + 1) % 3;
0581         axis1 = (axis + 2) % 3;
0582         }
0583     }
0584     }
0585 
0586     glBegin(GL_QUADS);
0587     glNormal3fv (normal);   // Used by lighting.
0588 
0589     p [axis1] = + lenB;     // Set the first vertex of the sticker.
0590     p [axis2] = + lenB;
0591     glVertex3fv (p);        // Draw the first vertex,  eg. (+X,+Y) quadrant.
0592     p [axis1] = - lenB;
0593     glVertex3fv (p);        // Draw the second vertex, eg. (+X,-Y) quadrant.
0594     p [axis2] = - lenB;
0595     glVertex3fv (p);        // Draw the third vertex,  eg. (-X,-Y) quadrant.
0596     p [axis1] = + lenB;
0597     glVertex3fv (p);        // Draw the fourth vertex, eg. (+X,-Y) quadrant.
0598 
0599     glEnd();
0600 
0601     glPopAttrib();
0602     glPopMatrix();
0603     checkGLError();
0604 }
0605 
0606 
0607 void GameGLView::setBlinkIntensity (float intensity)
0608 {
0609     blinkIntensity = intensity;
0610 }
0611 
0612 
0613 bool GameGLView::checkGLError()
0614 {
0615     GLenum error = glGetError();
0616     if (error != GL_NO_ERROR)
0617     {
0618     // std::cerr << "An OpenGL error occurred" << std::endl;
0619     return true;
0620     }
0621     return false;
0622 }
0623 
0624 
0625 void GameGLView::mousePressEvent(QMouseEvent* e)
0626 {
0627     // ensure our context outside of paint event when querying scene data
0628     makeCurrent();
0629     // Convert Y co-ordinate to OpenGL convention (zero at bottom of window).
0630     game->handleMouseEvent (ButtonDown, e->button(),
0631                 e->pos().x(), height() - e->pos().y());
0632 }
0633 
0634 
0635 void GameGLView::mouseReleaseEvent(QMouseEvent* e)
0636 {
0637     // ensure our context outside of paint event when querying scene data
0638     makeCurrent();
0639     // Convert Y co-ordinate to OpenGL convention (zero at bottom of window).
0640     game->handleMouseEvent (ButtonUp, e->button(),
0641                 e->pos().x(), height() - e->pos().y());
0642 }
0643 
0644 // End gameglview.cpp
0645 
0646