summaryrefslogtreecommitdiffstats
path: root/src/datavisualization
diff options
context:
space:
mode:
authorMika Salmela <mika.salmela@digia.com>2014-02-06 12:56:54 +0200
committerMika Salmela <mika.salmela@digia.com>2014-02-06 13:00:59 +0200
commite91237b54c2f58eaa8a2ce36bf016e2d8e8588f2 (patch)
treeec99b80a217b2e316a280c299fe5bc84edd7eb1b /src/datavisualization
parent427e7f5f5c62f728e159462dd28ae1ef76761d75 (diff)
Multiseries support for surface
Task-number: QTRD-2767 Change-Id: Ifa7ca07f2afdb27974ad20819f0a4646293764b0 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Diffstat (limited to 'src/datavisualization')
-rw-r--r--src/datavisualization/data/qabstract3dseries.h1
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp13
-rw-r--r--src/datavisualization/engine/abstract3drenderer_p.h1
-rw-r--r--src/datavisualization/engine/engine.pri6
-rw-r--r--src/datavisualization/engine/seriesrendercache.cpp4
-rw-r--r--src/datavisualization/engine/seriesrendercache_p.h2
-rw-r--r--src/datavisualization/engine/surface3dcontroller.cpp25
-rw-r--r--src/datavisualization/engine/surface3dcontroller_p.h1
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp751
-rw-r--r--src/datavisualization/engine/surface3drenderer_p.h24
-rw-r--r--src/datavisualization/engine/surfaceseriesrendercache.cpp73
-rw-r--r--src/datavisualization/engine/surfaceseriesrendercache_p.h101
-rw-r--r--src/datavisualization/global/datavisualizationglobal_p.h2
-rw-r--r--src/datavisualization/utils/surfaceobject.cpp7
-rw-r--r--src/datavisualization/utils/surfaceobject_p.h13
-rw-r--r--src/datavisualization/utils/texturehelper.cpp12
-rw-r--r--src/datavisualization/utils/texturehelper_p.h1
17 files changed, 659 insertions, 378 deletions
diff --git a/src/datavisualization/data/qabstract3dseries.h b/src/datavisualization/data/qabstract3dseries.h
index ebb22b7f..c45bb801 100644
--- a/src/datavisualization/data/qabstract3dseries.h
+++ b/src/datavisualization/data/qabstract3dseries.h
@@ -142,6 +142,7 @@ private:
friend class Abstract3DController;
friend class Bars3DController;
friend class Surface3DController;
+ friend class Surface3DRenderer;
friend class Scatter3DController;
friend class QBar3DSeries;
friend class SeriesRenderCache;
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp
index e3ec7c9a..e62f2a00 100644
--- a/src/datavisualization/engine/abstract3drenderer.cpp
+++ b/src/datavisualization/engine/abstract3drenderer.cpp
@@ -426,8 +426,17 @@ void Abstract3DRenderer::lowerShadowQuality()
updateShadowQuality(newQuality);
}
-void Abstract3DRenderer::fixGradientAndGenerateTexture(QLinearGradient *gradient,
- GLuint *gradientTexture)
+void Abstract3DRenderer::generateBaseColorTexture(const QColor &color, GLuint *texture)
+{
+ if (*texture) {
+ m_textureHelper->deleteTexture(texture);
+ *texture = 0;
+ }
+
+ *texture = m_textureHelper->createUniformTexture(color);
+}
+
+void Abstract3DRenderer::fixGradientAndGenerateTexture(QLinearGradient *gradient, GLuint *gradientTexture)
{
// Readjust start/stop to match gradient texture size
gradient->setStart(qreal(gradientTextureWidth), qreal(gradientTextureHeight));
diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h
index e7591a10..a381adf8 100644
--- a/src/datavisualization/engine/abstract3drenderer_p.h
+++ b/src/datavisualization/engine/abstract3drenderer_p.h
@@ -94,6 +94,7 @@ public:
virtual void updateAxisLabelFormat(QAbstract3DAxis::AxisOrientation orientation, const QString &format);
virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh);
+ void generateBaseColorTexture(const QColor &color, GLuint *texture);
void fixGradientAndGenerateTexture(QLinearGradient *gradient, GLuint *gradientTexture);
inline bool isClickPending() { return m_clickPending; }
diff --git a/src/datavisualization/engine/engine.pri b/src/datavisualization/engine/engine.pri
index e13a9a04..b686397c 100644
--- a/src/datavisualization/engine/engine.pri
+++ b/src/datavisualization/engine/engine.pri
@@ -26,7 +26,8 @@ HEADERS += $$PWD/qabstract3dgraph_p.h \
$$PWD/q3dbox.h \
$$PWD/q3dobject.h \
$$PWD/q3dobject_p.h \
- $$PWD/q3dscene_p.h
+ $$PWD/q3dscene_p.h \
+ $$PWD/surfaceseriesrendercache_p.h
SOURCES += $$PWD/qabstract3dgraph.cpp \
$$PWD/q3dbars.cpp \
@@ -48,6 +49,7 @@ SOURCES += $$PWD/qabstract3dgraph.cpp \
$$PWD/q3dlight.cpp \
$$PWD/q3dbox.cpp \
$$PWD/q3dobject.cpp \
- $$PWD/q3dscene.cpp
+ $$PWD/q3dscene.cpp \
+ $$PWD/surfaceseriesrendercache.cpp
RESOURCES += engine/engine.qrc
diff --git a/src/datavisualization/engine/seriesrendercache.cpp b/src/datavisualization/engine/seriesrendercache.cpp
index fe2db319..5d20e761 100644
--- a/src/datavisualization/engine/seriesrendercache.cpp
+++ b/src/datavisualization/engine/seriesrendercache.cpp
@@ -30,6 +30,7 @@ SeriesRenderCache::SeriesRenderCache()
: m_series(0),
m_object(0),
m_mesh(QAbstract3DSeries::MeshCube),
+ m_baseUniformTexture(0),
m_baseGradientTexture(0),
m_singleHighlightGradientTexture(0),
m_multiHighlightGradientTexture(0)
@@ -138,6 +139,8 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer *
if (seriesChanged || changeTracker.baseColorChanged) {
m_baseColor = Utils::vectorFromColor(series->baseColor());
+ if (m_series->type() == QAbstract3DSeries::SeriesTypeSurface)
+ renderer->generateBaseColorTexture(series->baseColor(), &m_baseUniformTexture);
changeTracker.baseColorChanged = false;
}
@@ -178,6 +181,7 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer *
void SeriesRenderCache::cleanup(TextureHelper *texHelper)
{
delete m_object;
+ texHelper->deleteTexture(&m_baseUniformTexture);
texHelper->deleteTexture(&m_baseGradientTexture);
texHelper->deleteTexture(&m_singleHighlightGradientTexture);
texHelper->deleteTexture(&m_multiHighlightGradientTexture);
diff --git a/src/datavisualization/engine/seriesrendercache_p.h b/src/datavisualization/engine/seriesrendercache_p.h
index 82f69ccd..7994339a 100644
--- a/src/datavisualization/engine/seriesrendercache_p.h
+++ b/src/datavisualization/engine/seriesrendercache_p.h
@@ -58,6 +58,7 @@ public:
inline ObjectHelper *object() const { return m_object; }
inline const Q3DTheme::ColorStyle &colorStyle() const { return m_colorStyle; }
inline const QVector3D &baseColor() const { return m_baseColor; }
+ inline const GLuint &baseUniformTexture() const { return m_baseUniformTexture; }
inline const GLuint &baseGradientTexture() const { return m_baseGradientTexture; }
inline const QVector3D &singleHighlightColor() const { return m_singleHighlightColor; }
inline const GLuint &singleHighlightGradientTexture() const { return m_singleHighlightGradientTexture; }
@@ -74,6 +75,7 @@ protected:
Q3DTheme::ColorStyle m_colorStyle;
QVector3D m_baseColor;
+ GLuint m_baseUniformTexture;
GLuint m_baseGradientTexture;
QVector3D m_singleHighlightColor;
GLuint m_singleHighlightGradientTexture;
diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp
index 664c4a71..553166e1 100644
--- a/src/datavisualization/engine/surface3dcontroller.cpp
+++ b/src/datavisualization/engine/surface3dcontroller.cpp
@@ -68,6 +68,11 @@ void Surface3DController::synchDataToRenderer()
if (!isInitialized())
return;
+ if (m_changedSeriesList.size()) {
+ m_renderer->modifiedSeriesList(m_changedSeriesList);
+ m_changedSeriesList.clear();
+ }
+
Abstract3DController::synchDataToRenderer();
// Notify changes to renderer
@@ -143,14 +148,10 @@ void Surface3DController::addSeries(QAbstract3DSeries *series)
{
Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeSurface);
- if (!m_seriesList.size()) {
- Abstract3DController::addSeries(series);
+ Abstract3DController::addSeries(series);
- if (series->isVisible())
- adjustValueAxisRange();
- } else {
- qWarning("Surface graph only supports a single series.");
- }
+ if (series->isVisible())
+ adjustValueAxisRange();
QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
if (surfaceSeries->selectedPoint() != invalidSelectionPosition())
@@ -260,7 +261,7 @@ void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSer
emitNeedRender();
}
- if (pos != m_selectedPoint) {
+ if (pos != m_selectedPoint || series != m_selectedSeries) {
m_selectedPoint = pos;
m_selectedSeries = series;
m_changeTracker.selectedPointChanged = true;
@@ -288,6 +289,8 @@ void Surface3DController::handleArrayReset()
QSurface3DSeries *series = static_cast<QSurfaceDataProxy *>(sender())->series();
if (series->isVisible()) {
adjustValueAxisRange();
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
m_isDataDirty = true;
}
// Clear selection unless still valid
@@ -375,6 +378,8 @@ void Surface3DController::handleRowsAdded(int startIndex, int count)
if (series->isVisible()) {
adjustValueAxisRange();
m_isDataDirty = true;
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
}
emitNeedRender();
}
@@ -396,6 +401,8 @@ void Surface3DController::handleRowsInserted(int startIndex, int count)
if (series->isVisible()) {
adjustValueAxisRange();
m_isDataDirty = true;
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
}
emitNeedRender();
@@ -422,6 +429,8 @@ void Surface3DController::handleRowsRemoved(int startIndex, int count)
if (series->isVisible()) {
adjustValueAxisRange();
m_isDataDirty = true;
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
}
emitNeedRender();
diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h
index 4ca9c8e2..64a57b3b 100644
--- a/src/datavisualization/engine/surface3dcontroller_p.h
+++ b/src/datavisualization/engine/surface3dcontroller_p.h
@@ -67,6 +67,7 @@ private:
bool m_flatShadingSupported;
QVector<QPoint> m_changedItems;
QVector<int> m_changedRows;
+ QVector<QSurface3DSeries *> m_changedSeriesList;
public:
explicit Surface3DController(QRect rect, Q3DScene *scene = 0);
diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp
index 4dbd48ba..48d10932 100644
--- a/src/datavisualization/engine/surface3drenderer.cpp
+++ b/src/datavisualization/engine/surface3drenderer.cpp
@@ -60,7 +60,8 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_cachedIsSlicingActivated(false),
m_depthShader(0),
m_backgroundShader(0),
- m_surfaceShader(0),
+ m_surfaceFlatShader(0),
+ m_surfaceSmoothShader(0),
m_surfaceGridShader(0),
m_selectionShader(0),
m_labelShader(0),
@@ -84,19 +85,15 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_gridLineObj(0),
m_labelObj(0),
m_surfaceObj(0),
- m_sliceSurfaceObj(0),
m_depthTexture(0),
m_depthModelTexture(0),
m_depthFrameBuffer(0),
m_selectionFrameBuffer(0),
m_selectionDepthBuffer(0),
- m_selectionTexture(0),
m_selectionResultTexture(0),
m_shadowQualityToShader(33.3f),
m_cachedFlatShading(false),
m_flatSupported(true),
- m_cachedSurfaceVisible(true),
- m_cachedSurfaceGridOn(true),
m_selectionPointer(0),
m_selectionActive(false),
m_xFlipped(false),
@@ -108,8 +105,8 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_hasHeightAdjustmentChanged(true),
m_selectedPoint(Surface3DController::invalidSelectionPosition()),
m_selectedSeries(0),
- m_uniformGradientTexture(0),
- m_clickedPosition(Surface3DController::invalidSelectionPosition())
+ m_clickedPosition(Surface3DController::invalidSelectionPosition()),
+ m_selectionTexturesDirty(false)
{
// Check if flat feature is supported
ShaderHelper tester(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
@@ -125,9 +122,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
initializeOpenGLFunctions();
initializeOpenGL();
-
- // Create initial uniform gradient
- generateUniformGradient(m_uniformGradientTextureColor);
}
Surface3DRenderer::~Surface3DRenderer()
@@ -139,32 +133,29 @@ Surface3DRenderer::~Surface3DRenderer()
m_textureHelper->deleteTexture(&m_depthTexture);
m_textureHelper->deleteTexture(&m_depthModelTexture);
- m_textureHelper->deleteTexture(&m_selectionTexture);
m_textureHelper->deleteTexture(&m_selectionResultTexture);
- m_textureHelper->deleteTexture(&m_uniformGradientTexture);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ GLuint texture = cache->selectionTexture();
+ m_textureHelper->deleteTexture(&texture);
+ }
}
delete m_depthShader;
delete m_backgroundShader;
delete m_selectionShader;
- delete m_surfaceShader;
+ delete m_surfaceFlatShader;
+ delete m_surfaceSmoothShader;
delete m_surfaceGridShader;
delete m_labelShader;
delete m_backgroundObj;
- delete m_surfaceObj;
- delete m_sliceSurfaceObj;
delete m_gridLineObj;
delete m_labelObj;
delete m_selectionPointer;
- for (int i = 0; i < m_dataArray.size(); i++)
- delete m_dataArray.at(i);
- m_dataArray.clear();
-
- for (int i = 0; i < m_sliceDataArray.size(); i++)
- delete m_sliceDataArray.at(i);
- m_sliceDataArray.clear();
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList)
+ delete cache;
+ m_renderCacheList.clear();
}
void Surface3DRenderer::initializeOpenGL()
@@ -200,77 +191,56 @@ void Surface3DRenderer::initializeOpenGL()
void Surface3DRenderer::updateData()
{
- // Surface only supports single series for now, so we are only interested in the first series
- const QSurfaceDataArray *array = 0;
- if (m_visibleSeriesList.size()) {
- QSurface3DSeries *firstSeries = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
- QSurfaceDataProxy *dataProxy = firstSeries->dataProxy();
- if (dataProxy)
- array = dataProxy->array();
- }
-
calculateSceneScalingFactors();
- // Need minimum of 2x2 array to draw a surface
- if (array && array->size() >= 2 && array->at(0)->size() >= 2) {
- QRect sampleSpace = calculateSampleRect(*array);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ const QSurface3DSeries *currentSeries = cache->series();
+ QSurfaceDataProxy *dataProxy = currentSeries->dataProxy();
+ const QSurfaceDataArray &array = *dataProxy->array();
- bool dimensionChanged = false;
- if (m_sampleSpace != sampleSpace) {
- dimensionChanged = true;
- m_sampleSpace = sampleSpace;
+ // Need minimum of 2x2 array to draw a surface
+ if (array.size() >= 2 && array.at(0)->size() >= 2) {
+ QRect sampleSpace = calculateSampleRect(array);
- for (int i = 0; i < m_dataArray.size(); i++)
- delete m_dataArray.at(i);
- m_dataArray.clear();
- }
+ QSurfaceDataArray &dataArray = cache->dataArray();
+ bool dimensionChanged = false;
+ if (cache->sampleSpace() != sampleSpace) {
+ if (cache->sampleSpace().width())
+ m_selectionTexturesDirty = true;
- if (sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
- if (dimensionChanged) {
- m_dataArray.reserve(sampleSpace.height());
- for (int i = 0; i < sampleSpace.height(); i++)
- m_dataArray << new QSurfaceDataRow(sampleSpace.width());
- }
- for (int i = 0; i < sampleSpace.height(); i++) {
- for (int j = 0; j < sampleSpace.width(); j++)
- (*(m_dataArray.at(i)))[j] = array->at(i + sampleSpace.y())->at(
- j + sampleSpace.x());
- }
+ dimensionChanged = true;
+ cache->setSampleSpace(sampleSpace);
- if (m_dataArray.size() > 0) {
- if (!m_surfaceObj)
- loadSurfaceObj();
+ for (int i = 0; i < dataArray.size(); i++)
+ delete dataArray.at(i);
+ dataArray.clear();
+ }
- // Note: Data setup can change sample space (as min width/height is 1)
- if (!m_cachedFlatShading) {
- m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer,
- m_axisCacheY.min(), dimensionChanged);
- } else {
- m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer,
- m_axisCacheY.min(), dimensionChanged);
+ if (sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
+ if (dimensionChanged) {
+ dataArray.reserve(sampleSpace.height());
+ for (int i = 0; i < sampleSpace.height(); i++)
+ dataArray << new QSurfaceDataRow(sampleSpace.width());
+ }
+ for (int i = 0; i < sampleSpace.height(); i++) {
+ for (int j = 0; j < sampleSpace.width(); j++) {
+ (*(dataArray.at(i)))[j] = array.at(i + sampleSpace.y())->at(
+ j + sampleSpace.x());
+ }
}
- if (dimensionChanged)
- updateSelectionTexture();
+ if (dataArray.size() > 0 && (cache->objectDirty() || dimensionChanged)) {
+ checkFlatSupport(cache);
+ updateObjects(cache, dimensionChanged);
+ cache->setObjectDirty(false);
+ cache->setFlatStatusDirty(false);
+ }
}
}
- } else {
- for (int i = 0; i < m_dataArray.size(); i++)
- delete m_dataArray.at(i);
- m_dataArray.clear();
- m_sampleSpace = QRect();
-
- delete m_surfaceObj;
- m_surfaceObj = 0;
-#if !defined(QT_OPENGL_ES_2)
- m_textureHelper->fillDepthTexture(m_depthTexture, m_primarySubViewport.size(),
- m_shadowQualityMultiplier, 1.0f);
-#endif
}
- for (int i = 0; i < m_sliceDataArray.size(); i++)
- delete m_sliceDataArray.at(i);
- m_sliceDataArray.clear();
+ if (m_selectionTexturesDirty && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone)
+ updateSelectionTextures();
updateSelectedPoint(m_selectedPoint, m_selectedSeries);
}
@@ -278,35 +248,69 @@ void Surface3DRenderer::updateData()
void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList,
bool updateVisibility)
{
- Abstract3DRenderer::updateSeries(seriesList, updateVisibility);
+ Q_UNUSED(updateVisibility);
- if (m_visibleSeriesList.size()) {
- QSurface3DSeries *series = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
- updateFlatStatus(series->isFlatShadingEnabled());
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList)
+ cache->setValid(false);
- QSurface3DSeries::DrawFlags drawMode = series->drawMode();
- m_cachedSurfaceVisible = drawMode.testFlag(QSurface3DSeries::DrawSurface);
-#if !defined(QT_OPENGL_ES_2)
- if (!m_cachedSurfaceVisible) {
- m_textureHelper->fillDepthTexture(m_depthTexture, m_primarySubViewport.size(),
- m_shadowQualityMultiplier, 1.0f);
+ foreach (QAbstract3DSeries *series, seriesList) {
+ // Item selection label may need update
+ if (series->d_ptr->m_changeTracker.nameChanged
+ || series->d_ptr->m_changeTracker.itemLabelFormatChanged) {
+ m_selectionLabelDirty = true;
}
-#endif
- m_cachedSurfaceGridOn = drawMode.testFlag(QSurface3DSeries::DrawWireframe);
- QVector3D seriesColor = Utils::vectorFromColor(series->baseColor());
- if (m_uniformGradientTextureColor != seriesColor)
- generateUniformGradient(seriesColor);
- if (m_selectionPointer) {
+ QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
+ SurfaceSeriesRenderCache *cache = m_renderCacheList.value(surfaceSeries);
+ if (!cache) {
+ cache = new SurfaceSeriesRenderCache;
+ m_renderCacheList[surfaceSeries] = cache;
+
+ m_selectionTexturesDirty = true;
+ }
+ cache->setValid(true);
+ cache->populate(surfaceSeries, this);
+ if (cache->isFlatStatusDirty() && cache->sampleSpace().width()) {
+ checkFlatSupport(cache);
+ updateObjects(cache, true);
+ cache->setFlatStatusDirty(false);
+ }
+ }
+
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (!cache->isValid()) {
+ if (cache->series() == m_selectedSeries)
+ updateSelectedPoint(Surface3DController::invalidSelectionPosition(), 0);
+
+ m_renderCacheList.remove(cache->series());
+ delete cache;
+
+ m_selectionTexturesDirty = true;
+ }
+ }
+
+ if (m_selectionPointer && m_selectedSeries) {
+ SurfaceSeriesRenderCache *cache =
+ m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ if (cache) {
m_selectionPointer->setHighlightColor(
- Utils::vectorFromColor(series->singleHighlightColor()));
+ Utils::vectorFromColor(m_selectedSeries->singleHighlightColor()));
// Make sure selection pointer object reference is still good
- m_selectionPointer->setPointerObject(m_visibleSeriesList.at(0).object());
- m_selectionPointer->setRotation(m_visibleSeriesList.at(0).meshRotation());
+ m_selectionPointer->setPointerObject(cache->object());
+ m_selectionPointer->setRotation(cache->meshRotation());
}
}
}
+void Surface3DRenderer::modifiedSeriesList(const QVector<QSurface3DSeries *> &seriesList)
+{
+ foreach (QSurface3DSeries *series, seriesList) {
+ SurfaceSeriesRenderCache *cache = m_renderCacheList.value(series);
+ if (cache)
+ cache->setObjectDirty(true);
+ }
+}
+
void Surface3DRenderer::updateRows(const QVector<int> &rows)
{
// Surface only supports single series for now, so we are only interested in the first series
@@ -392,52 +396,53 @@ void Surface3DRenderer::updateSliceDataModel(const QPoint &point)
int column = point.y();
int row = point.x();
- for (int i = 0; i < m_sliceDataArray.size(); i++)
- delete m_sliceDataArray.at(i);
- m_sliceDataArray.clear();
-
- m_sliceDataArray.reserve(2);
- QSurfaceDataRow *sliceRow;
-
- float adjust = (0.025f * m_heightNormalizer) / 2.0f;
- float stepDown = 2.0f * adjust;
- if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) {
- QSurfaceDataRow *src = m_dataArray.at(row);
- sliceRow = new QSurfaceDataRow(src->size());
- for (int i = 0; i < sliceRow->size(); i++)
- (*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, -1.0f));
- } else {
- sliceRow = new QSurfaceDataRow(m_sampleSpace.height());
- for (int i = 0; i < m_sampleSpace.height(); i++) {
- (*sliceRow)[i].setPosition(QVector3D(m_dataArray.at(i)->at(column).z(),
- m_dataArray.at(i)->at(column).y() + adjust,
- -1.0f));
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ QSurfaceDataArray &sliceDataArray = cache->sliceDataArray();
+ for (int i = 0; i < sliceDataArray.size(); i++)
+ delete sliceDataArray.at(i);
+ sliceDataArray.clear();
+ sliceDataArray.reserve(2);
+
+ QSurfaceDataRow *sliceRow;
+ QSurfaceDataArray &dataArray = cache->dataArray();
+ float adjust = (0.025f * m_heightNormalizer) / 2.0f;
+ float stepDown = 2.0f * adjust;
+ if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) {
+ QSurfaceDataRow *src = dataArray.at(row);
+ sliceRow = new QSurfaceDataRow(src->size());
+ for (int i = 0; i < sliceRow->size(); i++)
+ (*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, -1.0f));
+ } else {
+ QRect sampleSpace = cache->sampleSpace();
+ sliceRow = new QSurfaceDataRow(sampleSpace.height());
+ for (int i = 0; i < sampleSpace.height(); i++) {
+ (*sliceRow)[i].setPosition(QVector3D(dataArray.at(i)->at(column).z(),
+ dataArray.at(i)->at(column).y() + adjust,
+ -1.0f));
+ }
}
- }
- m_sliceDataArray << sliceRow;
+ sliceDataArray << sliceRow;
- // Make a duplicate, so that we get a little bit depth
- QSurfaceDataRow *duplicateRow = new QSurfaceDataRow(*sliceRow);
- for (int i = 0; i < sliceRow->size(); i++) {
- (*sliceRow)[i].setPosition(QVector3D(sliceRow->at(i).x(), sliceRow->at(i).y() - stepDown,
- 1.0f));
- }
-
- m_sliceDataArray << duplicateRow;
+ // Make a duplicate, so that we get a little bit depth
+ QSurfaceDataRow *duplicateRow = new QSurfaceDataRow(*sliceRow);
+ for (int i = 0; i < sliceRow->size(); i++) {
+ (*sliceRow)[i].setPosition(QVector3D(sliceRow->at(i).x(), sliceRow->at(i).y() - stepDown,
+ 1.0f));
+ }
- QRect sliceRect(0, 0, sliceRow->size(), 2);
+ sliceDataArray << duplicateRow;
- if (sliceRow->size() > 0) {
- if (!m_sliceSurfaceObj)
- loadSliceSurfaceObj();
+ QRect sliceRect(0, 0, sliceRow->size(), 2);
- if (!m_cachedFlatShading) {
- m_sliceSurfaceObj->setUpSmoothData(m_sliceDataArray, sliceRect, m_heightNormalizer,
- m_axisCacheY.min(), true);
- } else {
- m_sliceSurfaceObj->setUpData(m_sliceDataArray, sliceRect, m_heightNormalizer,
- m_axisCacheY.min(), true);
+ if (sliceRow->size() > 0) {
+ if (cache->isFlatShadingEnabled()) {
+ cache->sliceSurfaceObject()->setUpData(sliceDataArray, sliceRect, m_heightNormalizer,
+ m_axisCacheY.min(), true);
+ } else {
+ cache->sliceSurfaceObject()->setUpSmoothData(sliceDataArray, sliceRect, m_heightNormalizer,
+ m_axisCacheY.min(), true);
+ }
}
}
}
@@ -612,13 +617,11 @@ void Surface3DRenderer::drawSlicedScene()
offset = -m_surfaceOffsetZ;
}
- if (m_surfaceObj) {
+ if (m_renderCacheList.size()) {
QMatrix4x4 MVPMatrix;
QMatrix4x4 modelMatrix;
QMatrix4x4 itModelMatrix;
- const SeriesRenderCache &series = m_visibleSeriesList.at(0);
-
modelMatrix.translate(offset, 0.0f, 0.0f);
QVector3D scaling(scaleX, 1.0f, sliceZScale);
modelMatrix.scale(scaling);
@@ -626,41 +629,49 @@ void Surface3DRenderer::drawSlicedScene()
MVPMatrix = projectionViewMatrix * modelMatrix;
- if (m_cachedSurfaceVisible) {
- if (m_cachedSurfaceGridOn) {
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(0.5f, 1.0f);
- }
+ bool drawGrid = false;
+
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->surfaceVisible()) {
+ if (cache->surfaceGridVisible()) {
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(0.5f, 1.0f);
+ drawGrid = true;
+ }
- ShaderHelper *surfaceShader = m_surfaceShader;
- surfaceShader->bind();
-
- GLuint baseGradientTexture = m_uniformGradientTexture;
- if (series.colorStyle() != Q3DTheme::ColorStyleUniform)
- baseGradientTexture = series.baseGradientTexture();
-
- // Set shader bindings
- surfaceShader->setUniformValue(surfaceShader->lightP(), lightPos);
- surfaceShader->setUniformValue(surfaceShader->view(), viewMatrix);
- surfaceShader->setUniformValue(surfaceShader->model(), modelMatrix);
- surfaceShader->setUniformValue(surfaceShader->nModel(),
- itModelMatrix.inverted().transposed());
- surfaceShader->setUniformValue(surfaceShader->MVP(), MVPMatrix);
- surfaceShader->setUniformValue(surfaceShader->lightS(), 0.15f);
- surfaceShader->setUniformValue(surfaceShader->ambientS(),
- m_cachedTheme->ambientLightStrength() * 2.3f);
- surfaceShader->setUniformValue(surfaceShader->lightColor(), lightColor);
-
- m_drawer->drawObject(surfaceShader, m_sliceSurfaceObj, baseGradientTexture);
+ ShaderHelper *surfaceShader = m_surfaceFlatShader;
+ surfaceShader->bind();
+
+ GLuint colorTexture = cache->baseUniformTexture();;
+ if (cache->colorStyle() != Q3DTheme::ColorStyleUniform)
+ colorTexture = cache->baseGradientTexture();
+
+ // Set shader bindings
+ surfaceShader->setUniformValue(surfaceShader->lightP(), lightPos);
+ surfaceShader->setUniformValue(surfaceShader->view(), viewMatrix);
+ surfaceShader->setUniformValue(surfaceShader->model(), modelMatrix);
+ surfaceShader->setUniformValue(surfaceShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ surfaceShader->setUniformValue(surfaceShader->MVP(), MVPMatrix);
+ surfaceShader->setUniformValue(surfaceShader->lightS(), 0.15f);
+ surfaceShader->setUniformValue(surfaceShader->ambientS(),
+ m_cachedTheme->ambientLightStrength() * 2.3f);
+ surfaceShader->setUniformValue(surfaceShader->lightColor(), lightColor);
+
+ m_drawer->drawObject(surfaceShader, cache->sliceSurfaceObject(), colorTexture);
+ }
}
// Draw surface grid
- if (m_cachedSurfaceGridOn) {
+ if (drawGrid) {
m_surfaceGridShader->bind();
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(),
Utils::vectorFromColor(m_cachedTheme->gridLineColor()));
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix);
- m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_sliceSurfaceObj);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->surfaceGridVisible())
+ m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->sliceSurfaceObject());
+ }
glDisable(GL_POLYGON_OFFSET_FILL);
}
@@ -849,8 +860,6 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_primarySubViewport.width(),
m_primarySubViewport.height());
- // Specify viewport
-
// Set up projection matrix
QMatrix4x4 projectionMatrix;
projectionMatrix.perspective(45.0f, (GLfloat)m_primarySubViewport.width()
@@ -893,8 +902,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Draw depth buffer
#if !defined(QT_OPENGL_ES_2)
GLfloat adjustedLightStrength = m_cachedTheme->lightStrength() / 10.0f;
- if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone && m_surfaceObj
- && m_cachedSurfaceVisible) {
+ if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone && m_renderCacheList.size()) {
// Render scene into a depth texture for using with shadow mapping
// Enable drawing to depth framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer);
@@ -943,18 +951,23 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(m_depthShader->posAtt());
- glBindBuffer(GL_ARRAY_BUFFER, m_surfaceObj->vertexBuf());
- glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
- (void *)0);
-
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_surfaceObj->elementBuf());
-
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), m_surfaceObj->indicesType(),
- (void *)0);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->surfaceVisible() && cache->isSeriesVisible()) {
+ SurfaceObject *object = cache->surfaceObject();
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(m_depthShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, object->vertexBuf());
+ glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
+ (void *)0);
+
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object->elementBuf());
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, object->indexCount(),
+ object->indicesType(), (void *)0);
+ }
+ }
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
@@ -963,9 +976,23 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_depthModelTexture, 0);
glClear(GL_DEPTH_BUFFER_BIT);
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), m_surfaceObj->indicesType(),
- (void *)0);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->surfaceVisible() && cache->isSeriesVisible()) {
+ SurfaceObject *object = cache->surfaceObject();
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(m_depthShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, object->vertexBuf());
+ glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
+ (void *)0);
+
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object->elementBuf());
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, object->indexCount(),
+ object->indicesType(), (void *)0);
+ }
+ }
// Free buffers
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@@ -991,10 +1018,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glEnable(GL_TEXTURE_2D);
// Draw selection buffer
- if (!m_cachedIsSlicingActivated && m_surfaceObj && m_selectionState == SelectOnScene
- && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone
- && (m_cachedSurfaceVisible || m_cachedSurfaceGridOn)
- && m_visibleSeriesList.size() > 0) {
+ if (!m_cachedIsSlicingActivated && m_renderCacheList.size() && m_selectionState == SelectOnScene
+ && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone) {
m_selectionShader->bind();
glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer);
glViewport(0,
@@ -1019,7 +1044,12 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
- m_drawer->drawObject(m_selectionShader, m_surfaceObj, m_selectionTexture);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->surfaceVisible() && cache->isSeriesVisible()) {
+ m_drawer->drawObject(m_selectionShader, cache->surfaceObject(),
+ cache->selectionTexture());
+ }
+ }
glEnable(GL_DITHER);
@@ -1037,7 +1067,6 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
#endif
m_clickedPosition = selectionIdToSurfacePoint(selectionId);
- m_clickedSeries = m_visibleSeriesList.at(0).series();
emit needRender();
@@ -1049,14 +1078,9 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
// Draw the surface
- if (m_surfaceObj && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
- m_surfaceShader->bind();
+ if (m_renderCacheList.size()) {
// For surface we can see climpses from underneath
glDisable(GL_CULL_FACE);
- if (m_cachedSurfaceGridOn) {
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(0.5f, 1.0f);
- }
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
@@ -1071,57 +1095,77 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
#else
MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
+ bool drawGrid = false;
+
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ QRect sampleSpace = cache->sampleSpace();
+ if (cache->isSeriesVisible() && sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
+ if (cache->surfaceGridVisible()) {
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(0.5f, 1.0f);
+ drawGrid = true;
+ }
- if (m_cachedSurfaceVisible) {
- // Set shader bindings
- m_surfaceShader->setUniformValue(m_surfaceShader->lightP(), lightPos);
- m_surfaceShader->setUniformValue(m_surfaceShader->view(), viewMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->model(), modelMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->nModel(),
- itModelMatrix.inverted().transposed());
- m_surfaceShader->setUniformValue(m_surfaceShader->MVP(), MVPMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->ambientS(),
- m_cachedTheme->ambientLightStrength());
- m_surfaceShader->setUniformValue(m_surfaceShader->lightColor(), lightColor);
-
- GLuint gradientTexture;
- if (m_visibleSeriesList.at(0).colorStyle() == Q3DTheme::ColorStyleUniform)
- gradientTexture = m_uniformGradientTexture;
- else
- gradientTexture = m_visibleSeriesList.at(0).baseGradientTexture();
-
-#if !defined(QT_OPENGL_ES_2)
- if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
- // Set shadow shader bindings
- QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
- m_surfaceShader->setUniformValue(m_surfaceShader->shadowQ(),
- m_shadowQualityToShader);
- m_surfaceShader->setUniformValue(m_surfaceShader->depth(), depthMVPMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->lightS(), adjustedLightStrength);
-
- // Draw the object
- m_drawer->drawObject(m_surfaceShader, m_surfaceObj, gradientTexture,
- m_depthModelTexture);
- } else
-#endif
- {
- // Set shadowless shader bindings
- m_surfaceShader->setUniformValue(m_surfaceShader->lightS(),
- m_cachedTheme->lightStrength());
-
- // Draw the object
- m_drawer->drawObject(m_surfaceShader, m_surfaceObj, gradientTexture);
+ if (cache->surfaceVisible()) {
+ ShaderHelper *shader = m_surfaceFlatShader;
+ if (!cache->isFlatShadingEnabled())
+ shader = m_surfaceSmoothShader;
+ shader->bind();
+
+ // Set shader bindings
+ shader->setUniformValue(shader->lightP(), lightPos);
+ shader->setUniformValue(shader->view(), viewMatrix);
+ shader->setUniformValue(shader->model(), modelMatrix);
+ shader->setUniformValue(shader->nModel(),
+ itModelMatrix.inverted().transposed());
+ shader->setUniformValue(shader->MVP(), MVPMatrix);
+ shader->setUniformValue(shader->ambientS(),
+ m_cachedTheme->ambientLightStrength());
+ shader->setUniformValue(shader->lightColor(), lightColor);
+
+ GLuint gradientTexture;
+ if (cache->colorStyle() == Q3DTheme::ColorStyleUniform)
+ gradientTexture = cache->baseUniformTexture();
+ else
+ gradientTexture = cache->baseGradientTexture();
+
+ #if !defined(QT_OPENGL_ES_2)
+ if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
+ // Set shadow shader bindings
+ QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ shader->setUniformValue(shader->shadowQ(), m_shadowQualityToShader);
+ shader->setUniformValue(shader->depth(), depthMVPMatrix);
+ shader->setUniformValue(shader->lightS(), adjustedLightStrength);
+
+ // Draw the objects
+ m_drawer->drawObject(shader, cache->surfaceObject(), gradientTexture, m_depthModelTexture);
+ } else
+ #endif
+ {
+ // Set shadowless shader bindings
+ shader->setUniformValue(shader->lightS(),
+ m_cachedTheme->lightStrength());
+
+ // Draw the objects
+ m_drawer->drawObject(shader, cache->surfaceObject(), gradientTexture);
+ }
+ }
}
- glEnable(GL_CULL_FACE);
}
+ glEnable(GL_CULL_FACE);
// Draw surface grid
- if (m_cachedSurfaceGridOn) {
+ if (drawGrid) {
m_surfaceGridShader->bind();
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(),
Utils::vectorFromColor(m_cachedTheme->gridLineColor()));
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix);
- m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_surfaceObj);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ QRect sampleSpace = cache->sampleSpace();
+ if (cache->surfaceGridVisible() && cache->isSeriesVisible() &&
+ sampleSpace.width() >= 2 && sampleSpace.height() >= 2)
+ m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->surfaceObject());
+ }
glDisable(GL_POLYGON_OFFSET_FILL);
}
@@ -1699,12 +1743,17 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Selection handling
if (m_selectionDirty || m_selectionLabelDirty) {
QPoint visiblePoint = Surface3DController::invalidSelectionPosition();
- if (m_selectedPoint != Surface3DController::invalidSelectionPosition()) {
- int x = m_selectedPoint.x() - m_sampleSpace.y();
- int y = m_selectedPoint.y() - m_sampleSpace.x();
- if (x >= 0 && y >= 0 && x < m_sampleSpace.height() && y < m_sampleSpace.width()
- && m_dataArray.size()) {
- visiblePoint = QPoint(x, y);
+ if (m_selectedSeries) {
+ SurfaceSeriesRenderCache *cache =
+ m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ if (cache && m_selectedPoint != Surface3DController::invalidSelectionPosition()) {
+ QRect sampleSpace = cache->sampleSpace();
+ int x = m_selectedPoint.x() - sampleSpace.y();
+ int y = m_selectedPoint.y() - sampleSpace.x();
+ if (x >= 0 && y >= 0 && x < sampleSpace.height() && y < sampleSpace.width()
+ && cache->dataArray().size()) {
+ visiblePoint = QPoint(x, y);
+ }
}
}
@@ -1723,47 +1772,64 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
}
-// This one needs to be called when the data size changes
-void Surface3DRenderer::updateSelectionTexture()
+void Surface3DRenderer::updateSelectionMode(QAbstract3DGraph::SelectionFlags mode)
+{
+ Abstract3DRenderer::updateSelectionMode(mode);
+
+ if (m_cachedSelectionMode > QAbstract3DGraph::SelectionNone)
+ updateSelectionTextures();
+}
+
+void Surface3DRenderer::updateSelectionTextures()
+{
+ uint lastSelectionId = 1;
+
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ GLuint texture = cache->selectionTexture();
+ m_textureHelper->deleteTexture(&texture);
+ createSelectionTexture(cache, lastSelectionId);
+ }
+ m_selectionTexturesDirty = false;
+}
+
+void Surface3DRenderer::createSelectionTexture(SurfaceSeriesRenderCache *cache, uint &lastSelectionId)
{
// 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
- int idImageWidth = (m_sampleSpace.width() - 1) * 4;
- int idImageHeight = (m_sampleSpace.height() - 1) * 4;
+ QRect sampleSpace = cache->sampleSpace();
+ int idImageWidth = (sampleSpace.width() - 1) * 4;
+ int idImageHeight = (sampleSpace.height() - 1) * 4;
int stride = idImageWidth * 4 * sizeof(uchar); // 4 = number of color components (rgba)
+ uint idStart = lastSelectionId;
uchar *bits = new uchar[idImageWidth * idImageHeight * 4 * sizeof(uchar)];
- uint id = 1;
for (int i = 0; i < idImageHeight; i += 4) {
for (int j = 0; j < idImageWidth; j += 4) {
int p = (i * idImageWidth + j) * 4;
uchar r, g, b, a;
- idToRGBA(id, &r, &g, &b, &a);
+ idToRGBA(lastSelectionId, &r, &g, &b, &a);
fillIdCorner(&bits[p], r, g, b, a, stride);
- idToRGBA(id + 1, &r, &g, &b, &a);
+ idToRGBA(lastSelectionId + 1, &r, &g, &b, &a);
fillIdCorner(&bits[p + 8], r, g, b, a, stride);
- idToRGBA(id + m_sampleSpace.width(), &r, &g, &b, &a);
+ idToRGBA(lastSelectionId + sampleSpace.width(), &r, &g, &b, &a);
fillIdCorner(&bits[p + 2 * stride], r, g, b, a, stride);
- idToRGBA(id + m_sampleSpace.width() + 1, &r, &g, &b, &a);
+ idToRGBA(lastSelectionId + sampleSpace.width() + 1, &r, &g, &b, &a);
fillIdCorner(&bits[p + 2 * stride + 8], r, g, b, a, stride);
- id++;
+ lastSelectionId++;
}
- id++;
- }
-
- // If old texture exists, delete it
- if (m_selectionTexture) {
- m_textureHelper->deleteTexture(&m_selectionTexture);
- m_selectionTexture = 0;
+ lastSelectionId++;
}
+ lastSelectionId += sampleSpace.width();
+ cache->setSelectionIdRange(idStart, lastSelectionId - 1);
// Move the ID image (bits) to the texture
QImage image = QImage(bits, idImageWidth, idImageHeight, QImage::Format_RGB32);
- m_selectionTexture = m_textureHelper->create2DTexture(image, false, false, false);
+ GLuint selectionTexture = m_textureHelper->create2DTexture(image, false, false, false);
+ cache->setSelectionTexture(selectionTexture);
// Release the temp bits allocation
delete[] bits;
@@ -1823,33 +1889,29 @@ void Surface3DRenderer::calculateSceneScalingFactors()
m_scaleZWithBackground = m_scaleZ * backgroundMargin;
}
-bool Surface3DRenderer::updateFlatStatus(bool enable)
+void Surface3DRenderer::checkFlatSupport(SurfaceSeriesRenderCache *cache)
{
- if (enable && !m_flatSupported) {
+ bool flatEnable = cache->isFlatShadingEnabled();
+ if (flatEnable && !m_flatSupported) {
qWarning() << "Warning: Flat qualifier not supported on your platform's GLSL language."
" Requires at least GLSL version 1.2 with GL_EXT_gpu_shader4 extension.";
- enable = false;
+ cache->setFlatShadingEnabled(false);
+ cache->setFlatChangeAllowed(false);
}
+}
- bool changed = false;
- if (enable != m_cachedFlatShading) {
- m_cachedFlatShading = enable;
- changed = true;
- initSurfaceShaders();
- }
+void Surface3DRenderer::updateObjects(SurfaceSeriesRenderCache *cache, bool dimensionChanged)
+{
+ QSurfaceDataArray &dataArray = cache->dataArray();
+ const QRect sampleSpace = cache->sampleSpace();
- // If no surface object created yet, don't try to update the object
- if (m_surfaceObj && changed && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
- if (!m_cachedFlatShading) {
- m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer,
- m_axisCacheY.min(), true);
- } else {
- m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer,
- m_axisCacheY.min(), true);
- }
+ if (cache->isFlatShadingEnabled()) {
+ cache->surfaceObject()->setUpData(dataArray, sampleSpace, m_heightNormalizer,
+ m_axisCacheY.min(), dimensionChanged);
+ } else {
+ cache->surfaceObject()->setUpSmoothData(dataArray, sampleSpace, m_heightNormalizer,
+ m_axisCacheY.min(), dimensionChanged);
}
-
- return m_cachedFlatShading;
}
void Surface3DRenderer::updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series)
@@ -1865,11 +1927,6 @@ void Surface3DRenderer::resetClickedStatus()
m_clickedSeries = 0;
}
-void Surface3DRenderer::updateSurfaceGridStatus(bool enable)
-{
- m_cachedSurfaceGridOn = enable;
-}
-
void Surface3DRenderer::loadBackgroundMesh()
{
if (m_backgroundObj)
@@ -1878,20 +1935,6 @@ void Surface3DRenderer::loadBackgroundMesh()
m_backgroundObj->load();
}
-void Surface3DRenderer::loadSurfaceObj()
-{
- if (m_surfaceObj)
- delete m_surfaceObj;
- m_surfaceObj = new SurfaceObject();
-}
-
-void Surface3DRenderer::loadSliceSurfaceObj()
-{
- if (m_sliceSurfaceObj)
- delete m_sliceSurfaceObj;
- m_sliceSurfaceObj = new SurfaceObject();
-}
-
void Surface3DRenderer::loadGridLineMesh()
{
if (m_gridLineObj)
@@ -1905,7 +1948,9 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point)
int row = point.x();
int column = point.y();
- float value = m_dataArray.at(row)->at(column).y();
+ SurfaceSeriesRenderCache *cache = m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ QSurfaceDataArray &dataArray = cache->dataArray();
+ float value = dataArray.at(row)->at(column).y();
if (!m_selectionPointer)
m_selectionPointer = new SelectionPointer(m_drawer);
@@ -1913,20 +1958,20 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point)
QVector3D pos;
if (m_cachedIsSlicingActivated) {
if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) {
- pos = m_sliceSurfaceObj->vertexAt(column, 0);
+ pos = cache->sliceSurfaceObject()->vertexAt(column, 0);
pos *= QVector3D(m_surfaceScaleX, 1.0f, 0.0f);
pos += QVector3D(m_surfaceOffsetX, 0.0f, 0.0f);
m_selectionPointer->updateBoundingRect(m_secondarySubViewport);
m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
} else if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn)) {
- pos = m_sliceSurfaceObj->vertexAt(row, 0);
+ pos = cache->sliceSurfaceObject()->vertexAt(row, 0);
pos *= QVector3D(m_surfaceScaleZ, 1.0f, 0.0f);
pos += QVector3D(-m_surfaceOffsetZ, 0.0f, 0.0f);
m_selectionPointer->updateBoundingRect(m_secondarySubViewport);
m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
}
} else {
- pos = m_surfaceObj->vertexAt(column, row);
+ pos = cache->surfaceObject()->vertexAt(column, row);
pos *= QVector3D(m_surfaceScaleX, 1.0f, m_surfaceScaleZ);;
pos += QVector3D(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ);
m_selectionPointer->updateBoundingRect(m_primarySubViewport);
@@ -1935,23 +1980,42 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point)
m_selectionPointer->setPosition(pos);
m_selectionPointer->setLabel(createSelectionLabel(value, column, row));
- m_selectionPointer->setPointerObject(m_visibleSeriesList.at(0).object());
- m_selectionPointer->setHighlightColor(m_visibleSeriesList.at(0).singleHighlightColor());
+ m_selectionPointer->setPointerObject(cache->object());
+ m_selectionPointer->setHighlightColor(cache->singleHighlightColor());
m_selectionPointer->updateScene(m_cachedScene);
- m_selectionPointer->setRotation(m_visibleSeriesList.at(0).meshRotation());
+ m_selectionPointer->setRotation(cache->meshRotation());
}
// Maps selection Id to surface point in data array
QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id)
{
- int column = ((id - 1) % m_sampleSpace.width()) + m_sampleSpace.x();
- int row = ((id - 1) / m_sampleSpace.width()) + m_sampleSpace.y();
+ SurfaceSeriesRenderCache *selectedCache = 0;
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->isWithinIdRange(id)) {
+ selectedCache = cache;
+ break;
+ }
+ }
+ if (!selectedCache) {
+ m_clickedSeries = 0;
+ return Surface3DController::invalidSelectionPosition();
+ }
+
+ uint idInSeries = id - selectedCache->selectionIdStart() + 1;
+ QRect sampleSpace = selectedCache->sampleSpace();
+ int column = ((idInSeries - 1) % sampleSpace.width()) + sampleSpace.x();
+ int row = ((idInSeries - 1) / sampleSpace.width()) + sampleSpace.y();
+
+ m_clickedSeries = selectedCache->series();
return QPoint(row, column);
}
QString Surface3DRenderer::createSelectionLabel(float value, int column, int row)
{
- QString labelText = m_visibleSeriesList[0].itemLabelFormat();
+ SurfaceSeriesRenderCache *cache =
+ m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ QSurfaceDataArray &dataArray = cache->dataArray();
+ QString labelText = cache->itemLabelFormat();
static const QString xTitleTag(QStringLiteral("@xTitle"));
static const QString yTitleTag(QStringLiteral("@yTitle"));
static const QString zTitleTag(QStringLiteral("@zTitle"));
@@ -1969,7 +2033,7 @@ QString Surface3DRenderer::createSelectionLabel(float value, int column, int row
if (labelFormat.isEmpty())
labelFormat = Utils::defaultLabelFormat();
QString valueLabelText = generateValueLabel(labelFormat,
- m_dataArray.at(row)->at(column).x());
+ dataArray.at(row)->at(column).x());
labelText.replace(xLabelTag, valueLabelText);
}
if (labelText.contains(yLabelTag)) {
@@ -1984,11 +2048,11 @@ QString Surface3DRenderer::createSelectionLabel(float value, int column, int row
if (labelFormat.isEmpty())
labelFormat = Utils::defaultLabelFormat();
QString valueLabelText = generateValueLabel(labelFormat,
- m_dataArray.at(row)->at(column).z());
+ dataArray.at(row)->at(column).z());
labelText.replace(zLabelTag, valueLabelText);
}
- labelText.replace(seriesNameTag, m_visibleSeriesList[0].name());
+ labelText.replace(seriesNameTag, cache->name());
m_selectionLabelDirty = false;
@@ -2073,31 +2137,34 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &
Q_UNUSED(fragmentShader);
// draw the shader for the surface according to smooth status, shadow and uniform color
- if (m_surfaceShader)
- delete m_surfaceShader;
+ if (m_surfaceFlatShader)
+ delete m_surfaceFlatShader;
+ if (m_surfaceSmoothShader)
+ delete m_surfaceSmoothShader;
+
#if !defined(QT_OPENGL_ES_2)
- if (!m_cachedFlatShading) {
- if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentSurfaceShadowNoTex"));
- } else {
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragmentSurface"));
- }
+ if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
+ m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentSurfaceShadowNoTex"));
} else {
- if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceShadowFlat"),
+ m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentSurface"));
+ }
+ if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
+ m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceShadowFlat"),
QStringLiteral(":/shaders/fragmentSurfaceShadowFlat"));
- } else {
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
+ } else {
+ m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
QStringLiteral(":/shaders/fragmentSurfaceFlat"));
- }
}
#else
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragmentSurfaceES2"));
+ m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentSurfaceES2"));
+ m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentSurfaceES2"));
#endif
- m_surfaceShader->initialize();
+ m_surfaceSmoothShader->initialize();
+ m_surfaceFlatShader->initialize();
}
void Surface3DRenderer::initBackgroundShaders(const QString &vertexShader,
@@ -2177,16 +2244,4 @@ void Surface3DRenderer::updateDepthBuffer()
}
#endif
-void Surface3DRenderer::generateUniformGradient(const QVector3D newColor)
-{
- if (m_visibleSeriesList.size()) {
- QColor newQColor = Utils::colorFromVector(newColor);
- m_uniformGradientTextureColor = newColor;
- QLinearGradient newGradient;
- newGradient.setColorAt(0.0, newQColor);
- newGradient.setColorAt(1.0, newQColor);
- fixGradientAndGenerateTexture(&newGradient, &m_uniformGradientTexture);
- }
-}
-
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h
index 06973f43..5f4e70ec 100644
--- a/src/datavisualization/engine/surface3drenderer_p.h
+++ b/src/datavisualization/engine/surface3drenderer_p.h
@@ -34,6 +34,7 @@
#include "abstract3drenderer_p.h"
#include "scatterrenderitem_p.h"
#include "qsurfacedataproxy.h"
+#include "surfaceseriesrendercache_p.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -60,7 +61,8 @@ private:
// Internal attributes purely related to how the scene is drawn with GL.
ShaderHelper *m_depthShader;
ShaderHelper *m_backgroundShader;
- ShaderHelper *m_surfaceShader;
+ ShaderHelper *m_surfaceFlatShader;
+ ShaderHelper *m_surfaceSmoothShader;
ShaderHelper *m_surfaceGridShader;
ShaderHelper *m_selectionShader;
ShaderHelper *m_labelShader;
@@ -84,19 +86,15 @@ private:
ObjectHelper *m_gridLineObj;
ObjectHelper *m_labelObj;
SurfaceObject *m_surfaceObj;
- SurfaceObject *m_sliceSurfaceObj;
GLuint m_depthTexture;
GLuint m_depthModelTexture;
GLuint m_depthFrameBuffer;
GLuint m_selectionFrameBuffer;
GLuint m_selectionDepthBuffer;
- GLuint m_selectionTexture;
GLuint m_selectionResultTexture;
GLfloat m_shadowQualityToShader;
bool m_cachedFlatShading;
bool m_flatSupported;
- bool m_cachedSurfaceVisible;
- bool m_cachedSurfaceGridOn;
SelectionPointer *m_selectionPointer;
bool m_selectionActive;
bool m_xFlipped;
@@ -104,7 +102,6 @@ private:
bool m_yFlipped;
AbstractRenderItem m_dummyRenderItem;
QSurfaceDataArray m_dataArray;
- QSurfaceDataArray m_sliceDataArray;
QRect m_sampleSpace;
GLint m_shadowQualityMultiplier;
QSizeF m_areaSize;
@@ -112,9 +109,10 @@ private:
bool m_hasHeightAdjustmentChanged;
QPoint m_selectedPoint;
const QSurface3DSeries *m_selectedSeries;
- GLuint m_uniformGradientTexture;
QVector3D m_uniformGradientTextureColor;
QPoint m_clickedPosition;
+ QHash<QSurface3DSeries *, SurfaceSeriesRenderCache *> m_renderCacheList;
+ bool m_selectionTexturesDirty;
public:
explicit Surface3DRenderer(Surface3DController *controller);
@@ -122,11 +120,11 @@ public:
void updateData();
void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility);
+ void updateSelectionMode(QAbstract3DGraph::SelectionFlags mode);
+ void modifiedSeriesList(const QVector<QSurface3DSeries *> &seriesList);
void updateRows(const QVector<int> &rows);
void updateItem(const QVector<QPoint> &points);
void updateScene(Q3DScene *scene);
- bool updateFlatStatus(bool enable);
- void updateSurfaceGridStatus(bool enable);
void updateSlicingActive(bool isSlicing);
void updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series);
inline QPoint clickedPosition() const { return m_clickedPosition; }
@@ -142,6 +140,8 @@ signals:
void flatShadingSupportedChanged(bool supported);
private:
+ void checkFlatSupport(SurfaceSeriesRenderCache *cache);
+ void updateObjects(SurfaceSeriesRenderCache *cache, bool dimensionChanged);
void updateSliceDataModel(const QPoint &point);
void updateShadowQuality(QAbstract3DGraph::ShadowQuality quality);
void updateTextures();
@@ -150,8 +150,6 @@ private:
void loadBackgroundMesh();
void loadGridLineMesh();
void loadLabelMesh();
- void loadSurfaceObj();
- void loadSliceSurfaceObj();
void drawScene(GLuint defaultFboHandle);
void calculateSceneScalingFactors();
void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader);
@@ -160,7 +158,8 @@ private:
void initSurfaceShaders();
void initSelectionBuffer();
void initDepthShader();
- void updateSelectionTexture();
+ void updateSelectionTextures();
+ void createSelectionTexture(SurfaceSeriesRenderCache *cache, uint &lastSelectionId);
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(const QPoint &point);
@@ -170,7 +169,6 @@ private:
void updateDepthBuffer();
#endif
void emitSelectedPointChanged(QPoint position);
- void generateUniformGradient(const QVector3D newColor);
Q_DISABLE_COPY(Surface3DRenderer)
};
diff --git a/src/datavisualization/engine/surfaceseriesrendercache.cpp b/src/datavisualization/engine/surfaceseriesrendercache.cpp
new file mode 100644
index 00000000..e6243472
--- /dev/null
+++ b/src/datavisualization/engine/surfaceseriesrendercache.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 QtDataVisualization 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 "seriesrendercache_p.h"
+#include "surfaceseriesrendercache_p.h"
+#include "objecthelper_p.h"
+#include "abstract3drenderer_p.h"
+#include "texturehelper_p.h"
+#include "utils_p.h"
+
+QT_BEGIN_NAMESPACE_DATAVISUALIZATION
+
+SurfaceSeriesRenderCache::SurfaceSeriesRenderCache()
+ : m_surfaceVisible(false),
+ m_surfaceGridVisible(false),
+ m_surfaceFlatShading(true),
+ m_surfaceObj(new SurfaceObject),
+ m_sliceSurfaceObj(new SurfaceObject),
+ m_sampleSpace(QRect(0, 0, 0 , 0)),
+ m_selectionTexture(0),
+ m_selectionIdStart(0),
+ m_selectionIdEnd(0),
+ m_flatChangeAllowed(true),
+ m_flatStatusDirty(false),
+ m_valid(false),
+ m_objectDirty(true)
+{
+}
+
+SurfaceSeriesRenderCache::~SurfaceSeriesRenderCache()
+{
+ delete m_surfaceObj;
+ delete m_sliceSurfaceObj;
+ for (int i = 0; i < m_dataArray.size(); i++)
+ delete m_dataArray.at(i);
+ m_dataArray.clear();
+
+ for (int i = 0; i < m_sliceDataArray.size(); i++)
+ delete m_sliceDataArray.at(i);
+ m_sliceDataArray.clear();
+}
+
+void SurfaceSeriesRenderCache::populate(QSurface3DSeries *series, Abstract3DRenderer *renderer)
+{
+ Q_ASSERT(series);
+
+ SeriesRenderCache::populate(series, renderer);
+
+ QSurface3DSeries::DrawFlags drawMode = series->drawMode();
+ m_surfaceVisible = drawMode.testFlag(QSurface3DSeries::DrawSurface);
+ m_surfaceGridVisible = drawMode.testFlag(QSurface3DSeries::DrawWireframe);
+ if (m_flatChangeAllowed && m_surfaceFlatShading != series->isFlatShadingEnabled()) {
+ m_surfaceFlatShading = series->isFlatShadingEnabled();
+ m_flatStatusDirty = true;
+ }
+}
+
+QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/surfaceseriesrendercache_p.h b/src/datavisualization/engine/surfaceseriesrendercache_p.h
new file mode 100644
index 00000000..a0d23e45
--- /dev/null
+++ b/src/datavisualization/engine/surfaceseriesrendercache_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 QtDataVisualization 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 QtDataVisualization 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 SURFACESERIESRENDERCACHE_P_H
+#define SURFACESERIESRENDERCACHE_P_H
+
+#include "datavisualizationglobal_p.h"
+#include "seriesrendercache_p.h"
+#include "qabstract3dseries_p.h"
+#include "qsurface3dseries_p.h"
+#include "surfaceobject_p.h"
+
+QT_BEGIN_NAMESPACE_DATAVISUALIZATION
+
+class Abstract3DRenderer;
+class ObjectHelper;
+class TextureHelper;
+
+class SurfaceSeriesRenderCache : public SeriesRenderCache
+{
+public:
+ SurfaceSeriesRenderCache();
+ virtual ~SurfaceSeriesRenderCache();
+
+ void populate(QSurface3DSeries *series, Abstract3DRenderer *renderer);
+ void cleanup(TextureHelper *texHelper);
+
+ inline bool surfaceVisible() const { return m_surfaceVisible; }
+ inline bool surfaceGridVisible() const { return m_surfaceGridVisible; }
+ inline bool isFlatShadingEnabled() const { return m_surfaceFlatShading; }
+ inline void setFlatShadingEnabled(bool enabled) { m_surfaceFlatShading = enabled; }
+ inline void setFlatChangeAllowed(bool allowed) { m_flatChangeAllowed = allowed; }
+ inline void setValid(bool valid) { m_valid = valid; }
+ inline bool isValid() const { return m_valid; }
+ inline SurfaceObject *surfaceObject() { return m_surfaceObj; }
+ inline SurfaceObject *sliceSurfaceObject() { return m_sliceSurfaceObj; }
+ inline const QRect sampleSpace() const { return m_sampleSpace; }
+ inline void setSampleSpace(const QRect &sampleSpace) { m_sampleSpace = sampleSpace; }
+ inline QSurface3DSeries *series() const { return static_cast<QSurface3DSeries *>(m_series); }
+ inline QSurfaceDataArray &dataArray() { return m_dataArray; }
+ inline QSurfaceDataArray &sliceDataArray() { return m_sliceDataArray; }
+ inline bool isSeriesVisible() const { return m_series->isVisible(); }
+ inline void setObjectDirty(bool state) { m_objectDirty = state; }
+ inline bool objectDirty() const { return m_objectDirty; }
+ inline void setSelectionTexture(GLuint texture) { m_selectionTexture = texture; }
+ inline GLuint selectionTexture() const { return m_selectionTexture; }
+ inline void setSelectionIdRange(uint start, uint end) { m_selectionIdStart = start;
+ m_selectionIdEnd = end; }
+ inline uint selectionIdStart() const { return m_selectionIdStart; }
+ inline bool isWithinIdRange(uint selection) const { return selection >= m_selectionIdStart &&
+ selection <= m_selectionIdEnd; }
+ inline bool isFlatStatusDirty() const { return m_flatStatusDirty; }
+ inline void setFlatStatusDirty(bool status) { m_flatStatusDirty = status; }
+
+protected:
+ bool m_surfaceVisible;
+ bool m_surfaceGridVisible;
+ bool m_surfaceFlatShading;
+ SurfaceObject *m_surfaceObj;
+ SurfaceObject *m_sliceSurfaceObj;
+ QRect m_sampleSpace;
+ QSurfaceDataArray m_dataArray;
+ QSurfaceDataArray m_sliceDataArray;
+ GLuint m_selectionTexture;
+ uint m_selectionIdStart;
+ uint m_selectionIdEnd;
+ bool m_flatChangeAllowed;
+ bool m_flatStatusDirty;
+
+ bool m_valid;
+ bool m_objectDirty;
+};
+
+QT_END_NAMESPACE_DATAVISUALIZATION
+
+#endif
diff --git a/src/datavisualization/global/datavisualizationglobal_p.h b/src/datavisualization/global/datavisualizationglobal_p.h
index 83af408a..2cfa559c 100644
--- a/src/datavisualization/global/datavisualizationglobal_p.h
+++ b/src/datavisualization/global/datavisualizationglobal_p.h
@@ -55,6 +55,8 @@ static const QVector3D selectionSkipColor = QVector3D(255.0f, 255.0f, 255.0f);
static const QVector3D invalidColorVector = QVector3D(-1.0f, -1.0f, -1.0f);
static const GLfloat gradientTextureHeight = 1024.0f;
static const GLfloat gradientTextureWidth = 2.0f;
+static const GLfloat uniformTextureHeight = 64.0f;
+static const GLfloat uniformTextureWidth = 2.0f;
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/utils/surfaceobject.cpp b/src/datavisualization/utils/surfaceobject.cpp
index b0cd6c82..cfaab09c 100644
--- a/src/datavisualization/utils/surfaceobject.cpp
+++ b/src/datavisualization/utils/surfaceobject.cpp
@@ -25,6 +25,10 @@
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
SurfaceObject::SurfaceObject()
+ : m_surfaceType(Undefined),
+ m_columns(0),
+ m_rows(0),
+ m_gridIndexCount(0)
{
m_indicesType = GL_UNSIGNED_INT;
initializeOpenGLFunctions();
@@ -668,6 +672,9 @@ GLuint SurfaceObject::gridIndexCount()
QVector3D SurfaceObject::vertexAt(int column, int row)
{
int pos = 0;
+ if (m_surfaceType == Undefined || !m_vertices.size())
+ return zeroVector;
+
if (m_surfaceType == SurfaceFlat)
pos = row * (m_columns * 2 - 2) + column * 2 - (column > 0);
else
diff --git a/src/datavisualization/utils/surfaceobject_p.h b/src/datavisualization/utils/surfaceobject_p.h
index ec1a30bd..f51c2909 100644
--- a/src/datavisualization/utils/surfaceobject_p.h
+++ b/src/datavisualization/utils/surfaceobject_p.h
@@ -40,6 +40,13 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class SurfaceObject : public AbstractObjectHelper
{
public:
+ enum SurfaceType {
+ SurfaceSmooth,
+ SurfaceFlat,
+ Undefined
+ };
+
+public:
SurfaceObject();
~SurfaceObject();
@@ -71,11 +78,7 @@ private:
bool changeGeometry);
private:
- enum SurfaceType {
- SurfaceSmooth,
- SurfaceFlat
- };
- int m_surfaceType;
+ SurfaceType m_surfaceType;
int m_columns;
int m_rows;
GLuint m_gridElementbuffer;
diff --git a/src/datavisualization/utils/texturehelper.cpp b/src/datavisualization/utils/texturehelper.cpp
index 91d70946..0f5c8313 100644
--- a/src/datavisualization/utils/texturehelper.cpp
+++ b/src/datavisualization/utils/texturehelper.cpp
@@ -151,6 +151,18 @@ GLuint TextureHelper::createSelectionTexture(const QSize &size, GLuint &frameBuf
return textureid;
}
+GLuint TextureHelper::createUniformTexture(const QColor &color)
+{
+ QImage image(QSize(int(uniformTextureWidth), int(uniformTextureHeight)),
+ QImage::Format_RGB32);
+ QPainter pmp(&image);
+ pmp.setBrush(QBrush(color));
+ pmp.setPen(Qt::NoPen);
+ pmp.drawRect(0, 0, int(uniformTextureWidth), int(uniformTextureHeight));
+
+ return create2DTexture(image, false, true, false, true);
+}
+
GLuint TextureHelper::createGradientTexture(const QLinearGradient &gradient)
{
QImage image(QSize(int(gradientTextureWidth), int(gradientTextureHeight)),
diff --git a/src/datavisualization/utils/texturehelper_p.h b/src/datavisualization/utils/texturehelper_p.h
index 17553f30..f9a23a08 100644
--- a/src/datavisualization/utils/texturehelper_p.h
+++ b/src/datavisualization/utils/texturehelper_p.h
@@ -48,6 +48,7 @@ class TextureHelper : protected QOpenGLFunctions
GLuint createCubeMapTexture(const QImage &image, bool useTrilinearFiltering = false);
// Returns selection texture and inserts generated framebuffers to framebuffer parameters
GLuint createSelectionTexture(const QSize &size, GLuint &frameBuffer, GLuint &depthBuffer);
+ GLuint createUniformTexture(const QColor &color);
GLuint createGradientTexture(const QLinearGradient &gradient);
#if !defined(QT_OPENGL_ES_2)
GLuint createDepthTexture(const QSize &size, GLuint textureSize);