diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-08-06 14:48:59 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-08-07 08:25:50 +0300 |
commit | 54fde3bd0b61a696977cb1cb680d482eb0112156 (patch) | |
tree | 40fb846d5daf47f07fb287c3cfdd9ceaa3aef080 | |
parent | 6fdda6d560fafb086501cfc60616d84324bb6cb0 (diff) |
Implement axis caching to renderer.
Axis properties are passed via signals from controller
to renderer.
Change-Id: Iaa0e47c4ea4dc0b586480f260b42958af95c028d
Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
23 files changed, 547 insertions, 400 deletions
diff --git a/src/datavis3d/axis/qabstractaxis.cpp b/src/datavis3d/axis/qabstractaxis.cpp index 4b3de4ff..ba215fd1 100644 --- a/src/datavis3d/axis/qabstractaxis.cpp +++ b/src/datavis3d/axis/qabstractaxis.cpp @@ -78,9 +78,6 @@ void QAbstractAxis::setTitle(QString title) { if (d_ptr->m_title != title) { d_ptr->m_title = title; - // Generate axis label texture - if (d_ptr->m_drawer) - d_ptr->m_drawer->generateLabelItem(d_ptr->m_titleItem, title); emit titleChanged(title); } } @@ -90,7 +87,6 @@ void QAbstractAxis::setTitle(QString title) QAbstractAxisPrivate::QAbstractAxisPrivate(QAbstractAxis *q, QAbstractAxis::AxisType type) : QObject(0), q_ptr(q), - m_drawer(0), m_orientation(QAbstractAxis::AxisOrientationNone), m_type(type) { @@ -98,18 +94,6 @@ QAbstractAxisPrivate::QAbstractAxisPrivate(QAbstractAxis *q, QAbstractAxis::Axis QAbstractAxisPrivate::~QAbstractAxisPrivate() { - m_titleItem.clear(); - for (int i = 0; i < m_labelItems.size(); i++) - delete m_labelItems[i]; -} - -void QAbstractAxisPrivate::setDrawer(Drawer *drawer) -{ - m_drawer = drawer; - if (m_drawer) { - QObject::connect(m_drawer, &Drawer::drawerChanged, this, &QAbstractAxisPrivate::updateTextures); - updateTextures(); - } } void QAbstractAxisPrivate::setOrientation(QAbstractAxis::AxisOrientation orientation) @@ -120,19 +104,4 @@ void QAbstractAxisPrivate::setOrientation(QAbstractAxis::AxisOrientation orienta Q_ASSERT("Attempted to reset axis orientation."); } -void QAbstractAxisPrivate::updateTextures() -{ - if (m_title.isEmpty()) - m_titleItem.clear(); - else - m_drawer->generateLabelItem(m_titleItem, m_title); - - updateLabels(); -} - -void QAbstractAxisPrivate::updateLabels() -{ - // Default implementation does nothing. -} - QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qabstractaxis.h b/src/datavis3d/axis/qabstractaxis.h index 97823381..f8c799ac 100644 --- a/src/datavis3d/axis/qabstractaxis.h +++ b/src/datavis3d/axis/qabstractaxis.h @@ -73,7 +73,7 @@ public: AxisTypeNone = 0, AxisTypeCategory = 1, AxisTypeValue = 2 - //AxisTypeLogValue = 4 // TODO + //AxisTypeLogValue = 6 // inherits valueaxis (4 + 2) // TODO }; protected: @@ -92,6 +92,7 @@ public slots: signals: void titleChanged(QString newTitle); + void labelsChanged(); protected: QScopedPointer<QAbstractAxisPrivate> d_ptr; @@ -100,10 +101,6 @@ private: Q_DISABLE_COPY(QAbstractAxis) friend class Abstract3DController; - friend class Bars3dController; - friend class Bars3dRenderer; - friend class Scatter3DController; - friend class Scatter3DRenderer; }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qabstractaxis_p.h b/src/datavis3d/axis/qabstractaxis_p.h index 3f1b2547..abe20ae5 100644 --- a/src/datavis3d/axis/qabstractaxis_p.h +++ b/src/datavis3d/axis/qabstractaxis_p.h @@ -50,8 +50,6 @@ // We mean it. #include "qabstractaxis.h" -#include "drawer_p.h" -#include "labelitem_p.h" #ifndef QABSTRACTAXIS_P_H #define QABSTRACTAXIS_P_H @@ -65,26 +63,13 @@ public: QAbstractAxisPrivate(QAbstractAxis *q, QAbstractAxis::AxisType type); virtual ~QAbstractAxisPrivate(); - void setDrawer(Drawer *drawer); - QList<LabelItem *> &labelItems() { return m_labelItems; } - LabelItem &titleItem() { return m_titleItem; } void setOrientation(QAbstractAxis::AxisOrientation orientation); -public slots: - void updateTextures(); - protected: - virtual void updateLabels(); - QAbstractAxis *q_ptr; QString m_title; - // TODO: Does m_titleItem/m_drawer/m_labelItems usage need to be protected with render mutex? - // TODO: Replace Drawer with AbstractRenderer? - LabelItem m_titleItem; - Drawer *m_drawer; // not owned QStringList m_labels; - QList<LabelItem *> m_labelItems; QAbstractAxis::AxisOrientation m_orientation; QAbstractAxis::AxisType m_type; diff --git a/src/datavis3d/axis/qcategoryaxis.cpp b/src/datavis3d/axis/qcategoryaxis.cpp index 80dc8fdb..aa3e2cc9 100644 --- a/src/datavis3d/axis/qcategoryaxis.cpp +++ b/src/datavis3d/axis/qcategoryaxis.cpp @@ -55,26 +55,10 @@ QCategoryAxis::~QCategoryAxis() void QCategoryAxis::setLabels(const QStringList &labels) { - int newSize(labels.size()); - int oldSize(d_ptr->m_labels.size()); - - for (int i = newSize; i < oldSize; i++) - delete d_ptr->m_labelItems.takeLast(); - - d_ptr->m_labelItems.reserve(newSize); - - if (d_ptr->m_drawer) { - for (int i = 0; i < newSize; i++) { - if (i >= oldSize) - d_ptr->m_labelItems.append(new LabelItem); - if (labels.at(i).isEmpty()) - d_ptr->m_labelItems[i]->clear(); - else if (i >= oldSize || labels.at(i) != d_ptr->m_labels.at(i)) - d_ptr->m_drawer->generateLabelItem(*d_ptr->m_labelItems[i], labels.at(i)); - } + if (d_ptr->m_labels != labels) { + d_ptr->m_labels = labels; + emit labelsChanged(); } - - d_ptr->m_labels = labels; } QCategoryAxisPrivate *QCategoryAxis::dptr() @@ -91,14 +75,4 @@ QCategoryAxisPrivate::~QCategoryAxisPrivate() { } -void QCategoryAxisPrivate::updateLabels() -{ - for (int i = 0; i < m_labels.size(); i++) { - if (m_labels.at(i).isEmpty()) - m_labelItems[i]->clear(); - else - m_drawer->generateLabelItem(*m_labelItems[i], m_labels.at(i)); - } -} - QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qcategoryaxis_p.h b/src/datavis3d/axis/qcategoryaxis_p.h index bbab23bd..156ca831 100644 --- a/src/datavis3d/axis/qcategoryaxis_p.h +++ b/src/datavis3d/axis/qcategoryaxis_p.h @@ -64,10 +64,7 @@ class QCategoryAxisPrivate : public QAbstractAxisPrivate public: QCategoryAxisPrivate(QCategoryAxis *q); - ~QCategoryAxisPrivate(); - -protected: - void updateLabels(); + virtual ~QCategoryAxisPrivate(); }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qvalueaxis.cpp b/src/datavis3d/axis/qvalueaxis.cpp index 27aa62b0..a4e0c85f 100644 --- a/src/datavis3d/axis/qvalueaxis.cpp +++ b/src/datavis3d/axis/qvalueaxis.cpp @@ -53,23 +53,66 @@ QValueAxis::~QValueAxis() { } +void QValueAxis::setRange(qreal min, qreal max) +{ + bool dirty = false; + if (dptr()->m_min != min) { + dptr()->m_min = min; + dirty = true; + } + if (dptr()->m_max != max) { + dptr()->m_max = max; + dirty = true; + } + if (dirty) + emit rangeChanged(min, max); +} + +void QValueAxis::setMin(qreal min) +{ + if (dptr()->m_min != min) { + dptr()->m_min = min; + emit rangeChanged(min, dptr()->m_max); + } +} + +void QValueAxis::setMax(qreal max) +{ + if (dptr()->m_max != max) { + dptr()->m_max = max; + emit rangeChanged(dptr()->m_min, max); + } +} + +qreal QValueAxis::min() const +{ + return dptrc()->m_min; +} + +qreal QValueAxis::max() const +{ + return dptrc()->m_max; +} + QValueAxisPrivate *QValueAxis::dptr() { return static_cast<QValueAxisPrivate *>(d_ptr.data()); } -QValueAxisPrivate::QValueAxisPrivate(QValueAxis *q) - : QAbstractAxisPrivate(q, QAbstractAxis::AxisTypeValue) +const QValueAxisPrivate *QValueAxis::dptrc() const { + return static_cast<const QValueAxisPrivate *>(d_ptr.data()); } -QValueAxisPrivate::~QValueAxisPrivate() +QValueAxisPrivate::QValueAxisPrivate(QValueAxis *q) + : QAbstractAxisPrivate(q, QAbstractAxis::AxisTypeValue), + m_min(0.0), + m_max(0.0) { } -void QValueAxisPrivate::updateLabels() +QValueAxisPrivate::~QValueAxisPrivate() { - // TODO } QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qvalueaxis.h b/src/datavis3d/axis/qvalueaxis.h index c7b0c3b1..5467b81c 100644 --- a/src/datavis3d/axis/qvalueaxis.h +++ b/src/datavis3d/axis/qvalueaxis.h @@ -55,8 +55,18 @@ public: explicit QValueAxis(); ~QValueAxis(); + void setRange(qreal min, qreal max); + void setMin(qreal min); + void setMax (qreal max); + qreal min() const; + qreal max() const; + +signals: + void rangeChanged(qreal min, qreal max); + protected: QValueAxisPrivate *dptr(); + const QValueAxisPrivate *dptrc() const; private: Q_DISABLE_COPY(QValueAxis) diff --git a/src/datavis3d/axis/qvalueaxis_p.h b/src/datavis3d/axis/qvalueaxis_p.h index 7bcbd3b6..22663eb8 100644 --- a/src/datavis3d/axis/qvalueaxis_p.h +++ b/src/datavis3d/axis/qvalueaxis_p.h @@ -63,10 +63,14 @@ class QValueAxisPrivate : public QAbstractAxisPrivate public: QValueAxisPrivate(QValueAxis *q); - ~QValueAxisPrivate(); + virtual ~QValueAxisPrivate(); protected: - void updateLabels(); + qreal m_min; + qreal m_max; + +private: + friend class QValueAxis; }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/abstract3dcontroller.cpp b/src/datavis3d/engine/abstract3dcontroller.cpp index b9c57265..30e5e694 100644 --- a/src/datavis3d/engine/abstract3dcontroller.cpp +++ b/src/datavis3d/engine/abstract3dcontroller.cpp @@ -41,6 +41,7 @@ #include "abstract3dcontroller_p.h" #include "camerahelper_p.h" #include "qabstractaxis_p.h" +#include "qvalueaxis.h" QT_DATAVIS3D_BEGIN_NAMESPACE @@ -143,14 +144,7 @@ int Abstract3DController::y() void Abstract3DController::setAxisX(QAbstractAxis *axis) { - Q_ASSERT(axis); - - delete m_axisX; - m_axisX = axis; - m_axisX->d_ptr->setOrientation(QAbstractAxis::AxisOrientationX); - m_axisX->d_ptr->setDrawer(drawer()); - - emit axisChanged(QAbstractAxis::AxisOrientationX, m_axisX); + setAxisHelper(QAbstractAxis::AxisOrientationX, axis, &m_axisX); } QAbstractAxis *Abstract3DController::axisX() @@ -160,14 +154,7 @@ QAbstractAxis *Abstract3DController::axisX() void Abstract3DController::setAxisY(QAbstractAxis *axis) { - Q_ASSERT(axis); - - delete m_axisY; - m_axisY = axis; - m_axisY->d_ptr->setOrientation(QAbstractAxis::AxisOrientationY); - m_axisY->d_ptr->setDrawer(drawer()); - - emit axisChanged(QAbstractAxis::AxisOrientationY, m_axisY); + setAxisHelper(QAbstractAxis::AxisOrientationY, axis, &m_axisY); } QAbstractAxis *Abstract3DController::axisY() @@ -177,14 +164,7 @@ QAbstractAxis *Abstract3DController::axisY() void Abstract3DController::setAxisZ(QAbstractAxis *axis) { - Q_ASSERT(axis); - - delete m_axisZ; - m_axisZ = axis; - m_axisZ->d_ptr->setOrientation(QAbstractAxis::AxisOrientationZ); - m_axisZ->d_ptr->setDrawer(drawer()); - - emit axisChanged(QAbstractAxis::AxisOrientationZ, m_axisZ); + setAxisHelper(QAbstractAxis::AxisOrientationZ, axis, &m_axisZ); } QAbstractAxis *Abstract3DController::axisZ() @@ -286,4 +266,67 @@ LabelTransparency Abstract3DController::labelTransparency() return m_labelTransparency; } +void Abstract3DController::handleAxisTitleChanged(const QString &title) +{ + if (sender() == m_axisX) + emit axisTitleChanged(QAbstractAxis::AxisOrientationX, title); + else if (sender() == m_axisY) + emit axisTitleChanged(QAbstractAxis::AxisOrientationY, title); + else if (sender() == m_axisZ) + emit axisTitleChanged(QAbstractAxis::AxisOrientationZ, title); + else + qWarning() << __FUNCTION__ << "invoked for invalid axis"; +} + +void Abstract3DController::handleAxisLabelsChanged() +{ + if (sender() == m_axisX) + emit axisLabelsChanged(QAbstractAxis::AxisOrientationX, m_axisX->labels()); + else if (sender() == m_axisY) + emit axisLabelsChanged(QAbstractAxis::AxisOrientationY, m_axisY->labels()); + else if (sender() == m_axisZ) + emit axisLabelsChanged(QAbstractAxis::AxisOrientationZ, m_axisZ->labels()); + else + qWarning() << __FUNCTION__ << "invoked for invalid axis"; +} + +void Abstract3DController::handleAxisRangeChanged(qreal min, qreal max) +{ + if (sender() == m_axisX) + emit axisRangeChanged(QAbstractAxis::AxisOrientationX, min, max); + else if (sender() == m_axisY) + emit axisRangeChanged(QAbstractAxis::AxisOrientationY, min, max); + else if (sender() == m_axisZ) + emit axisRangeChanged(QAbstractAxis::AxisOrientationZ, min, max); + else + qWarning() << __FUNCTION__ << "invoked for invalid axis"; +} + +void Abstract3DController::setAxisHelper(QAbstractAxis::AxisOrientation orientation, + QAbstractAxis *axis, QAbstractAxis **axisPtr) +{ + Q_ASSERT(axis); + + delete *axisPtr; + *axisPtr = axis; + axis->d_ptr->setOrientation(orientation); + + QObject::connect(axis, &QAbstractAxis::titleChanged, + this, &Abstract3DController::handleAxisTitleChanged); + QObject::connect(axis, &QAbstractAxis::labelsChanged, + this, &Abstract3DController::handleAxisLabelsChanged); + + emit axisTypeChanged(orientation, axis->type()); + emit axisTitleChanged(orientation, axis->title()); + emit axisLabelsChanged(orientation, axis->labels()); + + if (axis->type() & QAbstractAxis::AxisTypeValue) { + QValueAxis *valueAxis = static_cast<QValueAxis *>(axis); + QObject::connect(valueAxis, &QValueAxis::rangeChanged, + this, &Abstract3DController::handleAxisRangeChanged); + emit axisRangeChanged(orientation, valueAxis->min(), valueAxis->max()); + } + +} + QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/abstract3dcontroller_p.h b/src/datavis3d/engine/abstract3dcontroller_p.h index c1856ad9..abf4845a 100644 --- a/src/datavis3d/engine/abstract3dcontroller_p.h +++ b/src/datavis3d/engine/abstract3dcontroller_p.h @@ -160,8 +160,10 @@ public: virtual void setLabelTransparency(LabelTransparency transparency); virtual LabelTransparency labelTransparency(); - // TODO: abstract renderer should have accessor for Drawer instead - virtual Drawer *drawer() = 0; +public slots: + void handleAxisTitleChanged(const QString &title); + void handleAxisLabelsChanged(); + void handleAxisRangeChanged(qreal min, qreal max); signals: void boundingRectChanged(QRect boundingRect); @@ -169,10 +171,16 @@ signals: void positionChanged(QRect boundingRect); void zoomLevelChanged(int zoomLevel); void themeChanged(Theme theme); - void fontChanged(QFont font); + void fontChanged(QFont font); // TODO should be handled via axis?? What about font for selection label? void shadowQualityChanged(ShadowQuality quality); void labelTransparencyUpdated(LabelTransparency transparency); - void axisChanged(QAbstractAxis::AxisOrientation orientation, QAbstractAxis *newAxis); + void axisTypeChanged(QAbstractAxis::AxisOrientation orientation, QAbstractAxis::AxisType type); + void axisTitleChanged(QAbstractAxis::AxisOrientation orientation, QString title); + void axisLabelsChanged(QAbstractAxis::AxisOrientation orientation, QStringList labels); + void axisRangeChanged(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); + +private: + void setAxisHelper(QAbstractAxis::AxisOrientation orientation, QAbstractAxis *axis, QAbstractAxis **axisPtr); }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/abstract3drenderer.cpp b/src/datavis3d/engine/abstract3drenderer.cpp index 361d1a7d..e291419a 100644 --- a/src/datavis3d/engine/abstract3drenderer.cpp +++ b/src/datavis3d/engine/abstract3drenderer.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ #include "abstract3drenderer_p.h" +#include "qvalueaxis.h" QT_DATAVIS3D_BEGIN_NAMESPACE @@ -67,6 +68,14 @@ void Abstract3DRenderer::initializePreOpenGL() &Abstract3DRenderer::updateBoundingRect); QObject::connect(m_controller, &Abstract3DController::shadowQualityChanged, this, &Abstract3DRenderer::updateShadowQuality); + QObject::connect(m_controller, &Abstract3DController::axisTypeChanged, this, + &Abstract3DRenderer::updateAxisType); + QObject::connect(m_controller, &Abstract3DController::axisTitleChanged, this, + &Abstract3DRenderer::updateAxisTitle); + QObject::connect(m_controller, &Abstract3DController::axisLabelsChanged, this, + &Abstract3DRenderer::updateAxisLabels); + QObject::connect(m_controller, &Abstract3DController::axisRangeChanged, this, + &Abstract3DRenderer::updateAxisRange); updateTheme(m_controller->theme()); updateFont(m_controller->font()); @@ -78,6 +87,10 @@ void Abstract3DRenderer::initializeOpenGL() // OpenGL is initialized, safe to call these. updateBoundingRect(m_controller->boundingRect()); updateShadowQuality(m_controller->shadowQuality()); + + initializeAxisCache(QAbstractAxis::AxisOrientationX, m_controller->axisX()); + initializeAxisCache(QAbstractAxis::AxisOrientationY, m_controller->axisY()); + initializeAxisCache(QAbstractAxis::AxisOrientationZ, m_controller->axisZ()); } void Abstract3DRenderer::updateBoundingRect(const QRect boundingRect) @@ -171,4 +184,58 @@ void Abstract3DRenderer::handleResize() #endif } +void Abstract3DRenderer::updateAxisType(QAbstractAxis::AxisOrientation orientation, QAbstractAxis::AxisType type) +{ + axisCacheForOrientation(orientation).setType(type); +} + +void Abstract3DRenderer::updateAxisTitle(QAbstractAxis::AxisOrientation orientation, const QString &title) +{ + axisCacheForOrientation(orientation).setTitle(title); +} + +void Abstract3DRenderer::updateAxisLabels(QAbstractAxis::AxisOrientation orientation, const QStringList &labels) +{ + axisCacheForOrientation(orientation).setLabels(labels); +} + +void Abstract3DRenderer::updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max) +{ + AxisRenderCache &cache = axisCacheForOrientation(orientation); + cache.setMin(min); + cache.setMax(max); +} + +// This method needs to be called under the controller-renderer sync mutex +void Abstract3DRenderer::initializeAxisCache(QAbstractAxis::AxisOrientation orientation, const QAbstractAxis *axis) +{ + axisCacheForOrientation(orientation).setDrawer(m_drawer); + + if (axis) { + updateAxisType(orientation, axis->type()); + updateAxisTitle(orientation, axis->title()); + updateAxisLabels(orientation, axis->labels()); + if (axis->type() & QAbstractAxis::AxisTypeValue) { + const QValueAxis *valueAxis = static_cast<const QValueAxis *>(axis); + updateAxisRange(orientation, valueAxis->min(), valueAxis->max()); + } + } +} + +AxisRenderCache &Abstract3DRenderer::axisCacheForOrientation(QAbstractAxis::AxisOrientation orientation) +{ + switch (orientation) { + case QAbstractAxis::AxisOrientationX: + return m_axisCacheX; + case QAbstractAxis::AxisOrientationY: + return m_axisCacheY; + case QAbstractAxis::AxisOrientationZ: + return m_axisCacheZ; + default: + qFatal(__FUNCTION__); + return m_axisCacheX; + } +} + + QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/abstract3drenderer_p.h b/src/datavis3d/engine/abstract3drenderer_p.h index fb91602a..e7764710 100644 --- a/src/datavis3d/engine/abstract3drenderer_p.h +++ b/src/datavis3d/engine/abstract3drenderer_p.h @@ -57,7 +57,7 @@ #include "datavis3dglobal_p.h" #include "abstract3dcontroller_p.h" - +#include "axisrendercache_p.h" QT_DATAVIS3D_BEGIN_NAMESPACE @@ -75,6 +75,10 @@ protected: Drawer *m_drawer; GLfloat m_autoScaleAdjustment; + AxisRenderCache m_axisCacheX; + AxisRenderCache m_axisCacheY; + AxisRenderCache m_axisCacheZ; + Abstract3DRenderer(Abstract3DController *controller); virtual void initializePreOpenGL(); virtual void initializeOpenGL(); @@ -96,7 +100,13 @@ protected: virtual void updateShadowQuality(ShadowQuality quality)=0; virtual void initShaders(const QString &vertexShader, const QString &fragmentShader)=0; virtual void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader)=0; + virtual void updateAxisType(QAbstractAxis::AxisOrientation orientation, QAbstractAxis::AxisType type); + virtual void updateAxisTitle(QAbstractAxis::AxisOrientation orientation, const QString &title); + virtual void updateAxisLabels(QAbstractAxis::AxisOrientation orientation, const QStringList &labels); + virtual void updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); + void initializeAxisCache(QAbstractAxis::AxisOrientation orientation, const QAbstractAxis *axis); + AxisRenderCache &axisCacheForOrientation(QAbstractAxis::AxisOrientation orientation); }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/axisrendercache.cpp b/src/datavis3d/engine/axisrendercache.cpp new file mode 100644 index 00000000..4997ed80 --- /dev/null +++ b/src/datavis3d/engine/axisrendercache.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtDataVis3D module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "axisrendercache_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +AxisRenderCache::AxisRenderCache() + : m_type(QAbstractAxis::AxisTypeNone), + m_min(0.0), + m_max(0.0), + m_drawer(0) +{ +} + +AxisRenderCache::~AxisRenderCache() +{ + foreach (LabelItem *label, m_labelItems) + delete label; +} + +void AxisRenderCache::setDrawer(Drawer *drawer) +{ + m_drawer = drawer; + if (m_drawer) { + QObject::connect(m_drawer, &Drawer::drawerChanged, this, &AxisRenderCache::updateTextures); + updateTextures(); + } +} + +void AxisRenderCache::setType(QAbstractAxis::AxisType type) +{ + m_type = type; + + // If type is set, it means completely new axis instance, so clear all generated label items. + m_titleItem.clear(); + foreach (LabelItem *label, m_labelItems) + delete label; + m_labelItems.clear(); +} + +void AxisRenderCache::setTitle(const QString &title) +{ + if (m_title != title) { + m_title = title; + // Generate axis label texture + if (m_drawer) + m_drawer->generateLabelItem(m_titleItem, title); + } +} + +void AxisRenderCache::setLabels(const QStringList &labels) +{ + if (m_labels != labels) { + int newSize(labels.size()); + int oldSize(m_labels.size()); + + for (int i = newSize; i < oldSize; i++) + delete m_labelItems.takeLast(); + + m_labelItems.reserve(newSize); + + if (m_drawer) { + for (int i = 0; i < newSize; i++) { + if (i >= oldSize) + m_labelItems.append(new LabelItem); + if (labels.at(i).isEmpty()) + m_labelItems[i]->clear(); + else if (i >= oldSize || labels.at(i) != m_labels.at(i)) + m_drawer->generateLabelItem(*m_labelItems[i], labels.at(i)); + } + } + m_labels = labels; + } +} + +void AxisRenderCache::updateTextures() +{ + if (m_title.isEmpty()) + m_titleItem.clear(); + else + m_drawer->generateLabelItem(m_titleItem, m_title); + + for (int i = 0; i < m_labels.size(); i++) { + if (m_labels.at(i).isEmpty()) + m_labelItems[i]->clear(); + else + m_drawer->generateLabelItem(*m_labelItems[i], m_labels.at(i)); + } +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/axisrendercache_p.h b/src/datavis3d/engine/axisrendercache_p.h new file mode 100644 index 00000000..c8fa45d5 --- /dev/null +++ b/src/datavis3d/engine/axisrendercache_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtDataVis3D module. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef AXISRENDERCACHE_P_H +#define AXISRENDERCACHE_P_H + +#include "datavis3dglobal_p.h" +#include "labelitem_p.h" +#include "qabstractaxis_p.h" +#include "drawer_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class AxisRenderCache : public QObject +{ + Q_OBJECT +public: + AxisRenderCache(); + virtual ~AxisRenderCache(); + + void setDrawer(Drawer *drawer); + + void setType(QAbstractAxis::AxisType type); + inline QAbstractAxis::AxisType type() const { return m_type; } + void setTitle(const QString &title); + inline const QString &title() { return m_title; } + void setLabels(const QStringList &labels); + inline const QStringList &labels() { return m_labels; } + inline void setMin(qreal min) { m_min = min; } + inline qreal min() { return m_min; } + inline void setMax(qreal max) { m_max = max; } + inline qreal max() { return m_max; } + + inline LabelItem &titleItem() { return m_titleItem; } + inline QList<LabelItem *> &labelItems() { return m_labelItems; } + +public slots: + void updateTextures(); + +private: + // Cached axis values + QAbstractAxis::AxisType m_type; + QString m_title; + QStringList m_labels; + qreal m_min; + qreal m_max; + + // Renderer items + Drawer *m_drawer; // Not owned + LabelItem m_titleItem; + QList<LabelItem *> m_labelItems; + + Q_DISABLE_COPY(AxisRenderCache); +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/bars3dcontroller.cpp b/src/datavis3d/engine/bars3dcontroller.cpp index ada177f6..c1dc09ef 100644 --- a/src/datavis3d/engine/bars3dcontroller.cpp +++ b/src/datavis3d/engine/bars3dcontroller.cpp @@ -98,12 +98,6 @@ void Bars3dController::initializeOpenGL() return; m_renderer = new Bars3dRenderer(this); - if (m_axisX) - m_axisX->d_ptr->setDrawer(m_renderer->drawer()); - if (m_axisY) - m_axisY->d_ptr->setDrawer(m_renderer->drawer()); - if (m_axisZ) - m_axisZ->d_ptr->setDrawer(m_renderer->drawer()); m_isInitialized = true; } @@ -117,8 +111,7 @@ void Bars3dController::render(const GLuint defaultFboHandle) // TODO --> Only if there is no need to store m_dataProxy for later, e.g. for string formatting // TODO Also, m_valuesDirty flag setting needs to be under same mutex QMutexLocker(m_data->mutex()); - m_renderer->render(m_data, m_valuesDirty, m_cameraHelper, m_axisX->d_ptr->titleItem(), - m_axisY->d_ptr->titleItem(), m_axisZ->d_ptr->titleItem(), defaultFboHandle); + m_renderer->render(m_data, m_valuesDirty, m_cameraHelper, defaultFboHandle); m_valuesDirty = false; @@ -269,15 +262,6 @@ void Bars3dController::wheelEvent(QWheelEvent *event) setZoomLevel(zoomLevel); } -// TODO: abstract renderer should have accessor for Drawer instead -Drawer *Bars3dController::drawer() -{ - if (m_renderer) - return m_renderer->drawer(); - else - return 0; -} - void Bars3dController::setDataProxy(QBarDataProxy *proxy) { delete m_data; diff --git a/src/datavis3d/engine/bars3dcontroller_p.h b/src/datavis3d/engine/bars3dcontroller_p.h index 1e7e08bb..25d1d2f5 100644 --- a/src/datavis3d/engine/bars3dcontroller_p.h +++ b/src/datavis3d/engine/bars3dcontroller_p.h @@ -180,9 +180,6 @@ public: void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); void wheelEvent(QWheelEvent *event); - // TODO: abstract renderer should have accessor for Drawer instead - virtual Drawer *drawer(); - // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. void setDataProxy(QBarDataProxy *proxy); QBarDataProxy *dataProxy(); @@ -197,13 +194,13 @@ public slots: signals: void selectionModeChanged(SelectionMode mode); void slicingActiveChanged(bool isSlicing); - void limitsChanged(QPair<GLfloat, GLfloat> limits); + void limitsChanged(QPair<GLfloat, GLfloat> limits); // TODO should be handled via axis range void sampleSpaceChanged(int samplesRow, int samplesColumn); void barSpecsChanged(QSizeF thickness, QSizeF spacing, bool relative); void objFileChanged(QString fileName); - void gridEnabledChanged(bool enable); + void gridEnabledChanged(bool enable); // TODO should be handled via axis void backgroundEnabledChanged(bool enable); - void tickCountChanged(GLint tickCount, GLfloat step, GLfloat minimum); + void tickCountChanged(GLint tickCount, GLfloat step, GLfloat minimum); // TODO should be handled via axis private: void handleLimitChange(); diff --git a/src/datavis3d/engine/bars3drenderer.cpp b/src/datavis3d/engine/bars3drenderer.cpp index dda2a984..dfac6414 100644 --- a/src/datavis3d/engine/bars3drenderer.cpp +++ b/src/datavis3d/engine/bars3drenderer.cpp @@ -48,7 +48,6 @@ #include "theme_p.h" #include "utils_p.h" #include "drawer_p.h" -#include "qabstractaxis_p.h" #include "qbardataitem.h" #include <QMatrix4x4> @@ -83,7 +82,7 @@ Bars3dRenderer::Bars3dRenderer(Bars3dController *controller) m_selectedBar(0), m_previouslySelectedBar(0), m_sliceSelection(0), - m_sliceAxisP(0), + m_sliceCache(0), m_sliceTitleItem(0), m_tickCount(0), m_tickStep(0), @@ -181,6 +180,7 @@ void Bars3dRenderer::initializePreOpenGL() QObject::connect(m_controller, &Bars3dController::zoomLevelChanged, this, &Bars3dRenderer::updateZoomLevel); + // TODO Should all this initial setup be mutexed? updateSampleSpace(m_controller->rowCount(), m_controller->columnCount()); updateSelectionMode(m_controller->selectionMode()); updateSlicingActive(m_controller->isSlicingActive()); @@ -195,14 +195,6 @@ void Bars3dRenderer::initializePreOpenGL() void Bars3dRenderer::initializeOpenGL() { - // TODO: Protect with mutex or redesign how axes create label items? - if (m_controller->axisX()) - m_controller->axisX()->d_ptr->setDrawer(m_drawer); - if (m_controller->axisY()) - m_controller->axisY()->d_ptr->setDrawer(m_drawer); - if (m_controller->axisZ()) - m_controller->axisZ()->d_ptr->setDrawer(m_drawer); - m_textureHelper = new TextureHelper(); m_drawer->initializeOpenGL(); @@ -257,9 +249,6 @@ void Bars3dRenderer::initializeOpenGL() void Bars3dRenderer::render(QBarDataProxy *dataProxy, bool valuesDirty, CameraHelper *camera, - const LabelItem &xLabel, - const LabelItem &yLabel, - const LabelItem &zLabel, const GLuint defaultFboHandle) { #ifdef DISPLAY_RENDER_SPEED @@ -326,7 +315,7 @@ void Bars3dRenderer::render(QBarDataProxy *dataProxy, // If slice selection is on, draw the sliced scene if (m_cachedIsSlicingActivated) - drawSlicedScene(camera, xLabel, yLabel, zLabel); + drawSlicedScene(camera, m_axisCacheX.titleItem(), m_axisCacheY.titleItem(), m_axisCacheZ.titleItem()); // Draw bars scene drawScene(camera, defaultFboHandle); @@ -500,15 +489,14 @@ void Bars3dRenderer::drawSlicedScene(CameraHelper *camera, m_labelObj, camera); // Draw labels - // TODO: Protect with mutex or redesign axis label handling? - if (m_sliceAxisP->labelItems().size() > col) { + if (m_sliceCache->labelItems().size() > col) { const LabelItem *labelItem(0); // If draw order of bars is flipped, label draw order should be too if (m_xFlipped) { - labelItem = m_sliceAxisP->labelItems().at( - m_sliceAxisP->labelItems().size() - col - 1); + labelItem = m_sliceCache->labelItems().at( + m_sliceCache->labelItems().size() - col - 1); } else { - labelItem = m_sliceAxisP->labelItems().at(col); + labelItem = m_sliceCache->labelItems().at(col); } m_drawer->drawLabel(*item, *labelItem, viewMatrix, projectionMatrix, QVector3D(0.0f, m_yAdjustment, zComp), @@ -843,7 +831,7 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, // Draw bars if (!m_cachedIsSlicingActivated && m_sliceSelection) { m_sliceSelection->clear(); // Slice doesn't own its items - m_sliceAxisP = 0; + m_sliceCache = 0; m_sliceTitleItem = 0; } bool barSelectionFound = false; @@ -914,11 +902,11 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, if (!m_cachedIsSlicingActivated && ModeZoomRow == m_cachedSelectionMode) { item.setTranslation(modelMatrix.column(3).toVector3D()); m_sliceSelection->append(&item); - if (!m_sliceAxisP) { - // m_sliceAxisP is the axis for labels, while title comes from different axis. - m_sliceAxisP = m_controller->axisZ()->d_ptr.data(); - if (m_controller->axisX()->d_ptr->labelItems().size() > row) - m_sliceTitleItem = m_controller->axisX()->d_ptr->labelItems().at(row); + if (!m_sliceCache) { + // m_sliceCache is the axis for labels, while title comes from different axis. + m_sliceCache = &m_axisCacheZ; + if (m_axisCacheX.labelItems().size() > row) + m_sliceTitleItem = m_axisCacheX.labelItems().at(row); } } break; @@ -930,11 +918,11 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, if (!m_cachedIsSlicingActivated && ModeZoomColumn == m_cachedSelectionMode) { item.setTranslation(modelMatrix.column(3).toVector3D()); m_sliceSelection->append(&item); - if (!m_sliceAxisP) { - // m_sliceAxisP is the axis for labels, while title comes from different axis. - m_sliceAxisP = m_controller->axisX()->d_ptr.data(); - if (m_controller->axisZ()->d_ptr->labelItems().size() > bar) - m_sliceTitleItem = m_controller->axisZ()->d_ptr->labelItems().at(bar); + if (!m_sliceCache) { + // m_sliceCache is the axis for labels, while title comes from different axis. + m_sliceCache = &m_axisCacheX; + if (m_axisCacheZ.labelItems().size() > bar) + m_sliceTitleItem = m_axisCacheZ.labelItems().at(bar); } } break; @@ -1344,12 +1332,12 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, LabelItem &labelItem = m_selectedBar->selectionLabel(); if (m_previouslySelectedBar != m_selectedBar || m_updateLabels || !labelItem.textureId()) { QString labelText = m_selectedBar->label(); - if ((m_controller->axisZ()->labels().size() > m_selectedBar->position().y()) - && (m_controller->axisX()->labels().size() > m_selectedBar->position().x())) { + if ((m_axisCacheZ.labels().size() > m_selectedBar->position().y()) + && (m_axisCacheX.labels().size() > m_selectedBar->position().x())) { labelText.append(QStringLiteral(" (")); - labelText.append(m_controller->axisX()->labels().at(m_selectedBar->position().x())); + labelText.append(m_axisCacheX.labels().at(m_selectedBar->position().x())); labelText.append(QStringLiteral(", ")); - labelText.append(m_controller->axisZ()->labels().at(m_selectedBar->position().y())); + labelText.append(m_axisCacheZ.labels().at(m_selectedBar->position().y())); labelText.append(QStringLiteral(")")); //qDebug() << labelText; } @@ -1385,9 +1373,9 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - // Calculate the positions for row and column labels and store them into QDataItems (and QDataRows?) + // Calculate the positions for row and column labels and store them for (int row = 0; row != m_cachedRowCount; row++) { - if (m_controller->axisX()->d_ptr->labelItems().size() > row) { + if (m_axisCacheX.labelItems().size() > row) { // Go through all rows and get position of max+1 or min-1 column, depending on x flip // We need only positions for them, labels have already been generated at QDataSetPrivate. Just add LabelItems rowPos = (row + 1) * (m_cachedBarSpacing.height()); @@ -1416,7 +1404,7 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, // TODO: Try it; draw the label here m_dummyBarRenderItem.setTranslation(labelPos); - const LabelItem &axisLabelItem = *m_controller->axisX()->d_ptr->labelItems().at(row); + const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(row); //qDebug() << "labelPos, row" << row + 1 << ":" << labelPos << dataSet->rowLabels().at(row); m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix, @@ -1429,7 +1417,7 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, } for (int bar = 0; bar != m_cachedColumnCount; bar += 1) { - if (m_controller->axisZ()->d_ptr->labelItems().size() > bar) { + if (m_axisCacheZ.labelItems().size() > bar) { // Go through all columns and get position of max+1 or min-1 row, depending on z flip // We need only positions for them, labels have already been generated at QDataSetPrivate. Just add LabelItems barPos = (bar + 1) * (m_cachedBarSpacing.width()); @@ -1458,7 +1446,7 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, // TODO: Try it; draw the label here m_dummyBarRenderItem.setTranslation(labelPos); - const LabelItem &axisLabelItem = *m_controller->axisZ()->d_ptr->labelItems().at(bar); + const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(bar); //qDebug() << "labelPos, col" << bar + 1 << ":" << labelPos << dataSet->columnLabels().at(bar); m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix, @@ -1534,7 +1522,7 @@ void Bars3dRenderer::updateSampleSpace(int rowCount, int columnCount) m_valueUpdateNeeded = true; // Force update for selection related items - m_sliceAxisP = 0; + m_sliceCache = 0; m_sliceTitleItem = 0; if (m_sliceSelection) m_sliceSelection->clear(); diff --git a/src/datavis3d/engine/bars3drenderer_p.h b/src/datavis3d/engine/bars3drenderer_p.h index 40d038dd..f886a2ef 100644 --- a/src/datavis3d/engine/bars3drenderer_p.h +++ b/src/datavis3d/engine/bars3drenderer_p.h @@ -81,7 +81,6 @@ class Theme; class Drawer; class LabelItem; class CameraHelper; -class QAbstractAxisPrivate; class QT_DATAVIS3D_EXPORT Bars3dRenderer : public Abstract3DRenderer { @@ -92,6 +91,7 @@ private: Bars3dController *m_controller; // Mutex for sharing resources between render and main threads. + // Note: Data access mutex is separate and owned by data proxy. QMutex m_mutex; // Cached state based on emitted signals from the controller @@ -105,13 +105,12 @@ private: int m_cachedColumnCount; bool m_cachedIsGridEnabled; bool m_cachedIsBackgroundEnabled; - ShadowQuality m_cachedShadowQuality; // Internal state BarRenderItem *m_selectedBar; // points to renderitem array BarRenderItem *m_previouslySelectedBar; // points to renderitem array QList<BarRenderItem *> *m_sliceSelection; - QAbstractAxisPrivate *m_sliceAxisP; // not owned + AxisRenderCache *m_sliceCache; // not owned const LabelItem *m_sliceTitleItem; // not owned GLint m_tickCount; GLfloat m_tickStep; @@ -171,12 +170,9 @@ public: ~Bars3dRenderer(); void render(QBarDataProxy *dataProxy, bool valuesDirty, CameraHelper *camera, - const LabelItem &xLabel, const LabelItem &yLabel, const LabelItem &zLabel, const GLuint defaultFboHandle = 0); QRect mainViewPort(); - // TODO: Not thread-safe, needs rethinking how axes create labels - Drawer *drawer() { return m_drawer; } public slots: void updateBarSpecs(QSizeF thickness = QSizeF(1.0f, 1.0f), diff --git a/src/datavis3d/engine/engine.pri b/src/datavis3d/engine/engine.pri index b72e873b..5dc415e1 100644 --- a/src/datavis3d/engine/engine.pri +++ b/src/datavis3d/engine/engine.pri @@ -19,6 +19,7 @@ HEADERS += $$PWD/q3dwindow_p.h \ $$PWD/q3dscatter_p.h \ $$PWD/scatter3dcontroller_p.h \ $$PWD/scatter3drenderer_p.h \ + $$PWD/axisrendercache_p.h \ $$PWD/abstract3drenderer_p.h SOURCES += $$PWD/q3dwindow.cpp \ @@ -37,6 +38,7 @@ SOURCES += $$PWD/q3dwindow.cpp \ $$PWD/q3dscatter.cpp \ $$PWD/scatter3dcontroller.cpp \ $$PWD/scatter3drenderer.cpp \ + $$PWD/axisrendercache.cpp \ $$PWD/abstract3drenderer.cpp RESOURCES += engine/engine.qrc diff --git a/src/datavis3d/engine/scatter3dcontroller.cpp b/src/datavis3d/engine/scatter3dcontroller.cpp index 55169cd9..a6ca6e17 100644 --- a/src/datavis3d/engine/scatter3dcontroller.cpp +++ b/src/datavis3d/engine/scatter3dcontroller.cpp @@ -94,12 +94,6 @@ void Scatter3DController::initializeOpenGL() return; m_renderer = new Scatter3DRenderer(this); - if (m_axisX) - m_axisX->d_ptr->setDrawer(m_renderer->drawer()); - if (m_axisY) - m_axisY->d_ptr->setDrawer(m_renderer->drawer()); - if (m_axisZ) - m_axisZ->d_ptr->setDrawer(m_renderer->drawer()); m_isInitialized = true; } @@ -113,8 +107,7 @@ void Scatter3DController::render(const GLuint defaultFboHandle) // TODO --> Only if there is no need to store m_dataProxy for later, e.g. for string formatting // TODO Also, m_valuesDirty flag setting needs to be under same mutex QMutexLocker(m_data->mutex()); - m_renderer->render(m_data, m_valuesDirty, m_cameraHelper, m_axisX->d_ptr->titleItem(), - m_axisY->d_ptr->titleItem(), m_axisZ->d_ptr->titleItem(), defaultFboHandle); + m_renderer->render(m_data, m_valuesDirty, m_cameraHelper, defaultFboHandle); m_valuesDirty = false; @@ -260,15 +253,6 @@ void Scatter3DController::wheelEvent(QWheelEvent *event) setZoomLevel(zoomLevel); } -// TODO: abstract renderer should have accessor for Drawer instead -Drawer *Scatter3DController::drawer() -{ - if (m_renderer) - return m_renderer->drawer(); - else - return 0; -} - void Scatter3DController::setDataProxy(QScatterDataProxy *proxy) { delete m_data; diff --git a/src/datavis3d/engine/scatter3dcontroller_p.h b/src/datavis3d/engine/scatter3dcontroller_p.h index 7b5fc11e..452fbe1e 100644 --- a/src/datavis3d/engine/scatter3dcontroller_p.h +++ b/src/datavis3d/engine/scatter3dcontroller_p.h @@ -164,9 +164,6 @@ public: void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); void wheelEvent(QWheelEvent *event); - // TODO: abstract renderer should have accessor for Drawer instead - virtual Drawer *drawer(); - // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. void setDataProxy(QScatterDataProxy *proxy); QScatterDataProxy *dataProxy(); diff --git a/src/datavis3d/engine/scatter3drenderer.cpp b/src/datavis3d/engine/scatter3drenderer.cpp index 491475e6..4f140cac 100644 --- a/src/datavis3d/engine/scatter3drenderer.cpp +++ b/src/datavis3d/engine/scatter3drenderer.cpp @@ -45,11 +45,7 @@ #include "shaderhelper_p.h" #include "objecthelper_p.h" #include "texturehelper_p.h" -#include "theme_p.h" #include "utils_p.h" -#include "drawer_p.h" -#include "qabstractaxis_p.h" -#include "qbardataitem.h" #include <QMatrix4x4> #include <QMouseEvent> @@ -80,7 +76,7 @@ const GLfloat gridLineWidth = 0.005f; static QVector3D selectionSkipColor = QVector3D(255, 255, 255); // Selection texture's background color Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller) - : QObject(controller), + : Abstract3DRenderer(controller), m_controller(controller), m_selectedItem(0), m_previouslySelectedItem(0), @@ -98,7 +94,6 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller) m_backgroundObj(0), m_gridLineObj(0), m_labelObj(0), - m_drawer(new Drawer(m_cachedTheme, m_cachedFont, m_cachedLabelTransparency)), m_bgrTexture(0), m_depthTexture(0), m_selectionTexture(0), @@ -106,7 +101,6 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller) m_selectionFrameBuffer(0), m_selectionDepthBuffer(0), m_shadowQualityToShader(33.3f), - m_autoScaleAdjustment(1.0f), m_heightNormalizer(1.0f), m_yAdjustment(0.0f), m_scaleFactor(0), @@ -122,127 +116,70 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller) { //qDebug() << __FUNCTION__; m_dummyRenderItem.setRenderer(this); + initializePreOpenGL(); + initializeOpenGLFunctions(); + initializeOpenGL(); +} + +Scatter3DRenderer::~Scatter3DRenderer() +{ + //qDebug() << __FUNCTION__; + m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); + m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); + m_textureHelper->deleteTexture(&m_selectionTexture); + m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); + m_textureHelper->deleteTexture(&m_bgrTexture); + delete m_dotShader; + delete m_depthShader; + delete m_selectionShader; + delete m_backgroundShader; + delete m_dotObj; + delete m_backgroundObj; + delete m_gridLineObj; + delete m_textureHelper; +} - // Listen to changes in the drawer - QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Scatter3DRenderer::updateTextures); +void Scatter3DRenderer::initializePreOpenGL() +{ + Abstract3DRenderer::initializePreOpenGL(); - // Listen to changes in the controller - QObject::connect(m_controller, &Scatter3DController::themeChanged, this, - &Scatter3DRenderer::updateTheme); QObject::connect(m_controller, &Scatter3DController::selectionModeChanged, this, &Scatter3DRenderer::updateSelectionMode); //QObject::connect(m_controller, &Scatter3DController::limitsChanged, this, // &Scatter3DRenderer::updateLimits); QObject::connect(m_controller, &Scatter3DController::objFileChanged, this, &Scatter3DRenderer::updateMeshFileName); - QObject::connect(m_controller, &Scatter3DController::boundingRectChanged, this, - &Scatter3DRenderer::updateBoundingRect); - QObject::connect(m_controller, &Scatter3DController::sizeChanged, this, - &Scatter3DRenderer::updateBoundingRect); QObject::connect(m_controller, &Scatter3DController::positionChanged, this, &Scatter3DRenderer::updatePosition); - QObject::connect(m_controller, &Scatter3DController::fontChanged, this, - &Scatter3DRenderer::updateFont); - QObject::connect(m_controller, &Scatter3DController::labelTransparencyUpdated, this, - &Scatter3DRenderer::updateLabelTransparency); QObject::connect(m_controller, &Scatter3DController::gridEnabledChanged, this, &Scatter3DRenderer::updateGridEnabled); QObject::connect(m_controller, &Scatter3DController::backgroundEnabledChanged, this, &Scatter3DRenderer::updateBackgroundEnabled); - QObject::connect(m_controller, &Scatter3DController::shadowQualityChanged, this, - &Scatter3DRenderer::updateShadowQuality); QObject::connect(m_controller, &Scatter3DController::tickCountChanged, this, &Scatter3DRenderer::updateTickCount); QObject::connect(m_controller, &Scatter3DController::zoomLevelChanged, this, &Scatter3DRenderer::updateZoomLevel); - updateTheme(m_controller->theme()); + // TODO Should all this initial setup be mutexed? updateSelectionMode(m_controller->selectionMode()); //updateLimits(m_controller->limits()); updateZoomLevel(m_controller->zoomLevel()); updateMeshFileName(m_controller->objFile()); - updateFont(m_controller->font()); - updateLabelTransparency(m_controller->labelTransparency()); updateGridEnabled(m_controller->gridEnabled()); updateBackgroundEnabled(m_controller->backgroundEnabled()); - initializeOpenGL(); - - updateBoundingRect(m_controller->boundingRect()); - updateShadowQuality(m_controller->shadowQuality()); - calculateSceneScalingFactors(); - - // TODO: Protect with mutex or redesign how axes create label items? - if (m_controller->axisX()) - m_controller->axisX()->d_ptr->setDrawer(m_drawer); - if (m_controller->axisY()) - m_controller->axisY()->d_ptr->setDrawer(m_drawer); - if (m_controller->axisZ()) - m_controller->axisZ()->d_ptr->setDrawer(m_drawer); } -Scatter3DRenderer::~Scatter3DRenderer() -{ - //qDebug() << __FUNCTION__; - m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); - m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); - m_textureHelper->deleteTexture(&m_selectionTexture); - m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); - m_textureHelper->deleteTexture(&m_bgrTexture); - delete m_dotShader; - delete m_depthShader; - delete m_selectionShader; - delete m_backgroundShader; - delete m_dotObj; - delete m_backgroundObj; - delete m_gridLineObj; - delete m_textureHelper; - delete m_drawer; -} void Scatter3DRenderer::initializeOpenGL() { //qDebug() << __FUNCTION__; - initializeOpenGLFunctions(); - m_textureHelper = new TextureHelper(); m_drawer->initializeOpenGL(); // Initialize shaders -#if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > ShadowNone) { - if (!m_cachedTheme.m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } else { - if (!m_cachedTheme.m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } -#else - if (!m_cachedTheme.m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); -#endif + handleShadowQualityChange(); initLabelShaders(QStringLiteral(":/shaders/vertexLabel"), QStringLiteral(":/shaders/fragmentLabel")); @@ -286,19 +223,15 @@ void Scatter3DRenderer::initializeOpenGL() // Load background mesh (we need to be initialized first) loadBackgroundMesh(); + + Abstract3DRenderer::initializeOpenGL(); } void Scatter3DRenderer::render(QScatterDataProxy *dataProxy, bool valuesDirty, CameraHelper *camera, - const LabelItem &xLabel, - const LabelItem &yLabel, - const LabelItem &zLabel, const GLuint defaultFboHandle) { - Q_UNUSED(xLabel); - Q_UNUSED(yLabel); - Q_UNUSED(zLabel); //qDebug() << __FUNCTION__; #ifdef DISPLAY_RENDER_SPEED @@ -1160,7 +1093,7 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, GLfloat startPos = -m_heightNormalizer; int labelNbr = 0; for (GLfloat labelPos = startPos; labelPos <= m_heightNormalizer; labelPos += posStep) { - if (m_controller->axisX()->d_ptr->labelItems().size() > labelNbr) { + if (m_axisCacheX.labelItems().size() > labelNbr) { GLfloat labelXTrans = (aspectRatio * backgroundMargin * m_areaSize.width()) / m_scaleFactor; GLfloat rotLabelX = -90.0f; @@ -1181,7 +1114,7 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, // TODO: Try it; draw the label here m_dummyRenderItem.setTranslation(labelTrans); const LabelItem &axisLabelItem = - *m_controller->axisZ()->d_ptr->labelItems().at(labelNbr); + *m_axisCacheZ.labelItems().at(labelNbr); m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix, QVector3D(0.0f, m_yAdjustment, zComp), @@ -1195,7 +1128,7 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, // X Labels labelNbr = 0; for (GLfloat labelPos = startPos; labelPos <= m_heightNormalizer; labelPos += posStep) { - if (m_controller->axisX()->d_ptr->labelItems().size() > labelNbr) { + if (m_axisCacheX.labelItems().size() > labelNbr) { GLfloat labelZTrans = (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor; GLfloat rotLabelX = -90.0f; @@ -1216,7 +1149,7 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, // TODO: Try it; draw the label here m_dummyRenderItem.setTranslation(labelTrans); const LabelItem &axisLabelItem = - *m_controller->axisX()->d_ptr->labelItems().at(labelNbr); + *m_axisCacheX.labelItems().at(labelNbr); m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix, QVector3D(0.0f, m_yAdjustment, zComp), @@ -1231,7 +1164,7 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, labelNbr = 0; for (GLfloat labelPos = startPos; labelPos <= m_heightNormalizer; labelPos += posStep) { // TODO: Test with x labels - if (m_controller->axisX()->d_ptr->labelItems().size() > labelNbr) { + if (m_axisCacheX.labelItems().size() > labelNbr) { GLfloat labelXTrans = (aspectRatio * backgroundMargin * m_areaSize.width()) / m_scaleFactor; GLfloat labelZTrans = (aspectRatio * backgroundMargin * m_areaSize.height()) @@ -1251,7 +1184,7 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, } // TODO: Test with x labels - const LabelItem &axisLabelItem = *m_controller->axisX()->d_ptr->labelItems().at(labelNbr); + const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(labelNbr); // Back wall QVector3D labelTrans = QVector3D(labelXTrans, labelYTrans, labelZTrans + zComp); @@ -1337,62 +1270,12 @@ void Scatter3DRenderer::updateMeshFileName(const QString &objFileName) loadBarMesh(); } -void Scatter3DRenderer::updateTheme(Theme theme) -{ - //qDebug() << __FUNCTION__; - m_cachedTheme.setFromTheme(theme); - - m_drawer->setTheme(m_cachedTheme); - // Re-initialize shaders -#if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > ShadowNone) { - if (!m_cachedTheme.m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - } else { - if (!m_cachedTheme.m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - } -#else - if (!m_cachedTheme.m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } -#endif -} - void Scatter3DRenderer::updateSelectionMode(SelectionMode mode) { //qDebug() << __FUNCTION__; m_cachedSelectionMode = mode; } -void Scatter3DRenderer::updateFont(const QFont &font) -{ - //qDebug() << __FUNCTION__; - m_cachedFont = font; - m_drawer->setFont(font); -} - -void Scatter3DRenderer::updateLabelTransparency(LabelTransparency transparency) -{ - //qDebug() << __FUNCTION__; - m_cachedLabelTransparency = transparency; - m_drawer->setTransparency(transparency); -} - void Scatter3DRenderer::updateGridEnabled(bool enable) { //qDebug() << __FUNCTION__; @@ -1478,19 +1361,6 @@ void Scatter3DRenderer::updateTickCount(GLint tickCount, GLfloat step, GLfloat m } } -void Scatter3DRenderer::updateBoundingRect(const QRect boundingRect) -{ - //qDebug() << __FUNCTION__; - m_cachedBoundingRect = boundingRect; - handleResize(); -} - -void Scatter3DRenderer::updatePosition(const QRect boundingRect) -{ - //qDebug() << __FUNCTION__; - m_cachedBoundingRect = boundingRect; -} - void Scatter3DRenderer::loadBarMesh() { //qDebug() << __FUNCTION__; diff --git a/src/datavis3d/engine/scatter3drenderer_p.h b/src/datavis3d/engine/scatter3drenderer_p.h index 8627e170..fa42cd91 100644 --- a/src/datavis3d/engine/scatter3drenderer_p.h +++ b/src/datavis3d/engine/scatter3drenderer_p.h @@ -49,8 +49,8 @@ // // We mean it. -#ifndef Q3DSCATTERRENDERER_p_H -#define Q3DSCATTERRENDERER_p_H +#ifndef Q3DSCATTERRENDERER_P_H +#define Q3DSCATTERRENDERER_P_H #include <QtCore/QSize> #include <QtCore/QObject> @@ -62,6 +62,7 @@ #include "datavis3dglobal_p.h" #include "scatter3dcontroller_p.h" +#include "abstract3drenderer_p.h" #include "qscatterdataproxy.h" #include "scatterrenderitem_p.h" @@ -76,13 +77,11 @@ QT_DATAVIS3D_BEGIN_NAMESPACE class ShaderHelper; class ObjectHelper; class TextureHelper; -class Theme; -class Drawer; class LabelItem; class CameraHelper; class QAbstractAxisPrivate; -class QT_DATAVIS3D_EXPORT Scatter3DRenderer : public QObject, protected QOpenGLFunctions +class QT_DATAVIS3D_EXPORT Scatter3DRenderer : public Abstract3DRenderer { Q_OBJECT @@ -100,13 +99,8 @@ private: QString m_cachedObjFile; SelectionMode m_cachedSelectionMode; int m_cachedZoomLevel; - QRect m_cachedBoundingRect; - Theme m_cachedTheme; - LabelTransparency m_cachedLabelTransparency; - QFont m_cachedFont; bool m_cachedIsGridEnabled; bool m_cachedIsBackgroundEnabled; - ShadowQuality m_cachedShadowQuality; // Internal state ScatterRenderItem *m_selectedItem; // points to renderitem array @@ -127,7 +121,6 @@ private: ObjectHelper *m_gridLineObj; ObjectHelper *m_labelObj; TextureHelper *m_textureHelper; - Drawer *m_drawer; GLuint m_bgrTexture; GLuint m_depthTexture; GLuint m_selectionTexture; @@ -135,7 +128,6 @@ private: GLuint m_selectionFrameBuffer; GLuint m_selectionDepthBuffer; GLfloat m_shadowQualityToShader; - GLfloat m_autoScaleAdjustment; GLfloat m_heightNormalizer; GLfloat m_yAdjustment; GLfloat m_scaleFactor; @@ -164,38 +156,34 @@ public: ~Scatter3DRenderer(); void render(QScatterDataProxy *dataProxy, bool valuesDirty, CameraHelper *camera, - const LabelItem &xLabel, const LabelItem &yLabel, const LabelItem &zLabel, const GLuint defaultFboHandle = 0); QRect mainViewPort(); - // TODO: Not thread-safe, needs rethinking how axes create labels - Drawer *drawer() { return m_drawer; } public slots: - void updateTheme(Theme theme); void updateSelectionMode(SelectionMode newMode); //void updateLimits(QPair<GLfloat, GLfloat> newLimits); void updateZoomLevel(int newZoomLevel); - void updateFont(const QFont &font); - void updateLabelTransparency(LabelTransparency transparency); void updateGridEnabled(bool enable); void updateBackgroundEnabled(bool enable); - void updateShadowQuality(ShadowQuality quality); void updateTickCount(GLint tickCount, GLfloat step, GLfloat minimum = 0.0f); void updateMeshFileName(const QString &objFileName); - void updateBoundingRect(const QRect boundingRect); - void updatePosition(const QRect boundingRect); // Requests that upon next render pass the column and row under the given point is inspected for selection. // Only one request can be queued per render pass at this point. New request will override any pending requests. // After inspection the selectionUpdated signal is emitted. - void requestSelectionAtPoint(const QPoint &point); + virtual void requestSelectionAtPoint(const QPoint &point); signals: void selectionUpdated(QVector3D selection); private: - void initializeOpenGL(); + virtual void initializePreOpenGL(); + virtual void initializeOpenGL(); + virtual void initShaders(const QString &vertexShader, const QString &fragmentShader); + virtual void updateShadowQuality(ShadowQuality quality); + virtual void updateTextures(); + void drawScene(CameraHelper *camera, const GLuint defaultFboHandle); void handleResize(); @@ -203,7 +191,6 @@ private: void loadBackgroundMesh(); void loadGridLineMesh(); void loadLabelMesh(); - void initShaders(const QString &vertexShader, const QString &fragmentShader); void initSelectionShader(); void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); void initLabelShaders(const QString &vertexShader, const QString &fragmentShader); @@ -212,7 +199,6 @@ private: void initDepthShader(); void updateDepthBuffer(); #endif - void updateTextures(); void calculateSceneScalingFactors(const QRect &areaRect = QRect(0, 0, 1, 1)); void calculateTranslation(ScatterRenderItem &item); void calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits); |