diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-09-26 11:16:12 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-09-27 08:05:12 +0300 |
commit | f2a5c09144f17f3240ae6a7e7b48237f1b234d9b (patch) | |
tree | 28f40212cd228f66277e8db84885ddef0ebb6c5a /src/datavisualization | |
parent | b776b6d3aa287b973c9346736badc6181e50cbc7 (diff) |
Allow resetting with existing array for surface
Improves performance when doing stuff like resetting image data.
Task-number: QTRD-2335
Change-Id: I9e8ce49fd520b67125305a7614afc550b2244169
Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Diffstat (limited to 'src/datavisualization')
-rw-r--r-- | src/datavisualization/data/qheightmapsurfacedataproxy.cpp | 27 | ||||
-rw-r--r-- | src/datavisualization/data/qsurfacedataproxy.cpp | 52 | ||||
-rw-r--r-- | src/datavisualization/data/qsurfacedataproxy_p.h | 6 | ||||
-rw-r--r-- | src/datavisualization/data/surfaceitemmodelhandler.cpp | 43 | ||||
-rw-r--r-- | src/datavisualization/data/surfaceitemmodelhandler_p.h | 1 | ||||
-rw-r--r-- | src/datavisualization/engine/surface3drenderer.cpp | 54 | ||||
-rw-r--r-- | src/datavisualization/utils/surfaceobject.cpp | 272 | ||||
-rw-r--r-- | src/datavisualization/utils/surfaceobject_p.h | 8 |
8 files changed, 239 insertions, 224 deletions
diff --git a/src/datavisualization/data/qheightmapsurfacedataproxy.cpp b/src/datavisualization/data/qheightmapsurfacedataproxy.cpp index 25e2a4db..c0b0723c 100644 --- a/src/datavisualization/data/qheightmapsurfacedataproxy.cpp +++ b/src/datavisualization/data/qheightmapsurfacedataproxy.cpp @@ -206,28 +206,35 @@ void QHeightMapSurfaceDataProxyPrivate::handlePendingResolve() int widthBits = imageWidth * 4; qreal height = 0; - QSurfaceDataArray *dataArray = new QSurfaceDataArray; - dataArray->reserve(imageHeight); + // Do not recreate array if dimensions have not changed + QSurfaceDataArray *dataArray = m_dataArray; + if (imageWidth != qptr()->columnCount() || imageHeight != dataArray->size()) { + dataArray = new QSurfaceDataArray; + dataArray->reserve(imageHeight); + for (int i = 0; i < imageHeight; i++) { + QSurfaceDataRow *newProxyRow = new QSurfaceDataRow(imageWidth); + dataArray->append(newProxyRow); + } + } + if (heightImage.isGrayscale()) { // Grayscale, it's enough to read Red byte - for (int i = imageHeight; i > 0; i--, bitCount -= widthBits) { - QSurfaceDataRow *newRow = new QSurfaceDataRow(imageWidth); + for (int i = 0; i < imageHeight; i++, bitCount -= widthBits) { + QSurfaceDataRow &newRow = *dataArray->at(i); for (int j = 0; j < imageWidth; j++) - (*newRow)[j] = qreal(bits[bitCount + (j * 4)]); - *dataArray << newRow; + newRow[j] = qreal(bits[bitCount + (j * 4)]); } } else { // Not grayscale, we'll need to calculate height from RGB - for (int i = imageHeight; i > 0; i--, bitCount -= widthBits) { - QSurfaceDataRow *newRow = new QSurfaceDataRow(imageWidth); + for (int i = 0; i < imageHeight; i++, bitCount -= widthBits) { + QSurfaceDataRow &newRow = *dataArray->at(i); for (int j = 0; j < imageWidth; j++) { int nextpixel = j * 4; height = (qreal(bits[bitCount + nextpixel]) + qreal(bits[1 + bitCount + nextpixel]) + qreal(bits[2 + bitCount + nextpixel])); - (*newRow)[j] = (height / 3.0); + newRow[j] = height / 3.0; } - *dataArray << newRow; } } diff --git a/src/datavisualization/data/qsurfacedataproxy.cpp b/src/datavisualization/data/qsurfacedataproxy.cpp index 1a2e29ce..98998f10 100644 --- a/src/datavisualization/data/qsurfacedataproxy.cpp +++ b/src/datavisualization/data/qsurfacedataproxy.cpp @@ -143,23 +143,29 @@ QSurfaceDataProxy::~QSurfaceDataProxy() } /*! - * Clears the existing array and takes ownership of the \a newArray. Do not use \a newArray pointer - * to further modify data after QSurfaceDataProxy assumes ownership of it, as such modifications will - * not trigger proper signals. - * Passing null array clears all data. - * Row and column ranges are reset to defaults. + * Takes ownership of the \a newArray. Clears the existing array and if the \a newArray is + * different than the existing array. If it's the same array, this just triggers arrayReset() + * signal. + * Passing null array deletes the old array and creates a new empty array. + * All rows in \a newArray must be of same length. + * Row and column ranges are reset to defaults, unless \a newArray is the same as the old array. + * In that case, old row and column ranges are kept. */ void QSurfaceDataProxy::resetArray(QSurfaceDataArray *newArray) { - if (dptr()->resetArray(newArray, defaultMinValue, defaultMaxValue, defaultMinValue, defaultMaxValue)) - emit arrayReset(); + if (dptr()->m_dataArray != newArray) { + dptr()->resetArray(newArray, defaultMinValue, defaultMaxValue, defaultMinValue, + defaultMaxValue); + } + emit arrayReset(); } /*! - * Clears the existing array and takes ownership of the \a newArray. Do not use \a newArray pointer - * to further modify data after QSurfaceDataProxy assumes ownership of it, as such modifications will - * not trigger proper signals. - * Passing null array clears all data. + * Takes ownership of the \a newArray. Clears the existing array and if the \a newArray is + * different than the existing array. If it's the same array, this just triggers arrayReset() + * signal and updates row/column values. + * Passing null array deletes the old array and creates a new empty array. + * All rows in \a newArray must be of same length. * Row and column ranges are set to values defined by the rest of the parameters: \a minValueRows, * \a maxValueRows, \a minValueColumns, and \a maxValueColumns. */ @@ -167,8 +173,8 @@ void QSurfaceDataProxy::resetArray(QSurfaceDataArray *newArray, qreal minValueRo qreal maxValueRows, qreal minValueColumns, qreal maxValueColumns) { - if (dptr()->resetArray(newArray, minValueRows, maxValueRows, minValueColumns, maxValueColumns)) - emit arrayReset(); + dptr()->resetArray(newArray, minValueRows, maxValueRows, minValueColumns, maxValueColumns); + emit arrayReset(); } /*! @@ -346,30 +352,20 @@ QSurfaceDataProxyPrivate::~QSurfaceDataProxyPrivate() clearArray(); } -bool QSurfaceDataProxyPrivate::resetArray(QSurfaceDataArray *newArray, qreal minValueRows, +void QSurfaceDataProxyPrivate::resetArray(QSurfaceDataArray *newArray, qreal minValueRows, qreal maxValueRows, qreal minValueColumns, qreal maxValueColumns) { - if (!m_dataArray->size() && (!newArray || !newArray->size())) - return false; - - clearArray(); + if (!newArray) + newArray = new QSurfaceDataArray; - if (newArray) { - for (int i = 0; i < newArray->size(); i++) { - Q_ASSERT_X((newArray->at(i) && newArray->at(i)->size() == newArray->at(0)->size()), - __FUNCTION__, - "All rows of QSurfaceDataArray mustn't be NULL and must be of equal size."); - } + if (newArray != m_dataArray) { + clearArray(); m_dataArray = newArray; - } else { - m_dataArray = new QSurfaceDataArray; } setValueRangeRows(minValueRows, maxValueRows); setValueRangeColumns(minValueColumns, maxValueColumns); - - return true; } void QSurfaceDataProxyPrivate::setValueRangeRows(qreal min, qreal max) diff --git a/src/datavisualization/data/qsurfacedataproxy_p.h b/src/datavisualization/data/qsurfacedataproxy_p.h index 8a60e93d..a40e8d65 100644 --- a/src/datavisualization/data/qsurfacedataproxy_p.h +++ b/src/datavisualization/data/qsurfacedataproxy_p.h @@ -43,7 +43,7 @@ public: QSurfaceDataProxyPrivate(QSurfaceDataProxy *q); virtual ~QSurfaceDataProxyPrivate(); - bool resetArray(QSurfaceDataArray *newArray, qreal minValueRows, qreal maxValueRows, + void resetArray(QSurfaceDataArray *newArray, qreal minValueRows, qreal maxValueRows, qreal minValueColumns, qreal maxValueColumns); void setValueRangeRows(qreal min, qreal max); @@ -58,12 +58,14 @@ public: void limitValues(QVector3D &minValues, QVector3D &maxValues); +protected: + QSurfaceDataArray *m_dataArray; + private: QSurfaceDataProxy *qptr(); void clearRow(int rowIndex); void clearArray(); - QSurfaceDataArray *m_dataArray; qreal m_minValueRows; qreal m_maxValueRows; qreal m_minValueColumns; diff --git a/src/datavisualization/data/surfaceitemmodelhandler.cpp b/src/datavisualization/data/surfaceitemmodelhandler.cpp index bc85847c..d32b442b 100644 --- a/src/datavisualization/data/surfaceitemmodelhandler.cpp +++ b/src/datavisualization/data/surfaceitemmodelhandler.cpp @@ -23,7 +23,8 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE SurfaceItemModelHandler::SurfaceItemModelHandler(QItemModelSurfaceDataProxy *proxy, QObject *parent) : AbstractItemModelHandler(parent), - m_proxy(proxy) + m_proxy(proxy), + m_proxyArray(0) { } @@ -51,7 +52,6 @@ void SurfaceItemModelHandler::resolveModel() float minColumnValue = 0.0f; float maxColumnValue = 1.0f; - QSurfaceDataArray *newProxyArray = new QSurfaceDataArray; QHash<int, QByteArray> roleHash = m_itemModel->roleNames(); // Default to display role if no mapping @@ -60,11 +60,20 @@ void SurfaceItemModelHandler::resolveModel() int columnCount = m_itemModel->columnCount(); if (mapping->useModelCategories()) { + // If dimensions have changed, recreate the array + if (!m_proxyArray || columnCount != m_proxy->columnCount() + || rowCount != m_proxyArray->size()) { + m_proxyArray = new QSurfaceDataArray; + m_proxyArray->reserve(rowCount); + for (int i = 0; i < rowCount; i++) { + QSurfaceDataRow *newProxyRow = new QSurfaceDataRow(columnCount); + m_proxyArray->append(newProxyRow); + } + } for (int i = 0; i < rowCount; i++) { - QSurfaceDataRow *newProxyRow = new QSurfaceDataRow(columnCount); + QSurfaceDataRow &newProxyRow = *m_proxyArray->at(i); for (int j = 0; j < columnCount; j++) - (*newProxyRow)[j] = m_itemModel->index(i, j).data(valueRole).toReal(); - newProxyArray->append(newProxyRow); + newProxyRow[j] = m_itemModel->index(i, j).data(valueRole).toReal(); } if (rowCount) { minRowValue = m_itemModel->headerData(0, Qt::Vertical).toFloat(); @@ -118,12 +127,22 @@ void SurfaceItemModelHandler::resolveModel() else columnList = mapping->columnCategories(); - // Create new data array from itemValueMap - foreach (QString rowKey, rowList) { - QSurfaceDataRow *newProxyRow = new QSurfaceDataRow(columnList.size()); - for (int i = 0; i < columnList.size(); i++) - (*newProxyRow)[i] = itemValueMap[rowKey][columnList.at(i)]; - newProxyArray->append(newProxyRow); + // If dimensions have changed, recreate the array + if (!m_proxyArray || columnList.size() != m_proxy->columnCount() + || rowList.size() != m_proxyArray->size()) { + m_proxyArray = new QSurfaceDataArray; + m_proxyArray->reserve(rowList.size()); + for (int i = 0; i < rowList.size(); i++) { + QSurfaceDataRow *newProxyRow = new QSurfaceDataRow(columnList.size()); + m_proxyArray->append(newProxyRow); + } + } + // Create data array from itemValueMap + for (int i = 0; i < rowList.size(); i++) { + QString rowKey = rowList.at(i); + QSurfaceDataRow &newProxyRow = *m_proxyArray->at(i); + for (int j = 0; j < columnList.size(); j++) + newProxyRow[j] = itemValueMap[rowKey][columnList.at(j)]; } // Use first and last roles converted to values for limits @@ -137,7 +156,7 @@ void SurfaceItemModelHandler::resolveModel() } } - m_proxy->resetArray(newProxyArray, minRowValue, maxRowValue, minColumnValue, maxColumnValue); + m_proxy->resetArray(m_proxyArray, minRowValue, maxRowValue, minColumnValue, maxColumnValue); } QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/surfaceitemmodelhandler_p.h b/src/datavisualization/data/surfaceitemmodelhandler_p.h index 045ac379..bcf642c5 100644 --- a/src/datavisualization/data/surfaceitemmodelhandler_p.h +++ b/src/datavisualization/data/surfaceitemmodelhandler_p.h @@ -45,6 +45,7 @@ protected: void virtual resolveModel(); QItemModelSurfaceDataProxy *m_proxy; // Not owned + QSurfaceDataArray *m_proxyArray; // Not owned }; QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index 0c234910..25a6a519 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -203,10 +203,6 @@ void Surface3DRenderer::initializeOpenGL() void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy) { - for (int i = 0; i < m_dataArray.size(); i++) - delete m_dataArray.at(i); - m_dataArray.clear(); - calculateSceneScalingFactors(); const QSurfaceDataArray *array = dataProxy->array(); @@ -219,17 +215,22 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy) if (m_sampleSpace != sampleSpace) { dimensionChanged = true; m_sampleSpace = sampleSpace; + + for (int i = 0; i < m_dataArray.size(); i++) + delete m_dataArray.at(i); + m_dataArray.clear(); } // TODO: Handle partial surface grids on the graph edges if (sampleSpace.width() >= 2 && sampleSpace.height() >= 2) { - m_dataArray.reserve(sampleSpace.height()); + if (dimensionChanged) { + m_dataArray.reserve(sampleSpace.height()); + for (int i = 0; i < sampleSpace.height(); i++) + m_dataArray << new QSurfaceDataRow(sampleSpace.width()); + } for (int i = 0; i < sampleSpace.height(); i++) { - QSurfaceDataRow *newRow = new QSurfaceDataRow(); - newRow->resize(sampleSpace.width()); for (int j = 0; j < sampleSpace.width(); j++) - (*newRow)[j] = array->at(i + sampleSpace.y())->at(j + sampleSpace.x()); - m_dataArray << newRow; + (*(m_dataArray.at(i)))[j] = array->at(i + sampleSpace.y())->at(j + sampleSpace.x()); } if (m_dataArray.size() > 0) { @@ -237,10 +238,15 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy) loadSurfaceObj(); // Note: Data setup can change samplespace (as min width/height is 1) - if (m_cachedSmoothSurface) - m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer, dimensionChanged); - else - m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer, dimensionChanged); + if (m_cachedSmoothSurface) { + m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer, + dimensionChanged, + m_cachedSelectionMode != QDataVis::ModeNone); + } else { + m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer, + dimensionChanged, + m_cachedSelectionMode != QDataVis::ModeNone); + } if (dimensionChanged) updateSelectionTexture(); @@ -285,10 +291,13 @@ void Surface3DRenderer::updateSliceDataModel(int selectionId) if (!m_sliceSurfaceObj) loadSliceSurfaceObj(); - if (m_cachedSmoothSurface) - m_sliceSurfaceObj->setUpSmoothData(m_sliceDataArray, sliceRect, m_heightNormalizer, true); - else - m_sliceSurfaceObj->setUpData(m_sliceDataArray, sliceRect, m_heightNormalizer, true); + if (m_cachedSmoothSurface) { + m_sliceSurfaceObj->setUpSmoothData(m_sliceDataArray, sliceRect, m_heightNormalizer, + true, true); + } else { + m_sliceSurfaceObj->setUpData(m_sliceDataArray, sliceRect, m_heightNormalizer, true, + true); + } } } @@ -1736,10 +1745,13 @@ bool Surface3DRenderer::updateSmoothStatus(bool enable) if (m_cachedSmoothSurface == false && !m_flatSupported) m_cachedSmoothSurface = true; - if (m_cachedSmoothSurface) - m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer, true); - else - m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer, true); + if (m_cachedSmoothSurface) { + m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer, true, + m_cachedSelectionMode != QDataVis::ModeNone); + } else { + m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer, true, + m_cachedSelectionMode != QDataVis::ModeNone); + } initSurfaceShaders(); diff --git a/src/datavisualization/utils/surfaceobject.cpp b/src/datavisualization/utils/surfaceobject.cpp index d28ad447..0f9bb7e0 100644 --- a/src/datavisualization/utils/surfaceobject.cpp +++ b/src/datavisualization/utils/surfaceobject.cpp @@ -30,66 +30,87 @@ SurfaceObject::SurfaceObject() { m_indicesType = GL_UNSIGNED_INT; initializeOpenGLFunctions(); + glGenBuffers(1, &m_vertexbuffer); + glGenBuffers(1, &m_normalbuffer); + glGenBuffers(1, &m_uvbuffer); + glGenBuffers(1, &m_elementbuffer); + glGenBuffers(1, &m_gridElementbuffer); } SurfaceObject::~SurfaceObject() { + glDeleteBuffers(1, &m_gridElementbuffer); } -void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space, GLfloat yRange, bool changeGeometry) +void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space, + GLfloat yRange, bool changeGeometry, bool needTexture) { int columns = space.width(); int rows = space.height(); + int totalSize = rows * columns; GLfloat width = (GLfloat(columns) - 1.0f) / 2.0f; GLfloat depth = (GLfloat(rows) - 1.0f) / -2.0f; GLfloat height = yRange / 2.0f; - // Create vertice table - QVector<QVector3D> vertices; + // Create/populate vertice table + if (changeGeometry) + m_vertices.resize(totalSize); + QVector<QVector2D> uvs; + if (needTexture) + uvs.resize(totalSize); float uvX = 1.0 / float(columns - 1); float uvY = 1.0 / float(rows - 1); - int row = 0; - for (float i = 0.0f; i < float(rows); i += 1.0, row += columns) { - for (float j = 0; j < columns; j++) { - vertices.append(QVector3D(j / width - 1.0f, - dataArray.at(int(i))->at(int(j)) / height - 1.0f, - i / depth + 1.0f)); - uvs.append(QVector2D(j * uvX, i * uvY)); + int totalIndex = 0; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < columns; j++) { + m_vertices[totalIndex] = QVector3D(float(j) / width - 1.0f, + float(dataArray.at(i)->at(j)) / height - 1.0f, + float(i) / depth + 1.0f); + if (needTexture) + uvs[totalIndex] = QVector2D(float(j) * uvX, float(i) * uvY); + totalIndex++; } } // Create normals - QVector<QVector3D> normals; - for (int row = 0; row < (rows - 1) * columns; row += columns) { - for (int j = 0; j < columns - 1; j++) { - normals.append(normal(vertices.at(row + j), - vertices.at(row + j + 1), - vertices.at(row + columns + j))); + int rowLimit = rows - 1; + int colLimit = columns - 1; + int rowColLimit = rowLimit * columns; + int totalLimit = totalSize - 1; + if (changeGeometry) + m_normals.resize(totalSize); + + totalIndex = 0; + for (int row = 0; row < rowColLimit; row += columns) { + for (int j = 0; j < colLimit; j++) { + m_normals[totalIndex++] = normal(m_vertices.at(row + j), + m_vertices.at(row + j + 1), + m_vertices.at(row + columns + j)); } - int p = row + columns - 1; - normals.append(normal(vertices.at(p), - vertices.at(p + columns), - vertices.at(p - 1))); + int p = row + colLimit; + m_normals[totalIndex++] = normal(m_vertices.at(p), + m_vertices.at(p + columns), + m_vertices.at(p - 1)); } - for (int j = (rows - 1) * columns ; j < rows * columns - 1; j++) { - normals.append(normal(vertices.at(j), - vertices.at(j - columns), - vertices.at(j + 1))); + for (int j = rowColLimit; j < totalLimit; j++) { + m_normals[totalIndex++] = normal(m_vertices.at(j), + m_vertices.at(j - columns), + m_vertices.at(j + 1)); } - int p = rows * columns - 1; - normals.append(normal(vertices.at(p), - vertices.at(p - 1), - vertices.at(p - columns - 1))); + int p = rows * colLimit; + m_normals[totalIndex++] = normal(m_vertices.at(p), + m_vertices.at(p - 1), + m_vertices.at(p - columns - 1)); // Create indices table GLint *indices = 0; if (changeGeometry) { - m_indexCount = 6 * (columns - 1) * (rows - 1); + m_indexCount = 6 * colLimit * rowLimit; indices = new GLint[m_indexCount]; p = 0; - for (int row = 0; row < (rows - 1) * columns; row += columns) { - for (int j = 0; j < columns - 1; j++) { + for (int row = 0; row < rowLimit * columns; row += columns) { + for (int j = 0; j < colLimit; j++) { // Left triangle indices[p++] = row + j + 1; indices[p++] = row + columns + j; @@ -106,16 +127,16 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR // Create line element indices GLint *gridIndices = 0; if (changeGeometry) { - m_gridIndexCount = 2 * columns * (rows - 1) + 2 * rows * (columns - 1); + m_gridIndexCount = 2 * columns * rowLimit + 2 * rows * colLimit; gridIndices = new GLint[m_gridIndexCount]; p = 0; for (int i = 0, row = 0; i < rows; i++, row += columns) { - for (int j = 0; j < columns - 1; j++) { + for (int j = 0; j < colLimit; j++) { gridIndices[p++] = row + j; gridIndices[p++] = row + j + 1; } } - for (int i = 0, row = 0; i < rows - 1; i++, row += columns) { + for (int i = 0, row = 0; i < rowLimit; i++, row += columns) { for (int j = 0; j < columns; j++) { gridIndices[p++] = row + j; gridIndices[p++] = row + j + columns; @@ -123,17 +144,19 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR } } - createBuffers(vertices, uvs, normals, indices, gridIndices, changeGeometry); + createBuffers(m_vertices, uvs, m_normals, indices, gridIndices, changeGeometry); delete[] indices; delete[] gridIndices; } -void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &space, GLfloat yRange, bool changeGeometry) +void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &space, + GLfloat yRange, bool changeGeometry, bool needTexture) { int columns = space.width(); int rows = space.height(); + int totalSize = rows * columns * 2; GLfloat width = (GLfloat(columns) - 1.0f) / 2.0f; GLfloat depth = (GLfloat(rows) - 1.0f) / -2.0f; GLfloat height = yRange / 2.0f; @@ -141,46 +164,63 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s float uvY = 1.0 / float(rows - 1); // Create vertice table - QVector<QVector3D> vertices; + if (changeGeometry) + m_vertices.resize(totalSize); + QVector<QVector2D> uvs; - int row = 0; - for (float i = 0.0f; i < float(rows); i += 1.0f, row += columns) { - for (float j = 0.0f; j < float(columns); j += 1.0f) { - vertices.append(QVector3D(j / width - 1.0f, - dataArray.at(int(i))->at(int(j)) / height - 1.0f, - i / depth + 1.0f)); - uvs.append(QVector2D(j * uvX, i * uvY)); - if (j > 0 && j < columns - 1) { - vertices.append(vertices.last()); - uvs.append(uvs.last()); + if (needTexture) + uvs.resize(totalSize); + + int totalIndex = 0; + int rowLimit = rows - 1; + int colLimit = columns - 1; + int doubleColumns = columns * 2 - 2; + int rowColLimit = rowLimit * doubleColumns; + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < columns; j++) { + m_vertices[totalIndex] = QVector3D(float(j) / width - 1.0f, + float(dataArray.at(i)->at(j)) / height - 1.0f, + float(i) / depth + 1.0f); + + if (needTexture) + uvs[totalIndex] = QVector2D(float(j) * uvX, float(i) * uvY); + + totalIndex++; + + if (j > 0 && j < colLimit) { + m_vertices[totalIndex] = m_vertices[totalIndex - 1]; + if (needTexture) + uvs[totalIndex] = uvs[totalIndex - 1]; + totalIndex++; } } } // Create normals & indices table - QVector<QVector3D> normals; - int doubleColumns = columns * 2 - 2; - GLint *indices = 0; int p = 0; if (changeGeometry) { - m_indexCount = 6 * (columns - 1) * (rows - 1); + int normalCount = 2 * colLimit * rowLimit; + m_indexCount = 3 * normalCount; indices = new GLint[m_indexCount]; + m_normals.resize(normalCount); } + totalIndex = 0; for (int row = 0, upperRow = doubleColumns; - row < (rows - 1) * doubleColumns; + row < rowColLimit; row += doubleColumns, upperRow += doubleColumns) { for (int j = 0; j < doubleColumns; j += 2) { // Normal for the left triangle - normals.append(normal(vertices.at(row + j), - vertices.at(row + j + 1), - vertices.at(upperRow + j))); + m_normals[totalIndex++] = normal(m_vertices.at(row + j), + m_vertices.at(row + j + 1), + m_vertices.at(upperRow + j)); // Normal for the right triangle - normals.append(normal(vertices.at(row + j + 1), - vertices.at(upperRow + j + 1), - vertices.at(upperRow + j))); + m_normals[totalIndex++] = normal(m_vertices.at(row + j + 1), + m_vertices.at(upperRow + j + 1), + m_vertices.at(upperRow + j)); if (changeGeometry) { // Left triangle @@ -197,79 +237,66 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s } // Create grid line element indices - m_gridIndexCount = 2 * columns * (rows - 1) + 2 * rows * (columns - 1); - GLint *gridIndices = new GLint[m_gridIndexCount]; - p = 0; - int rowLimit = (rows - 1) * doubleColumns; - for (int row = 0; row < rows * doubleColumns; row += doubleColumns) { - for (int j = 0; j < doubleColumns; j += 2) { - gridIndices[p++] = row + j; - gridIndices[p++] = row + j + 1; - - if (row < rowLimit) { + GLint *gridIndices = 0; + if (changeGeometry) { + m_gridIndexCount = 2 * columns * rowLimit + 2 * rows * colLimit; + gridIndices = new GLint[m_gridIndexCount]; + p = 0; + int fullRowLimit = rows * doubleColumns; + for (int row = 0; row < fullRowLimit; row += doubleColumns) { + for (int j = 0; j < doubleColumns; j += 2) { gridIndices[p++] = row + j; - gridIndices[p++] = row + j + doubleColumns; + gridIndices[p++] = row + j + 1; + + if (row < rowColLimit) { + gridIndices[p++] = row + j; + gridIndices[p++] = row + j + doubleColumns; + } } } - } - for (int i = doubleColumns - 1; i < rowLimit; i += doubleColumns) { - gridIndices[p++] = i; - gridIndices[p++] = i + doubleColumns; + for (int i = doubleColumns - 1; i < rowColLimit; i += doubleColumns) { + gridIndices[p++] = i; + gridIndices[p++] = i + doubleColumns; + } } - createBuffers(vertices, uvs, normals, indices, gridIndices, changeGeometry); + createBuffers(m_vertices, uvs, m_normals, indices, gridIndices, changeGeometry); delete[] indices; delete[] gridIndices; } void SurfaceObject::createBuffers(const QVector<QVector3D> &vertices, const QVector<QVector2D> &uvs, - const QVector<QVector3D> &normals, const GLint *indices, - const GLint *gridIndices, bool changeGeometry) + const QVector<QVector3D> &normals, const GLint *indices, + const GLint *gridIndices, bool changeGeometry) { - if (m_meshDataLoaded) { - // Delete old data - glDeleteBuffers(1, &m_vertexbuffer); - glDeleteBuffers(1, &m_normalbuffer); - if (changeGeometry) { - glDeleteBuffers(1, &m_uvbuffer); - glDeleteBuffers(1, &m_elementbuffer); - glDeleteBuffers(1, &m_gridElementbuffer); - } - } - // Move to buffers - glGenBuffers(1, &m_vertexbuffer); glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(QVector3D), - &vertices.at(0), GL_STATIC_DRAW); + &vertices.at(0), GL_DYNAMIC_DRAW); - glGenBuffers(1, &m_normalbuffer); glBindBuffer(GL_ARRAY_BUFFER, m_normalbuffer); glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(QVector3D), - &normals.at(0), GL_STATIC_DRAW); + &normals.at(0), GL_DYNAMIC_DRAW); if (changeGeometry) { - glGenBuffers(1, &m_uvbuffer); glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer); glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(QVector2D), &uvs.at(0), GL_STATIC_DRAW); - glGenBuffers(1, &m_elementbuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(GLint), indices, GL_STATIC_DRAW); - glGenBuffers(1, &m_gridElementbuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_gridElementbuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_gridIndexCount * sizeof(GLint), gridIndices, GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - // We're done. Set the flag ON m_meshDataLoaded = true; } @@ -293,56 +320,3 @@ QVector3D SurfaceObject::normal(const QVector3D &a, const QVector3D &b, const QV } QT_DATAVISUALIZATION_END_NAMESPACE - - - -// For rainy days - -// QVector3D vertices[] = { -// QVector3D(-0.5f, 0.0f, 0.1f), -// QVector3D(0.5f, 0.0f, 0.1f), -// QVector3D(0.0f, 1.0f, -0.5f) -// }; - -// QVector3D normals[] = { -// QVector3D(0.5, 0.0, 1.0), -// QVector3D(0.5, 0.0, 1.0), -// QVector3D(0.5, 0.0, 1.0) -// }; - -// vertices.append(QVector3D(-1.0f, 0.0f, 0.1f)); -// vertices.append(QVector3D(0.0f, 0.0f, 0.1f)); -// vertices.append(QVector3D(0.0f, 0.5f, -0.5f)); - -// normals.append(QVector3D(0.5, 0.0, 1.0)); -// normals.append(QVector3D(0.5, 0.0, 1.0)); -// normals.append(QVector3D(0.5, 0.0, 1.0)); - -//GLushort indices[] = {0, 1, 2, 1, 3, 2}; -//GLushort indices[] = {1, 3, 2}; - -//qDebug() << indices[p + 0] << ", " << indices[p + 1] << ", " << indices[p + 2]; -//qDebug() << indices[p + 3] << ", " << indices[p + 4] << ", " << indices[p + 5]; - -//qDebug() << "(" << float(j) / width << ", 0.0, " << float(i) / depth * -1.0f << ")"; - -//normals.append(QVector3D(1,0,0)); -//normals.append(QVector3D(0,1,0)); -//normals.append(QVector3D(0,0,1)); -//normals.append(QVector3D(1,0,1)); - -//normals.append(QVector3D(1,0,0)); -//normals.append(QVector3D(0,1,0)); -//normals.append(QVector3D(0,0,1)); -//normals.append(QVector3D(1,0,1)); - -//normals.append(QVector3D(1,0,0)); -//normals.append(QVector3D(0,1,0)); -//normals.append(QVector3D(0,0,1)); -//normals.append(QVector3D(1,0,1)); - - -//qDebug() << "Left normal from (" << row + j << ", " << row + j + 1 << ", " << row + doubleColumns + j << ")"; - -//qDebug() << "right normal from (" << row + j +1 << ", " << row + doubleColumns + j + 1 << ", " << row + doubleColumns + j << ")"; - diff --git a/src/datavisualization/utils/surfaceobject_p.h b/src/datavisualization/utils/surfaceobject_p.h index f19fffc0..0a52ca7c 100644 --- a/src/datavisualization/utils/surfaceobject_p.h +++ b/src/datavisualization/utils/surfaceobject_p.h @@ -44,8 +44,10 @@ public: SurfaceObject(); ~SurfaceObject(); - void setUpData(const QSurfaceDataArray &dataArray, const QRect &space, GLfloat yRange, bool changeGeometry); - void setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space, GLfloat yRange, bool changeGeometry); + void setUpData(const QSurfaceDataArray &dataArray, const QRect &space, GLfloat yRange, + bool changeGeometry, bool needTexture); + void setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space, GLfloat yRange, + bool changeGeometry, bool needTexture); GLuint gridElementBuf(); GLuint gridIndexCount(); @@ -61,6 +63,8 @@ private: GLfloat m_yRange; GLuint m_gridElementbuffer; GLuint m_gridIndexCount; + QVector<QVector3D> m_vertices; + QVector<QVector3D> m_normals; }; QT_DATAVISUALIZATION_END_NAMESPACE |