diff options
author | Sarah Smith <sarah.j.smith@nokia.com> | 2009-09-21 01:23:06 (GMT) |
---|---|---|
committer | Sarah Smith <sarah.j.smith@nokia.com> | 2009-09-21 01:23:06 (GMT) |
commit | 11fed1f64f43593a2890e0a3f27b4e2e7ebde783 (patch) | |
tree | 99f57336eafe2403af7526154d8d4743f416333e /examples/opengl | |
parent | 1b8d92b1ae453bd2d395658c7086d0049916e88f (diff) | |
download | Qt-11fed1f64f43593a2890e0a3f27b4e2e7ebde783.zip Qt-11fed1f64f43593a2890e0a3f27b4e2e7ebde783.tar.gz Qt-11fed1f64f43593a2890e0a3f27b4e2e7ebde783.tar.bz2 |
remove display lists and qt3d-ize overpainting/hellogl example
On the way to making opengl examples portable, remove display lists
and go to triangles only. Use QMatrix4x4. While on the job use Qt/3D
stylee to make the QtLogo as an example of 3D programming more Qt-like.
Reviewed-by: Rhys Weatherley
Diffstat (limited to 'examples/opengl')
-rw-r--r-- | examples/opengl/hellogl/glwidget.cpp | 124 | ||||
-rw-r--r-- | examples/opengl/hellogl/glwidget.h | 10 | ||||
-rw-r--r-- | examples/opengl/hellogl/hellogl.pro | 9 | ||||
-rw-r--r-- | examples/opengl/overpainting/glwidget.cpp | 125 | ||||
-rw-r--r-- | examples/opengl/overpainting/glwidget.h | 14 | ||||
-rw-r--r-- | examples/opengl/overpainting/overpainting.pro | 28 | ||||
-rw-r--r-- | examples/opengl/shared/qtlogo.cpp | 403 | ||||
-rw-r--r-- | examples/opengl/shared/qtlogo.h | 67 |
8 files changed, 549 insertions, 231 deletions
diff --git a/examples/opengl/hellogl/glwidget.cpp b/examples/opengl/hellogl/glwidget.cpp index 64e14ea..b0c3ba4 100644 --- a/examples/opengl/hellogl/glwidget.cpp +++ b/examples/opengl/hellogl/glwidget.cpp @@ -45,12 +45,13 @@ #include <math.h> #include "glwidget.h" +#include "qtlogo.h" //! [0] GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent) { - object = 0; + logo = 0; xRot = 0; yRot = 0; zRot = 0; @@ -63,8 +64,6 @@ GLWidget::GLWidget(QWidget *parent) //! [1] GLWidget::~GLWidget() { - makeCurrent(); - glDeleteLists(object, 1); } //! [1] @@ -83,10 +82,18 @@ QSize GLWidget::sizeHint() const } //! [4] +static void qNormalizeAngle(int &angle) +{ + while (angle < 0) + angle += 360 * 16; + while (angle > 360 * 16) + angle -= 360 * 16; +} + //! [5] void GLWidget::setXRotation(int angle) { - normalizeAngle(&angle); + qNormalizeAngle(angle); if (angle != xRot) { xRot = angle; emit xRotationChanged(angle); @@ -97,7 +104,7 @@ void GLWidget::setXRotation(int angle) void GLWidget::setYRotation(int angle) { - normalizeAngle(&angle); + qNormalizeAngle(angle); if (angle != yRot) { yRot = angle; emit yRotationChanged(angle); @@ -107,7 +114,7 @@ void GLWidget::setYRotation(int angle) void GLWidget::setZRotation(int angle) { - normalizeAngle(&angle); + qNormalizeAngle(angle); if (angle != zRot) { zRot = angle; emit zRotationChanged(angle); @@ -119,10 +126,18 @@ void GLWidget::setZRotation(int angle) void GLWidget::initializeGL() { qglClearColor(qtPurple.dark()); - object = makeObject(); - glShadeModel(GL_FLAT); + + logo = new QtLogo(this, 64); + logo->setColor(qtGreen.dark()); + glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); + glShadeModel(GL_SMOOTH); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_MULTISAMPLE); + static GLfloat lightPosition[4] = { 0.5, 5.0, 7.0, 1.0 }; + glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); } //! [6] @@ -135,7 +150,7 @@ void GLWidget::paintGL() glRotated(xRot / 16.0, 1.0, 0.0, 0.0); glRotated(yRot / 16.0, 0.0, 1.0, 0.0); glRotated(zRot / 16.0, 0.0, 0.0, 1.0); - glCallList(object); + logo->draw(); } //! [7] @@ -147,7 +162,7 @@ void GLWidget::resizeGL(int width, int height) glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0); + glOrtho(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0); glMatrixMode(GL_MODELVIEW); } //! [8] @@ -175,92 +190,3 @@ void GLWidget::mouseMoveEvent(QMouseEvent *event) lastPos = event->pos(); } //! [10] - -GLuint GLWidget::makeObject() -{ - GLuint list = glGenLists(1); - glNewList(list, GL_COMPILE); - - glBegin(GL_QUADS); - - GLdouble x1 = +0.06; - GLdouble y1 = -0.14; - GLdouble x2 = +0.14; - GLdouble y2 = -0.06; - GLdouble x3 = +0.08; - GLdouble y3 = +0.00; - GLdouble x4 = +0.30; - GLdouble y4 = +0.22; - - quad(x1, y1, x2, y2, y2, x2, y1, x1); - quad(x3, y3, x4, y4, y4, x4, y3, x3); - - extrude(x1, y1, x2, y2); - extrude(x2, y2, y2, x2); - extrude(y2, x2, y1, x1); - extrude(y1, x1, x1, y1); - extrude(x3, y3, x4, y4); - extrude(x4, y4, y4, x4); - extrude(y4, x4, y3, x3); - - const double Pi = 3.14159265358979323846; - const int NumSectors = 200; - - for (int i = 0; i < NumSectors; ++i) { - double angle1 = (i * 2 * Pi) / NumSectors; - GLdouble x5 = 0.30 * sin(angle1); - GLdouble y5 = 0.30 * cos(angle1); - GLdouble x6 = 0.20 * sin(angle1); - GLdouble y6 = 0.20 * cos(angle1); - - double angle2 = ((i + 1) * 2 * Pi) / NumSectors; - GLdouble x7 = 0.20 * sin(angle2); - GLdouble y7 = 0.20 * cos(angle2); - GLdouble x8 = 0.30 * sin(angle2); - GLdouble y8 = 0.30 * cos(angle2); - - quad(x5, y5, x6, y6, x7, y7, x8, y8); - - extrude(x6, y6, x7, y7); - extrude(x8, y8, x5, y5); - } - - glEnd(); - - glEndList(); - return list; -} - -void GLWidget::quad(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2, - GLdouble x3, GLdouble y3, GLdouble x4, GLdouble y4) -{ - qglColor(qtGreen); - - glVertex3d(x1, y1, -0.05); - glVertex3d(x2, y2, -0.05); - glVertex3d(x3, y3, -0.05); - glVertex3d(x4, y4, -0.05); - - glVertex3d(x4, y4, +0.05); - glVertex3d(x3, y3, +0.05); - glVertex3d(x2, y2, +0.05); - glVertex3d(x1, y1, +0.05); -} - -void GLWidget::extrude(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) -{ - qglColor(qtGreen.dark(250 + int(100 * x1))); - - glVertex3d(x1, y1, +0.05); - glVertex3d(x2, y2, +0.05); - glVertex3d(x2, y2, -0.05); - glVertex3d(x1, y1, -0.05); -} - -void GLWidget::normalizeAngle(int *angle) -{ - while (*angle < 0) - *angle += 360 * 16; - while (*angle > 360 * 16) - *angle -= 360 * 16; -} diff --git a/examples/opengl/hellogl/glwidget.h b/examples/opengl/hellogl/glwidget.h index b202a61..4ffd4d7 100644 --- a/examples/opengl/hellogl/glwidget.h +++ b/examples/opengl/hellogl/glwidget.h @@ -44,6 +44,8 @@ #include <QGLWidget> +class QtLogo; + //! [0] class GLWidget : public QGLWidget { @@ -80,13 +82,7 @@ protected: //! [3] private: - GLuint makeObject(); - void quad(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2, - GLdouble x3, GLdouble y3, GLdouble x4, GLdouble y4); - void extrude(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); - void normalizeAngle(int *angle); - - GLuint object; + QtLogo *logo; int xRot; int yRot; int zRot; diff --git a/examples/opengl/hellogl/hellogl.pro b/examples/opengl/hellogl/hellogl.pro index 6d57c19..0e3209a 100644 --- a/examples/opengl/hellogl/hellogl.pro +++ b/examples/opengl/hellogl/hellogl.pro @@ -1,8 +1,13 @@ +VPATH += ../shared +INCLUDEPATH += ../shared + HEADERS = glwidget.h \ - window.h + window.h \ + qtlogo.h SOURCES = glwidget.cpp \ main.cpp \ - window.cpp + window.cpp \ + qtlogo.cpp QT += opengl # install diff --git a/examples/opengl/overpainting/glwidget.cpp b/examples/opengl/overpainting/glwidget.cpp index 30d3266..0dcccbf 100644 --- a/examples/opengl/overpainting/glwidget.cpp +++ b/examples/opengl/overpainting/glwidget.cpp @@ -46,6 +46,7 @@ #include <math.h> #include "bubble.h" +#include "qtlogo.h" #include "glwidget.h" #ifndef GL_MULTISAMPLE @@ -59,7 +60,7 @@ GLWidget::GLWidget(QWidget *parent) QTime midnight(0, 0, 0); qsrand(midnight.secsTo(QTime::currentTime())); - object = 0; + logo = 0; xRot = 0; yRot = 0; zRot = 0; @@ -80,28 +81,34 @@ GLWidget::GLWidget(QWidget *parent) //! [1] GLWidget::~GLWidget() { - makeCurrent(); - glDeleteLists(object, 1); } //! [1] +static void qNormalizeAngle(int &angle) +{ + while (angle < 0) + angle += 360 * 16; + while (angle > 360 * 16) + angle -= 360 * 16; +} + void GLWidget::setXRotation(int angle) { - normalizeAngle(&angle); + qNormalizeAngle(angle); if (angle != xRot) xRot = angle; } void GLWidget::setYRotation(int angle) { - normalizeAngle(&angle); + qNormalizeAngle(angle); if (angle != yRot) yRot = angle; } void GLWidget::setZRotation(int angle) { - normalizeAngle(&angle); + qNormalizeAngle(angle); if (angle != zRot) zRot = angle; } @@ -109,7 +116,10 @@ void GLWidget::setZRotation(int angle) //! [2] void GLWidget::initializeGL() { - object = makeObject(); + glEnable(GL_MULTISAMPLE); + + logo = new QtLogo(this); + logo->setColor(qtGreen.dark()); } //! [2] @@ -162,7 +172,8 @@ void GLWidget::paintEvent(QPaintEvent *event) glRotated(xRot / 16.0, 1.0, 0.0, 0.0); glRotated(yRot / 16.0, 0.0, 1.0, 0.0); glRotated(zRot / 16.0, 0.0, 0.0, 1.0); - glCallList(object); + + logo->draw(); //! [7] //! [8] @@ -207,102 +218,6 @@ QSize GLWidget::sizeHint() const return QSize(400, 400); } -GLuint GLWidget::makeObject() -{ - GLuint list = glGenLists(1); - glNewList(list, GL_COMPILE); - - glEnable(GL_NORMALIZE); - glBegin(GL_QUADS); - - static GLfloat logoDiffuseColor[4] = {qtGreen.red()/255.0, - qtGreen.green()/255.0, - qtGreen.blue()/255.0, 1.0}; - glMaterialfv(GL_FRONT, GL_DIFFUSE, logoDiffuseColor); - - GLdouble x1 = +0.06; - GLdouble y1 = -0.14; - GLdouble x2 = +0.14; - GLdouble y2 = -0.06; - GLdouble x3 = +0.08; - GLdouble y3 = +0.00; - GLdouble x4 = +0.30; - GLdouble y4 = +0.22; - - quad(x1, y1, x2, y2, y2, x2, y1, x1); - quad(x3, y3, x4, y4, y4, x4, y3, x3); - - extrude(x1, y1, x2, y2); - extrude(x2, y2, y2, x2); - extrude(y2, x2, y1, x1); - extrude(y1, x1, x1, y1); - extrude(x3, y3, x4, y4); - extrude(x4, y4, y4, x4); - extrude(y4, x4, y3, x3); - - const double Pi = 3.14159265358979323846; - const int NumSectors = 200; - - for (int i = 0; i < NumSectors; ++i) { - double angle1 = (i * 2 * Pi) / NumSectors; - GLdouble x5 = 0.30 * sin(angle1); - GLdouble y5 = 0.30 * cos(angle1); - GLdouble x6 = 0.20 * sin(angle1); - GLdouble y6 = 0.20 * cos(angle1); - - double angle2 = ((i + 1) * 2 * Pi) / NumSectors; - GLdouble x7 = 0.20 * sin(angle2); - GLdouble y7 = 0.20 * cos(angle2); - GLdouble x8 = 0.30 * sin(angle2); - GLdouble y8 = 0.30 * cos(angle2); - - quad(x5, y5, x6, y6, x7, y7, x8, y8); - - extrude(x6, y6, x7, y7); - extrude(x8, y8, x5, y5); - } - - glEnd(); - - glEndList(); - return list; -} - -void GLWidget::quad(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2, - GLdouble x3, GLdouble y3, GLdouble x4, GLdouble y4) -{ - glNormal3d(0.0, 0.0, -1.0); - glVertex3d(x1, y1, -0.05); - glVertex3d(x2, y2, -0.05); - glVertex3d(x3, y3, -0.05); - glVertex3d(x4, y4, -0.05); - - glNormal3d(0.0, 0.0, 1.0); - glVertex3d(x4, y4, +0.05); - glVertex3d(x3, y3, +0.05); - glVertex3d(x2, y2, +0.05); - glVertex3d(x1, y1, +0.05); -} - -void GLWidget::extrude(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) -{ - qglColor(qtGreen.dark(250 + int(100 * x1))); - - glNormal3d((x1 + x2)/2.0, (y1 + y2)/2.0, 0.0); - glVertex3d(x1, y1, +0.05); - glVertex3d(x2, y2, +0.05); - glVertex3d(x2, y2, -0.05); - glVertex3d(x1, y1, -0.05); -} - -void GLWidget::normalizeAngle(int *angle) -{ - while (*angle < 0) - *angle += 360 * 16; - while (*angle > 360 * 16) - *angle -= 360 * 16; -} - void GLWidget::createBubbles(int number) { for (int i = 0; i < number; ++i) { @@ -337,7 +252,7 @@ void GLWidget::setupViewport(int width, int height) glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0); + glOrtho(-0.5, +0.5, -0.5, 0.5, 4.0, 15.0); glMatrixMode(GL_MODELVIEW); } //! [14] diff --git a/examples/opengl/overpainting/glwidget.h b/examples/opengl/overpainting/glwidget.h index 5323a6f..6c9f7e0 100644 --- a/examples/opengl/overpainting/glwidget.h +++ b/examples/opengl/overpainting/glwidget.h @@ -50,6 +50,7 @@ #include <QTimer> class Bubble; +class QtLogo; QT_BEGIN_NAMESPACE class QPaintEvent; class QWidget; @@ -88,27 +89,24 @@ private slots: void animate(); private: - GLuint makeObject(); void createBubbles(int number); void drawInstructions(QPainter *painter); //! [1] - void extrude(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); - void normalizeAngle(int *angle); - void quad(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2, - GLdouble x3, GLdouble y3, GLdouble x4, GLdouble y4); void setupViewport(int width, int height); + QColor qtGreen; + QColor qtPurple; + GLuint object; int xRot; int yRot; int zRot; QPoint lastPos; - QColor qtGreen; - QColor qtPurple; //! [4] + QtLogo *logo; QList<Bubble*> bubbles; QTimer animationTimer; -}; //! [4] +}; #endif diff --git a/examples/opengl/overpainting/overpainting.pro b/examples/opengl/overpainting/overpainting.pro index 10b6bd3..f9ba245 100644 --- a/examples/opengl/overpainting/overpainting.pro +++ b/examples/opengl/overpainting/overpainting.pro @@ -1,15 +1,23 @@ -QT += opengl +VPATH += ../shared +INCLUDEPATH += ../shared -HEADERS = bubble.h \ - glwidget.h -SOURCES = bubble.cpp \ - glwidget.cpp \ - main.cpp +QT += opengl +HEADERS = bubble.h \ + glwidget.h \ + qtlogo.h +SOURCES = bubble.cpp \ + glwidget.cpp \ + main.cpp \ + qtlogo.cpp # install target.path = $$[QT_INSTALL_EXAMPLES]/opengl/overpainting -sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS overpainting.pro +sources.files = $$SOURCES \ + $$HEADERS \ + $$RESOURCES \ + $$FORMS \ + overpainting.pro sources.path = $$[QT_INSTALL_EXAMPLES]/opengl/overpainting -INSTALLS += target sources - -symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) +INSTALLS += target \ + sources +symbian:include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/opengl/shared/qtlogo.cpp b/examples/opengl/shared/qtlogo.cpp new file mode 100644 index 0000000..3294da1 --- /dev/null +++ b/examples/opengl/shared/qtlogo.cpp @@ -0,0 +1,403 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtlogo.h" + +static const qreal tee_height = 0.311126; +static const qreal cross_width = 0.25; +static const qreal bar_thickness = 0.113137; +static const qreal inside_diam = 0.20; +static const qreal outside_diam = 0.30; +static const qreal logo_depth = 0.10; +static const int num_divisions = 32; + +//! [0] +struct Geometry +{ + QVector<GLushort> faces; + QVector<QVector3D> vertices; + QVector<QVector3D> normals; + void appendSmooth(const QVector3D &a, const QVector3D &n, int from); + void appendFaceted(const QVector3D &a, const QVector3D &n); + void finalize(); + void loadArrays() const; +}; +//! [0] + +//! [1] +class Patch +{ +public: + enum Smoothing { Faceted, Smooth }; + Patch(Geometry *); + void setSmoothing(Smoothing s) { sm = s; } + void translate(const QVector3D &t); + void rotate(qreal deg, QVector3D axis); + void draw() const; + void addTri(const QVector3D &a, const QVector3D &b, const QVector3D &c, const QVector3D &n); + void addQuad(const QVector3D &a, const QVector3D &b, const QVector3D &c, const QVector3D &d); + + GLushort start; + GLushort count; + GLushort initv; + + GLfloat faceColor[4]; + QMatrix4x4 mat; + Smoothing sm; + Geometry *geom; +}; +//! [1] + +static inline void qSetColor(float colorVec[], QColor c) +{ + colorVec[0] = c.redF(); + colorVec[1] = c.greenF(); + colorVec[2] = c.blueF(); + colorVec[3] = c.alphaF(); +} + +void Geometry::loadArrays() const +{ + glVertexPointer(3, GL_FLOAT, 0, vertices.constData()); + glNormalPointer(GL_FLOAT, 0, normals.constData()); +} + +void Geometry::finalize() +{ + // TODO: add vertex buffer uploading here + + // Finish smoothing normals by ensuring accumulated normals are returned + // to length 1.0. + for (int i = 0; i < normals.count(); ++i) + normals[i].normalize(); +} + +void Geometry::appendSmooth(const QVector3D &a, const QVector3D &n, int from) +{ + // Smooth normals are acheived by averaging the normals for faces meeting + // at a point. First find the point in geometry already generated + // (working backwards, since most often the points shared are between faces + // recently added). + int v = vertices.count() - 1; + for ( ; v >= from; --v) + if (qFuzzyCompare(vertices[v], a)) + break; + if (v < from) + { + // The vert was not found so add it as a new one, and initialize + // its corresponding normal + v = vertices.count(); + vertices.append(a); + normals.append(n); + } + else + { + // Vert found, accumulate normals into corresponding normal slot. + // Must call finalize once finished accumulating normals + normals[v] += n; + } + // In both cases (found or not) reference the vert via its index + faces.append(v); +} + +void Geometry::appendFaceted(const QVector3D &a, const QVector3D &n) +{ + // Faceted normals are achieved by duplicating the vert for every + // normal, so that faces meeting at a vert get a sharp edge. + int v = vertices.count(); + vertices.append(a); + normals.append(n); + faces.append(v); +} + +Patch::Patch(Geometry *g) + : start(g->faces.count()) + , count(0) + , initv(g->vertices.count()) + , sm(Patch::Smooth) + , geom(g) +{ + qSetColor(faceColor, QColor(Qt::darkGray)); +} + +void Patch::rotate(qreal deg, QVector3D axis) +{ + mat.rotate(deg, axis); +} + +void Patch::translate(const QVector3D &t) +{ + mat.translate(t); +} + +static inline void qMultMatrix(const QMatrix4x4 &mat) +{ + if (sizeof(qreal) == sizeof(GLfloat)) + glMultMatrixf((GLfloat*)mat.constData()); + else if (sizeof(qreal) == sizeof(GLdouble)) + glMultMatrixd((GLdouble*)mat.constData()); + else + { + GLfloat fmat[16]; + qreal const *r = mat.constData(); + for (int i = 0; i < 16; ++i) + fmat[i] = r[i]; + } +} + +//! [2] +void Patch::draw() const +{ + glPushMatrix(); + qMultMatrix(mat); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, faceColor); + + const GLushort *indices = geom->faces.constData(); + glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, indices + start); + glPopMatrix(); +} +//! [2] + +void Patch::addTri(const QVector3D &a, const QVector3D &b, const QVector3D &c, const QVector3D &n) +{ + QVector3D norm = n.isNull() ? QVector3D::normal(a, b, c) : n; + if (sm == Smooth) + { + geom->appendSmooth(a, norm, initv); + geom->appendSmooth(b, norm, initv); + geom->appendSmooth(c, norm, initv); + } + else + { + geom->appendFaceted(a, norm); + geom->appendFaceted(b, norm); + geom->appendFaceted(c, norm); + } + count += 3; +} + +void Patch::addQuad(const QVector3D &a, const QVector3D &b, const QVector3D &c, const QVector3D &d) +{ + QVector3D norm = QVector3D::normal(a, b, c); + if (sm == Smooth) + { + addTri(a, b, c, norm); + addTri(a, c, d, norm); + } + else + { + // If faceted share the two common verts + addTri(a, b, c, norm); + int k = geom->vertices.count(); + geom->appendSmooth(a, norm, k); + geom->appendSmooth(c, norm, k); + geom->appendFaceted(d, norm); + count += 3; + } +} + +static inline QVector<QVector3D> extrude(const QVector<QVector3D> &verts, qreal depth) +{ + QVector<QVector3D> extr = verts; + for (int v = 0; v < extr.count(); ++v) + extr[v].setZ(extr[v].z() - depth); + return extr; +} + +class Rectoid +{ +public: + void translate(const QVector3D &t) + { + for (int i = 0; i < parts.count(); ++i) + parts[i]->translate(t); + } + void rotate(qreal deg, QVector3D axis) + { + for (int i = 0; i < parts.count(); ++i) + parts[i]->rotate(deg, axis); + } + + // No special Rectoid destructor - the parts are fetched out of this member + // variable, and destroyed by the new owner + QList<Patch*> parts; +}; + +class RectPrism : public Rectoid +{ +public: + RectPrism(Geometry *g, qreal width, qreal height, qreal depth); +}; + +RectPrism::RectPrism(Geometry *g, qreal width, qreal height, qreal depth) +{ + enum { bl, br, tr, tl }; + Patch *fb = new Patch(g); + fb->setSmoothing(Patch::Faceted); + + // front face + QVector<QVector3D> r(4); + r[br].setX(width); + r[tr].setX(width); + r[tr].setY(height); + r[tl].setY(height); + QVector3D adjToCenter(-width / 2.0, -height / 2.0, depth / 2.0); + for (int i = 0; i < 4; ++i) + r[i] += adjToCenter; + fb->addQuad(r[bl], r[br], r[tr], r[tl]); + + // back face + QVector<QVector3D> s = extrude(r, depth); + fb->addQuad(s[tl], s[tr], s[br], s[bl]); + + // side faces + Patch *sides = new Patch(g); + sides->setSmoothing(Patch::Faceted); + sides->addQuad(s[bl], s[br], r[br], r[bl]); + sides->addQuad(s[br], s[tr], r[tr], r[br]); + sides->addQuad(s[tr], s[tl], r[tl], r[tr]); + sides->addQuad(s[tl], s[bl], r[bl], r[tl]); + + parts << fb << sides; +} + +class RectTorus : public Rectoid +{ +public: + RectTorus(Geometry *g, qreal iRad, qreal oRad, qreal depth, int numSectors); +}; + +RectTorus::RectTorus(Geometry *g, qreal iRad, qreal oRad, qreal depth, int k) +{ + QVector<QVector3D> inside; + QVector<QVector3D> outside; + for (int i = 0; i < k; ++i) { + qreal angle = (i * 2 * M_PI) / k; + inside << QVector3D(iRad * qSin(angle), iRad * qCos(angle), depth / 2.0); + outside << QVector3D(oRad * qSin(angle), oRad * qCos(angle), depth / 2.0); + } + inside << QVector3D(0.0, iRad, 0.0); + outside << QVector3D(0.0, oRad, 0.0); + QVector<QVector3D> in_back = extrude(inside, depth); + QVector<QVector3D> out_back = extrude(outside, depth); + + // Create front, back and sides as seperate patches so that smooth normals + // are generated for the curving sides, but a faceted edge is created between + // sides and front/back + Patch *front = new Patch(g); + for (int i = 0; i < k; ++i) + front->addQuad(outside[i], inside[i], + inside[(i + 1) % k], outside[(i + 1) % k]); + Patch *back = new Patch(g); + for (int i = 0; i < k; ++i) + back->addQuad(in_back[i], out_back[i], + out_back[(i + 1) % k], in_back[(i + 1) % k]); + Patch *is = new Patch(g); + for (int i = 0; i < k; ++i) + is->addQuad(in_back[i], in_back[(i + 1) % k], + inside[(i + 1) % k], inside[i]); + Patch *os = new Patch(g); + for (int i = 0; i < k; ++i) + os->addQuad(out_back[(i + 1) % k], out_back[i], + outside[i], outside[(i + 1) % k]); + parts << front << back << is << os; +} + +QtLogo::QtLogo(QObject *parent, int divisions, qreal scale) + : QObject(parent) + , geom(new Geometry()) +{ + buildGeometry(divisions, scale); +} + +QtLogo::~QtLogo() +{ + qDeleteAll(parts); + delete geom; +} + +void QtLogo::setColor(QColor c) +{ + for (int i = 0; i < parts.count(); ++i) + qSetColor(parts[i]->faceColor, c); +} + +//! [3] +void QtLogo::buildGeometry(int divisions, qreal scale) +{ + qreal cw = cross_width * scale; + qreal bt = bar_thickness * scale; + qreal ld = logo_depth * scale; + qreal th = tee_height *scale; + + RectPrism cross(geom, cw, bt, ld); + RectPrism stem(geom, bt, th, ld); + + QVector3D z(0.0, 0.0, 1.0); + cross.rotate(45.0, z); + stem.rotate(45.0, z); + + qreal stem_downshift = (th + bt) / 2.0; + stem.translate(QVector3D(0.0, -stem_downshift, 0.0)); + + RectTorus body(geom, 0.20, 0.30, 0.1, divisions); + + parts << stem.parts << cross.parts << body.parts; + + geom->finalize(); +} +//! [3] + +//! [4] +void QtLogo::draw() const +{ + geom->loadArrays(); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + for (int i = 0; i < parts.count(); ++i) + parts[i]->draw(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); +} +//! [4] diff --git a/examples/opengl/shared/qtlogo.h b/examples/opengl/shared/qtlogo.h new file mode 100644 index 0000000..26508e1 --- /dev/null +++ b/examples/opengl/shared/qtlogo.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTLOGO_H +#define QTLOGO_H + +#include <QObject> +#include <QtOpenGL> + +class Patch; +class Geometry; + +//! [0] +class QtLogo : public QObject +{ +public: + QtLogo(QObject *parent, int d = 64, qreal s = 1.0); + ~QtLogo(); + void setColor(QColor c); + void draw() const; +private: + void buildGeometry(int d, qreal s); + + QList<Patch *> parts; + Geometry *geom; +}; +//! [0] + +#endif // QTLOGO_H |