Multiseries support for surface

Multiseries support for item and row changes.

Task-number: QTRD-2767
Change-Id: I5702989e7f59913481a2ca888e402effa22a4221
Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
This commit is contained in:
Mika Salmela 2014-02-10 10:26:30 +02:00
parent 61c84e2d9c
commit 51ad2b7e53
6 changed files with 172 additions and 118 deletions

View File

@ -322,29 +322,29 @@ void Surface3DController::handleRowsChanged(int startIndex, int count)
m_changedRows.reserve(sender->rowCount());
QSurface3DSeries *series = sender->series();
if (series->isVisible()) {
// Change is for the visible series, put the change to queue
int oldChangeCount = m_changedRows.size();
for (int i = 0; i < count; i++) {
bool newItem = true;
int candidate = startIndex + i;
for (int i = 0; i < oldChangeCount; i++) {
if (m_changedRows.at(i) == candidate) {
newItem = false;
break;
}
int oldChangeCount = m_changedRows.size();
for (int i = 0; i < count; i++) {
bool newItem = true;
int candidate = startIndex + i;
for (int i = 0; i < oldChangeCount; i++) {
if (m_changedRows.at(i).row == candidate &&
series == m_changedRows.at(i).series) {
newItem = false;
break;
}
if (newItem)
m_changedRows.append(candidate);
}
if (m_changedRows.size()) {
m_changeTracker.rowsChanged = true;
if (newItem) {
ChangeRow newItem = {series, candidate};
m_changedRows.append(newItem);
}
}
if (m_changedRows.size()) {
m_changeTracker.rowsChanged = true;
adjustValueAxisRange();
// Clear selection unless still valid
setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
emitNeedRender();
}
adjustValueAxisRange();
// Clear selection unless still valid
setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
emitNeedRender();
}
}
@ -352,26 +352,25 @@ void Surface3DController::handleItemChanged(int rowIndex, int columnIndex)
{
QSurfaceDataProxy *sender = static_cast<QSurfaceDataProxy *>(QObject::sender());
QSurface3DSeries *series = sender->series();
if (series->isVisible()) {
// Change is for the visible series, put the change to queue
bool newItem = true;
QPoint candidate(columnIndex, rowIndex);
foreach (QPoint item, m_changedItems) {
if (item == candidate) {
newItem = false;
break;
}
}
if (newItem) {
m_changedItems.append(candidate);
m_changeTracker.itemChanged = true;
adjustValueAxisRange();
// Clear selection unless still valid
setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
emitNeedRender();
bool newItem = true;
QPoint candidate(columnIndex, rowIndex);
foreach (ChangeItem item, m_changedItems) {
if (item.point == candidate && item.series == series) {
newItem = false;
break;
}
}
if (newItem) {
ChangeItem newItem = {series, candidate};
m_changedItems.append(newItem);
m_changeTracker.itemChanged = true;
adjustValueAxisRange();
// Clear selection unless still valid
setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
emitNeedRender();
}
}
void Surface3DController::handleRowsAdded(int startIndex, int count)

View File

@ -58,6 +58,16 @@ class QT_DATAVISUALIZATION_EXPORT Surface3DController : public Abstract3DControl
{
Q_OBJECT
public:
struct ChangeItem {
QSurface3DSeries *series;
QPoint point;
};
struct ChangeRow {
QSurface3DSeries *series;
int row;
};
private:
Surface3DChangeBitField m_changeTracker;
Surface3DRenderer *m_renderer;
@ -65,8 +75,8 @@ private:
QSurface3DSeries *m_selectedSeries; // Points to the series for which the point is selected in
// single series selection cases.
bool m_flatShadingSupported;
QVector<QPoint> m_changedItems;
QVector<int> m_changedRows;
QVector<ChangeItem> m_changedItems;
QVector<ChangeRow> m_changedRows;
QVector<QSurface3DSeries *> m_changedSeriesList;
public:

View File

@ -45,18 +45,12 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
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;
const GLfloat backgroundBottom = 1.0f;
const GLfloat gridLineWidth = 0.005f;
const GLfloat sliceZScale = 0.1f;
const GLfloat sliceUnits = 2.5f;
const int subViewDivider = 5;
const uint invalidSelectionId = uint(-1);
Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
: Abstract3DRenderer(controller),
m_labelBackground(false),
m_font(QFont(QStringLiteral("Arial"))),
m_isGridEnabled(true),
m_cachedIsSlicingActivated(false),
m_depthShader(0),
m_backgroundShader(0),
@ -84,7 +78,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_backgroundObj(0),
m_gridLineObj(0),
m_labelObj(0),
m_surfaceObj(0),
m_depthTexture(0),
m_depthModelTexture(0),
m_depthFrameBuffer(0),
@ -92,16 +85,13 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_selectionDepthBuffer(0),
m_selectionResultTexture(0),
m_shadowQualityToShader(33.3f),
m_cachedFlatShading(false),
m_flatSupported(true),
m_selectionPointer(0),
m_selectionActive(false),
m_xFlipped(false),
m_zFlipped(false),
m_yFlipped(false),
m_sampleSpace(QRect(0, 0, 0, 0)),
m_shadowQualityMultiplier(3),
m_clickedPointId(invalidSelectionId),
m_hasHeightAdjustmentChanged(true),
m_selectedPoint(Surface3DController::invalidSelectionPosition()),
m_selectedSeries(0),
@ -318,81 +308,86 @@ void Surface3DRenderer::modifiedSeriesList(const QVector<QSurface3DSeries *> &se
}
}
void Surface3DRenderer::updateRows(const QVector<int> &rows)
void Surface3DRenderer::updateRows(const QVector<Surface3DController::ChangeRow> &rows)
{
// 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();
foreach (Surface3DController::ChangeRow item, rows) {
SurfaceSeriesRenderCache *cache = m_renderCacheList.value(item.series);
QSurfaceDataArray &dstArray = cache->dataArray();
QRect sampleSpace = cache->sampleSpace();
const QSurfaceDataArray *srcArray = 0;
QSurfaceDataProxy *dataProxy = item.series->dataProxy();
if (dataProxy)
array = dataProxy->array();
}
srcArray = dataProxy->array();
if (array && array->size() >= 2 && array->at(0)->size() >= 2
&& m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
bool updateBuffers = false;
int sampleSpaceTop = m_sampleSpace.y() + m_sampleSpace.height();
foreach (int row, rows) {
if (row >= m_sampleSpace.y() && row <= sampleSpaceTop) {
if (cache && srcArray->size() >= 2 && srcArray->at(0)->size() >= 2 &&
sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
bool updateBuffers = false;
int sampleSpaceTop = sampleSpace.y() + sampleSpace.height();
int row = item.row;
if (row >= sampleSpace.y() && row <= sampleSpaceTop) {
updateBuffers = true;
for (int j = 0; j < m_sampleSpace.width(); j++)
(*(m_dataArray.at(row - m_sampleSpace.y())))[j] =
array->at(row)->at(j + m_sampleSpace.x());
for (int j = 0; j < sampleSpace.width(); j++) {
(*(dstArray.at(row - sampleSpace.y())))[j] =
srcArray->at(row)->at(j + sampleSpace.x());
}
if (m_cachedFlatShading) {
m_surfaceObj->updateCoarseRow(m_dataArray, row - m_sampleSpace.y(),
m_heightNormalizer,
m_axisCacheY.min());
if (cache->isFlatShadingEnabled()) {
cache->surfaceObject()->updateCoarseRow(dstArray, row - sampleSpace.y(),
m_heightNormalizer,
m_axisCacheY.min());
} else {
m_surfaceObj->updateSmoothRow(m_dataArray, row - m_sampleSpace.y(),
m_heightNormalizer,
m_axisCacheY.min());
cache->surfaceObject()->updateSmoothRow(dstArray, row - sampleSpace.y(),
m_heightNormalizer,
m_axisCacheY.min());
}
}
if (updateBuffers)
cache->surfaceObject()->uploadBuffers();
}
if (updateBuffers)
m_surfaceObj->uploadBuffers();
}
updateSelectedPoint(m_selectedPoint, m_selectedSeries);
}
void Surface3DRenderer::updateItem(const QVector<QPoint> &points)
void Surface3DRenderer::updateItem(const QVector<Surface3DController::ChangeItem> &points)
{
// 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();
foreach (Surface3DController::ChangeItem item, points) {
SurfaceSeriesRenderCache *cache = m_renderCacheList.value(item.series);
QSurfaceDataArray &dstArray = cache->dataArray();
QRect sampleSpace = cache->sampleSpace();
const QSurfaceDataArray *srcArray = 0;
QSurfaceDataProxy *dataProxy = item.series->dataProxy();
if (dataProxy)
array = dataProxy->array();
}
srcArray = dataProxy->array();
if (array && array->size() >= 2 && array->at(0)->size() >= 2
&& m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
int sampleSpaceTop = m_sampleSpace.y() + m_sampleSpace.height();
int sampleSpaceRight = m_sampleSpace.x() + m_sampleSpace.width();
bool updateBuffers = false;
foreach (QPoint item, points) {
if (item.y() <= sampleSpaceTop && item.y() >= m_sampleSpace.y() &&
item.x() <= sampleSpaceRight && item.x() >= m_sampleSpace.x()) {
if (cache && srcArray->size() >= 2 && srcArray->at(0)->size() >= 2 &&
sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
int sampleSpaceTop = sampleSpace.y() + sampleSpace.height();
int sampleSpaceRight = sampleSpace.x() + sampleSpace.width();
bool updateBuffers = false;
QPoint point = item.point;
if (point.y() <= sampleSpaceTop && point.y() >= sampleSpace.y() &&
point.x() <= sampleSpaceRight && point.x() >= sampleSpace.x()) {
updateBuffers = true;
int x = item.x() - m_sampleSpace.x();
int y = item.y() - m_sampleSpace.y();
(*(m_dataArray.at(y)))[x] = array->at(item.y())->at(item.x());
int x = point.x() - sampleSpace.x();
int y = point.y() - sampleSpace.y();
(*(dstArray.at(y)))[x] = srcArray->at(point.y())->at(point.x());
if (m_cachedFlatShading) {
m_surfaceObj->updateCoarseItem(m_dataArray, y, x, m_heightNormalizer,
m_axisCacheY.min());
if (cache->isFlatShadingEnabled()) {
cache->surfaceObject()->updateCoarseItem(dstArray, y, x, m_heightNormalizer,
m_axisCacheY.min());
} else {
m_surfaceObj->updateSmoothItem(m_dataArray, y, x, m_heightNormalizer,
m_axisCacheY.min());
cache->surfaceObject()->updateSmoothItem(dstArray, y, x, m_heightNormalizer,
m_axisCacheY.min());
}
}
if (updateBuffers)
cache->surfaceObject()->uploadBuffers();
}
if (updateBuffers)
m_surfaceObj->uploadBuffers();
}
updateSelectedPoint(m_selectedPoint, m_selectedSeries);

View File

@ -48,13 +48,6 @@ class QT_DATAVISUALIZATION_EXPORT Surface3DRenderer : public Abstract3DRenderer
{
Q_OBJECT
public:
// Visual parameters
QRect m_boundingRect;
bool m_labelBackground;
QFont m_font;
bool m_isGridEnabled;
private:
bool m_cachedIsSlicingActivated;
@ -85,7 +78,6 @@ private:
ObjectHelper *m_backgroundObj;
ObjectHelper *m_gridLineObj;
ObjectHelper *m_labelObj;
SurfaceObject *m_surfaceObj;
GLuint m_depthTexture;
GLuint m_depthModelTexture;
GLuint m_depthFrameBuffer;
@ -93,7 +85,6 @@ private:
GLuint m_selectionDepthBuffer;
GLuint m_selectionResultTexture;
GLfloat m_shadowQualityToShader;
bool m_cachedFlatShading;
bool m_flatSupported;
SelectionPointer *m_selectionPointer;
bool m_selectionActive;
@ -101,15 +92,11 @@ private:
bool m_zFlipped;
bool m_yFlipped;
AbstractRenderItem m_dummyRenderItem;
QSurfaceDataArray m_dataArray;
QRect m_sampleSpace;
GLint m_shadowQualityMultiplier;
QSizeF m_areaSize;
uint m_clickedPointId;
bool m_hasHeightAdjustmentChanged;
QPoint m_selectedPoint;
const QSurface3DSeries *m_selectedSeries;
QVector3D m_uniformGradientTextureColor;
QPoint m_clickedPosition;
QHash<QSurface3DSeries *, SurfaceSeriesRenderCache *> m_renderCacheList;
bool m_selectionTexturesDirty;
@ -123,8 +110,8 @@ public:
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 updateRows(const QVector<Surface3DController::ChangeRow> &rows);
void updateItem(const QVector<Surface3DController::ChangeItem> &points);
void updateScene(Q3DScene *scene);
void updateSlicingActive(bool isSlicing);
void updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series);

View File

@ -122,9 +122,9 @@ void GraphModifier::fillSeries()
QSurfaceDataRow *newRow3 = new QSurfaceDataRow(m_xCount);
QSurfaceDataRow *newRow4 = new QSurfaceDataRow(m_xCount);
float z = float(i) - m_limitZ + 0.5f;
for (int j = 0; j < m_xCount; j++) {
float x = float(j) - m_limitX + 0.5f;
float z = float(i) - m_limitZ + 0.5f;
float angle = (z * x) / float(full) * 1.57f;
(*newRow1)[j].setPosition(QVector3D(x, qSin(angle), z));
angle *= 1.3f;
@ -701,10 +701,39 @@ void GraphModifier::changeRow()
m_theSeries->dataProxy()->setRow(int(i), newRow);
} else {
#ifdef MULTI_SERIES
static int changeRowSeries = 0;
qDebug() << "Generating new values to a row at random pos for series " << changeRowSeries;
int row = rand() % m_zCount;
QSurfaceDataRow *newRow = createMultiRow(row, changeRowSeries);
m_multiseries[changeRowSeries]->dataProxy()->setRow(row, newRow);
changeRowSeries++;
if (changeRowSeries > 3)
changeRowSeries = 0;
#else
qDebug() << "Change row function active only for SqrtSin";
#endif
}
}
QSurfaceDataRow *GraphModifier::createMultiRow(int row, int series)
{
int full = m_limitX * m_limitZ;
float i = float(row);
QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount);
float z = float(i) - m_limitZ + 0.5f;
for (int j = 0; j < m_xCount; j++) {
float x = float(j) - m_limitX + 0.5f;
float angle = (z * x) / float(full) * 1.57f;
float y = qSin(angle * float(qPow(1.3f, series))) + 0.2f + 1.1f *series;
(*newRow)[j].setPosition(QVector3D(x, y, z));
}
return newRow;
}
void GraphModifier::changeRows()
{
if (m_activeSample == GraphModifier::SqrtSin) {
@ -734,7 +763,24 @@ void GraphModifier::changeRows()
m_theSeries->dataProxy()->setRows(int(start), dataArray);
} else {
#ifdef MULTI_SERIES
static int changeRowSeries = 0;
qDebug() << "Generating new values for 3 rows at random pos for series " << changeRowSeries;
int row = rand() % (m_zCount - 3);
QSurfaceDataArray dataArray;
for (int i = 0; i < 3; i++) {
QSurfaceDataRow *newRow = createMultiRow(row + i, changeRowSeries);
dataArray.append(newRow);
}
m_multiseries[changeRowSeries]->dataProxy()->setRows(row, dataArray);
changeRowSeries++;
if (changeRowSeries > 3)
changeRowSeries = 0;
#else
qDebug() << "Change row function active only for SqrtSin";
#endif
}
}
@ -759,7 +805,23 @@ void GraphModifier::changeItem()
m_theSeries->dataProxy()->setItem(int(i), int(j), newItem);
} else {
qDebug() << "Change row function active only for SqrtSin";
#ifdef MULTI_SERIES
static int changeItemSeries = 0;
int full = m_limitX * m_limitZ;
float i = float(rand() % m_zCount);
float j = float(rand() % m_xCount);
float x = float(j) - m_limitX + 0.5f;
float z = float(i) - m_limitZ + 0.5f;
float angle = (z * x) / float(full) * 1.57f;
float y = qSin(angle * float(qPow(1.3f, changeItemSeries))) + 0.2f + 1.1f *changeItemSeries;
QSurfaceDataItem newItem(QVector3D(x, y, z));
m_multiseries[changeItemSeries]->dataProxy()->setItem(int(i), int(j), newItem);
changeItemSeries++;
if (changeItemSeries > 3)
changeItemSeries = 0;
#else
qDebug() << "Change item function active only for SqrtSin";
#endif
}
}

View File

@ -119,6 +119,7 @@ private:
void fillSeries();
void resetArrayAndSliders(QSurfaceDataArray *array, float minZ, float maxZ, float minX,
float maxX);
QSurfaceDataRow *createMultiRow(int row, int series);
Q3DSurface *m_graph;
QSurface3DSeries *m_multiseries[4];