diff options
author | Samuel Rødal <sroedal@trolltech.com> | 2008-06-23 11:34:41 +0200 |
---|---|---|
committer | Samuel Rødal <sroedal@trolltech.com> | 2008-06-23 11:34:41 +0200 |
commit | d33e1a6025e80df963745592dbbc5eb53d6ce63f (patch) | |
tree | 5dfaa73a34bb551d1c225e70c147108ca705c463 | |
parent | f726310976201bf033ac2e39e2d6da7fbf018405 (diff) |
Added background color and mouse rotation.
-rw-r--r-- | main.cpp | 195 |
1 files changed, 169 insertions, 26 deletions
@@ -21,19 +21,35 @@ public slots: void enableWireframe(bool enabled); void enableNormals(bool enabled); void setLightPosition(int pos); - void setColor(QRgb color); + 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_color; + QRgb m_backgroundColor; + QRgb m_modelColor; Model *m_model; + + float m_matrix[4][4]; }; class Controls : public QGroupBox @@ -46,19 +62,23 @@ public: private slots: void loadModel(const QString &model); void modelLoaded(); - void setColor(bool showDialog = true); + void setModelColor(bool showDialog = true); + void setBackgroundColor(bool showDialog = true); private: GraphicsScene *m_scene; QFutureWatcher<Model *> m_modelLoader; QComboBox *m_models; - QRgb m_color; + + QRgb m_modelColor; + QRgb m_backgroundColor; }; Controls::Controls(GraphicsScene *scene) : m_scene(scene) , m_models(new QComboBox) - , m_color(qRgb(180, 100, 255)) + , m_modelColor(qRgb(180, 100, 255)) + , m_backgroundColor(qRgb(0, 0, 0)) { QVBoxLayout *layout = new QVBoxLayout(this); @@ -91,16 +111,21 @@ Controls::Controls(GraphicsScene *scene) layout->addWidget(new QLabel("Light position:")); QSlider *lightPosition = new QSlider(Qt::Horizontal); - lightPosition->setRange(-1000, 1000); + 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("Set model color"); - connect(colorButton, SIGNAL(pressed()), this, SLOT(setColor())); + QPushButton *colorButton = new QPushButton("Choose model color"); + connect(colorButton, SIGNAL(pressed()), this, SLOT(setModelColor())); layout->addWidget(colorButton); - setColor(false); + 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) @@ -122,33 +147,63 @@ void Controls::modelLoaded() QApplication::restoreOverrideCursor(); } -void Controls::setColor(bool showDialog) +void Controls::setModelColor(bool showDialog) { if (showDialog) - m_color = QColorDialog::getRgba(m_color); + m_modelColor = QColorDialog::getRgba(m_modelColor); - m_scene->setColor(m_color); + 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_angle(0) + , 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); - addWidget(controls)->translate(10, 10); + 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(1, 1, 1, 1); + 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(); @@ -162,19 +217,19 @@ void GraphicsScene::drawBackground(QPainter *painter, const QRectF &) glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); - float pos[] = { m_lightPos, 5, 2, 0 }; glLightfv(GL_LIGHT0, GL_POSITION, pos); - glColor4f(qRed(m_color)/255.0f, qGreen(m_color)/255.0f, qBlue(m_color)/255.0f, 1.0f); + glColor4f(qRed(m_modelColor)/255.0f, qGreen(m_modelColor)/255.0f, qBlue(m_modelColor)/255.0f, 1.0f); - if (useMultisample) - glEnable(GL_MULTISAMPLE); + if (m_autoRotate && !m_rotating) + updateMatrix(); - glTranslatef(0, 0, -1.5); - glRotatef(m_angle, 0.5, 1, 0.1); + glLoadIdentity(); + glTranslatef(0, 0, -m_distance); + glMultMatrixf(&m_matrix[0][0]); - if (m_autoRotate) - m_angle += 0.4; + if (useMultisample) + glEnable(GL_MULTISAMPLE); m_model->render(m_wireframeEnabled, m_normalsEnabled); @@ -217,13 +272,101 @@ void GraphicsScene::enableNormals(bool enabled) void GraphicsScene::setLightPosition(int pos) { - m_lightPos = pos * 0.005; + m_lightPos = pos * 0.05; + update(); +} + +void GraphicsScene::setModelColor(QRgb color) +{ + m_modelColor = color; + update(); +} + +void GraphicsScene::setBackgroundColor(QRgb color) +{ + m_backgroundColor = color; update(); } -void GraphicsScene::setColor(QRgb color) +static Point3d spherical(const QPointF &point, qreal w, qreal h) { - m_color = color; + 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(); } |