diff options
Diffstat (limited to 'main.cpp')
-rw-r--r-- | main.cpp | 371 |
1 files changed, 1 insertions, 370 deletions
@@ -1,374 +1,7 @@ #include <QtGui> #include <QtOpenGL> -#include <QFuture> -#include <QFutureWatcher> - -#include "model.h" - -class GraphicsScene : public QGraphicsScene -{ - Q_OBJECT - -public: - GraphicsScene(); - - void drawBackground(QPainter *painter, const QRectF &rect); - -public slots: - void setModel(Model *model); - void enableAutoRotate(bool enabled); - void enableWireframe(bool enabled); - void enableNormals(bool enabled); - void setLightPosition(int pos); - void setModelColor(QRgb color); - void setBackgroundColor(QRgb color); - -protected: - void mousePressEvent(QGraphicsSceneMouseEvent *event); - void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); - void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - void wheelEvent(QGraphicsSceneWheelEvent * wheelEvent); - -private: - void updateMatrix(); - void updateRotation(const QPointF &last, const QPointF ¤t); - - bool m_wireframeEnabled; - bool m_normalsEnabled; - bool m_autoRotate; - bool m_rotating; - - Point3d m_axis; - float m_angle; - float m_lightPos; - float m_distance; - - QRgb m_backgroundColor; - QRgb m_modelColor; - - Model *m_model; - - float m_matrix[4][4]; -}; - -class Controls : public QGroupBox -{ - Q_OBJECT - -public: - Controls(GraphicsScene *scene); - -private slots: - void loadModel(const QString &model); - void modelLoaded(); - void setModelColor(bool showDialog = true); - void setBackgroundColor(bool showDialog = true); - -private: - GraphicsScene *m_scene; - QFutureWatcher<Model *> m_modelLoader; - QComboBox *m_models; - - QRgb m_modelColor; - QRgb m_backgroundColor; -}; - -Controls::Controls(GraphicsScene *scene) - : m_scene(scene) - , m_models(new QComboBox) - , m_modelColor(qRgb(180, 100, 255)) - , m_backgroundColor(qRgb(0, 0, 0)) -{ - QVBoxLayout *layout = new QVBoxLayout(this); - - layout->addWidget(new QLabel("Model:")); - - QDir dir("models"); - dir.setNameFilters(QStringList() << "*.obj"); - m_models->addItems(dir.entryList()); - connect(m_models, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(loadModel(const QString &))); - connect(&m_modelLoader, SIGNAL(finished()), this, SLOT(modelLoaded())); - - if (m_models->count() > 0) - loadModel(m_models->currentText()); - layout->addWidget(m_models); - - QCheckBox *autoRotate = new QCheckBox("Auto-rotate"); - autoRotate->setChecked(true); - connect(autoRotate, SIGNAL(toggled(bool)), m_scene, SLOT(enableAutoRotate(bool))); - layout->addWidget(autoRotate); - - QCheckBox *wireframe = new QCheckBox("Render as wireframe"); - wireframe->setChecked(true); - connect(wireframe, SIGNAL(toggled(bool)), m_scene, SLOT(enableWireframe(bool))); - layout->addWidget(wireframe); - - QCheckBox *normals = new QCheckBox("Display normals vectors"); - wireframe->setChecked(false); - connect(normals, SIGNAL(toggled(bool)), m_scene, SLOT(enableNormals(bool))); - layout->addWidget(normals); - - layout->addWidget(new QLabel("Light position:")); - QSlider *lightPosition = new QSlider(Qt::Horizontal); - lightPosition->setRange(-100, 100); - connect(lightPosition, SIGNAL(valueChanged(int)), m_scene, SLOT(setLightPosition(int))); - layout->addWidget(lightPosition); - - m_scene->setLightPosition(lightPosition->value()); - - QPushButton *colorButton = new QPushButton("Choose model color"); - connect(colorButton, SIGNAL(pressed()), this, SLOT(setModelColor())); - layout->addWidget(colorButton); - setModelColor(false); - - QPushButton *backgroundButton = new QPushButton("Choose background color"); - connect(backgroundButton, SIGNAL(pressed()), this, SLOT(setBackgroundColor())); - layout->addWidget(backgroundButton); - setBackgroundColor(false); -} - -Model *loadModel(const QString &filename) -{ - return new Model(QString("models/") + filename); -} - -void Controls::loadModel(const QString &filename) -{ - m_modelLoader.setFuture(QtConcurrent::run(::loadModel, filename)); - m_models->setEnabled(false); - QApplication::setOverrideCursor(Qt::BusyCursor); -} - -void Controls::modelLoaded() -{ - m_scene->setModel(m_modelLoader.result()); - m_models->setEnabled(true); - QApplication::restoreOverrideCursor(); -} - -void Controls::setModelColor(bool showDialog) -{ - if (showDialog) - m_modelColor = QColorDialog::getRgba(m_modelColor); - - m_scene->setModelColor(m_modelColor); -} - -void Controls::setBackgroundColor(bool showDialog) -{ - if (showDialog) - m_backgroundColor = QColorDialog::getRgba(m_backgroundColor); - - m_scene->setBackgroundColor(m_backgroundColor); -} - -GraphicsScene::GraphicsScene() - : m_wireframeEnabled(true) - , m_normalsEnabled(false) - , m_autoRotate(true) - , m_rotating(false) - , m_axis(0.5, 1, 0.1) - , m_angle(0.2) - , m_distance(1.5) - , m_model(0) -{ - // set identity matrix - for (int i = 0; i < 4; ++i) - for (int j = 0; j < 4; ++j) - m_matrix[i][j] = (i == j); - - Controls *controls = new Controls(this); - controls->setWindowOpacity(0.8); - - QGraphicsProxyWidget *item = addWidget(controls); - item->translate(10, 10); - item->setCacheMode(QGraphicsItem::DeviceCoordinateCache); - - setSceneRect(QRect(0, 0, 1024, 768)); -} - -void GraphicsScene::updateMatrix() -{ - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glRotatef(m_angle, m_axis.x, m_axis.y, m_axis.z); - glMultMatrixf(&m_matrix[0][0]); - glGetFloatv(GL_MODELVIEW_MATRIX, &m_matrix[0][0]); - glPopMatrix(); -} - -void GraphicsScene::drawBackground(QPainter *painter, const QRectF &) -{ - painter->save(); - - glClearColor(qRed(m_backgroundColor)/255.0f, qGreen(m_backgroundColor)/255.0f, qBlue(m_backgroundColor)/255.0f, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - bool useMultisample = static_cast<QGLWidget *>(painter->device())->format().sampleBuffers(); - - if (m_model) { - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - gluPerspective(70, painter->device()->width() / float(painter->device()->height()), 0.01, 1000); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - float pos[] = { m_lightPos, 5, 2, 0 }; - glLightfv(GL_LIGHT0, GL_POSITION, pos); - glColor4f(qRed(m_modelColor)/255.0f, qGreen(m_modelColor)/255.0f, qBlue(m_modelColor)/255.0f, 1.0f); - - if (m_autoRotate && !m_rotating) - updateMatrix(); - - glLoadIdentity(); - glTranslatef(0, 0, -m_distance); - glMultMatrixf(&m_matrix[0][0]); - - if (useMultisample) - glEnable(GL_MULTISAMPLE); - - m_model->render(m_wireframeEnabled, m_normalsEnabled); - - if (useMultisample) - glDisable(GL_MULTISAMPLE); - - glPopMatrix(); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - } - - painter->restore(); - - QTimer::singleShot(20, this, SLOT(update())); -} - -void GraphicsScene::setModel(Model *model) -{ - delete m_model; - m_model = model; - update(); -} - -void GraphicsScene::enableAutoRotate(bool enabled) -{ - m_autoRotate = enabled; - update(); -} - -void GraphicsScene::enableWireframe(bool enabled) -{ - m_wireframeEnabled = enabled; -} - -void GraphicsScene::enableNormals(bool enabled) -{ - m_normalsEnabled = enabled; -} - -void GraphicsScene::setLightPosition(int pos) -{ - m_lightPos = pos * 0.05; - update(); -} - -void GraphicsScene::setModelColor(QRgb color) -{ - m_modelColor = color; - update(); -} - -void GraphicsScene::setBackgroundColor(QRgb color) -{ - m_backgroundColor = color; - update(); -} - -static Point3d spherical(const QPointF &point, qreal w, qreal h) -{ - qreal R = qMax(w, h); - - Point3d p; - p.x = -(point.x() - w / 2); - p.y = point.y() - h / 2; - p.z = sqrt(R * R - p.x * p.x - p.y * p.y); - - p.x /= R; - p.y /= R; - p.z /= R; - return p; -} - -void GraphicsScene::updateRotation(const QPointF &last, const QPointF ¤t) -{ - Point3d pos = spherical(current, width(), height()); - Point3d lastPos = spherical(last, width(), height()); - - m_axis.x = lastPos.y * pos.z - lastPos.z * pos.y; - m_axis.y = lastPos.z * pos.x - lastPos.x * pos.z; - m_axis.z = lastPos.x * pos.y - lastPos.y * pos.x; - - qreal length = sqrt(m_axis.x * m_axis.x + m_axis.y * m_axis.y + m_axis.z * m_axis.z); - - if (length == 0) { - m_angle = 0; - } else { - m_angle = -10 * asin(sqrt(length)); - - m_axis.x /= length; - m_axis.y /= length; - m_axis.z /= length; - - updateMatrix(); - update(); - } -} - -void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - QGraphicsScene::mouseMoveEvent(event); - if (event->isAccepted() || !m_rotating) - return; - - updateRotation(event->lastScenePos(), event->scenePos()); - event->accept(); -} - -void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - QGraphicsScene::mousePressEvent(event); - if (event->isAccepted()) - return; - - event->accept(); - m_rotating = true; -} - -void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ - QGraphicsScene::mouseReleaseEvent(event); - if (event->isAccepted()) - return; - - event->accept(); - m_rotating = false; -} - - -void GraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *event) -{ - QGraphicsScene::wheelEvent(event); - if (event->isAccepted()) - return; - - m_distance *= qPow(1.2, -event->delta() / 120); - event->accept(); - update(); -} +#include "graphicsscene.h" int main(int argc, char **argv) { @@ -388,5 +21,3 @@ int main(int argc, char **argv) return app.exec(); } - -#include "main.moc" |