summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/engine/surface3drenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/datavisualization/engine/surface3drenderer.cpp')
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp1543
1 files changed, 871 insertions, 672 deletions
diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp
index 41415393..12627966 100644
--- a/src/datavisualization/engine/surface3drenderer.cpp
+++ b/src/datavisualization/engine/surface3drenderer.cpp
@@ -16,22 +16,12 @@
**
****************************************************************************/
-#include "surface3dcontroller_p.h"
#include "surface3drenderer_p.h"
-#include "q3dcamera.h"
#include "q3dcamera_p.h"
#include "shaderhelper_p.h"
-#include "objecthelper_p.h"
-#include "surfaceobject_p.h"
#include "texturehelper_p.h"
-#include "selectionpointer_p.h"
#include "utils_p.h"
-#include "drawer_p.h"
-#include "q3dlight.h"
-#include "qsurface3dseries_p.h"
-#include <QtGui/QMatrix4x4>
-#include <QtGui/QMouseEvent>
#include <QtCore/qmath.h>
static const int ID_TO_RGBA_MASK = 0xff;
@@ -40,12 +30,15 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
//#define SHOW_DEPTH_TEXTURE_SCENE
-const GLfloat aspectRatio = 2.0f; // Forced ratio of x and z to y. Dynamic will make it look odd.
-const GLfloat backgroundMargin = 1.1f; // Margin for background (1.1f = make it 10% larger to avoid items being drawn inside background)
-const GLfloat labelMargin = 0.05f;
+// Margin for background (1.10 make it 10% larger to avoid
+// selection ball being drawn inside background)
+const GLfloat backgroundMargin = 1.1f;
const GLfloat gridLineWidth = 0.005f;
const GLfloat sliceZScale = 0.1f;
const GLfloat sliceUnits = 2.5f;
+const uint greenMultiplier = 256;
+const uint blueMultiplier = 65536;
+const uint alphaMultiplier = 16777216;
Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
: Abstract3DRenderer(controller),
@@ -65,15 +58,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_scaleZ(0.0f),
m_scaleXWithBackground(0.0f),
m_scaleZWithBackground(0.0f),
- m_minVisibleColumnValue(0.0f),
- m_maxVisibleColumnValue(0.0f),
- m_minVisibleRowValue(0.0f),
- m_maxVisibleRowValue(0.0f),
- m_visibleColumnRange(0.0f),
- m_visibleRowRange(0.0f),
- m_backgroundObj(0),
- m_gridLineObj(0),
- m_labelObj(0),
m_depthTexture(0),
m_depthModelTexture(0),
m_depthFrameBuffer(0),
@@ -83,9 +67,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_shadowQualityToShader(33.3f),
m_flatSupported(true),
m_selectionActive(false),
- m_xFlipped(false),
- m_zFlipped(false),
- m_yFlipped(false),
m_shadowQualityMultiplier(3),
m_hasHeightAdjustmentChanged(true),
m_selectedPoint(Surface3DController::invalidSelectionPosition()),
@@ -94,6 +75,9 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_selectionTexturesDirty(false),
m_noShadowTexture(0)
{
+ m_axisCacheY.setScale(2.0f);
+ m_axisCacheY.setTranslate(-1.0f);
+
// Check if flat feature is supported
ShaderHelper tester(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
QStringLiteral(":/shaders/fragmentSurfaceFlat"));
@@ -131,16 +115,6 @@ Surface3DRenderer::~Surface3DRenderer()
delete m_surfaceSliceFlatShader;
delete m_surfaceSliceSmoothShader;
delete m_labelShader;
-
- delete m_backgroundObj;
- delete m_gridLineObj;
- delete m_labelObj;
-
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
- cache->cleanup(m_textureHelper);
- delete cache;
- }
- m_renderCacheList.clear();
}
void Surface3DRenderer::initializeOpenGL()
@@ -160,8 +134,10 @@ void Surface3DRenderer::initializeOpenGL()
// Init selection shader
initSelectionShaders();
+#if !(defined QT_OPENGL_ES_2)
// Load grid line mesh
loadGridLineMesh();
+#endif
// Load label mesh
loadLabelMesh();
@@ -183,22 +159,25 @@ void Surface3DRenderer::updateData()
{
calculateSceneScalingFactors();
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
- const QSurface3DSeries *currentSeries = cache->series();
- QSurfaceDataProxy *dataProxy = currentSeries->dataProxy();
- const QSurfaceDataArray &array = *dataProxy->array();
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
+ if (cache->isVisible() && cache->dataDirty()) {
+ const QSurface3DSeries *currentSeries = cache->series();
+ QSurfaceDataProxy *dataProxy = currentSeries->dataProxy();
+ const QSurfaceDataArray &array = *dataProxy->array();
+ QSurfaceDataArray &dataArray = cache->dataArray();
+ QRect sampleSpace;
- // Need minimum of 2x2 array to draw a surface
- if (array.size() >= 2 && array.at(0)->size() >= 2) {
- QRect sampleSpace = calculateSampleRect(cache, array);
+ // Need minimum of 2x2 array to draw a surface
+ if (array.size() >= 2 && array.at(0)->size() >= 2)
+ sampleSpace = calculateSampleRect(array);
- QSurfaceDataArray &dataArray = cache->dataArray();
- bool dimensionChanged = false;
+ bool dimensionsChanged = false;
if (cache->sampleSpace() != sampleSpace) {
if (sampleSpace.width() >= 2)
m_selectionTexturesDirty = true;
- dimensionChanged = true;
+ dimensionsChanged = true;
cache->setSampleSpace(sampleSpace);
for (int i = 0; i < dataArray.size(); i++)
@@ -207,7 +186,7 @@ void Surface3DRenderer::updateData()
}
if (sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
- if (dimensionChanged) {
+ if (dimensionsChanged) {
dataArray.reserve(sampleSpace.height());
for (int i = 0; i < sampleSpace.height(); i++)
dataArray << new QSurfaceDataRow(sampleSpace.width());
@@ -219,13 +198,13 @@ void Surface3DRenderer::updateData()
}
}
- if (dataArray.size() > 0 && (cache->objectDirty() || dimensionChanged)) {
- checkFlatSupport(cache);
- updateObjects(cache, dimensionChanged);
- cache->setObjectDirty(false);
- cache->setFlatStatusDirty(false);
- }
+ checkFlatSupport(cache);
+ updateObjects(cache, dimensionsChanged);
+ cache->setFlatStatusDirty(false);
+ } else {
+ cache->surfaceObject()->clear();
}
+ cache->setDataDirty(false);
}
}
@@ -235,31 +214,22 @@ void Surface3DRenderer::updateData()
updateSelectedPoint(m_selectedPoint, m_selectedSeries);
}
-void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList,
- bool updateVisibility)
+void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList)
{
- Q_UNUSED(updateVisibility);
-
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList)
- cache->setValid(false);
+ Abstract3DRenderer::updateSeries(seriesList);
+ bool noSelection = true;
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;
- }
-
QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
- SurfaceSeriesRenderCache *cache = m_renderCacheList.value(surfaceSeries);
- if (!cache) {
- cache = new SurfaceSeriesRenderCache;
- m_renderCacheList[surfaceSeries] = cache;
-
- m_selectionTexturesDirty = true;
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>( m_renderCacheList.value(series));
+ if (noSelection
+ && surfaceSeries->selectedPoint() != QSurface3DSeries::invalidSelectionPosition()) {
+ if (selectionLabel() != cache->itemLabel())
+ m_selectionLabelDirty = true;
+ noSelection = false;
}
- cache->setValid(true);
- cache->populate(surfaceSeries, this);
+
if (cache->isFlatStatusDirty() && cache->sampleSpace().width()) {
checkFlatSupport(cache);
updateObjects(cache, true);
@@ -267,24 +237,16 @@ void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesLis
}
}
- // Remove non-valid objects from the cache list
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
- if (!cache->isValid()) {
- if (cache->series() == m_selectedSeries)
- updateSelectedPoint(Surface3DController::invalidSelectionPosition(), 0);
-
- m_renderCacheList.remove(cache->series());
- cache->cleanup(m_textureHelper);
- delete cache;
-
- m_selectionTexturesDirty = true;
- }
+ if (noSelection && !selectionLabel().isEmpty()) {
+ m_selectionLabelDirty = true;
+ updateSelectedPoint(Surface3DController::invalidSelectionPosition(), 0);
}
// Selection pointer issues
if (m_selectedSeries) {
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
- QVector3D highlightColor =
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
+ QVector4D highlightColor =
Utils::vectorFromColor(cache->series()->singleHighlightColor());
SelectionPointer *slicePointer = cache->sliceSelectionPointer();
if (slicePointer) {
@@ -302,19 +264,23 @@ void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesLis
}
}
-void Surface3DRenderer::modifiedSeriesList(const QVector<QSurface3DSeries *> &seriesList)
+SeriesRenderCache *Surface3DRenderer::createNewCache(QAbstract3DSeries *series)
{
- foreach (QSurface3DSeries *series, seriesList) {
- SurfaceSeriesRenderCache *cache = m_renderCacheList.value(series);
- if (cache)
- cache->setObjectDirty(true);
- }
+ m_selectionTexturesDirty = true;
+ return new SurfaceSeriesRenderCache(series, this);
+}
+
+void Surface3DRenderer::cleanCache(SeriesRenderCache *cache)
+{
+ Abstract3DRenderer::cleanCache(cache);
+ m_selectionTexturesDirty = true;
}
void Surface3DRenderer::updateRows(const QVector<Surface3DController::ChangeRow> &rows)
{
foreach (Surface3DController::ChangeRow item, rows) {
- SurfaceSeriesRenderCache *cache = m_renderCacheList.value(item.series);
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(m_renderCacheList.value(item.series));
QSurfaceDataArray &dstArray = cache->dataArray();
const QRect &sampleSpace = cache->sampleSpace();
@@ -335,15 +301,10 @@ void Surface3DRenderer::updateRows(const QVector<Surface3DController::ChangeRow>
srcArray->at(row)->at(j + sampleSpace.x());
}
- if (cache->isFlatShadingEnabled()) {
- cache->surfaceObject()->updateCoarseRow(dstArray, row - sampleSpace.y(),
- m_heightNormalizer,
- m_axisCacheY.min());
- } else {
- cache->surfaceObject()->updateSmoothRow(dstArray, row - sampleSpace.y(),
- m_heightNormalizer,
- m_axisCacheY.min());
- }
+ if (cache->isFlatShadingEnabled())
+ cache->surfaceObject()->updateCoarseRow(dstArray, row - sampleSpace.y());
+ else
+ cache->surfaceObject()->updateSmoothRow(dstArray, row - sampleSpace.y());
}
if (updateBuffers)
cache->surfaceObject()->uploadBuffers();
@@ -353,10 +314,11 @@ void Surface3DRenderer::updateRows(const QVector<Surface3DController::ChangeRow>
updateSelectedPoint(m_selectedPoint, m_selectedSeries);
}
-void Surface3DRenderer::updateItem(const QVector<Surface3DController::ChangeItem> &points)
+void Surface3DRenderer::updateItems(const QVector<Surface3DController::ChangeItem> &points)
{
foreach (Surface3DController::ChangeItem item, points) {
- SurfaceSeriesRenderCache *cache = m_renderCacheList.value(item.series);
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(m_renderCacheList.value(item.series));
QSurfaceDataArray &dstArray = cache->dataArray();
const QRect &sampleSpace = cache->sampleSpace();
@@ -370,22 +332,20 @@ void Surface3DRenderer::updateItem(const QVector<Surface3DController::ChangeItem
int sampleSpaceTop = sampleSpace.y() + sampleSpace.height();
int sampleSpaceRight = sampleSpace.x() + sampleSpace.width();
bool updateBuffers = false;
+ // Note: Point is (row, column), samplespace is (columns x rows)
QPoint point = item.point;
- if (point.y() <= sampleSpaceTop && point.y() >= sampleSpace.y() &&
- point.x() <= sampleSpaceRight && point.x() >= sampleSpace.x()) {
+ if (point.x() <= sampleSpaceTop && point.x() >= sampleSpace.y() &&
+ point.y() <= sampleSpaceRight && point.y() >= sampleSpace.x()) {
updateBuffers = true;
- int x = point.x() - sampleSpace.x();
- int y = point.y() - sampleSpace.y();
- (*(dstArray.at(y)))[x] = srcArray->at(point.y())->at(point.x());
-
- if (cache->isFlatShadingEnabled()) {
- cache->surfaceObject()->updateCoarseItem(dstArray, y, x, m_heightNormalizer,
- m_axisCacheY.min());
- } else {
- cache->surfaceObject()->updateSmoothItem(dstArray, y, x, m_heightNormalizer,
- m_axisCacheY.min());
- }
+ int x = point.y() - sampleSpace.x();
+ int y = point.x() - sampleSpace.y();
+ (*(dstArray.at(y)))[x] = srcArray->at(point.x())->at(point.y());
+
+ if (cache->isFlatShadingEnabled())
+ cache->surfaceObject()->updateCoarseItem(dstArray, y, x);
+ else
+ cache->surfaceObject()->updateSmoothItem(dstArray, y, x);
}
if (updateBuffers)
cache->surfaceObject()->uploadBuffers();
@@ -396,31 +356,22 @@ void Surface3DRenderer::updateItem(const QVector<Surface3DController::ChangeItem
updateSelectedPoint(m_selectedPoint, m_selectedSeries);
}
-void Surface3DRenderer::updateAxisRange(QAbstract3DAxis::AxisOrientation orientation, float min,
- float max)
-{
- Abstract3DRenderer::updateAxisRange(orientation, min, max);
-
- if (orientation == QAbstract3DAxis::AxisOrientationY) {
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList)
- cache->setObjectDirty(true);
- }
-}
-
void Surface3DRenderer::updateSliceDataModel(const QPoint &point)
{
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList)
- cache->sliceSurfaceObject()->clear();
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList)
+ static_cast<SurfaceSeriesRenderCache *>(baseCache)->sliceSurfaceObject()->clear();
if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries)) {
// Find axis coordinates for the selected point
- SurfaceSeriesRenderCache *selectedCache =
- m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
- QSurfaceDataArray &dataArray = selectedCache->dataArray();
+ SeriesRenderCache *selectedCache =
+ m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ QSurfaceDataArray &dataArray =
+ static_cast<SurfaceSeriesRenderCache *>(selectedCache)->dataArray();
QSurfaceDataItem item = dataArray.at(point.x())->at(point.y());
QPointF coords(item.x(), item.z());
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->series() != m_selectedSeries) {
QPoint mappedPoint = mapCoordsToSampleSpace(cache, coords);
updateSliceObject(cache, mappedPoint);
@@ -431,9 +382,10 @@ void Surface3DRenderer::updateSliceDataModel(const QPoint &point)
} else {
if (m_selectedSeries) {
SurfaceSeriesRenderCache *cache =
- m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ static_cast<SurfaceSeriesRenderCache *>(
+ m_renderCacheList.value(m_selectedSeries));
if (cache)
- updateSliceObject(cache, point);
+ updateSliceObject(static_cast<SurfaceSeriesRenderCache *>(cache), point);
}
}
}
@@ -536,7 +488,7 @@ void Surface3DRenderer::updateSliceObject(SurfaceSeriesRenderCache *cache, const
int row = point.x();
if ((m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow) && row == -1) ||
- (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn) && column == -1)) {
+ (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn) && column == -1)) {
cache->sliceSurfaceObject()->clear();
return;
}
@@ -550,19 +502,27 @@ void Surface3DRenderer::updateSliceObject(SurfaceSeriesRenderCache *cache, const
QSurfaceDataRow *sliceRow;
QSurfaceDataArray &dataArray = cache->dataArray();
float adjust = (0.025f * m_heightNormalizer) / 2.0f;
- float stepDown = 2.0f * adjust;
+ float doubleAdjust = 2.0f * adjust;
+ bool flipZX = false;
+ float zBack;
+ float zFront;
if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) {
QSurfaceDataRow *src = dataArray.at(row);
sliceRow = new QSurfaceDataRow(src->size());
+ zBack = m_axisCacheZ.min();
+ zFront = m_axisCacheZ.max();
for (int i = 0; i < sliceRow->size(); i++)
- (*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, -1.0f));
+ (*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, zFront));
} else {
+ flipZX = true;
const QRect &sampleSpace = cache->sampleSpace();
sliceRow = new QSurfaceDataRow(sampleSpace.height());
+ zBack = m_axisCacheX.min();
+ zFront = m_axisCacheX.max();
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));
+ zFront));
}
}
sliceDataArray << sliceRow;
@@ -571,114 +531,134 @@ void Surface3DRenderer::updateSliceObject(SurfaceSeriesRenderCache *cache, const
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));
+ sliceRow->at(i).y() - doubleAdjust,
+ zBack));
}
sliceDataArray << duplicateRow;
QRect sliceRect(0, 0, sliceRow->size(), 2);
if (sliceRow->size() > 0) {
- if (cache->isFlatShadingEnabled()) {
- cache->sliceSurfaceObject()->setUpData(sliceDataArray, sliceRect,
- m_heightNormalizer,
- m_axisCacheY.min(), true);
+ if (cache->isFlatShadingEnabled())
+ cache->sliceSurfaceObject()->setUpData(sliceDataArray, sliceRect, true, flipZX);
+ else
+ cache->sliceSurfaceObject()->setUpSmoothData(sliceDataArray, sliceRect, true, flipZX);
+ }
+}
+
+inline static float getDataValue(const QSurfaceDataArray &array, bool searchRow, int index)
+{
+ if (searchRow)
+ return array.at(0)->at(index).x();
+ else
+ return array.at(index)->at(0).z();
+}
+
+inline static int binarySearchArray(const QSurfaceDataArray &array, int maxIdx, float limitValue,
+ bool searchRow, bool lowBound, bool ascending)
+{
+ int min = 0;
+ int max = maxIdx;
+ int mid = 0;
+ int retVal;
+ while (max >= min) {
+ mid = (min + max) / 2;
+ float arrayValue = getDataValue(array, searchRow, mid);
+ if (arrayValue == limitValue)
+ return mid;
+ if (ascending) {
+ if (arrayValue < limitValue)
+ min = mid + 1;
+ else
+ max = mid - 1;
} else {
- cache->sliceSurfaceObject()->setUpSmoothData(sliceDataArray, sliceRect,
- m_heightNormalizer,
- m_axisCacheY.min(), true);
+ if (arrayValue > limitValue)
+ min = mid + 1;
+ else
+ max = mid - 1;
}
}
+
+ // Exact match not found, return closest depending on bound.
+ // The boundary is between last mid and min/max.
+ if (lowBound == ascending) {
+ if (mid > max)
+ retVal = mid;
+ else
+ retVal = min;
+ } else {
+ if (mid > max)
+ retVal = max;
+ else
+ retVal = mid;
+ }
+ if (retVal < 0 || retVal > maxIdx) {
+ retVal = -1;
+ } else if (lowBound) {
+ if (getDataValue(array, searchRow, retVal) < limitValue)
+ retVal = -1;
+ } else {
+ if (getDataValue(array, searchRow, retVal) > limitValue)
+ retVal = -1;
+ }
+ return retVal;
}
-QRect Surface3DRenderer::calculateSampleRect(SurfaceSeriesRenderCache *cache,
- const QSurfaceDataArray &array)
+QRect Surface3DRenderer::calculateSampleRect(const QSurfaceDataArray &array)
{
QRect sampleSpace;
- int rowCount = array.size();
- int columnCount = array.at(0)->size();
+ const int maxRow = array.size() - 1;
+ const int maxColumn = array.at(0)->size() - 1;
- int i;
- bool found;
- float axisMinX = m_axisCacheX.min();
- float axisMaxX = m_axisCacheX.max();
- float axisMinZ = m_axisCacheZ.min();
- float axisMaxZ = m_axisCacheZ.max();
+ // We assume data is ordered sequentially in rows for X-value and in columns for Z-value.
+ // Determine if data is ascending or descending in each case.
+ const bool ascendingX = array.at(0)->at(0).x() < array.at(0)->at(maxColumn).x();
+ const bool ascendingZ = array.at(0)->at(0).z() < array.at(maxRow)->at(0).z();
- // m_minVisibleColumnValue
- for (i = 0, found = false; i < columnCount; i++) {
- if (array.at(0)->at(i).x() >= axisMinX) {
- found = true;
- break;
- }
- }
- if (found) {
- m_minVisibleColumnValue = array.at(0)->at(i).x();
- sampleSpace.setLeft(i);
+ int idx = binarySearchArray(array, maxColumn, m_axisCacheX.min(), true, true, ascendingX);
+ if (idx != -1) {
+ if (ascendingX)
+ sampleSpace.setLeft(idx);
+ else
+ sampleSpace.setRight(idx);
} else {
sampleSpace.setWidth(-1); // to indicate nothing needs to be shown
return sampleSpace;
}
- // m_maxVisibleColumnValue
- for (i = columnCount - 1, found = false; i >= 0; i--) {
- if (array.at(0)->at(i).x() <= axisMaxX) {
- found = true;
- break;
- }
- }
- if (found) {
- m_maxVisibleColumnValue = array.at(0)->at(i).x();
- sampleSpace.setRight(i);
+ idx = binarySearchArray(array, maxColumn, m_axisCacheX.max(), true, false, ascendingX);
+ if (idx != -1) {
+ if (ascendingX)
+ sampleSpace.setRight(idx);
+ else
+ sampleSpace.setLeft(idx);
} else {
sampleSpace.setWidth(-1); // to indicate nothing needs to be shown
return sampleSpace;
}
- // m_minVisibleRowValue
- for (i = 0, found = false; i < rowCount; i++) {
- if (array.at(i)->at(0).z() >= axisMinZ) {
- found = true;
- break;
- }
- }
- if (found) {
- m_minVisibleRowValue = array.at(i)->at(0).z();
- sampleSpace.setTop(i);
+ idx = binarySearchArray(array, maxRow, m_axisCacheZ.min(), false, true, ascendingZ);
+ if (idx != -1) {
+ if (ascendingZ)
+ sampleSpace.setTop(idx);
+ else
+ sampleSpace.setBottom(idx);
} else {
sampleSpace.setWidth(-1); // to indicate nothing needs to be shown
return sampleSpace;
}
- // m_maxVisibleRowValue
- for (i = rowCount - 1, found = false; i >= 0; i--) {
- if (array.at(i)->at(0).z() <= axisMaxZ) {
- found = true;
- break;
- }
- }
- if (found) {
- m_maxVisibleRowValue = array.at(i)->at(0).z();
- sampleSpace.setBottom(i);
+ idx = binarySearchArray(array, maxRow, m_axisCacheZ.max(), false, false, ascendingZ);
+ if (idx != -1) {
+ if (ascendingZ)
+ sampleSpace.setBottom(idx);
+ else
+ sampleSpace.setTop(idx);
} else {
sampleSpace.setWidth(-1); // to indicate nothing needs to be shown
return sampleSpace;
}
- m_visibleColumnRange = m_maxVisibleColumnValue - m_minVisibleColumnValue;
- m_visibleRowRange = m_maxVisibleRowValue - m_minVisibleRowValue;
- GLfloat surfaceScaleX = m_scaleX * m_visibleColumnRange / m_areaSize.width();
- GLfloat surfaceScaleZ = m_scaleZ * m_visibleRowRange / m_areaSize.height();
- GLfloat axis2XCenterX = axisMinX + axisMaxX;
- GLfloat axis2XCenterZ = axisMinZ + axisMaxZ;
- GLfloat data2XCenterX = GLfloat(m_minVisibleColumnValue + m_maxVisibleColumnValue);
- GLfloat data2XCenterZ = GLfloat(m_minVisibleRowValue + m_maxVisibleRowValue);
- GLfloat surfaceOffsetX = m_scaleX * (data2XCenterX - axis2XCenterX) / m_areaSize.width();
- GLfloat surfaceOffsetZ = -m_scaleZ * (data2XCenterZ - axis2XCenterZ) / m_areaSize.height();
-
- cache->setScale(QVector3D(surfaceScaleX, 1.0f, surfaceScaleZ));
- cache->setOffset(QVector3D(surfaceOffsetX, 0.0f, surfaceOffsetZ));
-
return sampleSpace;
}
@@ -708,6 +688,13 @@ void Surface3DRenderer::render(GLuint defaultFboHandle)
// Handle GL state setup for FBO buffers and clearing of the render surface
Abstract3DRenderer::render(defaultFboHandle);
+ if (m_axisCacheX.positionsDirty())
+ m_axisCacheX.updateAllPositions();
+ if (m_axisCacheY.positionsDirty())
+ m_axisCacheY.updateAllPositions();
+ if (m_axisCacheZ.positionsDirty())
+ m_axisCacheZ.updateAllPositions();
+
drawScene(defaultFboHandle);
if (m_cachedIsSlicingActivated)
drawSlicedScene();
@@ -715,13 +702,14 @@ void Surface3DRenderer::render(GLuint defaultFboHandle)
// Render selection ball
if (m_selectionActive
&& m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionItem)) {
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->slicePointerActive() && cache->renderable() &&
m_cachedIsSlicingActivated ) {
cache->sliceSelectionPointer()->render(defaultFboHandle);
}
if (cache->mainPointerActive() && cache->renderable())
- cache->mainSelectionPointer()->render(defaultFboHandle);
+ cache->mainSelectionPointer()->render(defaultFboHandle, m_useOrthoProjection);
}
}
}
@@ -730,7 +718,7 @@ void Surface3DRenderer::drawSlicedScene()
{
QVector3D lightPos;
- QVector3D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
+ QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
// Specify viewport
glViewport(m_secondarySubViewport.x(),
@@ -760,13 +748,18 @@ void Surface3DRenderer::drawSlicedScene()
const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
bool rowMode = m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow);
+ AxisRenderCache &sliceCache = rowMode ? m_axisCacheX : m_axisCacheZ;
GLfloat scaleXBackground = 0.0f;
- if (m_renderCacheList.size()) {
+ // Disable culling to avoid ugly conditionals with reversed axes and data
+ glDisable(GL_CULL_FACE);
+
+ if (!m_renderCacheList.isEmpty()) {
bool drawGrid = false;
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->sliceSurfaceObject()->indexCount() && cache->renderable()) {
if (!drawGrid && cache->surfaceGridVisible()) {
glEnable(GL_POLYGON_OFFSET_FILL);
@@ -774,24 +767,16 @@ void Surface3DRenderer::drawSlicedScene()
drawGrid = true;
}
- GLfloat scaleX = 0.0f;
- GLfloat offset = 0.0f;
- if (rowMode) {
- scaleX = cache->scale().x();
+ if (rowMode)
scaleXBackground = m_scaleXWithBackground;
- offset = cache->offset().x();
- } else {
- scaleX = cache->scale().z();
+ else
scaleXBackground = m_scaleZWithBackground;
- offset = -cache->offset().z();
- }
QMatrix4x4 MVPMatrix;
QMatrix4x4 modelMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(offset, 0.0f, 0.0f);
- QVector3D scaling(scaleX, 1.0f, sliceZScale);
+ QVector3D scaling(1.0f, 1.0f, sliceZScale);
modelMatrix.scale(scaling);
itModelMatrix.scale(scaling);
@@ -832,10 +817,13 @@ void Surface3DRenderer::drawSlicedScene()
m_surfaceGridShader->bind();
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(),
Utils::vectorFromColor(m_cachedTheme->gridLineColor()));
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
- if (cache->sliceSurfaceObject()->indexCount() && cache->isSeriesVisible() &&
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(baseCache);
+ if (cache->sliceSurfaceObject()->indexCount() && cache->isVisible() &&
cache->surfaceGridVisible()) {
- m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), cache->MVPMatrix());
+ m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(),
+ cache->MVPMatrix());
m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->sliceSurfaceObject());
}
}
@@ -845,14 +833,22 @@ void Surface3DRenderer::drawSlicedScene()
// Disable textures
glDisable(GL_TEXTURE_2D);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+
// Grid lines
if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
+#if !(defined QT_OPENGL_ES_2)
ShaderHelper *lineShader = m_backgroundShader;
+#else
+ ShaderHelper *lineShader = m_selectionShader; // Plain color shader for GL_LINES
+#endif
+
// Bind line shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
+ QVector4D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), lineColor);
@@ -862,19 +858,16 @@ void Surface3DRenderer::drawSlicedScene()
lineShader->setUniformValue(lineShader->lightColor(), lightColor);
// Horizontal lines
+ int gridLineCount = m_axisCacheY.gridLineCount();
if (m_axisCacheY.segmentCount() > 0) {
QVector3D gridLineScaleX(scaleXBackground, gridLineWidth, gridLineWidth);
- GLfloat lineStep = 2.0f * m_axisCacheY.subSegmentStep() / m_heightNormalizer;
- GLfloat linePos = -1.0f;
- int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
-
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(0.0f, linePos, -sliceZScale);
+ modelMatrix.translate(0.0f, m_axisCacheY.gridLinePosition(line), -1.0f);
modelMatrix.scale(gridLineScaleX);
itModelMatrix.scale(gridLineScaleX);
@@ -888,36 +881,30 @@ void Surface3DRenderer::drawSlicedScene()
lineShader->setUniformValue(lineShader->MVP(), MVPMatrix);
// Draw the object
+#if !(defined QT_OPENGL_ES_2)
m_drawer->drawObject(lineShader, m_gridLineObj);
-
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
// Vertical lines
QVector3D gridLineScaleY(gridLineWidth, backgroundMargin, gridLineWidth);
- int lastSegment;
- GLfloat lineStep;
- GLfloat linePos;
- if (rowMode) {
- lineStep = -2.0f * aspectRatio * m_axisCacheX.subSegmentStep() / m_scaleFactor;
- lastSegment = m_axisCacheX.subSegmentCount() * m_axisCacheX.segmentCount();
- linePos = m_scaleX;
- } else {
- lineStep = -2.0f * aspectRatio * m_axisCacheZ.subSegmentStep() / m_scaleFactor;
- lastSegment = m_axisCacheZ.subSegmentCount() * m_axisCacheZ.segmentCount();
- linePos = m_scaleZ;
- }
-
- for (int segment = 0; segment <= lastSegment; segment++) {
+ gridLineCount = sliceCache.gridLineCount();
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(linePos, 0.0f, -sliceZScale);
+ modelMatrix.translate(sliceCache.gridLinePosition(line), 0.0f, -1.0f);
modelMatrix.scale(gridLineScaleY);
itModelMatrix.scale(gridLineScaleY);
+#if (defined QT_OPENGL_ES_2)
+ modelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+ itModelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+#endif
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -928,9 +915,11 @@ void Surface3DRenderer::drawSlicedScene()
lineShader->setUniformValue(lineShader->MVP(), MVPMatrix);
// Draw the object
+#if !(defined QT_OPENGL_ES_2)
m_drawer->drawObject(lineShader, m_gridLineObj);
-
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
@@ -938,96 +927,76 @@ void Surface3DRenderer::drawSlicedScene()
m_labelShader->bind();
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
- glCullFace(GL_BACK);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Y Labels to back wall
- GLfloat posStep = 2.0f * m_axisCacheY.segmentStep() / m_heightNormalizer;
- GLfloat labelPos = -1.0f;
int labelNbr = 0;
QVector3D positionComp(0.0f, 0.0f, 0.0f);
- QVector3D rotation(0.0f, 0.0f, 0.0f);
- QVector3D labelTrans = QVector3D(scaleXBackground + labelMargin, labelPos, 0.0f);
- for (int segment = 0; segment <= m_axisCacheY.segmentCount(); segment++) {
+ QVector3D labelTrans = QVector3D(scaleXBackground + labelMargin, 0.0f, 0.0f);
+ int labelCount = m_axisCacheY.labelCount();
+ for (int label = 0; label < labelCount; label++) {
if (m_axisCacheY.labelItems().size() > labelNbr) {
- labelTrans.setY(labelPos);
+ labelTrans.setY(m_axisCacheY.labelPosition(label));
const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
// Draw the label here
m_dummyRenderItem.setTranslation(labelTrans);
m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionComp, rotation, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, Qt::AlignRight, true);
+ positionComp, identityQuaternion, 0, m_cachedSelectionMode,
+ m_labelShader, m_labelObj, activeCamera, true, true,
+ Drawer::LabelMid, Qt::AlignLeft, true);
}
labelNbr++;
- labelPos += posStep;
}
// X Labels to ground
- int countLabelItems;
- int lastSegment;
- if (rowMode) {
- posStep = 2.0f * aspectRatio * m_axisCacheX.segmentStep() / m_scaleFactor;
- labelPos = -m_scaleX;
- lastSegment = m_axisCacheX.segmentCount();
- countLabelItems = m_axisCacheX.labelItems().size();
- } else {
- posStep = 2.0f * aspectRatio * m_axisCacheZ.segmentStep() / m_scaleFactor;
- labelPos = -m_scaleZ;
- lastSegment = m_axisCacheZ.segmentCount();
- countLabelItems = m_axisCacheZ.labelItems().size();
- }
+ int countLabelItems = sliceCache.labelItems().size();
+
+ QVector3D rotation(0.0f, 0.0f, -45.0f);
+ QQuaternion totalRotation = Utils::calculateRotation(rotation);
labelNbr = 0;
positionComp.setY(-0.1f);
- rotation.setZ(-45.0f);
labelTrans.setY(-backgroundMargin);
- for (int segment = 0; segment <= lastSegment; segment++) {
+ labelCount = sliceCache.labelCount();
+ for (int label = 0; label < labelCount; label++) {
if (countLabelItems > labelNbr) {
// Draw the label here
- labelTrans.setX(labelPos);
+ labelTrans.setX(sliceCache.labelPosition(label));
m_dummyRenderItem.setTranslation(labelTrans);
LabelItem *axisLabelItem;
- if (rowMode)
- axisLabelItem = m_axisCacheX.labelItems().at(labelNbr);
- else
- axisLabelItem = m_axisCacheZ.labelItems().at(labelNbr);
+ axisLabelItem = sliceCache.labelItems().at(labelNbr);
m_drawer->drawLabel(m_dummyRenderItem, *axisLabelItem, viewMatrix, projectionMatrix,
- positionComp, rotation, 0, QAbstract3DGraph::SelectionRow,
+ positionComp, totalRotation, 0, QAbstract3DGraph::SelectionRow,
m_labelShader, m_labelObj, activeCamera,
- false, false, Drawer::LabelBelow, Qt::AlignBottom, true);
+ false, false, Drawer::LabelBelow,
+ Qt::AlignmentFlag(Qt::AlignLeft | Qt::AlignTop), true);
}
labelNbr++;
- labelPos += posStep;
}
// Draw labels for axes
AbstractRenderItem *dummyItem(0);
positionComp.setY(m_autoScaleAdjustment);
- if (rowMode) {
- m_drawer->drawLabel(*dummyItem, m_axisCacheX.titleItem(), viewMatrix, projectionMatrix,
- positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelBottom,
- Qt::AlignCenter, true);
- } else {
- m_drawer->drawLabel(*dummyItem, m_axisCacheZ.titleItem(), viewMatrix, projectionMatrix,
- positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelBottom,
- Qt::AlignCenter, true);
- }
+ m_drawer->drawLabel(*dummyItem, sliceCache.titleItem(), viewMatrix, projectionMatrix,
+ positionComp, identityQuaternion, 0, m_cachedSelectionMode, m_labelShader,
+ m_labelObj, activeCamera, false, false, Drawer::LabelBottom,
+ Qt::AlignCenter, true);
+
// Y-axis label
+ rotation = QVector3D(0.0f, 0.0f, 90.0f);
+ totalRotation = Utils::calculateRotation(rotation);
labelTrans = QVector3D(-scaleXBackground - labelMargin, 0.0f, 0.0f);
m_dummyRenderItem.setTranslation(labelTrans);
m_drawer->drawLabel(m_dummyRenderItem, m_axisCacheY.titleItem(), viewMatrix,
- projectionMatrix, zeroVector, QVector3D(0.0f, 0.0f, 90.0f), 0,
+ projectionMatrix, zeroVector, totalRotation, 0,
m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera,
- false, false, Drawer::LabelMid, Qt::AlignHCenter);
+ false, false, Drawer::LabelMid, Qt::AlignBottom);
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
@@ -1042,7 +1011,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
bool noShadows = true;
GLfloat backgroundRotation = 0;
- QVector3D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
+ QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
glViewport(m_primarySubViewport.x(),
m_primarySubViewport.y(),
@@ -1051,8 +1020,16 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Set up projection matrix
QMatrix4x4 projectionMatrix;
- projectionMatrix.perspective(45.0f, (GLfloat)m_primarySubViewport.width()
- / (GLfloat)m_primarySubViewport.height(), 0.1f, 100.0f);
+ GLfloat viewPortRatio = (GLfloat)m_primarySubViewport.width()
+ / (GLfloat)m_primarySubViewport.height();
+ if (m_useOrthoProjection) {
+ GLfloat orthoRatio = 2.0f;
+ projectionMatrix.ortho(-viewPortRatio * orthoRatio, viewPortRatio * orthoRatio,
+ -orthoRatio, orthoRatio,
+ 0.0f, 100.0f);
+ } else {
+ projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
+ }
const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
@@ -1089,8 +1066,9 @@ 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_renderCacheList.size()) {
+ GLfloat adjustedLightStrength = m_cachedTheme->lightStrength() / 10.0f;
+ if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone &&
+ (!m_renderCacheList.isEmpty() || !m_customRenderCache.isEmpty())) {
// Render scene into a depth texture for using with shadow mapping
// Enable drawing to depth framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer);
@@ -1121,15 +1099,14 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glDisable(GL_CULL_FACE);
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
SurfaceObject *object = cache->surfaceObject();
- if (object->indexCount() && cache->surfaceVisible() && cache->isSeriesVisible()
+ if (object->indexCount() && cache->surfaceVisible() && cache->isVisible()
&& cache->sampleSpace().width() >= 2 && cache->sampleSpace().height() >= 2) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
- modelMatrix.translate(cache->offset());
- modelMatrix.scale(cache->scale());
MVPMatrix = depthProjectionViewMatrix * modelMatrix;
cache->setMVPMatrix(MVPMatrix);
m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
@@ -1149,16 +1126,18 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
}
- glEnable(GL_CULL_FACE);
- glCullFace(GL_FRONT);
+ Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
m_depthModelTexture, 0);
glClear(GL_DEPTH_BUFFER_BIT);
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
SurfaceObject *object = cache->surfaceObject();
- if (object->indexCount() && cache->surfaceVisible() && cache->isSeriesVisible()
+ if (object->indexCount() && cache->surfaceVisible() && cache->isVisible()
&& cache->sampleSpace().width() >= 2 && cache->sampleSpace().height() >= 2) {
m_depthShader->setUniformValue(m_depthShader->MVP(), cache->MVPMatrix());
@@ -1183,6 +1162,10 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glDisableVertexAttribArray(m_depthShader->posAtt());
+ Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
+
// Disable drawing to depth framebuffer (= enable drawing to screen)
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
@@ -1201,7 +1184,9 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glEnable(GL_TEXTURE_2D);
// Draw selection buffer
- if (!m_cachedIsSlicingActivated && m_renderCacheList.size() && m_selectionState == SelectOnScene
+ if (!m_cachedIsSlicingActivated && (!m_renderCacheList.isEmpty()
+ || !m_customRenderCache.isEmpty())
+ && m_selectionState == SelectOnScene
&& m_cachedSelectionMode > QAbstract3DGraph::SelectionNone) {
m_selectionShader->bind();
glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer);
@@ -1217,14 +1202,12 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glDisable(GL_CULL_FACE);
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->surfaceObject()->indexCount() && cache->renderable()) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
- modelMatrix.translate(cache->offset());
- modelMatrix.scale(cache->scale());
-
MVPMatrix = projectionViewMatrix * modelMatrix;
m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
@@ -1232,21 +1215,23 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
cache->selectionTexture());
}
}
+ m_surfaceGridShader->bind();
+ Abstract3DRenderer::drawCustomItems(RenderingSelection, m_surfaceGridShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
+ drawLabels(true, activeCamera, viewMatrix, projectionMatrix);
glEnable(GL_DITHER);
- GLubyte pixel[4] = {0, 0, 0, 0};
- glReadPixels(m_inputPosition.x(), m_viewport.height() - m_inputPosition.y(),
- 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void *)pixel);
+ QVector4D clickedColor = Utils::getSelection(m_inputPosition, m_viewport.height());
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
// Put the RGBA value back to uint
-#if !defined(QT_OPENGL_ES_2)
- uint selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536 + pixel[3] * 16777216;
-#else
- uint selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536;
-#endif
+ uint selectionId = uint(clickedColor.x())
+ + uint(clickedColor.y()) * greenMultiplier
+ + uint(clickedColor.z()) * blueMultiplier
+ + uint(clickedColor.w()) * alphaMultiplier;
m_clickedPosition = selectionIdToSurfacePoint(selectionId);
@@ -1260,21 +1245,18 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
// Draw the surface
- if (m_renderCacheList.size()) {
+ if (!m_renderCacheList.isEmpty()) {
// For surface we can see climpses from underneath
glDisable(GL_CULL_FACE);
bool drawGrid = false;
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(cache->offset());
- modelMatrix.scale(cache->scale());
- itModelMatrix.scale(cache->scale());
-
#ifdef SHOW_DEPTH_TEXTURE_SCENE
MVPMatrix = depthProjectionViewMatrix * modelMatrix;
#else
@@ -1283,7 +1265,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
cache->setMVPMatrix(MVPMatrix);
const QRect &sampleSpace = cache->sampleSpace();
- if (cache->surfaceObject()->indexCount() && cache->isSeriesVisible() &&
+ if (cache->surfaceObject()->indexCount() && cache->isVisible() &&
sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
noShadows = false;
if (!drawGrid && cache->surfaceGridVisible()) {
@@ -1346,13 +1328,18 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glDisable(GL_POLYGON_OFFSET_FILL);
m_surfaceGridShader->bind();
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(),
- Utils::vectorFromColor(m_cachedTheme->gridLineColor()));
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
- m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), cache->MVPMatrix());
+ Utils::vectorFromColor(
+ m_cachedTheme->gridLineColor()));
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(baseCache);
+ m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(),
+ cache->MVPMatrix());
const QRect &sampleSpace = cache->sampleSpace();
- if (cache->surfaceObject()->indexCount() && cache->surfaceGridVisible() &&
- cache->isSeriesVisible() && sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
+ if (cache->surfaceObject()->indexCount() && cache->surfaceGridVisible()
+ && cache->isVisible() && sampleSpace.width() >= 2
+ && sampleSpace.height() >= 2) {
m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->surfaceObject());
}
}
@@ -1388,7 +1375,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
+ QVector4D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
// Set shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos);
@@ -1412,7 +1399,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_backgroundShader->setUniformValue(m_backgroundShader->lightS(),
adjustedLightStrength);
// Draw the object
- if (noShadows)
+ if (noShadows && m_customRenderCache.isEmpty())
m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_noShadowTexture);
else
m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_depthTexture);
@@ -1436,13 +1423,17 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
QVector3D gridLineScaleY(gridLineWidth, backgroundMargin, gridLineWidth);
if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
+#if !(defined QT_OPENGL_ES_2)
ShaderHelper *lineShader = m_backgroundShader;
+#else
+ ShaderHelper *lineShader = m_selectionShader; // Plain color shader for GL_LINES
+#endif
// Bind line shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
+ QVector4D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), lineColor);
@@ -1482,16 +1473,15 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Rows (= Z)
if (m_axisCacheZ.segmentCount() > 0) {
// Floor lines
- GLfloat lineStep = 2.0f * aspectRatio * m_axisCacheZ.subSegmentStep() / m_scaleFactor;
- GLfloat linePos = m_scaleZ; // Start line
- int lastSegment = m_axisCacheZ.subSegmentCount() * m_axisCacheZ.segmentCount();
+ int gridLineCount = m_axisCacheZ.gridLineCount();
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(0.0f, yFloorLinePosition, linePos);
+ modelMatrix.translate(0.0f, yFloorLinePosition,
+ m_axisCacheZ.gridLinePosition(line));
modelMatrix.scale(gridLineScaleX);
itModelMatrix.scale(gridLineScaleX);
@@ -1514,34 +1504,38 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos -= lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
// Side wall lines
GLfloat lineXTrans = m_scaleXWithBackground - gridLineOffset;
- linePos = m_scaleZ; // Start line
if (!m_xFlipped)
lineXTrans = -lineXTrans;
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(lineXTrans, 0.0f, linePos);
+ modelMatrix.translate(lineXTrans, 0.0f, m_axisCacheZ.gridLinePosition(line));
modelMatrix.scale(gridLineScaleY);
itModelMatrix.scale(gridLineScaleY);
+#if !defined(QT_OPENGL_ES_2)
modelMatrix.rotate(lineYRotation);
itModelMatrix.rotate(lineYRotation);
+#else
+ modelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+ itModelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+#endif
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1558,29 +1552,31 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos -= lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
// Columns (= X)
if (m_axisCacheX.segmentCount() > 0) {
+#if defined(QT_OPENGL_ES_2)
+ lineXRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f);
+#endif
// Floor lines
- GLfloat lineStep = -2.0f * aspectRatio * m_axisCacheX.subSegmentStep() / m_scaleFactor;
- GLfloat linePos = m_scaleX;
- int lastSegment = m_axisCacheX.subSegmentCount() * m_axisCacheX.segmentCount();
+ int gridLineCount = m_axisCacheX.gridLineCount();
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(linePos, yFloorLinePosition, 0.0f);
+ modelMatrix.translate(m_axisCacheX.gridLinePosition(line), yFloorLinePosition,
+ 0.0f);
modelMatrix.scale(gridLineScaleZ);
itModelMatrix.scale(gridLineScaleZ);
@@ -1603,36 +1599,40 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
// Back wall lines
GLfloat lineZTrans = m_scaleZWithBackground - gridLineOffset;
- linePos = m_scaleX;
if (!m_zFlipped)
lineZTrans = -lineZTrans;
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(linePos, 0.0f, lineZTrans);
+ modelMatrix.translate(m_axisCacheX.gridLinePosition(line), 0.0f, lineZTrans);
modelMatrix.scale(gridLineScaleY);
itModelMatrix.scale(gridLineScaleY);
+#if !defined(QT_OPENGL_ES_2)
if (m_zFlipped) {
modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
}
+#else
+ modelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+ itModelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+#endif
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1649,34 +1649,32 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
// Horizontal wall lines
if (m_axisCacheY.segmentCount() > 0) {
// Back wall
- GLfloat lineStep = 2.0f * m_axisCacheY.subSegmentStep() / m_heightNormalizer;
- GLfloat linePos = -1.0f;
- int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
+ int gridLineCount = m_axisCacheY.gridLineCount();
GLfloat lineZTrans = m_scaleZWithBackground - gridLineOffset;
if (!m_zFlipped)
lineZTrans = -lineZTrans;
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(0.0f, linePos, lineZTrans);
+ modelMatrix.translate(0.0f, m_axisCacheY.gridLinePosition(line), lineZTrans);
modelMatrix.scale(gridLineScaleX);
itModelMatrix.scale(gridLineScaleX);
@@ -1701,29 +1699,27 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
// Side wall
- linePos = -1.0f;
- lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
GLfloat lineXTrans = m_scaleXWithBackground - gridLineOffset;
if (!m_xFlipped)
lineXTrans = -lineXTrans;
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(lineXTrans, linePos, 0.0f);
+ modelMatrix.translate(lineXTrans, m_axisCacheY.gridLinePosition(line), 0.0f);
modelMatrix.scale(gridLineScaleZ);
itModelMatrix.scale(gridLineScaleZ);
@@ -1746,221 +1742,434 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
}
- // Draw axis labels
- m_labelShader->bind();
+ Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
+
+ drawLabels(false, activeCamera, viewMatrix, projectionMatrix);
+
+ // Release shader
+ glUseProgram(0);
+
+ // Selection handling
+ if (m_selectionDirty || m_selectionLabelDirty) {
+ QPoint visiblePoint = Surface3DController::invalidSelectionPosition();
+ if (m_selectedSeries) {
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(
+ m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries)));
+ if (cache && m_selectedPoint != Surface3DController::invalidSelectionPosition()) {
+ const 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);
+ }
+ }
+ }
+
+ if (m_cachedSelectionMode == QAbstract3DGraph::SelectionNone
+ || visiblePoint == Surface3DController::invalidSelectionPosition()) {
+ m_selectionActive = false;
+ } else {
+ if (m_cachedIsSlicingActivated)
+ updateSliceDataModel(visiblePoint);
+ if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionItem))
+ surfacePointSelected(visiblePoint);
+ m_selectionActive = true;
+ }
+
+ m_selectionDirty = false;
+ }
+}
+
+void Surface3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamera,
+ const QMatrix4x4 &viewMatrix,
+ const QMatrix4x4 &projectionMatrix)
+{
+ ShaderHelper *shader = 0;
+ GLfloat alphaForValueSelection = labelValueAlpha / 255.0f;
+ GLfloat alphaForRowSelection = labelRowAlpha / 255.0f;
+ GLfloat alphaForColumnSelection = labelColumnAlpha / 255.0f;
+ if (drawSelection) {
+ shader = m_surfaceGridShader;
+ } else {
+ shader = m_labelShader;
+ shader->bind();
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POLYGON_OFFSET_FILL);
+ float labelAutoAngle = m_axisCacheZ.labelAutoRotation();
+ float labelAngleFraction = labelAutoAngle / 90.0f;
+ float fractionCamY = activeCamera->yRotation() * labelAngleFraction;
+ float fractionCamX = activeCamera->xRotation() * labelAngleFraction;
+ float labelsMaxWidth = 0.0f;
+
+ int startIndex;
+ int endIndex;
+ int indexStep;
+
// Z Labels
QVector3D positionZComp(0.0f, 0.0f, 0.0f);
if (m_axisCacheZ.segmentCount() > 0) {
- GLfloat posStep = 2.0f * aspectRatio * m_axisCacheZ.segmentStep() / m_scaleFactor;
- GLfloat labelPos = m_scaleZ;
- int lastSegment = m_axisCacheZ.segmentCount();
- int labelNbr = 0;
+ int labelCount = m_axisCacheZ.labelCount();
GLfloat labelXTrans = m_scaleXWithBackground + labelMargin;
GLfloat labelYTrans = -backgroundMargin;
- GLfloat rotLabelX = -90.0f;
- GLfloat rotLabelY = 0.0f;
- GLfloat rotLabelZ = 0.0f;
- Qt::AlignmentFlag alignment = Qt::AlignRight;
- if (m_zFlipped)
- rotLabelY = 180.0f;
- if (m_xFlipped) {
+ Qt::AlignmentFlag alignment = (m_xFlipped == m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
+ QVector3D labelRotation;
+ if (m_xFlipped)
labelXTrans = -labelXTrans;
- alignment = Qt::AlignLeft;
- }
- if (m_yFlipped) {
- rotLabelZ += 180.0f;
- rotLabelY += 180.0f;
+ if (m_yFlipped)
labelYTrans = -labelYTrans;
+ if (labelAutoAngle == 0.0f) {
+ labelRotation.setX(-90.0f);
+ if (m_zFlipped)
+ labelRotation.setY(180.0f);
+ if (m_yFlipped) {
+ if (m_zFlipped)
+ labelRotation.setY(0.0f);
+ else
+ labelRotation.setY(180.0f);
+ labelRotation.setZ(180.0f);
+ }
+ } else {
+ if (m_zFlipped)
+ labelRotation.setY(180.0f);
+ if (m_yFlipped) {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f - (labelAutoAngle - fractionCamX)
+ * (-labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(90.0f + (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f + (labelAutoAngle - fractionCamX)
+ * -(labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(90.0f - (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ }
+ }
+ } else {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f + (labelAutoAngle - fractionCamX)
+ * (-labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f - (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f - (labelAutoAngle - fractionCamX)
+ * (-labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f + (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ }
+ }
+ }
}
+
+ QQuaternion totalRotation = Utils::calculateRotation(labelRotation);
+
QVector3D labelTrans = QVector3D(labelXTrans,
labelYTrans,
- labelPos);
- QVector3D rotation(rotLabelX, rotLabelY, rotLabelZ);
-
- for (int segment = 0; segment <= lastSegment; segment++) {
- if (m_axisCacheZ.labelItems().size() > labelNbr) {
- glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
- // Draw the label here
- labelTrans.setZ(labelPos);
- m_dummyRenderItem.setTranslation(labelTrans);
- const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(labelNbr);
-
- m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionZComp, rotation, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, alignment);
+ 0.0f);
+
+ if (m_zFlipped) {
+ startIndex = 0;
+ endIndex = labelCount;
+ indexStep = 1;
+ } else {
+ startIndex = labelCount - 1;
+ endIndex = -1;
+ indexStep = -1;
+ }
+ for (int label = startIndex; label != endIndex; label = label + indexStep) {
+ glPolygonOffset(GLfloat(label) / -10.0f, 1.0f);
+ // Draw the label here
+ labelTrans.setZ(m_axisCacheZ.labelPosition(label));
+ m_dummyRenderItem.setTranslation(labelTrans);
+ const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(label);
+
+ if (drawSelection) {
+ QVector4D labelColor = QVector4D(label / 255.0f, 0.0f, 0.0f,
+ alphaForRowSelection);
+ shader->setUniformValue(shader->color(), labelColor);
}
- labelNbr++;
- labelPos -= posStep;
+
+ m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ positionZComp, totalRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, alignment, false, drawSelection);
+ labelsMaxWidth = qMax(labelsMaxWidth, float(axisLabelItem.size().width()));
+ }
+ if (!drawSelection && m_axisCacheZ.isTitleVisible()) {
+ labelTrans.setZ(0.0f);
+ drawAxisTitleZ(labelRotation, labelTrans, totalRotation, m_dummyRenderItem,
+ activeCamera, labelsMaxWidth, viewMatrix, projectionMatrix, shader);
}
}
// X Labels
if (m_axisCacheX.segmentCount() > 0) {
- GLfloat posStep = 2.0f * aspectRatio * m_axisCacheX.segmentStep() / m_scaleFactor;
- GLfloat labelPos = -m_scaleX;
- int lastSegment = m_axisCacheX.segmentCount();
+ labelsMaxWidth = 0.0f;
+ labelAutoAngle = m_axisCacheX.labelAutoRotation();
+ labelAngleFraction = labelAutoAngle / 90.0f;
+ fractionCamY = activeCamera->yRotation() * labelAngleFraction;
+ fractionCamX = activeCamera->xRotation() * labelAngleFraction;
+ int labelCount = m_axisCacheX.labelCount();
- int labelNbr = 0;
GLfloat labelZTrans = m_scaleZWithBackground + labelMargin;
GLfloat labelYTrans = -backgroundMargin;
- GLfloat rotLabelX = -90.0f;
- GLfloat rotLabelY = 90.0f;
- GLfloat rotLabelZ = 0.0f;
- Qt::AlignmentFlag alignment = Qt::AlignLeft;
- if (m_xFlipped)
- rotLabelY = -90.0f;
- if (m_zFlipped) {
+ Qt::AlignmentFlag alignment = (m_xFlipped != m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
+ QVector3D labelRotation;
+ if (m_zFlipped)
labelZTrans = -labelZTrans;
- alignment = Qt::AlignRight;
- }
- if (m_yFlipped) {
- rotLabelZ += 180.0f;
- rotLabelY += 180.0f;
+ if (m_yFlipped)
labelYTrans = -labelYTrans;
+ if (labelAutoAngle == 0.0f) {
+ labelRotation = QVector3D(-90.0f, 90.0f, 0.0f);
+ if (m_xFlipped)
+ labelRotation.setY(-90.0f);
+ if (m_yFlipped) {
+ if (m_xFlipped)
+ labelRotation.setY(90.0f);
+ else
+ labelRotation.setY(-90.0f);
+ labelRotation.setZ(180.0f);
+ }
+ } else {
+ if (m_xFlipped)
+ labelRotation.setY(-90.0f);
+ else
+ labelRotation.setY(90.0f);
+ if (m_yFlipped) {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f - (2.0f * labelAutoAngle - fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(90.0f - (2.0f * labelAutoAngle + fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f + fractionCamX
+ * -(labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(90.0f - fractionCamX
+ * (-labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ }
+ }
+ } else {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f + (2.0f * labelAutoAngle - fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f + (2.0f * labelAutoAngle + fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f - fractionCamX
+ * (-labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f + fractionCamX
+ * -(labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ }
+ }
+ }
}
- QVector3D labelTrans = QVector3D(labelPos,
+ QQuaternion totalRotation = Utils::calculateRotation(labelRotation);
+
+ QVector3D labelTrans = QVector3D(0.0f,
labelYTrans,
labelZTrans);
- QVector3D rotation(rotLabelX, rotLabelY, rotLabelZ);
-
- for (int segment = 0; segment <= lastSegment; segment++) {
- if (m_axisCacheX.labelItems().size() > labelNbr) {
- glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
- // Draw the label here
- labelTrans.setX(labelPos);
- m_dummyRenderItem.setTranslation(labelTrans);
- const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(labelNbr);
-
- m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionZComp, rotation, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, alignment);
+
+ if (m_xFlipped) {
+ startIndex = labelCount - 1;
+ endIndex = -1;
+ indexStep = -1;
+ } else {
+ startIndex = 0;
+ endIndex = labelCount;
+ indexStep = 1;
+ }
+ for (int label = startIndex; label != endIndex; label = label + indexStep) {
+ glPolygonOffset(GLfloat(label) / -10.0f, 1.0f);
+ // Draw the label here
+ labelTrans.setX(m_axisCacheX.labelPosition(label));
+ m_dummyRenderItem.setTranslation(labelTrans);
+ const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(label);
+
+ if (drawSelection) {
+ QVector4D labelColor = QVector4D(0.0f, label / 255.0f, 0.0f,
+ alphaForColumnSelection);
+ shader->setUniformValue(shader->color(), labelColor);
}
- labelNbr++;
- labelPos += posStep;
+
+ m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ positionZComp, totalRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, alignment, false, drawSelection);
+ labelsMaxWidth = qMax(labelsMaxWidth, float(axisLabelItem.size().width()));
+ }
+ if (!drawSelection && m_axisCacheX.isTitleVisible()) {
+ labelTrans.setX(0.0f);
+ drawAxisTitleX(labelRotation, labelTrans, totalRotation, m_dummyRenderItem,
+ activeCamera, labelsMaxWidth, viewMatrix, projectionMatrix, shader);
}
}
// Y Labels
if (m_axisCacheY.segmentCount() > 0) {
- GLfloat posStep = 2.0f * m_axisCacheY.segmentStep() / m_heightNormalizer;
- GLfloat labelPos = -1.0f;
- int labelNbr = 0;
+ labelsMaxWidth = 0.0f;
+ labelAutoAngle = m_axisCacheY.labelAutoRotation();
+ labelAngleFraction = labelAutoAngle / 90.0f;
+ fractionCamY = activeCamera->yRotation() * labelAngleFraction;
+ fractionCamX = activeCamera->xRotation() * labelAngleFraction;
+ int labelCount = m_axisCacheY.labelCount();
+
GLfloat labelXTrans = m_scaleXWithBackground;
GLfloat labelZTrans = m_scaleZWithBackground;
- // Back wall init
+ // Back & side wall
GLfloat labelMarginXTrans = labelMargin;
GLfloat labelMarginZTrans = labelMargin;
- GLfloat rotLabelX = 0.0f;
- GLfloat rotLabelY = -90.0f;
- GLfloat rotLabelZ = 0.0f;
- Qt::AlignmentFlag alignmentBack = Qt::AlignLeft;
+ QVector3D backLabelRotation(0.0f, -90.0f, 0.0f);
+ QVector3D sideLabelRotation(0.0f, 0.0f, 0.0f);
+ Qt::AlignmentFlag backAlignment =
+ (m_xFlipped != m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
+ Qt::AlignmentFlag sideAlignment =
+ (m_xFlipped == m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
if (!m_xFlipped) {
labelXTrans = -labelXTrans;
labelMarginXTrans = -labelMargin;
- rotLabelY = 90.0f;
}
if (m_zFlipped) {
labelZTrans = -labelZTrans;
labelMarginZTrans = -labelMargin;
- alignmentBack = Qt::AlignRight;
}
- QVector3D labelRotateVectorBack(rotLabelX, rotLabelY, rotLabelZ);
- QVector3D labelTransBack = QVector3D(labelXTrans, 0.0f, labelZTrans + labelMarginZTrans);
+ if (labelAutoAngle == 0.0f) {
+ if (!m_xFlipped)
+ backLabelRotation.setY(90.0f);
+ if (m_zFlipped)
+ sideLabelRotation.setY(180.f);
+ } else {
+ // Orient side labels somewhat towards the camera
+ if (m_xFlipped) {
+ if (m_zFlipped)
+ sideLabelRotation.setY(180.0f + (2.0f * labelAutoAngle) - fractionCamX);
+ else
+ sideLabelRotation.setY(-fractionCamX);
+ backLabelRotation.setY(-90.0f + labelAutoAngle - fractionCamX);
+ } else {
+ if (m_zFlipped)
+ sideLabelRotation.setY(180.0f - (2.0f * labelAutoAngle) - fractionCamX);
+ else
+ sideLabelRotation.setY(-fractionCamX);
+ backLabelRotation.setY(90.0f - labelAutoAngle - fractionCamX);
+ }
+ }
+ sideLabelRotation.setX(-fractionCamY);
+ backLabelRotation.setX(-fractionCamY);
- // Side wall init
- Qt::AlignmentFlag alignmentSide = Qt::AlignLeft;
- if (m_xFlipped)
- alignmentSide = Qt::AlignLeft;
- else
- alignmentSide = Qt::AlignRight;
- if (m_zFlipped)
- rotLabelY = 180.0f;
- else
- rotLabelY = 0.0f;
+ QQuaternion totalSideRotation = Utils::calculateRotation(sideLabelRotation);
+ QQuaternion totalBackRotation = Utils::calculateRotation(backLabelRotation);
- QVector3D labelRotateVectorSide(rotLabelX, rotLabelY, rotLabelZ);
+ QVector3D labelTransBack = QVector3D(labelXTrans, 0.0f, labelZTrans + labelMarginZTrans);
QVector3D labelTransSide(-labelXTrans - labelMarginXTrans, 0.0f, -labelZTrans);
- for (int segment = 0; segment <= m_axisCacheY.segmentCount(); segment++) {
- if (m_axisCacheY.labelItems().size() > labelNbr) {
- const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
-
- glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
-
- // Back wall
- labelTransBack.setY(labelPos);
- m_dummyRenderItem.setTranslation(labelTransBack);
- m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionZComp, labelRotateVectorBack, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, alignmentBack);
-
- // Side wall
- labelTransSide.setY(labelPos);
- m_dummyRenderItem.setTranslation(labelTransSide);
- m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionZComp, labelRotateVectorSide, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, alignmentSide);
- }
- labelNbr++;
- labelPos += posStep;
+ if (m_yFlipped) {
+ startIndex = labelCount - 1;
+ endIndex = -1;
+ indexStep = -1;
+ } else {
+ startIndex = 0;
+ endIndex = labelCount;
+ indexStep = 1;
}
- }
- glDisable(GL_POLYGON_OFFSET_FILL);
+ for (int label = startIndex; label != endIndex; label = label + indexStep) {
+ const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(label);
+ const GLfloat labelYTrans = m_axisCacheY.labelPosition(label);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
+ glPolygonOffset(GLfloat(label) / -10.0f, 1.0f);
- // Release shader
- glUseProgram(0);
-
- // Selection handling
- if (m_selectionDirty || m_selectionLabelDirty) {
- QPoint visiblePoint = Surface3DController::invalidSelectionPosition();
- if (m_selectedSeries) {
- SurfaceSeriesRenderCache *cache =
- m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
- if (cache && m_selectedPoint != Surface3DController::invalidSelectionPosition()) {
- const 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);
- }
+ if (drawSelection) {
+ QVector4D labelColor = QVector4D(0.0f, 0.0f, label / 255.0f,
+ alphaForValueSelection);
+ shader->setUniformValue(shader->color(), labelColor);
}
- }
- if (m_cachedSelectionMode == QAbstract3DGraph::SelectionNone
- || visiblePoint == Surface3DController::invalidSelectionPosition()) {
- m_selectionActive = false;
- } else {
- if (m_cachedIsSlicingActivated)
- updateSliceDataModel(visiblePoint);
- if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionItem))
- surfacePointSelected(visiblePoint);
- m_selectionActive = true;
+ // Back wall
+ labelTransBack.setY(labelYTrans);
+ m_dummyRenderItem.setTranslation(labelTransBack);
+ m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ positionZComp, totalBackRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, backAlignment, false,
+ drawSelection);
+
+ // Side wall
+ labelTransSide.setY(labelYTrans);
+ m_dummyRenderItem.setTranslation(labelTransSide);
+ m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ positionZComp, totalSideRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, sideAlignment, false,
+ drawSelection);
+ labelsMaxWidth = qMax(labelsMaxWidth, float(axisLabelItem.size().width()));
+ }
+ if (!drawSelection && m_axisCacheY.isTitleVisible()) {
+ labelTransSide.setY(0.0f);
+ labelTransBack.setY(0.0f);
+ drawAxisTitleY(sideLabelRotation, backLabelRotation, labelTransSide, labelTransBack,
+ totalSideRotation, totalBackRotation, m_dummyRenderItem, activeCamera,
+ labelsMaxWidth, viewMatrix, projectionMatrix,
+ shader);
}
+ }
+ glDisable(GL_POLYGON_OFFSET_FILL);
- m_selectionDirty = false;
+ if (!drawSelection) {
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
}
}
@@ -1976,7 +2185,9 @@ void Surface3DRenderer::updateSelectionTextures()
{
uint lastSelectionId = 1;
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(baseCache);
GLuint texture = cache->selectionTexture();
m_textureHelper->deleteTexture(&texture);
createSelectionTexture(cache, lastSelectionId);
@@ -1992,6 +2203,13 @@ void Surface3DRenderer::createSelectionTexture(SurfaceSeriesRenderCache *cache,
const QRect &sampleSpace = cache->sampleSpace();
int idImageWidth = (sampleSpace.width() - 1) * 4;
int idImageHeight = (sampleSpace.height() - 1) * 4;
+
+ if (idImageHeight <= 0 || idImageWidth <= 0) {
+ cache->setSelectionIdRange(-1, -1);
+ cache->setSelectionTexture(0);
+ return;
+ }
+
int stride = idImageWidth * 4 * sizeof(uchar); // 4 = number of color components (rgba)
uint idStart = lastSelectionId;
@@ -2031,10 +2249,7 @@ void Surface3DRenderer::createSelectionTexture(SurfaceSeriesRenderCache *cache,
void Surface3DRenderer::initSelectionBuffer()
{
// Create the result selection texture and buffers
- if (m_selectionResultTexture) {
- m_textureHelper->deleteTexture(&m_selectionResultTexture);
- m_selectionResultTexture = 0;
- }
+ m_textureHelper->deleteTexture(&m_selectionResultTexture);
m_selectionResultTexture = m_textureHelper->createSelectionTexture(m_primarySubViewport.size(),
m_selectionFrameBuffer,
@@ -2076,10 +2291,16 @@ void Surface3DRenderer::calculateSceneScalingFactors()
m_areaSize.setHeight(m_axisCacheZ.max() - m_axisCacheZ.min());
m_areaSize.setWidth(m_axisCacheX.max() - m_axisCacheX.min());
m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height());
- m_scaleX = aspectRatio * m_areaSize.width() / m_scaleFactor;
- m_scaleZ = aspectRatio * m_areaSize.height() / m_scaleFactor;
- m_scaleXWithBackground = m_scaleX * backgroundMargin;
- m_scaleZWithBackground = m_scaleZ * backgroundMargin;
+ m_scaleX = m_graphAspectRatio * m_areaSize.width() / m_scaleFactor;
+ m_scaleZ = m_graphAspectRatio * m_areaSize.height() / m_scaleFactor;
+ m_scaleXWithBackground = m_scaleX + backgroundMargin - 1.0f;
+ m_scaleZWithBackground = m_scaleZ + backgroundMargin - 1.0f;
+
+ float factorScaler = 2.0f * m_graphAspectRatio / m_scaleFactor;
+ m_axisCacheX.setScale(factorScaler * m_areaSize.width());
+ m_axisCacheZ.setScale(-factorScaler * m_areaSize.height());
+ m_axisCacheX.setTranslate(-m_axisCacheX.scale() / 2.0f);
+ m_axisCacheZ.setTranslate(-m_axisCacheZ.scale() / 2.0f);
}
void Surface3DRenderer::checkFlatSupport(SurfaceSeriesRenderCache *cache)
@@ -2098,17 +2319,13 @@ void Surface3DRenderer::updateObjects(SurfaceSeriesRenderCache *cache, bool dime
QSurfaceDataArray &dataArray = cache->dataArray();
const QRect &sampleSpace = cache->sampleSpace();
-
- 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);
- }
+ if (cache->isFlatShadingEnabled())
+ cache->surfaceObject()->setUpData(dataArray, sampleSpace, dimensionChanged);
+ else
+ cache->surfaceObject()->setUpSmoothData(dataArray, sampleSpace, dimensionChanged);
}
-void Surface3DRenderer::updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series)
+void Surface3DRenderer::updateSelectedPoint(const QPoint &position, QSurface3DSeries *series)
{
m_selectedPoint = position;
m_selectedSeries = series;
@@ -2123,23 +2340,15 @@ void Surface3DRenderer::resetClickedStatus()
void Surface3DRenderer::loadBackgroundMesh()
{
- if (m_backgroundObj)
- delete m_backgroundObj;
- m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background"));
- m_backgroundObj->load();
-}
-
-void Surface3DRenderer::loadGridLineMesh()
-{
- if (m_gridLineObj)
- delete m_gridLineObj;
- m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
- m_gridLineObj->load();
+ ObjectHelper::resetObjectHelper(this, m_backgroundObj,
+ QStringLiteral(":/defaultMeshes/background"));
}
void Surface3DRenderer::surfacePointSelected(const QPoint &point)
{
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(baseCache);
cache->setSlicePointerActivity(false);
cache->setMainPointerActivity(false);
}
@@ -2147,12 +2356,15 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point)
if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries)) {
// Find axis coordinates for the selected point
SurfaceSeriesRenderCache *selectedCache =
- m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ static_cast<SurfaceSeriesRenderCache *>(
+ m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries)));
QSurfaceDataArray &dataArray = selectedCache->dataArray();
QSurfaceDataItem item = dataArray.at(point.x())->at(point.y());
QPointF coords(item.x(), item.z());
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->series() != m_selectedSeries) {
QPoint mappedPoint = mapCoordsToSampleSpace(cache, coords);
updateSelectionPoint(cache, mappedPoint, false);
@@ -2163,7 +2375,8 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point)
} else {
if (m_selectedSeries) {
SurfaceSeriesRenderCache *cache =
- m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ static_cast<SurfaceSeriesRenderCache *>(
+ m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries)));
if (cache)
updateSelectionPoint(cache, point, true);
}
@@ -2179,9 +2392,6 @@ void Surface3DRenderer::updateSelectionPoint(SurfaceSeriesRenderCache *cache, co
if (column < 0 || row < 0)
return;
- QSurfaceDataArray &dataArray = cache->dataArray();
- float value = dataArray.at(row)->at(column).y();
-
SelectionPointer *slicePointer = cache->sliceSelectionPointer();
if (!slicePointer && m_cachedIsSlicingActivated) {
slicePointer = new SelectionPointer(m_drawer);
@@ -2193,28 +2403,28 @@ void Surface3DRenderer::updateSelectionPoint(SurfaceSeriesRenderCache *cache, co
cache->setMainSelectionPointer(mainPointer);
}
- const QVector3D &scale = cache->scale();
- const QVector3D &offset = cache->offset();
QString selectionLabel;
- if (label)
- selectionLabel = createSelectionLabel(cache, value, column, row);
+ if (label) {
+ m_selectionLabelDirty = false;
+ selectionLabel = cache->itemLabel();
+ }
if (m_cachedIsSlicingActivated) {
- QVector3D subPos;
+ QVector3D subPosFront;
+ QVector3D subPosBack;
if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) {
- subPos = cache->sliceSurfaceObject()->vertexAt(column, 0);
- subPos *= QVector3D(scale.x(), 1.0f, 0.0f);
- subPos += QVector3D(offset.x(), 0.0f, 0.0f);
+ subPosFront = cache->sliceSurfaceObject()->vertexAt(column, 0);
+ subPosBack = cache->sliceSurfaceObject()->vertexAt(column, 1);
} else if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn)) {
- subPos = cache->sliceSurfaceObject()->vertexAt(row, 0);
- subPos *= QVector3D(scale.z(), 1.0f, 0.0f);
- subPos += QVector3D(-offset.z(), 0.0f, 0.0f);
+ subPosFront = cache->sliceSurfaceObject()->vertexAt(row, 0);
+ subPosBack = cache->sliceSurfaceObject()->vertexAt(row, 1);
}
slicePointer->updateBoundingRect(m_secondarySubViewport);
slicePointer->updateSliceData(true, m_autoScaleAdjustment);
- slicePointer->setPosition(subPos);
+ slicePointer->setPosition((subPosFront + subPosBack) / 2.0f);
slicePointer->setLabel(selectionLabel);
slicePointer->setPointerObject(cache->object());
+ slicePointer->setLabelObject(m_labelObj);
slicePointer->setHighlightColor(cache->singleHighlightColor());
slicePointer->updateScene(m_cachedScene);
slicePointer->setRotation(cache->meshRotation());
@@ -2223,13 +2433,12 @@ void Surface3DRenderer::updateSelectionPoint(SurfaceSeriesRenderCache *cache, co
QVector3D mainPos;
mainPos = cache->surfaceObject()->vertexAt(column, row);
- mainPos *= scale;
- mainPos += offset;
mainPointer->updateBoundingRect(m_primarySubViewport);
mainPointer->updateSliceData(false, m_autoScaleAdjustment);
mainPointer->setPosition(mainPos);
mainPointer->setLabel(selectionLabel);
mainPointer->setPointerObject(cache->object());
+ mainPointer->setLabelObject(m_labelObj);
mainPointer->setHighlightColor(cache->singleHighlightColor());
mainPointer->updateScene(m_cachedScene);
mainPointer->setRotation(cache->meshRotation());
@@ -2239,8 +2448,33 @@ void Surface3DRenderer::updateSelectionPoint(SurfaceSeriesRenderCache *cache, co
// Maps selection Id to surface point in data array
QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id)
{
+ m_clickedType = QAbstract3DGraph::ElementNone;
+ m_selectedLabelIndex = -1;
+ m_selectedCustomItemIndex = -1;
+ // Check for label and custom item selection
+ if (id / alphaMultiplier == labelRowAlpha) {
+ m_selectedLabelIndex = id - (alphaMultiplier * uint(labelRowAlpha));
+ m_clickedType = QAbstract3DGraph::ElementAxisZLabel;
+ return Surface3DController::invalidSelectionPosition();
+ } else if (id / alphaMultiplier == labelColumnAlpha) {
+ m_selectedLabelIndex = (id - (alphaMultiplier * uint(labelColumnAlpha))) / greenMultiplier;
+ m_clickedType = QAbstract3DGraph::ElementAxisXLabel;
+ return Surface3DController::invalidSelectionPosition();
+ } else if (id / alphaMultiplier == labelValueAlpha) {
+ m_selectedLabelIndex = (id - (alphaMultiplier * uint(labelValueAlpha))) / blueMultiplier;
+ m_clickedType = QAbstract3DGraph::ElementAxisYLabel;
+ return Surface3DController::invalidSelectionPosition();
+ } else if (id / alphaMultiplier == customItemAlpha) {
+ // Custom item selection
+ m_clickedType = QAbstract3DGraph::ElementCustomItem;
+ m_selectedCustomItemIndex = id - (alphaMultiplier * uint(customItemAlpha));
+ return Surface3DController::invalidSelectionPosition();
+ }
+
+ // Not a label selection
SurfaceSeriesRenderCache *selectedCache = 0;
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->isWithinIdRange(id)) {
selectedCache = cache;
break;
@@ -2257,57 +2491,10 @@ QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id)
int row = ((idInSeries - 1) / sampleSpace.width()) + sampleSpace.y();
m_clickedSeries = selectedCache->series();
+ m_clickedType = QAbstract3DGraph::ElementSeries;
return QPoint(row, column);
}
-QString Surface3DRenderer::createSelectionLabel(SurfaceSeriesRenderCache *cache, float value,
- int column, int row)
-{
- 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"));
- static const QString xLabelTag(QStringLiteral("@xLabel"));
- static const QString yLabelTag(QStringLiteral("@yLabel"));
- static const QString zLabelTag(QStringLiteral("@zLabel"));
- static const QString seriesNameTag(QStringLiteral("@seriesName"));
-
- labelText.replace(xTitleTag, m_axisCacheX.title());
- labelText.replace(yTitleTag, m_axisCacheY.title());
- labelText.replace(zTitleTag, m_axisCacheZ.title());
-
- if (labelText.contains(xLabelTag)) {
- QString labelFormat = m_axisCacheX.labelFormat();
- if (labelFormat.isEmpty())
- labelFormat = Utils::defaultLabelFormat();
- QString valueLabelText = generateValueLabel(labelFormat,
- dataArray.at(row)->at(column).x());
- labelText.replace(xLabelTag, valueLabelText);
- }
- if (labelText.contains(yLabelTag)) {
- QString labelFormat = m_axisCacheY.labelFormat();
- if (labelFormat.isEmpty())
- labelFormat = Utils::defaultLabelFormat();
- QString valueLabelText = generateValueLabel(labelFormat, value);
- labelText.replace(yLabelTag, valueLabelText);
- }
- if (labelText.contains(zLabelTag)) {
- QString labelFormat = m_axisCacheZ.labelFormat();
- if (labelFormat.isEmpty())
- labelFormat = Utils::defaultLabelFormat();
- QString valueLabelText = generateValueLabel(labelFormat,
- dataArray.at(row)->at(column).z());
- labelText.replace(zLabelTag, valueLabelText);
- }
-
- labelText.replace(seriesNameTag, cache->name());
-
- m_selectionLabelDirty = false;
-
- return labelText;
-}
-
void Surface3DRenderer::updateShadowQuality(QAbstract3DGraph::ShadowQuality quality)
{
m_cachedShadowQuality = quality;
@@ -2371,20 +2558,13 @@ void Surface3DRenderer::updateSlicingActive(bool isSlicing)
m_selectionDirty = true;
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->mainSelectionPointer())
cache->mainSelectionPointer()->updateBoundingRect(m_primarySubViewport);
}
}
-void Surface3DRenderer::loadLabelMesh()
-{
- if (m_labelObj)
- delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
- m_labelObj->load();
-}
-
void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader)
{
Q_UNUSED(vertexShader);
@@ -2408,17 +2588,22 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &
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_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
- QStringLiteral(":/shaders/fragmentSurfaceFlat"));
- }
m_surfaceSliceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentSurface"));
- m_surfaceSliceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
- QStringLiteral(":/shaders/fragmentSurfaceFlat"));
+ if (m_flatSupported) {
+ if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
+ m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceShadowFlat"),
+ QStringLiteral(":/shaders/fragmentSurfaceShadowFlat"));
+ } else {
+ m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
+ QStringLiteral(":/shaders/fragmentSurfaceFlat"));
+ }
+ m_surfaceSliceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
+ QStringLiteral(":/shaders/fragmentSurfaceFlat"));
+ } else {
+ m_surfaceFlatShader = 0;
+ m_surfaceSliceFlatShader = 0;
+ }
#else
m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentSurfaceES2"));
@@ -2430,9 +2615,11 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &
QStringLiteral(":/shaders/fragmentSurfaceES2"));
#endif
m_surfaceSmoothShader->initialize();
- m_surfaceFlatShader->initialize();
m_surfaceSliceSmoothShader->initialize();
- m_surfaceSliceFlatShader->initialize();
+ if (m_flatSupported) {
+ m_surfaceFlatShader->initialize();
+ m_surfaceSliceFlatShader->initialize();
+ }
}
void Surface3DRenderer::initBackgroundShaders(const QString &vertexShader,
@@ -2486,14 +2673,8 @@ void Surface3DRenderer::initDepthShader()
void Surface3DRenderer::updateDepthBuffer()
{
- if (m_depthTexture) {
- m_textureHelper->deleteTexture(&m_depthTexture);
- m_depthTexture = 0;
- }
- if (m_depthModelTexture) {
- m_textureHelper->deleteTexture(&m_depthModelTexture);
- m_depthModelTexture = 0;
- }
+ m_textureHelper->deleteTexture(&m_depthTexture);
+ m_textureHelper->deleteTexture(&m_depthModelTexture);
if (m_primarySubViewport.size().isEmpty())
return;
@@ -2512,4 +2693,22 @@ void Surface3DRenderer::updateDepthBuffer()
}
#endif
+QVector3D Surface3DRenderer::convertPositionToTranslation(const QVector3D &position,
+ bool isAbsolute)
+{
+ float xTrans = 0.0f;
+ float yTrans = 0.0f;
+ float zTrans = 0.0f;
+ if (!isAbsolute) {
+ xTrans = m_axisCacheX.positionAt(position.x());
+ yTrans = m_axisCacheY.positionAt(position.y());
+ zTrans = m_axisCacheZ.positionAt(position.z());
+ } else {
+ xTrans = position.x() * m_scaleX;
+ yTrans = position.y();
+ zTrans = position.z() * m_scaleZ;
+ }
+ return QVector3D(xTrans, yTrans, zTrans);
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION