diff options
author | Mika Salmela <mika.salmela@digia.com> | 2013-12-03 14:00:23 +0200 |
---|---|---|
committer | Mika Salmela <mika.salmela@digia.com> | 2013-12-03 14:06:59 +0200 |
commit | 344870fb79e647b87aa79b9433eef8237c901e10 (patch) | |
tree | f0ccaa5991d9f0304bc6f6f91ce3ffd45232384d /src/datavisualization | |
parent | 2af35db1a112c49991a80f48e3cd8d8814deb321 (diff) |
Better proxy API for surface
Part 2, item change. More is on the way.
Change-Id: Ic41f3a90b5a47502b741391ace990117ef2eaf80
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Diffstat (limited to 'src/datavisualization')
-rw-r--r-- | src/datavisualization/data/qsurface3dseries.cpp | 2 | ||||
-rw-r--r-- | src/datavisualization/data/qsurfacedataproxy.cpp | 17 | ||||
-rw-r--r-- | src/datavisualization/data/qsurfacedataproxy.h | 3 | ||||
-rw-r--r-- | src/datavisualization/data/qsurfacedataproxy_p.h | 1 | ||||
-rw-r--r-- | src/datavisualization/engine/surface3dcontroller.cpp | 66 | ||||
-rw-r--r-- | src/datavisualization/engine/surface3dcontroller_p.h | 9 | ||||
-rw-r--r-- | src/datavisualization/engine/surface3drenderer.cpp | 78 | ||||
-rw-r--r-- | src/datavisualization/engine/surface3drenderer_p.h | 3 | ||||
-rw-r--r-- | src/datavisualization/utils/surfaceobject.cpp | 248 | ||||
-rw-r--r-- | src/datavisualization/utils/surfaceobject_p.h | 13 |
10 files changed, 331 insertions, 109 deletions
diff --git a/src/datavisualization/data/qsurface3dseries.cpp b/src/datavisualization/data/qsurface3dseries.cpp index 5a47a6e4..deb12f44 100644 --- a/src/datavisualization/data/qsurface3dseries.cpp +++ b/src/datavisualization/data/qsurface3dseries.cpp @@ -332,6 +332,8 @@ void QSurface3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *ne &Surface3DController::handleArrayReset); QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::rowsChanged, controller, &Surface3DController::handleRowsChanged); + QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::itemChanged, controller, + &Surface3DController::handleItemChanged); } } diff --git a/src/datavisualization/data/qsurfacedataproxy.cpp b/src/datavisualization/data/qsurfacedataproxy.cpp index aba2e288..4c6c85f7 100644 --- a/src/datavisualization/data/qsurfacedataproxy.cpp +++ b/src/datavisualization/data/qsurfacedataproxy.cpp @@ -158,6 +158,15 @@ void QSurfaceDataProxy::setRows(int rowIndex, const QSurfaceDataArray &rows) } /*! + * Changes a single item at \a rowIndex, \a columnIndex to the \a item. + */ +void QSurfaceDataProxy::setItem(int rowIndex, int columnIndex, const QSurfaceDataItem &item) +{ + dptr()->setItem(rowIndex, columnIndex, item); + emit itemChanged(rowIndex, columnIndex); +} + +/*! * \return pointer to the data array. */ const QSurfaceDataArray *QSurfaceDataProxy::array() const @@ -273,6 +282,14 @@ void QSurfaceDataProxyPrivate::setRows(int rowIndex, const QSurfaceDataArray &ro } } +void QSurfaceDataProxyPrivate::setItem(int rowIndex, int columnIndex, const QSurfaceDataItem &item) +{ + Q_ASSERT(rowIndex >= 0 && rowIndex < m_dataArray->size()); + QSurfaceDataRow &row = *(*m_dataArray)[rowIndex]; + Q_ASSERT(columnIndex < row.size()); + row[columnIndex] = item; +} + QSurfaceDataProxy *QSurfaceDataProxyPrivate::qptr() { return static_cast<QSurfaceDataProxy *>(q_ptr); diff --git a/src/datavisualization/data/qsurfacedataproxy.h b/src/datavisualization/data/qsurfacedataproxy.h index d8808ded..4533f4c5 100644 --- a/src/datavisualization/data/qsurfacedataproxy.h +++ b/src/datavisualization/data/qsurfacedataproxy.h @@ -53,9 +53,12 @@ public: void setRow(int rowIndex, QSurfaceDataRow *row); void setRows(int rowIndex, const QSurfaceDataArray &rows); + void setItem(int rowIndex, int columnIndex, const QSurfaceDataItem &item); + signals: void arrayReset(); void rowsChanged(int startIndex, int count); + void itemChanged(int rowIndex, int columnIndex); void seriesChanged(QSurface3DSeries *series); protected: diff --git a/src/datavisualization/data/qsurfacedataproxy_p.h b/src/datavisualization/data/qsurfacedataproxy_p.h index 38d92be1..3125a40a 100644 --- a/src/datavisualization/data/qsurfacedataproxy_p.h +++ b/src/datavisualization/data/qsurfacedataproxy_p.h @@ -46,6 +46,7 @@ public: void resetArray(QSurfaceDataArray *newArray); void setRow(int rowIndex, QSurfaceDataRow *row); void setRows(int rowIndex, const QSurfaceDataArray &rows); + void setItem(int rowIndex, int columnIndex, const QSurfaceDataItem &item); void limitValues(QVector3D &minValues, QVector3D &maxValues) const; virtual void setSeries(QAbstract3DSeries *series); diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp index b1586a78..a9c5f508 100644 --- a/src/datavisualization/engine/surface3dcontroller.cpp +++ b/src/datavisualization/engine/surface3dcontroller.cpp @@ -37,8 +37,6 @@ Surface3DController::Surface3DController(QRect rect) m_renderer(0), m_selectedPoint(invalidSelectionPosition()), m_selectedSeries(0), - m_rowsChangeStartId(0), - m_rowsChangeCount(0), m_flatShadingSupported(true) { // Setting a null axis creates a new default axis according to orientation and graph type. @@ -84,8 +82,15 @@ void Surface3DController::synchDataToRenderer() } if (m_changeTracker.rowsChanged) { - m_renderer->updateRows(m_rowsChangeStartId, m_rowsChangeCount); + m_renderer->updateRows(m_changedRows); m_changeTracker.rowsChanged = false; + m_changedRows.clear(); + } + + if (m_changeTracker.itemChanged) { + m_renderer->updateItem(m_changedItems); + m_changeTracker.itemChanged = false; + m_changedItems.clear(); } if (m_changeTracker.selectedPointChanged) { @@ -320,16 +325,57 @@ void Surface3DController::handleFlatShadingSupportedChange(bool supported) void Surface3DController::handleRowsChanged(int startIndex, int count) { QSurfaceDataProxy *sender = static_cast<QSurfaceDataProxy *>(QObject::sender()); + if (m_changedRows.size() == 0) + m_changedRows.reserve(sender->rowCount()); + if (static_cast<QSurface3DSeries *>(m_seriesList.at(0)) == sender->series()) { // Change is for the visible series, put the change to queue - m_rowsChangeStartId = startIndex; - m_rowsChangeCount = count; - m_changeTracker.rowsChanged = true; + 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; + } + } + if (newItem) + m_changedRows.append(candidate); + } + if (m_changedRows.size()) { + m_changeTracker.rowsChanged = true; - adjustValueAxisRange(); - // Clear selection unless still valid - setSelectedPoint(m_selectedPoint, m_selectedSeries); - emitNeedRender(); + adjustValueAxisRange(); + // Clear selection unless still valid + setSelectedPoint(m_selectedPoint, m_selectedSeries); + emitNeedRender(); + } + } +} + +void Surface3DController::handleItemChanged(int rowIndex, int columnIndex) +{ + QSurfaceDataProxy *sender = static_cast<QSurfaceDataProxy *>(QObject::sender()); + if (static_cast<QSurface3DSeries *>(m_seriesList.at(0)) == sender->series()) { + // 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); + emitNeedRender(); + } } } diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h index b9bd60a1..c7496c18 100644 --- a/src/datavisualization/engine/surface3dcontroller_p.h +++ b/src/datavisualization/engine/surface3dcontroller_p.h @@ -45,13 +45,15 @@ struct Surface3DChangeBitField { bool surfaceGridChanged : 1; bool selectedPointChanged : 1; bool rowsChanged : 1; + bool itemChanged : 1; Surface3DChangeBitField() : gradientColorChanged(false), // Set to false, as it is initially set in theme smoothStatusChanged(true), surfaceGridChanged(true), selectedPointChanged(true), - rowsChanged(true) + rowsChanged(false), + itemChanged(false) { } }; @@ -67,9 +69,9 @@ private: QPoint m_selectedPoint; QSurface3DSeries *m_selectedSeries; // Points to the series for which the point is selected in // single series selection cases. - int m_rowsChangeStartId; - int m_rowsChangeCount; bool m_flatShadingSupported; + QVector<QPoint> m_changedItems; + QVector<int> m_changedRows; public: explicit Surface3DController(QRect rect); @@ -100,6 +102,7 @@ public: public slots: void handleArrayReset(); void handleRowsChanged(int startIndex, int count); + void handleItemChanged(int rowIndex, int columnIndex); // Renderer callback handlers void handlePointClicked(const QPoint &position, QSurface3DSeries *series); diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index 4942c4ae..81da15da 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -285,14 +285,8 @@ void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesLis } } -void Surface3DRenderer::updateRows(int startIndex, int count) +void Surface3DRenderer::updateRows(const QVector<int> &rows) { - // TODO: Properly support non-straight rows and columns (QTRD-2643) - if (startIndex > m_sampleSpace.height()) { - // No changes on visible area - return; - } - // Surface only supports single series for now, so we are only interested in the first series const QSurfaceDataArray *array = 0; if (m_visibleSeriesList.size()) { @@ -306,22 +300,68 @@ void Surface3DRenderer::updateRows(int startIndex, int count) if (array && array->size() >= 2 && array->at(0)->size() >= 2 && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) { - int endRow = startIndex + count; - if (endRow > m_sampleSpace.height()) - endRow = m_sampleSpace.height(); + bool updateBuffers = false; + int sampleSpaceTop = m_sampleSpace.y() + m_sampleSpace.height(); + foreach (int row, rows) { + if (row >= m_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()); + + if (m_cachedFlatShading) { + m_surfaceObj->updateCoarseRow(m_dataArray, row - m_sampleSpace.y(), m_heightNormalizer, + m_axisCacheY.min()); + } else { + m_surfaceObj->updateSmoothRow(m_dataArray, row - m_sampleSpace.y(), m_heightNormalizer, + m_axisCacheY.min()); + } + } + } + if (updateBuffers) + m_surfaceObj->uploadBuffers(); + } + + updateSelectedPoint(m_selectedPoint, m_selectedSeries); +} - for (int i = startIndex; i < endRow; i++) { - for (int j = 0; j < m_sampleSpace.width(); j++) - (*(m_dataArray.at(i)))[j] = array->at(i + m_sampleSpace.y())->at(j + m_sampleSpace.x()); +void Surface3DRenderer::updateItem(const QVector<QPoint> &points) +{ + // TODO: Properly support non-straight rows and columns (QTRD-2643) + + // 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()); + if (m_cachedSurfaceGridOn || m_cachedSurfaceVisible) { + QSurfaceDataProxy *dataProxy = firstSeries->dataProxy(); + if (dataProxy) + array = dataProxy->array(); } + } - if (!m_cachedFlatShading) { - m_surfaceObj->updateSmoothRows(m_dataArray, startIndex, endRow, m_heightNormalizer, - m_axisCacheY.min()); - } else { - m_surfaceObj->updateCoarseRows(m_dataArray, startIndex, endRow, m_heightNormalizer, - m_axisCacheY.min()); + 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()) { + 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()); + + if (m_cachedFlatShading) { + m_surfaceObj->updateCoarseItem(m_dataArray, y, x, m_heightNormalizer, m_axisCacheY.min()); + } else { + m_surfaceObj->updateSmoothItem(m_dataArray, y, x, m_heightNormalizer, m_axisCacheY.min()); + } + } } + if (updateBuffers) + m_surfaceObj->uploadBuffers(); } updateSelectedPoint(m_selectedPoint, m_selectedSeries); diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index 476ef78e..37adb0b9 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -135,7 +135,8 @@ public: void updateData(); void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility); - void updateRows(int startIndex, int count); + void updateRows(const QVector<int> &rows); + void updateItem(const QVector<QPoint> &points); void updateScene(Q3DScene *scene); bool updateFlatStatus(bool enable); void updateSurfaceGridStatus(bool enable); diff --git a/src/datavisualization/utils/surfaceobject.cpp b/src/datavisualization/utils/surfaceobject.cpp index 81945900..ca23482a 100644 --- a/src/datavisualization/utils/surfaceobject.cpp +++ b/src/datavisualization/utils/surfaceobject.cpp @@ -120,8 +120,8 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR createBuffers(m_vertices, uvs, m_normals, 0, changeGeometry); } -void SurfaceObject::updateSmoothRows(const QSurfaceDataArray &dataArray, int startRow, - int endRow, GLfloat yRange, GLfloat yMin) +void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowIndex, + GLfloat yRange, GLfloat yMin) { GLfloat xMin = dataArray.at(0)->at(0).x(); GLfloat zMin = dataArray.at(0)->at(0).z(); @@ -130,64 +130,114 @@ void SurfaceObject::updateSmoothRows(const QSurfaceDataArray &dataArray, int sta GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f; // Update vertices - int totalIndex = startRow * m_columns; - for (int i = startRow; i < endRow; i++) { - const QSurfaceDataRow &p = *dataArray.at(i); - for (int j = 0; j < m_columns; j++) { - const QSurfaceDataItem &data = p.at(j); - float normalizedX = ((data.x() - xMin) / xNormalizer); - float normalizedY = ((data.y() - yMin) / yNormalizer); - float normalizedZ = ((data.z() - zMin) / zNormalizer); - m_vertices[totalIndex++] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f); - } + int p = rowIndex * m_columns; + const QSurfaceDataRow &dataRow = *dataArray.at(rowIndex); + for (int j = 0; j < m_columns; j++) { + const QSurfaceDataItem &data = dataRow.at(j); + float normalizedX = ((data.x() - xMin) / xNormalizer); + float normalizedY = ((data.y() - yMin) / yNormalizer); + float normalizedZ = ((data.z() - zMin) / zNormalizer); + m_vertices[p++] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f); } // Create normals int colLimit = m_columns - 1; - int rowColLimit = endRow * m_columns; - if (endRow == m_rows) - rowColLimit = (endRow - 1) * m_columns; - int totalLimit = endRow * m_columns - 1; - - totalIndex = startRow * m_columns; - if (startRow > 0) { - // Change the normals for the previous row also - totalIndex -= m_columns; - } - if (totalIndex < (m_rows - 1) * m_columns) { - for (int row = totalIndex; row < rowColLimit; row += m_columns) { - for (int j = 0; j < colLimit; j++) { - // One right and one up - m_normals[totalIndex++] = normal(m_vertices.at(row + j), - m_vertices.at(row + j + 1), - m_vertices.at(row + m_columns + j)); - } - int p = row + colLimit; - // One up and one left - m_normals[totalIndex++] = normal(m_vertices.at(p), - m_vertices.at(p + m_columns), - m_vertices.at(p - 1)); + int startRow = rowIndex; + if (startRow > 0) + startRow--; + int totalIndex = startRow * m_columns; + int rowLimit = (rowIndex + 1) * m_columns; + if (rowIndex == m_rows - 1) + rowLimit = rowIndex * m_columns; // The rowIndex is top most row, special handling + + for (int row = totalIndex; row < rowLimit; row += m_columns) { + for (int j = 0; j < colLimit; j++) { + // One right and one up + m_normals[totalIndex++] = normal(m_vertices.at(row + j), + m_vertices.at(row + j + 1), + m_vertices.at(row + m_columns + j)); } + int p = row + colLimit; + // One up and one left + m_normals[totalIndex++] = normal(m_vertices.at(p), + m_vertices.at(p + m_columns), + m_vertices.at(p - 1)); } - if (endRow == m_rows) { + if (rowIndex == m_rows - 1) { // Top most line, nothing above, must have different handling. // Take from one down and one right. Read till second-to-last - for (int j = rowColLimit; j < totalLimit; j++) { + rowLimit = (rowIndex + 1) * m_columns - 1; + for (int j = rowIndex * m_columns; j < rowLimit; j++) { m_normals[totalIndex++] = normal(m_vertices.at(j), m_vertices.at(j - m_columns), m_vertices.at(j + 1)); } // Top left corner. Take from one left and one down - m_normals[totalIndex++] = normal(m_vertices.at(totalLimit), - m_vertices.at(totalLimit - 1), - m_vertices.at(totalLimit - m_columns)); + m_normals[totalIndex++] = normal(m_vertices.at(rowLimit), + m_vertices.at(rowLimit - 1), + m_vertices.at(rowLimit - m_columns)); } +} - QVector<QVector2D> uvs; // Empty dummy - createBuffers(m_vertices, uvs, m_normals, 0, false); +void SurfaceObject::updateSmoothItem(const QSurfaceDataArray &dataArray, int row, + int column, GLfloat yRange, GLfloat yMin) +{ + GLfloat xMin = dataArray.at(0)->at(0).x(); + GLfloat zMin = dataArray.at(0)->at(0).z(); + GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f; + GLfloat yNormalizer = yRange / 2.0f; + GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f; + + // Update a vertice + const QSurfaceDataItem &data = dataArray.at(row)->at(column); + float normalizedX = ((data.x() - xMin) / xNormalizer); + float normalizedY = ((data.y() - yMin) / yNormalizer); + float normalizedZ = ((data.z() - zMin) / zNormalizer); + m_vertices[row * m_columns + column] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f); + + // Create normals + int startRow = row; + if (startRow > 0) + startRow--; // Change the normal for previous row also + int startCol = column; + if (startCol > 0) + startCol--; + + for (int i = startRow; i <= row; i++) { + for (int j = startCol; j <= column; j++) { + int p = i * m_columns + j; + if (i < m_rows) { + if (j < m_columns) { + // One right and one up + m_normals[p] = normal(m_vertices.at(p), + m_vertices.at(p + 1), + m_vertices.at(p + m_columns)); + } else { + // Last item, nothing on the right. One up and one left + m_normals[p] = normal(m_vertices.at(p), + m_vertices.at(p + m_columns), + m_vertices.at(p - 1)); + } + } else { + // Top most line, nothing above, must have different handling. + if (j < m_columns) { + // Take from one down and one right. Read till second-to-last + m_normals[p] = normal(m_vertices.at(p), + m_vertices.at(j - m_columns), + m_vertices.at(j + 1)); + } else { + // Top left corner. Take from one left and one down + m_normals[p] = normal(m_vertices.at(p), + m_vertices.at(p - 1), + m_vertices.at(p - m_columns)); + } + } + } + } } + void SurfaceObject::createSmoothIndices(int x, int y, int endX, int endY) { if (endX >= m_columns) @@ -364,8 +414,8 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s delete[] indices; } -void SurfaceObject::updateCoarseRows(const QSurfaceDataArray &dataArray, int startRow, - int endRow, GLfloat yRange, GLfloat yMin) +void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex, + GLfloat yRange, GLfloat yMin) { GLfloat xMin = dataArray.at(0)->at(0).x(); GLfloat zMin = dataArray.at(0)->at(0).z(); @@ -375,47 +425,95 @@ void SurfaceObject::updateCoarseRows(const QSurfaceDataArray &dataArray, int sta int colLimit = m_columns - 1; int doubleColumns = m_columns * 2 - 2; - int totalIndex = startRow * doubleColumns; - for (int i = startRow; i < endRow; i++) { - const QSurfaceDataRow &row = *dataArray.at(i); - for (int j = 0; j < m_columns; j++) { - const QSurfaceDataItem &data = row.at(j); - float normalizedX = ((data.x() - xMin) / xNormalizer); - float normalizedY = ((data.y() - yMin) / yNormalizer); - float normalizedZ = ((data.z() - zMin) / zNormalizer); - m_vertices[totalIndex++] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f); - - if (j > 0 && j < colLimit) { - m_vertices[totalIndex] = m_vertices[totalIndex - 1]; - totalIndex++; - } + int p = rowIndex * doubleColumns; + const QSurfaceDataRow &dataRow = *dataArray.at(rowIndex); + for (int j = 0; j < m_columns; j++) { + const QSurfaceDataItem &data = dataRow.at(j); + float normalizedX = ((data.x() - xMin) / xNormalizer); + float normalizedY = ((data.y() - yMin) / yNormalizer); + float normalizedZ = ((data.z() - zMin) / zNormalizer); + m_vertices[p++] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f); + + if (j > 0 && j < colLimit) { + m_vertices[p] = m_vertices[p - 1]; + p++; } } // Create normals - if (startRow > 0) - startRow--; - totalIndex = startRow * doubleColumns; - int rowColLimit = startRow * doubleColumns; - for (int row = totalIndex, upperRow = totalIndex + doubleColumns; - row <= rowColLimit; + p = rowIndex * doubleColumns; + if (p > 0) + p -= doubleColumns; + int rowLimit = (rowIndex + 1) * doubleColumns; + for (int row = p, upperRow = p + doubleColumns; + row < rowLimit; row += doubleColumns, upperRow += doubleColumns) { for (int j = 0; j < doubleColumns; j += 2) { // Normal for the left triangle - m_normals[totalIndex++] = normal(m_vertices.at(row + j), - m_vertices.at(row + j + 1), - m_vertices.at(upperRow + j)); + m_normals[p++] = normal(m_vertices.at(row + j), + m_vertices.at(row + j + 1), + m_vertices.at(upperRow + j)); // Normal for the right triangle - m_normals[totalIndex++] = normal(m_vertices.at(row + j + 1), - m_vertices.at(upperRow + j + 1), - m_vertices.at(upperRow + j)); + m_normals[p++] = normal(m_vertices.at(row + j + 1), + m_vertices.at(upperRow + j + 1), + m_vertices.at(upperRow + j)); } } +} - QVector<QVector2D> uvs; // Empty dummy - createBuffers(m_vertices, uvs, m_normals, 0, false); +void SurfaceObject::updateCoarseItem(const QSurfaceDataArray &dataArray, int row, + int column, GLfloat yRange, GLfloat yMin) +{ + GLfloat xMin = dataArray.at(0)->at(0).x(); + GLfloat zMin = dataArray.at(0)->at(0).z(); + GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f; + GLfloat yNormalizer = yRange / 2.0f; + GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f; + + int colLimit = m_columns - 1; + int doubleColumns = m_columns * 2 - 2; + + // Update a vertice + int p = row * doubleColumns + column * 2 - (column > 0); + const QSurfaceDataItem &data = dataArray.at(row)->at(column); + float normalizedX = ((data.x() - xMin) / xNormalizer); + float normalizedY = ((data.y() - yMin) / yNormalizer); + float normalizedZ = ((data.z() - zMin) / zNormalizer); + m_vertices[p] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f); + p++; + + if (column > 0 && column < colLimit) + m_vertices[p] = m_vertices[p - 1]; + + // Create normals + int startRow = row; + if (startRow > 0) + startRow--; // Change the normal for previous row also + int startCol = column; + if (startCol > 0) + startCol--; + if (row == m_rows - 1) + row--; + if (column == m_columns - 1) + column--; + + for (int i = startRow; i <= row; i++) { + for (int j = startCol; j <= column; j++) { + p = i * doubleColumns + j * 2; + // Normal for the left triangle + m_normals[p] = normal(m_vertices.at(p), + m_vertices.at(p + 1), + m_vertices.at(p + doubleColumns)); + p++; + + // Normal for the right triangle + m_normals[p] = normal(m_vertices.at(p), + m_vertices.at(p + doubleColumns), + m_vertices.at(p + doubleColumns - 1)); + } + } } void SurfaceObject::createCoarseIndices(int x, int y, int columns, int rows) @@ -511,6 +609,12 @@ void SurfaceObject::createCoarseGridlineIndices(int x, int y, int endX, int endY delete[] gridIndices; } +void SurfaceObject::uploadBuffers() +{ + QVector<QVector2D> uvs; // Empty dummy + createBuffers(m_vertices, uvs, m_normals, 0, false); +} + void SurfaceObject::createBuffers(const QVector<QVector3D> &vertices, const QVector<QVector2D> &uvs, const QVector<QVector3D> &normals, const GLint *indices, bool changeGeometry) diff --git a/src/datavisualization/utils/surfaceobject_p.h b/src/datavisualization/utils/surfaceobject_p.h index 895fd3eb..e035d905 100644 --- a/src/datavisualization/utils/surfaceobject_p.h +++ b/src/datavisualization/utils/surfaceobject_p.h @@ -48,14 +48,19 @@ public: GLfloat yMin, bool changeGeometry); void setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space, GLfloat yRange, GLfloat yMin, bool changeGeometry); - void updateCoarseRows(const QSurfaceDataArray &dataArray, int startRow, - int endRow, GLfloat yRange, GLfloat yMin); - void updateSmoothRows(const QSurfaceDataArray &dataArray, int startRow, - int endRow, GLfloat yRange, GLfloat yMin); + void updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex, + GLfloat yRange, GLfloat yMin); + void updateSmoothRow(const QSurfaceDataArray &dataArray, int startRow, + GLfloat yRange, GLfloat yMin); + void updateSmoothItem(const QSurfaceDataArray &dataArray, int row, + int column, GLfloat yRange, GLfloat yMin); + void updateCoarseItem(const QSurfaceDataArray &dataArray, int row, + int column, GLfloat yRange, GLfloat yMin); void createSmoothIndices(int x, int y, int endX, int endY); void createCoarseIndices(int x, int y, int columns, int rows); void createSmoothGridlineIndices(int x, int y, int endX, int endY); void createCoarseGridlineIndices(int x, int y, int endX, int endY); + void uploadBuffers(); GLuint gridElementBuf(); GLuint gridIndexCount(); QVector3D vertexAt(int column, int row); |