From 294a23e02474838186cc102a8ec9e50aa159a2dd Mon Sep 17 00:00:00 2001 From: Mika Salmela Date: Fri, 6 Sep 2013 12:17:06 +0300 Subject: First step for using proxy in surface TODOS: - handling for deletions, insertions and modifications - some solution for axis handling Change-Id: I5a35a45e103d1a4393ca8747a7a99af95147da90 Reviewed-by: Miikka Heikkinen --- examples/surfacechart/Heightmap.png | Bin 0 -> 71764 bytes examples/surfacechart/chartmodifier.cpp | 74 ++++++++---- examples/surfacechart/chartmodifier.h | 1 + examples/surfacechart/main.cpp | 7 ++ examples/surfacechart/surface.qrc | 5 + examples/surfacechart/surfacechart.pro | 3 +- src/datavis3d/data/data.pri | 7 +- src/datavis3d/data/qabstractdataproxy.h | 1 + src/datavis3d/data/qsurfacedataproxy.cpp | 106 ++++++++++++++++++ src/datavis3d/data/qsurfacedataproxy.h | 63 +++++++++++ src/datavis3d/data/qsurfacedataproxy_p.h | 56 ++++++++++ src/datavis3d/engine/q3dsurface.cpp | 58 +++++----- src/datavis3d/engine/q3dsurface.h | 12 +- src/datavis3d/engine/q3dsurface_p.h | 8 -- src/datavis3d/engine/surface3dcontroller.cpp | 44 ++++++-- src/datavis3d/engine/surface3dcontroller_p.h | 5 + src/datavis3d/engine/surface3drenderer.cpp | 161 ++++++++++++--------------- src/datavis3d/engine/surface3drenderer_p.h | 26 ++--- src/datavis3d/utils/surfaceobject.cpp | 12 +- src/datavis3d/utils/surfaceobject_p.h | 8 +- 20 files changed, 467 insertions(+), 190 deletions(-) create mode 100644 examples/surfacechart/Heightmap.png create mode 100644 examples/surfacechart/surface.qrc create mode 100644 src/datavis3d/data/qsurfacedataproxy.cpp create mode 100644 src/datavis3d/data/qsurfacedataproxy.h create mode 100644 src/datavis3d/data/qsurfacedataproxy_p.h diff --git a/examples/surfacechart/Heightmap.png b/examples/surfacechart/Heightmap.png new file mode 100644 index 00000000..2a860111 Binary files /dev/null and b/examples/surfacechart/Heightmap.png differ diff --git a/examples/surfacechart/chartmodifier.cpp b/examples/surfacechart/chartmodifier.cpp index bfd032f7..30df0998 100644 --- a/examples/surfacechart/chartmodifier.cpp +++ b/examples/surfacechart/chartmodifier.cpp @@ -18,6 +18,7 @@ #include "chartmodifier.h" #include +#include #include @@ -33,6 +34,9 @@ ChartModifier::ChartModifier(Q3DSurface *chart) m_chart->setAxisX(new Q3DValueAxis); m_chart->setAxisY(new Q3DValueAxis); m_chart->setAxisZ(new Q3DValueAxis); + + QSurfaceDataProxy *proxy = new QSurfaceDataProxy; + m_chart->setActiveDataProxy(proxy); } ChartModifier::~ChartModifier() @@ -56,7 +60,6 @@ void ChartModifier::toggleSqrtSin(bool enable) { qreal biggest = -9999.0; qreal smallest = 9999.0; - QList series; if (enable) { qDebug() << "Create Sqrt&Sin surface, (" << m_xCount << ", " << m_zCount << ")"; @@ -64,22 +67,27 @@ void ChartModifier::toggleSqrtSin(bool enable) qreal stepZ = 16.0 / qreal(m_zCount); qreal stepX = 16.0 / qreal(m_xCount); + QSurfaceDataArray *dataArray = new QSurfaceDataArray; + dataArray->reserve(m_zCount); for (qreal i = -8.0 + stepZ / 2.0 ; i < 8.0 ; i += stepZ) { + QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); + int index = 0; for (qreal j = -8.0 + stepX / 2.0; j < 8.0; j += stepX) { qreal R = qSqrt(i*i + j*j) + 0.01; qreal y = (sin(R)/R + 0.24) * 1.61; - series << y; + (*newRow)[index++] = y; if (y > biggest) biggest = y; if (y < smallest) smallest = y; } + *dataArray << newRow; } - m_chart->setSegmentCount(4, 0.5f); // Going to be obsolete - m_chart->appendSeries(series, m_xCount, m_zCount); - - m_chart->axisZ()->setSegmentCount(7); + m_chart->axisX()->setRange(0.0, qreal(m_xCount - 1)); + m_chart->axisY()->setRange(0.0, 2.0); + m_chart->axisZ()->setRange(0.0, qreal(m_zCount - 1)); + m_chart->activeDataProxy()->resetArray(dataArray); - qDebug() << "biggest = " << biggest << ", smallest = " << smallest; + //qDebug() << "biggest = " << biggest << ", smallest = " << smallest; } else { qDebug() << "Remove surface"; } @@ -88,24 +96,52 @@ void ChartModifier::toggleSqrtSin(bool enable) void ChartModifier::togglePlane(bool enable) { qDebug() << "ChartModifier::togglePlane " << enable; - if (enable) { - QList series; + if (enable) { + QSurfaceDataArray *dataArray = new QSurfaceDataArray; qreal y = 2.0 / qreal(m_zCount - 1); + dataArray->reserve(m_zCount); for (int i = 0; i < m_zCount; i++) { - for (int j = 0; j < m_xCount; j++) { - series << i * y; - } + QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); + for (int j = 0; j < m_xCount; j++) + (*newRow)[j] = i * y; + *dataArray << newRow; } - m_chart->setSegmentCount(4, 0.5f); - m_chart->appendSeries(series, m_xCount, m_zCount); - m_chart->axisX()->setSegmentCount(m_xCount - 1); - m_chart->axisX()->setRange(1.0, qreal(m_xCount)); - m_chart->axisY()->setSegmentCount(4); + m_chart->axisX()->setSegmentCount(3); + m_chart->axisX()->setRange(0.0, qreal(m_xCount - 1)); + //m_chart->axisY()->setSegmentCount(4); m_chart->axisY()->setRange(0.0, 2.0); - m_chart->axisZ()->setSegmentCount(m_zCount - 1); - m_chart->axisZ()->setRange(1.0, qreal(m_zCount)); + //m_chart->axisZ()->setSegmentCount(4/*m_zCount - 1*/); + m_chart->axisZ()->setRange(0.0, qreal(m_zCount - 1)); + + m_chart->activeDataProxy()->resetArray(dataArray); + } +} + +void ChartModifier::setHeightMapData(bool enable) +{ + if (enable) { + QImage image(":/maps/map"); + + QSurfaceDataArray *dataArray = new QSurfaceDataArray; + uchar *bits = image.bits(); + + 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++) + (*newRow)[j] = (qreal(bits[p + (j * 4)]) + 1.0) / 1.0; + *dataArray << newRow; + } + + m_chart->axisX()->setRange(0.0, qreal(image.width() - 1)); + m_chart->axisY()->setRange(0.0, 255.0); + m_chart->axisZ()->setRange(0.0, qreal(image.height() - 1)); + + m_chart->activeDataProxy()->resetArray(dataArray); } } diff --git a/examples/surfacechart/chartmodifier.h b/examples/surfacechart/chartmodifier.h index 3ab2d179..3c0f8ad9 100644 --- a/examples/surfacechart/chartmodifier.h +++ b/examples/surfacechart/chartmodifier.h @@ -35,6 +35,7 @@ public: void toggleSurfaceGrid(bool enable); void toggleSqrtSin(bool enable); void togglePlane(bool enable); + void setHeightMapData(bool enable); void toggleGridSliderLock(bool enable); void setGridSliderX(QSlider *slider) { m_gridSliderX = slider; } void setGridSliderZ(QSlider *slider) { m_gridSliderZ = slider; } diff --git a/examples/surfacechart/main.cpp b/examples/surfacechart/main.cpp index 1297d92b..00fd8627 100644 --- a/examples/surfacechart/main.cpp +++ b/examples/surfacechart/main.cpp @@ -72,6 +72,10 @@ int main(int argc, char *argv[]) planeCB->setText(QStringLiteral("Plane")); planeCB->setChecked(false); + QCheckBox *heightMapCB = new QCheckBox(widget); + heightMapCB->setText(QStringLiteral("Height map")); + heightMapCB->setChecked(false); + QCheckBox *gridSlidersLockCB = new QCheckBox(widget); gridSlidersLockCB->setText(QStringLiteral("Lock")); gridSlidersLockCB->setChecked(false); @@ -110,6 +114,7 @@ int main(int argc, char *argv[]) vLayout->addWidget(new QLabel(QStringLiteral("Select surface sample"))); vLayout->addWidget(sqrtSinCB); vLayout->addWidget(planeCB); + vLayout->addWidget(heightMapCB); vLayout->addWidget(new QLabel(QStringLiteral("Adjust sample count"))); vLayout->addWidget(gridSlidersLockCB); vLayout->addWidget(gridSliderX); @@ -129,6 +134,8 @@ int main(int argc, char *argv[]) modifier, &ChartModifier::toggleSqrtSin); QObject::connect(planeCB, &QCheckBox::stateChanged, modifier, &ChartModifier::togglePlane); + QObject::connect(heightMapCB, &QCheckBox::stateChanged, + modifier, &ChartModifier::setHeightMapData); QObject::connect(gridSlidersLockCB, &QCheckBox::stateChanged, modifier, &ChartModifier::toggleGridSliderLock); QObject::connect(gridSliderX, &QSlider::valueChanged, diff --git a/examples/surfacechart/surface.qrc b/examples/surfacechart/surface.qrc new file mode 100644 index 00000000..c18da2c4 --- /dev/null +++ b/examples/surfacechart/surface.qrc @@ -0,0 +1,5 @@ + + + Heightmap.png + + diff --git a/examples/surfacechart/surfacechart.pro b/examples/surfacechart/surfacechart.pro index 6b3067ae..2ebc90da 100644 --- a/examples/surfacechart/surfacechart.pro +++ b/examples/surfacechart/surfacechart.pro @@ -12,4 +12,5 @@ INSTALLS += target HEADERS += \ chartmodifier.h -QT += widgets +RESOURCES += \ + surface.qrc diff --git a/src/datavis3d/data/data.pri b/src/datavis3d/data/data.pri index 312a8658..da5fa477 100644 --- a/src/datavis3d/data/data.pri +++ b/src/datavis3d/data/data.pri @@ -25,7 +25,9 @@ HEADERS += \ $$PWD/baritemmodelhandler_p.h \ $$PWD/qabstractdatamapping.h \ $$PWD/qabstractdatamapping_p.h \ - $$PWD/scatteritemmodelhandler_p.h + $$PWD/scatteritemmodelhandler_p.h \ + $$PWD/qsurfacedataproxy.h \ + $$PWD/qsurfacedataproxy_p.h SOURCES += \ $$PWD/labelitem.cpp \ @@ -44,4 +46,5 @@ SOURCES += \ $$PWD/abstractitemmodelhandler.cpp \ $$PWD/baritemmodelhandler.cpp \ $$PWD/qabstractdatamapping.cpp \ - $$PWD/scatteritemmodelhandler.cpp + $$PWD/scatteritemmodelhandler.cpp \ + $$PWD/qsurfacedataproxy.cpp diff --git a/src/datavis3d/data/qabstractdataproxy.h b/src/datavis3d/data/qabstractdataproxy.h index 6cd2386d..ba190583 100644 --- a/src/datavis3d/data/qabstractdataproxy.h +++ b/src/datavis3d/data/qabstractdataproxy.h @@ -65,6 +65,7 @@ private: friend class Abstract3DController; friend class Bars3DController; friend class Scatter3DController; + friend class Surface3DController; }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qsurfacedataproxy.cpp b/src/datavis3d/data/qsurfacedataproxy.cpp new file mode 100644 index 00000000..4d2d2176 --- /dev/null +++ b/src/datavis3d/data/qsurfacedataproxy.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qsurfacedataproxy.h" +#include "qsurfacedataproxy_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +/*! + * Constructs QSurfaceDataProxy with the given \a parent. + */ +QSurfaceDataProxy::QSurfaceDataProxy(QObject *parent) : + QAbstractDataProxy(new QSurfaceDataProxyPrivate(this), parent) +{ +} + +/*! + * \internal + */ +QSurfaceDataProxy::QSurfaceDataProxy(QSurfaceDataProxyPrivate *d, QObject *parent) : + QAbstractDataProxy(d, parent) +{ +} + +/*! + * Destroys QSurfaceDataProxy. + */ +QSurfaceDataProxy::~QSurfaceDataProxy() +{ +} + +void QSurfaceDataProxy::resetArray(QSurfaceDataArray *newArray) +{ + if (dptr()->resetArray(newArray)) + emit arrayReset(); +} + +const QSurfaceDataArray *QSurfaceDataProxy::array() const +{ + return dptrc()->m_dataArray; +} + +const QSurfaceDataItem *QSurfaceDataProxy::itemAt(int index) const +{ + return &dptrc()->m_dataArray->at(index)->at(2); +} + +QSurfaceDataProxyPrivate *QSurfaceDataProxy::dptr() +{ + return static_cast(d_ptr.data()); +} + +const QSurfaceDataProxyPrivate *QSurfaceDataProxy::dptrc() const +{ + return static_cast(d_ptr.data()); +} + +// +// QSurfaceDataProxyPrivate +// + +QSurfaceDataProxyPrivate::QSurfaceDataProxyPrivate(QSurfaceDataProxy *q) + : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeSurface), + m_dataArray(new QSurfaceDataArray) +{ + m_itemLabelFormat = QStringLiteral("(@yLabel)"); +} + +QSurfaceDataProxyPrivate::~QSurfaceDataProxyPrivate() +{ + m_dataArray->clear(); + delete m_dataArray; +} + +bool QSurfaceDataProxyPrivate::resetArray(QSurfaceDataArray *newArray) +{ + if (!m_dataArray->size() && (!newArray || !newArray->size())) + return false; + + m_dataArray->clear(); + delete m_dataArray; + + if (newArray) + m_dataArray = newArray; + else + m_dataArray = new QSurfaceDataArray; + + return true; +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qsurfacedataproxy.h b/src/datavis3d/data/qsurfacedataproxy.h new file mode 100644 index 00000000..70481ee2 --- /dev/null +++ b/src/datavis3d/data/qsurfacedataproxy.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QSURFACEDATAPROXY_H +#define QSURFACEDATAPROXY_H + +#include +#include + +QT_DATAVIS3D_BEGIN_NAMESPACE + +typedef qreal QSurfaceDataItem; // Let's stick to this for now, expand if needed +typedef QVector QSurfaceDataRow; +typedef QList QSurfaceDataArray; + +class QSurfaceDataProxyPrivate; + +class QT_DATAVIS3D_EXPORT QSurfaceDataProxy : public QAbstractDataProxy +{ + Q_OBJECT + +public: + explicit QSurfaceDataProxy(QObject *parent = 0); + virtual ~QSurfaceDataProxy(); + + int itemCount() const; + const QSurfaceDataArray *array() const; + const QSurfaceDataItem *itemAt(int index) const; + + void resetArray(QSurfaceDataArray *newArray); + +signals: + void arrayReset(); + +protected: + explicit QSurfaceDataProxy(QSurfaceDataProxyPrivate *d, QObject *parent = 0); + QSurfaceDataProxyPrivate *dptr(); + const QSurfaceDataProxyPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QSurfaceDataProxy) + + friend class Surface3DController; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QSURFACEDATAPROXY_H diff --git a/src/datavis3d/data/qsurfacedataproxy_p.h b/src/datavis3d/data/qsurfacedataproxy_p.h new file mode 100644 index 00000000..f6a13818 --- /dev/null +++ b/src/datavis3d/data/qsurfacedataproxy_p.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// 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 QSURFACEDATAPROXY_P_H +#define QSURFACEDATAPROXY_P_H + +#include "qsurfacedataproxy.h" +#include "qabstractdataproxy_p.h" + +#include + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QSurfaceDataProxyPrivate : public QAbstractDataProxyPrivate +{ + Q_OBJECT +public: + QSurfaceDataProxyPrivate(QSurfaceDataProxy *q); + virtual ~QSurfaceDataProxyPrivate(); + + bool resetArray(QSurfaceDataArray *newArray); + +private: + QSurfaceDataArray *m_dataArray; + + friend class QSurfaceDataProxy; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QSURFACEDATAPROXY_P_H diff --git a/src/datavis3d/engine/q3dsurface.cpp b/src/datavis3d/engine/q3dsurface.cpp index aee3ecf2..6607b552 100644 --- a/src/datavis3d/engine/q3dsurface.cpp +++ b/src/datavis3d/engine/q3dsurface.cpp @@ -19,6 +19,7 @@ #include "q3dsurface.h" #include "q3dsurface_p.h" #include "q3dvalueaxis.h" +#include "qsurfacedataproxy.h" #include @@ -265,57 +266,56 @@ QList Q3DSurface::axes() const return retList; } -void Q3DSurface::setGradientColorAt(qreal pos, const QColor &color) +void Q3DSurface::setActiveDataProxy(QSurfaceDataProxy *proxy) { - d_ptr->m_shared->setGradientColorAt(pos, color); + d_ptr->m_shared->setActiveDataProxy(proxy); } -// TODO ///////////////////////////////////////// -void Q3DSurface::appendSeries(QList series, int width, int depth ) +/*! + * \return active data proxy. + */ +QSurfaceDataProxy *Q3DSurface::activeDataProxy() const { - d_ptr->appendSeries(series); - d_ptr->m_shared->setData(series, width, depth); + return static_cast(d_ptr->m_shared->activeDataProxy()); } -void Q3DSurface::showData() const +void Q3DSurface::addDataProxy(QSurfaceDataProxy *proxy) { - for (int i = 0; i < d_ptr->numOfSeries(); i++) { - QList s = d_ptr->seriesAt(i); - qDebug() << "Series = "; - foreach (qreal val, s) { - qDebug() << val; - } - } + d_ptr->m_shared->addDataProxy(proxy); } -// TODO END ////////////////////////////////////////// - -/////////////////// PRIVATE /////////////////////////////////// - -Q3DSurfacePrivate::Q3DSurfacePrivate(Q3DSurface *q, QRect rect) - : q_ptr(q), - m_shared(new Surface3DController(rect)) +void Q3DSurface::releaseDataProxy(QSurfaceDataProxy *proxy) { + d_ptr->m_shared->releaseDataProxy(proxy); } -Q3DSurfacePrivate::~Q3DSurfacePrivate() +QList Q3DSurface::dataProxies() const { - delete m_shared; + QList retList; + QList abstractList = d_ptr->m_shared->dataProxies(); + foreach (QAbstractDataProxy *proxy, abstractList) + retList.append(static_cast(proxy)); + + return retList; } -void Q3DSurfacePrivate::appendSeries(QList series) + +void Q3DSurface::setGradientColorAt(qreal pos, const QColor &color) { - m_seriesList.append(series); + d_ptr->m_shared->setGradientColorAt(pos, color); } -QList Q3DSurfacePrivate::seriesAt(int i) +/////////////////// PRIVATE /////////////////////////////////// + +Q3DSurfacePrivate::Q3DSurfacePrivate(Q3DSurface *q, QRect rect) + : q_ptr(q), + m_shared(new Surface3DController(rect)) { - return m_seriesList.at(i); } -int Q3DSurfacePrivate::numOfSeries() +Q3DSurfacePrivate::~Q3DSurfacePrivate() { - return m_seriesList.count(); + delete m_shared; } QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dsurface.h b/src/datavis3d/engine/q3dsurface.h index 9492bfe4..e99600dd 100644 --- a/src/datavis3d/engine/q3dsurface.h +++ b/src/datavis3d/engine/q3dsurface.h @@ -26,6 +26,7 @@ QT_DATAVIS3D_BEGIN_NAMESPACE class Q3DSurfacePrivate; class Q3DValueAxis; +class QSurfaceDataProxy; class QT_DATAVIS3D_EXPORT Q3DSurface : public Q3DWindow { @@ -68,14 +69,15 @@ public: void releaseAxis(Q3DValueAxis *axis); QList axes() const; + void setActiveDataProxy(QSurfaceDataProxy *proxy); + QSurfaceDataProxy *activeDataProxy() const; + void addDataProxy(QSurfaceDataProxy *proxy); + void releaseDataProxy(QSurfaceDataProxy *proxy); + QList dataProxies() const; + // TODO: Remove when axes handling in use void setSegmentCount(int segmentCount, qreal step, qreal minimum = 0.0f); -//TODO part - void appendSeries(QList series, int width, int depth); - void showData() const; -//END TODO - // TODO: Do these need to be public? Where are they called from? // Size void setWidth(const int width); diff --git a/src/datavis3d/engine/q3dsurface_p.h b/src/datavis3d/engine/q3dsurface_p.h index 7009af0f..d119f01f 100644 --- a/src/datavis3d/engine/q3dsurface_p.h +++ b/src/datavis3d/engine/q3dsurface_p.h @@ -44,16 +44,8 @@ public: Q3DSurfacePrivate(Q3DSurface *q, QRect rect); ~Q3DSurfacePrivate(); - // TODO - void appendSeries(QList series); - QList seriesAt(int i); - int numOfSeries(); - // TODO - Q3DSurface *q_ptr; Surface3DController *m_shared; - - QList > m_seriesList; // Temp to be replaced by dataset }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/surface3dcontroller.cpp b/src/datavis3d/engine/surface3dcontroller.cpp index 90e23f07..01e24a92 100644 --- a/src/datavis3d/engine/surface3dcontroller.cpp +++ b/src/datavis3d/engine/surface3dcontroller.cpp @@ -22,6 +22,7 @@ #include "q3dabstractaxis_p.h" #include "q3dvalueaxis_p.h" #include "q3dcategoryaxis.h" +#include "qsurfacedataproxy_p.h" #include #include @@ -38,6 +39,8 @@ Surface3DController::Surface3DController(QRect rect) m_mouseState(MouseNone), m_mousePos(QPoint(0, 0)) { + setActiveDataProxy(0); + // Setting a null axis creates a new default axis according to orientation and chart type. // Note: These cannot be set in Abstract3DController constructor, as they will call virtual // functions implemented by subclasses. @@ -70,6 +73,10 @@ void Surface3DController::synchDataToRenderer() return; // Notify changes to renderer + if (m_isDataDirty) { + m_renderer->updateDataModel(static_cast(m_data)); + m_isDataDirty = false; + } } void Surface3DController::handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust) @@ -174,6 +181,31 @@ QPoint Surface3DController::mousePosition() return m_mousePos; } +void Surface3DController::setActiveDataProxy(QAbstractDataProxy *proxy) +{ + // Setting null proxy indicates default proxy + if (!proxy) { + proxy = new QSurfaceDataProxy; + proxy->d_ptr->setDefaultProxy(true); + } + + Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeSurface); + + Abstract3DController::setActiveDataProxy(proxy); + + QSurfaceDataProxy *surfaceDataProxy = static_cast(m_data); + + // TODO connections and handler for proxy changes + QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::arrayReset, + this, &Surface3DController::handleArrayReset); +} + +void Surface3DController::handleArrayReset() +{ + m_isDataDirty = true; + emitNeedRender(); +} + void Surface3DController::setSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum) { m_segmentCount = segmentCount; @@ -191,16 +223,4 @@ void Surface3DController::setGradientColorAt(qreal pos, const QColor &color) emitNeedRender(); } -// TODO: Temp -void Surface3DController::setData(QList series, int width, int depth) -{ - m_series = series; - m_dataWidth = width; - m_dataDepth = depth; - - m_renderer->setXZStuff(width, depth); - m_renderer->setSeries(series); - emitNeedRender(); -} - QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/surface3dcontroller_p.h b/src/datavis3d/engine/surface3dcontroller_p.h index d9f69f28..c626a00d 100644 --- a/src/datavis3d/engine/surface3dcontroller_p.h +++ b/src/datavis3d/engine/surface3dcontroller_p.h @@ -97,8 +97,13 @@ public: void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); void wheelEvent(QWheelEvent *event); + virtual void setActiveDataProxy(QAbstractDataProxy *proxy); + virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust); +public slots: + void handleArrayReset(); + signals: void smoothStatusChanged(bool enable); void surfaceGridChanged(bool enable); diff --git a/src/datavis3d/engine/surface3drenderer.cpp b/src/datavis3d/engine/surface3drenderer.cpp index 43d307ae..345fcc32 100644 --- a/src/datavis3d/engine/surface3drenderer.cpp +++ b/src/datavis3d/engine/surface3drenderer.cpp @@ -56,23 +56,16 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) m_shadowQuality(QDataVis::ShadowLow), m_segmentYCount(0), m_segmentYStep(0.0f), - m_segmentXCount(0), - m_segmentZCount(0), m_shader(0), m_backgroundShader(0), m_surfaceShader(0), m_surfaceGridShader(0), m_selectionShader(0), m_labelShader(0), - m_yRange(0.0f), // m_heightNormalizer - m_yAdjustment(0.0f), - m_xLength(0.0f), - m_zLength(0.0f), - m_maxDimension(0.0f), + m_heightNormalizer(0.0f), m_scaleFactor(0.0f), m_scaleX(0.0f), m_scaleZ(0.0f), - m_maxSceneSize(40.0), m_backgroundObj(0), m_gridLineObj(0), m_labelObj(0), @@ -90,15 +83,14 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) m_selectionActive(false), m_xFlipped(false), m_zFlipped(false), - m_yFlipped(false) + m_yFlipped(false), + m_sampleSpace(QRect(0, 0, 0, 0)) { // 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::segmentCountChanged, this, - &Surface3DRenderer::updateSegmentCount); QObject::connect(m_controller, &Surface3DController::leftMousePressed, this, &Surface3DRenderer::requestSelectionAtPoint); // TODO: Possible temp @@ -171,23 +163,56 @@ void Surface3DRenderer::initializeOpenGL() updateSurfaceGradient(); } -void Surface3DRenderer::render(CameraHelper *camera, const GLuint defaultFboHandle) +void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy) { - if (defaultFboHandle) { - glDepthMask(true); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); + // Make a copy of data array. + for (int i = 0; i < m_dataArray.size(); i++) + delete m_dataArray.at(i); + m_dataArray.clear(); + + const QSurfaceDataArray *array = dataProxy->array(); + + m_dataArray.reserve(array->size()); + for (int i = 0; i < array->size(); i++) { + QSurfaceDataRow *newRow = new QSurfaceDataRow(*array->at(i)); + m_dataArray << newRow; + } + + if (m_dataArray.size() > 0) { + if (!m_surfaceObj) + loadSurfaceObj(); + + QRect sampleSpace(0, 0, m_dataArray.at(0)->size(), m_dataArray.size()); + + bool dimensionChanged = false; + if (m_sampleSpace != sampleSpace) { + dimensionChanged = true; + m_sampleSpace = sampleSpace; + } + + // TODO: Setting height bigger than biggest value on data works nicely, but smaller + // creates odd scaling. That's not going to be trivial to clip 'peaks' off + m_heightNormalizer = (GLfloat)qMax(qAbs(m_axisCacheY.max()), qAbs(m_axisCacheY.min())); + + if (m_cachedSmoothSurface) + m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer, dimensionChanged); + else + m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer, dimensionChanged); + + if (dimensionChanged) + updateSelectionTexture(); } - 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); + calculateSceneScalingFactors(); + + Abstract3DRenderer::updateDataModel(dataProxy); +} + +void Surface3DRenderer::render(CameraHelper *camera, const GLuint defaultFboHandle) +{ + // Handle GL state setup for FBO buffers and clearing of the render surface + Abstract3DRenderer::render(camera, defaultFboHandle); - // 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 camera->setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 6.0f + zComp), QVector3D(0.0f, 0.0f, zComp), QVector3D(0.0f, 1.0f, 0.0f)); @@ -229,7 +254,6 @@ void Surface3DRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboH else m_xFlipped = true; - // calculate background rotation based on view matrix rotation if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() <= 0) backgroundRotation = 270.0f; @@ -245,7 +269,7 @@ void Surface3DRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboH QMatrix4x4 depthViewMatrix; QMatrix4x4 depthProjectionMatrix; depthProjectionMatrix = projectionMatrix; // TODO - depthViewMatrix.lookAt(lightPos, QVector3D(0.0f, -m_yAdjustment, zComp), + depthViewMatrix.lookAt(lightPos, QVector3D(0.0f, 0.0f, zComp), QVector3D(0.0f, 1.0f, 0.0f)); // TODO: Move // Enable texturing @@ -268,7 +292,7 @@ void Surface3DRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboH QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; - modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); + modelMatrix.translate(0.0f, 0.0f, zComp); modelMatrix.scale(QVector3D(m_scaleX, 1.0f, m_scaleZ)); MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; @@ -321,7 +345,7 @@ void Surface3DRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboH // Put the RGBA value back to uint uint id = pixel[0] + pixel[1] * 256 + pixel[2] * 65536 + pixel[3] * 16777216; if (id) { - surfacePointSelected(m_series.at(id - 1), (id - 1) % m_segmentXCount, (id - 1) / m_segmentXCount); + surfacePointSelected(id); } else { //surfacePointCleared(); m_selectionActive = false; @@ -340,7 +364,7 @@ void Surface3DRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboH QMatrix4x4 depthMVPMatrix; QMatrix4x4 itModelMatrix; - modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); + modelMatrix.translate(0.0f, 0.0f, zComp); modelMatrix.scale(QVector3D(m_scaleX, 1.0f, m_scaleZ)); itModelMatrix.scale(QVector3D(m_scaleX, 1.0f, m_scaleZ)); @@ -413,7 +437,7 @@ void Surface3DRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboH QMatrix4x4 depthMVPMatrix; QMatrix4x4 itModelMatrix; - modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); + modelMatrix.translate(0.0f, 0.0f, zComp); modelMatrix.scale(QVector3D(m_scaleX * backgroundMargin, 1.0f, m_scaleZ * backgroundMargin)); modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); itModelMatrix.scale(QVector3D(m_scaleX * backgroundMargin, 1.0f, m_scaleZ * backgroundMargin)); @@ -862,28 +886,6 @@ void Surface3DRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboH } -void Surface3DRenderer::updateSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum) -{ - m_segmentYCount = segmentCount; - m_segmentYStep = step; - if (segmentCount > 0 && step > 0.0) { - m_yRange = m_segmentYCount * m_segmentYStep; - m_yAdjustment = 2.0f - ((m_yRange - minimum) / m_yRange); // TODO: to function - } -} - -void Surface3DRenderer::setXZStuff(GLint segmentXCount, GLint segmentZCount) -{ - m_segmentXCount = segmentXCount; - m_segmentZCount = segmentZCount; - - // TODO: Invent "idiotproof" max scene size formula.. - // This seems to work ok if spacing is not negative (and row/column or column/row ratio is not too high) - m_maxSceneSize = 2 * qSqrt(segmentXCount * segmentZCount); - - calculateSceneScalingFactors(); -} - void Surface3DRenderer::updateSurfaceGradient() { QImage image(QSize(4, 100), QImage::Format_RGB32); @@ -918,8 +920,8 @@ void Surface3DRenderer::updateSelectionTexture() // Create the selection ID image. Each grid corner gets 2x2 pixel area of // ID color so that each vertex (data point) has 4x4 pixel area of ID color // TODO: power of two thing for ES - int idImageWidth = (m_segmentXCount - 1) * 4; - int idImageHeight = (m_segmentZCount - 1) * 4; + int idImageWidth = (m_sampleSpace.width() - 1) * 4; + int idImageHeight = (m_sampleSpace.height() - 1) * 4; int stride = idImageWidth * 4 * sizeof(uchar); // 4 = number of color components (rgba) uchar *bits = new uchar[idImageWidth * idImageHeight * 4 * sizeof(uchar)]; @@ -934,10 +936,10 @@ void Surface3DRenderer::updateSelectionTexture() idToRGBA(id + 1, &r, &g, &b, &a); fillIdCorner(&bits[p + 8], r, g, b, a, stride); - idToRGBA(id + m_segmentXCount, &r, &g, &b, &a); + idToRGBA(id + m_sampleSpace.width(), &r, &g, &b, &a); fillIdCorner(&bits[p + 2 * stride], r, g, b, a, stride); - idToRGBA(id + m_segmentXCount + 1, &r, &g, &b, &a); + idToRGBA(id + m_sampleSpace.width() + 1, &r, &g, &b, &a); fillIdCorner(&bits[p + 2 * stride + 8], r, g, b, a, stride); id++; @@ -1003,22 +1005,6 @@ void Surface3DRenderer::idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a *a = (id >> 24) & ID_TO_RGBA_MASK; } -void Surface3DRenderer::setSeries(QList series) -{ - m_series = series; - - // TODO temp solution - if (!m_surfaceObj) - loadSurfaceObj(); - - if (m_cachedSmoothSurface) - m_surfaceObj->setUpSmoothData(series, m_segmentXCount, m_segmentZCount, m_yRange, true); - else - m_surfaceObj->setUpData(series, m_segmentXCount, m_segmentZCount, m_yRange, true); - - updateSelectionTexture(); -} - void Surface3DRenderer::updateTextures() { qDebug() << __FUNCTION__ << "NEED TO DO SOMETHING"; @@ -1029,21 +1015,12 @@ void Surface3DRenderer::updateTextures() void Surface3DRenderer::calculateSceneScalingFactors() { // Calculate scene scaling and translation factors - m_xLength = m_segmentXCount; - m_zLength = m_segmentZCount; - m_maxDimension = qMax(m_xLength, m_zLength); -// m_scaleFactor = qMin((m_segmentXCount * (m_maxDimension / m_maxSceneSize)), -// (m_segmentZCount * (m_maxDimension / m_maxSceneSize))); -// m_scaleX = 1.0f / m_scaleFactor; -// m_scaleZ = 1.0f / m_scaleFactor; - - m_scaleFactor = qMax(m_xLength, m_zLength); - m_scaleX = (coordSpace * m_xLength) / m_scaleFactor; - m_scaleZ = (coordSpace * m_zLength) / m_scaleFactor; + m_scaleFactor = qMax(m_sampleSpace.width(), m_sampleSpace.height()); + m_scaleX = (coordSpace * m_sampleSpace.width()) / m_scaleFactor; + m_scaleZ = (coordSpace * m_sampleSpace.height()) / m_scaleFactor; //qDebug() << "m_scaleX" << m_scaleX << "m_scaleFactor" << m_scaleFactor; //qDebug() << "m_scaleZ" << m_scaleZ << "m_scaleFactor" << m_scaleFactor; - //qDebug() << "m_rowWidth:" << m_rowWidth << "m_columnDepth:" << m_columnDepth << "m_maxDimension:" << m_maxDimension; } void Surface3DRenderer::updateSmoothStatus(bool enable) @@ -1054,9 +1031,9 @@ void Surface3DRenderer::updateSmoothStatus(bool enable) return; if (m_cachedSmoothSurface) - m_surfaceObj->setUpSmoothData(m_series, m_segmentXCount, m_segmentZCount, m_yRange, true); + m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer, true); else - m_surfaceObj->setUpData(m_series, m_segmentXCount, m_segmentZCount, m_yRange, true); + m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer, true); initSurfaceShaders(); } @@ -1143,8 +1120,12 @@ void Surface3DRenderer::updateDepthBuffer() } #endif -void Surface3DRenderer::surfacePointSelected(qreal value, int column, int row) +void Surface3DRenderer::surfacePointSelected(int id) { + int column = (id - 1) % m_sampleSpace.width(); + int row = (id - 1) / m_sampleSpace.width(); + qreal value = m_dataArray.at(row)->at(column); + if (!m_selectionPointer) m_selectionPointer = new SelectionPointer(m_controller); @@ -1159,9 +1140,9 @@ void Surface3DRenderer::surfacePointSelected(qreal value, int column, int row) QVector3D Surface3DRenderer::normalize(float x, float y, float z) { - float resX = x / ((float(m_segmentXCount) - 1.0f) / 2.0f) - 1.0f; - float resY = y / (m_yRange / 2.0f) - 1.0f; - float resZ = z / ((float(m_segmentZCount) - 1.0f) / -2.0f) + 1.0f; + float resX = x / ((float(m_sampleSpace.width()) - 1.0f) / 2.0f) - 1.0f; + float resY = y / (m_heightNormalizer / 2.0f) - 1.0f; + float resZ = z / ((float(m_sampleSpace.height()) - 1.0f) / -2.0f) + 1.0f; return QVector3D(resX, resY, resZ); } diff --git a/src/datavis3d/engine/surface3drenderer_p.h b/src/datavis3d/engine/surface3drenderer_p.h index a8d21478..4649b997 100644 --- a/src/datavis3d/engine/surface3drenderer_p.h +++ b/src/datavis3d/engine/surface3drenderer_p.h @@ -40,6 +40,7 @@ #include "surface3dcontroller_p.h" #include "abstract3drenderer_p.h" #include "scatterrenderitem_p.h" +#include "qsurfacedataproxy.h" class QOpenGLShaderProgram; @@ -74,8 +75,6 @@ private: QList m_series; // TODO: TEMP GLint m_segmentYCount; GLfloat m_segmentYStep; - GLint m_segmentXCount; - GLint m_segmentZCount; // Internal attributes purely related to how the scene is drawn with GL. QRect m_mainViewPort; @@ -85,15 +84,10 @@ private: ShaderHelper *m_surfaceGridShader; ShaderHelper *m_selectionShader; ShaderHelper *m_labelShader; - GLfloat m_yRange; // m_heightNormalizer - GLfloat m_yAdjustment; - GLfloat m_xLength; - GLfloat m_zLength; - GLfloat m_maxDimension; + GLfloat m_heightNormalizer; GLfloat m_scaleFactor; GLfloat m_scaleX; GLfloat m_scaleZ; - GLfloat m_maxSceneSize; ObjectHelper *m_backgroundObj; ObjectHelper *m_gridLineObj; ObjectHelper *m_labelObj; @@ -115,26 +109,24 @@ private: bool m_zFlipped; bool m_yFlipped; ScatterRenderItem m_dummyRenderItem; // Let's use scatter for dummy for now - -protected: - virtual void loadMeshFile(); + QSurfaceDataArray m_dataArray; + QRect m_sampleSpace; public: explicit Surface3DRenderer(Surface3DController *controller); ~Surface3DRenderer(); - void initializeOpenGL(); + void updateDataModel(QSurfaceDataProxy *dataProxy); void render(CameraHelper *camera, const GLuint defaultFboHandle = 0); - // TODO: temp - void setXZStuff(GLint segmentXCount, GLint segmentZCount); - void setSeries(QList series); +protected: + void initializeOpenGL(); + virtual void loadMeshFile(); public slots: void updateSmoothStatus(bool enable); void updateSurfaceGridStatus(bool enable); void updateSurfaceGradient(); - void updateSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum = 0.0f); virtual void requestSelectionAtPoint(const QPoint &point); private: @@ -156,7 +148,7 @@ private: void updateSelectionTexture(); 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(qreal value, int column, int row); + void surfacePointSelected(int id); void surfacePointCleared(); QVector3D normalize(float x, float y, float z); #if !defined(QT_OPENGL_ES_2) diff --git a/src/datavis3d/utils/surfaceobject.cpp b/src/datavis3d/utils/surfaceobject.cpp index b985bec0..211e483f 100644 --- a/src/datavis3d/utils/surfaceobject.cpp +++ b/src/datavis3d/utils/surfaceobject.cpp @@ -35,8 +35,10 @@ SurfaceObject::~SurfaceObject() { } -void SurfaceObject::setUpSmoothData(QList series, int columns, int rows, GLfloat yRange, bool changeGeometry) +void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, QRect space, GLfloat yRange, bool changeGeometry) { + int columns = space.width(); + int rows = space.height(); GLfloat width = (GLfloat(columns) - 1.0f) / 2.0f; GLfloat depth = (GLfloat(rows) - 1.0f) / -2.0f; GLfloat height = yRange / 2.0f; @@ -50,7 +52,7 @@ void SurfaceObject::setUpSmoothData(QList series, int columns, int rows, for (float i = 0.0f; i < float(rows); i += 1.0, row += columns) { for (float j = 0; j < columns; j++) { vertices.append(QVector3D(j / width - 1.0f, - series.at(row + int(j)) / height - 1.0f, + dataArray.at(int(i))->at(int(j)) / height - 1.0f, i / depth + 1.0f)); uvs.append(QVector2D(j * uvX, i * uvY)); } @@ -127,8 +129,10 @@ void SurfaceObject::setUpSmoothData(QList series, int columns, int rows, } -void SurfaceObject::setUpData(QList series, int columns, int rows, GLfloat yRange, bool changeGeometry) +void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, QRect space, GLfloat yRange, bool changeGeometry) { + int columns = space.width(); + int rows = space.height(); GLfloat width = (GLfloat(columns) - 1.0f) / 2.0f; GLfloat depth = (GLfloat(rows) - 1.0f) / -2.0f; GLfloat height = yRange / 2.0f; @@ -142,7 +146,7 @@ void SurfaceObject::setUpData(QList series, int columns, int rows, GLfloa for (float i = 0.0f; i < float(rows); i += 1.0f, row += columns) { for (float j = 0.0f; j < float(columns); j += 1.0f) { vertices.append(QVector3D(j / width - 1.0f, - series.at(row + int(j)) / height - 1.0f, + dataArray.at(int(i))->at(int(j)) / height - 1.0f, i / depth + 1.0f)); uvs.append(QVector2D(j * uvX, i * uvY)); if (j > 0 && j < columns - 1) { diff --git a/src/datavis3d/utils/surfaceobject_p.h b/src/datavis3d/utils/surfaceobject_p.h index 729757c4..e71d6832 100644 --- a/src/datavis3d/utils/surfaceobject_p.h +++ b/src/datavis3d/utils/surfaceobject_p.h @@ -31,7 +31,10 @@ #include "datavis3dglobal_p.h" #include "abstractobjecthelper_p.h" +#include "qsurfacedataproxy.h" + #include +#include QT_DATAVIS3D_BEGIN_NAMESPACE @@ -41,8 +44,8 @@ public: SurfaceObject(); ~SurfaceObject(); - void setUpData(QList series, int columns, int rows, GLfloat yRange, bool changeGeometry); - void setUpSmoothData(QList series, int columns, int rows, GLfloat yRange, bool changeGeometry); + void setUpData(const QSurfaceDataArray &dataArray, QRect space, GLfloat yRange, bool changeGeometry); + void setUpSmoothData(const QSurfaceDataArray &dataArray, QRect space, GLfloat yRange, bool changeGeometry); GLuint gridElementBuf(); GLuint gridIndexCount(); @@ -53,7 +56,6 @@ private: const GLint *gridIndices, bool changeGeometry); private: - QList m_series; int m_dataWidth; int m_dataDepth; GLfloat m_yRange; -- cgit v1.2.3