diff options
author | Mika Salmela <mika.salmela@digia.com> | 2013-09-17 11:48:54 +0300 |
---|---|---|
committer | Mika Salmela <mika.salmela@digia.com> | 2013-09-17 12:04:49 +0300 |
commit | ab8343a2df664545575b5233b74ea0329647c7df (patch) | |
tree | be72d823cbfb9fa22d1d2c9ff90229252e02d74e | |
parent | dbc876fa0f9c5c87d0ee250efa4d7a211bde3ddf (diff) |
Misc bug fixes
- Enabled zooming on Surface C++ api
- User modified gradient takes effect
- Scene pointer is updated to selection pointer
- Font changing is listened on selection pointer and label's are generated
using selected font
- Selection label format copied from scatter. Looks to be very handy.
- Check for OpenGL 1.5 version and block coarse surface if below
- Added some theme handling. Not sure if the bug is fully fixed. Probably
requires shadow fixes to be fully similar to others.
- HAHAA. Now even single rows and columns supported. Even one value will
produce surface
Task-number: QTRD-2279
Task-number: QTRD-2265
Task-number: QTRD-2261
Task-number: QTRD-2269
Task-number: QTRD-2268
Task-number: QTRD-2272
Change-Id: Id34d843b2898e4cf1e4dde10ce23e0eaab4738a7
Signed-off-by: Mika Salmela <mika.salmela@digia.com>
Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
-rw-r--r-- | examples/surfacechart/chartmodifier.cpp | 37 | ||||
-rw-r--r-- | examples/surfacechart/chartmodifier.h | 8 | ||||
-rw-r--r-- | examples/surfacechart/main.cpp | 88 | ||||
-rw-r--r-- | src/datavisualization/data/qsurfacedataproxy.cpp | 2 | ||||
-rw-r--r-- | src/datavisualization/engine/q3dsurface.cpp | 67 | ||||
-rw-r--r-- | src/datavisualization/engine/q3dsurface.h | 16 | ||||
-rw-r--r-- | src/datavisualization/engine/selectionpointer.cpp | 26 | ||||
-rw-r--r-- | src/datavisualization/engine/selectionpointer_p.h | 5 | ||||
-rw-r--r-- | src/datavisualization/engine/surface3dcontroller.cpp | 47 | ||||
-rw-r--r-- | src/datavisualization/engine/surface3dcontroller_p.h | 28 | ||||
-rw-r--r-- | src/datavisualization/engine/surface3drenderer.cpp | 242 | ||||
-rw-r--r-- | src/datavisualization/engine/surface3drenderer_p.h | 15 | ||||
-rw-r--r-- | src/datavisualization/utils/shaderhelper.cpp | 12 | ||||
-rw-r--r-- | src/datavisualization/utils/shaderhelper_p.h | 1 |
14 files changed, 454 insertions, 140 deletions
diff --git a/examples/surfacechart/chartmodifier.cpp b/examples/surfacechart/chartmodifier.cpp index e904dae2..b1c6a71f 100644 --- a/examples/surfacechart/chartmodifier.cpp +++ b/examples/surfacechart/chartmodifier.cpp @@ -30,7 +30,8 @@ ChartModifier::ChartModifier(Q3DSurface *chart) : m_chart(chart), m_xCount(10), m_zCount(10), - m_activeSample(0) + m_activeSample(0), + m_fontSize(40.0f) { m_chart->setAxisX(new Q3DValueAxis); m_chart->setAxisY(new Q3DValueAxis); @@ -133,7 +134,6 @@ void ChartModifier::setHeightMapData(bool enable) int p = image.width() * 4 * (image.height() - 1); dataArray->reserve(image.height()); - qDebug() << image.height() << image.width(); for (int i = image.height(); i > 0; i--, p -= image.width() * 4) { QSurfaceDataRow *newRow = new QSurfaceDataRow(image.width()); for (int j = 0; j < image.width(); j++) @@ -186,6 +186,39 @@ void ChartModifier::adjustZCount(int count) qDebug() << "Z count = " << count; } +void ChartModifier::colorPressed() +{ + m_chart->setGradientColorAt(0.0, Qt::blue); +} + +void ChartModifier::changeFont(const QFont &font) +{ + QFont newFont = font; + newFont.setPointSizeF(m_fontSize); + m_chart->setFont(newFont); +} + +void ChartModifier::changeTransparency() +{ + static int transparency = QDataVis::TransparencyNone; + + m_chart->setLabelTransparency((QDataVis::LabelTransparency)transparency); + + if (++transparency > QDataVis::TransparencyNoBackground) + transparency = QDataVis::TransparencyNone; +} + +void ChartModifier::changeTheme(int theme) +{ + m_chart->setTheme((QDataVis::ColorTheme)theme); +} + +void ChartModifier::changeShadowQuality(int quality) +{ + QDataVis::ShadowQuality sq = QDataVis::ShadowQuality(quality); + m_chart->setShadowQuality(sq); +} + void ChartModifier::updateSamples() { switch (m_activeSample) { diff --git a/examples/surfacechart/chartmodifier.h b/examples/surfacechart/chartmodifier.h index 1de5840e..ad0ea162 100644 --- a/examples/surfacechart/chartmodifier.h +++ b/examples/surfacechart/chartmodifier.h @@ -48,6 +48,13 @@ public: void adjustXCount(int count); void adjustZCount(int count); void updateSamples(); + void colorPressed(); + void changeFont(const QFont &font); + void changeTransparency(); + +public slots: + void changeShadowQuality(int quality); + void changeTheme(int theme); private: Q3DSurface *m_chart; @@ -57,6 +64,7 @@ private: int m_xCount; int m_zCount; int m_activeSample; + int m_fontSize; }; #endif // CHARTMODIFIER_H diff --git a/examples/surfacechart/main.cpp b/examples/surfacechart/main.cpp index 7a989adf..02d5e7a0 100644 --- a/examples/surfacechart/main.cpp +++ b/examples/surfacechart/main.cpp @@ -30,6 +30,7 @@ #include <QLabel> #include <QScreen> #include <QPainter> +#include <QFontComboBox> #include <QDebug> using namespace QtDataVisualization; @@ -84,19 +85,19 @@ int main(int argc, char *argv[]) QSlider *gridSliderX = new QSlider(Qt::Horizontal, widget); gridSliderX->setTickInterval(1); - gridSliderX->setMinimum(2); + gridSliderX->setMinimum(1); gridSliderX->setValue(10); gridSliderX->setMaximum(200); gridSliderX->setEnabled(true); QSlider *gridSliderZ = new QSlider(Qt::Horizontal, widget); gridSliderZ->setTickInterval(1); - gridSliderZ->setMinimum(2); + gridSliderZ->setMinimum(1); gridSliderZ->setValue(10); gridSliderZ->setMaximum(200); gridSliderZ->setEnabled(true); QLinearGradient gr(0, 0, 100, 1); - gr.setColorAt(0.0, Qt::green); + gr.setColorAt(0.0, Qt::blue); gr.setColorAt(0.5, Qt::yellow); gr.setColorAt(1.0, Qt::red); QPixmap pm(100, 24); @@ -104,11 +105,36 @@ int main(int argc, char *argv[]) pmp.setBrush(QBrush(gr)); pmp.setPen(Qt::NoPen); pmp.drawRect(0, 0, 100, 24); - //pm.save("C:\\Users\\misalmel\\Work\\test.png", "png"); - QPushButton *color = new QPushButton(); - color->setIcon(QIcon(pm)); - color->setIconSize(QSize(100, 24)); - color->setFlat(true); + QPushButton *colorPB = new QPushButton(); + colorPB->setIcon(QIcon(pm)); + colorPB->setIconSize(QSize(100, 24)); + + QFontComboBox *fontList = new QFontComboBox(widget); + fontList->setCurrentFont(QFont("Arial")); + + QPushButton *labelButton = new QPushButton(widget); + labelButton->setText(QStringLiteral("Change label style")); + + QComboBox *themeList = new QComboBox(widget); + themeList->addItem(QStringLiteral("System")); + themeList->addItem(QStringLiteral("Blue Cerulean")); + themeList->addItem(QStringLiteral("Blue Icy")); + themeList->addItem(QStringLiteral("Blue Ncs")); + themeList->addItem(QStringLiteral("Brown Sand")); + themeList->addItem(QStringLiteral("Dark")); + themeList->addItem(QStringLiteral("High Contrast")); + themeList->addItem(QStringLiteral("Light")); + themeList->setCurrentIndex(4); + + QComboBox *shadowQuality = new QComboBox(widget); + shadowQuality->addItem(QStringLiteral("None")); + shadowQuality->addItem(QStringLiteral("Low")); + shadowQuality->addItem(QStringLiteral("Medium")); + shadowQuality->addItem(QStringLiteral("High")); + shadowQuality->addItem(QStringLiteral("Low Soft")); + shadowQuality->addItem(QStringLiteral("Medium Soft")); + shadowQuality->addItem(QStringLiteral("High Soft")); + shadowQuality->setCurrentIndex(3); // Add controls to the layout vLayout->addWidget(smoothCB); @@ -121,7 +147,14 @@ int main(int argc, char *argv[]) vLayout->addWidget(gridSlidersLockCB); vLayout->addWidget(gridSliderX); vLayout->addWidget(gridSliderZ); - vLayout->addWidget(color); + vLayout->addWidget(colorPB); + vLayout->addWidget(new QLabel(QStringLiteral("Change font"))); + vLayout->addWidget(fontList); + vLayout->addWidget(labelButton); + vLayout->addWidget(new QLabel(QStringLiteral("Change theme"))); + vLayout->addWidget(themeList); + vLayout->addWidget(new QLabel(QStringLiteral("Adjust shadow quality"))); + vLayout->addWidget(shadowQuality); widget->show(); @@ -144,37 +177,20 @@ int main(int argc, char *argv[]) modifier, &ChartModifier::adjustXCount); QObject::connect(gridSliderZ, &QSlider::valueChanged, modifier, &ChartModifier::adjustZCount); + QObject::connect(colorPB, &QPushButton::pressed, + modifier, &ChartModifier::colorPressed); + QObject::connect(fontList, &QFontComboBox::currentFontChanged, + modifier, &ChartModifier::changeFont); + QObject::connect(labelButton, &QPushButton::clicked, + modifier, &ChartModifier::changeTransparency); + QObject::connect(themeList, SIGNAL(currentIndexChanged(int)), + modifier, SLOT(changeTheme(int))); + QObject::connect(shadowQuality, SIGNAL(currentIndexChanged(int)), + modifier, SLOT(changeShadowQuality(int))); modifier->setGridSliderZ(gridSliderZ); modifier->setGridSliderX(gridSliderX); modifier->toggleGridSliderLock(gridSlidersLockCB->checkState()); -// QList<qreal> lowList; -// lowList << 15.0 << 35.0 << 55.0 << 75.0 << 80.0 << 75.0 << 55.0 << 35.0 << 15.0; -// lowList << 65.0 << 105.0 << 135.0 << 155.0 << 190.0 << 155.0 << 135.0 << 105.0 << 65.0; -// lowList << 105.0 << 170.0 << 215.0 << 240.0 << 245.0 << 240.0 << 215.0 << 170.0 << 105.0; -// lowList << 65.0 << 105.0 << 135.0 << 155.0 << 190.0 << 155.0 << 135.0 << 105.0 << 65.0; -// lowList << 15.0 << 35.0 << 55.0 << 75.0 << 80.0 << 75.0 << 55.0 << 35.0 << 16.1; - -// lowList << 15.0 << 65.0 << 105.0 << 65.0 << 15.0; -// lowList << 35.0 << 105.0 << 170.0 << 105.0 << 35; -// lowList << 55.0 << 135.0 << 215.0 << 135.0 << 55; -// lowList << 75.0 << 155.0 << 240.0 << 155.0 << 75; -// lowList << 80.0 << 190.0 << 245.0 << 190.0 << 80; -// lowList << 75.0 << 155.0 << 240.0 << 155.0 << 75.0; -// lowList << 55.0 << 135.0 << 215.0 << 135.0 << 55; -// lowList << 35.0 << 105.0 << 170.0 << 105.0 << 35.0; -// lowList << 15.0 << 65.0 << 105.0 << 65.0 << 16.1; - -// surfaceChart->appendSeries(lowList, 9, 5); - -// QList<qreal> topList; -// topList << 2.1 << 2.2; -// surfaceChart.appendSeries(topList); - -// surfaceChart.resize(screenSize.width() / 1.5, screenSize.height() / 1.5); -// surfaceChart.setPosition(screenSize.width() / 6, screenSize.height() / 6); -// surfaceChart.show(); - return app.exec(); } diff --git a/src/datavisualization/data/qsurfacedataproxy.cpp b/src/datavisualization/data/qsurfacedataproxy.cpp index 5d284501..5ec5f05d 100644 --- a/src/datavisualization/data/qsurfacedataproxy.cpp +++ b/src/datavisualization/data/qsurfacedataproxy.cpp @@ -241,7 +241,7 @@ QSurfaceDataProxyPrivate::QSurfaceDataProxyPrivate(QSurfaceDataProxy *q) m_minValueColumns(0.0), m_maxValueColumns(0.0) { - m_itemLabelFormat = QStringLiteral("(@yLabel)"); + m_itemLabelFormat = QStringLiteral("@yLabel (@xLabel, @zLabel)"); } QSurfaceDataProxyPrivate::~QSurfaceDataProxyPrivate() diff --git a/src/datavisualization/engine/q3dsurface.cpp b/src/datavisualization/engine/q3dsurface.cpp index 0bec5a8b..f61b35d4 100644 --- a/src/datavisualization/engine/q3dsurface.cpp +++ b/src/datavisualization/engine/q3dsurface.cpp @@ -220,7 +220,7 @@ void Q3DSurface::mouseMoveEvent(QMouseEvent *event) */ void Q3DSurface::wheelEvent(QWheelEvent *event) { - Q_UNUSED(event) + d_ptr->m_shared->wheelEvent(event); } /*! @@ -264,6 +264,40 @@ bool Q3DSurface::isBackgroundVisible() const } /*! + * Sets a predefined \a theme from \c QDataVis::ColorTheme. It is preset to \c QDataVis::ThemeSystem by + * default. Theme affects label colors, text color, background color, window color and + * grid color. Lighting is also adjusted by themes. + * + * \sa setObjectColor() + * + * \warning This method is subject to change. + */ +void Q3DSurface::setTheme(QDataVis::ColorTheme theme) +{ + d_ptr->m_shared->setColorTheme(theme); +} + +/*! + * \property Q3DSurface::shadowQuality + * + * Sets shadow \a quality to one of \c QDataVis::ShadowQuality. It is preset to + * \c QDataVis::ShadowMedium by default. + * + * \note If setting QDataVis::ShadowQuality of a certain level fails, a level is lowered + * until it is successful and shadowQualityChanged signal is emitted for each time the change is + * done. + */ +void Q3DSurface::setShadowQuality(QDataVis::ShadowQuality quality) +{ + return d_ptr->m_shared->setShadowQuality(quality); +} + +QDataVis::ShadowQuality Q3DSurface::shadowQuality() const +{ + return d_ptr->m_shared->shadowQuality(); +} + +/*! * \property Q3DSurface::smoothSurfaceEnabled * * Sets surface smoothing to \a enabled. It is preset to \c false by default. @@ -294,6 +328,37 @@ bool Q3DSurface::isSurfaceGridEnabled() const } /*! + * \property Q3DSurface::font + * + * Sets the \a font for labels. It is preset to \c Arial by default. + */ +void Q3DSurface::setFont(const QFont &font) +{ + d_ptr->m_shared->setFont(font); +} + +QFont Q3DSurface::font() const +{ + return d_ptr->m_shared->font(); +} + +/*! + * \property Q3DSurface::labelTransparency + * + * Sets label \a transparency to one of \c QDataVis::LabelTransparency. It is preset to + * \c QDataVis::TransparencyFromTheme by default. + */ +void Q3DSurface::setLabelTransparency(QDataVis::LabelTransparency transparency) +{ + d_ptr->m_shared->setLabelTransparency(transparency); +} + +QDataVis::LabelTransparency Q3DSurface::labelTransparency() const +{ + return d_ptr->m_shared->labelTransparency(); +} + +/*! * Sets window \a width. */ void Q3DSurface::setWidth(const int width) diff --git a/src/datavisualization/engine/q3dsurface.h b/src/datavisualization/engine/q3dsurface.h index ce057555..cfcc1deb 100644 --- a/src/datavisualization/engine/q3dsurface.h +++ b/src/datavisualization/engine/q3dsurface.h @@ -21,6 +21,7 @@ #include <QtDataVisualization/qdatavisualizationenums.h> #include <QtDataVisualization/q3dwindow.h> +#include <QFont> QT_DATAVISUALIZATION_BEGIN_NAMESPACE @@ -31,10 +32,14 @@ class QSurfaceDataProxy; class QT_DATAVISUALIZATION_EXPORT Q3DSurface : public Q3DWindow { Q_OBJECT + Q_PROPERTY(QtDataVisualization::QDataVis::LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) + Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) Q_PROPERTY(bool smoothSurfaceEnabled READ isSmoothSurfaceEnabled WRITE setSmoothSurfaceEnabled) Q_PROPERTY(bool surfaceGridEnabled READ isSurfaceGridEnabled WRITE setSurfaceGridEnabled) + Q_PROPERTY(QFont font READ font WRITE setFont) + Q_ENUMS(QtDataVisualization::QDataVis::LabelTransparency) public: explicit Q3DSurface(); @@ -48,6 +53,11 @@ public: void setBackgroundVisible(bool visible); bool isBackgroundVisible() const; + void setTheme(QDataVis::ColorTheme theme); + + void setShadowQuality(QDataVis::ShadowQuality quality); + QDataVis::ShadowQuality shadowQuality() const; + // Enable or disable the smoothes of the surface void setSmoothSurfaceEnabled(bool enabled); bool isSmoothSurfaceEnabled() const; @@ -75,6 +85,12 @@ public: void releaseDataProxy(QSurfaceDataProxy *proxy); QList<QSurfaceDataProxy *> dataProxies() const; + void setFont(const QFont &font); + QFont font() const; + + void setLabelTransparency(QDataVis::LabelTransparency transparency); + QDataVis::LabelTransparency labelTransparency() const; + // TODO: Do these need to be public? Where are they called from? // Size void setWidth(const int width); diff --git a/src/datavisualization/engine/selectionpointer.cpp b/src/datavisualization/engine/selectionpointer.cpp index a19f3e82..53c0b816 100644 --- a/src/datavisualization/engine/selectionpointer.cpp +++ b/src/datavisualization/engine/selectionpointer.cpp @@ -33,7 +33,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE -SelectionPointer::SelectionPointer(Surface3DController *controller) +SelectionPointer::SelectionPointer(Surface3DController *controller, Drawer *drawer) : QObject(controller), m_controller(controller), m_labelShader(0), @@ -43,11 +43,13 @@ SelectionPointer::SelectionPointer(Surface3DController *controller) m_textureHelper(0), m_isInitialized(false), m_cachedScene(0), - m_font(QFont(QStringLiteral("Arial"))), m_labelTransparency(QDataVis::TransparencyFromTheme), - m_drawer(new Drawer(m_cachedTheme, m_font, m_labelTransparency)) + m_drawer(drawer) { initializeOpenGL(); + + QObject::connect(m_drawer, &Drawer::drawerChanged, + this, &SelectionPointer::updateLabel); } SelectionPointer::~SelectionPointer() @@ -57,8 +59,6 @@ SelectionPointer::~SelectionPointer() delete m_labelObj; delete m_pointObj; delete m_textureHelper; - delete m_drawer; - delete m_cachedScene; } void SelectionPointer::initializeOpenGL() @@ -84,9 +84,7 @@ void SelectionPointer::initializeOpenGL() void SelectionPointer::updateScene(Q3DScene *scene) { - Q_UNUSED(scene) - // Synchronize the scenes - // TODO + m_cachedScene = scene; } void SelectionPointer::render(GLuint defaultFboHandle) @@ -106,7 +104,7 @@ void SelectionPointer::render(GLuint defaultFboHandle) itModelMatrix.scale(m_scale); // Calculate scale factor to get uniform font size - GLfloat scaledFontSize = 0.05f + m_font.pointSizeF() / 500.0f; + GLfloat scaledFontSize = 0.05f + m_drawer->font().pointSizeF() / 500.0f; GLfloat scaleFactor = scaledFontSize / (GLfloat)textureSize.height(); // Set up projection matrix @@ -208,15 +206,16 @@ void SelectionPointer::setScaling(QVector3D scaling) void SelectionPointer::setLabel(QString label) { + m_label = label; + m_labelItem.clear(); // Print label into a QImage - QImage image = Utils::printTextToImage(m_font, + QImage image = Utils::printTextToImage(m_drawer->font(), label, m_cachedTheme.m_textBackgroundColor, m_cachedTheme.m_textColor, m_labelTransparency); - //label.save("C:\\Users\\misalmel\\Work\\gerrit\\qtdatavisualization_2\\notification.png"); // Set label size m_labelItem.setSize(image.size()); @@ -224,6 +223,11 @@ void SelectionPointer::setLabel(QString label) m_labelItem.setTextureId(m_textureHelper->create2DTexture(image, true, true)); } +void SelectionPointer::updateLabel() +{ + setLabel(m_label); +} + void SelectionPointer::updateTheme(Theme theme) { m_cachedTheme.setFromTheme(theme); diff --git a/src/datavisualization/engine/selectionpointer_p.h b/src/datavisualization/engine/selectionpointer_p.h index 67867232..d13dffaa 100644 --- a/src/datavisualization/engine/selectionpointer_p.h +++ b/src/datavisualization/engine/selectionpointer_p.h @@ -56,7 +56,7 @@ class QT_DATAVISUALIZATION_EXPORT SelectionPointer : public QObject, protected Q Q_OBJECT public: - explicit SelectionPointer(Surface3DController *controller); + explicit SelectionPointer(Surface3DController *controller, Drawer *drawer); ~SelectionPointer(); void initializeOpenGL(); @@ -64,6 +64,7 @@ public: void setPosition(QVector3D position); void setScaling(QVector3D scaling); void setLabel(QString label); + void updateLabel(); void updateTheme(Theme theme); void updateBoundingRect(QRect rect); void updateScene(Q3DScene *scene); @@ -81,7 +82,6 @@ private: ObjectHelper *m_pointObj; TextureHelper *m_textureHelper; bool m_isInitialized; - QFont m_font; Theme m_cachedTheme; QDataVis::LabelTransparency m_labelTransparency; LabelItem m_labelItem; @@ -90,6 +90,7 @@ private: QVector3D m_position; QVector3D m_scale; Q3DScene *m_cachedScene; + QString m_label; }; QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp index fa13a995..dbd1969a 100644 --- a/src/datavisualization/engine/surface3dcontroller.cpp +++ b/src/datavisualization/engine/surface3dcontroller.cpp @@ -34,8 +34,8 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE Surface3DController::Surface3DController(QRect rect) : Abstract3DController(rect), m_renderer(0), - m_smoothSurface(false), - m_surfaceGrid(true) + m_isSmoothSurfaceEnabled(false), + m_isSurfaceGridEnabled(true) { setActiveDataProxy(0); @@ -47,6 +47,9 @@ Surface3DController::Surface3DController(QRect rect) setAxisZ(0); QObject::connect(m_activeInputHandler, &QAbstract3DInputHandler::selectionAtPoint, this, &Surface3DController::handleSelectionAtPoint); + + // Set the default from the theme + m_userDefinedGradient = theme().m_surfaceGradient; } Surface3DController::~Surface3DController() @@ -73,6 +76,21 @@ void Surface3DController::synchDataToRenderer() return; // Notify changes to renderer + if (m_changeTracker.gradientColorChanged) { + m_renderer->updateSurfaceGradient(m_userDefinedGradient); + m_changeTracker.gradientColorChanged = false; + } + + if (m_changeTracker.smoothStatusChanged) { + m_isSmoothSurfaceEnabled = m_renderer->updateSmoothStatus(m_isSmoothSurfaceEnabled); + m_changeTracker.smoothStatusChanged = false; + } + + if (m_changeTracker.surfaceGridChanged) { + m_renderer->updateSurfaceGridStatus(m_isSurfaceGridEnabled); + m_changeTracker.surfaceGridChanged = false; + } + if (m_isDataDirty) { m_renderer->updateDataModel(static_cast<QSurfaceDataProxy *>(m_data)); m_isDataDirty = false; @@ -89,26 +107,33 @@ void Surface3DController::handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstr void Surface3DController::setSmoothSurface(bool enable) { - m_smoothSurface = enable; - emit smoothStatusChanged(m_smoothSurface); + m_isSmoothSurfaceEnabled = enable; + m_changeTracker.smoothStatusChanged = true; emitNeedRender(); } bool Surface3DController::smoothSurface() { - return m_smoothSurface; + return m_isSmoothSurfaceEnabled; } void Surface3DController::setSurfaceGrid(bool enable) { - m_surfaceGrid = enable; - emit surfaceGridChanged(m_surfaceGrid); + m_isSurfaceGridEnabled = enable; + m_changeTracker.surfaceGridChanged = true; emitNeedRender(); } bool Surface3DController::surfaceGrid() { - return m_surfaceGrid; + return m_isSurfaceGridEnabled; +} + +void Surface3DController::setGradientColorAt(qreal pos, const QColor &color) +{ + m_userDefinedGradient.setColorAt(pos, color); + m_changeTracker.gradientColorChanged = true; + emitNeedRender(); } void Surface3DController::setActiveDataProxy(QAbstractDataProxy *proxy) @@ -136,12 +161,6 @@ void Surface3DController::handleArrayReset() emitNeedRender(); } -void Surface3DController::setGradientColorAt(qreal pos, const QColor &color) -{ - Theme t = theme(); - t.m_surfaceGradient.setColorAt(pos, color); - emitNeedRender(); -} void Surface3DController::handleSelectionAtPoint(const QPoint &point) { diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h index 55597922..290b18b4 100644 --- a/src/datavisualization/engine/surface3dcontroller_p.h +++ b/src/datavisualization/engine/surface3dcontroller_p.h @@ -38,21 +38,31 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Surface3DRenderer; +struct Surface3DChangeBitField { + bool gradientColorChanged : 1; + bool smoothStatusChanged : 1; + bool surfaceGridChanged : 1; + + Surface3DChangeBitField() : + gradientColorChanged(true), + smoothStatusChanged(true), + surfaceGridChanged(true) + { + } +}; + class QT_DATAVISUALIZATION_EXPORT Surface3DController : public Abstract3DController { Q_OBJECT private: + Surface3DChangeBitField m_changeTracker; + + // Rendering Surface3DRenderer *m_renderer; - QList<qreal> m_series; // TODO: TEMP - int m_dataWidth; - int m_dataDepth; - bool m_smoothSurface; - bool m_surfaceGrid; - - GLint m_segmentCount; - GLfloat m_segmentStep; - GLfloat m_segmentMinimum; + bool m_isSmoothSurfaceEnabled; + bool m_isSurfaceGridEnabled; + QLinearGradient m_userDefinedGradient; public: explicit Surface3DController(QRect rect); diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index ed07da4e..a212b9fd 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -54,7 +54,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) m_labelTransparency(QDataVis::TransparencyFromTheme), m_font(QFont(QStringLiteral("Arial"))), m_isGridEnabled(true), - m_shadowQuality(QDataVis::ShadowLow), m_segmentYCount(0), m_segmentYStep(0.0f), m_shader(0), @@ -80,21 +79,28 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) m_selectionResultTexture(0), m_shadowQualityToShader(33.3f), m_querySelection(false), + m_flatSupported(true), m_selectionPointer(0), m_selectionActive(false), m_xFlipped(false), m_zFlipped(false), m_yFlipped(false), - m_sampleSpace(QRect(0, 0, 0, 0)) + m_sampleSpace(QRect(0, 0, 0, 0)), + m_shadowQualityMultiplier(3), + m_hasHeightAdjustmentChanged(true) { // Listen to changes in the controller - QObject::connect(m_controller, &Surface3DController::smoothStatusChanged, this, - &Surface3DRenderer::updateSmoothStatus); - QObject::connect(m_controller, &Surface3DController::surfaceGridChanged, this, - &Surface3DRenderer::updateSurfaceGridStatus); QObject::connect(m_controller, &Surface3DController::leftMousePressed, this, &Surface3DRenderer::requestSelectionAtPoint); // TODO: Possible temp + // Check if flat feature is supported + ShaderHelper tester(this, QStringLiteral(":/shaders/vertexSurfaceFlat"), + QStringLiteral(":/shaders/fragmentSurfaceFlat")); + if (!tester.testCompile()) { + m_flatSupported = false; + m_controller->setSmoothSurface(true); + } + m_cachedSmoothSurface = m_controller->smoothSurface(); updateSurfaceGridStatus(m_controller->surfaceGrid()); @@ -160,8 +166,6 @@ void Surface3DRenderer::initializeOpenGL() // Load background mesh (we need to be initialized first) loadBackgroundMesh(); - - updateSurfaceGradient(); } void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy) @@ -184,6 +188,16 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy) m_dataArray << newRow; } + // If data contains only one row, duplicate it to make surface + if (sampleSpace.height() == 1) + m_dataArray << m_dataArray.last(); + + // If data contains only one column, duplicate the value to make surface + if (sampleSpace.width() == 1) { + for (int i = 0; i < sampleSpace.height(); i++) + (*m_dataArray.at(i)) << m_dataArray.at(i)->last(); + } + if (m_dataArray.size() > 0) { if (!m_surfaceObj) loadSurfaceObj(); @@ -247,35 +261,32 @@ void Surface3DRenderer::updateScene(Q3DScene *scene) scene->setMainViewport(m_mainViewPort); scene->setUnderSideCameraEnabled(m_hasNegativeValues); - // TODO: bars have m_hasHeightAdjustmentChanged, which is always true! // Set initial camera position // X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later - scene->camera()->setDefaultOrientation(QVector3D(0.0f, 0.0f, 6.0f + zComp), - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); + if (m_hasHeightAdjustmentChanged) { + scene->camera()->setDefaultOrientation(QVector3D(0.0f, 0.0f, 6.0f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + // For now this is used just to make things once. Proper use will come + m_hasHeightAdjustmentChanged = false; + } - // TODO: m_autoScaleAdjustment - scene->camera()->updateViewMatrix(1.0f); + scene->camera()->updateViewMatrix(m_autoScaleAdjustment); scene->setLightPositionRelativeToCamera(defaultLightPos); + if (m_selectionPointer) + m_selectionPointer->updateScene(scene); + Abstract3DRenderer::updateScene(scene); } void Surface3DRenderer::render(GLuint defaultFboHandle) { m_cachedScene->setUnderSideCameraEnabled(m_hasNegativeValues); - if (defaultFboHandle) { - glDepthMask(true); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - } - - QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme.m_windowColor); - glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // Handle GL state setup for FBO buffers and clearing of the render surface + Abstract3DRenderer::render(defaultFboHandle); + // Draw the surface scene drawScene(defaultFboHandle); // If selection pointer is active, pass the render request for it also @@ -297,9 +308,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) projectionMatrix.perspective(45.0f, (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f); - // Calculate view matrix TODO: m_autoScaleAdjustment - camera->updateViewMatrix(1.0f); - QMatrix4x4 viewMatrix = camera->viewMatrix(); + // Calculate view matrix + QMatrix4x4 viewMatrix = m_cachedScene->camera()->viewMatrix(); // Calculate flipping indicators if (viewMatrix.row(0).x() > 0) @@ -377,7 +387,6 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) // Draw the triangles glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), m_surfaceObj->indicesType(), (void *)0); - //m_drawer->drawObject(m_selectionShader, m_surfaceObj, m_selectionTexture, 0); // Free buffers glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -521,7 +530,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) m_cachedTheme.m_ambientStrength * 2.0f); #if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowNone) { // Set shadow shader bindings m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), m_shadowQualityToShader); @@ -944,11 +953,11 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) } -void Surface3DRenderer::updateSurfaceGradient() +void Surface3DRenderer::updateSurfaceGradient(const QLinearGradient &gradient) { QImage image(QSize(4, 100), QImage::Format_RGB32); QPainter pmp(&image); - pmp.setBrush(QBrush(m_cachedTheme.m_surfaceGradient)); + pmp.setBrush(QBrush(gradient)); pmp.setPen(Qt::NoPen); pmp.drawRect(0, 0, 4, 100); @@ -1078,12 +1087,20 @@ void Surface3DRenderer::calculateSceneScalingFactors() m_scaleZ = (coordSpace * m_sampleSpace.height()) / m_scaleFactor; } -void Surface3DRenderer::updateSmoothStatus(bool enable) +bool Surface3DRenderer::updateSmoothStatus(bool enable) { m_cachedSmoothSurface = enable; + if (!m_cachedSmoothSurface && !m_flatSupported) { + qWarning() << "Warning: Flat qualifier not supported on your platform's GLSL language." + " Requires at least GLSL version 1.5."; + m_cachedSmoothSurface = true; + } if (!m_surfaceObj) - return; + return m_cachedSmoothSurface; + + if (m_cachedSmoothSurface == false && !m_flatSupported) + m_cachedSmoothSurface = true; if (m_cachedSmoothSurface) m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer, true); @@ -1091,6 +1108,8 @@ void Surface3DRenderer::updateSmoothStatus(bool enable) m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer, true); initSurfaceShaders(); + + return m_cachedSmoothSurface; } void Surface3DRenderer::updateSurfaceGridStatus(bool enable) @@ -1146,30 +1165,46 @@ void Surface3DRenderer::updateDepthBuffer() m_depthTexture = 0; } - // TODO: bars uses some m_cachedShadowQuality - if (m_shadowQuality > QDataVis::ShadowNone && !m_mainViewPort.size().isEmpty()) { + if (m_cachedShadowQuality > QDataVis::ShadowNone && !m_mainViewPort.size().isEmpty()) { m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(), m_depthFrameBuffer, - m_shadowQuality); + m_shadowQualityMultiplier); if (!m_depthTexture) { - qDebug() << "Failed to create m_depthTexture"; - // switch (m_shadowQuality) { - // case ShadowHigh: - // qWarning("Creating high quality shadows failed. Changing to medium quality."); - // (void)setShadowQuality(ShadowMedium); - // break; - // case ShadowMedium: - // qWarning("Creating medium quality shadows failed. Changing to low quality."); - // (void)setShadowQuality(ShadowLow); - // break; - // case ShadowLow: - // qWarning("Creating low quality shadows failed. Switching shadows off."); - // (void)setShadowQuality(ShadowNone); - // break; - // default: - // // You'll never get here - // break; - // } + switch (m_cachedShadowQuality) { + case QDataVis::ShadowHigh: + qWarning("Creating high quality shadows failed. Changing to medium quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowMedium); + updateShadowQuality(QDataVis::ShadowMedium); + break; + case QDataVis::ShadowMedium: + qWarning("Creating medium quality shadows failed. Changing to low quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowLow); + updateShadowQuality(QDataVis::ShadowLow); + break; + case QDataVis::ShadowLow: + qWarning("Creating low quality shadows failed. Switching shadows off."); + (void)m_controller->setShadowQuality(QDataVis::ShadowNone); + updateShadowQuality(QDataVis::ShadowNone); + break; + case QDataVis::ShadowSoftHigh: + qWarning("Creating soft high quality shadows failed. Changing to soft medium quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowSoftMedium); + updateShadowQuality(QDataVis::ShadowSoftMedium); + break; + case QDataVis::ShadowSoftMedium: + qWarning("Creating soft medium quality shadows failed. Changing to soft low quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowSoftLow); + updateShadowQuality(QDataVis::ShadowSoftLow); + break; + case QDataVis::ShadowSoftLow: + qWarning("Creating soft low quality shadows failed. Switching shadows off."); + (void)m_controller->setShadowQuality(QDataVis::ShadowNone); + updateShadowQuality(QDataVis::ShadowNone); + break; + default: + // You'll never get here + break; + } } } } @@ -1182,17 +1217,75 @@ void Surface3DRenderer::surfacePointSelected(int id) qreal value = m_dataArray.at(row)->at(column); if (!m_selectionPointer) - m_selectionPointer = new SelectionPointer(m_controller); + m_selectionPointer = new SelectionPointer(m_controller, m_drawer); m_selectionPointer->setPosition(normalize(float(column), value, float(row))); m_selectionPointer->setScaling(QVector3D(m_scaleX, 1.0f, m_scaleZ)); - m_selectionPointer->setLabel(QString::number(value)); + m_selectionPointer->setLabel(createSelectionLabel(value, column, row)); m_selectionPointer->updateBoundingRect(m_mainViewPort); + m_selectionPointer->updateScene(m_cachedScene); //Put the selection pointer flag active m_selectionActive = true; } +QString Surface3DRenderer::createSelectionLabel(qreal value, int column, int row) +{ + QString labelText = itemLabelFormat(); + static const QString xTitleTag(QStringLiteral("@xTitle")); + static const QString yTitleTag(QStringLiteral("@yTitle")); + static const QString zTitleTag(QStringLiteral("@zTitle")); + static const QString xLabelTag(QStringLiteral("@xLabel")); + static const QString yLabelTag(QStringLiteral("@yLabel")); + static const QString zLabelTag(QStringLiteral("@zLabel")); + + labelText.replace(xTitleTag, m_axisCacheX.title()); + labelText.replace(yTitleTag, m_axisCacheY.title()); + labelText.replace(zTitleTag, m_axisCacheZ.title()); + + if (labelText.contains(xLabelTag)) { + QString labelFormat = m_axisCacheX.labelFormat(); + if (labelFormat.isEmpty()) + labelFormat = Utils::defaultLabelFormat(); + QString valueLabelText = generateValueLabel(labelFormat, columnInRange(column)); + labelText.replace(xLabelTag, valueLabelText); + } + if (labelText.contains(yLabelTag)) { + QString labelFormat = m_axisCacheY.labelFormat(); + if (labelFormat.isEmpty()) + labelFormat = Utils::defaultLabelFormat(); + QString valueLabelText = generateValueLabel(labelFormat, value); + labelText.replace(yLabelTag, valueLabelText); + } + if (labelText.contains(zLabelTag)) { + QString labelFormat = m_axisCacheZ.labelFormat(); + if (labelFormat.isEmpty()) + labelFormat = Utils::defaultLabelFormat(); + QString valueLabelText = generateValueLabel(labelFormat, rowInRange(row)); + labelText.replace(zLabelTag, valueLabelText); + } + + return labelText; +} + +// Transforms the model column coordinate to axis coordinate +qreal Surface3DRenderer::columnInRange(int column) +{ + // At this point we'll work only with fixed grid and demand that the user uses proper steps on + // value axis. Zero prevented when doing duplicate from the data. + qreal stepInRange = (m_axisCacheX.max() - m_axisCacheX.min()) / qreal(m_dataArray.at(0)->size() - 1); + return stepInRange * qreal(column) + m_axisCacheX.min(); +} + +// Transforms the model row coordinate to axis coordinate +qreal Surface3DRenderer::rowInRange(int row) +{ + // At this point we'll work only with fixed grid and demand that the user uses proper steps on + // value axis. Zero prevented when doing duplicate from the data. + qreal stepInRange = (m_axisCacheZ.max() - m_axisCacheZ.min()) / qreal(m_dataArray.size() - 1); + return stepInRange * qreal(row) + m_axisCacheZ.min(); +} + QVector3D Surface3DRenderer::normalize(float x, float y, float z) { float resX = x / ((float(m_sampleSpace.width()) - 1.0f) / 2.0f) - 1.0f; @@ -1218,8 +1311,39 @@ void Surface3DRenderer::loadMeshFile() void Surface3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality) { - Q_UNUSED(quality) - qDebug() << __FUNCTION__ << "NEED TO DO SOMETHING"; + m_cachedShadowQuality = quality; + switch (quality) { + case QDataVis::ShadowLow: + m_shadowQualityToShader = 33.3f; + m_shadowQualityMultiplier = 1; + break; + case QDataVis::ShadowMedium: + m_shadowQualityToShader = 100.0f; + m_shadowQualityMultiplier = 3; + break; + case QDataVis::ShadowHigh: + m_shadowQualityToShader = 200.0f; + m_shadowQualityMultiplier = 5; + break; + case QDataVis::ShadowSoftLow: + m_shadowQualityToShader = 5.0f; + m_shadowQualityMultiplier = 1; + break; + case QDataVis::ShadowSoftMedium: + m_shadowQualityToShader = 10.0f; + m_shadowQualityMultiplier = 3; + break; + case QDataVis::ShadowSoftHigh: + m_shadowQualityToShader = 15.0f; + m_shadowQualityMultiplier = 4; + break; + default: + m_shadowQualityToShader = 0.0f; + m_shadowQualityMultiplier = 1; + break; + } + + updateDepthBuffer(); } void Surface3DRenderer::loadLabelMesh() diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index fd8b15a9..771ecce4 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -64,11 +64,9 @@ public: // Visual parameters QRect m_boundingRect; - Theme m_cachedTheme; QDataVis::LabelTransparency m_labelTransparency; QFont m_font; bool m_isGridEnabled; - QDataVis::ShadowQuality m_shadowQuality; private: // Data parameters @@ -102,15 +100,19 @@ private: GLfloat m_shadowQualityToShader; bool m_querySelection; bool m_cachedSmoothSurface; + bool m_flatSupported; bool m_cachedSurfaceGridOn; SelectionPointer *m_selectionPointer; bool m_selectionActive; bool m_xFlipped; bool m_zFlipped; bool m_yFlipped; - ScatterRenderItem m_dummyRenderItem; // Let's use scatter for dummy for now + AbstractRenderItem m_dummyRenderItem; QSurfaceDataArray m_dataArray; QRect m_sampleSpace; + GLint m_shadowQualityMultiplier; + + bool m_hasHeightAdjustmentChanged; public: explicit Surface3DRenderer(Surface3DController *controller); @@ -125,9 +127,9 @@ protected: virtual void loadMeshFile(); public slots: - void updateSmoothStatus(bool enable); + bool updateSmoothStatus(bool enable); void updateSurfaceGridStatus(bool enable); - void updateSurfaceGradient(); + void updateSurfaceGradient(const QLinearGradient &gradient); virtual void requestSelectionAtPoint(const QPoint &point); private: @@ -151,6 +153,9 @@ private: void idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a); void fillIdCorner(uchar *p, uchar r, uchar g, uchar b, uchar a, int stride); void surfacePointSelected(int id); + QString createSelectionLabel(qreal value, int column, int row); + qreal columnInRange(int column); + qreal rowInRange(int row); void surfacePointCleared(); QVector3D normalize(float x, float y, float z); #if !defined(QT_OPENGL_ES_2) diff --git a/src/datavisualization/utils/shaderhelper.cpp b/src/datavisualization/utils/shaderhelper.cpp index 508bc90a..7df1736c 100644 --- a/src/datavisualization/utils/shaderhelper.cpp +++ b/src/datavisualization/utils/shaderhelper.cpp @@ -86,6 +86,18 @@ void ShaderHelper::initialize() m_initialized = true; } +bool ShaderHelper::testCompile() +{ + if (m_program) + delete m_program; + m_program = new QOpenGLShaderProgram(m_caller); + if (!m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, m_vertexShaderFile)) + return false; + if (!m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, m_fragmentShaderFile)) + return false; + return true; +} + void ShaderHelper::bind() { m_program->bind(); diff --git a/src/datavisualization/utils/shaderhelper_p.h b/src/datavisualization/utils/shaderhelper_p.h index 72a7b256..73e5b9ee 100644 --- a/src/datavisualization/utils/shaderhelper_p.h +++ b/src/datavisualization/utils/shaderhelper_p.h @@ -50,6 +50,7 @@ class ShaderHelper void setTextures(const QString &texture, const QString &depthTexture); void initialize(); + bool testCompile(); void bind(); void release(); void setUniformValue(GLuint uniform, const QVector3D &value); |